Skip to content

Instantly share code, notes, and snippets.

@iKlotho
Created February 19, 2020 21:27
Show Gist options
  • Save iKlotho/00a3a8b16b1ba7bd72b7fd54a0d379cc to your computer and use it in GitHub Desktop.
Save iKlotho/00a3a8b16b1ba7bd72b7fd54a0d379cc to your computer and use it in GitHub Desktop.
Youtube Python Upload
"""
Upload a video to youtube
"""
import os
import time
import cookielib
import json
import requests
import mechanize
from BeautifulSoup import BeautifulSoup
class YoutubeUpload:
def __init__(
self,
email,
passwd,
file="",
video_name="default",
description="",
privacy="public",
tags="",
):
self.rupio_formdata = {
"protocolVersion": "0.8",
"createSessionRequest": {
"fields": [
{
"external": {
"name": "file",
"filename": "videoname",
"put": {},
"size": 0,
}
},
{
"inlined": {
"name": "return_address",
"content": "www.youtube.com",
"contentType": "text/plain",
}
},
{
"inlined": {
"name": "user_token",
"content": "aBSi_UqNbqLNey9asEQZrl3awgh8MTQ0MzIxMjM3MEAxNDQyNjA3NTcw",
"contentType": "text/plain",
}
},
{
"inlined": {
"name": "authuser",
"content": "0",
"contentType": "text/plain",
}
},
{
"inlined": {
"name": "uploader_type",
"content": "Web_XHR",
"contentType": "text/plain",
}
},
{
"inlined": {
"name": "frontend_id",
"content": "web_upload:b7ef7a96-a27f-48dd-9ff1-8f311b0d11ac:0",
"contentType": "text/plain",
}
},
{
"inlined": {
"name": "use_drishti_thumbnailer",
"content": "1",
"contentType": "text/plain",
}
},
{
"inlined": {
"name": "use_drishti_thumbnailer_for_high_priority",
"content": "1",
"contentType": "text/plain",
}
},
{
"inlined": {
"name": "use_venom_processing",
"content": "true",
"contentType": "text/plain",
}
},
{
"inlined": {
"name": "field_privacy",
"content": "private",
"contentType": "text/plain",
}
},
{
"inlined": {
"name": "field_myvideo_title",
"content": "videosxlilyseditzxokay issa",
"contentType": "text/plain",
}
},
{
"inlined": {
"name": "field_myvideo_descr",
"content": "",
"contentType": "text/plain",
}
},
{
"inlined": {
"name": "field_myvideo_keywords",
"content": "",
"contentType": "text/plain",
}
},
{
"inlined": {
"name": "field_myvideo_categories",
"content": "23",
"contentType": "text/plain",
}
},
{
"inlined": {
"name": "allow_public_stats",
"content": "yes",
"contentType": "text/plain",
}
},
{
"inlined": {
"name": "allow_comments",
"content": "yes",
"contentType": "text/plain",
}
},
{
"inlined": {
"name": "allow_comments_detail",
"content": "all",
"contentType": "text/plain",
}
},
{
"inlined": {
"name": "allow_ratings",
"content": "yes",
"contentType": "text/plain",
}
},
{
"inlined": {
"name": "privacy_draft",
"content": "public",
"contentType": "text/plain",
}
},
{
"inlined": {
"name": "session_token",
"content": "QUFFLUhqbnVUZW9NckNVbWE0OHJaTVFHVzdaZkwyZW1WZ3xBQ3Jtc0tsZFBGajRVNWhxQnp0VWF1MlZfb3BRSkUzRjVnZU51S3hWWWhuYlAxTGRhMzgyZkpKekJJNXJNekdkSHVaOWt1V3RkNkx3d1pLQkc5blJSMW9TWjdKeEZTc2NxVjhrQmw5Wk1TUVpZRERreTh2djczZHBIbVRfMVZfcmpmSElXWjlndnFveWc0Z1BZbTFibXlBVEtPLUE5cTZLV0E=",
"contentType": "text/plain",
}
},
{
"inlined": {
"name": "experiment_ids",
"content": "9415398,9416475,9417481,9419979,9420289,9422596,9423555,9428398,9428632,9429954,9431012,9431681,9432939,9433221,9433839,9433870,9434046,9434289,9434949,9435354,9435521,9438309,9439451,9439580,9439877,9440054,9441194,9441513,9441929,9442387,9442393,9442426,9442746,9444189,9445634,9445860,9446054,9446062,9446142,9446364,9446877,9447232,9447774,9448302,9449034,9449074,9449243,9449256,9450059,9450402,9450544,9450641,9451164,9451343,9451345,9451494,9451783,9451814,9451827,9451873,9451929,9451937,9452119,9452146,9452448,9452833,9452850,9453098,9453167,9453553,9453682,9454366,9454383,9454394,9454653,9454793,9455031,9455068,9455072,9455655,9455983,9456026,9456133,9456249,9456443,9456445,9456516,9456628,9456631,9456640,9456760,9456930,9457141,9457146,9457169,9457492,9457494,9457591,9457595,9457598,9457623,9457968,9458027,9458029,9458054,9458240,9458265,9458386,9458668,9458670,9458881,9459035,9459067,9459073,9459075,9459187,9459429,9459444,9459605,9459762,9459768,9459793,9459798,9460103,9460349,9460431,9460434,9460599,9460727,9460830,9461013,9461125,9461208,9461327,9461498",
"contentType": "text/plain",
}
},
]
},
}
self.json_data_check = False
self.user = email
self.passwd = passwd
self.rupio_url = "https://upload.youtube.com/upload/rupio"
self.csa_url = "https://www.youtube.com/creator_suggestions_ajax"
self.yummyajax_url = "https://www.youtube.com/yummy_ajax"
self.setvideoparams_url = "https://www.youtube.com/api/tag_suggest"
self.list_payload = {}
self.video_id = None
self.upload_id = None
self.ssn_token = None
self.user_token = None
self.frontend_upload_id = None
self.video_name = video_name
self.description = description
self.privacy = privacy
self.file_name = file
self.tag = tags
self.br = mechanize.Browser()
self.cj = cookielib.LWPCookieJar()
self.br.set_cookiejar(self.cj)
self.br.set_handle_equiv(True)
self.br.set_handle_gzip(False)
self.br.set_handle_redirect(True)
self.br.set_handle_referer(True)
self.br.set_handle_robots(False)
self.br.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1)
self.br.addheaders = [
(
"User-agent",
"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0",
)
]
self.br.addheaders = [("Accept-Language", "en-US;q=0.5,en;q=0.3")]
# call functions
self.access_1()
time.sleep(1)
self.access_2()
time.sleep((1))
self.getSessionToken()
self.getFrontendUploadIdBase()
self.getUserToken()
self.find_youtube_web_uploads()
self.setRupioData(self.file_name)
self.post_creator_suggestions_ajax()
time.sleep(0.5)
self.post_rupio()
time.sleep(0.5)
self.post_yummyAjax()
time.sleep(0.5)
self.doOptions()
time.sleep(0.5)
self.setVideoParamaters()
def access_1(self):
# pylint: disable=line-too-long
self.br.open(
"https://accounts.google.com/ServiceLogin?passive=true&continue=https%3A%2F%2Fwww.youtube.com%2Fsignin%3Faction_handle_signin%3Dtrue%26app%3Ddesktop%26feature%3Dsign_in_button%26hl%3Dtr%26next%3D%252F&uilel=3&hl=tr&service=youtube#identifier"
)
self.br.select_form(nr=0)
self.br.form.set_all_readonly(False)
self.br.form["Email"] = self.user
self.br.submit()
def access_2(self):
self.br.select_form(nr=0)
self.br.form.set_all_readonly(False)
self.br.form["Passwd"] = self.passwd
self.br.submit()
self.session = requests.Session()
self.session.cookies = self.cj
self.session.headers[
"User-Agent"
] = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0"
self.session.headers["Accept-Language"] = "en-US;q=0.5,en;q=0.3"
def getSessionToken(self):
token_req = self.session.get("https://www.youtube.com/upload")
self.soup = BeautifulSoup(token_req.content)
script = self.soup.findAll("script")
# TODO find with regex
script_id = self.find_word_fr_script(script, "session_token")
loc = script[script_id].text.find("var session_token")
if loc:
self.ssn_token = script[script_id].text[loc + 21 : loc + 313]
def find_word_fr_script(self, scripts, word):
count = 0
for j in scripts:
if j.text.find(word) > 0:
break
count += 1
return count
def getUserToken(self):
script = self.soup.findAll("script")
script_id = self.find_word_fr_script(script, "userToken")
loc = script[script_id].text.find("userToken")
if loc:
self.user_token = script[script_id].text[loc + 12 : loc + 68]
def getFrontendUploadIdBase(self):
script = self.soup.findAll("script")
script_id = self.find_word_fr_script(script, "frontend_upload_idBase")
loc = script[script_id].text.find("frontend_upload_idBase")
if loc:
self.frontend_upload_id = script[script_id].text[loc + 23 : loc + 59]
def get_userId(self):
get_user_id_req = self.session.get("https://www.youtube.com/account_advanced")
soup = BeautifulSoup(get_user_id_req.content)
div = soup.findAll("div", "account-subsection")
return div[0].findAll("p")[2].text[25 + 2 :]
def get_videoId(self):
self.list_payload = {
"client": {
"name": "youtube_web_uploads",
"version": str(self.version),
"token": str(self.token),
},
"queries": [
{
"id": {"frontendKey": self.frontend_upload_id},
"choice": {
"editorSuggestions": True,
"videoId": True,
"videoInfo2": True,
"videoIssues": True,
"processingProgress": True,
"youtubeStatus": True,
"thumbnailsDone": True,
},
}
],
}
check = True
while check:
videoid_req = self.session.post(
"https://www.googleapis.com/videofeedback/v1/feedback/list",
data=json.dumps(self.list_payload),
headers={"Content-Type": "application/json"},
)
id_json = videoid_req.json()
if videoid_req.status_code == 200:
if id_json.has_key("items"):
if id_json["items"][0]["feedback"]:
check = False
time.sleep(2)
self.video_id = id_json["items"][0]["feedback"]["videoId"]["youtubeId"]
if (
id_json["items"][0]["feedback"]["videoId"]["registrationStatus"]
== "STATUS_SUCCESS"
):
print("Video posting status success")
self.post_yummyAjaxWithVideoId()
def find_youtube_web_uploads(self):
script = self.soup.findAll("script")
script_id = self.find_word_fr_script(script, "youtube_web_uploads")
loc = script[script_id].text.find("youtube_web_uploads")
if loc:
keep = script[script_id].text[loc + 20 : loc + 38]
keep = keep.split(":")
if len(keep) >= 2:
self.version = keep[0]
self.token = keep[1]
else:
print("version and token not found try again!")
self.logout()
def setRupioData(self, file_name):
self.filename = file_name
self.rupio_formdata["createSessionRequest"]["fields"][2]["inlined"][
"content"
] = str(self.user_token)
self.rupio_formdata["createSessionRequest"]["fields"][19]["inlined"][
"content"
] = str(self.ssn_token)
self.frontend_upload_id = "web_upload:" + str(self.frontend_upload_id) + ":0"
self.rupio_formdata["createSessionRequest"]["fields"][5]["inlined"][
"content"
] = self.frontend_upload_id
self.rupio_formdata["createSessionRequest"]["fields"][0]["external"][
"filename"
] = file_name
self.rupio_formdata["createSessionRequest"]["fields"][0]["external"][
"size"
] = int(os.stat(file_name).st_size)
self.rupio_formdata["createSessionRequest"]["fields"][10]["inlined"][
"content"
] = self.video_name
self.rupio_formdata["createSessionRequest"]["fields"][18]["inlined"][
"content"
] = self.privacy
self.rupio_formdata["createSessionRequest"]["fields"][11]["inlined"][
"content"
] = self.description
self.rupio_formdata["createSessionRequest"]["fields"][12]["inlined"][
"content"
] = self.tag
def post_rupio(self):
req = self.session.post(
self.rupio_url,
data=json.dumps(self.rupio_formdata),
params={"authuser": "0"},
)
search = req.json()
self.upload_id = search["sessionStatus"]["upload_id"]
print("upload_id -> ", self.upload_id)
def post_creator_suggestions_ajax(self):
print("posting creator sugg ajax")
req = self.session.post(
self.csa_url,
params={"action_video_rules": "1", "location": "LOCATION_UPLOAD"},
data={"session_token": self.ssn_token},
)
print("creator sugg ajax code -> ", req.status_code)
def post_yummyAjax(self):
print("posting yummy_ajax")
yummyajax_req = self.session.post(
self.yummyajax_url,
data={
"action_report": "1",
"event_type": "UPLOAD_INTENT_DRAG_AND_DROP",
"frontend_id": self.frontend_upload_id,
"version": "1",
"filename": self.filename,
"session_token": str(self.ssn_token),
},
)
print("yummy return ->", yummyajax_req.content)
def post_yummyAjaxWithVideoId(self):
yummywith_req = self.session.post(
self.yummyajax_url,
data={
"action_report": "1",
"event_type": "REGISTRATION_INFO_RECEIVED",
"frontend_id": self.frontend_upload_id,
"version": "1",
"video_id": str(self.video_id),
"session_token": str(self.ssn_token),
},
)
print("yummy ajax result -> ", yummywith_req.json())
self.doLastYummyPost()
def doLastListPostYoutubeStat(self):
find_feedback = True
while find_feedback:
last_req = self.session.post(
"https://www.googleapis.com/videofeedback/v1/feedback/list",
data=json.dumps(self.list_payload),
headers={"Content-Type": "application/json"},
)
last_json = last_req.json()
if last_json["items"][0].has_key("feedback"):
if last_json["items"][0]["feedback"].has_key("youtubeStatus"):
find_feedback = False
print(
"Youtube status -> video status : ",
last_json["items"][0]["feedback"]["youtubeStatus"]["videoStatus"],
)
def doListPostWhileFeedBack(self):
find_feedback = True
while find_feedback:
last_req = self.session.post(
"https://www.googleapis.com/videofeedback/v1/feedback/list",
data=json.dumps(self.list_payload),
headers={"Content-Type": "application/json"},
)
last_json = last_req.json()
if last_json.has_key("items"):
if last_json["items"][0].has_key("feedback"):
find_feedback = False
time.sleep(2)
self.doLastYummyPost()
def doLastYummyPost(self):
yummy_with_req = self.session.post(
self.yummyajax_url,
data={
"action_report": "1",
"event_type": "UPLOAD_MESSAGE",
"frontend_id": self.frontend_upload_id,
"version": "1",
"upload_message_key": "HINT_NON_STREAMABLE_MOV",
"transfer_id": "scotty:" + str(self.upload_id),
"video_id": str(self.video_id),
"filename": self.video_name,
"session_token": str(self.ssn_token),
},
)
print("Return ->", yummy_with_req.json()["code"])
self.doLastListPostYoutubeStat()
def doOptions(self):
self.session.options(
"https://www.googleapis.com/videofeedback/v1/feedback/list"
)
time.sleep(0.5)
self.session.options(
"https://upload.youtube.com/",
params={
"authuser": "0",
"upload_id": str(self.upload_id),
"origin": "CidodHRwczovL3VwbG9hZC55b3V0dWJlLmNvbS91cGxvYWQvcnVwaW8SDXZpZGVvLXVwbG9hZHM",
},
)
self.session.post("https://www.googleapis.com/videofeedback/v1/feedback/list")
def postVideo(self):
print("Posting video...")
files = open(self.file_name, "rb")
check_req = self.session.post(
"https://upload.youtube.com",
data=files,
headers={"Content-Type": "application/octet-stream"},
params={
"authuser": "0",
"upload_id": str(self.upload_id),
"origin": "CidodHRwczovL3VwbG9hZC55b3V0dWJlLmNvbS91cGxvYWQvcnVwaW8SDXZpZGVvLXVwbG9hZHM",
},
)
if check_req.json().has_key("sessionStatus"):
print(
"Video posting status ->",
check_req.json()["sessionStatus"]["externalFieldTransfers"][0][
"status"
],
)
print(
"Transfered byte ->",
check_req.json()["sessionStatus"]["externalFieldTransfers"][0][
"bytesTransferred"
],
)
else:
print("Video posting status -> REJECTED")
self.logout()
self.get_videoId()
def setVideoParamaters(self):
print("Sending video parameter")
self.session.get(
self.setvideoparams_url,
params={
"title": self.video_name,
"description": self.description,
"language": "tr",
"privacy": self.privacy,
"tags": self.tag,
"exp_bucket": "747",
"youtube_category": 20,
"want_content_tags": "true",
"user_id": self.get_userId(),
},
)
def setVideoMetaData(
self,
title="video",
description="",
keywords="",
privacy="public",
privacy_draft="none",
still_id="2",
thumbnail_preview_version="",
allow_comments="yes",
allow_comments_detail="all",
allow_rating="yes",
reuse="all_right_reserved",
captions_certificate_reason="",
allow_embedding="yes",
creator_share_feeds="yes",
category="20",
location_longitude="",
location_latitude="",
location_altitude="",
audio_language="",
recorded_date="",
allow_public_stats="yes",
creator_share_gplus="yes",
creator_share_twitter="no",
self_racy="no",
modified_fields="privacy_draft",
):
if self.tag != "":
self.modified_fields = "keywords"
self.session.post(
"https://www.youtube.com/metadata_ajax",
params={"action_edit_video": "1"},
data={
"title": self.video_name,
"description": self.description,
"keywords": self.tag,
"privacy": self.privacy,
"privacy_draft": privacy_draft,
"still_id": still_id,
"thumbnail_preview_version": thumbnail_preview_version,
"allow_comments": allow_comments,
"allow_comments_detail": allow_comments_detail,
"allow_rating": allow_rating,
"reuse": reuse,
"captions_certificate_reason": captions_certificate_reason,
"allow_embedding": allow_embedding,
"creator_share_feeds": creator_share_feeds,
"category": category,
"location_longitude": location_longitude,
"location_latitude": location_latitude,
"location_altitude": location_altitude,
"audio_language": audio_language,
"recorded_date": recorded_date,
"allow_public_stats": allow_public_stats,
"creator_share_gplus": creator_share_gplus,
"creator_share_twitter": creator_share_twitter,
"self_racy": self_racy,
"modified_fields": modified_fields,
"video_id": str(self.video_id),
"session_token": str(self.getSessionToken()),
},
)
def publishVideo(self):
share_req = self.session.post(
"https://www.youtube.com/video_ajax",
params={"action_publish": "1", "o": "U"},
data={"video_id": str(self.video_id), "session_token": str(self.ssn_token)},
)
print("Video is publishing...")
if share_req.json()["success"] is True:
print("Video publishing status -> ", share_req.json()["messages"][0])
else:
print("Video is not published")
def logout(self):
self.session.post(
"https://www.youtube.com/logout",
params={"action_logout": "1", "session_token": str(self.ssn_token)},
)
print("Logout")
y = YoutubeUpload(
"[email protected]",
"xxx",
"video.mp4",
"pythonVideo Upload",
"video",
"private",
"test",
)
y.postVideo()
y.setVideoMetaData()
y.publishVideo()
time.sleep(1)
y.logout()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment