Skip to content

Commit c9293c5

Browse files
committed
changed all to use headless browser
1 parent a141526 commit c9293c5

21 files changed

+231
-93
lines changed

.gitignore

+13
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,19 @@ tiktok_chromium.py
1414
config.toml
1515
cozycore_videos/
1616
used/
17+
fidgetink_state.json
18+
instagram_old.py
19+
caption.txt
20+
testfile.mp4
21+
fidgetink_videos/
22+
test.py
23+
fidgetink.bat
24+
temp_main.py
25+
requirements2.txt
26+
youtube_api.py
27+
main_old.py
28+
caption.txt
29+
resources/
1730

1831
# Byte-compiled / optimized / DLL files
1932
__pycache__/

README.md

Whitespace-only changes.

add_account.py

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from playwright.sync_api import sync_playwright
2+
from pathlib import Path
3+
from PyQt5.QtWidgets import QApplication, QFileDialog
4+
import toml
5+
import os
6+
7+
def get_folder():
8+
app = QApplication([]) # Create a PyQt application
9+
folder = QFileDialog.getExistingDirectory(None, "Select Folder", options=QFileDialog.ShowDirsOnly)
10+
return folder
11+
12+
def login():
13+
# check for config file
14+
if not os.path.exists(Path("./config.toml")):
15+
os.mkdir(Path("./config.toml"))
16+
17+
name = input("Enter name for account: ")
18+
path = Path(f"./{name}_state.json")
19+
config_path = Path("./config.toml")
20+
folder = get_folder()
21+
22+
with sync_playwright() as p:
23+
# start up browser
24+
browser = p.firefox.launch(headless=False)
25+
context = browser.new_context()
26+
page = context.new_page()
27+
28+
page.goto("https://www.instagram.com/accounts/login/")
29+
print("Press Save info after logging in!")
30+
input("Press enter once you have logged into instagram")
31+
page.goto("https://www.tiktok.com/login/phone-or-email/email/?lang=en")
32+
input("Press enter once you have logged into tiktok")
33+
page.goto("https://www.youtube.com/")
34+
input("Press enter once you have logged into youtube")
35+
36+
context.storage_state(path=path)
37+
38+
with config_path.open(mode="r") as f:
39+
config = toml.load(f)
40+
41+
config[name] = {}
42+
config[name]["last_run"] = ""
43+
config[name]["path"] = str(folder)
44+
config[name]["storage_state"] = str(path).lower()
45+
config[name]["caption"] = input("Enter your default caption: ")
46+
47+
with config_path.open(mode="w") as f:
48+
toml.dump(config, f)
49+
50+
51+
if __name__ == "__main__":
52+
login()

caption.txt

-1
This file was deleted.

instagram.py

+45-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,49 @@
1-
from instagrapi import Client
2-
import os
3-
import dotenv
1+
from playwright.sync_api import sync_playwright
2+
from pathlib import Path
3+
import logging
4+
import time
45

6+
logging.basicConfig(level=logging.INFO)
7+
logger = logging.getLogger(__name__)
58

6-
def main(username, password, path, caption):
7-
client = Client()
89

9-
client.login(username, password)
10+
def post(path, caption, storage_state):
11+
logger.info("Opening up instagram website")
12+
path = Path(path)
13+
with sync_playwright() as p:
14+
# launch the browser
15+
browser = p.firefox.launch()
16+
context = browser.new_context(
17+
storage_state=storage_state, **p.devices["Desktop Firefox"]
18+
)
19+
page = context.new_page()
20+
page.goto("https://www.instagram.com/")
1021

11-
client.clip_upload(path=path, caption=caption)
22+
# start posting process
23+
logging.info("starting to post the video")
24+
page.get_by_label("New Post").click()
25+
26+
# upload the file
27+
logger.info("Uploading the video file")
28+
with page.expect_file_chooser() as fc_info:
29+
page.get_by_role("button", name="Select from computer").click()
30+
file_chooser = fc_info.value
31+
file_chooser.set_files(path)
32+
time.sleep(3)
33+
34+
# skip the reel editing portion
35+
for i in range(2):
36+
page.get_by_role("button", name="Next").click()
37+
38+
# writing caption
39+
logging.info("writing caption")
40+
page.get_by_label("Write a caption...").fill(caption)
41+
42+
# share the reel
43+
page.get_by_role("button", name="Share").click()
44+
logging.info("waiting for reel to be shared!")
45+
46+
page.wait_for_selector("text=Reel shared")
47+
logging.info("reel shared")
48+
49+
browser.close()

main.py

+26-34
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
from pathlib import Path
21
from datetime import date
2+
from pathlib import Path
33
import os
44
import toml
55
import random
@@ -8,65 +8,57 @@
88
import tiktok
99
import youtube
1010
import instagram
11+
import sys
1112

1213
# Set up logging
1314
logging.basicConfig(level=logging.INFO)
1415
logger = logging.getLogger(__name__)
1516

17+
def main():
18+
19+
# get account
20+
account = sys.argv[1]
1621

17-
def main(account: str, check_lr: bool = False):
1822
# Load config file
1923
with open("config.toml", "r") as file:
2024
config = toml.load(file)
2125

22-
# Check when the script was last run
23-
if check_lr == True:
24-
if config["last run"]["date"] == str(date.today()):
25-
logger.info("Script already run today. Exiting.")
26-
return
27-
2826
# Select a random video
29-
folder = config[account]["path"]
27+
folder = Path(config[account]["path"])
3028
video_name = random.choice(os.listdir(folder))
31-
video = folder + video_name
32-
logger.info(f"{video} has been chosen. {type(video)}")
29+
video = folder.joinpath(video_name)
30+
logger.info(f"{video} has been chosen.")
3331

3432
# Get relevant info
3533
caption = config[account]["caption"]
36-
tiktok_cookies = config[account]["tiktok_cookies"]
37-
instagram_uid = config[account]["insta_uid"]
38-
instagram_pwd = config[account]["insta_pwd"]
34+
storage_state = Path(config[account]["storage_state"])
35+
36+
# create the threads
37+
threads = (threading.Thread(target=tiktok.post, args=(video, caption, storage_state,)),
38+
threading.Thread(target=instagram.post, args=(video, caption, storage_state,)),
39+
threading.Thread(target=youtube.post, args=(video, caption, storage_state,)))
3940

40-
# Create threads for each social media platform
41-
threads = [
42-
threading.Thread(target=tiktok.post, args=(video, caption, tiktok_cookies)),
43-
threading.Thread(
44-
target=instagram.main, args=(instagram_uid, instagram_pwd, video, caption)
45-
),
46-
threading.Thread(target=youtube.main, args=(video, caption)),
47-
]
48-
49-
# Start and join threads
41+
# start and join threads
42+
logger.info("Starting Threads")
5043
for thread in threads:
5144
thread.start()
52-
45+
5346
for thread in threads:
54-
thread.join()
47+
thread.join()
48+
logger.info("Threads have been joined")
5549

56-
# update last used date
57-
config["last run"]["date"] = str(date.today())
50+
logger.info("Updating last used date")
51+
config[account]["last_run"] = str(date.today())
5852
with open("config.toml", "w") as file:
5953
toml.dump(config, file)
6054

6155
# move used video away to prevent reselection
6256
if not os.path.exists("./used"):
57+
logger.info("Creating a used folder for used videos")
6358
os.mkdir("./used")
6459

65-
os.rename(video, f"./used/{video_name}")
66-
os.rename(f"{video}.jpg", f"./used/{video_name}")
67-
68-
return
69-
60+
logger.info("Moving used video to Used folder")
61+
video.rename(f"./used/{video_name}")
7062

7163
if __name__ == "__main__":
72-
main("cozycore")
64+
main()

requirements.txt

-2.01 KB
Binary file not shown.

resources/android-chrome-192x192.png

-44.9 KB
Binary file not shown.

resources/android-chrome-512x512.png

-290 KB
Binary file not shown.

resources/apple-touch-icon.png

-40.2 KB
Binary file not shown.

resources/favicon-16x16.png

-761 Bytes
Binary file not shown.

resources/favicon-32x32.png

-2.08 KB
Binary file not shown.

resources/favicon.ico

-15 KB
Binary file not shown.

resources/logo.png

-254 KB
Binary file not shown.

resources/site.webmanifest

-1
This file was deleted.

sample.bat

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@echo off
2+
echo uploading a video now
3+
4+
call path\to\venv
5+
python path\to\main.py account_name
6+
7+
echo uploaded

setup.bat

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@echo off
2+
3+
python -m venv venv
4+
call .\venv\Scripts\activate
5+
pip install -r requirements.txt
6+
playwright install firefox

setup.sh

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/bin/bash
2+
3+
# Create virtual environment
4+
python3 -m venv venv
5+
6+
# Activate virtual environment
7+
source venv/bin/activate
8+
9+
# Install Python dependencies
10+
pip install -r requirements.txt
11+
12+
# Install Playwright for Firefox
13+
playwright install firefox

test_File.mp4

-1.92 MB
Binary file not shown.

tiktok.py

+19-9
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import time
2-
from playwright.sync_api import sync_playwright, Playwright
3-
import dotenv
4-
import os
2+
from playwright.sync_api import sync_playwright
3+
import logging
54

6-
dotenv.load_dotenv()
5+
# Set up logging
6+
logging.basicConfig(level=logging.INFO)
7+
logger = logging.getLogger(__name__)
78

89

9-
def login(username, password, account):
10+
def login(username: str, password: str, account: str) -> str:
11+
path = f"{account}_tiktok_state.json"
1012
with sync_playwright() as p:
1113
browser = p.firefox.launch(headless=False)
1214
context = browser.new_context()
@@ -16,11 +18,13 @@ def login(username, password, account):
1618
time.sleep(4)
1719

1820
# enter username
21+
logger.info("Entering Username")
1922
page.mouse.move(497, 235)
2023
page.mouse.click(497, 235)
2124
page.keyboard.type(username, delay=200)
2225

2326
# enter password
27+
logger.info("Entering Password")
2428
page.mouse.move(497, 302)
2529
page.mouse.click(497, 302)
2630
page.keyboard.type(password, delay=200)
@@ -30,21 +34,25 @@ def login(username, password, account):
3034
page.mouse.click(818, 318)
3135

3236
# click login
37+
logger.info("Logging in")
3338
page.mouse.move(622, 383)
3439
page.mouse.click(622, 383)
3540

3641
# complete captcha
42+
logger.info("Waiting for user to run captcha")
3743
input("Please complete captcha and press enter to continue")
3844
time.sleep(3)
3945

4046
# collect cookies
41-
context.storage_state(path=f"{account}_state.json")
47+
logger.info("Collecting all cookies to use for posting")
48+
context.storage_state(path=path)
4249
time.sleep(2)
4350

4451
browser.close()
4552

4653

4754
def post(path, caption, storage_state):
55+
logger.info("Opening up tiktok website")
4856
with sync_playwright() as p:
4957
# launch the browser
5058
browser = p.firefox.launch()
@@ -58,21 +66,23 @@ def post(path, caption, storage_state):
5866
time.sleep(2)
5967

6068
# upload video file
69+
logger.info("Uploading the video file")
6170
with page.expect_file_chooser() as fc_info:
6271
page.locator('css=button:has-text("Select file")').dblclick()
6372
file_chooser = fc_info.value
6473
file_chooser.set_files(path)
74+
time.sleep(3)
6575

6676
# type in caption
77+
logger.info("Typing in the caption")
6778
page.locator("//div[@spellcheck='false']").click()
6879
page.keyboard.type(caption)
6980
print("waitiing for upload to finish")
7081
time.sleep(10)
71-
print("clicking")
7282

73-
# page.locator("//div[contains(@class, 'jsx-399018856') and contains(@class, 'btn-post')]//button[contains(., 'Post')]").click()
83+
# press the post button
7484
page.evaluate('document.querySelector(".btn-post > button").click()')
75-
print("clicked")
85+
logger.info("Posting the video")
7686
time.sleep(10)
7787

7888
browser.close()

0 commit comments

Comments
 (0)