Merge pull request #125 from BlockArchitech/master
Create setup TUI and improve overall UX
This commit is contained in:
6 files changed
+272
-18
No files matched your search
@@ -1,6 +1,10 @@
|
||||
assets/
|
||||
reddit/__pycache__/
|
||||
utils/__pycache__/
|
||||
.env
|
||||
reddit-bot-351418-5560ebc49cac.json
|
||||
video_creation/__pycache__/
|
||||
.setup-done-before
|
||||
__pycache__
|
||||
.idea/
|
||||
.DS_Store
|
||||
|
||||
@@ -32,11 +32,17 @@ These videos on TikTok, YouTube and Instagram get MILLIONS of views across all p
|
||||
## Installation 👩💻
|
||||
|
||||
1. Clone this repository
|
||||
2. Rename `.env.template` to `.env` and replace all values with the appropriate fields. To get Reddit keys (**required**), visit [the Reddit Apps page.](https://www.reddit.com/prefs/apps) TL;DR set up an app that is a "script". Copy your keys into the `.env` file, along with whether your account uses two-factor authentication.
|
||||
3. Run `pip3 install -r requirements.txt`
|
||||
4. Run `playwright install` and `playwright install-deps`.
|
||||
5. Run `python3 main.py`
|
||||
6. Enjoy 😎
|
||||
|
||||
2. Run `pip3 install -r requirements.txt`
|
||||
3. Run `playwright install` and `playwright install-deps`.
|
||||
4.
|
||||
4a **Automatic Install**: Run `python3 main.py` and type 'yes' to activate the setup assistant.
|
||||
|
||||
4b **Manual Install**: Rename `.env.template` to `.env` and replace all values with the appropriate fields. To get Reddit keys (**required**), visit [the Reddit Apps page.](https://www.reddit.com/prefs/apps) TL;DR set up an app that is a "script". Copy your keys into the `.env` file, along with whether your account uses two-factor authentication.
|
||||
|
||||
5. Run `python3 main.py` (unless you chose automatic install, then the installer will automatically run main.py)
|
||||
7. Enjoy 😎
|
||||
|
||||
|
||||
If you want to see more detailed guide, please refer to the official [documentation](https://luka-hietala.gitbook.io/documentation-for-the-reddit-bot/).
|
||||
\*The Documentation is still being developed and worked on, please be patient as we change / add new knowledge!
|
||||
|
||||
@@ -1,43 +1,112 @@
|
||||
# Main
|
||||
from utils.console import print_markdown
|
||||
from utils.console import print_step
|
||||
from utils.console import print_substep
|
||||
from rich.console import Console
|
||||
import time
|
||||
from reddit.subreddit import get_subreddit_threads
|
||||
from video_creation.background import download_background, chop_background_video
|
||||
from video_creation.voices import save_text_to_mp3
|
||||
from video_creation.screenshot_downloader import download_screenshots_of_reddit_posts
|
||||
from video_creation.final_video import make_final_video
|
||||
from utils.loader import Loader
|
||||
from dotenv import load_dotenv
|
||||
|
||||
console = Console()
|
||||
from dotenv import load_dotenv
|
||||
import os, time, shutil
|
||||
|
||||
REQUIRED_VALUES = ["REDDIT_CLIENT_ID","REDDIT_CLIENT_SECRET","REDDIT_USERNAME","REDDIT_PASSWORD", "OPACITY"]
|
||||
configured = True
|
||||
REQUIRED_VALUES = [
|
||||
"REDDIT_CLIENT_ID",
|
||||
"REDDIT_CLIENT_SECRET",
|
||||
"REDDIT_USERNAME",
|
||||
"REDDIT_PASSWORD",
|
||||
"OPACITY",
|
||||
]
|
||||
|
||||
|
||||
print_markdown(
|
||||
"### Thanks for using this tool! [Feel free to contribute to this project on GitHub!](https://lewismenelaws.com) If you have any questions, feel free to reach out to me on Twitter or submit a GitHub issue."
|
||||
)
|
||||
|
||||
time.sleep(3)
|
||||
"""
|
||||
|
||||
Load .env file if exists. If it doesnt exist, print a warning and launch the setup wizard.
|
||||
If there is a .env file, check if the required variables are set. If not, print a warning and launch the setup wizard.
|
||||
|
||||
"""
|
||||
|
||||
client_id = os.getenv("REDDIT_CLIENT_ID")
|
||||
client_secret = os.getenv("REDDIT_CLIENT_SECRET")
|
||||
username = os.getenv("REDDIT_USERNAME")
|
||||
password = os.getenv("REDDIT_PASSWORD")
|
||||
reddit2fa = os.getenv("REDDIT_2FA")
|
||||
|
||||
load_dotenv()
|
||||
|
||||
configured = True
|
||||
console.log("[bold green]Checking environment variables...")
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
if not os.path.exists(".env"):
|
||||
shutil.copy(".env.template", ".env")
|
||||
configured = False
|
||||
console.log("[red] Your .env file is invalid, or was never created. Standby.")
|
||||
|
||||
for val in REQUIRED_VALUES:
|
||||
print(os.getenv(val))
|
||||
if val not in os.environ or not os.getenv(val):
|
||||
print(f"Please set the variable \"{val}\" in your .env file.")
|
||||
console.log(f'[bold red]Missing Variable: "{val}"')
|
||||
configured = False
|
||||
console.log(
|
||||
"[red]Looks like you need to set your Reddit credentials in the .env file. Please follow the instructions in the README.md file to set them up."
|
||||
)
|
||||
time.sleep(0.5)
|
||||
console.log(
|
||||
"[red]We can also launch the easy setup wizard. type yes to launch it, or no to quit the program."
|
||||
)
|
||||
setup_ask = input("Launch setup wizard? > ")
|
||||
if setup_ask == "yes":
|
||||
console.log("[bold green]Here goes nothing! Launching setup wizard...")
|
||||
time.sleep(0.5)
|
||||
os.system("python3 setup.py")
|
||||
else:
|
||||
if setup_ask == "no":
|
||||
console.print("[red]Exiting...")
|
||||
time.sleep(0.5)
|
||||
exit()
|
||||
else:
|
||||
console.print("[red]I don't understand that. Exiting...")
|
||||
time.sleep(0.5)
|
||||
exit()
|
||||
|
||||
exit()
|
||||
try:
|
||||
float(os.getenv("OPACITY"))
|
||||
except:
|
||||
print(f"Please ensure that OPACITY is set between 0 and 1 in your .env file")
|
||||
console.log(
|
||||
f"[red]Please ensure that OPACITY is set between 0 and 1 in your .env file"
|
||||
)
|
||||
configured = False
|
||||
exit()
|
||||
console.log("[bold green]Enviroment Variables are set! Continuing...")
|
||||
|
||||
|
||||
length, number_of_comments = save_text_to_mp3(reddit_object)
|
||||
download_screenshots_of_reddit_posts(
|
||||
reddit_object, number_of_comments, os.getenv("THEME")
|
||||
)
|
||||
download_background()
|
||||
chop_background_video(length)
|
||||
final_video = make_final_video(number_of_comments)
|
||||
|
||||
|
||||
if configured:
|
||||
reddit_object = get_subreddit_threads()
|
||||
length, number_of_comments = save_text_to_mp3(reddit_object)
|
||||
download_screenshots_of_reddit_posts(reddit_object, number_of_comments, os.getenv("THEME", "light"))
|
||||
download_screenshots_of_reddit_posts(
|
||||
reddit_object, number_of_comments, os.getenv("THEME", "light")
|
||||
)
|
||||
download_background()
|
||||
chop_background_video(length)
|
||||
final_video = make_final_video(number_of_comments)
|
||||
+6
-6
@@ -1,5 +1,8 @@
|
||||
from rich.console import Console
|
||||
from utils.console import print_markdown, print_step, print_substep
|
||||
from dotenv import load_dotenv
|
||||
|
||||
console = Console()
|
||||
import os, random, praw, re
|
||||
|
||||
|
||||
@@ -23,7 +26,6 @@ def get_subreddit_threads():
|
||||
passkey = os.getenv("REDDIT_PASSWORD")
|
||||
|
||||
content = {}
|
||||
|
||||
reddit = praw.Reddit(
|
||||
client_id=os.getenv("REDDIT_CLIENT_ID"),
|
||||
client_secret=os.getenv("REDDIT_CLIENT_SECRET"),
|
||||
@@ -31,6 +33,7 @@ def get_subreddit_threads():
|
||||
username=os.getenv("REDDIT_USERNAME"),
|
||||
password=passkey,
|
||||
)
|
||||
|
||||
# If the user specifies that he doesnt want a random thread, or if he doesn't insert the "RANDOM_THREAD" variable at all, ask the thread link
|
||||
if not os.getenv("RANDOM_THREAD") or os.getenv("RANDOM_THREAD") == "no":
|
||||
print_substep("Insert the full thread link:", style="bold green")
|
||||
@@ -45,11 +48,7 @@ def get_subreddit_threads():
|
||||
# ! Prompt the user to enter a subreddit
|
||||
try:
|
||||
subreddit = reddit.subreddit(
|
||||
re.sub(
|
||||
r"r\/",
|
||||
"",
|
||||
input("What subreddit would you like to pull from? "),
|
||||
)
|
||||
re.sub(r"r\/", "",input("What subreddit would you like to pull from? "))
|
||||
)
|
||||
except ValueError:
|
||||
subreddit = reddit.subreddit("askreddit")
|
||||
@@ -59,6 +58,7 @@ def get_subreddit_threads():
|
||||
submission = list(threads)[random.randrange(0, 25)]
|
||||
|
||||
print_substep(f"Video will be: {submission.title} :thumbsup:")
|
||||
console.log("Getting video comments...")
|
||||
try:
|
||||
content["thread_url"] = submission.url
|
||||
content["thread_title"] = submission.title
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
"""
|
||||
|
||||
Setup Script for RedditVideoMakerBot
|
||||
|
||||
"""
|
||||
|
||||
# Imports
|
||||
import os
|
||||
import time
|
||||
from utils.console import print_markdown
|
||||
from utils.console import print_step
|
||||
from utils.console import print_substep
|
||||
from rich.console import Console
|
||||
from utils.loader import Loader
|
||||
from os.path import exists
|
||||
console = Console()
|
||||
|
||||
setup_done = exists(".setup-done-before")
|
||||
|
||||
if setup_done == True:
|
||||
console.log("[red]Setup was already completed! Please make sure you have to run this script again. If you have to, please delete the file .setup-done-before")
|
||||
exit()
|
||||
|
||||
# These lines ensure the user:
|
||||
# - knows they are in setup mode
|
||||
# - knows that they are about to erase any other setup files/data.
|
||||
|
||||
print_step("Setup Assistant")
|
||||
|
||||
print_markdown(
|
||||
"### You're in the setup wizard. Ensure you're supposed to be here, then type yes to continue. If you're not sure, type no to quit."
|
||||
)
|
||||
|
||||
# This Input is used to ensure the user is sure they want to continue.
|
||||
ensureSetupIsRequired = input("Are you sure you want to continue? > ").casefold()
|
||||
if ensureSetupIsRequired != "yes":
|
||||
console.print("[red]Exiting...")
|
||||
time.sleep(0.5)
|
||||
exit()
|
||||
else:
|
||||
# Again, let them know they are about to erase all other setup data.
|
||||
console.print("[bold red] This will overwrite your current settings. Are you sure you want to continue? [bold green]yes/no")
|
||||
overwriteSettings = input("Are you sure you want to continue? > ").casefold()
|
||||
if overwriteSettings != "yes":
|
||||
console.print("[red]Abort mission! Exiting...")
|
||||
time.sleep(0.5)
|
||||
exit()
|
||||
else:
|
||||
# Once they confirm, move on with the script.
|
||||
console.print("[bold green]Alright! Let's get started!")
|
||||
time.sleep(1)
|
||||
|
||||
console.log("Ensure you have the following ready to enter:")
|
||||
console.log("[bold green]Reddit Client ID")
|
||||
console.log("[bold green]Reddit Client Secret")
|
||||
console.log("[bold green]Reddit Username")
|
||||
console.log("[bold green]Reddit Password")
|
||||
console.log("[bold green]Reddit 2FA (yes or no)")
|
||||
console.log("[bold green]Opacity (range of 0-1, decimals are OK)")
|
||||
console.log("[bold green]Subreddit (without r/ or /r/)")
|
||||
console.log("[bold green]Theme (light or dark)")
|
||||
time.sleep(0.5)
|
||||
console.print("[green]If you don't have these, please follow the instructions in the README.md file to set them up.")
|
||||
console.print("[green]If you do have these, type yes to continue. If you dont, go ahead and grab those quickly and come back.")
|
||||
confirmUserHasCredentials = input("Are you sure you have the credentials? > ").casefold()
|
||||
if confirmUserHasCredentials != "yes":
|
||||
console.print("[red]I don't understand that.")
|
||||
console.print("[red]Exiting...")
|
||||
exit()
|
||||
else:
|
||||
console.print("[bold green]Alright! Let's get started!")
|
||||
time.sleep(1)
|
||||
|
||||
"""
|
||||
|
||||
Begin the setup process.
|
||||
|
||||
"""
|
||||
|
||||
console.log("Enter your credentials now.")
|
||||
cliID = input("Client ID > ")
|
||||
cliSec = input("Client Secret > ")
|
||||
user = input("Username > ")
|
||||
passw = input("Password > ")
|
||||
twofactor = input("2fa Enabled? (yes/no) > ")
|
||||
opacity = input("Opacity? (range of 0-1) > ")
|
||||
subreddit = input("Subreddit (without r/) > ")
|
||||
theme = input("Theme? (light or dark) > ")
|
||||
console.log("Attempting to save your credentials...")
|
||||
loader = Loader("Saving Credentials...", "Done!").start()
|
||||
# you can also put a while loop here, e.g. while VideoIsBeingMade == True: ...
|
||||
time.sleep(0.5)
|
||||
console.log("Removing old .env file...")
|
||||
os.remove(".env")
|
||||
time.sleep(0.5)
|
||||
console.log("Creating new .env file...")
|
||||
with open('.env', 'a') as f:
|
||||
f.write(f'REDDIT_CLIENT_ID="{cliID}"\n')
|
||||
time.sleep(0.5)
|
||||
f.write(f'REDDIT_CLIENT_SECRET="{cliSec}"\n')
|
||||
time.sleep(0.5)
|
||||
f.write(f'REDDIT_USERNAME="{user}"\n')
|
||||
time.sleep(0.5)
|
||||
f.write(f'REDDIT_PASSWORD="{passw}"\n')
|
||||
time.sleep(0.5)
|
||||
f.write(f'REDDIT_2FA="{twofactor}"\n')
|
||||
time.sleep(0.5)
|
||||
f.write(f'THEME="{theme}"\n')
|
||||
time.sleep(0.5)
|
||||
f.write(f'SUBREDDIT="{subreddit}"\n')
|
||||
time.sleep(0.5)
|
||||
f.write(f'OPACITY="{opacity}"\n')
|
||||
|
||||
with open('.setup-done-before', 'a') as f:
|
||||
f.write("This file blocks the setup assistant from running again. Delete this file to run setup again.")
|
||||
|
||||
loader.stop()
|
||||
|
||||
console.log("[bold green]Setup Complete! Returning...")
|
||||
|
||||
# Post-Setup: send message and try to run main.py again.
|
||||
os.system("python3 main.py")
|
||||
@@ -0,0 +1,53 @@
|
||||
"""
|
||||
|
||||
Okay, have to admit. This code is from StackOverflow. It's so efficient, that it's probably the best way to do it.
|
||||
Although, it is edited to use less threads.
|
||||
|
||||
"""
|
||||
from itertools import cycle
|
||||
from shutil import get_terminal_size
|
||||
from threading import Thread
|
||||
from time import sleep
|
||||
|
||||
|
||||
class Loader:
|
||||
def __init__(self, desc="Loading...", end="Done!", timeout=0.1):
|
||||
"""
|
||||
A loader-like context manager
|
||||
|
||||
Args:
|
||||
desc (str, optional): The loader's description. Defaults to "Loading...".
|
||||
end (str, optional): Final print. Defaults to "Done!".
|
||||
timeout (float, optional): Sleep time between prints. Defaults to 0.1.
|
||||
"""
|
||||
self.desc = desc
|
||||
self.end = end
|
||||
self.timeout = timeout
|
||||
|
||||
self._thread = Thread(target=self._animate, daemon=True)
|
||||
self.steps = ["⢿", "⣻", "⣽", "⣾", "⣷", "⣯", "⣟", "⡿"]
|
||||
self.done = False
|
||||
|
||||
def start(self):
|
||||
self._thread.start()
|
||||
return self
|
||||
|
||||
def _animate(self):
|
||||
for c in cycle(self.steps):
|
||||
if self.done:
|
||||
break
|
||||
print(f"\r{self.desc} {c}", flush=True, end="")
|
||||
sleep(self.timeout)
|
||||
|
||||
def __enter__(self):
|
||||
self.start()
|
||||
|
||||
def stop(self):
|
||||
self.done = True
|
||||
cols = get_terminal_size((80, 20)).columns
|
||||
print("\r" + " " * cols, end="", flush=True)
|
||||
print(f"\r{self.end}", flush=True)
|
||||
|
||||
def __exit__(self, exc_type, exc_value, tb):
|
||||
# handle exceptions with those variables ^
|
||||
self.stop()
|
||||
Reference in new issue
Block a user