Browse Source

Add the publishAt option to allow planned publication for your videos. See README for prerequisites

develop
LecygneNoir 6 years ago
parent
commit
d2c6154738
5 changed files with 95 additions and 4 deletions
  1. +10
    -0
      README.md
  2. +8
    -3
      lib/pt_upload.py
  3. +42
    -0
      lib/utils.py
  4. +13
    -1
      lib/yt_upload.py
  5. +22
    -0
      prismedia_upload.py

+ 10
- 0
README.md View File

@ -12,6 +12,11 @@ Search in your package manager, otherwise use ``pip install --upgrade``
- schema - schema
- python-magic - python-magic
- requests-toolbelt - 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)
## Configuration ## Configuration
@ -102,6 +107,10 @@ Options:
--platform=STRING List of platform(s) to upload to, comma separated. --platform=STRING List of platform(s) to upload to, comma separated.
Supported platforms are youtube and peertube (default is both) Supported platforms are youtube and peertube (default is both)
--language=STRING Specify the default language for video. See below for supported language. (default is English) --language=STRING Specify the default language for video. See below for supported language. (default is English)
--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
-h --help Show this help. -h --help Show this help.
--version Show version. --version Show version.
@ -138,6 +147,7 @@ Languages:
- ~~thumbnail/preview~~ Canceled, waiting for Youtube's API support - ~~thumbnail/preview~~ Canceled, waiting for Youtube's API support
- [x] Use a config file (NFO) file to retrieve videos arguments - [x] Use a config file (NFO) file to retrieve videos arguments
- [x] Allow to choose peertube or youtube upload (to resume failed upload for example) - [x] Allow 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 and [curl](https://linux.die.net/man/1/curl))
- [ ] Record and forget: put the video in a directory, and the script uploads it for you - [ ] 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) - [ ] Usable on Desktop (Linux and/or Windows and/or MacOS)
- [ ] Graphical User Interface - [ ] Graphical User Interface

+ 8
- 3
lib/pt_upload.py View File

@ -36,6 +36,7 @@ def get_authenticated_service(secret):
client_id=str(secret.get('peertube', 'client_id')), client_id=str(secret.get('peertube', 'client_id')),
client_secret=str(secret.get('peertube', 'client_secret')) client_secret=str(secret.get('peertube', 'client_secret'))
) )
return oauth return oauth
@ -113,9 +114,10 @@ def upload_video(oauth, secret, options):
headers=headers) headers=headers)
if response is not None: if response is not None:
if response.status_code == 200: if response.status_code == 200:
uuid = response.json()
uuid = uuid['video']
uuid = uuid['uuid']
jresponse = response.json()
jresponse = jresponse['video']
uuid = jresponse['uuid']
idvideo = str(jresponse['id'])
template = ('Peertube : Video was successfully uploaded.\n' template = ('Peertube : Video was successfully uploaded.\n'
'Watch it at %s/videos/watch/%s.') 'Watch it at %s/videos/watch/%s.')
print(template % (url, uuid)) print(template % (url, uuid))
@ -123,6 +125,9 @@ def upload_video(oauth, secret, options):
exit(('Peertube : The upload failed with an unexpected response: ' exit(('Peertube : The upload failed with an unexpected response: '
'%s') % response) '%s') % response)
if options.get('--publishAt'):
utils.publishAt(str(options.get('--publishAt')), oauth, url, idvideo)
def run(options): def run(options):
secret = RawConfigParser() secret = RawConfigParser()

+ 42
- 0
lib/utils.py View File

@ -3,6 +3,8 @@
from ConfigParser import RawConfigParser, NoOptionError, NoSectionError from ConfigParser import RawConfigParser, NoOptionError, NoSectionError
from os.path import dirname, splitext, basename, isfile from os.path import dirname, splitext, basename, isfile
from os import devnull
from subprocess import check_call, CalledProcessError, STDOUT
import unicodedata import unicodedata
### CATEGORIES ### ### CATEGORIES ###
@ -161,6 +163,46 @@ def upcaseFirstLetter(s):
return s[0].upper() + s[1:] return s[0].upper() + s[1:]
def publishAt(publishAt, oauth, url, idvideo):
try:
FNULL = open(devnull, 'w')
check_call(["at", "-V"], stdout=FNULL, stderr=STDOUT)
except CalledProcessError:
exit("You need to install the atd daemon to use the publishAt option.")
try:
FNULL = open(devnull, 'w')
check_call(["curl", "-V"], stdout=FNULL, stderr=STDOUT)
except CalledProcessError:
exit("You need to install the curl command line to use the publishAt option.")
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]
token=str(oauth.__dict__['_client'].__dict__['access_token'])
atFile = "/tmp/peertube_" + idvideo + "_" + publishAt + ".at"
try:
file = open(atFile,"w")
file.write("curl '" + url + "/api/v1/videos/" + idvideo + "' -X PUT -H 'Authorization: Bearer " + token + "' -H 'Content-Type: multipart/form-data' -F 'privacy=1'")
file.write(" ") # atd needs an empty line at the end of the file to load...
file.close()
except Exception as e:
if hasattr(e, 'message'):
print("Error: " + str(e.message))
else:
print("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'):
print("Error: " + str(e.message))
else:
print("Error: " + str(e))
def mastodonTag(tag): def mastodonTag(tag):
tags = tag.split(' ') tags = tag.split(' ')
mtag = '' mtag = ''

+ 13
- 1
lib/yt_upload.py View File

@ -10,6 +10,9 @@ import copy
import json import json
from os.path import splitext, basename, exists from os.path import splitext, basename, exists
import google.oauth2.credentials import google.oauth2.credentials
import datetime
import pytz
from tzlocal import get_localzone
from googleapiclient.discovery import build from googleapiclient.discovery import build
from googleapiclient.errors import HttpError from googleapiclient.errors import HttpError
@ -100,10 +103,19 @@ def initialize_upload(youtube, options):
}, },
"status": { "status": {
"privacyStatus": str(options.get('--privacy') or "private"), "privacyStatus": str(options.get('--privacy') or "private"),
"license": str(license or "youtube")
"license": str(license or "youtube"),
} }
} }
if options.get('--publishAt'):
# Youtube needs microsecond and the local timezone from ISO 8601
publishAt = options.get('--publishAt') + ".000001"
publishAt = datetime.datetime.strptime(publishAt, '%Y-%m-%dT%H:%M:%S.%f')
tz = get_localzone()
tz = pytz.timezone(str(tz))
publishAt = tz.localize(publishAt).isoformat()
body['status']['publishAt'] = str(publishAt)
# Call the API's videos.insert method to create and upload the video. # Call the API's videos.insert method to create and upload the video.
insert_request = youtube.videos().insert( insert_request = youtube.videos().insert(
part=','.join(body.keys()), part=','.join(body.keys()),

+ 22
- 0
prismedia_upload.py View File

@ -30,6 +30,10 @@ Options:
--platform=STRING List of platform(s) to upload to, comma separated. --platform=STRING List of platform(s) to upload to, comma separated.
Supported platforms are youtube and peertube (default is both) Supported platforms are youtube and peertube (default is both)
--language=STRING Specify the default language for video. See below for supported language. (default is English) --language=STRING Specify the default language for video. See below for supported language. (default is English)
--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
-h --help Show this help. -h --help Show this help.
--version Show version. --version Show version.
@ -51,6 +55,7 @@ Languages:
""" """
from os.path import dirname, realpath from os.path import dirname, realpath
import sys import sys
import datetime
from docopt import docopt from docopt import docopt
@ -131,6 +136,18 @@ def validateLanguage(language):
return False return False
def validatePublish(publish):
# Check date format and if date is future
try:
now = datetime.datetime.now()
publishAt = datetime.datetime.strptime(publish, '%Y-%m-%dT%H:%M:%S')
if now >= publishAt:
return False
except ValueError:
return False
return True
if __name__ == '__main__': if __name__ == '__main__':
options = docopt(__doc__, version=VERSION) options = docopt(__doc__, version=VERSION)
@ -170,6 +187,11 @@ if __name__ == '__main__':
), ),
Optional('--nfo'): Or(None, str), Optional('--nfo'): Or(None, str),
Optional('--platform'): Or(None, And(str, validatePlatform, error="Sorry, upload platform not supported")), Optional('--platform'): Or(None, And(str, validatePlatform, error="Sorry, upload platform not supported")),
Optional('--publishAt'): Or(None, And(
str,
validatePublish,
error="DATE should be the form YYYY-MM-DDThh:mm:ss and has to be in the future")
),
Optional('--cca'): bool, Optional('--cca'): bool,
Optional('--disable-comments'): bool, Optional('--disable-comments'): bool,
Optional('--nsfw'): bool, Optional('--nsfw'): bool,

Loading…
Cancel
Save