From 3150b4c4884ae7a152edd43e31683ea5e5e42e4c Mon Sep 17 00:00:00 2001 From: Anatoly Date: Wed, 3 Nov 2021 00:42:51 +0300 Subject: [PATCH] Apiless uploads --- .gitignore | 3 +- .gitmodules | 3 + YouTubeUploader | 1 + upload.py | 181 --------------------------------------------- uploadanddelete.sh | 3 +- 5 files changed, 7 insertions(+), 184 deletions(-) create mode 100644 .gitmodules create mode 160000 YouTubeUploader delete mode 100644 upload.py diff --git a/.gitignore b/.gitignore index a9a6ef6..e3a5cb6 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,4 @@ node_modules/ .DS_Store trend/ *.mp4 -client_secrets.json -*-oauth2.json \ No newline at end of file +cookies.json \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..5386f2e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "YouTubeUploader"] + path = YouTubeUploader + url = git@github.com:ContentAutomation/YouTubeUploader.git diff --git a/YouTubeUploader b/YouTubeUploader new file mode 160000 index 0000000..74255c9 --- /dev/null +++ b/YouTubeUploader @@ -0,0 +1 @@ +Subproject commit 74255c90435ba412f0003e0dfb33b39aa85394c6 diff --git a/upload.py b/upload.py deleted file mode 100644 index a4ee091..0000000 --- a/upload.py +++ /dev/null @@ -1,181 +0,0 @@ -#!/usr/bin/python - -import httplib -import httplib2 -import os -import random -import sys -import time - -from apiclient.discovery import build -from apiclient.errors import HttpError -from apiclient.http import MediaFileUpload -from oauth2client.client import flow_from_clientsecrets -from oauth2client.file import Storage -from oauth2client.tools import argparser, run_flow - - -# Explicitly tell the underlying HTTP transport library not to retry, since -# we are handling retry logic ourselves. -httplib2.RETRIES = 1 - -# Maximum number of times to retry before giving up. -MAX_RETRIES = 10 - -# Always retry when these exceptions are raised. -RETRIABLE_EXCEPTIONS = (httplib2.HttpLib2Error, IOError, httplib.NotConnected, - httplib.IncompleteRead, httplib.ImproperConnectionState, - httplib.CannotSendRequest, httplib.CannotSendHeader, - httplib.ResponseNotReady, httplib.BadStatusLine) - -# Always retry when an apiclient.errors.HttpError with one of these status -# codes is raised. -RETRIABLE_STATUS_CODES = [500, 502, 503, 504] - -# The CLIENT_SECRETS_FILE variable specifies the name of a file that contains -# the OAuth 2.0 information for this application, including its client_id and -# client_secret. You can acquire an OAuth 2.0 client ID and client secret from -# the Google API Console at -# https://console.developers.google.com/. -# Please ensure that you have enabled the YouTube Data API for your project. -# For more information about using OAuth2 to access the YouTube Data API, see: -# https://developers.google.com/youtube/v3/guides/authentication -# For more information about the client_secrets.json file format, see: -# https://developers.google.com/api-client-library/python/guide/aaa_client_secrets -CLIENT_SECRETS_FILE = "client_secrets.json" - -# This OAuth 2.0 access scope allows an application to upload files to the -# authenticated user's YouTube channel, but doesn't allow other types of access. -YOUTUBE_UPLOAD_SCOPE = "https://www.googleapis.com/auth/youtube.upload" -YOUTUBE_API_SERVICE_NAME = "youtube" -YOUTUBE_API_VERSION = "v3" - -# This variable defines a message to display if the CLIENT_SECRETS_FILE is -# missing. -MISSING_CLIENT_SECRETS_MESSAGE = """ -WARNING: Please configure OAuth 2.0 - -To make this sample run you will need to populate the client_secrets.json file -found at: - - %s - -with information from the API Console -https://console.developers.google.com/ - -For more information about the client_secrets.json file format, please visit: -https://developers.google.com/api-client-library/python/guide/aaa_client_secrets -""" % os.path.abspath(os.path.join(os.path.dirname(__file__), - CLIENT_SECRETS_FILE)) - -VALID_PRIVACY_STATUSES = ("public", "private", "unlisted") - - -def get_authenticated_service(args): - flow = flow_from_clientsecrets(CLIENT_SECRETS_FILE, - scope=YOUTUBE_UPLOAD_SCOPE, - message=MISSING_CLIENT_SECRETS_MESSAGE) - - storage = Storage("%s-oauth2.json" % sys.argv[0]) - credentials = storage.get() - - if credentials is None or credentials.invalid: - credentials = run_flow(flow, storage, args) - - return build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, - http=credentials.authorize(httplib2.Http())) - -def initialize_upload(youtube, options): - tags = None - if options.keywords: - tags = options.keywords.split(",") - - body=dict( - snippet=dict( - title=options.title, - description=options.description, - tags=tags, - categoryId=options.category - ), - status=dict( - privacyStatus=options.privacyStatus - ) - ) - - # Call the API's videos.insert method to create and upload the video. - insert_request = youtube.videos().insert( - part=",".join(body.keys()), - body=body, - # The chunksize parameter specifies the size of each chunk of data, in - # bytes, that will be uploaded at a time. Set a higher value for - # reliable connections as fewer chunks lead to faster uploads. Set a lower - # value for better recovery on less reliable connections. - # - # Setting "chunksize" equal to -1 in the code below means that the entire - # file will be uploaded in a single HTTP request. (If the upload fails, - # it will still be retried where it left off.) This is usually a best - # practice, but if you're using Python older than 2.6 or if you're - # running on App Engine, you should set the chunksize to something like - # 1024 * 1024 (1 megabyte). - media_body=MediaFileUpload(options.file, chunksize=-1, resumable=True) - ) - - resumable_upload(insert_request) - -# This method implements an exponential backoff strategy to resume a -# failed upload. -def resumable_upload(insert_request): - response = None - error = None - retry = 0 - while response is None: - try: - print "Uploading file..." - status, response = insert_request.next_chunk() - if response is not None: - if 'id' in response: - print "Video id '%s' was successfully uploaded." % response['id'] - else: - exit("The upload failed with an unexpected response: %s" % response) - except HttpError, e: - if e.resp.status in RETRIABLE_STATUS_CODES: - error = "A retriable HTTP error %d occurred:\n%s" % (e.resp.status, - e.content) - else: - raise - except RETRIABLE_EXCEPTIONS, e: - error = "A retriable error occurred: %s" % e - - if error is not None: - print error - retry += 1 - if retry > MAX_RETRIES: - exit("No longer attempting to retry.") - - max_sleep = 2 ** retry - sleep_seconds = random.random() * max_sleep - print "Sleeping %f seconds and then retrying..." % sleep_seconds - time.sleep(sleep_seconds) - -if __name__ == '__main__': - argparser.add_argument("--file", required=True, help="Video file to upload") - argparser.add_argument("--title", help="Video title", default="Test Title") - argparser.add_argument("--description", help="Video description", - default="Test Description") - argparser.add_argument("--category", default="22", - help="Numeric video category. " + - "See https://developers.google.com/youtube/v3/docs/videoCategories/list") - argparser.add_argument("--keywords", help="Video keywords, comma separated", - default="") - argparser.add_argument("--privacyStatus", choices=VALID_PRIVACY_STATUSES, - default=VALID_PRIVACY_STATUSES[0], help="Video privacy status.") - args = argparser.parse_args() - - if not os.path.exists(args.file): - exit("Please specify a valid file using the --file= parameter.") - - youtube = get_authenticated_service(args) - try: - initialize_upload(youtube, args) - except HttpError, e: - print "An HTTP error %d occurred:\n%s" % (e.resp.status, e.content) diff --git a/uploadanddelete.sh b/uploadanddelete.sh index f51b159..53cfaea 100755 --- a/uploadanddelete.sh +++ b/uploadanddelete.sh @@ -1,2 +1,3 @@ #!/bin/sh -python2 upload.py --file output.mp4 --title="TikTok Test" && rm -rf trend && rm *.mp4 \ No newline at end of file +poetry run python main.py -l ../cookies.json -t "TikTok Compilation" -d "Best of TikTok" -B firefox "$(pwd)/../output.mp4" && +rm -rf trend && rm *.mp4 \ No newline at end of file