Browse Source

Merge branch 'master' of meewan/ptyt_upload into master

Refactor code to pep8 standards
develop
LecygneNoir 6 years ago
committed by Gogs
parent
commit
097f3af92f
3 changed files with 153 additions and 126 deletions
  1. +43
    -27
      lib/pt_upload.py
  2. +93
    -82
      lib/yt_upload.py
  3. +17
    -17
      ptyt_upload.py

+ 43
- 27
lib/pt_upload.py View File

@ -3,10 +3,8 @@
import os import os
import mimetypes import mimetypes
import httplib
import httplib2
import json import json
import array
from os.path import splitext, basename, abspath
from ConfigParser import RawConfigParser from ConfigParser import RawConfigParser
from requests_oauthlib import OAuth2Session from requests_oauthlib import OAuth2Session
@ -15,44 +13,58 @@ from requests_toolbelt.multipart.encoder import MultipartEncoder
PEERTUBE_SECRETS_FILE = 'peertube_secret' PEERTUBE_SECRETS_FILE = 'peertube_secret'
def get_authenticated_service(config): def get_authenticated_service(config):
oauth = OAuth2Session(client=LegacyApplicationClient(client_id=str(config.get('peertube', 'client_id'))))
oauth.fetch_token(token_url=str(config.get('peertube', 'peertube_url')) + '/api/v1/users/token',
username=str(config.get('peertube', 'username').lower()), #lower as peertube does not store uppecase for pseudo
password=str(config.get('peertube', 'password')),
client_id=str(config.get('peertube', 'client_id')),
client_secret=str(config.get('peertube', 'client_secret'))
)
peertube_url = str(config.get('peertube', 'peertube_url'))
oauth_client = LegacyApplicationClient(
client_id=str(config.get('peertube', 'client_id'))
)
oauth = OAuth2Session(client=oauth_client)
oauth.fetch_token(
token_url=peertube_url + '/api/v1/users/token',
# lower as peertube does not store uppecase for pseudo
username=str(config.get('peertube', 'username').lower()),
password=str(config.get('peertube', 'password')),
client_id=str(config.get('peertube', 'client_id')),
client_secret=str(config.get('peertube', 'client_secret'))
)
return oauth return oauth
def upload_video(oauth, config, options): def upload_video(oauth, config, options):
def get_userinfo(): def get_userinfo():
user_info = json.loads(oauth.get(url+"/api/v1/users/me").content)
user_info = json.loads(oauth.get(url + "/api/v1/users/me").content)
return str(user_info["id"]) return str(user_info["id"])
def get_videofile(path): def get_videofile(path):
mimetypes.init() mimetypes.init()
return (os.path.basename(path), open(os.path.abspath(path), 'rb'),
mimetypes.types_map[os.path.splitext(path)[1]])
return (basename(path), open(abspath(path), 'rb'),
mimetypes.types_map[splitext(path)[1]])
path = options.get('--file') path = options.get('--file')
url = config.get('peertube', 'peertube_url') url = config.get('peertube', 'peertube_url')
tags = None tags = None
tags_tuple=[]
# We need to transform fields into tuple to deal with tags as MultipartEncoder does not support list
# refer https://github.com/requests/toolbelt/issues/190 and https://github.com/requests/toolbelt/issues/205
# We need to transform fields into tuple to deal with tags as
# MultipartEncoder does not support list refer
# https://github.com/requests/toolbelt/issues/190 and
# https://github.com/requests/toolbelt/issues/205
fields = [ fields = [
("name", options.get('--name') or os.path.splitext(os.path.basename(path))[0]),
("category", str(options.get('--category') or 1)), # look at the list numbers at /videos/categories
("licence", str(options.get('--licence') or 1)), # look at the list numbers at /videos/licences
("name", options.get('--name') or splitext(basename(path))[0]),
# look at the list numbers at /videos/categories
("category", str(options.get('--category') or 1)),
# look at the list numbers at /videos/licences
("licence", str(options.get('--licence') or 1)),
("description", options.get('--description') or "default description"), ("description", options.get('--description') or "default description"),
("privacy", str(options.get('--privacy') or 3)), # look at the list numbers at /videos/privacies
# look at the list numbers at /videos/privacies
("privacy", str(options.get('--privacy') or 3)),
("nsfw", str(options.get('--nsfw') or 0)), ("nsfw", str(options.get('--nsfw') or 0)),
("commentsEnabled", "1"), ("commentsEnabled", "1"),
("channelId", get_userinfo()), ("channelId", get_userinfo()),
("videofile", get_videofile(path)) # beware, see validateVideo for supported types
# beware, see validateVideo for supported types
("videofile", get_videofile(path))
] ]
if options.get('--tags'): if options.get('--tags'):
@ -67,24 +79,28 @@ def upload_video(oauth, config, options):
'Content-Type': multipart_data.content_type 'Content-Type': multipart_data.content_type
} }
response = oauth.post(config.get('peertube', 'peertube_url')+"/api/v1/videos/upload", data=multipart_data, headers=headers)
response = oauth.post(url + "/api/v1/videos/upload",
data=multipart_data,
headers=headers)
if response is not None: if response is not None:
if response.status_code == 200: if response.status_code == 200:
print 'Peertube : Video was successfully uploaded.'
print('Peertube : Video was successfully uploaded.')
else: else:
exit('Peertube : The upload failed with an unexpected response: %s' % response)
exit(('Peertube : The upload failed with an unexpected response: '
'%s') % response)
def run(options): def run(options):
config = RawConfigParser() config = RawConfigParser()
config.read(PEERTUBE_SECRETS_FILE) config.read(PEERTUBE_SECRETS_FILE)
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = config.get('peertube', 'OAUTHLIB_INSECURE_TRANSPORT')
insecure_transport = config.get('peertube', 'OAUTHLIB_INSECURE_TRANSPORT')
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = insecure_transport
oauth = get_authenticated_service(config) oauth = get_authenticated_service(config)
try: try:
print 'Peertube : Uploading file...'
print('Peertube : Uploading file...')
upload_video(oauth, config, options) upload_video(oauth, config, options)
except Exception as e: except Exception as e:
if hasattr(e, 'message'): if hasattr(e, 'message'):
print(e.message) print(e.message)
else: else:
print(e)
print(e)

+ 93
- 82
lib/yt_upload.py View File

@ -1,18 +1,15 @@
#!/usr/bin/python #!/usr/bin/python
# coding: utf-8 # coding: utf-8
# From Youtube samples : https://raw.githubusercontent.com/youtube/api-samples/master/python/upload_video.py
# From Youtube samples : https://raw.githubusercontent.com/youtube/api-samples/master/python/upload_video.py # noqa
import argparse
import httplib import httplib
import httplib2 import httplib2
import os
import random import random
import time import time
import copy import copy
import json import json
from os.path import splitext, basename, exists
import google.oauth2.credentials import google.oauth2.credentials
import google_auth_oauthlib.flow
from googleapiclient.discovery import build from googleapiclient.discovery import build
from googleapiclient.errors import HttpError from googleapiclient.errors import HttpError
@ -28,10 +25,17 @@ httplib2.RETRIES = 1
MAX_RETRIES = 10 MAX_RETRIES = 10
# Youtube retriables cases # Youtube retriables cases
RETRIABLE_EXCEPTIONS = (httplib2.HttpLib2Error, IOError, httplib.NotConnected,
httplib.IncompleteRead, httplib.ImproperConnectionState,
httplib.CannotSendRequest, httplib.CannotSendHeader,
httplib.ResponseNotReady, httplib.BadStatusLine)
RETRIABLE_EXCEPTIONS = (
IOError,
httplib2.HttpLib2Error,
httplib.NotConnected,
httplib.IncompleteRead,
httplib.ImproperConnectionState,
httplib.CannotSendRequest,
httplib.CannotSendHeader,
httplib.ResponseNotReady,
httplib.BadStatusLine,
)
RETRIABLE_STATUS_CODES = [500, 502, 503, 504] RETRIABLE_STATUS_CODES = [500, 502, 503, 504]
@ -45,91 +49,98 @@ API_VERSION = 'v3'
# Authorize the request and store authorization credentials. # Authorize the request and store authorization credentials.
def get_authenticated_service(): def get_authenticated_service():
flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRETS_FILE, SCOPES)
if os.path.exists(CREDENTIALS_PATH):
with open(CREDENTIALS_PATH, 'r') as f:
credential_params = json.load(f)
credentials = google.oauth2.credentials.Credentials(
credential_params["token"],
refresh_token=credential_params["_refresh_token"],
token_uri=credential_params["_token_uri"],
client_id=credential_params["_client_id"],
client_secret=credential_params["_client_secret"]
)
else:
credentials = flow.run_local_server()
with open(CREDENTIALS_PATH, 'w') as f:
p = copy.deepcopy(vars(credentials))
del p["expiry"]
json.dump(p, f)
return build(API_SERVICE_NAME, API_VERSION, credentials = credentials)
flow = InstalledAppFlow.from_client_secrets_file(
CLIENT_SECRETS_FILE, SCOPES)
if exists(CREDENTIALS_PATH):
with open(CREDENTIALS_PATH, 'r') as f:
credential_params = json.load(f)
credentials = google.oauth2.credentials.Credentials(
credential_params["token"],
refresh_token=credential_params["_refresh_token"],
token_uri=credential_params["_token_uri"],
client_id=credential_params["_client_id"],
client_secret=credential_params["_client_secret"]
)
else:
credentials = flow.run_local_server()
with open(CREDENTIALS_PATH, 'w') as f:
p = copy.deepcopy(vars(credentials))
del p["expiry"]
json.dump(p, f)
return build(API_SERVICE_NAME, API_VERSION, credentials=credentials)
def initialize_upload(youtube, options): def initialize_upload(youtube, options):
path = options.get('--file')
tags = None
if options.get('--tags'):
tags = options.get('--tags').split(',')
body=dict(
snippet=dict(
title=options.get('--name') or os.path.splitext(os.path.basename(path))[0],
description=options.get('--description') or "",
tags=tags,
categoryId=str(options.get('--category') or 1),
),
status=dict(
privacyStatus=str(options.get('--privacy') or "private"),
path = options.get('--file')
tags = None
if options.get('--tags'):
tags = options.get('--tags').split(',')
body = {
"snippet": {
"title": options.get('--name') or splitext(basename(path))[0],
"description": options.get('--description') or "",
"tags": tags,
"categoryId": str(options.get('--category') or 1),
},
"status": {"privacyStatus": str(options.get('--privacy') or "private")}
}
# Call the API's videos.insert method to create and upload the video.
insert_request = youtube.videos().insert(
part=','.join(body.keys()),
body=body,
media_body=MediaFileUpload(path, chunksize=-1, resumable=True)
) )
)
# Call the API's videos.insert method to create and upload the video.
insert_request = youtube.videos().insert(
part=','.join(body.keys()),
body=body,
media_body=MediaFileUpload(path, chunksize=-1, resumable=True)
)
resumable_upload(insert_request)
resumable_upload(insert_request)
# This method implements an exponential backoff strategy to resume a # This method implements an exponential backoff strategy to resume a
# failed upload. # failed upload.
def resumable_upload(request): def resumable_upload(request):
response = None
error = None
retry = 0
while response is None:
try:
print 'Youtube : Uploading file...'
status, response = request.next_chunk()
if response is not None:
if 'id' in response:
print 'Youtube : Video id "%s" was successfully uploaded.' % response['id']
else:
exit('Youtube : The upload failed with an unexpected response: %s' % response)
except HttpError, e:
if e.resp.status in RETRIABLE_STATUS_CODES:
error = 'Youtube : A retriable HTTP error %d occurred:\n%s' % (e.resp.status,
e.content)
else:
raise
except RETRIABLE_EXCEPTIONS, e:
error = 'Youtube : A retriable error occurred: %s' % e
response = None
error = None
retry = 0
while response is None:
try:
print('Youtube : Uploading file...')
status, response = request.next_chunk()
if response is not None:
if 'id' in response:
template = ('Youtube : Video id "%s" was successfully '
'uploaded.')
print(template % response['id'])
else:
template = ('Youtube : The upload failed with an '
'unexpected response: %s')
exit(template % response)
except HttpError as e:
if e.resp.status in RETRIABLE_STATUS_CODES:
template = 'Youtube : A retriable HTTP error %d occurred:\n%s'
error = template % (e.resp.status, e.content)
else:
raise
except RETRIABLE_EXCEPTIONS as e:
error = 'Youtube : A retriable error occurred: %s' % e
if error is not None: if error is not None:
print error
retry += 1
if retry > MAX_RETRIES:
exit('Youtube : No longer attempting to retry.')
print(error)
retry += 1
if retry > MAX_RETRIES:
exit('Youtube : No longer attempting to retry.')
max_sleep = 2 ** retry
sleep_seconds = random.random() * max_sleep
print 'Youtube : Sleeping %f seconds and then retrying...' % sleep_seconds
time.sleep(sleep_seconds)
max_sleep = 2 ** retry
sleep_seconds = random.random() * max_sleep
print('Youtube : Sleeping %f seconds and then retrying...'
% sleep_seconds)
time.sleep(sleep_seconds)
def run(options): def run(options):
youtube = get_authenticated_service()
try:
initialize_upload(youtube, options)
except HttpError, e:
print 'Youtube : An HTTP error %d occurred:\n%s' % (e.resp.status, e.content)
youtube = get_authenticated_service()
try:
initialize_upload(youtube, options)
except HttpError as e:
print('Youtube : An HTTP error %d occurred:\n%s' % (e.resp.status,
e.content))

+ 17
- 17
ptyt_upload.py View File

@ -4,7 +4,7 @@
""" """
ptyt_upload - tool to upload videos to Peertube and Youtube ptyt_upload - tool to upload videos to Peertube and Youtube
Usage:
Usage:
ptyt_upload.py --file=<FILE> [options] ptyt_upload.py --file=<FILE> [options]
ptyt_upload.py -h | --help ptyt_upload.py -h | --help
ptyt_upload.py --version ptyt_upload.py --version
@ -15,14 +15,17 @@ Options:
-t, --tags=STRING Tags for the video. comma separated -t, --tags=STRING Tags for the video. comma separated
-h --help Show this help. -h --help Show this help.
--version Show version. --version Show version.
""" """
import argparse
from os.path import dirname, realpath
from sys.path import insert
from docopt import docopt from docopt import docopt
import yt_upload
import pt_upload
try: try:
from schema import Schema, And, Or, Use, Optional, SchemaError
from schema import Schema, And, Or, Optional, SchemaError
except ImportError: except ImportError:
exit('This program requires that the `schema` data-validation library' exit('This program requires that the `schema` data-validation library'
' is installed: \n' ' is installed: \n'
@ -34,9 +37,10 @@ except ImportError:
' is installed, NOT the Python bindings to libmagic API \n' ' is installed, NOT the Python bindings to libmagic API \n'
'see https://github.com/ahupp/python-magic\n') 'see https://github.com/ahupp/python-magic\n')
VERSION="ptyt 0.1-alpha"
VERSION = "ptyt 0.1-alpha"
VALID_PRIVACY_STATUSES = ('public', 'private', 'unlisted') VALID_PRIVACY_STATUSES = ('public', 'private', 'unlisted')
def validateVideo(path): def validateVideo(path):
supported_types = ['video/mp4'] supported_types = ['video/mp4']
if magic.from_file(path, mime=True) in supported_types: if magic.from_file(path, mime=True) in supported_types:
@ -44,19 +48,15 @@ def validateVideo(path):
else: else:
return False return False
if __name__ == '__main__':
#Allows you to a relative import from the parent folder
import os.path, sys
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__))+"/lib")
import yt_upload
import pt_upload
if __name__ == '__main__':
# Allows you to a relative import from the parent folder
insert(0, dirname(realpath(__file__)) + "/lib")
options = docopt(__doc__, version=VERSION) options = docopt(__doc__, version=VERSION)
schema = Schema({ schema = Schema({
'--file': And(str, lambda s: validateVideo(s), error='file is not supported, please use mp4'),
'--file': And(str, validateVideo, error='file is not supported, please use mp4'),
Optional('--name'): Or(None, And(str, lambda x: not x.isdigit(), error="The video name should be a string")), Optional('--name'): Or(None, And(str, lambda x: not x.isdigit(), error="The video name should be a string")),
Optional('--description'): Or(None, And(str, lambda x: not x.isdigit(), error="The video name should be a string")), Optional('--description'): Or(None, And(str, lambda x: not x.isdigit(), error="The video name should be a string")),
Optional('--tags'): Or(None, And(str, lambda x: not x.isdigit(), error="Tags should be a string")), Optional('--tags'): Or(None, And(str, lambda x: not x.isdigit(), error="Tags should be a string")),
@ -68,6 +68,6 @@ if __name__ == '__main__':
options = schema.validate(options) options = schema.validate(options)
except SchemaError as e: except SchemaError as e:
exit(e) exit(e)
yt_upload.run(options) yt_upload.run(options)
pt_upload.run(options)
pt_upload.run(options)

Loading…
Cancel
Save