tiktokautouploader 3.7__tar.gz → 3.14__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ /.DS_Store
2
+ /build
3
+ /dist
4
+ /tiktokautouploader.egg-info
5
+ /tiktokautouploader/.env
@@ -106,7 +106,7 @@ This document provides detailed information about the parameters and usage of th
106
106
  **Total runtime depends on your wifi connection and how long TikTok takes to upload your video to their servers, however, here are approximations on how much runtime is added by each parameter**
107
107
 
108
108
  - **Captcha's:** 3 - 10 secs (in RARE cases, it may take longer)
109
- - **Adding Sound:** 3 - 5 secs
109
+ - **Adding Sound:** 8 - 12 secs
110
110
  - **Scheduling:** 5 - 8 secs
111
111
  - **Copyright Check:** 2 - 5 secs
112
112
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: tiktokautouploader
3
- Version: 3.7
3
+ Version: 3.14
4
4
  Summary: Upload or schedule videos to TikTok with viral TikTok sounds and hashtags.
5
5
  Project-URL: Homepage, https://github.com/haziq-exe/TikTokAutoUploader
6
6
  Author-email: HAZIQ <haziqmk123@gmail.com>
@@ -17,6 +17,7 @@ Requires-Dist: inference>=0.18.1
17
17
  Requires-Dist: pillow>=8.0.0
18
18
  Requires-Dist: playwright>=1.0.0
19
19
  Requires-Dist: requests>=2.0.0
20
+ Requires-Dist: scikit-learn>=0.24.0
20
21
  Description-Content-Type: text/markdown
21
22
 
22
23
  <div align="center">
@@ -28,8 +29,9 @@ Description-Content-Type: text/markdown
28
29
 
29
30
  [![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
 
32
+
31
33
  <p align="center">
32
- <img src="READMEimage/READMEGIF.gif" alt="" width="900"/>
34
+ <img src="READMEimage/READMEvid.gif" alt="" width="900"/>
33
35
  </p>
34
36
 
35
37
  ## 🚀 Features
@@ -42,8 +44,6 @@ Description-Content-Type: text/markdown
42
44
  - **⏰ Cutdown on upload time:** Upload to TikTok with way less hassle and much more speed using our library.
43
45
  - **📝 Upload to different accounts:** Stay organized and on top of multiple different accounts with our multi-account functionality.
44
46
 
45
- ⭐️ If you like this project please feel free to star it, Thank you.
46
-
47
47
  ## 📦 Installation
48
48
 
49
49
  1. **Python Installation:** Install the package using `pip`:
@@ -143,10 +143,4 @@ Created by **Haziq**. Feel free to reach out at [haziqmk123@gmail.com](mailto:ha
143
143
  ## 📄 License
144
144
 
145
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
-
146
+ ```
@@ -7,8 +7,9 @@
7
7
 
8
8
  [![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)
9
9
 
10
+
10
11
  <p align="center">
11
- <img src="READMEimage/READMEGIF.gif" alt="" width="900"/>
12
+ <img src="READMEimage/READMEvid.gif" alt="" width="900"/>
12
13
  </p>
13
14
 
14
15
  ## 🚀 Features
@@ -21,8 +22,6 @@
21
22
  - **⏰ Cutdown on upload time:** Upload to TikTok with way less hassle and much more speed using our library.
22
23
  - **📝 Upload to different accounts:** Stay organized and on top of multiple different accounts with our multi-account functionality.
23
24
 
24
- ⭐️ If you like this project please feel free to star it, Thank you.
25
-
26
25
  ## 📦 Installation
27
26
 
28
27
  1. **Python Installation:** Install the package using `pip`:
@@ -122,10 +121,4 @@ Created by **Haziq**. Feel free to reach out at [haziqmk123@gmail.com](mailto:ha
122
121
  ## 📄 License
123
122
 
124
123
  This project is licensed under the MIT License. See the [LICENSE](LICENSE.md) file for details.
125
-
126
- ## 📮 Related Projects
127
-
128
- If you liked this project please check out my use case showcase project that generates TikToks and uploads them using 'tiktokautouploader'
129
-
130
- [TikTokGenerator](https://github.com/haziq-exe/TikTokGenerator)
131
-
124
+ ```
@@ -1,10 +1,10 @@
1
1
  [build-system]
2
- requires = ["hatchling", "setuptools", "wheel"]
2
+ requires = ["hatchling", "setupwheel"]
3
3
  build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "tiktokautouploader"
7
- version = "3.7"
7
+ version = "3.14"
8
8
  description = "Upload or schedule videos to TikTok with viral TikTok sounds and hashtags."
9
9
  readme = {file = "README.md", content-type = "text/markdown"}
10
10
  keywords = ["tiktok", "autoupload", "tiktokautoupload"]
@@ -27,6 +27,7 @@ dependencies = [
27
27
  "playwright>=1.0.0",
28
28
  "requests>=2.0.0",
29
29
  "Pillow>=8.0.0",
30
+ "scikit-learn>=0.24.0",
30
31
  "inference>=0.18.1",
31
32
  ]
32
33
 
@@ -35,7 +36,7 @@ tags = ["wheel"]
35
36
 
36
37
  [tool.hatch.metadata]
37
38
  name = "tiktokautouploader"
38
- version = "3.7"
39
+ version = "3.14"
39
40
  description = "Upload or schedule videos to TikTok with TikTok sounds and hashtags that work."
40
41
  readme = {file = "README.md", content-type = "text/markdown"}
41
42
  keywords = ["tiktok", "autoupload", "tiktokautoupload"]
@@ -1,14 +1,17 @@
1
1
  from playwright.sync_api import sync_playwright
2
2
  import json
3
3
  import time
4
+ import inference
4
5
  import subprocess
5
- from inference_sdk import InferenceHTTPClient
6
6
  import pkg_resources
7
7
  import requests
8
8
  from PIL import Image
9
9
  import sys
10
+ import base64
10
11
  import os
12
+ from dotenv import load_dotenv
11
13
  import warnings
14
+ load_dotenv()
12
15
  warnings.simplefilter("ignore")
13
16
 
14
17
 
@@ -54,14 +57,11 @@ def run_javascript():
54
57
  def install_js_dependencies():
55
58
  js_dir = pkg_resources.resource_filename(__name__, 'Js_assets')
56
59
  node_modules_path = os.path.join(js_dir, 'node_modules')
57
-
60
+
58
61
  if not os.path.exists(node_modules_path):
59
62
  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}")
63
+ subprocess.run(['npm', 'install', 'playwright', 'playwright-extra', 'puppeteer-extra-plugin-stealth', '--silent'], cwd=js_dir, check=True)
64
+ subprocess.run(['npx', 'playwright', 'install', 'chromium'], cwd=js_dir, check=True)
65
65
  else:
66
66
  time.sleep(0.1)
67
67
 
@@ -135,6 +135,8 @@ def get_image_src(page):
135
135
  image_url = page.get_attribute("img#captcha-verify-image", "src")
136
136
  return image_url
137
137
 
138
+ os.getenv('ROBOFLOW_API_KEY')
139
+
138
140
  def download_image(image_url):
139
141
  response = requests.get(image_url)
140
142
  image_path = "captcha_image.jpg"
@@ -144,25 +146,18 @@ def download_image(image_url):
144
146
 
145
147
  def run_inference_on_image_tougher(image_path, object):
146
148
 
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")
149
+ model = inference.get_model("captcha-2-6ehbe/2")
150
+ results = model.infer(image=image_path)
156
151
 
157
152
  class_names = []
158
153
  bounding_boxes = []
159
- for obj in results['predictions']:
160
- class_names.append(obj['class'])
154
+ for obj in results[0].predictions:
155
+ class_names.append(obj.class_name)
161
156
  bounding_boxes.append({
162
- "x": obj['x'],
163
- "y": obj['y'],
164
- "width": obj['width'],
165
- "height": obj['height']
157
+ "x": obj.x,
158
+ "y": obj.y,
159
+ "width": obj.width,
160
+ "height": obj.height
166
161
  })
167
162
 
168
163
  bounding_box = []
@@ -177,40 +172,34 @@ def run_inference_on_image_tougher(image_path, object):
177
172
 
178
173
  def run_inference_on_image(image_path):
179
174
 
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")
175
+ model = inference.get_model("tk-3nwi9/2")
176
+ results = model.infer(image=image_path)
189
177
 
190
178
  class_names = []
191
179
  bounding_boxes = []
192
- for obj in results['predictions']:
193
- class_names.append(obj['class'])
180
+ for obj in results[0].predictions:
181
+ class_names.append(obj.class_name)
194
182
  bounding_boxes.append({
195
- "x": obj['x'],
196
- "y": obj['y'],
197
- "width": obj['width'],
198
- "height": obj['height']
183
+ "x": obj.x,
184
+ "y": obj.y,
185
+ "width": obj.width,
186
+ "height": obj.height
199
187
  })
200
188
 
201
189
  already_written = []
202
190
  bounding_box = []
203
191
  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)
192
+ for i, classes in enumerate(class_names):
193
+ if classes in already_written:
194
+ class_to_click.append(classes)
207
195
  bounding_box.append(bounding_boxes[i])
208
- index = already_written.index(detected_class)
196
+ index = already_written.index(classes)
209
197
  bounding_box.append(bounding_boxes[index])
210
198
 
211
- already_written.append(detected_class)
199
+ already_written.append(classes)
212
200
 
213
201
  found = False
202
+
214
203
  if len(class_to_click) == 1:
215
204
  found = True
216
205
 
@@ -238,14 +227,13 @@ def click_on_objects(page, object_coords):
238
227
 
239
228
 
240
229
 
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):
230
+ def upload_tiktok(video, description, accountname, hashtags=None, sound_name=None, sound_aud_vol='mix', schedule=None, day=None, copyrightcheck=False, suppressprint=False):
242
231
 
243
232
  """
244
233
  UPLOADS VIDEO TO TIKTOK
245
234
  ------------------------------------------------------------------------------------------------------------------------------------------------c
246
235
  video (str) -> path to video to upload
247
236
  description (str) -> description for video
248
- accountname (str) -> account to upload on
249
237
  hashtags (str)(array) -> hashtags for video
250
238
  sound_name (str) -> name of tik tok sound to use for video
251
239
  sound_aud_vol (str) -> volume of tik tok sound, 'main', 'mix' or 'background', check documentation for more info -> https://github.com/haziq-exe/TikTokAutoUploader
@@ -253,7 +241,6 @@ def upload_tiktok(video, description, accountname, hashtags=None, sound_name=Non
253
241
  day (int) -> day to schedule video for, check documentation for more info -> https://github.com/haziq-exe/TikTokAutoUploader
254
242
  copyrightcheck (bool) -> include copyright check or not; CODE FAILS IF FAIL COPYRIGHT CHECK
255
243
  suppressprint (bool) -> True means function doesnt print anything to provide updates on progress
256
- headless (bool) -> run in headless mode or not
257
244
  --------------------------------------------------------------------------------------------------------------------------------------------
258
245
  """
259
246
  try:
@@ -289,7 +276,8 @@ def upload_tiktok(video, description, accountname, hashtags=None, sound_name=Non
289
276
 
290
277
  with sync_playwright() as p:
291
278
 
292
- browser = p.firefox.launch(headless=headless)
279
+ browser = p.firefox.launch(headless=True)
280
+
293
281
  context = browser.new_context()
294
282
  context.add_cookies(cookies)
295
283
  page = context.new_page()
@@ -475,16 +463,13 @@ def upload_tiktok(video, description, accountname, hashtags=None, sound_name=Non
475
463
  print("Description and Hashtags added")
476
464
 
477
465
  try:
478
- page.wait_for_selector('button.TUXButton.TUXButton--default.TUXButton--large.TUXButton--primary:has-text("Post")[aria-disabled="false"]', timeout=12000000)
466
+ page.wait_for_function("document.querySelector('.info-progress-num').textContent.trim() === '100%'", timeout=12000000)
479
467
  except:
480
468
  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")
481
469
 
482
470
  time.sleep(0.2)
483
471
  if suppressprint == False:
484
472
  print("Tik tok done loading file onto servers")
485
-
486
- if (schedule == None) and (day != None):
487
- 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")
488
473
 
489
474
  if schedule != None:
490
475
  try:
@@ -496,39 +481,31 @@ def upload_tiktok(video, description, accountname, hashtags=None, sound_name=Non
496
481
  except:
497
482
  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")
498
483
 
499
- page.locator('div.TUXRadioStandalone.TUXRadioStandalone--medium:has(input[value="schedule"])').click()
500
- # time.sleep(1)
501
- visible = False
502
- while visible == False:
503
- if page.locator('button.TUXButton.TUXButton--default.TUXButton--medium.TUXButton--primary:has-text("Allow")').nth(0).is_visible():
504
- page.locator('button.TUXButton.TUXButton--default.TUXButton--medium.TUXButton--primary:has-text("Allow")').nth(0).click()
505
- visible = True
506
- time.sleep(0.1)
507
- else:
508
- if page.locator('div.TUXTextInputCore-trailingIconWrapper').nth(1).is_visible():
509
- visible = True
510
- time.sleep(0.1)
484
+ page.locator('div.TUXRadioStandalone.TUXRadioStandalone--medium').nth(1).click()
485
+ time.sleep(1)
486
+ if page.locator('button.TUXButton.TUXButton--default.TUXButton--medium.TUXButton--primary:has-text("Allow")').nth(0).is_visible():
487
+ page.locator('button.TUXButton.TUXButton--default.TUXButton--medium.TUXButton--primary:has-text("Allow")').nth(0).click()
488
+ time.sleep(0.2)
489
+ else:
490
+ if page.locator('div.TUXTextInputCore-trailingIconWrapper').nth(1).is_visible():
491
+ time.sleep(0.2)
511
492
  if day != None:
512
- 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()
493
+ page.locator('div.TUXTextInputCore-trailingIconWrapper').nth(1).click()
513
494
  time.sleep(0.2)
514
495
  try:
515
- page.locator(f'span.day.valid:text-is("{day}")').click()
496
+ page.locator(f'span.day.valid:has-text("{day}")').click()
516
497
  except:
517
498
  sys.exit("SCHEDULE DAY ERROR: ERROR WITH SCHEDULED DAY, read documentation for more information on format of day")
518
499
  try:
500
+ time.sleep(1)
501
+ page.locator('div.TUXTextInputCore-trailingIconWrapper').nth(0).click()
519
502
  time.sleep(0.2)
520
- 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()
521
- time.sleep(0.2)
522
- page.locator(f'.tiktok-timepicker-option-text.tiktok-timepicker-right:text-is("{minute}")').scroll_into_view_if_needed()
503
+ page.locator(f'.tiktok-timepicker-option-text.tiktok-timepicker-right:has-text("{minute}")').nth(0).scroll_into_view_if_needed()
523
504
  time.sleep(0.2)
524
- page.locator(f'.tiktok-timepicker-option-text.tiktok-timepicker-right:text-is("{minute}")').click()
505
+ page.locator(f'.tiktok-timepicker-option-text.tiktok-timepicker-right:has-text("{minute}")').nth(0).click()
525
506
  time.sleep(0.2)
526
- if page.locator("div.tiktok-timepicker-time-picker-container").is_visible():
527
- time.sleep(0.1)
528
- else:
529
- 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()
530
- page.locator(f'.tiktok-timepicker-option-text.tiktok-timepicker-left:text-is("{hour}")').scroll_into_view_if_needed()
531
- page.locator(f'.tiktok-timepicker-option-text.tiktok-timepicker-left:text-is("{hour}")').click()
507
+ page.locator(f'.tiktok-timepicker-option-text:has-text("{hour}")').nth(0).scroll_into_view_if_needed()
508
+ page.locator(f'.tiktok-timepicker-option-text:has-text("{hour}")').nth(0).click()
532
509
  time.sleep(1)
533
510
 
534
511
  if suppressprint == False:
@@ -536,14 +513,93 @@ def upload_tiktok(video, description, accountname, hashtags=None, sound_name=Non
536
513
 
537
514
  except:
538
515
  sys.exit("SCHEDULING ERROR: VIDEO SAVED AS DRAFT")
516
+
517
+ if (schedule == None) and (day != None):
518
+ 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")
519
+
520
+ if(sound_name == None):
521
+ if copyrightcheck == True:
522
+ page.locator(".TUXSwitch-input").nth(0).click()
523
+ while copyrightcheck == True:
524
+ time.sleep(0.2)
525
+ if page.locator("span", has_text="No issues detected.").is_visible():
526
+ if suppressprint == False:
527
+ print("Copyright check complete")
528
+ break
529
+ if page.locator("span", has_text="Copyright issues detected.").is_visible():
530
+ sys.exit("COPYRIGHT CHECK FAILED: COPYRIGHT AUDIO DETECTED FROM TIKTOK")
531
+
532
+ if schedule == None:
533
+ page.click('button.TUXButton.TUXButton--default.TUXButton--large.TUXButton--primary:has-text("Post")', timeout=10000)
534
+ uploaded = False
535
+ checks = 0
536
+ while uploaded == False:
537
+ if page.locator(':has-text("Leaving the page does not interrupt")').nth(0).is_visible():
538
+ time.sleep(0.2)
539
+ break
540
+ time.sleep(0.2)
541
+ checks += 1
542
+ if checks > 100:
543
+ time.sleep(10)
544
+ if checks == 150:
545
+ break
546
+ else:
547
+ page.click('button.TUXButton.TUXButton--default.TUXButton--large.TUXButton--primary:has-text("Schedule")', timeout=10000)
548
+ uploaded = False
549
+ checks = 0
550
+ while uploaded == False:
551
+ if page.locator(':has-text("Leaving the page does not interrupt")').nth(0).is_visible():
552
+ time.sleep(0.2)
553
+ break
554
+ time.sleep(0.2)
555
+ checks += 1
556
+ if checks > 100:
557
+ time.sleep(10)
558
+ if checks == 150:
559
+ break
560
+ if suppressprint == False:
561
+ print("Done uploading video, NOTE: it may take a minute or two to show on TikTok")
562
+
563
+ page.close()
539
564
 
540
- sound_fail = False
541
- if sound_name != None:
565
+ else:
542
566
  try:
543
- page.click("div.TUXButton-label:has-text('Edit video')")
567
+ page.click('button.TUXButton.TUXButton--default.TUXButton--large.TUXButton--secondary:has-text("Save draft")', timeout=10000)
544
568
  except:
545
- sound_fail = True
546
- if sound_fail == False:
569
+ sys.exit("SAVE AS DRAFT BUTTON NOT FOUND; CANNOT ADD SOUND WITHOUT ABILITY TO SAVE DRAFTS")
570
+
571
+ time.sleep(0.5)
572
+ page.close()
573
+
574
+ browser = p.chromium.launch(headless=True)
575
+
576
+ context = browser.new_context()
577
+ context.add_cookies(cookies)
578
+ page = context.new_page()
579
+ url2 = 'https://www.tiktok.com/tiktokstudio/content?tab=draft'
580
+
581
+ while retries < 2:
582
+ try:
583
+ page.goto(url2, timeout=30000)
584
+ except:
585
+ retries +=1
586
+ time.sleep(5)
587
+ if retries == 2:
588
+ sys.exit("ERROR: TIK TOK PAGE FAILED TO LOAD, try again.")
589
+ else:
590
+ break
591
+
592
+ try:
593
+ 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']")
594
+ 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']")
595
+ page.wait_for_selector('div[data-contents="true"]')
596
+ page.wait_for_function("document.querySelector('.info-progress-num').textContent.trim() === '100%'", timeout=3000000)
597
+ time.sleep(0.2)
598
+ except:
599
+ sys.exit("ERROR ADDING SOUND: Video saved as draft")
600
+
601
+ if sound_name != None:
602
+ page.click("div.TUXButton-label:has-text('Edit video')")
547
603
  page.wait_for_selector("input.search-bar-input")
548
604
  page.fill(f"input.search-bar-input", f"{sound_name}")
549
605
  time.sleep(0.2)
@@ -596,150 +652,11 @@ def upload_tiktok(video, description, accountname, hashtags=None, sound_name=Non
596
652
  page.click("div.TUXButton-label:has-text('Save edit')")
597
653
  if suppressprint == False:
598
654
  print("Added sound")
599
-
600
- if sound_fail == False:
601
- page.wait_for_selector('div[data-contents="true"]')
602
-
603
- if copyrightcheck == True:
604
- page.click('div.TUXSwitch:has(label.TUXSwitch-label:has-text("Run a copyright check")) input.TUXSwitch-input')
605
- while copyrightcheck == True:
606
- time.sleep(0.2)
607
- if page.locator("span", has_text="No issues detected.").is_visible():
608
- if suppressprint == False:
609
- print("Copyright check complete")
610
- break
611
- if page.locator("span", has_text="Copyright issues detected.").is_visible():
612
- sys.exit("COPYRIGHT CHECK FAILED: VIDEO SAVED AS DRAFT, COPYRIGHT AUDIO DETECTED FROM TIKTOK")
613
-
614
-
615
- try:
616
- if schedule == None:
617
- page.click('button.TUXButton.TUXButton--default.TUXButton--large.TUXButton--primary:has-text("Post")', timeout=10000)
618
- uploaded = False
619
- checks = 0
620
- while uploaded == False:
621
- if page.locator(':has-text("Leaving the page does not interrupt")').nth(0).is_visible():
622
- time.sleep(0.1)
623
- break
624
- time.sleep(0.2)
625
- checks += 1
626
- if checks == 25:
627
- break
628
- else:
629
- page.click('button.TUXButton.TUXButton--default.TUXButton--large.TUXButton--primary:has-text("Schedule")', timeout=10000)
630
- uploaded = False
631
- checks = 0
632
- while uploaded == False:
633
- if page.locator(':has-text("Leaving the page does not interrupt")').nth(0).is_visible():
634
- time.sleep(0.2)
635
- break
636
- time.sleep(0.2)
637
- checks += 1
638
- if checks == 25:
639
- break
640
- if suppressprint == False:
641
- print("Done uploading video, NOTE: it may take a minute or two to show on TikTok")
642
- except:
643
- time.sleep(2)
644
- sys.exit("POSSIBLE ERROR UPLOADING: Cannot confirm if uploaded successfully, Please check account in a minute or two to confirm.")
645
- time.sleep(1)
646
-
647
- page.close()
648
- else:
649
- try:
650
- page.click('button.TUXButton.TUXButton--default.TUXButton--large.TUXButton--secondary:has-text("Save draft")', timeout=10000)
651
- except:
652
- sys.exit("SAVE AS DRAFT BUTTON NOT FOUND; Please try account that has ability to save as draft")
653
-
654
- time.sleep(0.5)
655
- page.close()
656
-
657
- browser = p.chromium.launch(headless=headless)
658
-
659
- context = browser.new_context()
660
- context.add_cookies(cookies)
661
- page = context.new_page()
662
- url2 = 'https://www.tiktok.com/tiktokstudio/content?tab=draft'
663
-
664
- while retries < 2:
665
- try:
666
- page.goto(url2, timeout=30000)
667
- except:
668
- retries +=1
669
- time.sleep(5)
670
- if retries == 2:
671
- sys.exit("ERROR: TIK TOK PAGE FAILED TO LOAD, try again.")
672
- else:
673
- break
674
-
675
- try:
676
- 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']")
677
- 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']")
678
- page.wait_for_selector('div[data-contents="true"]')
679
- time.sleep(0.2)
680
- except:
681
- sys.exit("ERROR ADDING SOUND: Video saved as draft")
682
-
683
- if sound_name != None:
684
- page.click("div.TUXButton-label:has-text('Edit video')")
685
- page.wait_for_selector("input.search-bar-input")
686
- page.fill(f"input.search-bar-input", f"{sound_name}")
687
- time.sleep(0.2)
688
- page.click("div.TUXButton-label:has-text('Search')")
689
- try:
690
- page.wait_for_selector('div.music-card-container')
691
- page.click("div.music-card-container")
692
- page.wait_for_selector("div.TUXButton-label:has-text('Use')")
693
- page.click("div.TUXButton-label:has-text('Use')")
694
- except:
695
- sys.exit(f"ERROR: SOUND '{sound_name}' NOT FOUND")
696
- try:
697
- page.wait_for_selector('img[src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMSAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTAgNy41MDE2QzAgNi42NzMxNyAwLjY3MTU3MyA2LjAwMTYgMS41IDYuMDAxNkgzLjU3NzA5QzMuODY4MDUgNi4wMDE2IDQuMTQ0NTggNS44NzQ4OCA0LjMzNDU1IDUuNjU0NDlMOC43NDI1NSAwLjU0MDUyQzkuMzQ3OCAtMC4xNjE2NjggMTAuNSAwLjI2NjM3NCAxMC41IDEuMTkzNDFWMTguOTY3MkMxMC41IDE5Ljg3NDUgOS4zODg5NCAyMC4zMTI5IDguNzY5NDIgMTkuNjVMNC4zMzE3OSAxNC45MDIxQzQuMTQyNjkgMTQuNjk5OCAzLjg3ODE2IDE0LjU4NDkgMy42MDEyMiAxNC41ODQ5SDEuNUMwLjY3MTU3MyAxNC41ODQ5IDAgMTMuOTEzNCAwIDEzLjA4NDlWNy41MDE2Wk01Ljg0OTQ1IDYuOTYwMjdDNS4yNzk1NiA3LjYyMTQzIDQuNDQ5OTcgOC4wMDE2IDMuNTc3MDkgOC4wMDE2SDJWMTIuNTg0OUgzLjYwMTIyQzQuNDMyMDMgMTIuNTg0OSA1LjIyNTY0IDEyLjkyOTUgNS43OTI5NSAxMy41MzY0TDguNSAxNi40MzI4VjMuODg1MjJMNS44NDk0NSA2Ljk2MDI3WiIgZmlsbD0iIzE2MTgyMyIgZmlsbC1vcGFjaXR5PSIwLjYiLz4KPHBhdGggZD0iTTEzLjUxNSA3LjE5MTE5QzEzLjM0MjQgNi45NzU1OSAxMy4zMzk5IDYuNjYwNTYgMTMuNTM1MiA2LjQ2NTNMMTQuMjQyMyA1Ljc1ODE5QzE0LjQzNzYgNS41NjI5MyAxNC43NTU4IDUuNTYxNzUgMTQuOTM1NiA1Ljc3MTM2QzE2Ljk5NTkgOC4xNzM2MiAxNi45OTU5IDExLjgyOCAxNC45MzU2IDE0LjIzMDNDMTQuNzU1OCAxNC40Mzk5IDE0LjQzNzYgMTQuNDM4NyAxNC4yNDIzIDE0LjI0MzVMMTMuNTM1MiAxMy41MzY0QzEzLjMzOTkgMTMuMzQxMSAxMy4zNDI0IDEzLjAyNjEgMTMuNTE1IDEyLjgxMDVDMTQuODEzIDExLjE4ODUgMTQuODEzIDguODEzMTIgMTMuNTE1IDcuMTkxMTlaIiBmaWxsPSIjMTYxODIzIiBmaWxsLW9wYWNpdHk9IjAuNiIvPgo8cGF0aCBkPSJNMTYuNzE3MiAxNi43MTgzQzE2LjUyMTkgMTYuNTIzMSAxNi41MjMxIDE2LjIwNzQgMTYuNzA3MiAxNi4wMDE3QzE5LjcyNTcgMTIuNjMgMTkuNzI1NyA3LjM3MTY4IDE2LjcwNzIgNC4wMDAwMUMxNi41MjMxIDMuNzk0MjcgMTYuNTIxOSAzLjQ3ODU4IDE2LjcxNzIgMy4yODMzMkwxNy40MjQzIDIuNTc2MjFDMTcuNjE5NSAyLjM4MDk1IDE3LjkzNyAyLjM4MDIgMTguMTIzMyAyLjU4NDA4QzIxLjkwOTkgNi43MjkyNiAyMS45MDk5IDEzLjI3MjQgMTguMTIzMyAxNy40MTc2QzE3LjkzNyAxNy42MjE1IDE3LjYxOTUgMTcuNjIwNyAxNy40MjQzIDE3LjQyNTVMMTYuNzE3MiAxNi43MTgzWiIgZmlsbD0iIzE2MTgyMyIgZmlsbC1vcGFjaXR5PSIwLjYiLz4KPC9zdmc+Cg=="]')
698
- page.click('img[src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMSAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTAgNy41MDE2QzAgNi42NzMxNyAwLjY3MTU3MyA2LjAwMTYgMS41IDYuMDAxNkgzLjU3NzA5QzMuODY4MDUgNi4wMDE2IDQuMTQ0NTggNS44NzQ4OCA0LjMzNDU1IDUuNjU0NDlMOC43NDI1NSAwLjU0MDUyQzkuMzQ3OCAtMC4xNjE2NjggMTAuNSAwLjI2NjM3NCAxMC41IDEuMTkzNDFWMTguOTY3MkMxMC41IDE5Ljg3NDUgOS4zODg5NCAyMC4zMTI5IDguNzY5NDIgMTkuNjVMNC4zMzE3OSAxNC45MDIxQzQuMTQyNjkgMTQuNjk5OCAzLjg3ODE2IDE0LjU4NDkgMy42MDEyMiAxNC41ODQ5SDEuNUMwLjY3MTU3MyAxNC41ODQ5IDAgMTMuOTEzNCAwIDEzLjA4NDlWNy41MDE2Wk01Ljg0OTQ1IDYuOTYwMjdDNS4yNzk1NiA3LjYyMTQzIDQuNDQ5OTcgOC4wMDE2IDMuNTc3MDkgOC4wMDE2SDJWMTIuNTg0OUgzLjYwMTIyQzQuNDMyMDMgMTIuNTg0OSA1LjIyNTY0IDEyLjkyOTUgNS43OTI5NSAxMy41MzY0TDguNSAxNi40MzI4VjMuODg1MjJMNS44NDk0NSA2Ljk2MDI3WiIgZmlsbD0iIzE2MTgyMyIgZmlsbC1vcGFjaXR5PSIwLjYiLz4KPHBhdGggZD0iTTEzLjUxNSA3LjE5MTE5QzEzLjM0MjQgNi45NzU1OSAxMy4zMzk5IDYuNjYwNTYgMTMuNTM1MiA2LjQ2NTNMMTQuMjQyMyA1Ljc1ODE5QzE0LjQzNzYgNS41NjI5MyAxNC43NTU4IDUuNTYxNzUgMTQuOTM1NiA1Ljc3MTM2QzE2Ljk5NTkgOC4xNzM2MiAxNi45OTU5IDExLjgyOCAxNC45MzU2IDE0LjIzMDNDMTQuNzU1OCAxNC40Mzk5IDE0LjQzNzYgMTQuNDM4NyAxNC4yNDIzIDE0LjI0MzVMMTMuNTM1MiAxMy41MzY0QzEzLjMzOTkgMTMuMzQxMSAxMy4zNDI0IDEzLjAyNjEgMTMuNTE1IDEyLjgxMDVDMTQuODEzIDExLjE4ODUgMTQuODEzIDguODEzMTIgMTMuNTE1IDcuMTkxMTlaIiBmaWxsPSIjMTYxODIzIiBmaWxsLW9wYWNpdHk9IjAuNiIvPgo8cGF0aCBkPSJNMTYuNzE3MiAxNi43MTgzQzE2LjUyMTkgMTYuNTIzMSAxNi41MjMxIDE2LjIwNzQgMTYuNzA3MiAxNi4wMDE3QzE5LjcyNTcgMTIuNjMgMTkuNzI1NyA3LjM3MTY4IDE2LjcwNzIgNC4wMDAwMUMxNi41MjMxIDMuNzk0MjcgMTYuNTIxOSAzLjQ3ODU4IDE2LjcxNzIgMy4yODMzMkwxNy40MjQzIDIuNTc2MjFDMTcuNjE5NSAyLjM4MDk1IDE3LjkzNyAyLjM4MDIgMTguMTIzMyAyLjU4NDA4QzIxLjkwOTkgNi43MjkyNiAyMS45MDk5IDEzLjI3MjQgMTguMTIzMyAxNy40MTc2QzE3LjkzNyAxNy42MjE1IDE3LjYxOTUgMTcuNjIwNyAxNy40MjQzIDE3LjQyNTVMMTYuNzE3MiAxNi43MTgzWiIgZmlsbD0iIzE2MTgyMyIgZmlsbC1vcGFjaXR5PSIwLjYiLz4KPC9zdmc+Cg=="]')
699
- time.sleep(0.5)
700
- sliders = page.locator("input.scaleInput")
701
-
702
- if sound_aud_vol == 'background':
703
- slider1 = sliders.nth(0)
704
- bounding_box1 = slider1.bounding_box()
705
- if bounding_box1:
706
- x1 = bounding_box1["x"] + (bounding_box1["width"] * 0.92)
707
- y1 = bounding_box1["y"] + bounding_box1["height"] / 2
708
- page.mouse.click(x1, y1)
709
-
710
- slider2 = sliders.nth(1)
711
- bounding_box2 = slider2.bounding_box()
712
- if bounding_box2:
713
- x2 = bounding_box2["x"] + (bounding_box2["width"] * 0.097)
714
- y2 = bounding_box2["y"] + bounding_box2["height"] / 2
715
- page.mouse.click(x2, y2)
716
-
717
- if sound_aud_vol == 'main':
718
- slider1 = sliders.nth(0)
719
- bounding_box1 = slider1.bounding_box()
720
- if bounding_box1:
721
- x1 = bounding_box1["x"] + (bounding_box1["width"] * 0.092)
722
- y1 = bounding_box1["y"] + bounding_box1["height"] / 2
723
- page.mouse.click(x1, y1)
724
- slider2 = sliders.nth(1)
725
- bounding_box2 = slider2.bounding_box()
726
- if bounding_box2:
727
- x2 = bounding_box2["x"] + (bounding_box2["width"] * 0.92)
728
- y2 = bounding_box2["y"] + bounding_box2["height"] / 2
729
- page.mouse.click(x2, y2)
730
- except:
731
- sys.exit("ERROR ADJUSTING SOUND VOLUME: please try again.")
732
-
733
- page.wait_for_selector("div.TUXButton-label:has-text('Save edit')")
734
- page.click("div.TUXButton-label:has-text('Save edit')")
735
- if suppressprint == False:
736
- print("Added sound")
737
-
738
-
655
+
739
656
  page.wait_for_selector('div[data-contents="true"]')
740
657
 
741
658
  if copyrightcheck == True:
742
- page.click('div.TUXSwitch:has(label.TUXSwitch-label:has-text("Run a copyright check")) input.TUXSwitch-input')
659
+ page.locator(".TUXSwitch-input").nth(0).click()
743
660
  while copyrightcheck == True:
744
661
  time.sleep(0.2)
745
662
  if page.locator("span", has_text="No issues detected.").is_visible():
@@ -761,7 +678,9 @@ def upload_tiktok(video, description, accountname, hashtags=None, sound_name=Non
761
678
  break
762
679
  time.sleep(0.2)
763
680
  checks += 1
764
- if checks == 25:
681
+ if checks > 100:
682
+ time.sleep(10)
683
+ if checks == 150:
765
684
  break
766
685
  else:
767
686
  page.click('button.TUXButton.TUXButton--default.TUXButton--large.TUXButton--primary:has-text("Schedule")', timeout=10000)
@@ -769,19 +688,19 @@ def upload_tiktok(video, description, accountname, hashtags=None, sound_name=Non
769
688
  checks = 0
770
689
  while uploaded == False:
771
690
  if page.locator(':has-text("Leaving the page does not interrupt")').nth(0).is_visible():
772
- time.sleep(0.1)
691
+ time.sleep(0.2)
773
692
  break
774
693
  time.sleep(0.2)
775
694
  checks += 1
776
- if checks == 25:
695
+ if checks > 100:
696
+ time.sleep(10)
697
+ if checks == 150:
777
698
  break
778
699
  if suppressprint == False:
779
700
  print("Done uploading video, NOTE: it may take a minute or two to show on TikTok")
780
701
  except:
781
- time.sleep(2)
782
- sys.exit("POSSIBLE ERROR UPLOADING: Cannot confirm if uploaded successfully, Please check account in a minute or two to confirm.")
702
+ time.sleep(5)
703
+ sys.exit("ERROR UPLOADING: VIDEO HAS SAVED AS DRAFT BUT CANT UPLOAD")
783
704
  time.sleep(1)
784
705
 
785
- page.close()
786
-
787
- return "Completed"
706
+ page.close()
@@ -1,4 +0,0 @@
1
- /.DS_Store
2
- /build
3
- /dist
4
- /tiktokautouploader.egg-info
@@ -1,12 +0,0 @@
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
- }