cleaning spaghetti code

pull/2337/head
electro199 3 months ago
parent 64bf647de9
commit 39412e2a35

@ -4,17 +4,17 @@ import sys
from os import name
from pathlib import Path
from subprocess import Popen
from typing import NoReturn
from typing import Dict, NoReturn, Optional
from prawcore import ResponseException
from reddit.subreddit import get_subreddit_threads
from utils import settings
from utils.cleanup import cleanup
from utils.console import print_markdown, print_step, print_substep
from utils.console import print_markdown, print_step, format_ordinal
from utils.ffmpeg_install import ffmpeg_install
from utils.id import id
from utils.version import checkversion
from utils.id import extract_id
from utils.version import checkversion, check_python
from video_creation.background import (
chop_background,
download_background_audio,
@ -38,15 +38,20 @@ print(
"""
)
print_markdown(
"### Thanks for using this tool! Feel free to contribute to this project on GitHub! If you have any questions, feel free to join my Discord server or submit a GitHub issue. You can find solutions to many common problems in the documentation: https://reddit-video-maker-bot.netlify.app/"
"### Thanks for using this tool! Feel free to contribute to this project on GitHub! If you have any questions,"
" feel free to join my Discord server or submit a GitHub issue."
" You can find solutions to many common problems in the documentation: https://reddit-video-maker-bot.netlify.app/"
)
checkversion(__VERSION__)
reddit_id: Optional[str] = None
reddit_object: Dict[str, str | list]
def main(POST_ID=None) -> None:
global redditid, reddit_object
reddit_object = get_subreddit_threads(POST_ID)
redditid = id(reddit_object)
redditid = extract_id(reddit_object)
length, number_of_comments = save_text_to_mp3(reddit_object)
length = math.ceil(length)
get_screenshots_of_reddit_posts(reddit_object, number_of_comments)
@ -63,14 +68,14 @@ def main(POST_ID=None) -> None:
def run_many(times) -> None:
for x in range(1, times + 1):
print_step(
f'on the {x}{("th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th")[x % 10]} iteration of {times}'
f"on the {format_ordinal(x)} iteration of {times}"
) # correct 1st 2nd 3rd 4th 5th....
main()
Popen("cls" if name == "nt" else "clear", shell=True).wait()
def shutdown() -> NoReturn:
if "redditid" in globals():
if reddit_id is not None:
print_markdown("## Clearing temp files")
cleanup(redditid)
@ -79,33 +84,19 @@ def shutdown() -> NoReturn:
if __name__ == "__main__":
if sys.version_info.major != 3 or sys.version_info.minor not in [10, 11]:
print(
"Hey! Congratulations, you've made it so far (which is pretty rare with no Python 3.10). Unfortunately, this program only works on Python 3.10. Please install Python 3.10 and try again."
)
sys.exit()
check_python()
ffmpeg_install()
directory = Path().absolute()
config = settings.check_toml(
f"{directory}/utils/.config.template.toml", f"{directory}/config.toml"
)
config is False and sys.exit()
config = settings.get_config(directory)
if (
not settings.config["settings"]["tts"]["tiktok_sessionid"]
or settings.config["settings"]["tts"]["tiktok_sessionid"] == ""
) and config["settings"]["tts"]["voice_choice"] == "tiktok":
print_substep(
"TikTok voice requires a sessionid! Check our documentation on how to obtain one.",
"bold red",
)
sys.exit()
try:
if config["reddit"]["thread"]["post_id"]:
for index, post_id in enumerate(config["reddit"]["thread"]["post_id"].split("+")):
for index, post_id in enumerate(
config["reddit"]["thread"]["post_id"].split("+")
):
index += 1
print_step(
f'on the {index}{("st" if index % 10 == 1 else ("nd" if index % 10 == 2 else ("rd" if index % 10 == 3 else "th")))} post of {len(config["reddit"]["thread"]["post_id"].split("+"))}'
f'on the {format_ordinal(index)} post of {len(config["reddit"]["thread"]["post_id"].split("+"))}'
)
main(post_id)
Popen("cls" if name == "nt" else "clear", shell=True).wait()

@ -118,3 +118,15 @@ def handle_input(
console.print(
"[red bold]" + err_message + "\nValid options are: " + ", ".join(map(str, options)) + "."
)
def format_ordinal(x):
if 10 <= x % 100 <= 20:
suffix = 'th'
else:
suffix = {1: 'st', 2: 'nd', 3: 'rd'}.get(x % 10, 'th')
return f"{x}{suffix}"
if __name__ == "__main__":
for i in range(20):
print(format_ordinal(i))

@ -3,7 +3,7 @@ import re
from utils.console import print_substep
def id(reddit_obj: dict):
def extract_id(reddit_obj: dict):
"""
This function takes a reddit object and returns the post id
"""

@ -1,11 +1,12 @@
import re
from pathlib import Path
from typing import Dict, Tuple
import sys
from typing import Any, Dict, Literal, Tuple
import toml
from rich.console import Console
from utils.console import handle_input
from utils.console import handle_input, print_substep
console = Console()
config = dict # autocomplete
@ -53,7 +54,11 @@ def check(value, checks, name):
and not hasattr(value, "__iter__")
and (
("nmin" in checks and checks["nmin"] is not None and value < checks["nmin"])
or ("nmax" in checks and checks["nmax"] is not None and value > checks["nmax"])
or (
"nmax" in checks
and checks["nmax"] is not None
and value > checks["nmax"]
)
)
):
incorrect = True
@ -61,8 +66,16 @@ def check(value, checks, name):
not incorrect
and hasattr(value, "__iter__")
and (
("nmin" in checks and checks["nmin"] is not None and len(value) < checks["nmin"])
or ("nmax" in checks and checks["nmax"] is not None and len(value) > checks["nmax"])
(
"nmin" in checks
and checks["nmin"] is not None
and len(value) < checks["nmin"]
)
or (
"nmax" in checks
and checks["nmax"] is not None
and len(value) > checks["nmax"]
)
)
):
incorrect = True
@ -70,9 +83,15 @@ def check(value, checks, name):
if incorrect:
value = handle_input(
message=(
(("[blue]Example: " + str(checks["example"]) + "\n") if "example" in checks else "")
(
("[blue]Example: " + str(checks["example"]) + "\n")
if "example" in checks
else ""
)
+ "[red]"
+ ("Non-optional ", "Optional ")["optional" in checks and checks["optional"] is True]
+ ("Non-optional ", "Optional ")[
"optional" in checks and checks["optional"] is True
]
)
+ "[#C0CAF5 bold]"
+ str(name)
@ -107,13 +126,15 @@ def check_vars(path, checks):
crawl_and_check(config, path, checks)
def check_toml(template_file, config_file) -> Tuple[bool, Dict]:
def check_toml(template_file, config_file) -> Dict[str, Any] | None | Literal[False]:
global config
config = None
try:
template = toml.load(template_file)
except Exception as error:
console.print(f"[red bold]Encountered error when trying to to load {template_file}: {error}")
console.print(
f"[red bold]Encountered error when trying to to load {template_file}: {error}"
)
return False
try:
config = toml.load(config_file)
@ -164,6 +185,25 @@ If you see any prompts, that means that you have unset/incorrectly set variables
toml.dump(config, f)
return config
def get_config(directory):
config = check_toml(
f"{directory}/utils/.config.template.toml", f"{directory}/config.toml"
)
if not config:
sys.exit()
if (
not config["settings"]["tts"]["tiktok_sessionid"]
or config["settings"]["tts"]["tiktok_sessionid"] == ""
) and config["settings"]["tts"]["voice_choice"] == "tiktok":
print_substep(
"TikTok voice requires a sessionid! Check our documentation on how to obtain one.",
"bold red",
)
sys.exit()
return config
if __name__ == "__main__":
directory = Path().absolute()

@ -1,3 +1,4 @@
import sys
import requests
from utils.console import print_step
@ -19,3 +20,11 @@ def checkversion(__VERSION__: str):
print_step(
f"Welcome to the test version ({__VERSION__}) of the bot. Thanks for testing and feel free to report any bugs you find."
)
def check_python() -> None:
minor_versions = [10, 11, 12, 13]
if sys.version_info.major != 3 or sys.version_info.minor not in minor_versions:
print(
f"Hey! Congratulations, you've made it so far (which is pretty rare with no Python 3.{minor_versions}). Unfortunately, this program only works on Python 3.{minor_versions}. Please install Python 3.{minor_versions} and try again."
)
sys.exit()

@ -2,7 +2,6 @@ import multiprocessing
import os
import re
import tempfile
import textwrap
import threading
import time
from os.path import exists # Needs to be imported specifically
@ -11,16 +10,16 @@ from typing import Dict, Final, Tuple
import ffmpeg
import translators
from PIL import Image, ImageDraw, ImageFont
from PIL import Image
from rich.console import Console
from rich.progress import track
from utils import settings
from utils.cleanup import cleanup
from utils.console import print_step, print_substep
from utils.fonts import getheight
from utils.thumbnail import create_thumbnail
from utils.videos import save_data
from video_creation.thumbnail import background_thumbnail
from .thumbnail import create_fancy_thumbnail
console = Console()
@ -108,63 +107,6 @@ def prepare_background(reddit_id: str, W: int, H: int) -> str:
return output_path
def create_fancy_thumbnail(image, text, text_color, padding, wrap=35):
print_step(f"Creating fancy thumbnail for: {text}")
font_title_size = 47
font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), font_title_size)
image_width, image_height = image.size
lines = textwrap.wrap(text, width=wrap)
y = (
(image_height / 2)
- (((getheight(font, text) + (len(lines) * padding) / len(lines)) * len(lines)) / 2)
+ 30
)
draw = ImageDraw.Draw(image)
username_font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), 30)
draw.text(
(205, 825),
settings.config["settings"]["channel_name"],
font=username_font,
fill=text_color,
align="left",
)
if len(lines) == 3:
lines = textwrap.wrap(text, width=wrap + 10)
font_title_size = 40
font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), font_title_size)
y = (
(image_height / 2)
- (((getheight(font, text) + (len(lines) * padding) / len(lines)) * len(lines)) / 2)
+ 35
)
elif len(lines) == 4:
lines = textwrap.wrap(text, width=wrap + 10)
font_title_size = 35
font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), font_title_size)
y = (
(image_height / 2)
- (((getheight(font, text) + (len(lines) * padding) / len(lines)) * len(lines)) / 2)
+ 40
)
elif len(lines) > 4:
lines = textwrap.wrap(text, width=wrap + 10)
font_title_size = 30
font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), font_title_size)
y = (
(image_height / 2)
- (((getheight(font, text) + (len(lines) * padding) / len(lines)) * len(lines)) / 2)
+ 30
)
for line in lines:
draw.text((120, y), line, font=font, fill=text_color, align="left")
y += getheight(font, line) + padding
return image
def merge_background_audio(audio: ffmpeg, reddit_id: str):
"""Gather an audio and merge with assets/backgrounds/background.mp3
Args:
@ -266,17 +208,12 @@ def make_final_video(
# get the title_template image and draw a text in the middle part of it with the title of the thread
title_template = Image.open("assets/title_template.png")
title = reddit_obj["thread_title"]
title = name_normalize(title)
title = name_normalize(reddit_obj["thread_title"])
font_color = "#000000"
padding = 5
# create_fancy_thumbnail(image, text, text_color, padding
title_img = create_fancy_thumbnail(title_template, title, font_color, padding)
title_img.save(f"assets/temp/{reddit_id}/png/title.png")
image_clips.insert(
0,
ffmpeg.input(f"assets/temp/{reddit_id}/png/title.png")["v"].filter(
@ -362,36 +299,7 @@ def make_final_video(
settingsbackground = settings.config["settings"]["background"]
if settingsbackground["background_thumbnail"]:
if not exists(f"./results/{subreddit}/thumbnails"):
print_substep(
"The 'results/thumbnails' folder could not be found so it was automatically created."
)
os.makedirs(f"./results/{subreddit}/thumbnails")
# get the first file with the .png extension from assets/backgrounds and use it as a background for the thumbnail
first_image = next(
(file for file in os.listdir("assets/backgrounds") if file.endswith(".png")),
None,
)
if first_image is None:
print_substep("No png files found in assets/backgrounds", "red")
else:
font_family = settingsbackground["background_thumbnail_font_family"]
font_size = settingsbackground["background_thumbnail_font_size"]
font_color = settingsbackground["background_thumbnail_font_color"]
thumbnail = Image.open(f"assets/backgrounds/{first_image}")
width, height = thumbnail.size
thumbnailSave = create_thumbnail(
thumbnail,
font_family,
font_size,
font_color,
width,
height,
title_thumb,
)
thumbnailSave.save(f"./assets/temp/{reddit_id}/thumbnail.png")
print_substep(f"Thumbnail - Building Thumbnail in assets/temp/{reddit_id}/thumbnail.png")
background_thumbnail(reddit_id, title_thumb, subreddit)
text = f"Background by {background_config['video'][2]}"
background_clip = ffmpeg.drawtext(

@ -0,0 +1,100 @@
import os
import textwrap
from os.path import exists
from PIL import Image, ImageDraw, ImageFont
from utils import settings
from utils.console import print_step, print_substep
from utils.fonts import getheight
from utils.thumbnail import create_thumbnail
def create_fancy_thumbnail(image, text, text_color, padding, wrap=35):
print_step(f"Creating fancy thumbnail for: {text}")
font_title_size = 47
font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), font_title_size)
image_width, image_height = image.size
lines = textwrap.wrap(text, width=wrap)
y = (
(image_height / 2)
- (((getheight(font, text) + (len(lines) * padding) / len(lines)) * len(lines)) / 2)
+ 30
)
draw = ImageDraw.Draw(image)
username_font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), 30)
draw.text(
(205, 825),
settings.config["settings"]["channel_name"],
font=username_font,
fill=text_color,
align="left",
)
if len(lines) == 3:
lines = textwrap.wrap(text, width=wrap + 10)
font_title_size = 40
font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), font_title_size)
y = (
(image_height / 2)
- (((getheight(font, text) + (len(lines) * padding) / len(lines)) * len(lines)) / 2)
+ 35
)
elif len(lines) == 4:
lines = textwrap.wrap(text, width=wrap + 10)
font_title_size = 35
font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), font_title_size)
y = (
(image_height / 2)
- (((getheight(font, text) + (len(lines) * padding) / len(lines)) * len(lines)) / 2)
+ 40
)
elif len(lines) > 4:
lines = textwrap.wrap(text, width=wrap + 10)
font_title_size = 30
font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), font_title_size)
y = (
(image_height / 2)
- (((getheight(font, text) + (len(lines) * padding) / len(lines)) * len(lines)) / 2)
+ 30
)
for line in lines:
draw.text((120, y), line, font=font, fill=text_color, align="left")
y += getheight(font, line) + padding
return image
def background_thumbnail(reddit_id, title_thumb, subreddit):
if not exists(f"./results/{subreddit}/thumbnails"):
print_substep(
"The 'results/thumbnails' folder could not be found so it was automatically created."
)
os.makedirs(f"./results/{subreddit}/thumbnails")
# get the first file with the .png extension from assets/backgrounds and use it as a background for the thumbnail
first_image = next(
(file for file in os.listdir("assets/backgrounds") if file.endswith(".png")),
None,
)
if first_image is None:
print_substep("No png files found in assets/backgrounds", "red")
else:
font_family = settings.config["settings"]["background"]["background_thumbnail_font_family"]
font_size = settings.config["settings"]["background"]["background_thumbnail_font_size"]
font_color = settings.config["settings"]["background"]["background_thumbnail_font_color"]
thumbnail = Image.open(f"assets/backgrounds/{first_image}")
width, height = thumbnail.size
thumbnailSave = create_thumbnail(
thumbnail,
font_family,
font_size,
font_color,
width,
height,
title_thumb,
)
thumbnailSave.save(f"./assets/temp/{reddit_id}/thumbnail.png")
print_substep(f"Thumbnail - Building Thumbnail in assets/temp/{reddit_id}/thumbnail.png")
Loading…
Cancel
Save