mirror of
https://github.com/ovosimpatico/CLI-TikTok.git
synced 2026-01-15 11:52:52 -03:00
PEP-8 Compliance
Signed-off-by: nanometer5088 <code.deleo@simplelogin.com>
This commit is contained in:
15
main.py
15
main.py
@@ -24,7 +24,7 @@ from src.init import init
|
|||||||
silent = True
|
silent = True
|
||||||
if len(sys.argv) <= 1:
|
if len(sys.argv) <= 1:
|
||||||
silent = False
|
silent = False
|
||||||
|
|
||||||
a = init(silent)
|
a = init(silent)
|
||||||
|
|
||||||
if a == -1:
|
if a == -1:
|
||||||
@@ -87,12 +87,11 @@ def main():
|
|||||||
username = str(input("Enter the tiktok username here: "))
|
username = str(input("Enter the tiktok username here: "))
|
||||||
log(f"The creator chosen was: @{username}\n")
|
log(f"The creator chosen was: @{username}\n")
|
||||||
links = proxitok_scraper(username)
|
links = proxitok_scraper(username)
|
||||||
downloadtiktoks(links) # add handling for when zero links are passed
|
downloadtiktoks(links) # add handling for when zero links are passed
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
## Stream
|
## Stream
|
||||||
if question == 2:
|
if question == 2:
|
||||||
|
|
||||||
watchquestion = int(
|
watchquestion = int(
|
||||||
input(
|
input(
|
||||||
"""Do you want to watch your liked videos, a creator or trending videos?
|
"""Do you want to watch your liked videos, a creator or trending videos?
|
||||||
@@ -107,7 +106,6 @@ def main():
|
|||||||
|
|
||||||
## Stream liked videos
|
## Stream liked videos
|
||||||
if watchquestion == 1:
|
if watchquestion == 1:
|
||||||
|
|
||||||
randomquestion = int(
|
randomquestion = int(
|
||||||
input(
|
input(
|
||||||
"""Do you want to watch the tiktoks in randomized order?
|
"""Do you want to watch the tiktoks in randomized order?
|
||||||
@@ -188,6 +186,7 @@ def main():
|
|||||||
# Warning, this section is experimental and will only run if you use any launch arguments
|
# Warning, this section is experimental and will only run if you use any launch arguments
|
||||||
# GUI Code:
|
# GUI Code:
|
||||||
|
|
||||||
|
|
||||||
def arguments(args):
|
def arguments(args):
|
||||||
log("Running using launch arguments")
|
log("Running using launch arguments")
|
||||||
|
|
||||||
@@ -199,7 +198,7 @@ def arguments(args):
|
|||||||
username = args.downloadcreator
|
username = args.downloadcreator
|
||||||
log(f"The creator chosen was: @{username}\n")
|
log(f"The creator chosen was: @{username}\n")
|
||||||
links = proxitok_scraper(username)
|
links = proxitok_scraper(username)
|
||||||
downloadtiktoks(links) # add handling for when zero links are passed
|
downloadtiktoks(links) # add handling for when zero links are passed
|
||||||
|
|
||||||
elif args.streamlikedrandom:
|
elif args.streamlikedrandom:
|
||||||
log("The user chose to stream liked videos in shuffled mode\n")
|
log("The user chose to stream liked videos in shuffled mode\n")
|
||||||
@@ -223,8 +222,10 @@ def arguments(args):
|
|||||||
log("The user chose to stream trending videos\n")
|
log("The user chose to stream trending videos\n")
|
||||||
videos = int(args.streamtrending)
|
videos = int(args.streamtrending)
|
||||||
if videos >= 1:
|
if videos >= 1:
|
||||||
streamtrending(videos)
|
streamtrending(videos)
|
||||||
|
|
||||||
|
|
||||||
if silent:
|
if silent:
|
||||||
arguments(args)
|
arguments(args)
|
||||||
else:
|
else:
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from bs4 import BeautifulSoup
|
|||||||
from log import logtofile as log
|
from log import logtofile as log
|
||||||
from src.streaming import getVideoInfo, mpv
|
from src.streaming import getVideoInfo, mpv
|
||||||
|
|
||||||
|
|
||||||
def streamuser(username):
|
def streamuser(username):
|
||||||
links = proxitok_scraper(username)
|
links = proxitok_scraper(username)
|
||||||
|
|
||||||
@@ -20,6 +21,7 @@ def streamuser(username):
|
|||||||
|
|
||||||
def proxitok_scraper(username: str) -> list[str]:
|
def proxitok_scraper(username: str) -> list[str]:
|
||||||
from src.constants import OPTIONS
|
from src.constants import OPTIONS
|
||||||
|
|
||||||
log("Scraper started")
|
log("Scraper started")
|
||||||
print("\nObtaining URLs - this can take a while with users with many posts.")
|
print("\nObtaining URLs - this can take a while with users with many posts.")
|
||||||
session = requests.Session()
|
session = requests.Session()
|
||||||
@@ -29,7 +31,7 @@ def proxitok_scraper(username: str) -> list[str]:
|
|||||||
url = f"{OPTIONS['proxitok_instance']}/@{username}{next_href}"
|
url = f"{OPTIONS['proxitok_instance']}/@{username}{next_href}"
|
||||||
response = session.get(url)
|
response = session.get(url)
|
||||||
log(f"Scraping {url}")
|
log(f"Scraping {url}")
|
||||||
|
|
||||||
if OPTIONS["ratelimit"] != 0:
|
if OPTIONS["ratelimit"] != 0:
|
||||||
log(f'Sleeping for {OPTIONS["ratelimit"]}s')
|
log(f'Sleeping for {OPTIONS["ratelimit"]}s')
|
||||||
time.sleep(OPTIONS["ratelimit"])
|
time.sleep(OPTIONS["ratelimit"])
|
||||||
@@ -39,11 +41,11 @@ def proxitok_scraper(username: str) -> list[str]:
|
|||||||
log(error_msg)
|
log(error_msg)
|
||||||
print(error_msg)
|
print(error_msg)
|
||||||
return direct_links
|
return direct_links
|
||||||
|
|
||||||
soup = BeautifulSoup(response.text, "html.parser")
|
soup = BeautifulSoup(response.text, "html.parser")
|
||||||
|
|
||||||
posts = soup.find_all("article", class_="media")
|
posts = soup.find_all("article", class_="media")
|
||||||
|
|
||||||
if not posts:
|
if not posts:
|
||||||
error_msg = "No posts found. The specified account is likely private or has no published videos"
|
error_msg = "No posts found. The specified account is likely private or has no published videos"
|
||||||
log(error_msg)
|
log(error_msg)
|
||||||
|
|||||||
@@ -5,14 +5,15 @@ from yt_dlp import YoutubeDL
|
|||||||
from yt_dlp.utils import DownloadError
|
from yt_dlp.utils import DownloadError
|
||||||
|
|
||||||
from log import logtofile as log
|
from log import logtofile as log
|
||||||
from src.functions import url_redirection
|
|
||||||
from src.constants import OPTIONS
|
from src.constants import OPTIONS
|
||||||
|
from src.functions import url_redirection
|
||||||
|
|
||||||
|
|
||||||
def downloader(url):
|
def downloader(url):
|
||||||
ydl_opts = {
|
ydl_opts = {
|
||||||
"format": "bestvideo*+bestaudio/best",
|
"format": "bestvideo*+bestaudio/best",
|
||||||
"outtmpl": os.getcwd() + "/video/%(creator)s/%(id)s.%(ext)s",
|
"outtmpl": os.getcwd() + "/video/%(creator)s/%(id)s.%(ext)s",
|
||||||
"download_archive": os.getcwd() + "/video/.video_archive"
|
"download_archive": os.getcwd() + "/video/.video_archive",
|
||||||
}
|
}
|
||||||
YoutubeDL(ydl_opts).download(url)
|
YoutubeDL(ydl_opts).download(url)
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ def downloadtiktoks(urls):
|
|||||||
if OPTIONS["ratelimit"] != 0:
|
if OPTIONS["ratelimit"] != 0:
|
||||||
log(f'Sleeping for {OPTIONS["ratelimit"]}s')
|
log(f'Sleeping for {OPTIONS["ratelimit"]}s')
|
||||||
time.sleep(OPTIONS["ratelimit"])
|
time.sleep(OPTIONS["ratelimit"])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
downloader(url)
|
downloader(url)
|
||||||
log(f"Video {url} was downloaded")
|
log(f"Video {url} was downloaded")
|
||||||
|
|||||||
@@ -2,19 +2,22 @@ import os
|
|||||||
import random
|
import random
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from log import logtofile as log
|
from log import logtofile as log
|
||||||
|
|
||||||
|
|
||||||
def listas():
|
def listas():
|
||||||
# Retrieves tiktok likes and dates from user_data.json
|
# Retrieves tiktok likes and dates from user_data.json
|
||||||
import json
|
import json
|
||||||
f = open('user_data.json')
|
|
||||||
|
f = open("user_data.json")
|
||||||
linklist = []
|
linklist = []
|
||||||
datelist = []
|
datelist = []
|
||||||
data = json.load(f)
|
data = json.load(f)
|
||||||
|
|
||||||
for i in data['Activity']["Like List"]['ItemFavoriteList']:
|
for i in data["Activity"]["Like List"]["ItemFavoriteList"]:
|
||||||
linklist.append(i['Link'])
|
linklist.append(i["Link"])
|
||||||
datelist.append(i['Date'])
|
datelist.append(i["Date"])
|
||||||
f.close()
|
f.close()
|
||||||
log("user_data.json file was processed sucessfully")
|
log("user_data.json file was processed sucessfully")
|
||||||
return linklist, datelist
|
return linklist, datelist
|
||||||
|
|||||||
67
src/init.py
67
src/init.py
@@ -12,6 +12,7 @@
|
|||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from log import logtofile as log
|
from log import logtofile as log
|
||||||
@@ -23,19 +24,25 @@ def clear_screen():
|
|||||||
|
|
||||||
def init(silent):
|
def init(silent):
|
||||||
clear_screen()
|
clear_screen()
|
||||||
|
|
||||||
if not silent:
|
if not silent:
|
||||||
|
|
||||||
print("Welcome to CLI TikTok, an open-source TikTok archiver and viewer!")
|
print("Welcome to CLI TikTok, an open-source TikTok archiver and viewer!")
|
||||||
input("Press ENTER to proceed")
|
input("Press ENTER to proceed")
|
||||||
|
|
||||||
log("Started dependency test")
|
log("Started dependency test")
|
||||||
required_libraries = ["requests", "yt_dlp", "distro", "bs4"]
|
required_libraries = ["requests", "yt_dlp", "distro", "bs4"]
|
||||||
missing_libraries = [library for library in required_libraries if not _library_exists(library)]
|
missing_libraries = [
|
||||||
|
library for library in required_libraries if not _library_exists(library)
|
||||||
|
]
|
||||||
if missing_libraries:
|
if missing_libraries:
|
||||||
log("Dependency test failed - Missing libraries: " + ", ".join(missing_libraries))
|
log(
|
||||||
|
"Dependency test failed - Missing libraries: "
|
||||||
|
+ ", ".join(missing_libraries)
|
||||||
|
)
|
||||||
clear_screen()
|
clear_screen()
|
||||||
input("The program detected dependencies are not installed.\nPress ENTER to install the necessary libraries.\n(You will need to open the program again afterwards)")
|
input(
|
||||||
|
"The program detected dependencies are not installed.\nPress ENTER to install the necessary libraries.\n(You will need to open the program again afterwards)"
|
||||||
|
)
|
||||||
log("User accepted automatic installation, running it.\n")
|
log("User accepted automatic installation, running it.\n")
|
||||||
os.system("pip install -r requirements.txt --user")
|
os.system("pip install -r requirements.txt --user")
|
||||||
clear_screen()
|
clear_screen()
|
||||||
@@ -50,36 +57,56 @@ def init(silent):
|
|||||||
|
|
||||||
log("Started update / networking test")
|
log("Started update / networking test")
|
||||||
try:
|
try:
|
||||||
link = requests.get("https://raw.githubusercontent.com/nanometer5088/CLI-TikTok/main/src/constants.py").text.strip()
|
link = requests.get(
|
||||||
|
"https://raw.githubusercontent.com/nanometer5088/CLI-TikTok/main/src/constants.py"
|
||||||
|
).text.strip()
|
||||||
|
|
||||||
userversion = _read_user_version()
|
userversion = _read_user_version()
|
||||||
|
|
||||||
version_line = next(line for line in link.split('\n')
|
version_line = next(
|
||||||
if line.startswith(' "version": '))
|
line for line in link.split("\n") if line.startswith(' "version": ')
|
||||||
data = version_line.split(': ')[1]
|
)
|
||||||
|
data = version_line.split(": ")[1]
|
||||||
|
|
||||||
if userversion < data:
|
if userversion < data:
|
||||||
log(f"New version detected! User version is {userversion}, but {data} was found on Github.")
|
log(
|
||||||
|
f"New version detected! User version is {userversion}, but {data} was found on Github."
|
||||||
|
)
|
||||||
clear_screen()
|
clear_screen()
|
||||||
input("\tThere's a new version available!\n\tUpdates bring performance and feature improvements!\n\tDownload the new version here:\n\thttps://github.com/nanometer5088/CLI-TikTok/archive/refs/heads/main.zip\n\n\tPress ENTER to proceed")
|
input(
|
||||||
|
"\tThere's a new version available!\n\tUpdates bring performance and feature improvements!\n\tDownload the new version here:\n\thttps://github.com/nanometer5088/CLI-TikTok/archive/refs/heads/main.zip\n\n\tPress ENTER to proceed"
|
||||||
|
)
|
||||||
clear_screen()
|
clear_screen()
|
||||||
else:
|
else:
|
||||||
log("The user has internet access and the software is up-to-date.\n")
|
log("The user has internet access and the software is up-to-date.\n")
|
||||||
clear_screen()
|
clear_screen()
|
||||||
|
|
||||||
except requests.exceptions.ConnectionError:
|
except requests.exceptions.ConnectionError:
|
||||||
log("A connection error was detected when trying to connect to https://raw.githubusercontent.com/ to check for updates.")
|
log(
|
||||||
|
"A connection error was detected when trying to connect to https://raw.githubusercontent.com/ to check for updates."
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
for site in ["https://www.eff.org", "https://freedom.press", "https://www.torproject.org", "https://www.privacyguides.org"]:
|
for site in [
|
||||||
|
"https://www.eff.org",
|
||||||
|
"https://freedom.press",
|
||||||
|
"https://www.torproject.org",
|
||||||
|
"https://www.privacyguides.org",
|
||||||
|
]:
|
||||||
requests.get(site)
|
requests.get(site)
|
||||||
log("The user seems to be connected to the internet, but Github is not accessible. Dazed and confused, but trying to continue.")
|
log(
|
||||||
|
"The user seems to be connected to the internet, but Github is not accessible. Dazed and confused, but trying to continue."
|
||||||
|
)
|
||||||
clear_screen()
|
clear_screen()
|
||||||
except requests.exceptions.ConnectionError:
|
except requests.exceptions.ConnectionError:
|
||||||
clear_screen()
|
clear_screen()
|
||||||
print("CLI-TikTok detected your device isn't connected to the internet.")
|
print("CLI-TikTok detected your device isn't connected to the internet.")
|
||||||
print("This software requires a reliable and uncensored internet connection to properly work.")
|
print(
|
||||||
|
"This software requires a reliable and uncensored internet connection to properly work."
|
||||||
|
)
|
||||||
print("Please try again with an internet connection.")
|
print("Please try again with an internet connection.")
|
||||||
log("The software exited, and the user was notified of the connection problem.")
|
log(
|
||||||
|
"The software exited, and the user was notified of the connection problem."
|
||||||
|
)
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
|
||||||
@@ -99,6 +126,7 @@ def _get_os_info():
|
|||||||
return f"Mac OS {platform.mac_ver()}"
|
return f"Mac OS {platform.mac_ver()}"
|
||||||
elif system == "Linux":
|
elif system == "Linux":
|
||||||
import distro
|
import distro
|
||||||
|
|
||||||
return f"{distro.name()} {distro.version()} - {os.uname().release}"
|
return f"{distro.name()} {distro.version()} - {os.uname().release}"
|
||||||
else:
|
else:
|
||||||
return f"{system} - {platform.machine()}"
|
return f"{system} - {platform.machine()}"
|
||||||
@@ -110,4 +138,5 @@ def _get_python_version():
|
|||||||
|
|
||||||
def _read_user_version():
|
def _read_user_version():
|
||||||
from src.constants import APP
|
from src.constants import APP
|
||||||
return str(APP["version"])
|
|
||||||
|
return str(APP["version"])
|
||||||
|
|||||||
20
src/logs.py
20
src/logs.py
@@ -2,34 +2,38 @@ import glob
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
|
||||||
class Logging:
|
class Logging:
|
||||||
# logFileOpened is a variable that keeps track of the log file status.
|
# logFileOpened is a variable that keeps track of the log file status.
|
||||||
# It is initialized as False to represent the log file wasn't open.
|
# It is initialized as False to represent the log file wasn't open.
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.logFileOpened = False
|
self.logFileOpened = False
|
||||||
|
|
||||||
# `log_string` is a string that is the log message that will be written to the log file.
|
# `log_string` is a string that is the log message that will be written to the log file.
|
||||||
def log(self, log_string: str):
|
def log(self, log_string: str):
|
||||||
logs_directory = os.getcwd() + "/logs"
|
logs_directory = os.getcwd() + "/logs"
|
||||||
|
|
||||||
if not os.path.exists(logs_directory):
|
if not os.path.exists(logs_directory):
|
||||||
os.mkdir(logs_directory)
|
os.mkdir(logs_directory)
|
||||||
|
|
||||||
log_files = glob.glob(r"logs/log-*.txt")
|
log_files = glob.glob(r"logs/log-*.txt")
|
||||||
|
|
||||||
# The log file numbers are extracted from the filenames
|
# The log file numbers are extracted from the filenames
|
||||||
log_file_numbers = [int(file[9:-4]) for file in log_files]
|
log_file_numbers = [int(file[9:-4]) for file in log_files]
|
||||||
|
|
||||||
# If log_file_numbers list is empty, append the value 0 to it.
|
# If log_file_numbers list is empty, append the value 0 to it.
|
||||||
# This ensures that the list always contains at least one value.
|
# This ensures that the list always contains at least one value.
|
||||||
if not log_file_numbers:
|
if not log_file_numbers:
|
||||||
log_file_numbers.append(0)
|
log_file_numbers.append(0)
|
||||||
|
|
||||||
log_file_name = f"logs/log-{max(log_file_numbers) + 1 if not self.logFileOpened else max(log_file_numbers)}.txt"
|
log_file_name = f"logs/log-{max(log_file_numbers) + 1 if not self.logFileOpened else max(log_file_numbers)}.txt"
|
||||||
|
|
||||||
|
|
||||||
with open(log_file_name, "a" if self.logFileOpened else "w") as log_file:
|
with open(log_file_name, "a" if self.logFileOpened else "w") as log_file:
|
||||||
self.logFileOpened = True
|
self.logFileOpened = True
|
||||||
|
|
||||||
current_time = time.strftime("%Y.%m.%d-%H.%M.%S", time.localtime(time.time()))
|
current_time = time.strftime(
|
||||||
log_file.write(f"[{current_time}] {log_string.encode('ascii', 'replace').decode()}\n")
|
"%Y.%m.%d-%H.%M.%S", time.localtime(time.time())
|
||||||
|
)
|
||||||
|
log_file.write(
|
||||||
|
f"[{current_time}] {log_string.encode('ascii', 'replace').decode()}\n"
|
||||||
|
)
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ from yt_dlp import YoutubeDL
|
|||||||
from yt_dlp.utils import DownloadError
|
from yt_dlp.utils import DownloadError
|
||||||
|
|
||||||
from log import logtofile as log
|
from log import logtofile as log
|
||||||
from src.functions import url_redirection
|
|
||||||
from src.constants import OPTIONS
|
from src.constants import OPTIONS
|
||||||
|
from src.functions import url_redirection
|
||||||
|
|
||||||
|
|
||||||
def getVideoInfo(url):
|
def getVideoInfo(url):
|
||||||
@@ -16,7 +16,9 @@ def getVideoInfo(url):
|
|||||||
|
|
||||||
|
|
||||||
def mpv(url):
|
def mpv(url):
|
||||||
subprocess.check_output(f'{OPTIONS["player_command"]} "{getVideoInfo(url)}"', shell=True)
|
subprocess.check_output(
|
||||||
|
f'{OPTIONS["player_command"]} "{getVideoInfo(url)}"', shell=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def playbackrandom(urls, datas):
|
def playbackrandom(urls, datas):
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ from bs4 import BeautifulSoup
|
|||||||
from log import logtofile as log
|
from log import logtofile as log
|
||||||
from src.constants import OPTIONS
|
from src.constants import OPTIONS
|
||||||
|
|
||||||
def streamtrending(amount:int = 24):
|
|
||||||
|
def streamtrending(amount: int = 24):
|
||||||
links = proxitok_trending(amount)
|
links = proxitok_trending(amount)
|
||||||
|
|
||||||
if len(links) == 0:
|
if len(links) == 0:
|
||||||
@@ -23,6 +24,7 @@ def streamtrending(amount:int = 24):
|
|||||||
|
|
||||||
def proxitok_trending(amount: int = 24) -> list[str]:
|
def proxitok_trending(amount: int = 24) -> list[str]:
|
||||||
from src.constants import OPTIONS
|
from src.constants import OPTIONS
|
||||||
|
|
||||||
log("Scraper started")
|
log("Scraper started")
|
||||||
print("\nObtaining URLs - this can take a while when requesting many posts.")
|
print("\nObtaining URLs - this can take a while when requesting many posts.")
|
||||||
session = requests.Session()
|
session = requests.Session()
|
||||||
@@ -34,7 +36,7 @@ def proxitok_trending(amount: int = 24) -> list[str]:
|
|||||||
|
|
||||||
response = session.get(url)
|
response = session.get(url)
|
||||||
log(f"Scraping {url}")
|
log(f"Scraping {url}")
|
||||||
|
|
||||||
if OPTIONS["ratelimit"] != 0:
|
if OPTIONS["ratelimit"] != 0:
|
||||||
log(f'Sleeping for {OPTIONS["ratelimit"]}s')
|
log(f'Sleeping for {OPTIONS["ratelimit"]}s')
|
||||||
time.sleep(OPTIONS["ratelimit"])
|
time.sleep(OPTIONS["ratelimit"])
|
||||||
@@ -44,11 +46,11 @@ def proxitok_trending(amount: int = 24) -> list[str]:
|
|||||||
log(error_msg)
|
log(error_msg)
|
||||||
print(error_msg)
|
print(error_msg)
|
||||||
return direct_links
|
return direct_links
|
||||||
|
|
||||||
soup = BeautifulSoup(response.text, "html.parser")
|
soup = BeautifulSoup(response.text, "html.parser")
|
||||||
|
|
||||||
posts = soup.find_all("article", class_="media")
|
posts = soup.find_all("article", class_="media")
|
||||||
|
|
||||||
if not posts:
|
if not posts:
|
||||||
error_msg = "No posts found for trending."
|
error_msg = "No posts found for trending."
|
||||||
log(error_msg)
|
log(error_msg)
|
||||||
@@ -69,4 +71,4 @@ def proxitok_trending(amount: int = 24) -> list[str]:
|
|||||||
return direct_links
|
return direct_links
|
||||||
|
|
||||||
next_button = soup.find("a", class_="button", text="Next")
|
next_button = soup.find("a", class_="button", text="Next")
|
||||||
next_href = next_button["href"]
|
next_href = next_button["href"]
|
||||||
|
|||||||
Reference in New Issue
Block a user