mirror of
https://git.lecygnenoir.info/LecygneNoir/prismedia.git
synced 2025-10-06 02:29:58 +02:00
Merge branch 'release/v0.10.0'
This commit is contained in:
commit
e7a4d1656a
8 changed files with 422 additions and 162 deletions
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -1,5 +1,16 @@
|
|||
# Changelog
|
||||
|
||||
## v0.10.0
|
||||
|
||||
## Features
|
||||
- Add the possibility to specify strict checks option to never forgot parameters when uploading (see #36)
|
||||
- Improve logging system, add options for batch upload and print url-only in the stdout (see #29)
|
||||
- --debug option is now deprecated in favor of --log=debug
|
||||
|
||||
## Fixes
|
||||
- Workaround against the Youtube API breakdown while adding video in playlist. See #47 for details. Should be removed once Google fix their bugs.
|
||||
|
||||
|
||||
## v0.9.1
|
||||
|
||||
### Features
|
||||
|
|
71
README.md
71
README.md
|
@ -5,7 +5,7 @@ Scripting your way to upload videos to peertube and youtube. Works with Python 3
|
|||
[TOC]: #
|
||||
|
||||
## Table of Contents
|
||||
- [Installation](#installation)
|
||||
- [Installation](#installation-and-upgrade)
|
||||
- [From pip](#from-pip)
|
||||
- [From source](#from-source)
|
||||
- [Configuration](#configuration)
|
||||
|
@ -13,12 +13,13 @@ Scripting your way to upload videos to peertube and youtube. Works with Python 3
|
|||
- [Youtube](#youtube)
|
||||
- [Usage](#usage)
|
||||
- [Enhanced use of NFO](#enhanced-use-of-nfo)
|
||||
- [Strict check options](#strict-check-options)
|
||||
- [Features](#features)
|
||||
- [Compatibility](#compatibility)
|
||||
- [Sources](#sources)
|
||||
- [Inspirations](#inspirations)
|
||||
- [Contributors](#contributors)
|
||||
|
||||
## Installation an upgrade
|
||||
## Installation and upgrade
|
||||
|
||||
### From pip
|
||||
|
||||
|
@ -121,9 +122,8 @@ Use --help to get all available options:
|
|||
|
||||
```
|
||||
Options:
|
||||
-f, --file=STRING Path to the video file to upload in mp4
|
||||
-f, --file=STRING Path to the video file to upload in mp4. This is the only mandatory option.
|
||||
--name=NAME Name of the video to upload. (default to video filename)
|
||||
--debug Trigger some debug information like options used (default: no)
|
||||
-d, --description=STRING Description of the video. (default: default description)
|
||||
-t, --tags=STRING Tags for the video. comma separated.
|
||||
WARN: tags with punctuation (!, ', ", ?, ...)
|
||||
|
@ -159,6 +159,34 @@ Options:
|
|||
-h --help Show this help.
|
||||
--version Show version.
|
||||
|
||||
Logging options
|
||||
-q --quiet Suppress any log except Critical (alias for --log=critical).
|
||||
--log=STRING Log level, between debug, info, warning, error, critical. Ignored if --quiet is set (default to info)
|
||||
-u --url-only Display generated URL after upload directly on stdout, implies --quiet
|
||||
--batch Display generated URL after upload with platform information for easier parsing. Implies --quiet
|
||||
Be careful --batch and --url-only are mutually exclusives.
|
||||
--debug (Deprecated) Alias for --log=debug. Ignored if --log is set
|
||||
|
||||
Strict options:
|
||||
Strict options allow you to force some option to be present when uploading a video. It's useful to be sure you do not
|
||||
forget something when uploading a video, for example if you use multiples NFO. You may force the presence of description,
|
||||
tags, thumbnail, ...
|
||||
All strict option are optionals and are provided only to avoid errors when uploading :-)
|
||||
All strict options can be specified in NFO directly, the only strict option mandatory on cli is --withNFO
|
||||
All strict options are off by default
|
||||
|
||||
--withNFO Prevent the upload without a NFO, either specified via cli or found in the directory
|
||||
--withThumbnail Prevent the upload without a thumbnail
|
||||
--withName Prevent the upload if no name are found
|
||||
--withDescription Prevent the upload without description
|
||||
--withTags Prevent the upload without tags
|
||||
--withPlaylist Prevent the upload if no playlist
|
||||
--withPublishAt Prevent the upload if no schedule
|
||||
--withPlatform Prevent the upload if at least one platform is not specified
|
||||
--withCategory Prevent the upload if no category
|
||||
--withLanguage Prevent upload if no language
|
||||
--withChannel Prevent upload if no channel
|
||||
|
||||
Categories:
|
||||
Category is the type of video you upload. Default is films.
|
||||
Here are available categories from Peertube and Youtube:
|
||||
|
@ -173,6 +201,7 @@ Languages:
|
|||
Here are available languages from Peertube and Youtube:
|
||||
Arabic, English, French, German, Hindi, Italian,
|
||||
Japanese, Korean, Mandarin, Portuguese, Punjabi, Russian, Spanish
|
||||
|
||||
```
|
||||
|
||||
## Enhanced use of NFO
|
||||
|
@ -211,10 +240,32 @@ Prismedia will:
|
|||
- erase any previous option regarding CCA as it's specified in cli with `--cca`
|
||||
- take `yourvideo1.jpg` as thumbnail if no other files has been specified in previous NFO
|
||||
|
||||
In other word, Prismedia will now use option given in cli, then look for option in cli_nfo.txt, then complete with video_name.txt, then directory_name.txt, and finally complete with nfo.txt
|
||||
In other word, Prismedia will use option given in cli, then look for option in cli_nfo.txt, then complete with video_name.txt, then directory_name.txt, and finally complete with nfo.txt
|
||||
|
||||
It allows to specify more easily default options for an entire set of video, directory, playlist and so on.
|
||||
|
||||
## Strict check options
|
||||
Since prismedia v0.10.0, a bunch of special options have been added to force the presence of parameters before uploading.
|
||||
Strict options allow you to force some option to be present when uploading a video. It's useful to be sure you do not
|
||||
forget something when uploading a video, for example if you use multiples NFO. You may force the presence of description,
|
||||
tags, thumbnail, ...
|
||||
All strict option are optionals and are provided only to avoid errors when uploading :-)
|
||||
All strict options can be specified in NFO directly, the only strict option mandatory on cli is --withNFO
|
||||
All strict options are off by default.
|
||||
|
||||
Available strict options:
|
||||
- --withNFO Prevent the upload without a NFO, either specified via cli or found in the directory
|
||||
- --withThumbnail Prevent the upload without a thumbnail
|
||||
- --withName Prevent the upload if no name are found
|
||||
- --withDescription Prevent the upload without description
|
||||
- --withTags Prevent the upload without tags
|
||||
- --withPlaylist Prevent the upload if no playlist
|
||||
- --withPublishAt Prevent the upload if no schedule
|
||||
- --withPlatform Prevent the upload if at least one platform is not specified
|
||||
- --withCategory Prevent the upload if no category
|
||||
- --withLanguage Prevent upload if no language
|
||||
- --withChannel Prevent upload if no channel
|
||||
|
||||
## Features
|
||||
|
||||
- [x] Youtube upload
|
||||
|
@ -235,9 +286,11 @@ It allows to specify more easily default options for an entire set of video, dir
|
|||
- [x] schedule your video with publishAt
|
||||
- [x] combine channel and playlist (Peertube only as channel is Peertube feature). See [issue 40](https://git.lecygnenoir.info/LecygneNoir/prismedia/issues/40) for detailed usage.
|
||||
- [x] Use a config file (NFO) file to retrieve videos arguments
|
||||
- [x] Allow to choose peertube or youtube upload (to resume failed upload for example)
|
||||
- [x] Allow choosing peertube or youtube upload (to retry a failed upload for example)
|
||||
- [x] Usable on Desktop (Linux and/or Windows and/or MacOS)
|
||||
- [x] Different schedules on platforms to prepare preview
|
||||
- [x] Possibility to force the presence of upload options
|
||||
- [ ] Copy and forget, eg possibility to copy video in a directory, and prismedia uploads itself: [Work in progress](https://git.lecygnenoir.info/Zykino/prismedia-autoupload) thanks to @Zykino 🎉 (Discussions in [issue 27](https://git.lecygnenoir.info/LecygneNoir/prismedia/issues/27))
|
||||
- [ ] A usable graphical interface
|
||||
|
||||
## Compatibility
|
||||
|
@ -245,8 +298,8 @@ It allows to specify more easily default options for an entire set of video, dir
|
|||
- If you still use python2, use the version 0.7.1 (no more updated)
|
||||
- If you use peertube before 1.0.0-beta4, use the version inside tag 1.0.0-beta3
|
||||
|
||||
## Sources
|
||||
inspired by [peeror](https://git.rigelk.eu/rigelk/peeror) and [youtube-upload](https://github.com/tokland/youtube-upload)
|
||||
## Inspirations
|
||||
Inspired by [peeror](https://git.rigelk.eu/rigelk/peeror) and [youtube-upload](https://github.com/tokland/youtube-upload)
|
||||
|
||||
## Contributors
|
||||
Thanks to: @Zykino, @meewan, @rigelk 😘
|
162
poetry.lock
generated
162
poetry.lock
generated
|
@ -12,7 +12,7 @@ description = "Python package for providing Mozilla's CA Bundle."
|
|||
name = "certifi"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "2020.4.5.1"
|
||||
version = "2020.6.20"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
|
@ -34,6 +34,14 @@ version = "3.8.1"
|
|||
docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
|
||||
testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2)", "pytest-flake8"]
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Backports and enhancements for the contextlib module"
|
||||
name = "contextlib2"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
version = "0.6.0.post1"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Pythonic argument parser, that will make you smile"
|
||||
|
@ -56,19 +64,19 @@ description = "Google API client core library"
|
|||
name = "google-api-core"
|
||||
optional = false
|
||||
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
|
||||
version = "1.17.0"
|
||||
version = "1.22.2"
|
||||
|
||||
[package.dependencies]
|
||||
google-auth = ">=1.14.0,<2.0dev"
|
||||
google-auth = ">=1.21.1,<2.0dev"
|
||||
googleapis-common-protos = ">=1.6.0,<2.0dev"
|
||||
protobuf = ">=3.4.0"
|
||||
protobuf = ">=3.12.0"
|
||||
pytz = "*"
|
||||
requests = ">=2.18.0,<3.0.0dev"
|
||||
setuptools = ">=34.0.0"
|
||||
six = ">=1.10.0"
|
||||
|
||||
[package.extras]
|
||||
grpc = ["grpcio (>=1.8.2,<2.0dev)"]
|
||||
grpc = ["grpcio (>=1.29.0,<2.0dev)"]
|
||||
grpcgcp = ["grpcio-gcp (>=0.2.2)"]
|
||||
grpcio-gcp = ["grpcio-gcp (>=0.2.2)"]
|
||||
|
||||
|
@ -78,14 +86,14 @@ description = "Google API Client Library for Python"
|
|||
name = "google-api-python-client"
|
||||
optional = false
|
||||
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
|
||||
version = "1.8.2"
|
||||
version = "1.12.1"
|
||||
|
||||
[package.dependencies]
|
||||
google-api-core = ">=1.13.0,<2dev"
|
||||
google-auth = ">=1.4.1"
|
||||
google-api-core = ">=1.21.0,<2dev"
|
||||
google-auth = ">=1.16.0"
|
||||
google-auth-httplib2 = ">=0.0.3"
|
||||
httplib2 = ">=0.9.2,<1dev"
|
||||
six = ">=1.6.1,<2dev"
|
||||
six = ">=1.13.0,<2dev"
|
||||
uritemplate = ">=3.0.0,<4dev"
|
||||
|
||||
[[package]]
|
||||
|
@ -94,26 +102,30 @@ description = "Google Authentication Library"
|
|||
name = "google-auth"
|
||||
optional = false
|
||||
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
|
||||
version = "1.14.1"
|
||||
version = "1.21.1"
|
||||
|
||||
[package.dependencies]
|
||||
cachetools = ">=2.0.0,<5.0"
|
||||
pyasn1-modules = ">=0.2.1"
|
||||
rsa = ">=3.1.4,<4.1"
|
||||
setuptools = ">=40.3.0"
|
||||
six = ">=1.9.0"
|
||||
|
||||
[package.dependencies.rsa]
|
||||
python = ">=3.5"
|
||||
version = ">=3.1.4,<5"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Google Authentication Library: httplib2 transport"
|
||||
name = "google-auth-httplib2"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
|
||||
[package.dependencies]
|
||||
google-auth = "*"
|
||||
httplib2 = ">=0.9.1"
|
||||
six = "*"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
|
@ -121,7 +133,7 @@ description = "Google Authentication Library"
|
|||
name = "google-auth-oauthlib"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "0.2.0"
|
||||
version = "0.4.1"
|
||||
|
||||
[package.dependencies]
|
||||
google-auth = "*"
|
||||
|
@ -135,8 +147,8 @@ category = "main"
|
|||
description = "Common protobufs used in Google APIs"
|
||||
name = "googleapis-common-protos"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "1.51.0"
|
||||
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
|
||||
version = "1.52.0"
|
||||
|
||||
[package.dependencies]
|
||||
protobuf = ">=3.6.0"
|
||||
|
@ -158,7 +170,7 @@ description = "Internationalized Domain Names in Applications (IDNA)"
|
|||
name = "idna"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
version = "2.9"
|
||||
version = "2.10"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
|
@ -180,7 +192,7 @@ description = "Protocol Buffers"
|
|||
name = "protobuf"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "3.11.3"
|
||||
version = "3.13.0"
|
||||
|
||||
[package.dependencies]
|
||||
setuptools = "*"
|
||||
|
@ -210,8 +222,8 @@ category = "main"
|
|||
description = "File type identification using libmagic"
|
||||
name = "python-magic"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "0.4.15"
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
version = "0.4.18"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
|
@ -228,7 +240,7 @@ description = "World timezone definitions, modern and historical"
|
|||
name = "pytz"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "2019.3"
|
||||
version = "2020.1"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
|
@ -236,7 +248,7 @@ description = "Python HTTP for Humans."
|
|||
name = "requests"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
version = "2.23.0"
|
||||
version = "2.24.0"
|
||||
|
||||
[package.dependencies]
|
||||
certifi = ">=2017.4.17"
|
||||
|
@ -277,10 +289,11 @@ requests = ">=2.0.1,<3.0.0"
|
|||
[[package]]
|
||||
category = "main"
|
||||
description = "Pure-Python RSA implementation"
|
||||
marker = "python_version >= \"3.5\""
|
||||
name = "rsa"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "4.0"
|
||||
version = "4.4"
|
||||
|
||||
[package.dependencies]
|
||||
pyasn1 = ">=0.1.3"
|
||||
|
@ -291,7 +304,10 @@ description = "Simple data validation library"
|
|||
name = "schema"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "0.6.8"
|
||||
version = "0.7.3"
|
||||
|
||||
[package.dependencies]
|
||||
contextlib2 = ">=0.5.5"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
|
@ -299,7 +315,7 @@ description = "Python 2 and 3 compatibility utilities"
|
|||
name = "six"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
version = "1.14.0"
|
||||
version = "1.15.0"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
|
@ -341,7 +357,7 @@ secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "cer
|
|||
socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"]
|
||||
|
||||
[metadata]
|
||||
content-hash = "b3063876dbcd6443d0459a9ef376ccdba2a21adc2e7a49d75c9450904b40615f"
|
||||
content-hash = "5f912013e1ff1f79bdecd9626157960bd0ccc41f441370419888238adc32b385"
|
||||
python-versions = ">=3.5"
|
||||
|
||||
[metadata.files]
|
||||
|
@ -350,8 +366,8 @@ cachetools = [
|
|||
{file = "cachetools-3.1.1.tar.gz", hash = "sha256:8ea2d3ce97850f31e4a08b0e2b5e6c34997d7216a9d2c98e0f3978630d4da69a"},
|
||||
]
|
||||
certifi = [
|
||||
{file = "certifi-2020.4.5.1-py2.py3-none-any.whl", hash = "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304"},
|
||||
{file = "certifi-2020.4.5.1.tar.gz", hash = "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519"},
|
||||
{file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"},
|
||||
{file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"},
|
||||
]
|
||||
chardet = [
|
||||
{file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"},
|
||||
|
@ -361,6 +377,10 @@ configparser = [
|
|||
{file = "configparser-3.8.1-py2.py3-none-any.whl", hash = "sha256:45d1272aad6cfd7a8a06cf5c73f2ceb6a190f6acc1fa707e7f82a4c053b28b18"},
|
||||
{file = "configparser-3.8.1.tar.gz", hash = "sha256:bc37850f0cc42a1725a796ef7d92690651bf1af37d744cc63161dac62cabee17"},
|
||||
]
|
||||
contextlib2 = [
|
||||
{file = "contextlib2-0.6.0.post1-py2.py3-none-any.whl", hash = "sha256:3355078a159fbb44ee60ea80abd0d87b80b78c248643b49aa6d94673b413609b"},
|
||||
{file = "contextlib2-0.6.0.post1.tar.gz", hash = "sha256:01f490098c18b19d2bd5bb5dc445b2054d2fa97f09a4280ba2c5f3c394c8162e"},
|
||||
]
|
||||
docopt = [
|
||||
{file = "docopt-0.6.2.tar.gz", hash = "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"},
|
||||
]
|
||||
|
@ -368,60 +388,60 @@ future = [
|
|||
{file = "future-0.17.1.tar.gz", hash = "sha256:67045236dcfd6816dc439556d009594abf643e5eb48992e36beac09c2ca659b8"},
|
||||
]
|
||||
google-api-core = [
|
||||
{file = "google-api-core-1.17.0.tar.gz", hash = "sha256:e4082a0b479dc2dee2f8d7b80ea8b5d0184885b773caab15ab1836277a01d689"},
|
||||
{file = "google_api_core-1.17.0-py2.py3-none-any.whl", hash = "sha256:c0e430658ed6be902d7ba7095fb0a9cac810270d71bf7ac4484e76c300407aae"},
|
||||
{file = "google-api-core-1.22.2.tar.gz", hash = "sha256:779107f17e0fef8169c5239d56a8fbff03f9f72a3893c0c9e5842ec29dfedd54"},
|
||||
{file = "google_api_core-1.22.2-py2.py3-none-any.whl", hash = "sha256:67e33a852dcca7cb7eff49abc35c8cc2c0bb8ab11397dc8306d911505cae2990"},
|
||||
]
|
||||
google-api-python-client = [
|
||||
{file = "google-api-python-client-1.8.2.tar.gz", hash = "sha256:bf482c13fb41a6d01770f9d62be6b33fdcd41d68c97f2beb9be02297bdd9e725"},
|
||||
{file = "google_api_python_client-1.8.2-py3-none-any.whl", hash = "sha256:8dd35a3704650c2db44e6cf52abdaf9de71f409c93c56bbe48a321ab5e14ebad"},
|
||||
{file = "google-api-python-client-1.12.1.tar.gz", hash = "sha256:ddadc243ce627512c2a27e11d369f5ddf658ef80dbffb247787499486ef1ea98"},
|
||||
{file = "google_api_python_client-1.12.1-py2.py3-none-any.whl", hash = "sha256:750316d670119bf680c24ff73825a05b1b4f48b9157bd48c6e3f2bea15ceb586"},
|
||||
]
|
||||
google-auth = [
|
||||
{file = "google-auth-1.14.1.tar.gz", hash = "sha256:e63b2210e03c4ed829063b72c4af0c4b867c2788efb3210b6b9439b488bd3afd"},
|
||||
{file = "google_auth-1.14.1-py2.py3-none-any.whl", hash = "sha256:0c41a453b9a8e77975bfa436b8daedac00aed1c545d84410daff8272fff40fbb"},
|
||||
{file = "google-auth-1.21.1.tar.gz", hash = "sha256:bcbd9f970e7144fe933908aa286d7a12c44b7deb6d78a76871f0377a29d09789"},
|
||||
{file = "google_auth-1.21.1-py2.py3-none-any.whl", hash = "sha256:f4d5093f13b1b1c0a434ab1dc851cd26a983f86a4d75c95239974e33ed406a87"},
|
||||
]
|
||||
google-auth-httplib2 = [
|
||||
{file = "google-auth-httplib2-0.0.3.tar.gz", hash = "sha256:098fade613c25b4527b2c08fa42d11f3c2037dda8995d86de0745228e965d445"},
|
||||
{file = "google_auth_httplib2-0.0.3-py2.py3-none-any.whl", hash = "sha256:f1c437842155680cf9918df9bc51c1182fda41feef88c34004bd1978c8157e08"},
|
||||
{file = "google-auth-httplib2-0.0.4.tar.gz", hash = "sha256:8d092cc60fb16517b12057ec0bba9185a96e3b7169d86ae12eae98e645b7bc39"},
|
||||
{file = "google_auth_httplib2-0.0.4-py2.py3-none-any.whl", hash = "sha256:aeaff501738b289717fac1980db9711d77908a6c227f60e4aa1923410b43e2ee"},
|
||||
]
|
||||
google-auth-oauthlib = [
|
||||
{file = "google-auth-oauthlib-0.2.0.tar.gz", hash = "sha256:226d1d0960f86ba5d9efd426a70b291eaba96f47d071657e0254ea969025728a"},
|
||||
{file = "google_auth_oauthlib-0.2.0-py2.py3-none-any.whl", hash = "sha256:81ba22acada4d13b1d83f9371ab19fd61f1250a542d21cf49e4dcf0637a7344a"},
|
||||
{file = "google-auth-oauthlib-0.4.1.tar.gz", hash = "sha256:88d2cd115e3391eb85e1243ac6902e76e77c5fe438b7276b297fbe68015458dd"},
|
||||
{file = "google_auth_oauthlib-0.4.1-py2.py3-none-any.whl", hash = "sha256:a92a0f6f41a0fb6138454fbc02674e64f89d82a244ea32f98471733c8ef0e0e1"},
|
||||
]
|
||||
googleapis-common-protos = [
|
||||
{file = "googleapis-common-protos-1.51.0.tar.gz", hash = "sha256:013c91704279119150e44ef770086fdbba158c1f978a6402167d47d5409e226e"},
|
||||
{file = "googleapis-common-protos-1.52.0.tar.gz", hash = "sha256:560716c807117394da12cecb0a54da5a451b5cf9866f1d37e9a5e2329a665351"},
|
||||
{file = "googleapis_common_protos-1.52.0-py2.py3-none-any.whl", hash = "sha256:c8961760f5aad9a711d37b675be103e0cc4e9a39327e0d6d857872f698403e24"},
|
||||
]
|
||||
httplib2 = [
|
||||
{file = "httplib2-0.12.3-py3-none-any.whl", hash = "sha256:23914b5487dfe8ef09db6656d6d63afb0cf3054ad9ebc50868ddc8e166b5f8e8"},
|
||||
{file = "httplib2-0.12.3.tar.gz", hash = "sha256:a18121c7c72a56689efbf1aef990139ad940fee1e64c6f2458831736cd593600"},
|
||||
]
|
||||
idna = [
|
||||
{file = "idna-2.9-py2.py3-none-any.whl", hash = "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"},
|
||||
{file = "idna-2.9.tar.gz", hash = "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb"},
|
||||
{file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"},
|
||||
{file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"},
|
||||
]
|
||||
oauthlib = [
|
||||
{file = "oauthlib-2.1.0-py2.py3-none-any.whl", hash = "sha256:d883b36b21a6ad813953803edfa563b1b579d79ca758fe950d1bc9e8b326025b"},
|
||||
{file = "oauthlib-2.1.0.tar.gz", hash = "sha256:ac35665a61c1685c56336bda97d5eefa246f1202618a1d6f34fccb1bdd404162"},
|
||||
]
|
||||
protobuf = [
|
||||
{file = "protobuf-3.11.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ef2c2e56aaf9ee914d3dccc3408d42661aaf7d9bb78eaa8f17b2e6282f214481"},
|
||||
{file = "protobuf-3.11.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:dd9aa4401c36785ea1b6fff0552c674bdd1b641319cb07ed1fe2392388e9b0d7"},
|
||||
{file = "protobuf-3.11.3-cp35-cp35m-macosx_10_9_intel.whl", hash = "sha256:310a7aca6e7f257510d0c750364774034272538d51796ca31d42c3925d12a52a"},
|
||||
{file = "protobuf-3.11.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:e512b7f3a4dd780f59f1bf22c302740e27b10b5c97e858a6061772668cd6f961"},
|
||||
{file = "protobuf-3.11.3-cp35-cp35m-win32.whl", hash = "sha256:fdfb6ad138dbbf92b5dbea3576d7c8ba7463173f7d2cb0ca1bd336ec88ddbd80"},
|
||||
{file = "protobuf-3.11.3-cp35-cp35m-win_amd64.whl", hash = "sha256:e2f8a75261c26b2f5f3442b0525d50fd79a71aeca04b5ec270fc123536188306"},
|
||||
{file = "protobuf-3.11.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c40973a0aee65422d8cb4e7d7cbded95dfeee0199caab54d5ab25b63bce8135a"},
|
||||
{file = "protobuf-3.11.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:adf0e4d57b33881d0c63bb11e7f9038f98ee0c3e334c221f0858f826e8fb0151"},
|
||||
{file = "protobuf-3.11.3-cp36-cp36m-win32.whl", hash = "sha256:0bae429443cc4748be2aadfdaf9633297cfaeb24a9a02d0ab15849175ce90fab"},
|
||||
{file = "protobuf-3.11.3-cp36-cp36m-win_amd64.whl", hash = "sha256:e11df1ac6905e81b815ab6fd518e79be0a58b5dc427a2cf7208980f30694b956"},
|
||||
{file = "protobuf-3.11.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7774bbbaac81d3ba86de646c39f154afc8156717972bf0450c9dbfa1dc8dbea2"},
|
||||
{file = "protobuf-3.11.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:8eb9c93798b904f141d9de36a0ba9f9b73cc382869e67c9e642c0aba53b0fc07"},
|
||||
{file = "protobuf-3.11.3-cp37-cp37m-win32.whl", hash = "sha256:fac513a9dc2a74b99abd2e17109b53945e364649ca03d9f7a0b96aa8d1807d0a"},
|
||||
{file = "protobuf-3.11.3-cp37-cp37m-win_amd64.whl", hash = "sha256:82d7ac987715d8d1eb4068bf997f3053468e0ce0287e2729c30601feb6602fee"},
|
||||
{file = "protobuf-3.11.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:73152776dc75f335c476d11d52ec6f0f6925774802cd48d6189f4d5d7fe753f4"},
|
||||
{file = "protobuf-3.11.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:52e586072612c1eec18e1174f8e3bb19d08f075fc2e3f91d3b16c919078469d0"},
|
||||
{file = "protobuf-3.11.3-py2.7.egg", hash = "sha256:2affcaba328c4662f3bc3c0e9576ea107906b2c2b6422344cdad961734ff6b93"},
|
||||
{file = "protobuf-3.11.3-py2.py3-none-any.whl", hash = "sha256:24e3b6ad259544d717902777b33966a1a069208c885576254c112663e6a5bb0f"},
|
||||
{file = "protobuf-3.11.3.tar.gz", hash = "sha256:c77c974d1dadf246d789f6dad1c24426137c9091e930dbf50e0a29c1fcf00b1f"},
|
||||
{file = "protobuf-3.13.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:9c2e63c1743cba12737169c447374fab3dfeb18111a460a8c1a000e35836b18c"},
|
||||
{file = "protobuf-3.13.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1e834076dfef9e585815757a2c7e4560c7ccc5962b9d09f831214c693a91b463"},
|
||||
{file = "protobuf-3.13.0-cp35-cp35m-macosx_10_9_intel.whl", hash = "sha256:df3932e1834a64b46ebc262e951cd82c3cf0fa936a154f0a42231140d8237060"},
|
||||
{file = "protobuf-3.13.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:8c35bcbed1c0d29b127c886790e9d37e845ffc2725cc1db4bd06d70f4e8359f4"},
|
||||
{file = "protobuf-3.13.0-cp35-cp35m-win32.whl", hash = "sha256:339c3a003e3c797bc84499fa32e0aac83c768e67b3de4a5d7a5a9aa3b0da634c"},
|
||||
{file = "protobuf-3.13.0-cp35-cp35m-win_amd64.whl", hash = "sha256:361acd76f0ad38c6e38f14d08775514fbd241316cce08deb2ce914c7dfa1184a"},
|
||||
{file = "protobuf-3.13.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9edfdc679a3669988ec55a989ff62449f670dfa7018df6ad7f04e8dbacb10630"},
|
||||
{file = "protobuf-3.13.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5db9d3e12b6ede5e601b8d8684a7f9d90581882925c96acf8495957b4f1b204b"},
|
||||
{file = "protobuf-3.13.0-cp36-cp36m-win32.whl", hash = "sha256:c8abd7605185836f6f11f97b21200f8a864f9cb078a193fe3c9e235711d3ff1e"},
|
||||
{file = "protobuf-3.13.0-cp36-cp36m-win_amd64.whl", hash = "sha256:4d1174c9ed303070ad59553f435846a2f877598f59f9afc1b89757bdf846f2a7"},
|
||||
{file = "protobuf-3.13.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0bba42f439bf45c0f600c3c5993666fcb88e8441d011fad80a11df6f324eef33"},
|
||||
{file = "protobuf-3.13.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:c0c5ab9c4b1eac0a9b838f1e46038c3175a95b0f2d944385884af72876bd6bc7"},
|
||||
{file = "protobuf-3.13.0-cp37-cp37m-win32.whl", hash = "sha256:f68eb9d03c7d84bd01c790948320b768de8559761897763731294e3bc316decb"},
|
||||
{file = "protobuf-3.13.0-cp37-cp37m-win_amd64.whl", hash = "sha256:91c2d897da84c62816e2f473ece60ebfeab024a16c1751aaf31100127ccd93ec"},
|
||||
{file = "protobuf-3.13.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3dee442884a18c16d023e52e32dd34a8930a889e511af493f6dc7d4d9bf12e4f"},
|
||||
{file = "protobuf-3.13.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:e7662437ca1e0c51b93cadb988f9b353fa6b8013c0385d63a70c8a77d84da5f9"},
|
||||
{file = "protobuf-3.13.0-py2.py3-none-any.whl", hash = "sha256:d69697acac76d9f250ab745b46c725edf3e98ac24763990b24d58c16c642947a"},
|
||||
{file = "protobuf-3.13.0.tar.gz", hash = "sha256:6a82e0c8bb2bf58f606040cc5814e07715b2094caeba281e2e7d0b0e2e397db5"},
|
||||
]
|
||||
pyasn1 = [
|
||||
{file = "pyasn1-0.4.8-py2.4.egg", hash = "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"},
|
||||
|
@ -454,8 +474,8 @@ pyasn1-modules = [
|
|||
{file = "pyasn1_modules-0.2.8-py3.7.egg", hash = "sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd"},
|
||||
]
|
||||
python-magic = [
|
||||
{file = "python-magic-0.4.15.tar.gz", hash = "sha256:f3765c0f582d2dfc72c15f3b5a82aecfae9498bd29ca840d72f37d7bd38bfcd5"},
|
||||
{file = "python_magic-0.4.15-py2.py3-none-any.whl", hash = "sha256:f2674dcfad52ae6c49d4803fa027809540b130db1dec928cfbb9240316831375"},
|
||||
{file = "python-magic-0.4.18.tar.gz", hash = "sha256:b757db2a5289ea3f1ced9e60f072965243ea43a2221430048fd8cacab17be0ce"},
|
||||
{file = "python_magic-0.4.18-py2.py3-none-any.whl", hash = "sha256:356efa93c8899047d1eb7d3eb91e871ba2f5b1376edbaf4cc305e3c872207355"},
|
||||
]
|
||||
python-magic-bin = [
|
||||
{file = "python_magic_bin-0.4.14-py2.py3-none-macosx_10_6_intel.whl", hash = "sha256:7b1743b3dbf16601d6eedf4e7c2c9a637901b0faaf24ad4df4d4527e7d8f66a4"},
|
||||
|
@ -463,12 +483,12 @@ python-magic-bin = [
|
|||
{file = "python_magic_bin-0.4.14-py2.py3-none-win_amd64.whl", hash = "sha256:90be6206ad31071a36065a2fc169c5afb5e0355cbe6030e87641c6c62edc2b69"},
|
||||
]
|
||||
pytz = [
|
||||
{file = "pytz-2019.3-py2.py3-none-any.whl", hash = "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d"},
|
||||
{file = "pytz-2019.3.tar.gz", hash = "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"},
|
||||
{file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"},
|
||||
{file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"},
|
||||
]
|
||||
requests = [
|
||||
{file = "requests-2.23.0-py2.py3-none-any.whl", hash = "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee"},
|
||||
{file = "requests-2.23.0.tar.gz", hash = "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"},
|
||||
{file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"},
|
||||
{file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"},
|
||||
]
|
||||
requests-oauthlib = [
|
||||
{file = "requests-oauthlib-0.8.0.tar.gz", hash = "sha256:883ac416757eada6d3d07054ec7092ac21c7f35cb1d2cf82faf205637081f468"},
|
||||
|
@ -479,16 +499,16 @@ requests-toolbelt = [
|
|||
{file = "requests_toolbelt-0.9.1-py2.py3-none-any.whl", hash = "sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f"},
|
||||
]
|
||||
rsa = [
|
||||
{file = "rsa-4.0-py2.py3-none-any.whl", hash = "sha256:14ba45700ff1ec9eeb206a2ce76b32814958a98e372006c8fb76ba820211be66"},
|
||||
{file = "rsa-4.0.tar.gz", hash = "sha256:1a836406405730121ae9823e19c6e806c62bbad73f890574fff50efa4122c487"},
|
||||
{file = "rsa-4.4-py2.py3-none-any.whl", hash = "sha256:4afbaaecc3e9550c7351fdf0ab3fea1857ff616b85bab59215f00fb42e0e9582"},
|
||||
{file = "rsa-4.4.tar.gz", hash = "sha256:5d95293bbd0fbee1dd9cb4b72d27b723942eb50584abc8c4f5f00e4bcfa55307"},
|
||||
]
|
||||
schema = [
|
||||
{file = "schema-0.6.8-py2.py3-none-any.whl", hash = "sha256:d994b0dc4966000037b26898df638e3e2a694cc73636cb2050e652614a350687"},
|
||||
{file = "schema-0.6.8.tar.gz", hash = "sha256:fa1a53fe5f3b6929725a4e81688c250f46838e25d8c1885a10a590c8c01a7b74"},
|
||||
{file = "schema-0.7.3-py2.py3-none-any.whl", hash = "sha256:c331438b60f634cab5664ab720d3083cc444f924d55269530c36b33e3354276f"},
|
||||
{file = "schema-0.7.3.tar.gz", hash = "sha256:4cf529318cfd1e844ecbe02f41f7e5aa027463e7403666a52746f31f04f47a5e"},
|
||||
]
|
||||
six = [
|
||||
{file = "six-1.14.0-py2.py3-none-any.whl", hash = "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"},
|
||||
{file = "six-1.14.0.tar.gz", hash = "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a"},
|
||||
{file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"},
|
||||
{file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"},
|
||||
]
|
||||
tzlocal = [
|
||||
{file = "tzlocal-1.5.1.tar.gz", hash = "sha256:4ebeb848845ac898da6519b9b31879cf13b6626f7184c496037b818e238f2c4e"},
|
||||
|
|
|
@ -5,6 +5,7 @@ import os
|
|||
import mimetypes
|
||||
import json
|
||||
import logging
|
||||
import sys
|
||||
import datetime
|
||||
import pytz
|
||||
from os.path import splitext, basename, abspath
|
||||
|
@ -16,6 +17,7 @@ from oauthlib.oauth2 import LegacyApplicationClient
|
|||
from requests_toolbelt.multipart.encoder import MultipartEncoder
|
||||
|
||||
from . import utils
|
||||
logger = logging.getLogger('Prismedia')
|
||||
|
||||
PEERTUBE_SECRETS_FILE = 'peertube_secret'
|
||||
PEERTUBE_PRIVACY = {
|
||||
|
@ -43,10 +45,10 @@ def get_authenticated_service(secret):
|
|||
)
|
||||
except Exception as e:
|
||||
if hasattr(e, 'message'):
|
||||
logging.error("Peertube: Error: " + str(e.message))
|
||||
logger.critical("Peertube: " + str(e.message))
|
||||
exit(1)
|
||||
else:
|
||||
logging.error("Peertube: Error: " + str(e))
|
||||
logger.critical("Peertube: " + str(e))
|
||||
exit(1)
|
||||
return oauth
|
||||
|
||||
|
@ -63,7 +65,7 @@ def get_channel_by_name(user_info, options):
|
|||
|
||||
def create_channel(oauth, url, options):
|
||||
template = ('Peertube: Channel %s does not exist, creating it.')
|
||||
logging.info(template % (str(options.get('--channel'))))
|
||||
logger.info(template % (str(options.get('--channel'))))
|
||||
channel_name = utils.cleanString(str(options.get('--channel')))
|
||||
# Peertube allows 20 chars max for channel name
|
||||
channel_name = channel_name[:19]
|
||||
|
@ -81,23 +83,23 @@ def create_channel(oauth, url, options):
|
|||
headers=headers)
|
||||
except Exception as e:
|
||||
if hasattr(e, 'message'):
|
||||
logging.error("Error: " + str(e.message))
|
||||
logger.error("Peertube: " + str(e.message))
|
||||
else:
|
||||
logging.error("Error: " + str(e))
|
||||
logger.error("Peertube: " + str(e))
|
||||
if response is not None:
|
||||
if response.status_code == 200:
|
||||
jresponse = response.json()
|
||||
jresponse = jresponse['videoChannel']
|
||||
return jresponse['id']
|
||||
if response.status_code == 409:
|
||||
logging.error('Peertube: Error: It seems there is a conflict with an existing channel named '
|
||||
logger.critical('Peertube: It seems there is a conflict with an existing channel named '
|
||||
+ channel_name + '.'
|
||||
' Please beware Peertube internal name is compiled from 20 firsts characters of channel name.'
|
||||
' Also note that channel name are not case sensitive (no uppercase nor accent)'
|
||||
' Please check your channel name and retry.')
|
||||
exit(1)
|
||||
else:
|
||||
logging.error(('Peertube: Creating channel failed with an unexpected response: '
|
||||
logger.critical(('Peertube: Creating channel failed with an unexpected response: '
|
||||
'%s') % response)
|
||||
exit(1)
|
||||
|
||||
|
@ -114,7 +116,7 @@ def get_playlist_by_name(user_playlists, options):
|
|||
|
||||
def create_playlist(oauth, url, options, channel):
|
||||
template = ('Peertube: Playlist %s does not exist, creating it.')
|
||||
logging.info(template % (str(options.get('--playlist'))))
|
||||
logger.info(template % (str(options.get('--playlist'))))
|
||||
# We use files for form-data Content
|
||||
# see https://requests.readthedocs.io/en/latest/user/quickstart/#post-a-multipart-encoded-file
|
||||
# None is used to mute "filename" field
|
||||
|
@ -128,22 +130,22 @@ def create_playlist(oauth, url, options, channel):
|
|||
files=files)
|
||||
except Exception as e:
|
||||
if hasattr(e, 'message'):
|
||||
logging.error("Error: " + str(e.message))
|
||||
logger.error("Peertube: " + str(e.message))
|
||||
else:
|
||||
logging.error("Error: " + str(e))
|
||||
logger.error("Peertube: " + str(e))
|
||||
if response is not None:
|
||||
if response.status_code == 200:
|
||||
jresponse = response.json()
|
||||
jresponse = jresponse['videoPlaylist']
|
||||
return jresponse['id']
|
||||
else:
|
||||
logging.error(('Peertube: Creating the playlist failed with an unexpected response: '
|
||||
logger.critical(('Peertube: Creating the playlist failed with an unexpected response: '
|
||||
'%s') % response)
|
||||
exit(1)
|
||||
|
||||
|
||||
def set_playlist(oauth, url, video_id, playlist_id):
|
||||
logging.info('Peertube: add video to playlist.')
|
||||
logger.info('Peertube: add video to playlist.')
|
||||
data = '{"videoId":"' + str(video_id) + '"}'
|
||||
|
||||
headers = {
|
||||
|
@ -155,14 +157,14 @@ def set_playlist(oauth, url, video_id, playlist_id):
|
|||
headers=headers)
|
||||
except Exception as e:
|
||||
if hasattr(e, 'message'):
|
||||
logging.error("Error: " + str(e.message))
|
||||
logger.error("Peertube: " + str(e.message))
|
||||
else:
|
||||
logging.error("Error: " + str(e))
|
||||
logger.error("Peertube: " + str(e))
|
||||
if response is not None:
|
||||
if response.status_code == 200:
|
||||
logging.info('Peertube: Video is successfully added to the playlist.')
|
||||
logger.info('Peertube: Video is successfully added to the playlist.')
|
||||
else:
|
||||
logging.error(('Peertube: Configuring the playlist failed with an unexpected response: '
|
||||
logger.critical(('Peertube: Configuring the playlist failed with an unexpected response: '
|
||||
'%s') % response)
|
||||
exit(1)
|
||||
|
||||
|
@ -205,8 +207,9 @@ def upload_video(oauth, secret, options):
|
|||
continue
|
||||
# Tag more than 30 chars crashes Peertube, so exit and check tags
|
||||
if len(strtag) >= 30:
|
||||
logging.warning("Peertube: Sorry, Peertube does not support tag with more than 30 characters, please reduce tag: " + strtag)
|
||||
exit(1)
|
||||
logger.error("Peertube: Sorry, Peertube does not support tag with more than 30 characters, please reduce tag: " + strtag)
|
||||
logger.error("Peertube: Meanwhile, this tag will be skipped")
|
||||
continue
|
||||
fields.append(("tags[]", strtag))
|
||||
|
||||
if options.get('--category'):
|
||||
|
@ -256,7 +259,7 @@ def upload_video(oauth, secret, options):
|
|||
if not channel_id and options.get('--channelCreate'):
|
||||
channel_id = create_channel(oauth, url, options)
|
||||
elif not channel_id:
|
||||
logging.warning("Channel `" + options.get('--channel') + "` is unknown, using default channel.")
|
||||
logger.warning("Peertube: Channel `" + options.get('--channel') + "` is unknown, using default channel.")
|
||||
channel_id = get_default_channel(user_info)
|
||||
else:
|
||||
channel_id = get_default_channel(user_info)
|
||||
|
@ -268,10 +271,14 @@ def upload_video(oauth, secret, options):
|
|||
if not playlist_id and options.get('--playlistCreate'):
|
||||
playlist_id = create_playlist(oauth, url, options, channel_id)
|
||||
elif not playlist_id:
|
||||
logging.warning("Playlist `" + options.get('--playlist') + "` does not exist, please set --playlistCreate"
|
||||
logger.critical("Peertube: Playlist `" + options.get('--playlist') + "` does not exist, please set --playlistCreate"
|
||||
" if you want to create it")
|
||||
exit(1)
|
||||
|
||||
logger_stdout = None
|
||||
if options.get('--url-only') or options.get('--batch'):
|
||||
logger_stdout = logging.getLogger('stdoutlogs')
|
||||
|
||||
multipart_data = MultipartEncoder(fields)
|
||||
|
||||
headers = {
|
||||
|
@ -286,14 +293,19 @@ def upload_video(oauth, secret, options):
|
|||
jresponse = jresponse['video']
|
||||
uuid = jresponse['uuid']
|
||||
video_id = str(jresponse['id'])
|
||||
logging.info('Peertube : Video was successfully uploaded.')
|
||||
logger.info('Peertube : Video was successfully uploaded.')
|
||||
template = 'Peertube: Watch it at %s/videos/watch/%s.'
|
||||
logging.info(template % (url, uuid))
|
||||
logger.info(template % (url, uuid))
|
||||
template_stdout = '%s/videos/watch/%s'
|
||||
if options.get('--url-only'):
|
||||
logger_stdout.info(template_stdout % (url, uuid))
|
||||
elif options.get('--batch'):
|
||||
logger_stdout.info("Peertube: " + template_stdout % (url, uuid))
|
||||
# Upload is successful we may set playlist
|
||||
if options.get('--playlist'):
|
||||
set_playlist(oauth, url, video_id, playlist_id)
|
||||
else:
|
||||
logging.error(('Peertube: The upload failed with an unexpected response: '
|
||||
logger.critical(('Peertube: The upload failed with an unexpected response: '
|
||||
'%s') % response)
|
||||
exit(1)
|
||||
|
||||
|
@ -303,16 +315,16 @@ def run(options):
|
|||
try:
|
||||
secret.read(PEERTUBE_SECRETS_FILE)
|
||||
except Exception as e:
|
||||
logging.error("Peertube: Error loading " + str(PEERTUBE_SECRETS_FILE) + ": " + str(e))
|
||||
logger.critical("Peertube: Error loading " + str(PEERTUBE_SECRETS_FILE) + ": " + str(e))
|
||||
exit(1)
|
||||
insecure_transport = secret.get('peertube', 'OAUTHLIB_INSECURE_TRANSPORT')
|
||||
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = insecure_transport
|
||||
oauth = get_authenticated_service(secret)
|
||||
try:
|
||||
logging.info('Peertube: Uploading video...')
|
||||
logger.info('Peertube: Uploading video...')
|
||||
upload_video(oauth, secret, options)
|
||||
except Exception as e:
|
||||
if hasattr(e, 'message'):
|
||||
logging.error("Peertube: Error: " + str(e.message))
|
||||
logger.error("Peertube: " + str(e.message))
|
||||
else:
|
||||
logging.error("Peertube: Error: " + str(e))
|
||||
logger.error("Peertube: " + str(e))
|
||||
|
|
|
@ -11,9 +11,8 @@ Usage:
|
|||
prismedia --version
|
||||
|
||||
Options:
|
||||
-f, --file=STRING Path to the video file to upload in mp4
|
||||
-f, --file=STRING Path to the video file to upload in mp4. This is the only mandatory option.
|
||||
--name=NAME Name of the video to upload. (default to video filename)
|
||||
--debug Trigger some debug information like options used (default: no)
|
||||
-d, --description=STRING Description of the video. (default: default description)
|
||||
-t, --tags=STRING Tags for the video. comma separated.
|
||||
WARN: tags with punctuation (!, ', ", ?, ...)
|
||||
|
@ -49,6 +48,34 @@ Options:
|
|||
-h --help Show this help.
|
||||
--version Show version.
|
||||
|
||||
Logging options
|
||||
-q --quiet Suppress any log except Critical (alias for --log=critical).
|
||||
--log=STRING Log level, between debug, info, warning, error, critical. Ignored if --quiet is set (default to info)
|
||||
-u --url-only Display generated URL after upload directly on stdout, implies --quiet
|
||||
--batch Display generated URL after upload with platform information for easier parsing. Implies --quiet
|
||||
Be careful --batch and --url-only are mutually exclusives.
|
||||
--debug (Deprecated) Alias for --log=debug. Ignored if --log is set
|
||||
|
||||
Strict options:
|
||||
Strict options allow you to force some option to be present when uploading a video. It's useful to be sure you do not
|
||||
forget something when uploading a video, for example if you use multiples NFO. You may force the presence of description,
|
||||
tags, thumbnail, ...
|
||||
All strict option are optionals and are provided only to avoid errors when uploading :-)
|
||||
All strict options can be specified in NFO directly, the only strict option mandatory on cli is --withNFO
|
||||
All strict options are off by default
|
||||
|
||||
--withNFO Prevent the upload without a NFO, either specified via cli or found in the directory
|
||||
--withThumbnail Prevent the upload without a thumbnail
|
||||
--withName Prevent the upload if no name are found
|
||||
--withDescription Prevent the upload without description
|
||||
--withTags Prevent the upload without tags
|
||||
--withPlaylist Prevent the upload if no playlist
|
||||
--withPublishAt Prevent the upload if no schedule
|
||||
--withPlatform Prevent the upload if at least one platform is not specified
|
||||
--withCategory Prevent the upload if no category
|
||||
--withLanguage Prevent upload if no language
|
||||
--withChannel Prevent upload if no channel
|
||||
|
||||
Categories:
|
||||
Category is the type of video you upload. Default is films.
|
||||
Here are available categories from Peertube and Youtube:
|
||||
|
@ -69,9 +96,16 @@ import sys
|
|||
if sys.version_info[0] < 3:
|
||||
raise Exception("Python 3 or a more recent version is required.")
|
||||
|
||||
import os
|
||||
import datetime
|
||||
import logging
|
||||
logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO)
|
||||
logger = logging.getLogger('Prismedia')
|
||||
logger.setLevel(logging.INFO)
|
||||
ch = logging.StreamHandler()
|
||||
ch.setLevel(logging.INFO)
|
||||
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s: %(message)s')
|
||||
ch.setFormatter(formatter)
|
||||
logger.addHandler(ch)
|
||||
|
||||
from docopt import docopt
|
||||
|
||||
|
@ -81,9 +115,9 @@ from . import utils
|
|||
|
||||
try:
|
||||
# noinspection PyUnresolvedReferences
|
||||
from schema import Schema, And, Or, Optional, SchemaError
|
||||
from schema import Schema, And, Or, Optional, SchemaError, Hook, Use
|
||||
except ImportError:
|
||||
logging.error('This program requires that the `schema` data-validation library'
|
||||
logger.critical('This program requires that the `schema` data-validation library'
|
||||
' is installed: \n'
|
||||
'see https://github.com/halst/schema\n')
|
||||
exit(1)
|
||||
|
@ -91,12 +125,12 @@ try:
|
|||
# noinspection PyUnresolvedReferences
|
||||
import magic
|
||||
except ImportError:
|
||||
logging.error('This program requires that the `python-magic` library'
|
||||
logger.critical('This program requires that the `python-magic` library'
|
||||
' is installed, NOT the Python bindings to libmagic API \n'
|
||||
'see https://github.com/ahupp/python-magic\n')
|
||||
exit(1)
|
||||
|
||||
VERSION = "prismedia v0.9.1"
|
||||
VERSION = "prismedia v0.10.0"
|
||||
|
||||
VALID_PRIVACY_STATUSES = ('public', 'private', 'unlisted')
|
||||
VALID_CATEGORIES = (
|
||||
|
@ -170,17 +204,104 @@ def validatePublish(publish):
|
|||
|
||||
def validateThumbnail(thumbnail):
|
||||
supported_types = ['image/jpg', 'image/jpeg']
|
||||
if magic.from_file(thumbnail, mime=True) in supported_types:
|
||||
if os.path.exists(thumbnail) and \
|
||||
magic.from_file(thumbnail, mime=True) in supported_types:
|
||||
return thumbnail
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def validateLogLevel(loglevel):
|
||||
numeric_level = getattr(logging, loglevel, None)
|
||||
if not isinstance(numeric_level, int):
|
||||
return False
|
||||
return True
|
||||
|
||||
def _optionnalOrStrict(key, scope, error):
|
||||
option = key.replace('-', '')
|
||||
option = option[0].upper() + option[1:]
|
||||
if scope["--with" + option] is True and scope[key] is None:
|
||||
logger.critical("Prismedia: you have required the strict presence of " + key + " but none is found")
|
||||
exit(1)
|
||||
return True
|
||||
|
||||
|
||||
def configureLogs(options):
|
||||
if options.get('--batch') and options.get('--url-only'):
|
||||
logger.critical("Prismedia: Please use either --batch OR --url-only, not both.")
|
||||
exit(1)
|
||||
# batch and url-only implies quiet
|
||||
if options.get('--batch') or options.get('--url-only'):
|
||||
options['--quiet'] = True
|
||||
|
||||
if options.get('--quiet'):
|
||||
# We need to set both log level in the same time
|
||||
logger.setLevel(50)
|
||||
ch.setLevel(50)
|
||||
elif options.get('--log'):
|
||||
numeric_level = getattr(logging, options["--log"], None)
|
||||
# We need to set both log level in the same time
|
||||
logger.setLevel(numeric_level)
|
||||
ch.setLevel(numeric_level)
|
||||
elif options.get('--debug'):
|
||||
logger.warning("DEPRECATION: --debug is deprecated, please use --log=debug instead")
|
||||
logger.setLevel(10)
|
||||
ch.setLevel(10)
|
||||
|
||||
|
||||
def configureStdoutLogs():
|
||||
logger_stdout = logging.getLogger('stdoutlogs')
|
||||
logger_stdout.setLevel(logging.INFO)
|
||||
ch_stdout = logging.StreamHandler(stream=sys.stdout)
|
||||
ch_stdout.setLevel(logging.INFO)
|
||||
# Default stdout logs is url only
|
||||
formatter_stdout = logging.Formatter('%(message)s')
|
||||
ch_stdout.setFormatter(formatter_stdout)
|
||||
logger_stdout.addHandler(ch_stdout)
|
||||
|
||||
def main():
|
||||
options = docopt(__doc__, version=VERSION)
|
||||
|
||||
earlyoptionSchema = Schema({
|
||||
Optional('--log'): Or(None, And(
|
||||
str,
|
||||
Use(str.upper),
|
||||
validateLogLevel,
|
||||
error="Log level not recognized")
|
||||
),
|
||||
Optional('--quiet', default=False): bool,
|
||||
Optional('--debug'): bool,
|
||||
Optional('--url-only', default=False): bool,
|
||||
Optional('--batch', default=False): bool,
|
||||
Optional('--withNFO', default=False): bool,
|
||||
Optional('--withThumbnail', default=False): bool,
|
||||
Optional('--withName', default=False): bool,
|
||||
Optional('--withDescription', default=False): bool,
|
||||
Optional('--withTags', default=False): bool,
|
||||
Optional('--withPlaylist', default=False): bool,
|
||||
Optional('--withPublishAt', default=False): bool,
|
||||
Optional('--withPlatform', default=False): bool,
|
||||
Optional('--withCategory', default=False): bool,
|
||||
Optional('--withLanguage', default=False): bool,
|
||||
Optional('--withChannel', default=False): bool,
|
||||
# This allow to return all other options for further use: https://github.com/keleshev/schema#extra-keys
|
||||
object: object
|
||||
})
|
||||
|
||||
schema = Schema({
|
||||
'--file': And(str, validateVideo, error='file is not supported, please use mp4'),
|
||||
'--file': And(str, os.path.exists, validateVideo, error='file is not supported, please use mp4'),
|
||||
# Strict option checks - at the moment Schema needs to check Hook and Optional separately #
|
||||
Hook('--name', handler=_optionnalOrStrict): object,
|
||||
Hook('--description', handler=_optionnalOrStrict): object,
|
||||
Hook('--tags', handler=_optionnalOrStrict): object,
|
||||
Hook('--category', handler=_optionnalOrStrict): object,
|
||||
Hook('--language', handler=_optionnalOrStrict): object,
|
||||
Hook('--platform', handler=_optionnalOrStrict): object,
|
||||
Hook('--publishAt', handler=_optionnalOrStrict): object,
|
||||
Hook('--thumbnail', handler=_optionnalOrStrict): object,
|
||||
Hook('--channel', handler=_optionnalOrStrict): object,
|
||||
Hook('--playlist', handler=_optionnalOrStrict): object,
|
||||
# Validate checks #
|
||||
Optional('--name'): Or(None, And(
|
||||
str,
|
||||
lambda x: not x.isdigit(),
|
||||
|
@ -228,7 +349,6 @@ def main():
|
|||
validatePublish,
|
||||
error="DATE should be the form YYYY-MM-DDThh:mm:ss and has to be in the future")
|
||||
),
|
||||
Optional('--debug'): bool,
|
||||
Optional('--cca'): bool,
|
||||
Optional('--disable-comments'): bool,
|
||||
Optional('--nsfw'): bool,
|
||||
|
@ -240,22 +360,41 @@ def main():
|
|||
Optional('--playlist'): Or(None, str),
|
||||
Optional('--playlistCreate'): bool,
|
||||
'--help': bool,
|
||||
'--version': bool
|
||||
'--version': bool,
|
||||
# This allow to return all other options for further use: https://github.com/keleshev/schema#extra-keys
|
||||
object: object
|
||||
})
|
||||
# We need to validate early options first as withNFO and logs options should be prioritized
|
||||
try:
|
||||
options = earlyoptionSchema.validate(options)
|
||||
configureLogs(options)
|
||||
except SchemaError as e:
|
||||
logger.critical(e)
|
||||
exit(1)
|
||||
|
||||
if options.get('--url-only') or options.get('--batch'):
|
||||
configureStdoutLogs()
|
||||
|
||||
options = utils.parseNFO(options)
|
||||
|
||||
# Once NFO are loaded, we need to revalidate strict options in case some were in NFO
|
||||
try:
|
||||
options = earlyoptionSchema.validate(options)
|
||||
except SchemaError as e:
|
||||
logger.critical(e)
|
||||
exit(1)
|
||||
|
||||
if not options.get('--thumbnail'):
|
||||
options = utils.searchThumbnail(options)
|
||||
|
||||
try:
|
||||
options = schema.validate(options)
|
||||
except SchemaError as e:
|
||||
exit(e)
|
||||
logger.critical(e)
|
||||
exit(1)
|
||||
|
||||
if options.get('--debug'):
|
||||
print(sys.version)
|
||||
print(options)
|
||||
logger.debug("Python " + sys.version)
|
||||
logger.debug(options)
|
||||
|
||||
if options.get('--platform') is None or "peertube" in options.get('--platform'):
|
||||
pt_upload.run(options)
|
||||
|
@ -264,6 +403,5 @@ def main():
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import warnings
|
||||
warnings.warn("use 'python -m prismedia', not 'python -m prismedia.upload'", DeprecationWarning)
|
||||
logger.warning("DEPRECATION: use 'python -m prismedia', not 'python -m prismedia.upload'")
|
||||
main()
|
||||
|
|
|
@ -9,6 +9,8 @@ from subprocess import check_call, CalledProcessError, STDOUT
|
|||
import unidecode
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger('Prismedia')
|
||||
|
||||
### CATEGORIES ###
|
||||
YOUTUBE_CATEGORY = {
|
||||
"music": 10,
|
||||
|
@ -123,18 +125,25 @@ def searchThumbnail(options):
|
|||
options['--thumbnail'] = video_directory + video_file + ".jpg"
|
||||
elif isfile(video_directory + video_file + ".jpeg"):
|
||||
options['--thumbnail'] = video_directory + video_file + ".jpeg"
|
||||
|
||||
# Display some info after research
|
||||
if not options.get('--thumbnail'):
|
||||
logger.debug("No thumbnail has been found, continuing")
|
||||
else:
|
||||
logger.info("Using " + options.get('--thumbnail') + "as thumbnail")
|
||||
|
||||
return options
|
||||
|
||||
|
||||
# return the nfo as a RawConfigParser object
|
||||
def loadNFO(filename):
|
||||
try:
|
||||
logging.info("Loading " + filename + " as NFO")
|
||||
logger.info("Loading " + filename + " as NFO")
|
||||
nfo = RawConfigParser()
|
||||
nfo.read(filename, encoding='utf-8')
|
||||
return nfo
|
||||
except Exception as e:
|
||||
logging.error("Problem loading NFO file " + filename + ": " + str(e))
|
||||
logger.critical("Problem loading NFO file " + filename + ": " + str(e))
|
||||
exit(1)
|
||||
return False
|
||||
|
||||
|
@ -168,7 +177,17 @@ def parseNFO(options):
|
|||
if isfile(options.get('--nfo')):
|
||||
nfo_cli = loadNFO(options.get('--nfo'))
|
||||
else:
|
||||
logging.error("Given NFO file does not exist, please check your path.")
|
||||
logger.critical("Given NFO file does not exist, please check your path.")
|
||||
exit(1)
|
||||
|
||||
# If there is no NFO and strict option is enabled, then stop there
|
||||
if options.get('--withNFO'):
|
||||
if not isinstance(nfo_cli, RawConfigParser) and \
|
||||
not isinstance(nfo_file, RawConfigParser) and \
|
||||
not isinstance(nfo_videoname, RawConfigParser) and \
|
||||
not isinstance(nfo_directory, RawConfigParser) and \
|
||||
not isinstance(nfo_txt, RawConfigParser):
|
||||
logger.critical("You have required the strict presence of NFO but none is found, please use a NFO.")
|
||||
exit(1)
|
||||
|
||||
# We need to load NFO in this exact order to keep the priorities
|
||||
|
@ -188,7 +207,7 @@ def parseNFO(options):
|
|||
except NoOptionError:
|
||||
continue
|
||||
except NoSectionError:
|
||||
logging.error(nfo + " misses section [video], please check syntax of your NFO.")
|
||||
logger.critical(nfo + " misses section [video], please check syntax of your NFO.")
|
||||
exit(1)
|
||||
return options
|
||||
|
||||
|
|
|
@ -23,9 +23,7 @@ from google_auth_oauthlib.flow import InstalledAppFlow
|
|||
|
||||
|
||||
from . import utils
|
||||
|
||||
logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO)
|
||||
|
||||
logger = logging.getLogger('Prismedia')
|
||||
|
||||
# Explicitly tell the underlying HTTP transport library not to retry, since
|
||||
# we are handling retry logic ourselves.
|
||||
|
@ -87,7 +85,7 @@ def check_authenticated_scopes():
|
|||
credential_params = json.load(f)
|
||||
# Check if all scopes are present
|
||||
if credential_params["_scopes"] != SCOPES:
|
||||
logging.warning("Youtube: Credentials are obsolete, need to re-authenticate.")
|
||||
logger.warning("Youtube: Credentials are obsolete, need to re-authenticate.")
|
||||
os.remove(CREDENTIALS_PATH)
|
||||
|
||||
|
||||
|
@ -144,8 +142,8 @@ def initialize_upload(youtube, options):
|
|||
if not playlist_id and options.get('--playlistCreate'):
|
||||
playlist_id = create_playlist(youtube, options.get('--playlist'))
|
||||
elif not playlist_id:
|
||||
logging.warning("Youtube: Playlist `" + options.get('--playlist') + "` is unknown.")
|
||||
logging.warning("If you want to create it, set the --playlistCreate option.")
|
||||
logger.warning("Youtube: Playlist `" + options.get('--playlist') + "` is unknown.")
|
||||
logger.warning("Youtube: If you want to create it, set the --playlistCreate option.")
|
||||
playlist_id = ""
|
||||
else:
|
||||
playlist_id = ""
|
||||
|
@ -156,7 +154,7 @@ def initialize_upload(youtube, options):
|
|||
body=body,
|
||||
media_body=MediaFileUpload(path, chunksize=-1, resumable=True)
|
||||
)
|
||||
video_id = resumable_upload(insert_request, 'video', 'insert')
|
||||
video_id = resumable_upload(insert_request, 'video', 'insert', options)
|
||||
|
||||
# If we get a video_id, upload is successful and we are able to set thumbnail
|
||||
if video_id and options.get('--thumbnail'):
|
||||
|
@ -179,8 +177,8 @@ def get_playlist_by_name(youtube, playlist_name):
|
|||
|
||||
|
||||
def create_playlist(youtube, playlist_name):
|
||||
template = ('Youtube: Playlist %s does not exist, creating it.')
|
||||
logging.info(template % (str(playlist_name)))
|
||||
template = 'Youtube: Playlist %s does not exist, creating it.'
|
||||
logger.info(template % (str(playlist_name)))
|
||||
resources = build_resource({'snippet.title': playlist_name,
|
||||
'snippet.description': '',
|
||||
'status.privacyStatus': 'public'})
|
||||
|
@ -244,7 +242,7 @@ def set_thumbnail(youtube, media_file, **kwargs):
|
|||
|
||||
|
||||
def set_playlist(youtube, playlist_id, video_id):
|
||||
logging.info('Youtube: Configuring playlist...')
|
||||
logger.info('Youtube: Configuring playlist...')
|
||||
resource = build_resource({'snippet.playlistId': playlist_id,
|
||||
'snippet.resourceId.kind': 'youtube#video',
|
||||
'snippet.resourceId.videoId': video_id,
|
||||
|
@ -256,38 +254,48 @@ def set_playlist(youtube, playlist_id, video_id):
|
|||
part='snippet'
|
||||
).execute()
|
||||
except Exception as e:
|
||||
# Workaround while youtube API is broken, see issue #47 for details
|
||||
if e.resp.status != 404 and "Video not found" not in str(e):
|
||||
if hasattr(e, 'message'):
|
||||
logging.error("Youtube: Error: " + str(e.message))
|
||||
logger.critical("Youtube: " + str(e.message))
|
||||
exit(1)
|
||||
else:
|
||||
logging.error("Youtube: Error: " + str(e))
|
||||
logger.critical("Youtube: " + str(e))
|
||||
exit(1)
|
||||
logging.info('Youtube: Video is correctly added to the playlist.')
|
||||
logger.info('Youtube: Video is correctly added to the playlist.')
|
||||
|
||||
|
||||
# This method implements an exponential backoff strategy to resume a
|
||||
# failed upload.
|
||||
def resumable_upload(request, resource, method):
|
||||
def resumable_upload(request, resource, method, options):
|
||||
response = None
|
||||
error = None
|
||||
retry = 0
|
||||
logger_stdout = None
|
||||
if options.get('--url-only') or options.get('--batch'):
|
||||
logger_stdout = logging.getLogger('stdoutlogs')
|
||||
while response is None:
|
||||
try:
|
||||
template = 'Youtube: Uploading %s...'
|
||||
logging.info(template % resource)
|
||||
logger.info(template % resource)
|
||||
status, response = request.next_chunk()
|
||||
if response is not None:
|
||||
if method == 'insert' and 'id' in response:
|
||||
logging.info('Youtube : Video was successfully uploaded.')
|
||||
logger.info('Youtube : Video was successfully uploaded.')
|
||||
template = 'Youtube: Watch it at https://youtu.be/%s (post-encoding could take some time)'
|
||||
logging.info(template % response['id'])
|
||||
logger.info(template % response['id'])
|
||||
template_stdout = 'https://youtu.be/%s'
|
||||
if options.get('--url-only'):
|
||||
logger_stdout.info(template_stdout % response['id'])
|
||||
elif options.get('--batch'):
|
||||
logger_stdout.info("Youtube: " + template_stdout % response['id'])
|
||||
return response['id']
|
||||
elif method != 'insert' or "id" not in response:
|
||||
logging.info('Youtube: Thumbnail was successfully set.')
|
||||
logger.info('Youtube: Thumbnail was successfully set.')
|
||||
else:
|
||||
template = ('Youtube : The upload failed with an '
|
||||
'unexpected response: %s')
|
||||
logging.error(template % response)
|
||||
logger.critical(template % response)
|
||||
exit(1)
|
||||
except HttpError as e:
|
||||
if e.resp.status in RETRIABLE_STATUS_CODES:
|
||||
|
@ -299,15 +307,14 @@ def resumable_upload(request, resource, method):
|
|||
error = 'Youtube : A retriable error occurred: %s' % e
|
||||
|
||||
if error is not None:
|
||||
logging.warning(error)
|
||||
logger.warning(error)
|
||||
retry += 1
|
||||
if retry > MAX_RETRIES:
|
||||
logging.error('Youtube : No longer attempting to retry.')
|
||||
exit(1)
|
||||
logger.error('Youtube : No longer attempting to retry.')
|
||||
|
||||
max_sleep = 2 ** retry
|
||||
sleep_seconds = random.random() * max_sleep
|
||||
logging.warning('Youtube : Sleeping %f seconds and then retrying...'
|
||||
logger.warning('Youtube : Sleeping %f seconds and then retrying...'
|
||||
% sleep_seconds)
|
||||
time.sleep(sleep_seconds)
|
||||
|
||||
|
@ -317,5 +324,5 @@ def run(options):
|
|||
try:
|
||||
initialize_upload(youtube, options)
|
||||
except HttpError as e:
|
||||
logging.error('Youtube : An HTTP error %d occurred:\n%s' % (e.resp.status,
|
||||
logger.error('Youtube : An HTTP error %d occurred:\n%s' % (e.resp.status,
|
||||
e.content))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[tool.poetry]
|
||||
name = "prismedia"
|
||||
version = "0.9.1"
|
||||
version = "0.10.0"
|
||||
description = "scripting your way to upload videos on peertube and youtube"
|
||||
authors = [
|
||||
"LecygneNoir <git@lecygnenoir.info>",
|
||||
|
@ -21,10 +21,10 @@ python = ">=3.5"
|
|||
configparser = "^3.7.1"
|
||||
docopt = "^0.6.2"
|
||||
future = "^0.17.1"
|
||||
google-api-python-client = "^1.7.6"
|
||||
google-auth = "^1.6.1"
|
||||
google-auth-httplib2 = "^0.0.3"
|
||||
google-auth-oauthlib = "^0.2.0"
|
||||
google-api-python-client = ">=1.7.6"
|
||||
google-auth = ">=1.6.1"
|
||||
google-auth-httplib2 = ">=0.0.3"
|
||||
google-auth-oauthlib = ">=0.2.0"
|
||||
httplib2 = "^0.12.1"
|
||||
oauthlib = "^2.1.0"
|
||||
python-magic = "^0.4.15"
|
||||
|
@ -32,7 +32,7 @@ python-magic-bin = { version = "^0.4.14", markers = "platform_system == 'Windows
|
|||
requests = "^2.18.4"
|
||||
requests-oauthlib = "^0.8.0"
|
||||
requests-toolbelt = "^0.9.1"
|
||||
schema = "^0.6.8"
|
||||
schema = ">=0.7.1"
|
||||
tzlocal = "^1.5.1"
|
||||
Unidecode = "^1.0.23"
|
||||
uritemplate = "^3.0.0"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue