Browse Source

add compatibility with python 3

pull/34/head
Romain Kerguelen 5 years ago
parent
commit
b8e7727c0c
Signed by untrusted user: rigelk GPG Key ID: EA12971B0E438F36
12 changed files with 142 additions and 90 deletions
  1. +0
    -1
      .python-version
  2. +9
    -9
      README.md
  3. +47
    -28
      poetry.lock
  4. +3
    -0
      prismedia/__init__.py
  5. +2
    -0
      prismedia/__main__.py
  6. +2
    -2
      prismedia/config/nfo_example.txt
  7. +10
    -4
      prismedia/pt_upload.py
  8. +12
    -1
      prismedia/upload.py
  9. +16
    -10
      prismedia/utils.py
  10. +9
    -10
      prismedia/yt_upload.py
  11. +5
    -3
      pyproject.toml
  12. +27
    -22
      requirements.txt

+ 0
- 1
.python-version View File

@ -1 +0,0 @@
2.7.15

+ 9
- 9
README.md View File

@ -1,6 +1,6 @@
# Prismedia
Scripting your way to upload videos to peertube and youtube. Works only with Python 2 so far.
Scripting your way to upload videos to peertube and youtube. Works with Python 2.7 and 3.3+.
## Dependencies
@ -15,15 +15,15 @@ Search in your system package manager, otherwise use ``pip install --upgrade`` f
- python-magic-bin
- requests-toolbelt
- tzlocal
- configparser
- future
Otherwise, you can use the requirements file with `pip install -r requirements.txt`. (*note:* requirements are generated via `poetry export -f requirements.txt`)
Otherwise, you can use [pyenv](https://github.com/pyenv/pyenv) and [poetry](https://poetry.eustace.io/):
Otherwise, you can use [poetry](https://poetry.eustace.io/):
```
pyenv install # installs the python version specified in .python-version
pyenv shell # activates the python version for the session
poetry install # installs the dependency in a virtualenv specific to the project
poetry install # installs the dependency in the current virtualenv, or creates one specific to the project if no virtualenv is currently active
```
## Configuration
@ -72,26 +72,26 @@ Supports only mp4 for cross compatibility between Youtube and Peertube.
Simply upload a video:
```
python -m prismedia.upload --file="yourvideo.mp4"
python -m prismedia --file="yourvideo.mp4"
```
Specify description and tags:
```
python -m prismedia.upload --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:
```
python -m prismedia.upload --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:
```
python -m prismedia.upload --file="yourvideo.mp4" --nfo /path/to/your/nfo.txt
python -m prismedia --file="yourvideo.mp4" --nfo /path/to/your/nfo.txt
```
Use --help to get all available options:

+ 47
- 28
poetry.lock
File diff suppressed because it is too large
View File


+ 3
- 0
prismedia/__init__.py View File

@ -1,2 +1,5 @@
from future import standard_library
standard_library.install_aliases()
from . import upload
from . import genconfig

+ 2
- 0
prismedia/__main__.py View File

@ -0,0 +1,2 @@
from .upload import main
main()

+ 2
- 2
prismedia/config/nfo_example.txt View File

@ -9,7 +9,7 @@
name = videoname
description = Your complete video description
Multilines description
should be wrote with a blank space
should be written with a blank space
at the beginning of the line :)
tags = list of tags, comma separated
category = Films
@ -22,4 +22,4 @@ playlistCreate = True
nsfw = True
platform = youtube, peertube
language = French
publishAt=2034-05-07T19:00:00
publishAt=2034-05-07T19:00:00

+ 10
- 4
prismedia/pt_upload.py View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# coding: utf-8
import os
@ -10,12 +9,19 @@ import pytz
from os.path import splitext, basename, abspath
from tzlocal import get_localzone
from ConfigParser import RawConfigParser
from requests_oauthlib import OAuth2Session
from oauthlib.oauth2 import LegacyApplicationClient
from requests_toolbelt.multipart.encoder import MultipartEncoder
import utils
from . import utils
from six.moves import configparser
import six
if six.PY2:
ConfigParser = configparser.SafeConfigParser
else:
ConfigParser = configparser.ConfigParser
PEERTUBE_SECRETS_FILE = 'peertube_secret'
PEERTUBE_PRIVACY = {
@ -209,7 +215,7 @@ def upload_video(oauth, secret, options):
def run(options):
secret = RawConfigParser()
secret = ConfigParser()
try:
secret.read(PEERTUBE_SECRETS_FILE)
except Exception as e:

+ 12
- 1
prismedia/upload.py View File

@ -2,7 +2,7 @@
# 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=<FILE> [options]
@ -103,6 +103,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:
@ -110,18 +111,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:
@ -129,12 +133,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:
@ -146,6 +152,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:
@ -153,6 +160,7 @@ def validateThumbnail(thumbnail):
else:
return False
def main():
options = docopt(__doc__, version=VERSION)
@ -223,6 +231,9 @@ def main():
if options.get('--platform') is None or "peertube" in options.get('--platform'):
pt_upload.run(options)
if __name__ == '__main__':
import warnings
warnings.warn("use 'python -m prismedia', not 'python -m prismedia.upload'", DeprecationWarning)
main()

+ 16
- 10
prismedia/utils.py View File

@ -1,4 +1,3 @@
#!/usr/bin/python
# coding: utf-8
from ConfigParser import RawConfigParser, NoOptionError, NoSectionError
@ -8,6 +7,13 @@ from os import devnull
from subprocess import check_call, CalledProcessError, STDOUT
import unidecode
import logging
from six.moves import configparser
import six
if six.PY2:
ConfigParser = configparser.SafeConfigParser
else:
ConfigParser = configparser.ConfigParser
### CATEGORIES ###
YOUTUBE_CATEGORY = {
@ -102,7 +108,7 @@ def getLanguage(language, platform):
def remove_empty_kwargs(**kwargs):
good_kwargs = {}
if kwargs is not None:
for key, value in kwargs.iteritems():
for key, value in viewitems(kwargs):
if value:
good_kwargs[key] = value
return good_kwargs
@ -126,14 +132,14 @@ def searchThumbnail(options):
return options
# return the nfo as a RawConfigParser object
# return the nfo as a ConfigParser 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 = ConfigParser()
nfo.read(options.get('--nfo'))
return nfo
else:
@ -148,7 +154,7 @@ def loadNFO(options):
if isfile(nfo_file):
try:
logging.info("Using " + nfo_file + " as NFO, loading...")
nfo = RawConfigParser()
nfo = ConfigParser()
nfo.read(nfo_file)
return nfo
except Exception as e:
@ -161,7 +167,7 @@ def loadNFO(options):
if isfile(nfo_file):
try:
logging.info("Using " + nfo_file + " as NFO, loading...")
nfo = RawConfigParser()
nfo = ConfigParser()
nfo.read(nfo_file)
return nfo
except Exception as e:
@ -176,7 +182,7 @@ def parseNFO(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.iteritems():
for key, value in viewitems(options):
key = key.replace("-", "")
try:
# get string options
@ -185,10 +191,10 @@ def parseNFO(options):
# get boolean options
elif value is False and nfo.getboolean('video', key):
options['--' + key] = nfo.getboolean('video', key)
except NoOptionError:
except configparser.NoOptionError:
continue
except NoSectionError:
logging.error("Given NFO file miss section [video], please check syntax of your NFO.")
except configparser.NoSectionError:
logging.error("Given NFO file misses section [video], please check the syntax of your NFO.")
exit(1)
return options

+ 9
- 10
prismedia/yt_upload.py View File

@ -1,8 +1,7 @@
#!/usr/bin/env python2
# coding: utf-8
# From Youtube samples : https://raw.githubusercontent.com/youtube/api-samples/master/python/upload_video.py # noqa
import httplib
import http.client
import httplib2
import random
import time
@ -22,7 +21,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)
@ -38,13 +37,13 @@ MAX_RETRIES = 10
RETRIABLE_EXCEPTIONS = (
IOError,
httplib2.HttpLib2Error,
httplib.NotConnected,
httplib.IncompleteRead,
httplib.ImproperConnectionState,
httplib.CannotSendRequest,
httplib.CannotSendHeader,
httplib.ResponseNotReady,
httplib.BadStatusLine,
http.client.NotConnected,
http.client.IncompleteRead,
http.client.ImproperConnectionState,
http.client.CannotSendRequest,
http.client.CannotSendHeader,
http.client.ResponseNotReady,
http.client.BadStatusLine,
)
RETRIABLE_STATUS_CODES = [500, 502, 503, 504]

+ 5
- 3
pyproject.toml View File

@ -16,7 +16,7 @@ homepage = "https://git.lecygnenoir.info/LecygneNoir/prismedia"
keywords = ['peertube', 'youtube']
[tool.poetry.dependencies]
python = "^2.7"
python = "~2.7 || ^3.3"
google-auth-oauthlib = "^0.2.0"
requests-toolbelt = "^0.9.1"
docopt = "^0.6.2"
@ -26,12 +26,14 @@ tzlocal = "^1.5"
python-magic = "^0.4.15"
schema = "^0.6.8"
google-api-python-client = "^1.7"
configparser = "^3.7"
future = "^0.17.1"
[tool.poetry.dev-dependencies]
[tool.poetry.scripts]
prismedia = 'prismedia.upload:main'
[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"
[tool.poetry.scripts]
prismedia = 'prismedia.upload:main'

+ 27
- 22
requirements.txt View File

@ -7,14 +7,20 @@ certifi==2018.11.29 \
chardet==3.0.4 \
--hash=sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae \
--hash=sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691
configparser==3.7.1 \
--hash=sha256:5bd5fa2a491dc3cfe920a3f2a107510d65eceae10e9c6e547b90261a4710df32 \
--hash=sha256:c114ff90ee2e762db972fa205f02491b1f5cf3ff950decd8542c62970c9bedac \
--hash=sha256:df28e045fbff307a28795b18df6ac8662be3219435560ddb068c283afab1ea7a
docopt==0.6.2 \
--hash=sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491
google-api-python-client==1.7.8 \
--hash=sha256:06907006ed5ce831018f03af3852d739c0b2489cdacfda6971bcc2075c762858 \
--hash=sha256:937eabdc3940977f712fa648a096a5142766b6d0a0f58bc603e2ac0687397ef0
google-auth==1.6.2 \
--hash=sha256:b6081ba9946828d6417c15ecdc723fdb7c007cdd74e140747d3876a7440f0be5 \
--hash=sha256:e8d64e9bc8cb6f0fc5360c693f86dc9ee6964081ee702e3b5ddc937f99efc950
future==0.17.1 \
--hash=sha256:67045236dcfd6816dc439556d009594abf643e5eb48992e36beac09c2ca659b8
google-api-python-client==1.7.6 \
--hash=sha256:51dc9139aa06fd0b1339a22b6b1c9fe74cb891b3dd803e8c464c5a18a8de23dc \
--hash=sha256:bf98b066fb6e4e6da1f2f11d6cb0bb947de156aef8562a32b0692e7073d38593
google-auth==1.6.1 \
--hash=sha256:494e747bdc2cdeb0fa6ef85118de2ea1a563f160294cce05048c6ff563fda1bb \
--hash=sha256:b08a27888e9d1c17a891b3688aacc9c6f2019d7f6c5a2e73588e6bb9a2c0fa98
google-auth-httplib2==0.0.3 \
--hash=sha256:098fade613c25b4527b2c08fa42d11f3c2037dda8995d86de0745228e965d445 \
--hash=sha256:f1c437842155680cf9918df9bc51c1182fda41feef88c34004bd1978c8157e08
@ -23,12 +29,12 @@ google-auth-oauthlib==0.2.0 \
--hash=sha256:81ba22acada4d13b1d83f9371ab19fd61f1250a542d21cf49e4dcf0637a7344a
httplib2==0.12.1 \
--hash=sha256:4ba6b8fd77d0038769bf3c33c9a96a6f752bc4cdf739701fdcaf210121f399d4
idna==2.8 \
--hash=sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407 \
--hash=sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c
oauthlib==3.0.1 \
--hash=sha256:0ce32c5d989a1827e3f1148f98b9085ed2370fc939bf524c9c851d8714797298 \
--hash=sha256:3e1e14f6cde7e5475128d30e97edc3bfb4dc857cb884d8714ec161fdbb3b358e
idna==2.6 \
--hash=sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f \
--hash=sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4
oauthlib==2.1.0 \
--hash=sha256:ac35665a61c1685c56336bda97d5eefa246f1202618a1d6f34fccb1bdd404162 \
--hash=sha256:d883b36b21a6ad813953803edfa563b1b579d79ca758fe950d1bc9e8b326025b
pyasn1==0.4.5 \
--hash=sha256:061442c60842f6d11051d4fdae9bc197b64bd41573a12234a753a0cb80b4f30b \
--hash=sha256:0ee2449bf4c4e535823acc25624c45a8b454f328d59d3f3eeb82d3567100b9bd \
@ -63,13 +69,12 @@ python-magic==0.4.15 \
pytz==2018.9 \
--hash=sha256:32b0891edff07e28efe91284ed9c31e123d84bea3fd98e1f72be2508f43ef8d9 \
--hash=sha256:d5f05e487007e29e03409f9398d074e158d920d36eb82eaf66fb1136b0c5374c
requests==2.21.0 \
--hash=sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e \
--hash=sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b
requests-oauthlib==1.2.0 \
--hash=sha256:bd6533330e8748e94bf0b214775fed487d309b8b8fe823dc45641ebcd9a32f57 \
--hash=sha256:d3ed0c8f2e3bbc6b344fa63d6f933745ab394469da38db16bdddb461c7e25140 \
--hash=sha256:dd5a0499abfefd087c6dd96693cbd5bfd28aa009719a7f85ab3fabe3956ef19a
requests==2.18.4 \
--hash=sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b \
--hash=sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e
requests-oauthlib==0.8.0 \
--hash=sha256:50a8ae2ce8273e384895972b56193c7409601a66d4975774c60c2aed869639ca \
--hash=sha256:883ac416757eada6d3d07054ec7092ac21c7f35cb1d2cf82faf205637081f468
requests-toolbelt==0.9.1 \
--hash=sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f \
--hash=sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0
@ -88,6 +93,6 @@ uritemplate==3.0.0 \
--hash=sha256:01c69f4fe8ed503b2951bef85d996a9d22434d2431584b5b107b2981ff416fbd \
--hash=sha256:1b9c467a940ce9fb9f50df819e8ddd14696f89b9a8cc87ac77952ba416e0a8fd \
--hash=sha256:c02643cebe23fc8adb5e6becffe201185bf06c40bda5c0b4028a93f1527d011d
urllib3==1.24.1 \
--hash=sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39 \
--hash=sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22
urllib3==1.22 \
--hash=sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b \
--hash=sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f

Loading…
Cancel
Save