This repository has been archived by the owner on Feb 29, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathmain.py
265 lines (221 loc) · 11.6 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
"""
████████╗██╗██╗ ██╗████████╗ ██████╗ ██╗ ██╗ ████████╗ ██████╗ ██╗ ██╗████████╗
╚══██╔══╝██║██║ ██╔╝╚══██╔══╝██╔═══██╗██║ ██╔╝ ╚══██╔══╝██╔═══██╗ ╚██╗ ██╔╝╚══██╔══╝
██║ ██║█████╔╝ ██║ ██║ ██║█████╔╝ ██║ ██║ ██║ ╚████╔╝ ██║
██║ ██║██╔═██╗ ██║ ██║ ██║██╔═██╗ ██║ ██║ ██║ ╚██╔╝ ██║
██║ ██║██║ ██╗ ██║ ╚██████╔╝██║ ██╗ ██║ ╚██████╔╝ ██║ ██║
╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
By voletro
Downloads a trending TikTok video and uploads it to YouTube. This will happen every half an hour (30 mins).
Requirements:
Firefox - https://www.mozilla.org/en-US/firefox/new/
GeckoDriver - https://github.com/mozilla/geckodriver/releases
Setup:
1. Extract downloaded zip file to a folder. Go to that folder in a terminal.
2. Run "pip install -r requirements.txt" inside the downloaded folder.
3. Sign into YouTube on Firefox with the account you want to upload the videos to.
4. Install the EditThisCookie extension on Firefox, open it, and click the export button to export login cookies to clipboard.
5. Open the file called login.json in a text editor. Paste the exported login cookies into the file and save.
6. Run the main.py script!
Special thanks to these people for making this project possible:
davidteather - TikTokApi - https://github.com/davidteather/TikTok-Api
SeleniumHQ - selenium - https://github.com/SeleniumHQ/selenium
"""
import urllib.request
import os
import logging
from typing import Dict, List
import logging
import re
from datetime import datetime
from time import sleep
import json
from TikTokApi import TikTokApi
from datetime import datetime
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.remote.file_detector import LocalFileDetector
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from random import randint
currentpath = os.getcwd()
def domain_to_url(domain: str) -> str:
if domain.startswith("."):
domain = "www" + domain
return "http://" + domain
def login_using_cookie_file(driver: WebDriver, cookie_file: str):
"""Restore auth cookies from a file. Does not guarantee that the user is logged in afterwards.
Visits the domains specified in the cookies to set them, the previous page is not restored."""
domain_cookies: Dict[str, List[object]] = {}
with open(cookie_file) as file:
cookies: List = json.load(file)
# Sort cookies by domain, because we need to visit to domain to add cookies
for cookie in cookies:
try:
domain_cookies[cookie["domain"]].append(cookie)
except KeyError:
domain_cookies[cookie["domain"]] = [cookie]
for domain, cookies in domain_cookies.items():
driver.get(domain_to_url(domain + "/robots.txt"))
for cookie in cookies:
cookie.pop("sameSite", None) # Attribute should be available in Selenium >4
cookie.pop("storeId", None) # Firefox container attribute
try:
driver.add_cookie(cookie)
except:
print(f"Couldn't set cookie {cookie['name']} for {domain}")
def confirm_logged_in(driver: WebDriver) -> bool:
try:
WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.ID, "avatar-btn")))
return True
except TimeoutError:
return False
def upload_file(
driver: WebDriver,
video_path: str,
title: str,
description: str,
thumbnail_path: str = None,
):
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "ytcp-button#create-icon"))).click()
WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.XPATH, '//tp-yt-paper-item[@test-id="upload-beta"]'))
).click()
video_input = driver.find_element_by_xpath('//input[@type="file"]')
video_input.send_keys(video_path)
_set_basic_settings(driver, title, description, thumbnail_path)
# Go to visibility settings
for i in range(3):
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.ID, "next-button"))).click()
_set_time(driver)
_wait_for_processing(driver)
# Go back to endcard settings
driver.find_element_by_css_selector("#step-badge-1").click()
#_set_endcard(driver)
for _ in range(2):
# Sometimes, the button is clickable but clicking it raises an error, so we add a "safety-sleep" here
sleep(5)
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.ID, "next-button"))).click()
sleep(5)
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.ID, "done-button"))).click()
# Wait for the dialog to disappear
sleep(5)
logging.info("Upload is complete")
driver.quit()
def _wait_for_processing(driver):
# Wait for processing to complete
progress_label: WebElement = driver.find_element_by_css_selector("span.progress-label")
pattern = re.compile(r"(finished processing)|(processing hd.*)|(check.*)")
current_progress = progress_label.get_attribute("textContent")
last_progress = None
while not pattern.match(current_progress.lower()):
if last_progress != current_progress:
logging.info(f'Current progress: {current_progress}')
last_progress = current_progress
sleep(5)
current_progress = progress_label.get_attribute("textContent")
def _set_basic_settings(driver: WebDriver, title: str, description: str, thumbnail_path: str = None):
title_input: WebElement = WebDriverWait(driver, 20).until(
EC.element_to_be_clickable(
(
By.XPATH,
'//ytcp-mention-textbox[@label="Title"]//div[@id="textbox"]',
)
)
)
# Input meta data (title, description, etc ... )
description_input: WebElement = driver.find_element_by_xpath(
'//ytcp-mention-textbox[@label="Description"]//div[@id="textbox"]'
)
thumbnail_input: WebElement = driver.find_element_by_css_selector(
"input#file-loader"
)
title_input.clear()
title_input.send_keys(title)
description_input.send_keys(description)
if thumbnail_path:
thumbnail_input.send_keys(thumbnail_path)
driver.find_element_by_css_selector("#toggle-button").click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable(
(By.NAME, "NOT_MADE_FOR_KIDS")
)).click()
def _set_endcard(driver: WebDriver):
# Add endscreen
driver.find_element_by_css_selector("#endscreens-button").click()
sleep(5)
# Select endcard type from last video or first suggestion if no prev. video
driver.find_element_by_css_selector("div.card:nth-child(1)").click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.ID, "save-button"))).click()
def _set_time(driver: WebDriver):
# Start time scheduling
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, "PUBLIC"))).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.ID, "step-badge-2"))).click()
WebDriverWait(driver, 100).until(EC.presence_of_element_located((By.ID, "results-description")))
copyrightinfo: WebElement = driver.find_element_by_id("results-description")
if "Copyright claim found." in copyrightinfo.text:
driver.close()
else:
print("test")
def main():
api = TikTokApi.get_instance()
trending = api.by_trending(count=1, custom_verifyFp="")
for tiktok in trending:
tvideo = tiktok['video']
link = tvideo['downloadAddr']
author = tiktok['author']
username = author['uniqueId']
id = tiktok['id']
desc = tiktok['desc']
print("Downloading video...")
urllib.request.urlretrieve(link, f'{username}-{id}.mp4')
if len(desc) > 75:
desc = desc[:75]
title = f"{desc} - @{username} - For You"
description = f"Credit to the original creator, @{username}. Check out their other content here: https://tiktok.com/@{username} #shorts"
print("Downloaded video!")
print(title)
print("Starting upload...")
logging.getLogger().setLevel(logging.INFO)
firefox_profile = webdriver.FirefoxProfile()
firefox_profile.set_preference("intl.accept_languages", "en-us")
firefox_profile.update_preferences()
driver = webdriver.Firefox(firefox_profile)
#driver = webdriver.Chrome()
driver.set_window_size(1920, 1080)
login_using_cookie_file(driver, cookie_file='login.json')
driver.get("https://www.youtube.com")
assert "YouTube" in driver.title
try:
confirm_logged_in(driver)
driver.get("https://studio.youtube.com")
assert "Channel dashboard" in driver.title
driver.file_detector = LocalFileDetector()
upload_file(
driver,
video_path=currentpath + f'\{username}-{id}.mp4',
title=title,
description=description,
)
os.remove(f'{username}-{id}.mp4')
except:
driver.close()
raise
os.system('cls' if os.name in ('nt', 'dos') else 'clear')
texttitle = """
████████╗██╗██╗ ██╗████████╗ ██████╗ ██╗ ██╗ ████████╗ ██████╗ ██╗ ██╗████████╗
╚══██╔══╝██║██║ ██╔╝╚══██╔══╝██╔═══██╗██║ ██╔╝ ╚══██╔══╝██╔═══██╗ ╚██╗ ██╔╝╚══██╔══╝
██║ ██║█████╔╝ ██║ ██║ ██║█████╔╝ ██║ ██║ ██║ ╚████╔╝ ██║
██║ ██║██╔═██╗ ██║ ██║ ██║██╔═██╗ ██║ ██║ ██║ ╚██╔╝ ██║
██║ ██║██║ ██╗ ██║ ╚██████╔╝██║ ██╗ ██║ ╚██████╔╝ ██║ ██║
╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
"""
print(texttitle)
while True:
main()
print("Finished upload.")
print("Waiting for next upload.")
sleep(1800)