diff --git a/main.py b/main.py index 776c33e..0a26261 100644 --- a/main.py +++ b/main.py @@ -1,110 +1,140 @@ # Introduction and pre-test -from src.init import init import sys + +from src.init import init + a = init() if a == -1: print("Dependencies installed successfully.\nOpen the program again\n") sys.exit() # Import libraries and required functions after sucessful pre-test -from src.functions import listas -from src.streaming import playbackrandom, playback +import os +import subprocess + +from src.byuser import getLinks, streamuser from src.downloader import downloadtiktoks -from src.byuser import streamuser, getLinks -import os, subprocess +from src.functions import listas +from src.streaming import playback, playbackrandom # Needlessly big code to simply prompt the user which action they want to do try: - question = int(input("""Do you want to download or watch tiktoks? + question = int( + input( + """Do you want to download or watch tiktoks? (1) Download (2) Watch - """)) + """ + ) + ) os.system("cls || clear") - - + ## Download if question == 1: - downloadquestion = int(input("""Do you want to download your liked videos or a creator? + downloadquestion = int( + input( + """Do you want to download your liked videos or a creator? (1) Liked Videos (2) Creator - """)) + """ + ) + ) os.system("cls || clear") - + ## Download liked videos if downloadquestion == 1: urls = listas()[0] downloadtiktoks(urls) sys.exit() - + ## Download creator if downloadquestion == 2: - print('Due to specific limitations of the current data method, downloading by creator will only get the latest 30 videos.') - print('This limitation is being actively researched, any contributions will be welcome.') - username = str(input('Enter the tiktok username here: ')) + print( + "Due to specific limitations of the current data method, downloading by creator will only get the latest 30 videos." + ) + print( + "This limitation is being actively researched, any contributions will be welcome." + ) + username = str(input("Enter the tiktok username here: ")) links = getLinks(username) downloadtiktoks(links) sys.exit() - + ## Stream if question == 2: - - watchquestion = int(input("""Do you want to watch your liked videos or a creator? + + watchquestion = int( + input( + """Do you want to watch your liked videos or a creator? (1) Liked Videos (2) Creator - """)) + """ + ) + ) os.system("cls || clear") - + ## Stream liked videos if watchquestion == 1: - - - randomquestion = int(input("""Do you want to watch the tiktoks in randomized order? + + randomquestion = int( + input( + """Do you want to watch the tiktoks in randomized order? (1) Yes (2) No - """)) + """ + ) + ) os.system("cls || clear") - + ## Stream liked videos randomized if randomquestion == 1: urls = listas()[0] datas = listas()[1] playbackrandom(urls, datas) sys.exit() - + ## Stream liked videos in descending order if randomquestion == 2: urls = listas()[0] datas = listas()[1] playback(urls, datas) sys.exit() - + ## Stream creator if watchquestion == 2: - print('Due to specific limitations of the current data method, watching by creator will only get the latest 30 videos.') - print('This limitation is being actively researched, any contributions will be welcome.') - username = str(input('Enter the tiktok username here: ')) + print( + "Due to specific limitations of the current data method, watching by creator will only get the latest 30 videos." + ) + print( + "This limitation is being actively researched, any contributions will be welcome." + ) + username = str(input("Enter the tiktok username here: ")) streamuser(username) sys.exit() - + # Error handling for invalid number (3, 4, 6, 133) print("The option you chose isn't valid.") - + # Error handling for invalid input (ENTER, 't', '5ga') except ValueError: print("The option you chose isn't valid.") - + # Error handling for missing Likes.txt file except FileNotFoundError: - print("The 'Likes.txt' file was not found. Make sure it is in the program folder and try again.") - + print( + "The 'Likes.txt' file was not found. Make sure it is in the program folder and try again." + ) + # Error handling for MPV media player or MPV not found in PATH except subprocess.CalledProcessError: os.system("cls || clear") - print("Mpv media player was not found on your system path. Make sure it's installed and try again.") - + print( + "Mpv media player was not found on your system path. Make sure it's installed and try again." + ) + # Error handling for exiting the code with CTRL + C except KeyboardInterrupt: - print("\n\tKeyboardInterrupt was detected - Goodbye!") \ No newline at end of file + print("\n\tKeyboardInterrupt was detected - Goodbye!") diff --git a/setup.py b/setup.py index fcf9816..04e7f67 100644 --- a/setup.py +++ b/setup.py @@ -1,2 +1,3 @@ import os -os.system("pip install -r requirements.txt --user") \ No newline at end of file + +os.system("pip install -r requirements.txt --user") diff --git a/src/byuser.py b/src/byuser.py index fd0ac27..65798df 100644 --- a/src/byuser.py +++ b/src/byuser.py @@ -1,12 +1,16 @@ -import requests -import atoma import sys +import atoma +import requests + + def info(username): - response = requests.get(f'https://proxitok.pussthecat.org/@{username}/rss') + response = requests.get(f"https://proxitok.pussthecat.org/@{username}/rss") if response.status_code == 404: - print("Something went wrong while getting the information. Make sure the username was correctly inserted and try again.") + print( + "Something went wrong while getting the information. Make sure the username was correctly inserted and try again." + ) sys.exit() if str(response.content) == "b''": print("The specified account does not exist.") @@ -16,14 +20,15 @@ def info(username): # if feed.description == None: # print("This account does not have a bio.") # else: - #print(feed.description) ## TIKTOK BIO - + # print(feed.description) ## TIKTOK BIO + + def getLinks(username): feed = info(username) linklist = [] - + for i in range(len(feed.items)): - linklist.append('https://www.tiktok.com' + feed.items[i].link) + linklist.append("https://www.tiktok.com" + feed.items[i].link) return linklist @@ -35,4 +40,5 @@ def streamuser(username): for i in range(len(links)): from src.streaming import mpv - mpv(links[i]) \ No newline at end of file + + mpv(links[i]) diff --git a/src/downloader.py b/src/downloader.py index f9ede20..68d875e 100644 --- a/src/downloader.py +++ b/src/downloader.py @@ -1,43 +1,48 @@ -from src.functions import detect_dead_link -from src.functions import url_redirection +import os +from src.functions import detect_dead_link, url_redirection from yt_dlp import YoutubeDL -import os def downloader(url): ydl_opts = { - 'ignoreerrors': True, - 'format': 'bestvideo*+bestaudio/best', - 'outtmpl': os.getcwd()+'/video/by-creator/%(creator)s/%(id)s.%(ext)s' + "ignoreerrors": True, + "format": "bestvideo*+bestaudio/best", + "outtmpl": os.getcwd() + + "/video/by-creator/%(creator)s/%(id)s.%(ext)s", } YoutubeDL(ydl_opts).download(url) - + + def downloadtiktoks(urls): index = -1 errorcount = [] - a = input(f""" + a = input( + f""" **WARNING** This action will download up to {len(urls)} tiktoks in CLI-TIkTok/video/ Ensure you have enough free space before proceeding! \n\t\tPress ENTER to proceed... - """) - if a != '': - print('Operation canceled.') + """ + ) + if a != "": + print("Operation canceled.") return while True: try: randomvideo = index = index + 1 url = url_redirection(urls[randomvideo]) - + if detect_dead_link(url) == True: downloader(url) - print('') + print("") else: errorcount.append(urls) except IndexError: print("The tiktoks were downloaded") return if len(errorcount) != 0: - print(f'\n{len(errorcount)} video(s) failed to download.\nThe video(s) were likely banned or removed from the platform.') + print( + f"\n{len(errorcount)} video(s) failed to download.\nThe video(s) were likely banned or removed from the platform." + ) break diff --git a/src/functions.py b/src/functions.py index a5c3829..a64362e 100644 --- a/src/functions.py +++ b/src/functions.py @@ -1,12 +1,13 @@ -import requests -import random import os +import random + +import requests def listas(): - #Retrieves tiktok links and dates from Likes.txt + # Retrieves tiktok links and dates from Likes.txt i = 0 - arquivo = open('Likes.txt', 'r', encoding='utf-8') + arquivo = open("Likes.txt", "r", encoding="utf-8") linhas = arquivo.readlines() tamanho = len(linhas) arquivo.close() @@ -14,7 +15,7 @@ def listas(): vet = [] listalinks = [] listadatas = [] - arquivo = open('Likes.txt', 'r', encoding='utf-8') + arquivo = open("Likes.txt", "r", encoding="utf-8") while i <= tamanho: lelinha = arquivo.readline().rstrip() @@ -23,38 +24,40 @@ def listas(): arquivo.close() for i in range(2, len(vet), 3): - listalinks.append(vet[i-1][1]) + listalinks.append(vet[i - 1][1]) for i in range(2, len(vet), 3): - listadatas.append(vet[i-2][1] + ' ' + vet[i-2][2]) + listadatas.append(vet[i - 2][1] + " " + vet[i - 2][2]) return listalinks, listadatas -#Unused function - Might be useful in future iterations of the project -#https://github.com/nanometer5088/CLI-TikTok/commit/ad589d7b324042ee85a270625df3ad9f6f82ab8a +# Unused function - Might be useful in future iterations of the project +# https://github.com/nanometer5088/CLI-TikTok/commit/ad589d7b324042ee85a270625df3ad9f6f82ab8a def removevideo(): - if os.path.exists(os.getcwd()+"/video/video"): - os.remove(os.getcwd()+"/video/video") + if os.path.exists(os.getcwd() + "/video/video"): + os.remove(os.getcwd() + "/video/video") def detect_dead_link(url): - #Detects if the video is available to be streamed or downloaded. - dead_url_start_with = 'https://www.tiktok.com/@/video' - #No user on the @ means video was removed, taken down or isn't in a video format + # Detects if the video is available to be streamed or downloaded. + dead_url_start_with = "https://www.tiktok.com/@/video" + # No user on the @ means video was removed, taken down or isn't in a video format if dead_url_start_with in url: - return False # Means do not proceed with the download + return False # Means do not proceed with the download else: - return True # Means it's all clear to download. - + return True # Means it's all clear to download. + def url_redirection(url): - #Tiktok links from the Likes.txt are shortened. They need to be redirected to the final link, which is done here. - headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36'} + # Tiktok links from the Likes.txt are shortened. They need to be redirected to the final link, which is done here. + headers = { + "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" + } response = requests.get(url, headers=headers) return response.url def randomvideo(urls): - #Chooses a random video from Likes.txt - Optional Feature - return random.randint(0, (len(urls) - 1)) \ No newline at end of file + # Chooses a random video from Likes.txt - Optional Feature + return random.randint(0, (len(urls) - 1)) diff --git a/src/init.py b/src/init.py index 8229814..04b2c90 100644 --- a/src/init.py +++ b/src/init.py @@ -1,25 +1,32 @@ -from os import system import sys +from os import system + + def init(): - #Intro for the user + # Intro for the user system("cls || clear") - input("Welcome to CLI TikTok, an open-source TikTok archiver and viewer!\nPress ENTER to proceed") + input( + "Welcome to CLI TikTok, an open-source TikTok archiver and viewer!\nPress ENTER to proceed" + ) # Detect and install libraries - If they aren't installed, # the user is prompted to make the auto-installation. try: - import yt_dlp - import requests import atoma + import requests + import yt_dlp + system("cls || clear") except ModuleNotFoundError: system("cls || clear") - input(""" + input( + """ The program detected dependencies are not installed Press ENTER to install the necessary libraries (You will need to open the program again afterwards) - """) + """ + ) system("pip install -r requirements.txt --user") system("cls || clear") return -1 @@ -28,11 +35,15 @@ def init(): # If the user does not have internet access, warns him the software won't work properly and quit. try: import requests - data = requests.get("https://raw.githubusercontent.com/nanometer5088/CLI-TikTok/main/VERSION") - version = open('VERSION', 'r', encoding='utf=8') + + data = requests.get( + "https://raw.githubusercontent.com/nanometer5088/CLI-TikTok/main/VERSION" + ) + version = open("VERSION", "r", encoding="utf=8") if version.readline().rstrip() > (data.text): system("cls || clear") - input(""" + input( + """ There's a new version available! Updates bring performance and feature improvements! @@ -40,10 +51,15 @@ def init(): https://github.com/nanometer5088/CLI-TikTok/archive/refs/heads/main.zip Press ENTER to proceed - """) + """ + ) version.close() except requests.exceptions.ConnectionError: - 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( + "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("Please try again with an internet connection") - sys.exit() \ No newline at end of file + sys.exit() diff --git a/src/streaming.py b/src/streaming.py index e3688ff..103ce2e 100644 --- a/src/streaming.py +++ b/src/streaming.py @@ -1,34 +1,32 @@ -from src.functions import detect_dead_link -from src.functions import url_redirection +import os +import subprocess +from src.functions import detect_dead_link, url_redirection from yt_dlp import YoutubeDL -import subprocess -import os def getVideoInfo(url): - ydl_opts = { - "quiet": True, - "simulate": True, - "forceurl": True - } - + ydl_opts = {"quiet": True, "simulate": True, "forceurl": True} + return YoutubeDL(ydl_opts).extract_info(url)["url"] + def mpv(url): subprocess.check_output(f'mpv "{getVideoInfo(url)}"', shell=True) + def playbackrandom(urls, datas): while True: os.system("cls || clear") from src.functions import randomvideo + randomvideo = randomvideo(urls) url = url_redirection(urls[randomvideo]) - + if detect_dead_link(url) == True: - print(f'\nVideo Liked - {datas[randomvideo]}\n') + print(f"\nVideo Liked - {datas[randomvideo]}\n") mpv(url) - + def playback(urls, datas): index = 0 @@ -37,9 +35,9 @@ def playback(urls, datas): try: randomvideo = index = index + 1 url = url_redirection(urls[randomvideo]) - + if detect_dead_link(url) == True: - print(f'\nVideo Liked - {datas[randomvideo]}\n') + print(f"\nVideo Liked - {datas[randomvideo]}\n") mpv(url) except IndexError: print("All tiktoks were played.")