From 429ea2333e4ee56468aa399c01a8c7a1749785ae Mon Sep 17 00:00:00 2001 From: LecygneNoir Date: Mon, 30 Mar 2020 16:13:26 +0200 Subject: [PATCH 01/14] Add new feature to schedule different publication date depending of the platform. Target v0.9.0, Fix #43 --- CHANGELOG.md | 5 +++++ README.md | 2 ++ lib/pt_upload.py | 7 ++++++- lib/yt_upload.py | 10 ++++++++-- nfo_example.txt | 5 ++++- prismedia_upload.py | 12 ++++++++++++ 6 files changed, 37 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b4d2a8..f7bb84c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## v0.8.1 + +### Features + - Add two new options to schedule video by platform. You may now use youtubeAt and peertubeAt to prepare previews + ## v0.8.0 ### Breaking changes diff --git a/README.md b/README.md index 2c9accc..04aaa49 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,8 @@ Options: --publishAt=DATE Publish the video at the given DATE using local server timezone. DATE should be on the form YYYY-MM-DDThh:mm:ss eg: 2018-03-12T19:00:00 DATE should be in the future + --peertubeAt=DATE + --youtubeAt=DATE Override publishAt for the corresponding platform. Allow to create preview on specific platform --thumbnail=STRING Path to a file to use as a thumbnail for the video. Supported types are jpg and jpeg. By default, prismedia search for an image based on video name followed by .jpg or .jpeg diff --git a/lib/pt_upload.py b/lib/pt_upload.py index 4701844..ee5f78c 100644 --- a/lib/pt_upload.py +++ b/lib/pt_upload.py @@ -230,8 +230,13 @@ def upload_video(oauth, secret, options): if options.get('--privacy'): privacy = options.get('--privacy').lower() - if options.get('--publishAt'): + # If peertubeAt exists, use instead of publishAt + if options.get('--peertubeAt'): + publishAt = options.get('--peertubeAt') + elif options.get('--publishAt'): publishAt = options.get('--publishAt') + + if 'publishAt' in locals(): publishAt = datetime.datetime.strptime(publishAt, '%Y-%m-%dT%H:%M:%S') tz = get_localzone() tz = pytz.timezone(str(tz)) diff --git a/lib/yt_upload.py b/lib/yt_upload.py index c618a6f..5c10b2f 100644 --- a/lib/yt_upload.py +++ b/lib/yt_upload.py @@ -124,9 +124,15 @@ def initialize_upload(youtube, options): } } - if options.get('--publishAt'): + # If peertubeAt exists, use instead of publishAt + if options.get('--youtubeAt'): + publishAt = options.get('--youtubeAt') + elif options.get('--publishAt'): + publishAt = options.get('--publishAt') + + if 'publishAt' in locals(): # Youtube needs microsecond and the local timezone from ISO 8601 - publishAt = options.get('--publishAt') + ".000001" + publishAt = publishAt + ".000001" publishAt = datetime.datetime.strptime(publishAt, '%Y-%m-%dT%H:%M:%S.%f') tz = get_localzone() tz = pytz.timezone(str(tz)) diff --git a/nfo_example.txt b/nfo_example.txt index 4564d8a..a6c537d 100644 --- a/nfo_example.txt +++ b/nfo_example.txt @@ -24,4 +24,7 @@ playlistCreate = True nsfw = False platform = youtube, peertube language = French -publishAt=2034-05-07T19:00:00 \ No newline at end of file +publishAt=2034-05-07T19:00:00 +# platformAt overrides the default publishAt for the corresponding platform +#peertubeAt = 2034-05-14T19:00:00 +#youtubeAt = 2034-05-21T19:00:00 \ No newline at end of file diff --git a/prismedia_upload.py b/prismedia_upload.py index 02b9bb8..d36b3ed 100755 --- a/prismedia_upload.py +++ b/prismedia_upload.py @@ -33,6 +33,8 @@ Options: --publishAt=DATE Publish the video at the given DATE using local server timezone. DATE should be on the form YYYY-MM-DDThh:mm:ss eg: 2018-03-12T19:00:00 DATE should be in the future + --peertubeAt=DATE + --youtubeAt=DATE Override publishAt for the corresponding platform. Allow to create preview on specific platform --thumbnail=STRING Path to a file to use as a thumbnail for the video. Supported types are jpg and jpeg. By default, prismedia search for an image based on video name followed by .jpg or .jpeg @@ -208,6 +210,16 @@ if __name__ == '__main__': validatePublish, error="DATE should be the form YYYY-MM-DDThh:mm:ss and has to be in the future") ), + Optional('--peertubeAt'): Or(None, And( + str, + validatePublish, + error="DATE should be the form YYYY-MM-DDThh:mm:ss and has to be in the future") + ), + Optional('--youtubeAt'): Or(None, And( + str, + 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, From b1a5d244d49d9992315138ed5ab435090730bd13 Mon Sep 17 00:00:00 2001 From: LecygneNoir Date: Wed, 1 Apr 2020 09:59:55 +0200 Subject: [PATCH 02/14] Prepare poetry with more standard nomination and configuration and change gitignore to avoid committing file by error --- .gitignore | 5 ++++- nfo_example.txt => prismedia/config/nfo_example.txt | 0 .../config/peertube_secret.sample | 0 .../config/youtube_secret.json.sample | 0 {lib => prismedia}/pt_upload.py | 0 prismedia_upload.py => prismedia/upload.py | 0 {lib => prismedia}/utils.py | 0 {lib => prismedia}/yt_upload.py | 0 8 files changed, 4 insertions(+), 1 deletion(-) rename nfo_example.txt => prismedia/config/nfo_example.txt (100%) rename peertube_secret.sample => prismedia/config/peertube_secret.sample (100%) rename youtube_secret.json.sample => prismedia/config/youtube_secret.json.sample (100%) rename {lib => prismedia}/pt_upload.py (100%) rename prismedia_upload.py => prismedia/upload.py (100%) rename {lib => prismedia}/utils.py (100%) rename {lib => prismedia}/yt_upload.py (100%) diff --git a/.gitignore b/.gitignore index c22856f..38e944a 100644 --- a/.gitignore +++ b/.gitignore @@ -61,4 +61,7 @@ target/ # Project youtube_secret.json peertube_secret -.youtube_credentials.json \ No newline at end of file +.youtube_credentials.json +nfo_example.txt +peertube_secret.sample +youtube_secret.json.sample \ No newline at end of file diff --git a/nfo_example.txt b/prismedia/config/nfo_example.txt similarity index 100% rename from nfo_example.txt rename to prismedia/config/nfo_example.txt diff --git a/peertube_secret.sample b/prismedia/config/peertube_secret.sample similarity index 100% rename from peertube_secret.sample rename to prismedia/config/peertube_secret.sample diff --git a/youtube_secret.json.sample b/prismedia/config/youtube_secret.json.sample similarity index 100% rename from youtube_secret.json.sample rename to prismedia/config/youtube_secret.json.sample diff --git a/lib/pt_upload.py b/prismedia/pt_upload.py similarity index 100% rename from lib/pt_upload.py rename to prismedia/pt_upload.py diff --git a/prismedia_upload.py b/prismedia/upload.py similarity index 100% rename from prismedia_upload.py rename to prismedia/upload.py diff --git a/lib/utils.py b/prismedia/utils.py similarity index 100% rename from lib/utils.py rename to prismedia/utils.py diff --git a/lib/yt_upload.py b/prismedia/yt_upload.py similarity index 100% rename from lib/yt_upload.py rename to prismedia/yt_upload.py From 72b47b95ec864c56ebd9808b7f4d0f72ebdd17f8 Mon Sep 17 00:00:00 2001 From: LecygneNoir Date: Wed, 1 Apr 2020 10:23:33 +0200 Subject: [PATCH 03/14] Modify files and add poetry configuration files to use poetry for distributing and publishing --- poetry.lock | 508 +++++++++++++++++++++++++++++++++++++++++ prismedia/__init__.py | 5 + prismedia/__main__.py | 2 + prismedia/genconfig.py | 15 ++ prismedia/pt_upload.py | 2 +- prismedia/upload.py | 28 ++- prismedia/yt_upload.py | 2 +- pyproject.toml | 49 ++++ requirements.txt | 148 ++++++++++-- 9 files changed, 728 insertions(+), 31 deletions(-) create mode 100644 poetry.lock create mode 100644 prismedia/__init__.py create mode 100644 prismedia/__main__.py create mode 100644 prismedia/genconfig.py create mode 100644 pyproject.toml diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..1f72b3a --- /dev/null +++ b/poetry.lock @@ -0,0 +1,508 @@ +[[package]] +category = "main" +description = "Extensible memoizing collections and decorators" +name = "cachetools" +optional = false +python-versions = "*" +version = "3.1.1" + +[[package]] +category = "main" +description = "Python package for providing Mozilla's CA Bundle." +name = "certifi" +optional = false +python-versions = "*" +version = "2019.11.28" + +[[package]] +category = "main" +description = "Universal encoding detector for Python 2 and 3" +name = "chardet" +optional = false +python-versions = "*" +version = "3.0.4" + +[[package]] +category = "main" +description = "Updated configparser from Python 3.7 for Python 2.6+." +name = "configparser" +optional = false +python-versions = ">=2.6" +version = "3.8.1" + +[package.extras] +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 = "Pythonic argument parser, that will make you smile" +name = "docopt" +optional = false +python-versions = "*" +version = "0.6.2" + +[[package]] +category = "main" +description = "Clean single-source support for Python 3 and 2" +name = "future" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +version = "0.17.1" + +[[package]] +category = "main" +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.16.0" + +[package.dependencies] +google-auth = ">=0.4.0,<2.0dev" +googleapis-common-protos = ">=1.6.0,<2.0dev" +protobuf = ">=3.4.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)"] +grpcgcp = ["grpcio-gcp (>=0.2.2)"] +grpcio-gcp = ["grpcio-gcp (>=0.2.2)"] + +[[package]] +category = "main" +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.0" + +[package.dependencies] +google-api-core = ">=1.13.0,<2dev" +google-auth = ">=1.4.1" +google-auth-httplib2 = ">=0.0.3" +httplib2 = ">=0.9.2,<1dev" +six = ">=1.6.1,<2dev" +uritemplate = ">=3.0.0,<4dev" + +[[package]] +category = "main" +description = "Google Authentication Library" +name = "google-auth" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" +version = "1.12.0" + +[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]] +category = "main" +description = "Google Authentication Library: httplib2 transport" +name = "google-auth-httplib2" +optional = false +python-versions = "*" +version = "0.0.3" + +[package.dependencies] +google-auth = "*" +httplib2 = ">=0.9.1" + +[[package]] +category = "main" +description = "Google Authentication Library" +name = "google-auth-oauthlib" +optional = false +python-versions = "*" +version = "0.2.0" + +[package.dependencies] +google-auth = "*" +requests-oauthlib = ">=0.7.0" + +[package.extras] +tool = ["click"] + +[[package]] +category = "main" +description = "Common protobufs used in Google APIs" +name = "googleapis-common-protos" +optional = false +python-versions = "*" +version = "1.51.0" + +[package.dependencies] +protobuf = ">=3.6.0" + +[package.extras] +grpc = ["grpcio (>=1.0.0)"] + +[[package]] +category = "main" +description = "A comprehensive HTTP client library." +name = "httplib2" +optional = false +python-versions = "*" +version = "0.12.3" + +[[package]] +category = "main" +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" + +[[package]] +category = "main" +description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" +name = "oauthlib" +optional = false +python-versions = "*" +version = "2.1.0" + +[package.extras] +rsa = ["cryptography"] +signals = ["blinker"] +signedtoken = ["cryptography", "pyjwt (>=1.0.0)"] +test = ["nose", "unittest2", "cryptography", "mock", "pyjwt (>=1.0.0)", "blinker"] + +[[package]] +category = "main" +description = "Protocol Buffers" +name = "protobuf" +optional = false +python-versions = "*" +version = "3.11.3" + +[package.dependencies] +setuptools = "*" +six = ">=1.9" + +[[package]] +category = "main" +description = "ASN.1 types and codecs" +name = "pyasn1" +optional = false +python-versions = "*" +version = "0.4.8" + +[[package]] +category = "main" +description = "A collection of ASN.1-based protocols modules." +name = "pyasn1-modules" +optional = false +python-versions = "*" +version = "0.2.8" + +[package.dependencies] +pyasn1 = ">=0.4.6,<0.5.0" + +[[package]] +category = "main" +description = "File type identification using libmagic" +marker = "platform_system == \"Linux\"" +name = "python-magic" +optional = false +python-versions = "*" +version = "0.4.15" + +[[package]] +category = "main" +description = "File type identification using libmagic binary package" +marker = "platform_system == \"Windows\"" +name = "python-magic-bin" +optional = false +python-versions = "*" +version = "0.4.14" + +[[package]] +category = "main" +description = "World timezone definitions, modern and historical" +name = "pytz" +optional = false +python-versions = "*" +version = "2019.3" + +[[package]] +category = "main" +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" + +[package.dependencies] +certifi = ">=2017.4.17" +chardet = ">=3.0.2,<4" +idna = ">=2.5,<3" +urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" + +[package.extras] +security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] +socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] + +[[package]] +category = "main" +description = "OAuthlib authentication support for Requests." +name = "requests-oauthlib" +optional = false +python-versions = "*" +version = "0.8.0" + +[package.dependencies] +oauthlib = ">=0.6.2" +requests = ">=2.0.0" + +[package.extras] +rsa = ["oauthlib (>=0.6.2)", "requests (>=2.0.0)"] + +[[package]] +category = "main" +description = "A utility belt for advanced users of python-requests" +name = "requests-toolbelt" +optional = false +python-versions = "*" +version = "0.9.1" + +[package.dependencies] +requests = ">=2.0.1,<3.0.0" + +[[package]] +category = "main" +description = "Pure-Python RSA implementation" +name = "rsa" +optional = false +python-versions = "*" +version = "4.0" + +[package.dependencies] +pyasn1 = ">=0.1.3" + +[[package]] +category = "main" +description = "Simple data validation library" +name = "schema" +optional = false +python-versions = "*" +version = "0.6.8" + +[[package]] +category = "main" +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" + +[[package]] +category = "main" +description = "tzinfo object for the local timezone" +name = "tzlocal" +optional = false +python-versions = "*" +version = "1.5.1" + +[package.dependencies] +pytz = "*" + +[[package]] +category = "main" +description = "ASCII transliterations of Unicode text" +name = "unidecode" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.1.1" + +[[package]] +category = "main" +description = "URI templates" +name = "uritemplate" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "3.0.1" + +[[package]] +category = "main" +description = "HTTP library with thread-safe connection pooling, file post, and more." +name = "urllib3" +optional = false +python-versions = "*" +version = "1.22" + +[package.extras] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] + +[metadata] +content-hash = "8a3265f5af3ae0327d975200022dd0da8b6a0d72d06a81447e379691daf8726f" +python-versions = ">=3.5" + +[metadata.files] +cachetools = [ + {file = "cachetools-3.1.1-py2.py3-none-any.whl", hash = "sha256:428266a1c0d36dc5aca63a2d7c5942e88c2c898d72139fca0e97fdd2380517ae"}, + {file = "cachetools-3.1.1.tar.gz", hash = "sha256:8ea2d3ce97850f31e4a08b0e2b5e6c34997d7216a9d2c98e0f3978630d4da69a"}, +] +certifi = [ + {file = "certifi-2019.11.28-py2.py3-none-any.whl", hash = "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3"}, + {file = "certifi-2019.11.28.tar.gz", hash = "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"}, +] +chardet = [ + {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, + {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, +] +configparser = [ + {file = "configparser-3.8.1-py2.py3-none-any.whl", hash = "sha256:45d1272aad6cfd7a8a06cf5c73f2ceb6a190f6acc1fa707e7f82a4c053b28b18"}, + {file = "configparser-3.8.1.tar.gz", hash = "sha256:bc37850f0cc42a1725a796ef7d92690651bf1af37d744cc63161dac62cabee17"}, +] +docopt = [ + {file = "docopt-0.6.2.tar.gz", hash = "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"}, +] +future = [ + {file = "future-0.17.1.tar.gz", hash = "sha256:67045236dcfd6816dc439556d009594abf643e5eb48992e36beac09c2ca659b8"}, +] +google-api-core = [ + {file = "google-api-core-1.16.0.tar.gz", hash = "sha256:92e962a087f1c4b8d1c5c88ade1c1dfd550047dcffb320c57ef6a534a20403e2"}, + {file = "google_api_core-1.16.0-py2.py3-none-any.whl", hash = "sha256:859f7392676761f2b160c6ee030c3422135ada4458f0948c5690a6a7c8d86294"}, +] +google-api-python-client = [ + {file = "google-api-python-client-1.8.0.tar.gz", hash = "sha256:0f5b42a14e2d2f7dee40f2e4514531dbe95ebde9c2173b1c4040a65c427e7900"}, + {file = "google_api_python_client-1.8.0-py3-none-any.whl", hash = "sha256:5032ad1af5046889649b3848f2e871889fbb6ae440198a549fe1699581300386"}, +] +google-auth = [ + {file = "google-auth-1.12.0.tar.gz", hash = "sha256:016924388770b7e66c7e9ade1c4c3144ee88812d79697fd6c0dad9abdfcda2fd"}, + {file = "google_auth-1.12.0-py2.py3-none-any.whl", hash = "sha256:01d686448f57d3bc027726474faa1aa650ba333bedb392e06938b0add8ec8d3a"}, +] +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"}, +] +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"}, +] +googleapis-common-protos = [ + {file = "googleapis-common-protos-1.51.0.tar.gz", hash = "sha256:013c91704279119150e44ef770086fdbba158c1f978a6402167d47d5409e226e"}, +] +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"}, +] +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"}, +] +pyasn1 = [ + {file = "pyasn1-0.4.8-py2.4.egg", hash = "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"}, + {file = "pyasn1-0.4.8-py2.5.egg", hash = "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf"}, + {file = "pyasn1-0.4.8-py2.6.egg", hash = "sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00"}, + {file = "pyasn1-0.4.8-py2.7.egg", hash = "sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8"}, + {file = "pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d"}, + {file = "pyasn1-0.4.8-py3.1.egg", hash = "sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86"}, + {file = "pyasn1-0.4.8-py3.2.egg", hash = "sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7"}, + {file = "pyasn1-0.4.8-py3.3.egg", hash = "sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576"}, + {file = "pyasn1-0.4.8-py3.4.egg", hash = "sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12"}, + {file = "pyasn1-0.4.8-py3.5.egg", hash = "sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2"}, + {file = "pyasn1-0.4.8-py3.6.egg", hash = "sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359"}, + {file = "pyasn1-0.4.8-py3.7.egg", hash = "sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776"}, + {file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"}, +] +pyasn1-modules = [ + {file = "pyasn1-modules-0.2.8.tar.gz", hash = "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e"}, + {file = "pyasn1_modules-0.2.8-py2.4.egg", hash = "sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199"}, + {file = "pyasn1_modules-0.2.8-py2.5.egg", hash = "sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405"}, + {file = "pyasn1_modules-0.2.8-py2.6.egg", hash = "sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb"}, + {file = "pyasn1_modules-0.2.8-py2.7.egg", hash = "sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8"}, + {file = "pyasn1_modules-0.2.8-py2.py3-none-any.whl", hash = "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74"}, + {file = "pyasn1_modules-0.2.8-py3.1.egg", hash = "sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d"}, + {file = "pyasn1_modules-0.2.8-py3.2.egg", hash = "sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45"}, + {file = "pyasn1_modules-0.2.8-py3.3.egg", hash = "sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4"}, + {file = "pyasn1_modules-0.2.8-py3.4.egg", hash = "sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811"}, + {file = "pyasn1_modules-0.2.8-py3.5.egg", hash = "sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed"}, + {file = "pyasn1_modules-0.2.8-py3.6.egg", hash = "sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0"}, + {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"}, +] +python-magic-bin = [ + {file = "python_magic_bin-0.4.14-py2.py3-none-macosx_10_6_intel.whl", hash = "sha256:7b1743b3dbf16601d6eedf4e7c2c9a637901b0faaf24ad4df4d4527e7d8f66a4"}, + {file = "python_magic_bin-0.4.14-py2.py3-none-win32.whl", hash = "sha256:34a788c03adde7608028203e2dbb208f1f62225ad91518787ae26d603ae68892"}, + {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"}, +] +requests = [ + {file = "requests-2.23.0-py2.py3-none-any.whl", hash = "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee"}, + {file = "requests-2.23.0.tar.gz", hash = "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"}, +] +requests-oauthlib = [ + {file = "requests-oauthlib-0.8.0.tar.gz", hash = "sha256:883ac416757eada6d3d07054ec7092ac21c7f35cb1d2cf82faf205637081f468"}, + {file = "requests_oauthlib-0.8.0-py2.py3-none-any.whl", hash = "sha256:50a8ae2ce8273e384895972b56193c7409601a66d4975774c60c2aed869639ca"}, +] +requests-toolbelt = [ + {file = "requests-toolbelt-0.9.1.tar.gz", hash = "sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0"}, + {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"}, +] +schema = [ + {file = "schema-0.6.8-py2.py3-none-any.whl", hash = "sha256:d994b0dc4966000037b26898df638e3e2a694cc73636cb2050e652614a350687"}, + {file = "schema-0.6.8.tar.gz", hash = "sha256:fa1a53fe5f3b6929725a4e81688c250f46838e25d8c1885a10a590c8c01a7b74"}, +] +six = [ + {file = "six-1.14.0-py2.py3-none-any.whl", hash = "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"}, + {file = "six-1.14.0.tar.gz", hash = "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a"}, +] +tzlocal = [ + {file = "tzlocal-1.5.1.tar.gz", hash = "sha256:4ebeb848845ac898da6519b9b31879cf13b6626f7184c496037b818e238f2c4e"}, +] +unidecode = [ + {file = "Unidecode-1.1.1-py2.py3-none-any.whl", hash = "sha256:1d7a042116536098d05d599ef2b8616759f02985c85b4fef50c78a5aaf10822a"}, + {file = "Unidecode-1.1.1.tar.gz", hash = "sha256:2b6aab710c2a1647e928e36d69c21e76b453cd455f4e2621000e54b2a9b8cce8"}, +] +uritemplate = [ + {file = "uritemplate-3.0.1-py2.py3-none-any.whl", hash = "sha256:07620c3f3f8eed1f12600845892b0e036a2420acf513c53f7de0abd911a5894f"}, + {file = "uritemplate-3.0.1.tar.gz", hash = "sha256:5af8ad10cec94f215e3f48112de2022e1d5a37ed427fbd88652fa908f2ab7cae"}, +] +urllib3 = [ + {file = "urllib3-1.22-py2.py3-none-any.whl", hash = "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b"}, + {file = "urllib3-1.22.tar.gz", hash = "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f"}, +] diff --git a/prismedia/__init__.py b/prismedia/__init__.py new file mode 100644 index 0000000..7ec26e8 --- /dev/null +++ b/prismedia/__init__.py @@ -0,0 +1,5 @@ +from future import standard_library +standard_library.install_aliases() + +from . import upload +from . import genconfig diff --git a/prismedia/__main__.py b/prismedia/__main__.py new file mode 100644 index 0000000..858cea7 --- /dev/null +++ b/prismedia/__main__.py @@ -0,0 +1,2 @@ +from .upload import main +main() diff --git a/prismedia/genconfig.py b/prismedia/genconfig.py new file mode 100644 index 0000000..f03e423 --- /dev/null +++ b/prismedia/genconfig.py @@ -0,0 +1,15 @@ +from os.path import join, abspath, isfile, dirname +from os import listdir +from shutil import copyfile + + +def genconfig(): + path = join(dirname(__file__), 'config') + files = [f for f in listdir(path) if isfile(join(path, f))] + + for f in files: + copyfile(join(path, f), f) + + +if __name__ == '__main__': + genconfig() diff --git a/prismedia/pt_upload.py b/prismedia/pt_upload.py index ee5f78c..8e1aa1f 100644 --- a/prismedia/pt_upload.py +++ b/prismedia/pt_upload.py @@ -15,7 +15,7 @@ from requests_oauthlib import OAuth2Session from oauthlib.oauth2 import LegacyApplicationClient from requests_toolbelt.multipart.encoder import MultipartEncoder -import utils +from . import utils PEERTUBE_SECRETS_FILE = 'peertube_secret' PEERTUBE_PRIVACY = { diff --git a/prismedia/upload.py b/prismedia/upload.py index d36b3ed..42ec297 100755 --- a/prismedia/upload.py +++ b/prismedia/upload.py @@ -69,20 +69,15 @@ import sys if sys.version_info[0] < 3: raise Exception("Python 3 or a more recent version is required.") -from os.path import dirname, realpath import datetime -import locale import logging logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO) from docopt import docopt -# Allows a relative import from the parent folder -sys.path.insert(0, dirname(realpath(__file__)) + "/lib") - -import yt_upload -import pt_upload -import utils +from . import yt_upload +from . import pt_upload +from . import utils try: # noinspection PyUnresolvedReferences @@ -101,7 +96,7 @@ except ImportError: 'see https://github.com/ahupp/python-magic\n') exit(1) -VERSION = "prismedia v0.8.0" +VERSION = "prismedia v0.9.0" VALID_PRIVACY_STATUSES = ('public', 'private', 'unlisted') VALID_CATEGORIES = ( @@ -117,6 +112,7 @@ VALID_LANGUAGES = ('arabic', 'english', 'french', 'japanese', 'korean', 'mandarin', 'portuguese', 'punjabi', 'russian', 'spanish') + def validateVideo(path): supported_types = ['video/mp4'] if magic.from_file(path, mime=True) in supported_types: @@ -124,18 +120,21 @@ def validateVideo(path): else: return False + def validateCategory(category): if category.lower() in VALID_CATEGORIES: return True else: return False + def validatePrivacy(privacy): if privacy.lower() in VALID_PRIVACY_STATUSES: return True else: return False + def validatePlatform(platform): for plfrm in platform.split(','): if plfrm.lower().replace(" ", "") not in VALID_PLATFORM: @@ -143,12 +142,14 @@ def validatePlatform(platform): return True + def validateLanguage(language): if language.lower() in VALID_LANGUAGES: return True else: return False + def validatePublish(publish): # Check date format and if date is future try: @@ -160,6 +161,7 @@ def validatePublish(publish): return False return True + def validateThumbnail(thumbnail): supported_types = ['image/jpg', 'image/jpeg'] if magic.from_file(thumbnail, mime=True) in supported_types: @@ -167,8 +169,8 @@ def validateThumbnail(thumbnail): else: return False -if __name__ == '__main__': +def main(): options = docopt(__doc__, version=VERSION) schema = Schema({ @@ -253,3 +255,9 @@ if __name__ == '__main__': pt_upload.run(options) if options.get('--platform') is None or "youtube" in options.get('--platform'): yt_upload.run(options) + + +if __name__ == '__main__': + import warnings + warnings.warn("use 'python -m prismedia', not 'python -m prismedia.upload'", DeprecationWarning) + main() diff --git a/prismedia/yt_upload.py b/prismedia/yt_upload.py index 5c10b2f..da21ccc 100644 --- a/prismedia/yt_upload.py +++ b/prismedia/yt_upload.py @@ -22,7 +22,7 @@ from googleapiclient.http import MediaFileUpload from google_auth_oauthlib.flow import InstalledAppFlow -import utils +from . import utils logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..893fdf1 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,49 @@ +[tool.poetry] +name = "prismedia" +version = "0.9.0" +description = "scripting your way to upload videos on peertube and youtube" +authors = [ + "LecygneNoir ", + "Rigel Kent ", + "Zykino" +] + +license = "AGPL-3.0-only" + +readme = 'README.md' +repository = "https://git.lecygnenoir.info/LecygneNoir/prismedia" +homepage = "https://git.lecygnenoir.info/LecygneNoir/prismedia" + +keywords = ['peertube', 'youtube', 'prismedia'] + +[tool.poetry.dependencies] +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" +httplib2 = "^0.12.1" +oauthlib = "^2.1.0" +python-magic = { version = "^0.4.15", markers = "platform_system == 'Linux'" } +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" +tzlocal = "^1.5.1" +Unidecode = "^1.0.23" +uritemplate = "^3.0.0" +urllib3 = "^1.22" + + +[tool.poetry.dev-dependencies] + +[tool.poetry.scripts] +prismedia = 'prismedia.upload:main' +[build-system] +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" + diff --git a/requirements.txt b/requirements.txt index 6fa06a7..9ebf51f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,19 +1,129 @@ -configparser -docopt -future -google-api-python-client -google-auth -google-auth-httplib2 -google-auth-oauthlib -httplib2 -oauthlib -python-magic -python-magic-bin; platform_system == "Windows" -requests -requests-oauthlib -requests-toolbelt -schema -tzlocal -Unidecode -uritemplate -urllib3 +cachetools==3.1.1 \ + --hash=sha256:428266a1c0d36dc5aca63a2d7c5942e88c2c898d72139fca0e97fdd2380517ae \ + --hash=sha256:8ea2d3ce97850f31e4a08b0e2b5e6c34997d7216a9d2c98e0f3978630d4da69a +certifi==2019.11.28 \ + --hash=sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3 \ + --hash=sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f +chardet==3.0.4 \ + --hash=sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691 \ + --hash=sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae +configparser==3.8.1 \ + --hash=sha256:45d1272aad6cfd7a8a06cf5c73f2ceb6a190f6acc1fa707e7f82a4c053b28b18 \ + --hash=sha256:bc37850f0cc42a1725a796ef7d92690651bf1af37d744cc63161dac62cabee17 +docopt==0.6.2 \ + --hash=sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491 +future==0.17.1 \ + --hash=sha256:67045236dcfd6816dc439556d009594abf643e5eb48992e36beac09c2ca659b8 +google-api-core==1.16.0 \ + --hash=sha256:92e962a087f1c4b8d1c5c88ade1c1dfd550047dcffb320c57ef6a534a20403e2 \ + --hash=sha256:859f7392676761f2b160c6ee030c3422135ada4458f0948c5690a6a7c8d86294 +google-api-python-client==1.8.0 \ + --hash=sha256:0f5b42a14e2d2f7dee40f2e4514531dbe95ebde9c2173b1c4040a65c427e7900 \ + --hash=sha256:5032ad1af5046889649b3848f2e871889fbb6ae440198a549fe1699581300386 +google-auth==1.12.0 \ + --hash=sha256:016924388770b7e66c7e9ade1c4c3144ee88812d79697fd6c0dad9abdfcda2fd \ + --hash=sha256:01d686448f57d3bc027726474faa1aa650ba333bedb392e06938b0add8ec8d3a +google-auth-httplib2==0.0.3 \ + --hash=sha256:098fade613c25b4527b2c08fa42d11f3c2037dda8995d86de0745228e965d445 \ + --hash=sha256:f1c437842155680cf9918df9bc51c1182fda41feef88c34004bd1978c8157e08 +google-auth-oauthlib==0.2.0 \ + --hash=sha256:226d1d0960f86ba5d9efd426a70b291eaba96f47d071657e0254ea969025728a \ + --hash=sha256:81ba22acada4d13b1d83f9371ab19fd61f1250a542d21cf49e4dcf0637a7344a +googleapis-common-protos==1.51.0 \ + --hash=sha256:013c91704279119150e44ef770086fdbba158c1f978a6402167d47d5409e226e +httplib2==0.12.3 \ + --hash=sha256:23914b5487dfe8ef09db6656d6d63afb0cf3054ad9ebc50868ddc8e166b5f8e8 \ + --hash=sha256:a18121c7c72a56689efbf1aef990139ad940fee1e64c6f2458831736cd593600 +idna==2.9 \ + --hash=sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa \ + --hash=sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb +oauthlib==2.1.0 \ + --hash=sha256:d883b36b21a6ad813953803edfa563b1b579d79ca758fe950d1bc9e8b326025b \ + --hash=sha256:ac35665a61c1685c56336bda97d5eefa246f1202618a1d6f34fccb1bdd404162 +protobuf==3.11.3 \ + --hash=sha256:ef2c2e56aaf9ee914d3dccc3408d42661aaf7d9bb78eaa8f17b2e6282f214481 \ + --hash=sha256:dd9aa4401c36785ea1b6fff0552c674bdd1b641319cb07ed1fe2392388e9b0d7 \ + --hash=sha256:310a7aca6e7f257510d0c750364774034272538d51796ca31d42c3925d12a52a \ + --hash=sha256:e512b7f3a4dd780f59f1bf22c302740e27b10b5c97e858a6061772668cd6f961 \ + --hash=sha256:fdfb6ad138dbbf92b5dbea3576d7c8ba7463173f7d2cb0ca1bd336ec88ddbd80 \ + --hash=sha256:e2f8a75261c26b2f5f3442b0525d50fd79a71aeca04b5ec270fc123536188306 \ + --hash=sha256:c40973a0aee65422d8cb4e7d7cbded95dfeee0199caab54d5ab25b63bce8135a \ + --hash=sha256:adf0e4d57b33881d0c63bb11e7f9038f98ee0c3e334c221f0858f826e8fb0151 \ + --hash=sha256:0bae429443cc4748be2aadfdaf9633297cfaeb24a9a02d0ab15849175ce90fab \ + --hash=sha256:e11df1ac6905e81b815ab6fd518e79be0a58b5dc427a2cf7208980f30694b956 \ + --hash=sha256:7774bbbaac81d3ba86de646c39f154afc8156717972bf0450c9dbfa1dc8dbea2 \ + --hash=sha256:8eb9c93798b904f141d9de36a0ba9f9b73cc382869e67c9e642c0aba53b0fc07 \ + --hash=sha256:fac513a9dc2a74b99abd2e17109b53945e364649ca03d9f7a0b96aa8d1807d0a \ + --hash=sha256:82d7ac987715d8d1eb4068bf997f3053468e0ce0287e2729c30601feb6602fee \ + --hash=sha256:73152776dc75f335c476d11d52ec6f0f6925774802cd48d6189f4d5d7fe753f4 \ + --hash=sha256:52e586072612c1eec18e1174f8e3bb19d08f075fc2e3f91d3b16c919078469d0 \ + --hash=sha256:2affcaba328c4662f3bc3c0e9576ea107906b2c2b6422344cdad961734ff6b93 \ + --hash=sha256:24e3b6ad259544d717902777b33966a1a069208c885576254c112663e6a5bb0f \ + --hash=sha256:c77c974d1dadf246d789f6dad1c24426137c9091e930dbf50e0a29c1fcf00b1f +pyasn1==0.4.8 \ + --hash=sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3 \ + --hash=sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf \ + --hash=sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00 \ + --hash=sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8 \ + --hash=sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d \ + --hash=sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86 \ + --hash=sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7 \ + --hash=sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576 \ + --hash=sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12 \ + --hash=sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2 \ + --hash=sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359 \ + --hash=sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776 \ + --hash=sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba +pyasn1-modules==0.2.8 \ + --hash=sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e \ + --hash=sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199 \ + --hash=sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405 \ + --hash=sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb \ + --hash=sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8 \ + --hash=sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74 \ + --hash=sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d \ + --hash=sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45 \ + --hash=sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4 \ + --hash=sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811 \ + --hash=sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed \ + --hash=sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0 \ + --hash=sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd +python-magic==0.4.15; platform_system == "Linux" \ + --hash=sha256:f3765c0f582d2dfc72c15f3b5a82aecfae9498bd29ca840d72f37d7bd38bfcd5 \ + --hash=sha256:f2674dcfad52ae6c49d4803fa027809540b130db1dec928cfbb9240316831375 +python-magic-bin==0.4.14; platform_system == "Windows" \ + --hash=sha256:7b1743b3dbf16601d6eedf4e7c2c9a637901b0faaf24ad4df4d4527e7d8f66a4 \ + --hash=sha256:34a788c03adde7608028203e2dbb208f1f62225ad91518787ae26d603ae68892 \ + --hash=sha256:90be6206ad31071a36065a2fc169c5afb5e0355cbe6030e87641c6c62edc2b69 +pytz==2019.3 \ + --hash=sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d \ + --hash=sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be +requests==2.23.0 \ + --hash=sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee \ + --hash=sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6 +requests-oauthlib==0.8.0 \ + --hash=sha256:883ac416757eada6d3d07054ec7092ac21c7f35cb1d2cf82faf205637081f468 \ + --hash=sha256:50a8ae2ce8273e384895972b56193c7409601a66d4975774c60c2aed869639ca +requests-toolbelt==0.9.1 \ + --hash=sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0 \ + --hash=sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f +rsa==4.0 \ + --hash=sha256:14ba45700ff1ec9eeb206a2ce76b32814958a98e372006c8fb76ba820211be66 \ + --hash=sha256:1a836406405730121ae9823e19c6e806c62bbad73f890574fff50efa4122c487 +schema==0.6.8 \ + --hash=sha256:d994b0dc4966000037b26898df638e3e2a694cc73636cb2050e652614a350687 \ + --hash=sha256:fa1a53fe5f3b6929725a4e81688c250f46838e25d8c1885a10a590c8c01a7b74 +six==1.14.0 \ + --hash=sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c \ + --hash=sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a +tzlocal==1.5.1 \ + --hash=sha256:4ebeb848845ac898da6519b9b31879cf13b6626f7184c496037b818e238f2c4e +unidecode==1.1.1 \ + --hash=sha256:1d7a042116536098d05d599ef2b8616759f02985c85b4fef50c78a5aaf10822a \ + --hash=sha256:2b6aab710c2a1647e928e36d69c21e76b453cd455f4e2621000e54b2a9b8cce8 +uritemplate==3.0.1 \ + --hash=sha256:07620c3f3f8eed1f12600845892b0e036a2420acf513c53f7de0abd911a5894f \ + --hash=sha256:5af8ad10cec94f215e3f48112de2022e1d5a37ed427fbd88652fa908f2ab7cae +urllib3==1.22 \ + --hash=sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b \ + --hash=sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f From 8faae852ea815f60a84a5b30c6652a44d837d543 Mon Sep 17 00:00:00 2001 From: LecygneNoir Date: Wed, 1 Apr 2020 11:38:08 +0200 Subject: [PATCH 04/14] Add documentation for poetry and adjust Changelog --- CHANGELOG.md | 3 +- README.md | 70 ++++++++++++++++++++++++--------------------- prismedia/upload.py | 10 +++---- 3 files changed, 45 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7bb84c..dc9645f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,9 @@ # Changelog -## v0.8.1 +## v0.9.0 ### Features + - Prismedia now uses [poetry](https://python-poetry.org) to allow easier installation usage and build, see the README - Add two new options to schedule video by platform. You may now use youtubeAt and peertubeAt to prepare previews ## v0.8.0 diff --git a/README.md b/README.md index 04aaa49..6b9e915 100644 --- a/README.md +++ b/README.md @@ -2,35 +2,41 @@ Scripting your way to upload videos to peertube and youtube. Works with Python 3.5+. -## Dependencies -Search in your package manager, or with `pip` use ``pip install -r requirements.txt`` - - configparser - - docopt - - future - - google-api-python-client - - google-auth - - google-auth-httplib2 - - google-auth-oauthlib - - httplib2 - - oauthlib - - python-magic - - python-magic-bin (Windows only) - - requests - - requests-oauthlib - - requests-toolbelt - - schema - - tzlocal - - Unidecode - - uritemplate - - urllib3 +[TOC]: # + +## Table of Contents +- [Installation](#installation) +- [Configuration](#configuration) + - [Peertube](#peertube) + - [Youtube](#youtube) +- [Usage](#usage) +- [Features](#features) +- [Compatibility](#compatibility) +- [Sources](#sources) +- [Contributors](#contributors) + +## Installation + +You may use pip to install requirements: `pip install -r requirements.txt` +(*note:* requirements are generated via `poetry export -f requirements.txt`) + +Otherwise, you can use [poetry](https://python-poetry.org): + +``` +poetry install # installs the dependency in the current virtualenv, +or creates one specific to the project if no virtualenv is currently active +``` + ## Configuration -Edit peertube_secret and youtube_secret.json with your credentials. +Generate sample files with `python -m prismedia.genconfig`. +Then edit `peertube_secret` and `youtube_secret.json` with your credentials. ### Peertube Set your credentials, peertube server URL. -You can get client_id and client_secret by logging in your peertube website and reaching the URL: https://domain.example/api/v1/oauth-clients/local +You can get client_id and client_secret by logging in your peertube website and reaching the URL: +https://domain.example/api/v1/oauth-clients/local You can set ``OAUTHLIB_INSECURE_TRANSPORT`` to 1 if you do not use https (not recommended) ### Youtube @@ -56,33 +62,32 @@ If you plan an larger usage, please consider creating your own youtube_secret fi - Download JSON: Under the section "OAuth 2.0 client IDs". Save the file to your local system. - Save this JSON as your youtube_secret.json file. -## How To +## Usage Support only mp4 for cross compatibility between Youtube and Peertube -Simply upload a video: +Upload a video: ``` -./prismedia_upload.py --file="yourvideo.mp4" +python -m prismedia --file="yourvideo.mp4" ``` - Specify description and tags: ``` -./prismedia_upload.py --file="yourvideo.mp4" -d "My supa description" -t "tag1,tag2,foo" +python -m prismedia --file="yourvideo.mp4" -d "My supa description" -t "tag1,tag2,foo" ``` Provide a thumbnail: ``` -./prismedia_upload.py --file="yourvideo.mp4" -d "Video with thumbnail" --thumbnail="/path/to/your/thumbnail.jpg" +python -m prismedia --file="yourvideo.mp4" -d "Video with thumbnail" --thumbnail="/path/to/your/thumbnail.jpg" ``` -Use a NFO file to specify your video options: - +Use a NFO file to specify your video options: +(See nfo_example.txt for more precise example) ``` -./prismedia_upload.py --file="yourvideo.mp4" --nfo /path/to/your/nfo.txt +python -m prismedia --file="yourvideo.mp4" --nfo /path/to/your/nfo.txt ``` @@ -166,6 +171,7 @@ Languages: - [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] Usable on Desktop (Linux and/or Windows and/or MacOS) +- [x] Different schedules on platforms to prepare preview ## Compatibility diff --git a/prismedia/upload.py b/prismedia/upload.py index 42ec297..0a1ba9c 100755 --- a/prismedia/upload.py +++ b/prismedia/upload.py @@ -2,13 +2,13 @@ # coding: utf-8 """ -prismedia_upload - tool to upload videos to Peertube and Youtube +prismedia - tool to upload videos to Peertube and Youtube Usage: - prismedia_upload.py --file= [options] - prismedia_upload.py -f --tags=STRING [options] - prismedia_upload.py -h | --help - prismedia_upload.py --version + prismedia --file= [options] + prismedia -f --tags=STRING [options] + prismedia -h | --help + prismedia --version Options: -f, --file=STRING Path to the video file to upload in mp4 From af65627fcfe78001228b321abe8c5cdfdfa25d32 Mon Sep 17 00:00:00 2001 From: LecygneNoir Date: Fri, 3 Apr 2020 10:30:29 +0200 Subject: [PATCH 05/14] Fix some typo regarding poetry --- CHANGELOG.md | 4 ++++ README.md | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc9645f..36e16c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## v0.9.0 +## Breaking changes +Now using poetry for packaging and installing! It's now easier to maintain and publish package, but means changes to use prismedia. +Prismedia is now seen as a python module, so you may now use `python -m prismedia` (or even directly `prismedia` if you install with poetry) instead of `./prismedia_upload.py`. + ### Features - Prismedia now uses [poetry](https://python-poetry.org) to allow easier installation usage and build, see the README - Add two new options to schedule video by platform. You may now use youtubeAt and peertubeAt to prepare previews diff --git a/README.md b/README.md index 6b9e915..5be531c 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ or creates one specific to the project if no virtualenv is currently active ## Configuration Generate sample files with `python -m prismedia.genconfig`. -Then edit `peertube_secret` and `youtube_secret.json` with your credentials. +Then edit `peertube_secret` and `youtube_secret.json` with your credentials. (see below) ### Peertube Set your credentials, peertube server URL. @@ -162,7 +162,7 @@ Languages: - [x] enabling/disabling comment (Peertube only as Youtube API does not support it) - [x] nsfw (Peertube only as Youtube API does not support it) - [x] set default language - - [x] thumbnail/preview + - [x] thumbnail - [x] multiple lines description (see [issue 4](https://git.lecygnenoir.info/LecygneNoir/prismedia/issues/4)) - [x] add videos to playlist - [x] create playlist From e91ada951f1e45ac8eef3f7b0796b39e904b26e9 Mon Sep 17 00:00:00 2001 From: LecygneNoir Date: Fri, 3 Apr 2020 12:11:58 +0200 Subject: [PATCH 06/14] gitignore .mp4 to avoid commiting test files --- .gitignore | 3 ++- prismedia/config/nfo_example.txt | 30 ------------------------------ 2 files changed, 2 insertions(+), 31 deletions(-) delete mode 100644 prismedia/config/nfo_example.txt diff --git a/.gitignore b/.gitignore index 38e944a..16f1030 100644 --- a/.gitignore +++ b/.gitignore @@ -64,4 +64,5 @@ peertube_secret .youtube_credentials.json nfo_example.txt peertube_secret.sample -youtube_secret.json.sample \ No newline at end of file +youtube_secret.json.sample +*.mp4 \ No newline at end of file diff --git a/prismedia/config/nfo_example.txt b/prismedia/config/nfo_example.txt deleted file mode 100644 index a6c537d..0000000 --- a/prismedia/config/nfo_example.txt +++ /dev/null @@ -1,30 +0,0 @@ -### This NFO example show how to construct a NFO for your video ### -### All fields are optional, but you need at least one fields (otherwise NFO is useless :-p) ### -### See --help for options explanation -### Prismedia will search and use NFO in this order: ### -### 1. file passed in command line through --nfo ### -### 2. file inside video directory named after --name command line option append with .txt ### -### 3. file inside video directory named after --file command line option with .txt extension ### -[video] -name = videoname -description = Your complete video description - Multilines description - should be wrote with a blank space - at the beginning of the line :) -tags = list of tags, comma separated -category = Films -cca = True -privacy = private -disable-comments = True -#thumbnail = /path/to/your/thumbnail.jpg # Set the absolute path to your thumbnail -channel = CookingTest -channelCreate = True -playlist = Desserts Recipes playlist -playlistCreate = True -nsfw = False -platform = youtube, peertube -language = French -publishAt=2034-05-07T19:00:00 -# platformAt overrides the default publishAt for the corresponding platform -#peertubeAt = 2034-05-14T19:00:00 -#youtubeAt = 2034-05-21T19:00:00 \ No newline at end of file From 17017ae90c9da0300edb5e4ab485c71ddcbf8e75 Mon Sep 17 00:00:00 2001 From: LecygneNoir Date: Fri, 3 Apr 2020 12:24:23 +0200 Subject: [PATCH 07/14] Modify the NFO functions to allow an enhanced use with priorities in options --- prismedia/utils.py | 118 +++++++++++++++++++++++---------------------- 1 file changed, 61 insertions(+), 57 deletions(-) diff --git a/prismedia/utils.py b/prismedia/utils.py index fca5f51..2409e3f 100644 --- a/prismedia/utils.py +++ b/prismedia/utils.py @@ -107,6 +107,7 @@ def remove_empty_kwargs(**kwargs): good_kwargs[key] = value return good_kwargs + def searchThumbnail(options): video_directory = dirname(options.get('--file')) + "/" # First, check for thumbnail based on videoname @@ -124,73 +125,76 @@ def searchThumbnail(options): options['--thumbnail'] = video_directory + video_file + ".jpeg" return options + # return the nfo as a RawConfigParser object -def loadNFO(options): - video_directory = dirname(options.get('--file')) + "/" - if options.get('--nfo'): - try: - logging.info("Using " + options.get('--nfo') + " as NFO, loading...") - if isfile(options.get('--nfo')): - nfo = RawConfigParser() - nfo.read(options.get('--nfo'), encoding='utf-8') - return nfo - else: - logging.error("Given NFO file does not exist, please check your path.") - exit(1) - except Exception as e: - logging.error("Problem with NFO file: " + str(e)) - exit(1) - else: - if options.get('--name'): - nfo_file = video_directory + options.get('--name') + ".txt" - if isfile(nfo_file): - try: - logging.info("Using " + nfo_file + " as NFO, loading...") - nfo = RawConfigParser() - nfo.read(nfo_file, encoding='utf-8') - return nfo - except Exception as e: - logging.error("Problem with NFO file: " + str(e)) - exit(1) +def loadNFO(filename): + try: + logging.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)) + exit(1) + return False + + +def parseNFO(options): + video_directory = dirname(options.get('--file')) + directory_name = basename(video_directory) + nfo_txt = False + nfo_directory = False + nfo_videoname = False + nfo_file = False + nfo_cli = False + + if isfile(video_directory + "/" + "nfo.txt"): + nfo_txt = loadNFO(video_directory + "/" + "nfo.txt") + + if isfile(video_directory + "/" + directory_name+ ".txt"): + nfo_directory = loadNFO(video_directory + "/" + directory_name+ ".txt") + + if options.get('--name'): + if isfile(video_directory + "/" + options.get('--name')): + nfo_videoname = loadNFO(video_directory + "/" + options.get('--name') + ".txt") - # if --nfo and --name does not exist, use --file as default video_file = splitext(basename(options.get('--file')))[0] - nfo_file = video_directory + video_file + ".txt" - if isfile(nfo_file): - try: - logging.info("Using " + nfo_file + " as NFO, loading...") - nfo = RawConfigParser() - nfo.read(nfo_file, encoding='utf-8') - return nfo - except Exception as e: - logging.error("Problem with nfo file: " + str(e)) + if isfile(video_directory + "/" + video_file + ".txt"): + nfo_file = loadNFO(video_directory + "/" + video_file + ".txt") + + if options.get('--nfo'): + if isfile(options.get('--nfo')): + nfo_cli = loadNFO(options.get('--nfo')) + else: + logging.error("Given NFO file does not exist, please check your path.") exit(1) - logging.info("No suitable NFO found, skipping.") - return False -def parseNFO(options): - nfo = loadNFO(options) - if nfo: - # We need to check all options and replace it with the nfo value if not defined (None or False) - for key, value in options.items(): - key = key.replace("-", "") - try: - # get string options - if value is None and nfo.get('video', key): - options['--' + key] = nfo.get('video', key) - # get boolean options - elif value is False and nfo.getboolean('video', key): - options['--' + key] = nfo.getboolean('video', key) - except NoOptionError: - continue - except NoSectionError: - logging.error("Given NFO file miss section [video], please check syntax of your NFO.") - exit(1) + # We need to load NFO in this exact order to keep the priorities + # options in cli > nfo_cli > nfo_file > nfo_videoname > nfo_directory > nfo_txt + for nfo in [nfo_cli, nfo_file, nfo_videoname, nfo_directory, nfo_txt]: + if nfo: + # We need to check all options and replace it with the nfo value if not defined (None or False) + for key, value in options.items(): + key = key.replace("-", "") + try: + # get string options + if value is None and nfo.get('video', key): + options['--' + key] = nfo.get('video', key) + # get boolean options + elif value is False and nfo.getboolean('video', key): + options['--' + key] = nfo.getboolean('video', key) + except NoOptionError: + continue + except NoSectionError: + logging.error(nfo + " misses section [video], please check syntax of your NFO.") + exit(1) return options + def upcaseFirstLetter(s): return s[0].upper() + s[1:] + def cleanString(toclean): toclean = unidecode.unidecode(toclean) cleaned = re.sub('[^A-Za-z0-9]+', '', toclean) From ef5d6b843ab866ef4920e5f866105117af586f63 Mon Sep 17 00:00:00 2001 From: LecygneNoir Date: Fri, 3 Apr 2020 12:24:46 +0200 Subject: [PATCH 08/14] Add a full set of samples to understand better who NFO works now --- prismedia/samples/cli_nfo.txt | 12 ++++++++++++ prismedia/samples/full_nfo_examples.txt | 26 +++++++++++++++++++++++++ prismedia/samples/nfo.txt | 9 +++++++++ prismedia/samples/samples.txt | 14 +++++++++++++ prismedia/samples/yourvideo.txt | 14 +++++++++++++ 5 files changed, 75 insertions(+) create mode 100644 prismedia/samples/cli_nfo.txt create mode 100644 prismedia/samples/full_nfo_examples.txt create mode 100644 prismedia/samples/nfo.txt create mode 100644 prismedia/samples/samples.txt create mode 100644 prismedia/samples/yourvideo.txt diff --git a/prismedia/samples/cli_nfo.txt b/prismedia/samples/cli_nfo.txt new file mode 100644 index 0000000..880dd8f --- /dev/null +++ b/prismedia/samples/cli_nfo.txt @@ -0,0 +1,12 @@ +### This NFO is aimed to be passed to prismedia through the --nfo cli option ### +### eg: +### python -m prismedia --file=/path/to/yourvideo.mp4 --nfo=/path/to/cli_nfo.txt ### +### It's the more priority NFO, only erased by direct cli options ### +[video] +disable-comments = False +nsfw = True +# Publish on Peertube at a specific date +peertubeAt = 2034-05-14T19:00:00 +platform = peertube +# debug to display all loaded options +debug = True \ No newline at end of file diff --git a/prismedia/samples/full_nfo_examples.txt b/prismedia/samples/full_nfo_examples.txt new file mode 100644 index 0000000..0ee5410 --- /dev/null +++ b/prismedia/samples/full_nfo_examples.txt @@ -0,0 +1,26 @@ +### This NFO example show how to construct a NFO for your video ### +### All fields are optionals, but you need at least one field (otherwise NFO is useless :-p) ### +### See --help for options explanation +[video] +name = videoname +description = Your complete video description + Multilines description + should be wrote with a blank space + at the beginning of the line :-) +tags = list of tags, comma separated +category = Films +cca = True +privacy = private +disable-comments = True +#thumbnail = /path/to/your/thumbnail.jpg # Set the absolute path to your thumbnail +channel = CookingTest +channelCreate = True +playlist = Desserts Recipes playlist +playlistCreate = True +nsfw = False +platform = youtube, peertube +language = French +publishAt = 2034-05-07T19:00:00 +# platformAt overrides the default publishAt for the corresponding platform +#peertubeAt = 2034-05-14T19:00:00 +#youtubeAt = 2034-05-21T19:00:00 \ No newline at end of file diff --git a/prismedia/samples/nfo.txt b/prismedia/samples/nfo.txt new file mode 100644 index 0000000..7b18585 --- /dev/null +++ b/prismedia/samples/nfo.txt @@ -0,0 +1,9 @@ +### This NFO is named nfo.txt and is stored in the directory of your videos ### +### This is the less priority NFO, you may use it to set default generic options ### +[video] +# Some generic options for your videos +cca = True +privacy = private +disable-comments = True +channel = DefaultChannel +channelCreate = True \ No newline at end of file diff --git a/prismedia/samples/samples.txt b/prismedia/samples/samples.txt new file mode 100644 index 0000000..338905e --- /dev/null +++ b/prismedia/samples/samples.txt @@ -0,0 +1,14 @@ +### This NFO is named from the directory where your video are. ### +### While more specific than nfo.txt, it's less priority than other NFO ### +### You may use it for options specific to videos in this directory, but still globals ### +[video] +channel = MyMoreSpecificChannel +disable-comments = False +channelCreate = True +category = Films +playlist = Desserts Recipes playlist +playlistCreate = True +nsfw = False +platform = youtube, peertube +language = French +tags = list of tags, comma separated \ No newline at end of file diff --git a/prismedia/samples/yourvideo.txt b/prismedia/samples/yourvideo.txt new file mode 100644 index 0000000..269d751 --- /dev/null +++ b/prismedia/samples/yourvideo.txt @@ -0,0 +1,14 @@ +### This NFO is named from your video name (here let's say your video is named "yourvideo.mp4") ### +### It aims to give options specific to this videos ### +[video] +disable-comments = False +#thumbnail = /path/to/your/thumbnail.jpg # Set the absolute path to your thumbnail +name = videoname +description = Your complete video description + Multilines description + should be wrote with a blank space + at the beginning of the line :-) +publishAt = 2034-05-07T19:00:00 +# platformAt overrides the default publishAt for the corresponding platform +#peertubeAt = 2034-05-14T19:00:00 +#youtubeAt = 2034-05-21T19:00:00 \ No newline at end of file From 881a01f862f3ed53e6d12d80b1c000d1a206d5fe Mon Sep 17 00:00:00 2001 From: LecygneNoir Date: Fri, 3 Apr 2020 12:44:29 +0200 Subject: [PATCH 09/14] Write documentation about the new NFO usage and possibilities --- CHANGELOG.md | 9 +++++---- README.md | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36e16c0..aeb8b6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,12 +3,13 @@ ## v0.9.0 ## Breaking changes -Now using poetry for packaging and installing! It's now easier to maintain and publish package, but means changes to use prismedia. -Prismedia is now seen as a python module, so you may now use `python -m prismedia` (or even directly `prismedia` if you install with poetry) instead of `./prismedia_upload.py`. +Now using poetry for packaging and installing! It's easier to maintain and publish package, but means changes when using prismedia from command line. +Prismedia is now seen as a python module, so you need to use `python -m prismedia` (or even directly `prismedia` if you install with poetry) instead of `./prismedia_upload.py`. ### Features - - Prismedia now uses [poetry](https://python-poetry.org) to allow easier installation usage and build, see the README - - Add two new options to schedule video by platform. You may now use youtubeAt and peertubeAt to prepare previews + - Prismedia now uses [poetry](https://python-poetry.org) to allow easier installation usage and build, see the README (fix #34) + - Add two new options to schedule video by platform. You may now use youtubeAt and peertubeAt to prepare previews (fix #43) + - Enhance the NFO system to allow a hierarchical loading of multiple NFO, with priorities. See README and [prismedia/samples](prismedia/samples) for details (fix #11) ## v0.8.0 diff --git a/README.md b/README.md index 5be531c..17a006a 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Scripting your way to upload videos to peertube and youtube. Works with Python 3 - [Peertube](#peertube) - [Youtube](#youtube) - [Usage](#usage) +- [Enhanced use of NFO](#enhanced-use-of-nfo) - [Features](#features) - [Compatibility](#compatibility) - [Sources](#sources) @@ -149,6 +150,44 @@ Languages: Japanese, Korean, Mandarin, Portuguese, Punjabi, Russian, Spanish ``` +## Enhanced use of NFO +Since Prismedia v0.9.0, the NFO system has been improved to allow hierarchical loading. +First of all, if you already used nfo, either with `--nfo` or by using `videoname.txt`, nothing changes :-) + +But you are now able to use a more flexible NFO system, by using priorities. +You'll find a complete set of samples in the [prismedia/samples](prismedia/samples) directory. + +Let's take the following directory as an example: +``` +$ tree Recipes/ +Recipes/ +├── cli_nfo.txt +├── nfo.txt +├── samples.txt +├── yourvideo1.mp4 +├── yourvideo1.txt +├── yourvideo1.jpg +├── yourvideo2.mp4 +└── yourvideo2.txt +``` + +By using +``` +prismedia --file=/path/to/Recipes/yourvideo1.mp4 --nfo=/path/to/Recipes/cli_nfo.txt --cca +``` + +Prismedia will: +- look for options in `nfo.txt` +- look for options in `samples.txt` (from directory name) and erase any previous conflicting options +- look for options in `yourvideo1.txt` (from video name) and erase any previous conflicting options +- look for options in `cli_nfo.txt` (from the `--nfo` in command line) and erase any previous conflicting options +- 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 nfo.txt, then directory_name.txt, then videoname.txt, then cli_nfo.txt, and finally the option directly passed in cli. + +It allows to specify more easily default options for an entire set of video, directory, playlist and so on. + ## Features - [x] Youtube upload From 11a91af534e33ffc16ccf6dd81c4896b97a3b284 Mon Sep 17 00:00:00 2001 From: LecygneNoir Date: Sat, 4 Apr 2020 10:11:25 +0200 Subject: [PATCH 10/14] Add better description for Enhanced NFO based on @Zykino review --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 17a006a..eb317c9 100644 --- a/README.md +++ b/README.md @@ -152,12 +152,14 @@ Languages: ## Enhanced use of NFO Since Prismedia v0.9.0, the NFO system has been improved to allow hierarchical loading. -First of all, if you already used nfo, either with `--nfo` or by using `videoname.txt`, nothing changes :-) +First of all, **if you already used nfo**, either with `--nfo` or by using `videoname.txt`, nothing changes :-) -But you are now able to use a more flexible NFO system, by using priorities. -You'll find a complete set of samples in the [prismedia/samples](prismedia/samples) directory. +But you are now able to use a more flexible NFO system, by using priorities. This allow you to set some defaults to avoid recreating a full nfo for each video -Let's take the following directory as an example: +Basically, Prismedia will now load options in this order, using the last value found in case of conflict: +`nfo.txt < directory_name.txt < video_name.txt < command line NFO < command line argument` + +You'll find a complete set of samples in the [prismedia/samples](prismedia/samples) directory so let's take it as an example: ``` $ tree Recipes/ Recipes/ @@ -184,7 +186,7 @@ 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 nfo.txt, then directory_name.txt, then videoname.txt, then cli_nfo.txt, and finally the option directly passed in cli. +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 It allows to specify more easily default options for an entire set of video, directory, playlist and so on. From 03ae92d1afe58a894eb1ba7f3ea7aac902d15bc2 Mon Sep 17 00:00:00 2001 From: LecygneNoir Date: Sat, 4 Apr 2020 10:12:49 +0200 Subject: [PATCH 11/14] Load nfo.txt or NFO.txt regardless the letter case --- prismedia/utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/prismedia/utils.py b/prismedia/utils.py index 2409e3f..b9e4c89 100644 --- a/prismedia/utils.py +++ b/prismedia/utils.py @@ -150,6 +150,8 @@ def parseNFO(options): if isfile(video_directory + "/" + "nfo.txt"): nfo_txt = loadNFO(video_directory + "/" + "nfo.txt") + elif isfile(video_directory + "/" + "NFO.txt"): + nfo_txt = loadNFO(video_directory + "/" + "NFO.txt") if isfile(video_directory + "/" + directory_name+ ".txt"): nfo_directory = loadNFO(video_directory + "/" + directory_name+ ".txt") From 1169301f14c4bce01cd635c591d1237579084bc4 Mon Sep 17 00:00:00 2001 From: LecygneNoir Date: Tue, 7 Apr 2020 10:09:10 +0200 Subject: [PATCH 12/14] After test python-magic is required on Windows in addition to python-magic-bin, so remove the 'Linux only' marker --- poetry.lock | 1 - pyproject.toml | 2 +- requirements.txt | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 1f72b3a..ccd9b43 100644 --- a/poetry.lock +++ b/poetry.lock @@ -208,7 +208,6 @@ pyasn1 = ">=0.4.6,<0.5.0" [[package]] category = "main" description = "File type identification using libmagic" -marker = "platform_system == \"Linux\"" name = "python-magic" optional = false python-versions = "*" diff --git a/pyproject.toml b/pyproject.toml index 893fdf1..5e25d4f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ google-auth-httplib2 = "^0.0.3" google-auth-oauthlib = "^0.2.0" httplib2 = "^0.12.1" oauthlib = "^2.1.0" -python-magic = { version = "^0.4.15", markers = "platform_system == 'Linux'" } +python-magic = "^0.4.15" python-magic-bin = { version = "^0.4.14", markers = "platform_system == 'Windows'" } requests = "^2.18.4" requests-oauthlib = "^0.8.0" diff --git a/requirements.txt b/requirements.txt index 9ebf51f..3768210 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,7 +88,7 @@ pyasn1-modules==0.2.8 \ --hash=sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed \ --hash=sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0 \ --hash=sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd -python-magic==0.4.15; platform_system == "Linux" \ +python-magic==0.4.15 \ --hash=sha256:f3765c0f582d2dfc72c15f3b5a82aecfae9498bd29ca840d72f37d7bd38bfcd5 \ --hash=sha256:f2674dcfad52ae6c49d4803fa027809540b130db1dec928cfbb9240316831375 python-magic-bin==0.4.14; platform_system == "Windows" \ From 1b55340b34849501a232ba6040724dde04b0d374 Mon Sep 17 00:00:00 2001 From: LecygneNoir Date: Tue, 7 Apr 2020 10:39:44 +0200 Subject: [PATCH 13/14] Update poetry.lock to match new python-magic requirements --- poetry.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/poetry.lock b/poetry.lock index ccd9b43..6122597 100644 --- a/poetry.lock +++ b/poetry.lock @@ -12,7 +12,7 @@ description = "Python package for providing Mozilla's CA Bundle." name = "certifi" optional = false python-versions = "*" -version = "2019.11.28" +version = "2020.4.5.1" [[package]] category = "main" @@ -94,7 +94,7 @@ description = "Google Authentication Library" name = "google-auth" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" -version = "1.12.0" +version = "1.13.1" [package.dependencies] cachetools = ">=2.0.0,<5.0" @@ -341,7 +341,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 = "8a3265f5af3ae0327d975200022dd0da8b6a0d72d06a81447e379691daf8726f" +content-hash = "b3063876dbcd6443d0459a9ef376ccdba2a21adc2e7a49d75c9450904b40615f" python-versions = ">=3.5" [metadata.files] @@ -350,8 +350,8 @@ cachetools = [ {file = "cachetools-3.1.1.tar.gz", hash = "sha256:8ea2d3ce97850f31e4a08b0e2b5e6c34997d7216a9d2c98e0f3978630d4da69a"}, ] certifi = [ - {file = "certifi-2019.11.28-py2.py3-none-any.whl", hash = "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3"}, - {file = "certifi-2019.11.28.tar.gz", hash = "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"}, + {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"}, ] chardet = [ {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, @@ -376,8 +376,8 @@ google-api-python-client = [ {file = "google_api_python_client-1.8.0-py3-none-any.whl", hash = "sha256:5032ad1af5046889649b3848f2e871889fbb6ae440198a549fe1699581300386"}, ] google-auth = [ - {file = "google-auth-1.12.0.tar.gz", hash = "sha256:016924388770b7e66c7e9ade1c4c3144ee88812d79697fd6c0dad9abdfcda2fd"}, - {file = "google_auth-1.12.0-py2.py3-none-any.whl", hash = "sha256:01d686448f57d3bc027726474faa1aa650ba333bedb392e06938b0add8ec8d3a"}, + {file = "google-auth-1.13.1.tar.gz", hash = "sha256:a5ee4c40fef77ea756cf2f1c0adcf475ecb53af6700cf9c133354cdc9b267148"}, + {file = "google_auth-1.13.1-py2.py3-none-any.whl", hash = "sha256:cab6c707e6ee20e567e348168a5c69dc6480384f777a9e5159f4299ad177dcc0"}, ] google-auth-httplib2 = [ {file = "google-auth-httplib2-0.0.3.tar.gz", hash = "sha256:098fade613c25b4527b2c08fa42d11f3c2037dda8995d86de0745228e965d445"}, From 4e5c2e1245b1d7b4ac146a05436b902895c8956c Mon Sep 17 00:00:00 2001 From: LecygneNoir Date: Tue, 7 Apr 2020 10:40:11 +0200 Subject: [PATCH 14/14] Update Changelog for the v0.9.0 --- CHANGELOG.md | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aeb8b6d..f7dde81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,30 @@ ## v0.9.0 -## Breaking changes -Now using poetry for packaging and installing! It's easier to maintain and publish package, but means changes when using prismedia from command line. -Prismedia is now seen as a python module, so you need to use `python -m prismedia` (or even directly `prismedia` if you install with poetry) instead of `./prismedia_upload.py`. +### Upgrade from v0.8.0 +Now using [poetry](https://python-poetry.org/) for packaging and installing! It's easier to maintain and publish package, but means changes when using prismedia from command line. + +**Using poetry** (recommanded) + +- [install poetry](https://python-poetry.org/docs/#installation) +- git pull the repo +- install prismedia: +```bash +poetry install +``` +- use prismedia from the command line directly from your path: +```bash +prismedia -h +``` + +**From source** +Prismedia is now seen as a python module, so you need to use `python -m prismedia` instead of `./prismedia_upload.py`. +Once you have pulled the new v0.9.0, you may update by using: +``` +pip install -r requirements.txt +# Then use prismedia through python command line: +python -m prismedia -h +``` ### Features - Prismedia now uses [poetry](https://python-poetry.org) to allow easier installation usage and build, see the README (fix #34)