Started refactoring

pull/507/head
HallowedDust5 3 years ago
parent 4af7383e08
commit 9ad18a9004

@ -1,7 +1,5 @@
# Main # Main
from utils.console import print_markdown from utils.console import print_markdown
from utils.console import print_step
from utils.console import print_substep
from rich.console import Console from rich.console import Console
import time import time
from reddit.subreddit import get_subreddit_threads from reddit.subreddit import get_subreddit_threads
@ -9,13 +7,39 @@ from video_creation.background import download_background, chop_background_video
from video_creation.voices import save_text_to_mp3 from video_creation.voices import save_text_to_mp3
from video_creation.screenshot_downloader import download_screenshots_of_reddit_posts from video_creation.screenshot_downloader import download_screenshots_of_reddit_posts
from video_creation.final_video import make_final_video from video_creation.final_video import make_final_video
from utils.loader import Loader
from dotenv import load_dotenv from dotenv import load_dotenv
from pathlib import Path from pathlib import Path
from dotenv import load_dotenv
import os, time
"""TODO
- Refactor all .py files
- Write tests in tests/
"""
def main():
if envConfigured():
generateVideo()
def generateVideo():
# Video generation
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_background()
chop_background_video(length)
make_final_video(number_of_comments)
def envConfigured():
console = Console() console = Console()
from dotenv import load_dotenv
import os, time, shutil
configured = True configured = True
REQUIRED_VALUES = [ REQUIRED_VALUES = [
@ -32,10 +56,8 @@ print_markdown(
) )
""" """
Load .env file if exists. If it doesnt exist, print a warning and launch the setup wizard. 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. 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_id = os.getenv("REDDIT_CLIENT_ID")
@ -90,14 +112,8 @@ except:
configured = False configured = False
exit() exit()
console.log("[bold green]Enviroment Variables are set! Continuing...") console.log("[bold green]Enviroment Variables are set! Continuing...")
return configured
if configured:
# Video generation if __name__ == '__main__':
reddit_object = get_subreddit_threads() main()
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_background()
chop_background_video(length)
final_video = make_final_video(number_of_comments)

@ -7,23 +7,29 @@ import os, random, praw, re
def get_subreddit_threads(): def get_subreddit_threads():
global submission """Selects subreddit threads and returns them
"""
Returns a list of threads from the AskReddit subreddit. Returns:
dict[str]: Object of all the selected threads' data:
{
thread_post : str,
thread_title : str,
thread_post : str,
comments : list[dict],
}
`comments` is structured as follows:
{
comment_body : str,
comment_url : str,
comment_id : str,
}
""" """
global submission
load_dotenv() load_dotenv()
if os.getenv("REDDIT_2FA", default="no").casefold() == "yes": passkey = configurePasskey()
print(
"\nEnter your two-factor authentication code from your authenticator app.\n"
)
code = input("> ")
print()
pw = os.getenv("REDDIT_PASSWORD")
passkey = f"{pw}:{code}"
else:
passkey = os.getenv("REDDIT_PASSWORD")
content = {} content = {}
reddit = praw.Reddit( reddit = praw.Reddit(
@ -34,28 +40,7 @@ def get_subreddit_threads():
password=passkey, 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 pickThread(reddit)
if not os.getenv("RANDOM_THREAD") or os.getenv("RANDOM_THREAD") == "no":
print_substep("Insert the full thread link:", style="bold green")
thread_link = input()
print_step(f"Getting the inserted thread...")
submission = reddit.submission(url=thread_link)
else:
# Otherwise, picks a random thread from the inserted subreddit
if os.getenv("SUBREDDIT"):
subreddit = reddit.subreddit(re.sub(r"r\/", "", os.getenv("SUBREDDIT")))
else:
# ! Prompt the user to enter a subreddit
try:
subreddit = reddit.subreddit(
re.sub(r"r\/", "",input("What subreddit would you like to pull from? "))
)
except ValueError:
subreddit = reddit.subreddit("askreddit")
print_substep("Subreddit not defined. Using AskReddit.")
threads = subreddit.hot(limit=25)
submission = list(threads)[random.randrange(0, 25)]
print_substep(f"Video will be: {submission.title} :thumbsup:") print_substep(f"Video will be: {submission.title} :thumbsup:")
console.log("Getting video comments...") console.log("Getting video comments...")
@ -77,6 +62,44 @@ def get_subreddit_threads():
except AttributeError as e: except AttributeError as e:
pass pass
print_substep("Received AskReddit threads successfully.", style="bold green") print_substep("Received AskReddit threads successfully.", style="bold green")
return content return content
def pickThread(reddit):
# 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")
thread_link = input()
print_step(f"Getting the inserted thread...")
submission = reddit.submission(url=thread_link)
else:
# Otherwise, picks a random thread from the inserted subreddit
if os.getenv("SUBREDDIT"):
subreddit = reddit.subreddit(re.sub(r"r\/", "", os.getenv("SUBREDDIT")))
else:
# ! Prompt the user to enter a subreddit
try:
subreddit = reddit.subreddit(
re.sub(r"r\/", "",input("What subreddit would you like to pull from? "))
)
except ValueError:
subreddit = reddit.subreddit("askreddit")
print_substep("Subreddit not defined. Using AskReddit.")
threads = subreddit.hot(limit=25)
submission = list(threads)[random.randrange(0, 25)]
def configurePasskey():
if os.getenv("REDDIT_2FA", default="no").casefold() == "yes":
print(
"\nEnter your two-factor authentication code from your authenticator app.\n"
)
code = input("> ")
print()
pw = os.getenv("REDDIT_PASSWORD")
passkey = f"{pw}:{code}"
else:
passkey = os.getenv("REDDIT_PASSWORD")
return passkey

@ -7,6 +7,8 @@ Setup Script for RedditVideoMakerBot
# Imports # Imports
import os import os
import time import time
from setuptools import setup
from utils.console import print_markdown from utils.console import print_markdown
from utils.console import print_step from utils.console import print_step
from utils.console import print_substep from utils.console import print_substep
@ -15,6 +17,8 @@ from utils.loader import Loader
from pathlib import Path from pathlib import Path
console = Console() console = Console()
def main():
setup_done = Path(".setup-done-before").is_file() setup_done = Path(".setup-done-before").is_file()
if setup_done == True: if setup_done == True:
@ -31,24 +35,8 @@ 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." "### 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() ensureSetup()
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("Ensure you have the following ready to enter:")
console.log("[bold green]Reddit Client ID") console.log("[bold green]Reddit Client ID")
@ -60,9 +48,12 @@ 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]Subreddit (without r/ or /r/)")
console.log("[bold green]Theme (light or dark)") console.log("[bold green]Theme (light or dark)")
time.sleep(0.5) 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(
console.print("[green]If you do have these, type yes to continue. If you dont, go ahead and grab those quickly and come back.") "[green]If you don't have these, please follow the instructions in the README.md file to set them up.")
confirmUserHasCredentials = input("Are you sure you have the credentials? > ").casefold() 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": if confirmUserHasCredentials != "yes":
console.print("[red]I don't understand that.") console.print("[red]I don't understand that.")
console.print("[red]Exiting...") console.print("[red]Exiting...")
@ -71,10 +62,16 @@ else:
console.print("[bold green]Alright! Let's get started!") console.print("[bold green]Alright! Let's get started!")
time.sleep(1) time.sleep(1)
""" setup()
Begin the setup process. console.log("[bold green]Setup Complete! Returning...")
# Post-Setup: send message and try to run main.py again.
os.system("python3 main.py")
def setup():
"""
Begin the setup process.
""" """
console.log("Enter your credentials now.") console.log("Enter your credentials now.")
@ -112,11 +109,37 @@ with open('.env', 'a') as f:
f.write(f'OPACITY="{opacity}"\n') f.write(f'OPACITY="{opacity}"\n')
with open('.setup-done-before', 'a') as f: 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.") f.write(
"This file blocks the setup assistant from running again. Delete this file to run setup again.")
loader.stop() loader.stop()
console.log("[bold green]Setup Complete! Returning...")
# Post-Setup: send message and try to run main.py again. def ensureSetup():
os.system("python3 main.py") # 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)
if __name__ == '__main__':
main()

@ -19,7 +19,11 @@ W, H = 1080, 1920
def make_final_video(number_of_clips): def make_final_video(number_of_clips):
"""Generates and saves final video to assets/generated-videos
Args:
number_of_clips (int): The index of clips(comments) to go up to
"""
# Calls opacity from the .env # Calls opacity from the .env
load_dotenv() load_dotenv()
opacity = os.getenv('OPACITY') opacity = os.getenv('OPACITY')
@ -36,28 +40,11 @@ def make_final_video(number_of_clips):
.crop(x1=1166.6, y1=0, x2=2246.6, y2=1920) .crop(x1=1166.6, y1=0, x2=2246.6, y2=1920)
) )
# Gather all audio clips audio_clips, audio_composite = gatherAudioClips(number_of_clips)
audio_clips = []
for i in range(0, number_of_clips): image_clips = gatherImages(number_of_clips, opacity, audio_clips)
audio_clips.append(AudioFileClip(f"assets/mp3/{i}.mp3"))
audio_clips.insert(0, AudioFileClip(f"assets/mp3/title.mp3"))
try:
audio_clips.insert(1, AudioFileClip(f"assets/mp3/posttext.mp3"))
except:
OSError()
audio_concat = concatenate_audioclips(audio_clips)
audio_composite = CompositeAudioClip([audio_concat])
# Gather all images
image_clips = []
for i in range(0, number_of_clips):
image_clips.append(
ImageClip(f"assets/png/comment_{i}.png")
.set_duration(audio_clips[i + 1].duration)
.set_position("center")
.resize(width=W - 100)
.set_opacity(float(opacity)),
)
if Path(f"assets/mp3/posttext.mp3").is_file(): if Path(f"assets/mp3/posttext.mp3").is_file():
image_clips.insert( image_clips.insert(
0, 0,
@ -82,10 +69,57 @@ def make_final_video(number_of_clips):
image_concat.audio = audio_composite image_concat.audio = audio_composite
final = CompositeVideoClip([background_clip, image_concat]) final = CompositeVideoClip([background_clip, image_concat])
saveVideo(final)
def saveVideo(final):
"""Writes video to assets/generated videos
Args:
final (CompositeVideoClip): Final video object
"""
if not Path("assets/generated-videos").is_dir(): if not Path("assets/generated-videos").is_dir():
Path.mkdir("assets/generated-videos") Path.mkdir("assets/generated-videos")
raw_filename = Path("assets", "generated-videos") / (reddit.subreddit.submission.title + ".mp4") raw_filename = Path("assets", "generated-videos") / (reddit.subreddit.submission.title + ".mp4")
cleaned_filename = (re.sub('[?\"%*:|<>]', '', str(raw_filename))) cleaned_filename = (re.sub('[?\"%*:|<>]', '', str(raw_filename)))
final.write_videofile(cleaned_filename, fps=30, audio_codec="aac", audio_bitrate="192k") final.write_videofile(cleaned_filename, fps=30, audio_codec="aac", audio_bitrate="192k")
def gatherImages(number_of_clips, opacity, audio_clips):
"""Gathers thread screenshots from assets/png
Args:
number_of_clips (int): number of screenshots to be put into the video
opacity (float): how clear the comment is going to be in the video
audio_clips (list[AudioFileClip]): TTS of the thread
Returns:
list[ImageClip]: all the comments with TTS over it
"""
# Gather all images
image_clips = []
for i in range(0, number_of_clips):
image_clips.append(
ImageClip(f"assets/png/comment_{i}.png")
.set_duration(audio_clips[i + 1].duration)
.set_position("center")
.resize(width=W - 100)
.set_opacity(float(opacity)),
)
return image_clips
def gatherAudioClips(number_of_clips):
# Gather all audio clips
audio_clips = []
for i in range(0, number_of_clips):
audio_clips.append(AudioFileClip(f"assets/mp3/{i}.mp3"))
audio_clips.insert(0, AudioFileClip(f"assets/mp3/title.mp3"))
try:
audio_clips.insert(1, AudioFileClip(f"assets/mp3/posttext.mp3"))
except:
OSError()
audio_concat = concatenate_audioclips(audio_clips)
audio_composite = CompositeAudioClip([audio_concat])
return audio_clips,audio_composite
Loading…
Cancel
Save