diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index fede9f8..0000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: "" -labels: bug -assignees: "" ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**System (please complete the following information):** - -- Python Version: [e.g. Python 3.6] -- OS: [e.g. Windows 11] -- App version / Branch [e.g. latest, V2.0, master, develop ] - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..9059b5b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,64 @@ +name: Bug Report +title: "[Bug]: " +labels: bug +description: Report broken or incorrect behaviour +body: + - type: markdown + attributes: + value: > + Thanks for taking the time to fill out a bug. + Please note that this form is for bugs only! + - type: textarea + id: what-happened + attributes: + label: Describe the bug + description: A clear and concise description of what the bug is. + validations: + required: true + - type: textarea + attributes: + label: Reproduction Steps + description: > + What you did to make it happen. + validations: + required: true + - type: textarea + attributes: + label: Expected behavior + description: > + A clear and concise description of what you expected to happen. + validations: + required: true + - type: textarea + attributes: + label: Screenshots + description: > + If applicable, add screenshots to help explain your problem. + validations: + required: false + - type: textarea + attributes: + label: System Information + description: please fill your system informations + value: > + Operating System : [e.g. Windows 11] + + Python version : [e.g. Python 3.6] + + App version / Branch : [e.g. latest, V2.0, master, develop] + validations: + required: true + - type: checkboxes + attributes: + label: Checklist + description: > + Let's make sure you've properly done due diligence when reporting this issue! + options: + - label: I have searched the open issues for duplicates. + required: true + - label: I have shown the entire traceback, if possible. + required: true + - type: textarea + attributes: + label: Additional Context + description: Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..3390cfc --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Ask a question + about: Join our discord server to ask questions and discuss with maintainers and contributors. + url: https://discord.gg/swqtb7AsNQ \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 14b795a..0000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: enhancement -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** (optional) -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** (optional) -Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..34c2d5c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,39 @@ +name: Feature Request +description: Suggest an idea for this project +labels: enhancement +title: "[Feature]: " +body: + - type: input + attributes: + label: Summary + description: > + A short summary of what your feature request is. + validations: + required: true + - type: textarea + attributes: + label: Is your feature request related to a problem? + description: > + if yes, what becomes easier or possible when this feature is implemented? + validations: + required: true + - type: textarea + attributes: + label: Describe the solution you'd like + description: > + A clear and concise description of what you want to happen. + validations: + required: true + - type: textarea + attributes: + label: Describe alternatives you've considered + description: > + A clear and concise description of any alternative solutions or features you've considered. + validations: + required: false + + + - type: textarea + attributes: + label: Additional Context + description: Add any other context or screenshots about the feature request here. \ No newline at end of file diff --git a/.gitignore b/.gitignore index 793db5d..3da725f 100644 --- a/.gitignore +++ b/.gitignore @@ -243,3 +243,4 @@ video_creation/data/videos.json video_creation/data/envvars.txt config.toml +video_creation/data/videos.json diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8fc7d3d..3811f80 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,7 +28,7 @@ All types of contributions are encouraged and valued. See the [Table of Contents ## I Have a Question -> If you want to ask a question, we assume that you have read the available [Documentation](https://luka-hietala.gitbook.io/documentation-for-the-reddit-bot/). +> If you want to ask a question, we assume that you have read the available [Documentation](https://reddit-video-maker-bot.netlify.app/). Before you ask a question, it is best to search for existing [Issues](https://github.com/elebumm/RedditVideoMakerBot/issues) that might help you. In case you have found a suitable issue and still need clarification, you can write your question in this issue. It is also advisable to search the internet for answers first. @@ -144,4 +144,4 @@ When making your PR, follow these guidelines: ### Improving The Documentation -All updates to the documentation should be made in a pull request to [this repo](https://github.com/LukaHietala/reddit-bot-docs) +All updates to the documentation should be made in a pull request to [this repo](https://github.com/LukaHietala/RedditVideoMakerBot-website) diff --git a/README.md b/README.md index 8d61d9a..53504aa 100644 --- a/README.md +++ b/README.md @@ -39,12 +39,11 @@ The only original thing being done is the editing and gathering of all materials 1. Clone this repository 2. Run `pip install -r requirements.txt` - 3. Run `python -m playwright install` and `python -m playwright install-deps` **EXPERIMENTAL!!!!** -On MacOS and Linux (debian, arch, fedora and centos, and based on those), you can run an install script that will automatically install steps 1 to 3. (requires bash) +On macOS and Linux (debian, arch, fedora and centos, and based on those), you can run an install script that will automatically install steps 1 to 3. (requires bash) `bash <(curl -sL https://raw.githubusercontent.com/elebumm/RedditVideoMakerBot/master/install.sh)` @@ -58,7 +57,7 @@ This can also be used to update the installation (Note if you got an error installing or running the bot try first rerunning the command with a three after the name e.g. python3 or pip3) -If you want to read more detailed guide about the bot, please refer to the [documentation](https://luka-hietala.gitbook.io/documentation-for-the-reddit-bot/) +If you want to read more detailed guide about the bot, please refer to the [documentation](https://reddit-video-maker-bot.netlify.app/) ## Video diff --git a/TTS/GTTS.py b/TTS/GTTS.py index cef1b24..3bf8ee3 100644 --- a/TTS/GTTS.py +++ b/TTS/GTTS.py @@ -1,9 +1,9 @@ #!/usr/bin/env python3 import random -from utils import settings + from gtts import gTTS -max_chars = 0 +from utils import settings class GTTS: diff --git a/TTS/TikTok.py b/TTS/TikTok.py index 743118c..7f79c81 100644 --- a/TTS/TikTok.py +++ b/TTS/TikTok.py @@ -1,9 +1,11 @@ import base64 -from utils import settings import random + import requests from requests.adapters import HTTPAdapter, Retry +from utils import settings + # from profanity_filter import ProfanityFilter # pf = ProfanityFilter() # Code by @JasonLovesDoggo @@ -62,9 +64,7 @@ noneng = [ class TikTok: # TikTok Text-to-Speech Wrapper def __init__(self): - self.URI_BASE = ( - "https://api16-normal-useast5.us.tiktokv.com/media/api/text/speech/invoke/?text_speaker=" - ) + self.URI_BASE = "https://api16-normal-useast5.us.tiktokv.com/media/api/text/speech/invoke/?text_speaker=" self.max_chars = 300 self.voices = {"human": human, "nonhuman": nonhuman, "noneng": noneng} @@ -75,10 +75,7 @@ class TikTok: # TikTok Text-to-Speech Wrapper voice = ( self.randomvoice() if random_voice - else ( - settings.config["settings"]["tts"]["tiktok_voice"] - or random.choice(self.voices["human"]) - ) + else (settings.config["settings"]["tts"]["tiktok_voice"] or random.choice(self.voices["human"])) ) try: r = requests.post(f"{self.URI_BASE}{voice}&req_text={text}&speaker_map_type=0") diff --git a/TTS/aws_polly.py b/TTS/aws_polly.py index eac5884..fa02079 100644 --- a/TTS/aws_polly.py +++ b/TTS/aws_polly.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 +import random +import sys + from boto3 import Session from botocore.exceptions import BotoCoreError, ClientError, ProfileNotFound -import sys + from utils import settings -import random voices = [ "Brian", @@ -37,15 +39,11 @@ class AWSPolly: voice = self.randomvoice() else: if not settings.config["settings"]["tts"]["aws_polly_voice"]: - raise ValueError( - f"Please set the TOML variable AWS_VOICE to a valid voice. options are: {voices}" - ) + raise ValueError(f"Please set the TOML variable AWS_VOICE to a valid voice. options are: {voices}") voice = str(settings.config["settings"]["tts"]["aws_polly_voice"]).capitalize() try: # Request speech synthesis - response = polly.synthesize_speech( - Text=text, OutputFormat="mp3", VoiceId=voice, Engine="neural" - ) + response = polly.synthesize_speech(Text=text, OutputFormat="mp3", VoiceId=voice, Engine="neural") except (BotoCoreError, ClientError) as error: # The service returned an error, exit gracefully print(error) diff --git a/TTS/engine_wrapper.py b/TTS/engine_wrapper.py index 12668df..00485b3 100644 --- a/TTS/engine_wrapper.py +++ b/TTS/engine_wrapper.py @@ -1,17 +1,18 @@ #!/usr/bin/env python3 +import re from pathlib import Path from typing import Tuple -import re # import sox # from mutagen import MutagenError # from mutagen.mp3 import MP3, HeaderNotFoundError import translators as ts -from rich.progress import track from moviepy.editor import AudioFileClip, CompositeAudioClip, concatenate_audioclips +from rich.progress import track + +from utils import settings from utils.console import print_step, print_substep from utils.voice import sanitize_text -from utils import settings DEFAULT_MAX_LENGTH: int = 50 # video length variable @@ -70,9 +71,7 @@ class TTSEngine: self.length -= self.last_clip_length idx -= 1 break - if ( - len(comment["comment_body"]) > self.tts_module.max_chars - ): # Split the comment if it is too long + if len(comment["comment_body"]) > self.tts_module.max_chars: # Split the comment if it is too long self.split_post(comment["comment_body"], idx) # Split the comment else: # If the comment is not too long, just call the tts engine self.call_tts(f"{idx}", process_text(comment["comment_body"])) @@ -83,10 +82,7 @@ class TTSEngine: def split_post(self, text: str, idx: int): split_files = [] split_text = [ - x.group().strip() - for x in re.finditer( - r" *(((.|\n){0," + str(self.tts_module.max_chars) + "})(\.|.$))", text - ) + x.group().strip() for x in re.finditer(r" *(((.|\n){0," + str(self.tts_module.max_chars) + "})(\.|.$))", text) ] offset = 0 for idy, text_cut in enumerate(split_text): diff --git a/TTS/pyttsx.py b/TTS/pyttsx.py index b5ffb29..874d573 100644 --- a/TTS/pyttsx.py +++ b/TTS/pyttsx.py @@ -1,5 +1,7 @@ import random + import pyttsx3 + from utils import settings @@ -30,9 +32,7 @@ class pyttsx: voice_id = self.randomvoice() engine = pyttsx3.init() voices = engine.getProperty("voices") - engine.setProperty( - "voice", voices[voice_id].id - ) # changing index changes voices but ony 0 and 1 are working here + engine.setProperty("voice", voices[voice_id].id) # changing index changes voices but ony 0 and 1 are working here engine.save_to_file(text, f"{filepath}") engine.runAndWait() diff --git a/TTS/streamlabs_polly.py b/TTS/streamlabs_polly.py index 75c4f49..ce2250b 100644 --- a/TTS/streamlabs_polly.py +++ b/TTS/streamlabs_polly.py @@ -1,6 +1,8 @@ import random + import requests from requests.exceptions import JSONDecodeError + from utils import settings from utils.voice import check_ratelimit @@ -37,9 +39,7 @@ class StreamlabsPolly: voice = self.randomvoice() else: if not settings.config["settings"]["tts"]["streamlabs_polly_voice"]: - raise ValueError( - f"Please set the config variable STREAMLABS_POLLY_VOICE to a valid voice. options are: {voices}" - ) + raise ValueError(f"Please set the config variable STREAMLABS_POLLY_VOICE to a valid voice. options are: {voices}") voice = str(settings.config["settings"]["tts"]["streamlabs_polly_voice"]).capitalize() body = {"voice": voice, "text": text, "service": "polly"} response = requests.post(self.url, data=body) diff --git a/install.sh b/install.sh index f85c80b..38c1708 100644 --- a/install.sh +++ b/install.sh @@ -62,7 +62,13 @@ function install_macos(){ fi # Install the required packages echo "Installing required Packages" - brew install python@3.10 tcl-tk python-tk + if [! command --version python3 &> /dev/null ]; then + echo "Installing python3" + brew install python@3.10 + else + echo "python3 already installed." + fi + brew install tcl-tk python-tk } # Function to install for arch (and other forks like manjaro) diff --git a/main.py b/main.py index 893b4e2..788bc7a 100755 --- a/main.py +++ b/main.py @@ -9,12 +9,11 @@ from sys import platform from prawcore import ResponseException from reddit.subreddit import get_subreddit_threads -from utils.cleanup import cleanup -from utils.console import print_markdown, print_step, print_substep from utils import settings +from utils.cleanup import cleanup +from utils.console import print_markdown, print_step from utils.id import id from utils.version import checkversion - from video_creation.background import ( download_background, chop_background_video, @@ -24,7 +23,7 @@ from video_creation.final_video import make_final_video from video_creation.screenshot_downloader import download_screenshots_of_reddit_posts from video_creation.voices import save_text_to_mp3 -__VERSION__ = "2.4.1" +__VERSION__ = "2.4.2" ### 3 util functions. by github.com/notcooler ### def getPlatform(): @@ -77,7 +76,7 @@ print( ) # Modified by JasonLovesDoggo 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. You can find solutions to many common problems in the [Documentation](https://luka-hietala.gitbook.io/documentation-for-the-reddit-bot/)" + "### 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. You can find solutions to many common problems in the [Documentation](): https://reddit-video-maker-bot.netlify.app/" ) checkversion(__VERSION__) @@ -116,14 +115,13 @@ def shutdown(): print("Exiting...") exit() + if __name__ == "__main__": + assert sys.version_info >= (3, 9), "Python 3.10 or higher is required" config = settings.check_toml("utils/.config.template.toml", "config.toml") config is False and exit() try: - if config["settings"]["times_to_run"]: - run_many(config["settings"]["times_to_run"]) - - elif len(config["reddit"]["thread"]["post_id"].split("+")) > 1: + if len(config["reddit"]["thread"]["post_id"].split("+")) > 1: for index, post_id in enumerate(config["reddit"]["thread"]["post_id"].split("+")): index += 1 print_step( @@ -131,6 +129,8 @@ if __name__ == "__main__": ) main(post_id) Popen("cls" if name == "nt" else "clear", shell=True).wait() + elif config["settings"]["times_to_run"]: + run_many(config["settings"]["times_to_run"]) else: main() except KeyboardInterrupt: diff --git a/reddit/subreddit.py b/reddit/subreddit.py index 11b93af..5114d9a 100644 --- a/reddit/subreddit.py +++ b/reddit/subreddit.py @@ -1,11 +1,10 @@ import re -from prawcore.exceptions import ResponseException - -from utils import settings import praw from praw.models import MoreComments +from prawcore.exceptions import ResponseException +from utils import settings from utils.console import print_step, print_substep from utils.subreddit import get_subreddit_undone from utils.videos import check_done @@ -41,9 +40,8 @@ def get_subreddit_threads(POST_ID: str): check_for_async=False, ) except ResponseException as e: - match e.response.status_code: - case 401: - print("Invalid credentials - please check them in config.toml") + if e.response.status_code == 401: + print("Invalid credentials - please check them in config.toml") except: print("Something went wrong...") @@ -105,12 +103,9 @@ def get_subreddit_threads(POST_ID: str): sanitised = sanitize_text(top_level_comment.body) if not sanitised or sanitised == " ": continue - if len(top_level_comment.body) <= int( - settings.config["reddit"]["thread"]["max_comment_length"] - ): + if len(top_level_comment.body) <= int(settings.config["reddit"]["thread"]["max_comment_length"]): if ( - top_level_comment.author is not None - and sanitize_text(top_level_comment.body) is not None + top_level_comment.author is not None and sanitize_text(top_level_comment.body) is not None ): # if errors occur with this change to if not. content["comments"].append( { diff --git a/utils/console.py b/utils/console.py index 6f99a41..ce1b8a4 100644 --- a/utils/console.py +++ b/utils/console.py @@ -1,11 +1,12 @@ #!/usr/bin/env python3 +import re + +from rich.columns import Columns from rich.console import Console from rich.markdown import Markdown from rich.padding import Padding from rich.panel import Panel from rich.text import Text -from rich.columns import Columns -import re console = Console() @@ -54,11 +55,7 @@ def handle_input( return default if default is not NotImplemented else "" if default is not NotImplemented: console.print( - "[green]" - + message - + '\n[blue bold]The default value is "' - + str(default) - + '"\nDo you want to use it?(y/n)' + "[green]" + message + '\n[blue bold]The default value is "' + str(default) + '"\nDo you want to use it?(y/n)' ) if input().casefold().startswith("y"): return default @@ -71,9 +68,7 @@ def handle_input( if check_type is not False: try: user_input = check_type(user_input) - if (nmin is not None and user_input < nmin) or ( - nmax is not None and user_input > nmax - ): + if (nmin is not None and user_input < nmin) or (nmax is not None and user_input > nmax): # FAILSTATE Input out of bounds console.print("[red]" + oob_error) continue @@ -89,9 +84,7 @@ def handle_input( continue else: # FAILSTATE Input STRING out of bounds - if (nmin is not None and len(user_input) < nmin) or ( - nmax is not None and len(user_input) > nmax - ): + if (nmin is not None and len(user_input) < nmin) or (nmax is not None and len(user_input) > nmax): console.print("[red bold]" + oob_error) continue break # SUCCESS Input STRING in bounds @@ -105,16 +98,8 @@ def handle_input( isinstance(eval(user_input), check_type) return check_type(user_input) except: - console.print( - "[red bold]" - + err_message - + "\nValid options are: " - + ", ".join(map(str, options)) - + "." - ) + console.print("[red bold]" + err_message + "\nValid options are: " + ", ".join(map(str, options)) + ".") continue if user_input in options: return user_input - console.print( - "[red bold]" + err_message + "\nValid options are: " + ", ".join(map(str, options)) + "." - ) + console.print("[red bold]" + err_message + "\nValid options are: " + ", ".join(map(str, options)) + ".") diff --git a/utils/id.py b/utils/id.py index c66d77a..3d76593 100644 --- a/utils/id.py +++ b/utils/id.py @@ -1,10 +1,12 @@ import re + from utils.console import print_substep + def id(reddit_obj: dict): """ This function takes a reddit object and returns the post id """ id = re.sub(r"[^\w\s-]", "", reddit_obj["thread_id"]) print_substep(f"Thread ID is {id}", style="bold blue") - return id \ No newline at end of file + return id diff --git a/utils/settings.py b/utils/settings.py index a9d7726..9f1f78b 100755 --- a/utils/settings.py +++ b/utils/settings.py @@ -1,12 +1,11 @@ #!/usr/bin/env python -import toml -from rich.console import Console import re - from typing import Tuple, Dict -from utils.console import handle_input +import toml +from rich.console import Console +from utils.console import handle_input console = Console() config = dict # autocomplete @@ -35,17 +34,12 @@ def check(value, checks, name): except: incorrect = True - if ( - not incorrect and "options" in checks and value not in checks["options"] - ): # FAILSTATE Value is not one of the options + if not incorrect and "options" in checks and value not in checks["options"]: # FAILSTATE Value is not one of the options incorrect = True if ( not incorrect and "regex" in checks - and ( - (isinstance(value, str) and re.match(checks["regex"], value) is None) - or not isinstance(value, str) - ) + and ((isinstance(value, str) and re.match(checks["regex"], value) is None) or not isinstance(value, str)) ): # FAILSTATE Value doesn't match regex, or has regex but is not a string. incorrect = True @@ -85,9 +79,7 @@ def check(value, checks, name): err_message=get_check_value("input_error", "Incorrect input"), nmin=get_check_value("nmin", None), nmax=get_check_value("nmax", None), - oob_error=get_check_value( - "oob_error", "Input out of bounds(Value too high/low/long/short)" - ), + oob_error=get_check_value("oob_error", "Input out of bounds(Value too high/low/long/short)"), options=get_check_value("options", None), optional=get_check_value("optional", False), ) diff --git a/utils/subreddit.py b/utils/subreddit.py index c386868..b0b7ae5 100644 --- a/utils/subreddit.py +++ b/utils/subreddit.py @@ -54,9 +54,7 @@ def get_subreddit_undone(submissions: list, subreddit, times_checked=0): print("all time filters have been checked you absolute madlad ") return get_subreddit_undone( - subreddit.top( - time_filter=VALID_TIME_FILTERS[index], limit=(50 if int(index) == 0 else index + 1 * 50) - ), + subreddit.top(time_filter=VALID_TIME_FILTERS[index], limit=(50 if int(index) == 0 else index + 1 * 50)), subreddit, times_checked=index, ) # all the videos in hot have already been done diff --git a/utils/version.py b/utils/version.py index a8177cc..8cad1d8 100644 --- a/utils/version.py +++ b/utils/version.py @@ -1,11 +1,10 @@ import requests + from utils.console import print_step def checkversion(__VERSION__): - response = requests.get( - "https://api.github.com/repos/elebumm/RedditVideoMakerBot/releases/latest" - ) + response = requests.get("https://api.github.com/repos/elebumm/RedditVideoMakerBot/releases/latest") latestversion = response.json()["tag_name"] if __VERSION__ == latestversion: print_step(f"You are using the newest version ({__VERSION__}) of the bot") diff --git a/utils/video.py b/utils/video.py index 5566cd1..2d212df 100644 --- a/utils/video.py +++ b/utils/video.py @@ -1,7 +1,6 @@ from __future__ import annotations -from ast import Str -import re +import re from typing import Tuple from PIL import ImageFont, Image, ImageDraw, ImageEnhance @@ -37,9 +36,7 @@ class Video: im.save(path) return ImageClip(path) - def add_watermark( - self, text, redditid, opacity=0.5, duration: int | float = 5, position: Tuple = (0.7, 0.9), fontsize=15 - ): + def add_watermark(self, text, redditid, opacity=0.5, duration: int | float = 5, position: Tuple = (0.7, 0.9), fontsize=15): compensation = round( (position[0] / ((len(text) * (fontsize / 5) / 1.5) / 100 + position[0] * position[0])), ndigits=2, diff --git a/utils/videos.py b/utils/videos.py index 4a91e8c..7c756fc 100755 --- a/utils/videos.py +++ b/utils/videos.py @@ -1,6 +1,5 @@ import json import time -from typing import Dict from praw.models import Submission diff --git a/utils/voice.py b/utils/voice.py index a0709fa..0ff6b37 100644 --- a/utils/voice.py +++ b/utils/voice.py @@ -1,7 +1,7 @@ import re import sys -from datetime import datetime import time as pytime +from datetime import datetime from time import sleep from requests import Response @@ -81,7 +81,7 @@ def sanitize_text(text: str) -> str: result = re.sub(regex_urls, " ", text) # note: not removing apostrophes - regex_expr = r"\s['|’]|['|’]\s|[\^_~@!&;#:\-–—%“”‘\"%\*/{}\[\]\(\)\\|<>=+]" + regex_expr = r"\s['|’]|['|’]\s|[\^_~@!&;#:\-%—“”‘\"%\*/{}\[\]\(\)\\|<>=+]" result = re.sub(regex_expr, " ", result) result = result.replace("+", "plus").replace("&", "and") # remove extra whitespace diff --git a/video_creation/background.py b/video_creation/background.py index 1676f97..f0f38d5 100644 --- a/video_creation/background.py +++ b/video_creation/background.py @@ -1,10 +1,9 @@ -from pathlib import Path import random -from random import randrange import re +from pathlib import Path +from random import randrange from typing import Any, Tuple - from moviepy.editor import VideoFileClip from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip from pytube import YouTube @@ -52,9 +51,7 @@ def download_background(background_config: Tuple[str, str, str, Any]): uri, filename, credit, _ = background_config if Path(f"assets/backgrounds/{credit}-{filename}").is_file(): return - print_step( - "We need to download the backgrounds videos. they are fairly large but it's only done once. 😎" - ) + print_step("We need to download the backgrounds videos. they are fairly large but it's only done once. 😎") print_substep("Downloading the backgrounds videos... please be patient 🙏 ") print_substep(f"Downloading {filename} from {uri}") YouTube(uri, on_progress_callback=on_progress).streams.filter(res="1080p").first().download( diff --git a/video_creation/data/videos.json b/video_creation/data/videos.json index 0637a08..fe51488 100644 --- a/video_creation/data/videos.json +++ b/video_creation/data/videos.json @@ -1 +1 @@ -[] \ No newline at end of file +[] diff --git a/video_creation/final_video.py b/video_creation/final_video.py index 743e561..ad675c5 100755 --- a/video_creation/final_video.py +++ b/video_creation/final_video.py @@ -4,6 +4,7 @@ import os import re from os.path import exists from typing import Tuple, Any + from moviepy.audio.AudioClip import concatenate_audioclips, CompositeAudioClip from moviepy.audio.io.AudioFileClip import AudioFileClip from moviepy.video.VideoClip import ImageClip @@ -13,11 +14,11 @@ from moviepy.video.io.VideoFileClip import VideoFileClip from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip from rich.console import Console +from utils import settings from utils.cleanup import cleanup from utils.console import print_step, print_substep from utils.video import Video from utils.videos import save_data -from utils import settings console = Console() W, H = 1080, 1920 @@ -118,9 +119,7 @@ def make_final_video( # ) # else: story mode stuff img_clip_pos = background_config[3] - image_concat = concatenate_videoclips(image_clips).set_position( - img_clip_pos - ) # note transition kwarg for delay in imgs + image_concat = concatenate_videoclips(image_clips).set_position(img_clip_pos) # note transition kwarg for delay in imgs image_concat.audio = audio_composite final = CompositeVideoClip([background_clip, image_concat]) title = re.sub(r"[^\w\s-]", "", reddit_obj["thread_title"]) @@ -140,9 +139,7 @@ def make_final_video( # # lowered_audio = audio_background.multiply_volume( # todo get this to work # # VOLUME_MULTIPLIER) # lower volume by background_audio_volume, use with fx # final.set_audio(final_audio) - final = Video(final).add_watermark( - text=f"Background credit: {background_config[2]}", opacity=0.4, redditid=reddit_obj - ) + final = Video(final).add_watermark(text=f"Background credit: {background_config[2]}", opacity=0.4, redditid=reddit_obj) final.write_videofile( f"assets/temp/{id}/temp.mp4", fps=30, @@ -163,6 +160,4 @@ def make_final_video( print_substep(f"Removed {cleanups} temporary files 🗑") print_substep("See result in the results folder!") - print_step( - f'Reddit title: {reddit_obj["thread_title"]} \n Background Credit: {background_config[2]}' - ) + print_step(f'Reddit title: {reddit_obj["thread_title"]} \n Background Credit: {background_config[2]}') diff --git a/video_creation/screenshot_downloader.py b/video_creation/screenshot_downloader.py index 2344fce..ba7835f 100644 --- a/video_creation/screenshot_downloader.py +++ b/video_creation/screenshot_downloader.py @@ -1,19 +1,17 @@ import json - -from pathlib import Path import re +from pathlib import Path from typing import Dict -from utils import settings -from playwright.async_api import async_playwright # pylint: disable=unused-import - -# do not remove the above line +import translators as ts from playwright.sync_api import sync_playwright, ViewportSize from rich.progress import track -import translators as ts +from utils import settings from utils.console import print_step, print_substep +# do not remove the above line + storymode = False @@ -32,7 +30,7 @@ def download_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: in with sync_playwright() as p: print_substep("Launching Headless Browser...") - browser = p.chromium.launch() + browser = p.chromium.launch(headless=True) # add headless=False for debug context = browser.new_context() if settings.config["settings"]["theme"] == "dark": @@ -53,9 +51,7 @@ def download_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: in page.wait_for_load_state() # Wait for page to fully load if page.locator('[data-click-id="text"] button').is_visible(): - page.locator( - '[data-click-id="text"] button' - ).click() # Remove "Click to see nsfw" Button in Screenshot + page.locator('[data-click-id="text"] button').click() # Remove "Click to see nsfw" Button in Screenshot # translate code @@ -74,16 +70,12 @@ def download_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: in print_substep("Skipping translation...") postcontentpath = f"assets/temp/{id}/png/title.png" - page.locator('[data-test-id="post-content"]').screenshot(path= postcontentpath) + page.locator('[data-test-id="post-content"]').screenshot(path=postcontentpath) if storymode: - page.locator('[data-click-id="text"]').screenshot( - path=f"assets/temp/{id}/png/story_content.png" - ) + page.locator('[data-click-id="text"]').screenshot(path=f"assets/temp/{id}/png/story_content.png") else: - for idx, comment in enumerate( - track(reddit_object["comments"], "Downloading screenshots...") - ): + for idx, comment in enumerate(track(reddit_object["comments"], "Downloading screenshots...")): # Stop if we have reached the screenshot_num if idx >= screenshot_num: break @@ -105,9 +97,7 @@ def download_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: in [comment_tl, comment["comment_id"]], ) try: - page.locator(f"#t1_{comment['comment_id']}").screenshot( - path=f"assets/temp/{id}/png/comment_{idx}.png" - ) + page.locator(f"#t1_{comment['comment_id']}").screenshot(path=f"assets/temp/{id}/png/comment_{idx}.png") except TimeoutError: del reddit_object["comments"] screenshot_num += 1 diff --git a/video_creation/voices.py b/video_creation/voices.py index f49514d..511b7ff 100644 --- a/video_creation/voices.py +++ b/video_creation/voices.py @@ -1,19 +1,18 @@ #!/usr/bin/env python -from typing import Dict, Tuple +from typing import Tuple from rich.console import Console -from TTS.engine_wrapper import TTSEngine from TTS.GTTS import GTTS -from TTS.streamlabs_polly import StreamlabsPolly -from TTS.aws_polly import AWSPolly from TTS.TikTok import TikTok +from TTS.aws_polly import AWSPolly +from TTS.engine_wrapper import TTSEngine from TTS.pyttsx import pyttsx +from TTS.streamlabs_polly import StreamlabsPolly from utils import settings from utils.console import print_table, print_step - console = Console() TTSProviders = {