tiktokautouploader 4.0__py2.py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- tiktokautouploader/Js_assets/login.js +40 -0
- tiktokautouploader/Js_assets/package.json +12 -0
- tiktokautouploader/__init__.py +3 -0
- tiktokautouploader/function.py +857 -0
- tiktokautouploader-4.0.dist-info/METADATA +152 -0
- tiktokautouploader-4.0.dist-info/RECORD +8 -0
- tiktokautouploader-4.0.dist-info/WHEEL +5 -0
- tiktokautouploader-4.0.dist-info/licenses/LICENSE.md +21 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
const { chromium } = require('playwright-extra')
|
2
|
+
|
3
|
+
|
4
|
+
const stealth = require('puppeteer-extra-plugin-stealth')()
|
5
|
+
|
6
|
+
chromium.use(stealth)
|
7
|
+
|
8
|
+
|
9
|
+
function sleep(time) {
|
10
|
+
return new Promise(resolve => setTimeout(resolve, time));
|
11
|
+
}
|
12
|
+
|
13
|
+
|
14
|
+
async function checkForRedirect(page) {
|
15
|
+
const currentUrl = page.url();
|
16
|
+
const pattern = /^https:\/\/www\.tiktok\.com\/foryou/;
|
17
|
+
return pattern.test(currentUrl);
|
18
|
+
}
|
19
|
+
|
20
|
+
(async () => {
|
21
|
+
let redirected = false;
|
22
|
+
const browser = await chromium.launch({ headless: false });
|
23
|
+
const page = await browser.newPage();
|
24
|
+
await page.goto('https://www.tiktok.com/login');
|
25
|
+
|
26
|
+
while (!redirected) {
|
27
|
+
redirected = await checkForRedirect(page);
|
28
|
+
if (!redirected) {
|
29
|
+
await sleep(1000);
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
sleep(2000)
|
34
|
+
const cookies = await page.context().cookies();
|
35
|
+
const fs = require('fs');
|
36
|
+
fs.writeFileSync('TK_cookies.json', JSON.stringify(cookies, null, 2));
|
37
|
+
|
38
|
+
|
39
|
+
await browser.close();
|
40
|
+
})();
|
@@ -0,0 +1,12 @@
|
|
1
|
+
{
|
2
|
+
"name": "tiktokautouploader-assets",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"scripts": {
|
5
|
+
"postinstall": "npx playwright install chromium"
|
6
|
+
},
|
7
|
+
"dependencies": {
|
8
|
+
"playwright": "^1.48.2",
|
9
|
+
"playwright-extra": "^4.3.6",
|
10
|
+
"puppeteer-extra-plugin-stealth": "^2.11.2"
|
11
|
+
}
|
12
|
+
}
|
@@ -0,0 +1,857 @@
|
|
1
|
+
from playwright.sync_api import sync_playwright
|
2
|
+
import json
|
3
|
+
import time
|
4
|
+
import subprocess
|
5
|
+
from inference_sdk import InferenceHTTPClient
|
6
|
+
import pkg_resources
|
7
|
+
import requests
|
8
|
+
from PIL import Image
|
9
|
+
import sys
|
10
|
+
import os
|
11
|
+
import warnings
|
12
|
+
warnings.simplefilter("ignore")
|
13
|
+
|
14
|
+
|
15
|
+
def check_for_updates():
|
16
|
+
current_version = pkg_resources.get_distribution("tiktokautouploader").version
|
17
|
+
response = requests.get("https://pypi.org/pypi/tiktokautouploader/json")
|
18
|
+
|
19
|
+
if response.status_code == 200:
|
20
|
+
latest_version = response.json()["info"]["version"]
|
21
|
+
if current_version != latest_version:
|
22
|
+
print(f"WARNING: You are using version {current_version} of tiktokautouploader, "
|
23
|
+
f"PLEASE UPDATE TO LATEST VERSION {latest_version} FOR BEST EXPERIENCE.")
|
24
|
+
|
25
|
+
def login_warning(accountname):
|
26
|
+
print(f"NO COOKIES FILE FOUND FOR ACCOUNT {accountname}, PLEASE LOG-IN TO {accountname} WHEN PROMPTED")
|
27
|
+
|
28
|
+
def save_cookies(cookies):
|
29
|
+
with open('TK_cookies.json', 'w') as file:
|
30
|
+
json.dump(cookies, file, indent=4)
|
31
|
+
|
32
|
+
def check_expiry(accountname):
|
33
|
+
with open(f'TK_cookies_{accountname}.json', 'r') as file:
|
34
|
+
cookies = json.load(file)
|
35
|
+
|
36
|
+
current_time = int(time.time())
|
37
|
+
cookies_expire = []
|
38
|
+
expired = False
|
39
|
+
for cookie in cookies:
|
40
|
+
if cookie['name'] in ['sessionid', 'sid_tt', 'sessionid_ss', 'passport_auth_status']:
|
41
|
+
expiry = cookie.get('expires')
|
42
|
+
cookies_expire.append(expiry < current_time)
|
43
|
+
|
44
|
+
if all(cookies_expire):
|
45
|
+
expired = True
|
46
|
+
|
47
|
+
return expired
|
48
|
+
|
49
|
+
def run_javascript():
|
50
|
+
js_file_path = pkg_resources.resource_filename(__name__, 'Js_assets/login.js')
|
51
|
+
result = subprocess.run(['node', js_file_path], capture_output=True, text=True)
|
52
|
+
return result
|
53
|
+
|
54
|
+
def install_js_dependencies():
|
55
|
+
js_dir = pkg_resources.resource_filename(__name__, 'Js_assets')
|
56
|
+
node_modules_path = os.path.join(js_dir, 'node_modules')
|
57
|
+
|
58
|
+
if not os.path.exists(node_modules_path):
|
59
|
+
print("JavaScript dependencies not found. Installing...")
|
60
|
+
try:
|
61
|
+
subprocess.run(['npm', 'install', '--silent'], cwd=js_dir, check=True)
|
62
|
+
except subprocess.CalledProcessError as e:
|
63
|
+
print("An error occurred during npm installation.")
|
64
|
+
print(f"Error details: {e}")
|
65
|
+
else:
|
66
|
+
time.sleep(0.1)
|
67
|
+
|
68
|
+
|
69
|
+
def read_cookies(cookies_path):
|
70
|
+
cookie_read = False
|
71
|
+
try:
|
72
|
+
with open(cookies_path , 'r') as cookiefile:
|
73
|
+
cookies = json.load(cookiefile)
|
74
|
+
|
75
|
+
for cookie in cookies:
|
76
|
+
if cookie.get('sameSite') not in ['Strict', 'Lax', 'None']:
|
77
|
+
cookie['sameSite'] = 'Lax'
|
78
|
+
|
79
|
+
cookie_read = True
|
80
|
+
except:
|
81
|
+
sys.exit("ERROR: CANT READ COOKIES FILE")
|
82
|
+
|
83
|
+
return cookies, cookie_read
|
84
|
+
|
85
|
+
def detect_redirect(page):
|
86
|
+
redirect_detected = False
|
87
|
+
|
88
|
+
def on_response(response):
|
89
|
+
nonlocal redirect_detected
|
90
|
+
if response.request.redirected_from:
|
91
|
+
redirect_detected = True
|
92
|
+
|
93
|
+
page.on('response', on_response)
|
94
|
+
|
95
|
+
return redirect_detected
|
96
|
+
|
97
|
+
def understood_Qs(question):
|
98
|
+
understood_terms = {
|
99
|
+
'touchdowns' : 'football',
|
100
|
+
'orange and round': 'basketball',
|
101
|
+
'used in hoops': 'basketball',
|
102
|
+
'has strings': 'guitar',
|
103
|
+
'oval and inflatable': 'football',
|
104
|
+
'strumming': 'guitar',
|
105
|
+
'bounces': 'basketball',
|
106
|
+
'musical instrument': 'guitar',
|
107
|
+
'laces': 'football',
|
108
|
+
'bands': 'guitar',
|
109
|
+
'leather': 'football',
|
110
|
+
'leaves':'tree',
|
111
|
+
'pages': 'book',
|
112
|
+
'throwing': 'football',
|
113
|
+
'tossed in a spiral': 'football',
|
114
|
+
'spiky crown': 'pineapple',
|
115
|
+
'pigskin': 'football',
|
116
|
+
'photography': 'camera',
|
117
|
+
'lens': 'camera',
|
118
|
+
'grow': 'tree',
|
119
|
+
'captures images': 'camera',
|
120
|
+
'keeps doctors': 'apple',
|
121
|
+
'crown': 'pineapple',
|
122
|
+
'driven': 'car',
|
123
|
+
}
|
124
|
+
|
125
|
+
for key in understood_terms.keys():
|
126
|
+
if key in question:
|
127
|
+
item = understood_terms.get(key)
|
128
|
+
return item
|
129
|
+
|
130
|
+
return 'N.A'
|
131
|
+
|
132
|
+
|
133
|
+
|
134
|
+
def get_image_src(page):
|
135
|
+
image_url = page.get_attribute("img#captcha-verify-image", "src")
|
136
|
+
return image_url
|
137
|
+
|
138
|
+
def download_image(image_url):
|
139
|
+
response = requests.get(image_url)
|
140
|
+
image_path = "captcha_image.jpg"
|
141
|
+
with open(image_path, "wb") as f:
|
142
|
+
f.write(response.content)
|
143
|
+
return image_path
|
144
|
+
|
145
|
+
def run_inference_on_image_tougher(image_path, object):
|
146
|
+
|
147
|
+
k = 'n|KIeDZnRZiJ};iVHz;R'
|
148
|
+
rk = ''.join(chr((ord(c) - 3) % 256) for c in k)
|
149
|
+
|
150
|
+
CLIENT = InferenceHTTPClient(
|
151
|
+
api_url="https://detect.roboflow.com",
|
152
|
+
api_key=f"{rk}"
|
153
|
+
)
|
154
|
+
|
155
|
+
results = CLIENT.infer(image_path, model_id="captcha-2-6ehbe/2")
|
156
|
+
|
157
|
+
class_names = []
|
158
|
+
bounding_boxes = []
|
159
|
+
for obj in results['predictions']:
|
160
|
+
class_names.append(obj['class'])
|
161
|
+
bounding_boxes.append({
|
162
|
+
"x": obj['x'],
|
163
|
+
"y": obj['y'],
|
164
|
+
"width": obj['width'],
|
165
|
+
"height": obj['height']
|
166
|
+
})
|
167
|
+
|
168
|
+
bounding_box = []
|
169
|
+
class_to_click = object
|
170
|
+
for i, classes in enumerate(class_names):
|
171
|
+
if classes == class_to_click:
|
172
|
+
bounding_box.append(bounding_boxes[i])
|
173
|
+
|
174
|
+
|
175
|
+
|
176
|
+
return bounding_box
|
177
|
+
|
178
|
+
def run_inference_on_image(image_path):
|
179
|
+
|
180
|
+
k = 'n|KIeDZnRZiJ};iVHz;R'
|
181
|
+
rk = ''.join(chr((ord(c) - 3) % 256) for c in k)
|
182
|
+
|
183
|
+
CLIENT = InferenceHTTPClient(
|
184
|
+
api_url="https://detect.roboflow.com",
|
185
|
+
api_key=f"{rk}"
|
186
|
+
)
|
187
|
+
|
188
|
+
results = CLIENT.infer(image_path, model_id="tk-3nwi9/2")
|
189
|
+
|
190
|
+
class_names = []
|
191
|
+
bounding_boxes = []
|
192
|
+
for obj in results['predictions']:
|
193
|
+
class_names.append(obj['class'])
|
194
|
+
bounding_boxes.append({
|
195
|
+
"x": obj['x'],
|
196
|
+
"y": obj['y'],
|
197
|
+
"width": obj['width'],
|
198
|
+
"height": obj['height']
|
199
|
+
})
|
200
|
+
|
201
|
+
already_written = []
|
202
|
+
bounding_box = []
|
203
|
+
class_to_click = []
|
204
|
+
for i, detected_class in enumerate(class_names):
|
205
|
+
if detected_class in already_written:
|
206
|
+
class_to_click.append(detected_class)
|
207
|
+
bounding_box.append(bounding_boxes[i])
|
208
|
+
index = already_written.index(detected_class)
|
209
|
+
bounding_box.append(bounding_boxes[index])
|
210
|
+
|
211
|
+
already_written.append(detected_class)
|
212
|
+
|
213
|
+
found = False
|
214
|
+
if len(class_to_click) == 1:
|
215
|
+
found = True
|
216
|
+
|
217
|
+
return bounding_box, found
|
218
|
+
|
219
|
+
def convert_to_webpage_coordinates(bounding_boxes, image_x, image_y, image_height_web, image_width_web, image_height_real, image_width_real):
|
220
|
+
|
221
|
+
webpage_coordinates = []
|
222
|
+
for box in bounding_boxes:
|
223
|
+
x_box = box['x']
|
224
|
+
y_box = box['y']
|
225
|
+
rel_x = (x_box * image_width_web) / image_width_real
|
226
|
+
rel_y = (y_box * image_height_web) / image_height_real
|
227
|
+
x_cord = image_x + rel_x
|
228
|
+
y_cord = image_y + rel_y
|
229
|
+
|
230
|
+
webpage_coordinates.append((x_cord, y_cord))
|
231
|
+
|
232
|
+
return webpage_coordinates
|
233
|
+
|
234
|
+
def click_on_objects(page, object_coords):
|
235
|
+
for (x, y) in object_coords:
|
236
|
+
page.mouse.click(x, y)
|
237
|
+
time.sleep(0.5)
|
238
|
+
|
239
|
+
|
240
|
+
|
241
|
+
def upload_tiktok(video, description, accountname, hashtags=None, sound_name=None, sound_aud_vol='mix', schedule=None, day=None, copyrightcheck=False, suppressprint=False, headless=True, stealth=False):
|
242
|
+
|
243
|
+
"""
|
244
|
+
UPLOADS VIDEO TO TIKTOK
|
245
|
+
------------------------------------------------------------------------------------------------------------------------------------------------c
|
246
|
+
video (str) -> path to video to upload
|
247
|
+
description (str) -> description for video
|
248
|
+
accountname (str) -> account to upload on
|
249
|
+
hashtags (str)(array) -> hashtags for video
|
250
|
+
sound_name (str) -> name of tik tok sound to use for video
|
251
|
+
sound_aud_vol (str) -> volume of tik tok sound, 'main', 'mix' or 'background', check documentation for more info -> https://github.com/haziq-exe/TikTokAutoUploader
|
252
|
+
schedule (str) -> format HH:MM, your local time to upload video
|
253
|
+
day (int) -> day to schedule video for, check documentation for more info -> https://github.com/haziq-exe/TikTokAutoUploader
|
254
|
+
copyrightcheck (bool) -> include copyright check or not; CODE FAILS IF FAIL COPYRIGHT CHECK
|
255
|
+
suppressprint (bool) -> True means function doesnt print anything to provide updates on progress
|
256
|
+
headless (bool) -> run in headless mode or not
|
257
|
+
stealth (bool) -> will wait second(s) before each operation
|
258
|
+
--------------------------------------------------------------------------------------------------------------------------------------------
|
259
|
+
"""
|
260
|
+
try:
|
261
|
+
check_for_updates()
|
262
|
+
except:
|
263
|
+
time.sleep(0.1)
|
264
|
+
|
265
|
+
retries = 0
|
266
|
+
cookie_read = False
|
267
|
+
oldQ = 'N.A'
|
268
|
+
|
269
|
+
if accountname == None:
|
270
|
+
sys.exit("PLEASE ENTER NAME OF ACCOUNT TO POST ON, READ DOCUMENTATION FOR MORE INFO")
|
271
|
+
|
272
|
+
if os.path.exists(f'TK_cookies_{accountname}.json'):
|
273
|
+
cookies, cookie_read = read_cookies(cookies_path=f'TK_cookies_{accountname}.json')
|
274
|
+
expired = check_expiry(accountname=accountname)
|
275
|
+
if expired == True:
|
276
|
+
os.remove(f'TK_cookies_{accountname}.json')
|
277
|
+
print(f"COOKIES EXPIRED FOR ACCOUNT {accountname}, PLEASE LOG-IN AGAIN")
|
278
|
+
cookie_read = False
|
279
|
+
|
280
|
+
if cookie_read == False:
|
281
|
+
install_js_dependencies()
|
282
|
+
login_warning(accountname=accountname)
|
283
|
+
result = run_javascript()
|
284
|
+
os.rename('TK_cookies.json', f'TK_cookies_{accountname}.json')
|
285
|
+
|
286
|
+
cookies, cookie_read = read_cookies(f"TK_cookies_{accountname}.json")
|
287
|
+
if cookie_read == False:
|
288
|
+
sys.exit("ERROR READING COOKIES")
|
289
|
+
|
290
|
+
|
291
|
+
with sync_playwright() as p:
|
292
|
+
|
293
|
+
browser = p.firefox.launch(headless=headless)
|
294
|
+
context = browser.new_context()
|
295
|
+
context.add_cookies(cookies)
|
296
|
+
page = context.new_page()
|
297
|
+
url = 'https://www.tiktok.com/tiktokstudio/upload?from=upload&lang=en'
|
298
|
+
|
299
|
+
if suppressprint == False:
|
300
|
+
print(f"Uploading to account '{accountname}'")
|
301
|
+
|
302
|
+
while retries < 2:
|
303
|
+
try:
|
304
|
+
page.goto(url, timeout=30000)
|
305
|
+
except:
|
306
|
+
retries +=1
|
307
|
+
time.sleep(5)
|
308
|
+
if retries == 2:
|
309
|
+
sys.exit("ERROR: TIK TOK PAGE FAILED TO LOAD, try again.")
|
310
|
+
else:
|
311
|
+
break
|
312
|
+
|
313
|
+
detected = False
|
314
|
+
captcha = False
|
315
|
+
while detected == False:
|
316
|
+
if page.locator('.upload-text-container').is_visible():
|
317
|
+
detected = True
|
318
|
+
else:
|
319
|
+
if page.locator('div.VerifyBar___StyledDiv-sc-12zaxoy-0.hRJhHT').is_visible():
|
320
|
+
detected = True
|
321
|
+
captcha = True
|
322
|
+
else:
|
323
|
+
time.sleep(0.1)
|
324
|
+
|
325
|
+
if captcha == True:
|
326
|
+
image = get_image_src(page)
|
327
|
+
if image:
|
328
|
+
if suppressprint == False:
|
329
|
+
print("CAPTCHA DETECTED, Attempting to solve")
|
330
|
+
solved = False
|
331
|
+
attempts = 0
|
332
|
+
question = page.locator('div.VerifyBar___StyledDiv-sc-12zaxoy-0.hRJhHT').text_content()
|
333
|
+
while solved == False:
|
334
|
+
attempts += 1
|
335
|
+
start_time = time.time()
|
336
|
+
while question == oldQ:
|
337
|
+
question = page.locator('div.VerifyBar___StyledDiv-sc-12zaxoy-0.hRJhHT').text_content()
|
338
|
+
if time.time() - start_time > 2:
|
339
|
+
break
|
340
|
+
if 'Select 2 objects that are the same' in question or 'Select two objects that are the same' in question:
|
341
|
+
found = False
|
342
|
+
while found == False:
|
343
|
+
page.click('span.secsdk_captcha_refresh--text')
|
344
|
+
image = get_image_src(page)
|
345
|
+
img_path = download_image(image)
|
346
|
+
b_box, found = run_inference_on_image(image_path=img_path)
|
347
|
+
|
348
|
+
with Image.open(img_path) as img:
|
349
|
+
image_size = img.size
|
350
|
+
|
351
|
+
imageweb = page.locator('#captcha-verify-image')
|
352
|
+
imageweb.wait_for()
|
353
|
+
box = imageweb.bounding_box()
|
354
|
+
image_x = box['x']
|
355
|
+
image_y = box['y']
|
356
|
+
image_height_web = box['height']
|
357
|
+
image_width_web = box['width']
|
358
|
+
image_width_real, image_height_real = image_size
|
359
|
+
|
360
|
+
webpage_coords = convert_to_webpage_coordinates(b_box, image_x, image_y, image_height_web, image_width_web, image_height_real, image_width_real)
|
361
|
+
if not webpage_coords:
|
362
|
+
webpage_coords.append((image_x + 50, image_y + 50))
|
363
|
+
click_on_objects(page, webpage_coords)
|
364
|
+
page.click("div.verify-captcha-submit-button")
|
365
|
+
time.sleep(0.5)
|
366
|
+
if attempts > 5:
|
367
|
+
sys.exit("FAILED TO SOLVE CAPTCHA")
|
368
|
+
while showedup == False:
|
369
|
+
if page.locator("div.captcha_verify_message.captcha_verify_message-pass").is_visible():
|
370
|
+
solved = True
|
371
|
+
showedup = True
|
372
|
+
os.remove('captcha_image.jpg')
|
373
|
+
if page.locator("div.captcha_verify_message.captcha_verify_message-fail").is_visible():
|
374
|
+
showedup = True
|
375
|
+
oldQ = question
|
376
|
+
page.click('span.secsdk_captcha_refresh--text')
|
377
|
+
else:
|
378
|
+
objectclick = understood_Qs(question)
|
379
|
+
while objectclick == 'N.A':
|
380
|
+
oldQ = question
|
381
|
+
page.click('span.secsdk_captcha_refresh--text')
|
382
|
+
start_time = time.time()
|
383
|
+
runs = 0
|
384
|
+
while question == oldQ:
|
385
|
+
runs += 1
|
386
|
+
question = page.locator('div.VerifyBar___StyledDiv-sc-12zaxoy-0.hRJhHT').text_content()
|
387
|
+
if runs > 1:
|
388
|
+
time.sleep(1)
|
389
|
+
if time.time() - start_time > 2:
|
390
|
+
break
|
391
|
+
objectclick = understood_Qs(question)
|
392
|
+
image = get_image_src(page)
|
393
|
+
img_path = download_image(image)
|
394
|
+
b_box = run_inference_on_image_tougher(image_path=img_path, object=objectclick)
|
395
|
+
|
396
|
+
with Image.open(img_path) as img:
|
397
|
+
image_size = img.size
|
398
|
+
|
399
|
+
imageweb = page.locator('#captcha-verify-image')
|
400
|
+
imageweb.wait_for()
|
401
|
+
box = imageweb.bounding_box()
|
402
|
+
image_x = box['x']
|
403
|
+
image_y = box['y']
|
404
|
+
image_height_web = box['height']
|
405
|
+
image_width_web = box['width']
|
406
|
+
image_width_real, image_height_real = image_size
|
407
|
+
|
408
|
+
webpage_coords = convert_to_webpage_coordinates(b_box, image_x, image_y, image_height_web, image_width_web, image_height_real, image_width_real)
|
409
|
+
if not webpage_coords:
|
410
|
+
webpage_coords.append((image_x + 50, image_y + 50))
|
411
|
+
click_on_objects(page, webpage_coords)
|
412
|
+
page.click("div.verify-captcha-submit-button")
|
413
|
+
time.sleep(1)
|
414
|
+
if attempts > 20:
|
415
|
+
sys.exit("FAILED TO SOLVE CAPTCHA")
|
416
|
+
showedup = False
|
417
|
+
while showedup == False:
|
418
|
+
if page.locator("div.captcha_verify_message.captcha_verify_message-pass").is_visible():
|
419
|
+
solved = True
|
420
|
+
showedup = True
|
421
|
+
os.remove('captcha_image.jpg')
|
422
|
+
if suppressprint == False:
|
423
|
+
print("CAPTCHA SOLVED")
|
424
|
+
if page.locator("div.captcha_verify_message.captcha_verify_message-fail").is_visible():
|
425
|
+
showedup = True
|
426
|
+
oldQ = question
|
427
|
+
page.click('span.secsdk_captcha_refresh--text')
|
428
|
+
|
429
|
+
|
430
|
+
try:
|
431
|
+
page.set_input_files('input[type="file"][accept="video/*"]', f'{video}')
|
432
|
+
except:
|
433
|
+
sys.exit("ERROR: FAILED TO INPUT FILE. Possible Issues: Wifi too slow, file directory wrong, or check documentation to see if captcha is solvable")
|
434
|
+
page.wait_for_selector('div[data-contents="true"]')
|
435
|
+
page.click('div[data-contents="true"]')
|
436
|
+
if suppressprint == False:
|
437
|
+
print("Entered File, waiting for tiktok to load onto their server, this may take a couple of minutes, depending on your video length")
|
438
|
+
time.sleep(0.5)
|
439
|
+
if description == None:
|
440
|
+
sys.exit("ERROR: PLEASE INCLUDE A DESCRIPTION")
|
441
|
+
|
442
|
+
for _ in range(len(video) + 2):
|
443
|
+
page.keyboard.press("Backspace")
|
444
|
+
page.keyboard.press("Delete")
|
445
|
+
|
446
|
+
time.sleep(0.5)
|
447
|
+
|
448
|
+
page.keyboard.type(description)
|
449
|
+
|
450
|
+
for _ in range(3):
|
451
|
+
page.keyboard.press("Enter")
|
452
|
+
|
453
|
+
if hashtags != None:
|
454
|
+
for hashtag in hashtags:
|
455
|
+
if hashtag[0] != '#':
|
456
|
+
hashtag = "#" + hashtag
|
457
|
+
|
458
|
+
page.keyboard.type(hashtag)
|
459
|
+
time.sleep(0.5)
|
460
|
+
try:
|
461
|
+
if stealth == True:
|
462
|
+
time.sleep(2)
|
463
|
+
page.click(f'span.hash-tag-topic:has-text("{hashtag}")', timeout=1000)
|
464
|
+
except:
|
465
|
+
try:
|
466
|
+
page.click('span.hash-tag-topic', timeout=1000)
|
467
|
+
except:
|
468
|
+
page.keyboard.press("Backspace")
|
469
|
+
try:
|
470
|
+
page.click('span.hash-tag-topic', timeout=1000)
|
471
|
+
except:
|
472
|
+
if suppressprint == False:
|
473
|
+
print(f"Tik tok hashtag not working for {hashtag}, moving onto next")
|
474
|
+
for _ in range(len(hashtag)):
|
475
|
+
page.keyboard.press("Backspace")
|
476
|
+
|
477
|
+
if suppressprint == False:
|
478
|
+
print("Description and Hashtags added")
|
479
|
+
|
480
|
+
try:
|
481
|
+
page.wait_for_selector('button:has-text("Post")[aria-disabled="false"]', timeout=12000000)
|
482
|
+
except:
|
483
|
+
sys.exit("ERROR: TIK TOK TOOK TOO LONG TO UPLOAD YOUR FILE (>20min). Try again, if issue persists then try a lower file size or different wifi connection")
|
484
|
+
|
485
|
+
time.sleep(0.2)
|
486
|
+
if suppressprint == False:
|
487
|
+
print("Tik tok done loading file onto servers")
|
488
|
+
|
489
|
+
if (schedule == None) and (day != None):
|
490
|
+
sys.exit("ERROR: CANT SCHEDULE FOR ANOTHER DAY USING 'day' WITHOUT ALSO INCLUDING TIME OF UPLOAD WITH 'schedule'; PLEASE ALSO INCLUDE TIME WITH 'schedule' PARAMETER")
|
491
|
+
|
492
|
+
if schedule != None:
|
493
|
+
try:
|
494
|
+
hour = schedule[0:2]
|
495
|
+
minute = schedule[3:]
|
496
|
+
if (int(minute) % 5) != 0:
|
497
|
+
sys.exit("MINUTE FORMAT ERROR: PLEASE MAKE SURE MINUTE YOU SCHEDULE AT IS A MULTIPLE OF 5 UNTIL 60 (i.e: 40), VIDEO SAVED AS DRAFT")
|
498
|
+
|
499
|
+
except:
|
500
|
+
sys.exit("SCHEDULE TIME ERROR: PLEASE MAKE SURE YOUR SCHEDULE TIME IS A STRING THAT FOLLOWS THE 24H FORMAT 'HH:MM', VIDEO SAVED AS DRAFT")
|
501
|
+
|
502
|
+
page.locator('label:has-text("Schedule")').click()
|
503
|
+
if stealth==True:
|
504
|
+
time.sleep(2)
|
505
|
+
visible = False
|
506
|
+
while visible == False:
|
507
|
+
if page.locator('button:has-text("Allow")').nth(0).is_visible():
|
508
|
+
if stealth == True:
|
509
|
+
time.sleep(1)
|
510
|
+
page.locator('button:has-text("Allow")').nth(0).click()
|
511
|
+
visible = True
|
512
|
+
time.sleep(0.1)
|
513
|
+
else:
|
514
|
+
if page.locator('div.TUXTextInputCore-trailingIconWrapper').nth(1).is_visible():
|
515
|
+
visible = True
|
516
|
+
time.sleep(0.1)
|
517
|
+
if day != None:
|
518
|
+
if stealth==True:
|
519
|
+
time.sleep(1)
|
520
|
+
page.locator('div.TUXTextInputCore-leadingIconWrapper:has(svg > path[d="M15 3a1 1 0 0 0-1 1v3h-1.4c-3.36 0-5.04 0-6.32.65a6 6 0 0 0-2.63 2.63C3 11.56 3 13.24 3 16.6v16.8c0 3.36 0 5.04.65 6.32a6 6 0 0 0 2.63 2.63c1.28.65 2.96.65 6.32.65h22.8c3.36 0 5.04 0 6.32-.65a6 6 0 0 0 2.63-2.63c.65-1.28.65-2.96.65-6.32V16.6c0-3.36 0-5.04-.65-6.32a6 6 0 0 0-2.63-2.63C40.44 7 38.76 7 35.4 7H34V4a1 1 0 0 0-1-1h-2a1 1 0 0 0-1 1v3H18V4a1 1 0 0 0-1-1h-2Zm-2.4 8H14v3a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1v-3h12v3a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1v-3h1.4c1.75 0 2.82 0 3.62.07a5.11 5.11 0 0 1 .86.14h.03a2 2 0 0 1 .88.91 5.11 5.11 0 0 1 .14.86c.07.8.07 1.87.07 3.62v1.9H7v-1.9c0-1.75 0-2.82.07-3.62a5.12 5.12 0 0 1 .14-.86v-.03a2 2 0 0 1 .88-.87l.03-.01a5.11 5.11 0 0 1 .86-.14c.8-.07 1.87-.07 3.62-.07ZM7 22.5h34v10.9c0 1.75 0 2.82-.07 3.62a5.11 5.11 0 0 1-.14.86v.03a2 2 0 0 1-.88.87l-.03.01a5.11 5.11 0 0 1-.86.14c-.8.07-1.87.07-3.62.07H12.6c-1.75 0-2.82 0-3.62-.07a5.11 5.11 0 0 1-.89-.15 2 2 0 0 1-.87-.87l-.01-.03a5.12 5.12 0 0 1-.14-.86C7 36.22 7 35.15 7 33.4V22.5Z"])').click()
|
521
|
+
time.sleep(0.2)
|
522
|
+
try:
|
523
|
+
if stealth==True:
|
524
|
+
time.sleep(1)
|
525
|
+
page.locator(f'span.day.valid:text-is("{day}")').click()
|
526
|
+
except:
|
527
|
+
sys.exit("SCHEDULE DAY ERROR: ERROR WITH SCHEDULED DAY, read documentation for more information on format of day")
|
528
|
+
try:
|
529
|
+
time.sleep(0.2)
|
530
|
+
page.locator('div.TUXTextInputCore-leadingIconWrapper:has(svg > path[d="M24 2a22 22 0 1 0 0 44 22 22 0 0 0 0-44ZM6 24a18 18 0 1 1 36 0 18 18 0 0 1-36 0Z"])').click()
|
531
|
+
time.sleep(0.2)
|
532
|
+
page.locator(f'.tiktok-timepicker-option-text.tiktok-timepicker-right:text-is("{minute}")').scroll_into_view_if_needed()
|
533
|
+
time.sleep(0.2)
|
534
|
+
if stealth==True:
|
535
|
+
time.sleep(2)
|
536
|
+
page.locator(f'.tiktok-timepicker-option-text.tiktok-timepicker-right:text-is("{minute}")').click()
|
537
|
+
time.sleep(0.2)
|
538
|
+
if page.locator("div.tiktok-timepicker-time-picker-container").is_visible():
|
539
|
+
time.sleep(0.1)
|
540
|
+
else:
|
541
|
+
page.locator('div.TUXTextInputCore-leadingIconWrapper:has(svg > path[d="M24 2a22 22 0 1 0 0 44 22 22 0 0 0 0-44ZM6 24a18 18 0 1 1 36 0 18 18 0 0 1-36 0Z"])').click()
|
542
|
+
page.locator(f'.tiktok-timepicker-option-text.tiktok-timepicker-left:text-is("{hour}")').scroll_into_view_if_needed()
|
543
|
+
if stealth == True:
|
544
|
+
time.sleep(2)
|
545
|
+
page.locator(f'.tiktok-timepicker-option-text.tiktok-timepicker-left:text-is("{hour}")').click()
|
546
|
+
time.sleep(1)
|
547
|
+
|
548
|
+
if suppressprint == False:
|
549
|
+
print("Done scheduling video")
|
550
|
+
|
551
|
+
except:
|
552
|
+
sys.exit("SCHEDULING ERROR: VIDEO SAVED AS DRAFT")
|
553
|
+
|
554
|
+
sound_fail = False
|
555
|
+
if sound_name != None:
|
556
|
+
try:
|
557
|
+
if stealth == True:
|
558
|
+
time.sleep(2)
|
559
|
+
page.click("div.TUXButton-label:has-text('Edit video')")
|
560
|
+
except:
|
561
|
+
sound_fail = True
|
562
|
+
if sound_fail == False:
|
563
|
+
page.wait_for_selector("input.search-bar-input")
|
564
|
+
page.fill(f"input.search-bar-input", f"{sound_name}")
|
565
|
+
time.sleep(0.2)
|
566
|
+
if stealth == True:
|
567
|
+
time.sleep(2)
|
568
|
+
page.click("div.TUXButton-label:has-text('Search')")
|
569
|
+
try:
|
570
|
+
page.wait_for_selector('div.music-card-container')
|
571
|
+
if stealth == True:
|
572
|
+
time.sleep(0.5)
|
573
|
+
page.click("div.music-card-container")
|
574
|
+
page.wait_for_selector("div.TUXButton-label:has-text('Use')")
|
575
|
+
if stealth == True:
|
576
|
+
time.sleep(1)
|
577
|
+
page.click("div.TUXButton-label:has-text('Use')")
|
578
|
+
except:
|
579
|
+
sys.exit(f"ERROR: SOUND '{sound_name}' NOT FOUND")
|
580
|
+
try:
|
581
|
+
page.wait_for_selector('img[src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMSAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTAgNy41MDE2QzAgNi42NzMxNyAwLjY3MTU3MyA2LjAwMTYgMS41IDYuMDAxNkgzLjU3NzA5QzMuODY4MDUgNi4wMDE2IDQuMTQ0NTggNS44NzQ4OCA0LjMzNDU1IDUuNjU0NDlMOC43NDI1NSAwLjU0MDUyQzkuMzQ3OCAtMC4xNjE2NjggMTAuNSAwLjI2NjM3NCAxMC41IDEuMTkzNDFWMTguOTY3MkMxMC41IDE5Ljg3NDUgOS4zODg5NCAyMC4zMTI5IDguNzY5NDIgMTkuNjVMNC4zMzE3OSAxNC45MDIxQzQuMTQyNjkgMTQuNjk5OCAzLjg3ODE2IDE0LjU4NDkgMy42MDEyMiAxNC41ODQ5SDEuNUMwLjY3MTU3MyAxNC41ODQ5IDAgMTMuOTEzNCAwIDEzLjA4NDlWNy41MDE2Wk01Ljg0OTQ1IDYuOTYwMjdDNS4yNzk1NiA3LjYyMTQzIDQuNDQ5OTcgOC4wMDE2IDMuNTc3MDkgOC4wMDE2SDJWMTIuNTg0OUgzLjYwMTIyQzQuNDMyMDMgMTIuNTg0OSA1LjIyNTY0IDEyLjkyOTUgNS43OTI5NSAxMy41MzY0TDguNSAxNi40MzI4VjMuODg1MjJMNS44NDk0NSA2Ljk2MDI3WiIgZmlsbD0iIzE2MTgyMyIgZmlsbC1vcGFjaXR5PSIwLjYiLz4KPHBhdGggZD0iTTEzLjUxNSA3LjE5MTE5QzEzLjM0MjQgNi45NzU1OSAxMy4zMzk5IDYuNjYwNTYgMTMuNTM1MiA2LjQ2NTNMMTQuMjQyMyA1Ljc1ODE5QzE0LjQzNzYgNS41NjI5MyAxNC43NTU4IDUuNTYxNzUgMTQuOTM1NiA1Ljc3MTM2QzE2Ljk5NTkgOC4xNzM2MiAxNi45OTU5IDExLjgyOCAxNC45MzU2IDE0LjIzMDNDMTQuNzU1OCAxNC40Mzk5IDE0LjQzNzYgMTQuNDM4NyAxNC4yNDIzIDE0LjI0MzVMMTMuNTM1MiAxMy41MzY0QzEzLjMzOTkgMTMuMzQxMSAxMy4zNDI0IDEzLjAyNjEgMTMuNTE1IDEyLjgxMDVDMTQuODEzIDExLjE4ODUgMTQuODEzIDguODEzMTIgMTMuNTE1IDcuMTkxMTlaIiBmaWxsPSIjMTYxODIzIiBmaWxsLW9wYWNpdHk9IjAuNiIvPgo8cGF0aCBkPSJNMTYuNzE3MiAxNi43MTgzQzE2LjUyMTkgMTYuNTIzMSAxNi41MjMxIDE2LjIwNzQgMTYuNzA3MiAxNi4wMDE3QzE5LjcyNTcgMTIuNjMgMTkuNzI1NyA3LjM3MTY4IDE2LjcwNzIgNC4wMDAwMUMxNi41MjMxIDMuNzk0MjcgMTYuNTIxOSAzLjQ3ODU4IDE2LjcxNzIgMy4yODMzMkwxNy40MjQzIDIuNTc2MjFDMTcuNjE5NSAyLjM4MDk1IDE3LjkzNyAyLjM4MDIgMTguMTIzMyAyLjU4NDA4QzIxLjkwOTkgNi43MjkyNiAyMS45MDk5IDEzLjI3MjQgMTguMTIzMyAxNy40MTc2QzE3LjkzNyAxNy42MjE1IDE3LjYxOTUgMTcuNjIwNyAxNy40MjQzIDE3LjQyNTVMMTYuNzE3MiAxNi43MTgzWiIgZmlsbD0iIzE2MTgyMyIgZmlsbC1vcGFjaXR5PSIwLjYiLz4KPC9zdmc+Cg=="]')
|
582
|
+
if stealth == True:
|
583
|
+
time.sleep(1)
|
584
|
+
page.click('img[src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMSAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTAgNy41MDE2QzAgNi42NzMxNyAwLjY3MTU3MyA2LjAwMTYgMS41IDYuMDAxNkgzLjU3NzA5QzMuODY4MDUgNi4wMDE2IDQuMTQ0NTggNS44NzQ4OCA0LjMzNDU1IDUuNjU0NDlMOC43NDI1NSAwLjU0MDUyQzkuMzQ3OCAtMC4xNjE2NjggMTAuNSAwLjI2NjM3NCAxMC41IDEuMTkzNDFWMTguOTY3MkMxMC41IDE5Ljg3NDUgOS4zODg5NCAyMC4zMTI5IDguNzY5NDIgMTkuNjVMNC4zMzE3OSAxNC45MDIxQzQuMTQyNjkgMTQuNjk5OCAzLjg3ODE2IDE0LjU4NDkgMy42MDEyMiAxNC41ODQ5SDEuNUMwLjY3MTU3MyAxNC41ODQ5IDAgMTMuOTEzNCAwIDEzLjA4NDlWNy41MDE2Wk01Ljg0OTQ1IDYuOTYwMjdDNS4yNzk1NiA3LjYyMTQzIDQuNDQ5OTcgOC4wMDE2IDMuNTc3MDkgOC4wMDE2SDJWMTIuNTg0OUgzLjYwMTIyQzQuNDMyMDMgMTIuNTg0OSA1LjIyNTY0IDEyLjkyOTUgNS43OTI5NSAxMy41MzY0TDguNSAxNi40MzI4VjMuODg1MjJMNS44NDk0NSA2Ljk2MDI3WiIgZmlsbD0iIzE2MTgyMyIgZmlsbC1vcGFjaXR5PSIwLjYiLz4KPHBhdGggZD0iTTEzLjUxNSA3LjE5MTE5QzEzLjM0MjQgNi45NzU1OSAxMy4zMzk5IDYuNjYwNTYgMTMuNTM1MiA2LjQ2NTNMMTQuMjQyMyA1Ljc1ODE5QzE0LjQzNzYgNS41NjI5MyAxNC43NTU4IDUuNTYxNzUgMTQuOTM1NiA1Ljc3MTM2QzE2Ljk5NTkgOC4xNzM2MiAxNi45OTU5IDExLjgyOCAxNC45MzU2IDE0LjIzMDNDMTQuNzU1OCAxNC40Mzk5IDE0LjQzNzYgMTQuNDM4NyAxNC4yNDIzIDE0LjI0MzVMMTMuNTM1MiAxMy41MzY0QzEzLjMzOTkgMTMuMzQxMSAxMy4zNDI0IDEzLjAyNjEgMTMuNTE1IDEyLjgxMDVDMTQuODEzIDExLjE4ODUgMTQuODEzIDguODEzMTIgMTMuNTE1IDcuMTkxMTlaIiBmaWxsPSIjMTYxODIzIiBmaWxsLW9wYWNpdHk9IjAuNiIvPgo8cGF0aCBkPSJNMTYuNzE3MiAxNi43MTgzQzE2LjUyMTkgMTYuNTIzMSAxNi41MjMxIDE2LjIwNzQgMTYuNzA3MiAxNi4wMDE3QzE5LjcyNTcgMTIuNjMgMTkuNzI1NyA3LjM3MTY4IDE2LjcwNzIgNC4wMDAwMUMxNi41MjMxIDMuNzk0MjcgMTYuNTIxOSAzLjQ3ODU4IDE2LjcxNzIgMy4yODMzMkwxNy40MjQzIDIuNTc2MjFDMTcuNjE5NSAyLjM4MDk1IDE3LjkzNyAyLjM4MDIgMTguMTIzMyAyLjU4NDA4QzIxLjkwOTkgNi43MjkyNiAyMS45MDk5IDEzLjI3MjQgMTguMTIzMyAxNy40MTc2QzE3LjkzNyAxNy42MjE1IDE3LjYxOTUgMTcuNjIwNyAxNy40MjQzIDE3LjQyNTVMMTYuNzE3MiAxNi43MTgzWiIgZmlsbD0iIzE2MTgyMyIgZmlsbC1vcGFjaXR5PSIwLjYiLz4KPC9zdmc+Cg=="]')
|
585
|
+
time.sleep(0.5)
|
586
|
+
sliders = page.locator("input.scaleInput")
|
587
|
+
|
588
|
+
if sound_aud_vol == 'background':
|
589
|
+
slider1 = sliders.nth(0)
|
590
|
+
bounding_box1 = slider1.bounding_box()
|
591
|
+
if bounding_box1:
|
592
|
+
x1 = bounding_box1["x"] + (bounding_box1["width"] * 0.92)
|
593
|
+
y1 = bounding_box1["y"] + bounding_box1["height"] / 2
|
594
|
+
if stealth == True:
|
595
|
+
time.sleep(1)
|
596
|
+
page.mouse.click(x1, y1)
|
597
|
+
|
598
|
+
slider2 = sliders.nth(1)
|
599
|
+
bounding_box2 = slider2.bounding_box()
|
600
|
+
if bounding_box2:
|
601
|
+
x2 = bounding_box2["x"] + (bounding_box2["width"] * 0.097)
|
602
|
+
y2 = bounding_box2["y"] + bounding_box2["height"] / 2
|
603
|
+
if stealth == True:
|
604
|
+
time.sleep(1)
|
605
|
+
page.mouse.click(x2, y2)
|
606
|
+
|
607
|
+
if sound_aud_vol == 'main':
|
608
|
+
slider1 = sliders.nth(0)
|
609
|
+
bounding_box1 = slider1.bounding_box()
|
610
|
+
if bounding_box1:
|
611
|
+
x1 = bounding_box1["x"] + (bounding_box1["width"] * 0.092)
|
612
|
+
y1 = bounding_box1["y"] + bounding_box1["height"] / 2
|
613
|
+
if stealth == True:
|
614
|
+
time.sleep(1)
|
615
|
+
page.mouse.click(x1, y1)
|
616
|
+
slider2 = sliders.nth(1)
|
617
|
+
bounding_box2 = slider2.bounding_box()
|
618
|
+
if bounding_box2:
|
619
|
+
x2 = bounding_box2["x"] + (bounding_box2["width"] * 0.92)
|
620
|
+
y2 = bounding_box2["y"] + bounding_box2["height"] / 2
|
621
|
+
if stealth == True:
|
622
|
+
time.sleep(1)
|
623
|
+
page.mouse.click(x2, y2)
|
624
|
+
except:
|
625
|
+
sys.exit("ERROR ADJUSTING SOUND VOLUME: please try again.")
|
626
|
+
|
627
|
+
page.wait_for_selector("div.TUXButton-label:has-text('Save edit')")
|
628
|
+
if stealth == True:
|
629
|
+
time.sleep(1)
|
630
|
+
page.click("div.TUXButton-label:has-text('Save edit')")
|
631
|
+
if suppressprint == False:
|
632
|
+
print("Added sound")
|
633
|
+
|
634
|
+
if sound_fail == False:
|
635
|
+
page.wait_for_selector('div[data-contents="true"]')
|
636
|
+
|
637
|
+
if copyrightcheck == True:
|
638
|
+
if stealth == True:
|
639
|
+
time.sleep(1)
|
640
|
+
page.locator('div[data-e2e="copyright_container"] span[data-part="thumb"]').click()
|
641
|
+
while copyrightcheck == True:
|
642
|
+
time.sleep(0.2)
|
643
|
+
if page.locator("span" ,has_text="No issues detected.").is_visible():
|
644
|
+
if suppressprint == False:
|
645
|
+
print("Copyright check complete")
|
646
|
+
break
|
647
|
+
if page.locator("span", has_text="Copyright issues detected.").is_visible():
|
648
|
+
sys.exit("COPYRIGHT CHECK FAILED: VIDEO SAVED AS DRAFT, COPYRIGHT AUDIO DETECTED FROM TIKTOK")
|
649
|
+
|
650
|
+
|
651
|
+
try:
|
652
|
+
if schedule == None:
|
653
|
+
if stealth == True:
|
654
|
+
time.sleep(1)
|
655
|
+
page.click('button:has-text("Post")', timeout=10000)
|
656
|
+
uploaded = False
|
657
|
+
checks = 0
|
658
|
+
while uploaded == False:
|
659
|
+
if page.locator(':has-text("Leaving the page does not interrupt")').nth(0).is_visible():
|
660
|
+
time.sleep(0.1)
|
661
|
+
break
|
662
|
+
time.sleep(0.2)
|
663
|
+
checks += 1
|
664
|
+
if checks == 25:
|
665
|
+
break
|
666
|
+
else:
|
667
|
+
if stealth == True:
|
668
|
+
time.sleep(1)
|
669
|
+
page.click('button:has-text("Schedule")', timeout=10000)
|
670
|
+
uploaded = False
|
671
|
+
checks = 0
|
672
|
+
while uploaded == False:
|
673
|
+
if page.locator(':has-text("Leaving the page does not interrupt")').nth(0).is_visible():
|
674
|
+
time.sleep(0.2)
|
675
|
+
break
|
676
|
+
time.sleep(0.2)
|
677
|
+
checks += 1
|
678
|
+
if checks == 25:
|
679
|
+
break
|
680
|
+
if suppressprint == False:
|
681
|
+
print("Done uploading video, NOTE: it may take a minute or two to show on TikTok")
|
682
|
+
except:
|
683
|
+
time.sleep(2)
|
684
|
+
sys.exit("POSSIBLE ERROR UPLOADING: Cannot confirm if uploaded successfully, Please check account in a minute or two to confirm.")
|
685
|
+
time.sleep(1)
|
686
|
+
|
687
|
+
page.close()
|
688
|
+
else:
|
689
|
+
try:
|
690
|
+
if stealth == True:
|
691
|
+
time.sleep(1)
|
692
|
+
page.click('button:has-text("Save draft")', timeout=10000)
|
693
|
+
except:
|
694
|
+
sys.exit("SAVE AS DRAFT BUTTON NOT FOUND; Please try account that has ability to save as draft")
|
695
|
+
|
696
|
+
time.sleep(0.5)
|
697
|
+
page.close()
|
698
|
+
|
699
|
+
browser = p.chromium.launch(headless=headless)
|
700
|
+
|
701
|
+
context = browser.new_context()
|
702
|
+
context.add_cookies(cookies)
|
703
|
+
page = context.new_page()
|
704
|
+
url2 = 'https://www.tiktok.com/tiktokstudio/content?tab=draft'
|
705
|
+
|
706
|
+
while retries < 2:
|
707
|
+
try:
|
708
|
+
page.goto(url2, timeout=30000)
|
709
|
+
except:
|
710
|
+
retries +=1
|
711
|
+
time.sleep(5)
|
712
|
+
if retries == 2:
|
713
|
+
sys.exit("ERROR: TIK TOK PAGE FAILED TO LOAD, try again.")
|
714
|
+
else:
|
715
|
+
break
|
716
|
+
|
717
|
+
try:
|
718
|
+
page.wait_for_selector("path[d='M37.37 4.85a4.01 4.01 0 0 0-.99-.79 3 3 0 0 0-2.72 0c-.45.23-.81.6-1 .79a9 9 0 0 1-.04.05l-19.3 19.3c-1.64 1.63-2.53 2.52-3.35 3.47a36 36 0 0 0-4.32 6.16c-.6 1.1-1.14 2.24-2.11 4.33l-.3.6c-.4.75-.84 1.61-.8 2.43a2.5 2.5 0 0 0 2.37 2.36c.82.05 1.68-.4 2.44-.79l.59-.3c2.09-.97 3.23-1.5 4.33-2.11a36 36 0 0 0 6.16-4.32c.95-.82 1.84-1.71 3.47-3.34l19.3-19.3.05-.06a3 3 0 0 0 .78-3.71c-.22-.45-.6-.81-.78-1l-.02-.02-.03-.03-3.67-3.67a8.7 8.7 0 0 1-.06-.05ZM16.2 26.97 35.02 8.15l2.83 2.83L19.03 29.8c-1.7 1.7-2.5 2.5-3.33 3.21a32 32 0 0 1-7.65 4.93 32 32 0 0 1 4.93-7.65c.73-.82 1.51-1.61 3.22-3.32Z']")
|
719
|
+
if stealth == True:
|
720
|
+
time.sleep(1)
|
721
|
+
page.click("path[d='M37.37 4.85a4.01 4.01 0 0 0-.99-.79 3 3 0 0 0-2.72 0c-.45.23-.81.6-1 .79a9 9 0 0 1-.04.05l-19.3 19.3c-1.64 1.63-2.53 2.52-3.35 3.47a36 36 0 0 0-4.32 6.16c-.6 1.1-1.14 2.24-2.11 4.33l-.3.6c-.4.75-.84 1.61-.8 2.43a2.5 2.5 0 0 0 2.37 2.36c.82.05 1.68-.4 2.44-.79l.59-.3c2.09-.97 3.23-1.5 4.33-2.11a36 36 0 0 0 6.16-4.32c.95-.82 1.84-1.71 3.47-3.34l19.3-19.3.05-.06a3 3 0 0 0 .78-3.71c-.22-.45-.6-.81-.78-1l-.02-.02-.03-.03-3.67-3.67a8.7 8.7 0 0 1-.06-.05ZM16.2 26.97 35.02 8.15l2.83 2.83L19.03 29.8c-1.7 1.7-2.5 2.5-3.33 3.21a32 32 0 0 1-7.65 4.93 32 32 0 0 1 4.93-7.65c.73-.82 1.51-1.61 3.22-3.32Z']")
|
722
|
+
page.wait_for_selector('div[data-contents="true"]')
|
723
|
+
time.sleep(0.2)
|
724
|
+
except:
|
725
|
+
sys.exit("ERROR ADDING SOUND: Video saved as draft")
|
726
|
+
|
727
|
+
if sound_name != None:
|
728
|
+
if stealth == True:
|
729
|
+
time.sleep(1)
|
730
|
+
page.click("div.TUXButton-label:has-text('Edit video')")
|
731
|
+
page.wait_for_selector("input.search-bar-input")
|
732
|
+
page.fill(f"input.search-bar-input", f"{sound_name}")
|
733
|
+
time.sleep(0.2)
|
734
|
+
if stealth == True:
|
735
|
+
time.sleep(1)
|
736
|
+
page.click("div.TUXButton-label:has-text('Search')")
|
737
|
+
try:
|
738
|
+
page.wait_for_selector('div.music-card-container')
|
739
|
+
if stealth == True:
|
740
|
+
time.sleep(1)
|
741
|
+
page.click("div.music-card-container")
|
742
|
+
page.wait_for_selector("div.TUXButton-label:has-text('Use')")
|
743
|
+
if stealth == True:
|
744
|
+
time.sleep(1)
|
745
|
+
page.click("div.TUXButton-label:has-text('Use')")
|
746
|
+
except:
|
747
|
+
sys.exit(f"ERROR: SOUND '{sound_name}' NOT FOUND")
|
748
|
+
try:
|
749
|
+
page.wait_for_selector('img[src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMSAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTAgNy41MDE2QzAgNi42NzMxNyAwLjY3MTU3MyA2LjAwMTYgMS41IDYuMDAxNkgzLjU3NzA5QzMuODY4MDUgNi4wMDE2IDQuMTQ0NTggNS44NzQ4OCA0LjMzNDU1IDUuNjU0NDlMOC43NDI1NSAwLjU0MDUyQzkuMzQ3OCAtMC4xNjE2NjggMTAuNSAwLjI2NjM3NCAxMC41IDEuMTkzNDFWMTguOTY3MkMxMC41IDE5Ljg3NDUgOS4zODg5NCAyMC4zMTI5IDguNzY5NDIgMTkuNjVMNC4zMzE3OSAxNC45MDIxQzQuMTQyNjkgMTQuNjk5OCAzLjg3ODE2IDE0LjU4NDkgMy42MDEyMiAxNC41ODQ5SDEuNUMwLjY3MTU3MyAxNC41ODQ5IDAgMTMuOTEzNCAwIDEzLjA4NDlWNy41MDE2Wk01Ljg0OTQ1IDYuOTYwMjdDNS4yNzk1NiA3LjYyMTQzIDQuNDQ5OTcgOC4wMDE2IDMuNTc3MDkgOC4wMDE2SDJWMTIuNTg0OUgzLjYwMTIyQzQuNDMyMDMgMTIuNTg0OSA1LjIyNTY0IDEyLjkyOTUgNS43OTI5NSAxMy41MzY0TDguNSAxNi40MzI4VjMuODg1MjJMNS44NDk0NSA2Ljk2MDI3WiIgZmlsbD0iIzE2MTgyMyIgZmlsbC1vcGFjaXR5PSIwLjYiLz4KPHBhdGggZD0iTTEzLjUxNSA3LjE5MTE5QzEzLjM0MjQgNi45NzU1OSAxMy4zMzk5IDYuNjYwNTYgMTMuNTM1MiA2LjQ2NTNMMTQuMjQyMyA1Ljc1ODE5QzE0LjQzNzYgNS41NjI5MyAxNC43NTU4IDUuNTYxNzUgMTQuOTM1NiA1Ljc3MTM2QzE2Ljk5NTkgOC4xNzM2MiAxNi45OTU5IDExLjgyOCAxNC45MzU2IDE0LjIzMDNDMTQuNzU1OCAxNC40Mzk5IDE0LjQzNzYgMTQuNDM4NyAxNC4yNDIzIDE0LjI0MzVMMTMuNTM1MiAxMy41MzY0QzEzLjMzOTkgMTMuMzQxMSAxMy4zNDI0IDEzLjAyNjEgMTMuNTE1IDEyLjgxMDVDMTQuODEzIDExLjE4ODUgMTQuODEzIDguODEzMTIgMTMuNTE1IDcuMTkxMTlaIiBmaWxsPSIjMTYxODIzIiBmaWxsLW9wYWNpdHk9IjAuNiIvPgo8cGF0aCBkPSJNMTYuNzE3MiAxNi43MTgzQzE2LjUyMTkgMTYuNTIzMSAxNi41MjMxIDE2LjIwNzQgMTYuNzA3MiAxNi4wMDE3QzE5LjcyNTcgMTIuNjMgMTkuNzI1NyA3LjM3MTY4IDE2LjcwNzIgNC4wMDAwMUMxNi41MjMxIDMuNzk0MjcgMTYuNTIxOSAzLjQ3ODU4IDE2LjcxNzIgMy4yODMzMkwxNy40MjQzIDIuNTc2MjFDMTcuNjE5NSAyLjM4MDk1IDE3LjkzNyAyLjM4MDIgMTguMTIzMyAyLjU4NDA4QzIxLjkwOTkgNi43MjkyNiAyMS45MDk5IDEzLjI3MjQgMTguMTIzMyAxNy40MTc2QzE3LjkzNyAxNy42MjE1IDE3LjYxOTUgMTcuNjIwNyAxNy40MjQzIDE3LjQyNTVMMTYuNzE3MiAxNi43MTgzWiIgZmlsbD0iIzE2MTgyMyIgZmlsbC1vcGFjaXR5PSIwLjYiLz4KPC9zdmc+Cg=="]')
|
750
|
+
if stealth == True:
|
751
|
+
time.sleep(1)
|
752
|
+
page.click('img[src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMSAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTAgNy41MDE2QzAgNi42NzMxNyAwLjY3MTU3MyA2LjAwMTYgMS41IDYuMDAxNkgzLjU3NzA5QzMuODY4MDUgNi4wMDE2IDQuMTQ0NTggNS44NzQ4OCA0LjMzNDU1IDUuNjU0NDlMOC43NDI1NSAwLjU0MDUyQzkuMzQ3OCAtMC4xNjE2NjggMTAuNSAwLjI2NjM3NCAxMC41IDEuMTkzNDFWMTguOTY3MkMxMC41IDE5Ljg3NDUgOS4zODg5NCAyMC4zMTI5IDguNzY5NDIgMTkuNjVMNC4zMzE3OSAxNC45MDIxQzQuMTQyNjkgMTQuNjk5OCAzLjg3ODE2IDE0LjU4NDkgMy42MDEyMiAxNC41ODQ5SDEuNUMwLjY3MTU3MyAxNC41ODQ5IDAgMTMuOTEzNCAwIDEzLjA4NDlWNy41MDE2Wk01Ljg0OTQ1IDYuOTYwMjdDNS4yNzk1NiA3LjYyMTQzIDQuNDQ5OTcgOC4wMDE2IDMuNTc3MDkgOC4wMDE2SDJWMTIuNTg0OUgzLjYwMTIyQzQuNDMyMDMgMTIuNTg0OSA1LjIyNTY0IDEyLjkyOTUgNS43OTI5NSAxMy41MzY0TDguNSAxNi40MzI4VjMuODg1MjJMNS44NDk0NSA2Ljk2MDI3WiIgZmlsbD0iIzE2MTgyMyIgZmlsbC1vcGFjaXR5PSIwLjYiLz4KPHBhdGggZD0iTTEzLjUxNSA3LjE5MTE5QzEzLjM0MjQgNi45NzU1OSAxMy4zMzk5IDYuNjYwNTYgMTMuNTM1MiA2LjQ2NTNMMTQuMjQyMyA1Ljc1ODE5QzE0LjQzNzYgNS41NjI5MyAxNC43NTU4IDUuNTYxNzUgMTQuOTM1NiA1Ljc3MTM2QzE2Ljk5NTkgOC4xNzM2MiAxNi45OTU5IDExLjgyOCAxNC45MzU2IDE0LjIzMDNDMTQuNzU1OCAxNC40Mzk5IDE0LjQzNzYgMTQuNDM4NyAxNC4yNDIzIDE0LjI0MzVMMTMuNTM1MiAxMy41MzY0QzEzLjMzOTkgMTMuMzQxMSAxMy4zNDI0IDEzLjAyNjEgMTMuNTE1IDEyLjgxMDVDMTQuODEzIDExLjE4ODUgMTQuODEzIDguODEzMTIgMTMuNTE1IDcuMTkxMTlaIiBmaWxsPSIjMTYxODIzIiBmaWxsLW9wYWNpdHk9IjAuNiIvPgo8cGF0aCBkPSJNMTYuNzE3MiAxNi43MTgzQzE2LjUyMTkgMTYuNTIzMSAxNi41MjMxIDE2LjIwNzQgMTYuNzA3MiAxNi4wMDE3QzE5LjcyNTcgMTIuNjMgMTkuNzI1NyA3LjM3MTY4IDE2LjcwNzIgNC4wMDAwMUMxNi41MjMxIDMuNzk0MjcgMTYuNTIxOSAzLjQ3ODU4IDE2LjcxNzIgMy4yODMzMkwxNy40MjQzIDIuNTc2MjFDMTcuNjE5NSAyLjM4MDk1IDE3LjkzNyAyLjM4MDIgMTguMTIzMyAyLjU4NDA4QzIxLjkwOTkgNi43MjkyNiAyMS45MDk5IDEzLjI3MjQgMTguMTIzMyAxNy40MTc2QzE3LjkzNyAxNy42MjE1IDE3LjYxOTUgMTcuNjIwNyAxNy40MjQzIDE3LjQyNTVMMTYuNzE3MiAxNi43MTgzWiIgZmlsbD0iIzE2MTgyMyIgZmlsbC1vcGFjaXR5PSIwLjYiLz4KPC9zdmc+Cg=="]')
|
753
|
+
time.sleep(0.5)
|
754
|
+
sliders = page.locator("input.scaleInput")
|
755
|
+
|
756
|
+
if sound_aud_vol == 'background':
|
757
|
+
slider1 = sliders.nth(0)
|
758
|
+
bounding_box1 = slider1.bounding_box()
|
759
|
+
if bounding_box1:
|
760
|
+
x1 = bounding_box1["x"] + (bounding_box1["width"] * 0.92)
|
761
|
+
y1 = bounding_box1["y"] + bounding_box1["height"] / 2
|
762
|
+
if stealth == True:
|
763
|
+
time.sleep(1)
|
764
|
+
page.mouse.click(x1, y1)
|
765
|
+
|
766
|
+
slider2 = sliders.nth(1)
|
767
|
+
bounding_box2 = slider2.bounding_box()
|
768
|
+
if bounding_box2:
|
769
|
+
x2 = bounding_box2["x"] + (bounding_box2["width"] * 0.097)
|
770
|
+
y2 = bounding_box2["y"] + bounding_box2["height"] / 2
|
771
|
+
if stealth == True:
|
772
|
+
time.sleep(1)
|
773
|
+
page.mouse.click(x2, y2)
|
774
|
+
|
775
|
+
if sound_aud_vol == 'main':
|
776
|
+
slider1 = sliders.nth(0)
|
777
|
+
bounding_box1 = slider1.bounding_box()
|
778
|
+
if bounding_box1:
|
779
|
+
x1 = bounding_box1["x"] + (bounding_box1["width"] * 0.092)
|
780
|
+
y1 = bounding_box1["y"] + bounding_box1["height"] / 2
|
781
|
+
if stealth == True:
|
782
|
+
time.sleep(1)
|
783
|
+
page.mouse.click(x1, y1)
|
784
|
+
slider2 = sliders.nth(1)
|
785
|
+
bounding_box2 = slider2.bounding_box()
|
786
|
+
if bounding_box2:
|
787
|
+
x2 = bounding_box2["x"] + (bounding_box2["width"] * 0.92)
|
788
|
+
y2 = bounding_box2["y"] + bounding_box2["height"] / 2
|
789
|
+
if stealth == True:
|
790
|
+
time.sleep(1)
|
791
|
+
page.mouse.click(x2, y2)
|
792
|
+
except:
|
793
|
+
sys.exit("ERROR ADJUSTING SOUND VOLUME: please try again.")
|
794
|
+
|
795
|
+
page.wait_for_selector("div.TUXButton-label:has-text('Save edit')")
|
796
|
+
if stealth == True:
|
797
|
+
time.sleep(1)
|
798
|
+
page.click("div.TUXButton-label:has-text('Save edit')")
|
799
|
+
if suppressprint == False:
|
800
|
+
print("Added sound")
|
801
|
+
|
802
|
+
|
803
|
+
page.wait_for_selector('div[data-contents="true"]')
|
804
|
+
|
805
|
+
if copyrightcheck == True:
|
806
|
+
if stealth == True:
|
807
|
+
time.sleep(1)
|
808
|
+
page.locator('div[data-e2e="copyright_container"] span[data-part="thumb"]').click()
|
809
|
+
while copyrightcheck == True:
|
810
|
+
time.sleep(0.2)
|
811
|
+
if page.locator("span", has_text="No issues detected.").is_visible():
|
812
|
+
if suppressprint == False:
|
813
|
+
print("Copyright check complete")
|
814
|
+
break
|
815
|
+
if page.locator('span', has_text="Copyright issues detected.").is_visible():
|
816
|
+
sys.exit("COPYRIGHT CHECK FAILED: VIDEO SAVED AS DRAFT, COPYRIGHT AUDIO DETECTED FROM TIKTOK")
|
817
|
+
|
818
|
+
|
819
|
+
try:
|
820
|
+
if schedule == None:
|
821
|
+
if stealth == True:
|
822
|
+
time.sleep(1)
|
823
|
+
page.click('button:has-text("Post")', timeout=10000)
|
824
|
+
uploaded = False
|
825
|
+
checks = 0
|
826
|
+
while uploaded == False:
|
827
|
+
if page.locator(':has-text("Leaving the page does not interrupt")').nth(0).is_visible():
|
828
|
+
time.sleep(0.2)
|
829
|
+
break
|
830
|
+
time.sleep(0.2)
|
831
|
+
checks += 1
|
832
|
+
if checks == 25:
|
833
|
+
break
|
834
|
+
else:
|
835
|
+
if stealth == True:
|
836
|
+
time.sleep(1)
|
837
|
+
page.click('button:has-text("Schedule")', timeout=10000)
|
838
|
+
uploaded = False
|
839
|
+
checks = 0
|
840
|
+
while uploaded == False:
|
841
|
+
if page.locator(':has-text("Leaving the page does not interrupt")').nth(0).is_visible():
|
842
|
+
time.sleep(0.1)
|
843
|
+
break
|
844
|
+
time.sleep(0.2)
|
845
|
+
checks += 1
|
846
|
+
if checks == 25:
|
847
|
+
break
|
848
|
+
if suppressprint == False:
|
849
|
+
print("Done uploading video, NOTE: it may take a minute or two to show on TikTok")
|
850
|
+
except:
|
851
|
+
time.sleep(2)
|
852
|
+
sys.exit("POSSIBLE ERROR UPLOADING: Cannot confirm if uploaded successfully, Please check account in a minute or two to confirm.")
|
853
|
+
time.sleep(1)
|
854
|
+
|
855
|
+
page.close()
|
856
|
+
|
857
|
+
return "Completed"
|
@@ -0,0 +1,152 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: tiktokautouploader
|
3
|
+
Version: 4.0
|
4
|
+
Summary: Upload or schedule videos to TikTok with viral TikTok sounds and hashtags.
|
5
|
+
Project-URL: Homepage, https://github.com/haziq-exe/TikTokAutoUploader
|
6
|
+
Author-email: HAZIQ <haziqmk123@gmail.com>
|
7
|
+
License-File: LICENSE.md
|
8
|
+
Keywords: autoupload,tiktok,tiktokautoupload
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
10
|
+
Classifier: Operating System :: OS Independent
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
12
|
+
Classifier: Programming Language :: Python :: 3.8
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
16
|
+
Requires-Dist: inference>=0.18.1
|
17
|
+
Requires-Dist: pillow>=8.0.0
|
18
|
+
Requires-Dist: playwright>=1.0.0
|
19
|
+
Requires-Dist: requests>=2.0.0
|
20
|
+
Description-Content-Type: text/markdown
|
21
|
+
|
22
|
+
<div align="center">
|
23
|
+
<h1>tiktokautouploader</h1>
|
24
|
+
</div>
|
25
|
+
|
26
|
+
|
27
|
+
### AUTOMATE TIKTOK UPLOADS 🤖. USE TRENDING SOUNDS 🔊, ADD WORKING HASHTAGS 💯, SCHEDULE UPLOADS 🗓️, AUTOSOLVES CAPTCHAS 🧠, AND MORE 🎁
|
28
|
+
|
29
|
+
[![PyPI version](https://img.shields.io/pypi/v/tiktokautouploader.svg)](https://pypi.org/project/tiktokautouploader/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
|
30
|
+
|
31
|
+
<p align="center">
|
32
|
+
<img src="READMEimage/READMEGIF.gif" alt="" width="900"/>
|
33
|
+
</p>
|
34
|
+
|
35
|
+
## 🚀 Features
|
36
|
+
|
37
|
+
- **🔐 Bypass/Auto Solve Captchas:** No need to worry about any captchas interrupting the process, they'll be solved!
|
38
|
+
- **🎵 Use TikTok Sounds:** Go viral by seamlessly adding popular TikTok sounds to your videos.
|
39
|
+
- **🗓 Schedule Uploads:** Upload videos at specific times or upto 10 days in advance with our scheduling feature.
|
40
|
+
- **🔍 Copyright Check:** Ensure your video is safe from copyright claims before uploading.
|
41
|
+
- **🏷 Add Working Hashtags:** Increase your reach by adding effective hashtags that actually work.
|
42
|
+
- **⏰ Cutdown on upload time:** Upload to TikTok with way less hassle and much more speed using our library.
|
43
|
+
- **📝 Upload to different accounts:** Stay organized and on top of multiple different accounts with our multi-account functionality.
|
44
|
+
|
45
|
+
⭐️ If you like this project please feel free to star it, Thank you.
|
46
|
+
|
47
|
+
## 📦 Installation
|
48
|
+
|
49
|
+
1. **Python Installation:** Install the package using `pip`:
|
50
|
+
|
51
|
+
```bash
|
52
|
+
pip install tiktokautouploader
|
53
|
+
```
|
54
|
+
|
55
|
+
**NOTE:** IF YOU HAVE INSTALLED BEFORE, PLEASE MAKE SURE YOU UPGRADE TO THE LATEST VERSION.
|
56
|
+
|
57
|
+
---
|
58
|
+
|
59
|
+
## ⚙️ Pre-requisites
|
60
|
+
|
61
|
+
1. **Node.js:** You must have Node.js installed on your system, as some parts of this package rely on JavaScript code. If you don't have Node.js installed, you can download it from [nodejs.org](https://nodejs.org/).
|
62
|
+
|
63
|
+
- **Note:** The necessary JavaScript dependencies (`playwright`,`playwright-extra`, `puppeteer-extra-plugin-stealth`) will be AUTOMATICALLY installed the first time you run the function, so you don't need to install them manually. Make sure that `npm` (Node.js package manager) is available in your system's PATH.
|
64
|
+
|
65
|
+
|
66
|
+
2. **Browser Binaries:** If you don't have them already, you'll need to install the browser binaries for `playwright`. This library uses chromium and firefox.
|
67
|
+
|
68
|
+
to do so, just run the following command AFTER installing the package:
|
69
|
+
|
70
|
+
```bash
|
71
|
+
python -m playwright install
|
72
|
+
```
|
73
|
+
|
74
|
+
**NOTE:** If you want to add sounds to your TikTok, you MUST have the ability to save drafts. If you don't want to add sounds then you don't need this feature.
|
75
|
+
|
76
|
+
|
77
|
+
## 📝 Quick-Start
|
78
|
+
|
79
|
+
**NOTE:** It is highly recommended you read DOCUMENTATION.md before using the library.
|
80
|
+
The first time you run the code for an account, you will be prompted to log-in, this will only occur the first time the function is used for the account. Check documentation for more info.
|
81
|
+
|
82
|
+
## Upload with hashtags
|
83
|
+
|
84
|
+
```python
|
85
|
+
from tiktokautouploader import upload_tiktok
|
86
|
+
|
87
|
+
video_path = 'path/to/your/video.mp4'
|
88
|
+
description = 'Check out my latest TikTok video!'
|
89
|
+
accountname = 'mytiktokaccount'
|
90
|
+
hashtags = ['#fun', '#viral']
|
91
|
+
|
92
|
+
upload_tiktok(video=video_path, description=description, accountname=accountname, hashtags=hashtags)
|
93
|
+
|
94
|
+
```
|
95
|
+
|
96
|
+
### Upload with TikTok Sound
|
97
|
+
|
98
|
+
```python
|
99
|
+
upload_tiktok(video=video_path, description=description, accountname=accountname, sound_name='trending_sound', sound_aud_vol='main')
|
100
|
+
```
|
101
|
+
|
102
|
+
PLEASE READ DOCUMENTATION FOR MORE INFO.
|
103
|
+
|
104
|
+
### Schedule an Upload
|
105
|
+
|
106
|
+
```python
|
107
|
+
upload_tiktok(video=video_path, description=description, accountname=accountname, schedule='03:10', day=11)
|
108
|
+
```
|
109
|
+
|
110
|
+
PLEASE READ DOCUMENTATION FOR MORE INFO
|
111
|
+
|
112
|
+
### Perform Copyright Check Before Uploading
|
113
|
+
|
114
|
+
```python
|
115
|
+
upload_tiktok(video=video_path, description=description, accountname=accountname, hashtags=hashtags, copyrightcheck=True)
|
116
|
+
```
|
117
|
+
|
118
|
+
## 🎯 Why Choose `autotiktokuploader`?
|
119
|
+
|
120
|
+
- **No more captchas:** Fully automated uploads without interruptions, If captchas do show up, no worries, they will be solved. (read documentation for more info)
|
121
|
+
- **Maximize your reach:** Add popular sounds and effective hashtags that work to boost visibility and go viral!
|
122
|
+
- **Stay compliant:** Built-in copyright checks to avoid unforeseen takedowns.
|
123
|
+
- **Convenient scheduling:** Post at the right time, even when you're away!
|
124
|
+
- **Much faster than manually uploading:** Drastically reduce the time you need to upload videos, just click one button and be done much quicker!
|
125
|
+
- **Upload to different account:** Stay on top of all your TikTok accounts with our multi-account functionality!
|
126
|
+
|
127
|
+
## 🛠 Dependencies
|
128
|
+
|
129
|
+
This library requires the following dependencies:
|
130
|
+
|
131
|
+
- `playwright`
|
132
|
+
- `requests`
|
133
|
+
- `Pillow`
|
134
|
+
- `scikit-learn`
|
135
|
+
- `inference`
|
136
|
+
|
137
|
+
These will be automatically installed when you install the package.
|
138
|
+
|
139
|
+
## 👤 Author
|
140
|
+
|
141
|
+
Created by **Haziq**. Feel free to reach out at [haziqmk123@gmail.com](mailto:haziqmk123@gmail.com)
|
142
|
+
|
143
|
+
## 📄 License
|
144
|
+
|
145
|
+
This project is licensed under the MIT License. See the [LICENSE](LICENSE.md) file for details.
|
146
|
+
|
147
|
+
## 📮 Related Projects
|
148
|
+
|
149
|
+
If you liked this project please check out my use case showcase project that generates TikToks and uploads them using 'tiktokautouploader'
|
150
|
+
|
151
|
+
[TikTokGenerator](https://github.com/haziq-exe/TikTokGenerator)
|
152
|
+
|
@@ -0,0 +1,8 @@
|
|
1
|
+
tiktokautouploader/__init__.py,sha256=u7OWCK_u68ST8dfrkSF4Yw44CJOzV9NXI6ASRuoDfmE,64
|
2
|
+
tiktokautouploader/function.py,sha256=fKS8bm6yzvP9QXO_Y8gAcZufOIhA_G2WsSwM_xH0KmM,46918
|
3
|
+
tiktokautouploader/Js_assets/login.js,sha256=SLhtPYo8ZfTRUnbR7Xqp084lSuAOqIWUxi75FlFH3vs,966
|
4
|
+
tiktokautouploader/Js_assets/package.json,sha256=aNbwSOpEpDUlplSuXugHVeN11riVwV4ofVkRPwHzbLs,273
|
5
|
+
tiktokautouploader-4.0.dist-info/METADATA,sha256=7C6hDX0w_QKgybBMx756B3BqzuVQL1rCeSUP7dsWe9I,6125
|
6
|
+
tiktokautouploader-4.0.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
|
7
|
+
tiktokautouploader-4.0.dist-info/licenses/LICENSE.md,sha256=hYds_VJIpnS5gC73WhuWk2IY_e9BWjuEJthQCb9ThyU,1073
|
8
|
+
tiktokautouploader-4.0.dist-info/RECORD,,
|
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) [2024] [HAZIQ KHALID]
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|