diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a95b0d..12e2a1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Features - Add the possibility to upload thumbnail + - Use the API instead of external binaries for publishAt (thanks @zykino) ## v0.5 diff --git a/README.md b/README.md index 8c2b3d9..14c8a7e 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,6 @@ Search in your package manager, otherwise use ``pip install --upgrade`` - requests-toolbelt - tzlocal -For Peertube and if you want to use the publishAt option, you also need some utilities on you local system - - [atd](https://linux.die.net/man/8/atd) daemon - - [curl](https://linux.die.net/man/1/curl) - - [jq](https://stedolan.github.io/jq/) - ## Configuration Edit peertube_secret and youtube_secret.json with your credentials. @@ -118,7 +113,6 @@ 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 - For Peertube, requires the "atd" and "curl utilities installed on the system --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 @@ -161,7 +155,7 @@ Languages: - [ ] add videos to playlist for Youtube - [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] Add publishAt option to plan your videos (need the [atd](https://linux.die.net/man/8/atd) daemon, [curl](https://linux.die.net/man/1/curl) and [jq](https://stedolan.github.io/jq/)) +- [x] Add publishAt option to plan your videos - [ ] Record and forget: put the video in a directory, and the script uploads it for you - [ ] Usable on Desktop (Linux and/or Windows and/or MacOS) - [ ] Graphical User Interface diff --git a/lib/pt_upload.py b/lib/pt_upload.py index 015bfe6..4b57614 100644 --- a/lib/pt_upload.py +++ b/lib/pt_upload.py @@ -5,7 +5,10 @@ import os import mimetypes import json import logging +import datetime +import pytz from os.path import splitext, basename, abspath +from tzlocal import get_localzone from ConfigParser import RawConfigParser from requests_oauthlib import OAuth2Session @@ -140,16 +143,27 @@ def upload_video(oauth, secret, options): # if no language, set default to 1 (English) fields.append(("language", "en")) - if options.get('--privacy'): - fields.append(("privacy", str(PEERTUBE_PRIVACY[options.get('--privacy').lower()]))) - else: - fields.append(("privacy", "3")) - if options.get('--disable-comments'): fields.append(("commentsEnabled", "0")) else: fields.append(("commentsEnabled", "1")) + privacy = None + if options.get('--privacy'): + privacy = options.get('--privacy').lower() + + if options.get('--publishAt'): + publishAt = options.get('--publishAt') + publishAt = datetime.datetime.strptime(publishAt, '%Y-%m-%dT%H:%M:%S') + tz = get_localzone() + tz = pytz.timezone(str(tz)) + publishAt = tz.localize(publishAt).isoformat() + fields.append(("scheduleUpdate[updateAt]", publishAt)) + fields.append(("scheduleUpdate[privacy]", str(PEERTUBE_PRIVACY["public"]))) + fields.append(("privacy", str(PEERTUBE_PRIVACY["private"]))) + else: + fields.append(("privacy", str(PEERTUBE_PRIVACY[privacy or "private"]))) + if options.get('--thumbnail'): fields.append(("thumbnailfile", get_file(options.get('--thumbnail')))) fields.append(("previewfile", get_file(options.get('--thumbnail')))) @@ -182,8 +196,6 @@ def upload_video(oauth, secret, options): logging.info('Peertube : Video was successfully uploaded.') template = 'Peertube: Watch it at %s/videos/watch/%s.' logging.info(template % (url, uuid)) - if options.get('--publishAt'): - utils.publishAt(str(options.get('--publishAt')), oauth, url, idvideo, secret) else: logging.error(('Peertube: The upload failed with an unexpected response: ' '%s') % response) diff --git a/lib/utils.py b/lib/utils.py index f1958e1..bfabaad 100644 --- a/lib/utils.py +++ b/lib/utils.py @@ -193,62 +193,6 @@ def parseNFO(options): def upcaseFirstLetter(s): return s[0].upper() + s[1:] - -def publishAt(publishAt, oauth, url, idvideo, secret): - try: - FNULL = open(devnull, 'w') - check_call(["at", "-V"], stdout=FNULL, stderr=STDOUT) - except CalledProcessError: - logging.error("You need to install the atd daemon to use the publishAt option.") - exit(1) - try: - FNULL = open(devnull, 'w') - check_call(["curl", "-V"], stdout=FNULL, stderr=STDOUT) - except CalledProcessError: - logging.error("You need to install the curl command line to use the publishAt option.") - exit(1) - try: - FNULL = open(devnull, 'w') - check_call(["jq", "-V"], stdout=FNULL, stderr=STDOUT) - except CalledProcessError: - logging.error("You need to install the jq command line to use the publishAt option.") - exit(1) - time = publishAt.split("T") - # Remove leading seconds that atd does not manage - if time[1].count(":") == 2: - time[1] = time[1][:-3] - - atTime = time[1] + " " + time[0] - refresh_token=str(oauth.__dict__['_client'].__dict__['refresh_token']) - atFile = "/tmp/peertube_" + idvideo + "_" + publishAt + ".at" - try: - openfile = open(atFile,"w") - openfile.write('token=$(curl -X POST -d "client_id=' + str(secret.get('peertube', 'client_id')) + - '&client_secret=' + str(secret.get('peertube', 'client_secret')) + - '&grant_type=refresh_token&refresh_token=' + str(refresh_token) + - '" "' + url + '/api/v1/users/token" | jq -r .access_token)') - openfile.write("\n") - openfile.write('curl "' + url + '/api/v1/videos/' + idvideo + - '" -X PUT -H "Authorization: Bearer ${token}"' + - ' -H "Content-Type: multipart/form-data" -F "privacy=1"') - openfile.write("\n ") # atd needs an empty line at the end of the file to load... - openfile.close() - except Exception as e: - if hasattr(e, 'message'): - logging.error("Error: " + str(e.message)) - else: - logging.error("Error: " + str(e)) - - try: - FNULL = open(devnull, 'w') - check_call(["at", "-M", "-f", atFile, atTime], stdout=FNULL, stderr=STDOUT) - except Exception as e: - if hasattr(e, 'message'): - logging.error("Error: " + str(e.message)) - else: - logging.error("Error: " + str(e)) - - def mastodonTag(tag): tags = tag.split(' ') mtag = ''