Merge branch 'develop' into feat/better-tts-changer

pull/653/head
Callum Leslie 2 years ago
commit 7ad1492318

@ -1,31 +1,74 @@
REDDIT_CLIENT_ID=""
REDDIT_CLIENT_SECRET=""
REDDIT_CLIENT_ID="" #fFAGRNJru1FTz70BzhT3Zg
#EXPLANATION the ID of your Reddit app of SCRIPT type
#RANGE 12:30
#MATCH_REGEX [-a-zA-Z0-9._~+/]+=*$
#OOB_ERROR The ID should be over 12 and under 30 characters, double check your input.
REDDIT_USERNAME=""
REDDIT_PASSWORD=""
REDDIT_CLIENT_SECRET="" #fFAGRNJru1FTz70BzhT3Zg
#EXPLANATION the SECRET of your Reddit app of SCRIPT type
#RANGE 20:40
#MATCH_REGEX [-a-zA-Z0-9._~+/]+=*$
#OOB_ERROR The secret should be over 20 and under 40 characters, double check your input.
# If no, it will ask you a thread link to extract the thread, if yes it will randomize it. Default: "no"
REDDIT_USERNAME="" #asdfghjkl
#EXPLANATION the username of your reddit account
#RANGE 3:20
#MATCH_REGEX [_0-9a-zA-Z]+$
#OOB_ERROR A username HAS to be between 3 and 20 characters
REDDIT_PASSWORD="" #fFAGRNJru1FTz70BzhT3Zg
#EXPLANATION the password of your reddit account
#RANGE 8:None
#OOB_ERROR Password too short
#OPTIONAL
RANDOM_THREAD="no"
# If set to no, it will ask you a thread link to extract the thread, if yes it will randomize it. Default: "no"
REDDIT_2FA="" #no
#MATCH_REGEX ^(yes|no)
#EXPLANATION Whether you have Reddit 2FA enabled, Valid options are "yes" and "no"
# Valid options are "yes" and "no" for the variable below
REDDIT_2FA=""
SUBREDDIT="AskReddit"
# True or False
#EXPLANATION what subreddit to pull posts from, the name of the sub, not the URL
#RANGE 3:20
#MATCH_REGEX [_0-9a-zA-Z]+$
#OOB_ERROR A subreddit name HAS to be between 3 and 20 characters
ALLOW_NSFW="False"
# Used if you want to use a specific post. example of one is urdtfx
#EXPLANATION Whether to allow NSFW content, True or False
#MATCH_REGEX ^(True|False)$
POST_ID=""
#set to either LIGHT or DARK
THEME="LIGHT"
# used if you want to run multiple times. set to an int e.g. 4 or 29 and leave blank for 1
TIMES_TO_RUN=""
# max number of characters a comment can have.
MAX_COMMENT_LENGTH="500" # default is 500
# Range is 0 -> 1 recommended around 0.8-0.9
OPACITY="1"
#MATCH_REGEX ^((?!://|://).)*$
#EXPLANATION Used if you want to use a specific post. example of one is urdtfx
THEME="LIGHT" #dark
#EXPLANATION sets the Reddit theme, either LIGHT or DARK
#MATCH_REGEX ^(dark|light|DARK|LIGHT)$
TIMES_TO_RUN="" #2
#EXPLANATION used if you want to run multiple times. set to an int e.g. 4 or 29 and leave blank for 1
MAX_COMMENT_LENGTH="500" #500
#EXPLANATION max number of characters a comment can have. default is 500
#RANGE 0:10000
#MATCH_TYPE int
#OOB_ERROR the max comment length should be between 0 and 10000
OPACITY="1" #.8
#EXPLANATION Sets the opacity of the comments when overlayed over the background
#RANGE 0:1
#MATCH_TYPE float
#OOB_ERROR The opacity HAS to be between 0 and 1
# see different voice options: todo: add docs
VOICE="Matthew" # e.g. en_us_002
TTsChoice="polly"
VOICE="Matthew" #en_us_002
#EXPLANATION sets the voice the TTS uses
# IN-PROGRESS - not yet implemented
TTsChoice="polly" #polly
#EXPLANATION the backend used for TTS, default is polly
#OPTIONAL
STORYMODE="False"
# IN-PROGRESS - not yet implemented

@ -1,3 +1,4 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
@ -12,61 +13,61 @@
name: "CodeQL"
on:
push:
branches: [ "master" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "master" ]
schedule:
- cron: '16 14 * * 3'
push:
branches: [ "master" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "master" ]
schedule:
- cron: '16 14 * * 3'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
strategy:
fail-fast: false
matrix:
language: [ 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

@ -45,14 +45,17 @@ The only original thing being done is the editing and gathering of all materials
3. Install [SoX](https://sourceforge.net/projects/sox/files/sox/)
4. Run `pip install -r requirements.txt`
4. Add the directory of your SoX installation to the Path system variables (see https://github.com/elebumm/RedditVideoMakerBot/issues/613)
and move the added directory all the way to the top of the list of directories.
5. Run `playwright install` and `playwright install-deps`. (if this fails try adding python -m to the front of the command)
5. Run `pip install -r requirements.txt`
6. Run `python main.py` (unless you chose automatic install, then the installer will automatically run main.py)
6. Run `playwright install` and `playwright install-deps`. (if this fails try adding python -m to the front of the command)
7. Run `python main.py` (unless you chose automatic install, then the installer will automatically run main.py)
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.
7. Enjoy 😎
8. Enjoy 😎
(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)
## Video

@ -1,4 +1,4 @@
import time
#!/usr/bin/env python
from subprocess import Popen
from dotenv import load_dotenv
@ -6,11 +6,14 @@ from os import getenv, name
from reddit.subreddit import get_subreddit_threads
from utils.cleanup import cleanup
from utils.console import print_markdown, print_step
# from utils.checker import envUpdate
from video_creation.background import download_background, chop_background_video
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
from utils.checker import check_env
VERSION = 2.1
print(
"""
@ -22,23 +25,16 @@ print(
"""
)
load_dotenv()
# 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/)"
)
time.sleep(1)
client_id = getenv("REDDIT_CLIENT_ID")
client_secret = getenv("REDDIT_CLIENT_SECRET")
username = getenv("REDDIT_USERNAME")
password = getenv("REDDIT_PASSWORD")
reddit2fa = getenv("REDDIT_2FA")
def main():
#envUpdate()
if check_env() is not True:
exit()
load_dotenv()
cleanup()
def get_obj():
@ -54,8 +50,7 @@ def main():
def run_many(times):
for x in range(times):
x = x + 1
for x in range(1, times + 1):
print_step(
f'on the {x}{("st" if x == 1 else ("nd" if x == 2 else ("rd" if x == 3 else "th")))} iteration of {times}'
) # correct 1st 2nd 3rd 4th 5th....

@ -10,51 +10,14 @@ from utils.console import print_markdown
from utils.console import print_step
from rich.console import Console
from utils.loader import Loader
from utils.console import handle_input
console = Console()
def handle_input(
message: str = "",
check_type=False,
match: str = "",
err_message: str = "",
nmin=None,
nmax=None,
oob_error="",
):
match = re.compile(match + "$")
while True:
user_input = input(message + "\n> ").strip()
if re.match(match, user_input) is not None:
if check_type is not False:
try:
user_input = check_type(user_input)
if nmin is not None and user_input < nmin:
console.log("[red]" + oob_error) # Input too low failstate
continue
if nmax is not None and user_input > nmax:
console.log("[red]" + oob_error) # Input too high
continue
break # Successful type conversion and number in bounds
except ValueError:
console.log("[red]" + err_message) # Type conversion failed
continue
if nmin is not None and len(user_input) < nmin: # Check if string is long enough
console.log("[red]" + oob_error)
continue
if nmax is not None and len(user_input) > nmax: # Check if string is not too long
console.log("[red]" + oob_error)
continue
break
console.log("[red]" + err_message)
return user_input
if os.path.isfile(".setup-done-before"):
console.log(
"[red]Setup was already completed! Please make sure you have to run this script again. If that is such, delete the file .setup-done-before"
console.print(
"[red]WARNING: Setup was already completed! Please make sure you have to run this script again. If that is such, delete the file .setup-done-before"
)
exit()
@ -89,15 +52,15 @@ if input("Are you sure you want to continue? > ").strip().casefold() != "yes":
console.print("[bold green]Alright! Let's get started!")
print()
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)")
console.print("Ensure you have the following ready to enter:")
console.print("[bold green]Reddit Client ID")
console.print("[bold green]Reddit Client Secret")
console.print("[bold green]Reddit Username")
console.print("[bold green]Reddit Password")
console.print("[bold green]Reddit 2FA (yes or no)")
console.print("[bold green]Opacity (range of 0-1, decimals are OK)")
console.print("[bold green]Subreddit (without r/ or /r/)")
console.print("[bold green]Theme (light or dark)")
console.print(
"[green]If you don't have these, please follow the instructions in the README.md file to set them up."
)
@ -117,7 +80,7 @@ console.print("[bold green]Alright! Let's get started!")
# Begin the setup process.
console.log("Enter your credentials now.")
console.print("Enter your credentials now.")
client_id = handle_input(
"Client ID > ",
False,
@ -178,7 +141,7 @@ theme = handle_input(
)
loader = Loader("Attempting to save your credentials...", "Done!").start()
# you can also put a while loop here, e.g. while VideoIsBeingMade == True: ...
console.log("Writing to the .env file...")
console.print("Writing to the .env file...")
with open(".env", "w") as f:
f.write(
f"""REDDIT_CLIENT_ID="{client_id}"
@ -199,7 +162,7 @@ with open(".setup-done-before", "w") as f:
loader.stop()
console.log("[bold green]Setup Complete! Returning...")
console.print("[bold green]Setup Complete! Returning...")
# Post-Setup: send message and try to run main.py again.
subprocess.call("python3 main.py", shell=True)

@ -0,0 +1,190 @@
#!/usr/bin/env python
import os
from rich.console import Console
from rich.table import Table
from rich import box
import re
import dotenv
from utils.console import handle_input
console = Console()
def check_env() -> bool:
if not os.path.exists(".env.template"):
console.print("[red]Couldn't find .env.template. Unable to check variables.")
return True
if not os.path.exists(".env"):
console.print("[red]Couldn't find the .env file, creating one now.")
with open(".env", "x") as file:
file.write("")
success = True
with open(".env.template", "r") as template:
# req_envs = [env.split("=")[0] for env in template.readlines() if "=" in env]
matching = {}
explanations = {}
bounds = {}
types = {}
oob_errors = {}
examples = {}
req_envs = []
var_optional = False
for line in template.readlines():
if line.startswith("#") is not True and "=" in line and var_optional is not True:
req_envs.append(line.split("=")[0])
if "#" in line:
examples[line.split("=")[0]] = "#".join(line.split("#")[1:]).strip()
elif "#OPTIONAL" in line:
var_optional = True
elif line.startswith("#MATCH_REGEX "):
matching[req_envs[-1]] = line.removeprefix("#MATCH_REGEX ")[:-1]
var_optional = False
elif line.startswith("#OOB_ERROR "):
oob_errors[req_envs[-1]] = line.removeprefix("#OOB_ERROR ")[:-1]
var_optional = False
elif line.startswith("#RANGE "):
bounds[req_envs[-1]] = tuple(
map(
lambda x: float(x) if x != "None" else None,
line.removeprefix("#RANGE ")[:-1].split(":"),
)
)
var_optional = False
elif line.startswith("#MATCH_TYPE "):
types[req_envs[-1]] = eval(line.removeprefix("#MATCH_TYPE ")[:-1].split()[0])
var_optional = False
elif line.startswith("#EXPLANATION "):
explanations[req_envs[-1]] = line.removeprefix("#EXPLANATION ")[:-1]
var_optional = False
else:
var_optional = False
missing = set()
incorrect = set()
dotenv.load_dotenv()
for env in req_envs:
value = os.getenv(env)
if value is None:
missing.add(env)
continue
if env in matching.keys():
re.match(matching[env], value) is None and incorrect.add(env)
if env in bounds.keys() and env not in types.keys():
len(value) >= bounds[env][0] or (
len(bounds[env]) > 1 and bounds[env][1] >= len(value)
) or incorrect.add(env)
continue
if env in types.keys():
try:
temp = types[env](value)
if env in bounds.keys():
(bounds[env][0] <= temp or incorrect.add(env)) and len(bounds[env]) > 1 and (
bounds[env][1] >= temp or incorrect.add(env)
)
except ValueError:
incorrect.add(env)
if len(missing):
table = Table(
title="Missing variables",
highlight=True,
show_lines=True,
box=box.ROUNDED,
border_style="#414868",
header_style="#C0CAF5 bold",
title_justify="left",
title_style="#C0CAF5 bold",
)
table.add_column("Variable", justify="left", style="#7AA2F7 bold", no_wrap=True)
table.add_column("Explanation", justify="left", style="#BB9AF7", no_wrap=False)
table.add_column("Example", justify="center", style="#F7768E", no_wrap=True)
table.add_column("Min", justify="right", style="#F7768E", no_wrap=True)
table.add_column("Max", justify="left", style="#F7768E", no_wrap=True)
for env in missing:
table.add_row(
env,
explanations[env] if env in explanations.keys() else "No explanation given",
examples[env] if env in examples.keys() else "",
str(bounds[env][0]) if env in bounds.keys() and bounds[env][1] is not None else "",
str(bounds[env][1])
if env in bounds.keys() and len(bounds[env]) > 1 and bounds[env][1] is not None
else "",
)
console.print(table)
success = False
if len(incorrect):
table = Table(
title="Incorrect variables",
highlight=True,
show_lines=True,
box=box.ROUNDED,
border_style="#414868",
header_style="#C0CAF5 bold",
title_justify="left",
title_style="#C0CAF5 bold",
)
table.add_column("Variable", justify="left", style="#7AA2F7 bold", no_wrap=True)
table.add_column("Current value", justify="left", style="#F7768E", no_wrap=False)
table.add_column("Explanation", justify="left", style="#BB9AF7", no_wrap=False)
table.add_column("Example", justify="center", style="#F7768E", no_wrap=True)
table.add_column("Min", justify="right", style="#F7768E", no_wrap=True)
table.add_column("Max", justify="left", style="#F7768E", no_wrap=True)
for env in incorrect:
table.add_row(
env,
os.getenv(env),
explanations[env] if env in explanations.keys() else "No explanation given",
str(types[env].__name__) if env in types.keys() else "str",
str(bounds[env][0]) if env in bounds.keys() else "None",
str(bounds[env][1]) if env in bounds.keys() and len(bounds[env]) > 1 else "None",
)
missing.add(env)
console.print(table)
success = False
if success is True:
return True
console.print(
"[green]Do you want to automatically overwrite incorrect variables and add the missing variables? (y/n)"
)
if not input().casefold().startswith("y"):
console.print("[red]Aborting: Unresolved missing variables")
return False
if len(incorrect):
with open(".env", "r+") as env_file:
lines = []
for line in env_file.readlines():
line.split("=")[0].strip() not in incorrect and lines.append(line)
env_file.seek(0)
env_file.write("\n".join(lines))
env_file.truncate()
console.print("[green]Successfully removed incorrectly set variables from .env")
with open(".env", "a") as env_file:
for env in missing:
env_file.write(
env
+ "="
+ ('"' if env not in types.keys() else "")
+ str(
handle_input(
"[#F7768E bold]" + env + "[#C0CAF5 bold]=",
types[env] if env in types.keys() else False,
matching[env] if env in matching.keys() else ".*",
explanations[env]
if env in explanations.keys()
else "Incorrect input. Try again.",
bounds[env][0] if env in bounds.keys() else None,
bounds[env][1] if env in bounds.keys() and len(bounds[env]) > 1 else None,
oob_errors[env] if env in oob_errors.keys() else "Input too long/short.",
extra_info="[#C0CAF5 bold]⮶ "
+ (
explanations[env] if env in explanations.keys() else "No info available"
),
)
)
+ ('"' if env not in types.keys() else "")
+ "\n"
)
return True
if __name__ == "__main__":
check_env()

@ -5,6 +5,7 @@ from rich.padding import Padding
from rich.panel import Panel
from rich.text import Text
from rich.columns import Columns
import re
console = Console()
@ -32,3 +33,44 @@ def print_table(items):
"""Prints items in a table."""
console.print(Columns([Panel(f"[yellow]{item}", expand=True) for item in items]))
def handle_input(
message: str = "",
check_type=False,
match: str = "",
err_message: str = "",
nmin=None,
nmax=None,
oob_error="",
extra_info="",
):
match = re.compile(match + "$")
console.print(extra_info, no_wrap=True)
while True:
console.print(message, end="")
user_input = input("").strip()
if re.match(match, user_input) is not None:
if check_type is not False:
try:
user_input = check_type(user_input)
if nmin is not None and user_input < nmin:
console.print("[red]" + oob_error) # Input too low failstate
continue
if nmax is not None and user_input > nmax:
console.print("[red]" + oob_error) # Input too high
continue
break # Successful type conversion and number in bounds
except ValueError:
console.print("[red]" + err_message) # Type conversion failed
continue
if nmin is not None and len(user_input) < nmin: # Check if string is long enough
console.print("[red]" + oob_error)
continue
if nmax is not None and len(user_input) > nmax: # Check if string is not too long
console.print("[red]" + oob_error)
continue
break
console.print("[red]" + err_message)
return user_input

@ -1,9 +0,0 @@
$envFile = Get-Content ".\.env.template"
$envFile -split "=" | Where-Object {$_ -notmatch '\"'} | Set-Content ".\envVarsbefSpl.txt"
Get-Content ".\envVarsbefSpl.txt" | Where-Object {$_ -notmatch '\#'} | Set-Content ".\envVarsN.txt"
Get-Content ".\envVarsN.txt" | Where-Object {$_ -ne ''} | Set-Content ".\video_creation\data\envvars.txt"
Remove-Item ".\envVarsbefSpl.txt"
Remove-Item ".\envVarsN.txt"
Write-Host $nowSplit

@ -1,9 +0,0 @@
$envFile = Get-Content ".\.env"
$envFile -split "=" | Where-Object {$_ -notmatch '\"'} | Set-Content ".\envVarsbefSpl.txt"
Get-Content ".\envVarsbefSpl.txt" | Where-Object {$_ -notmatch '\#'} | Set-Content ".\envVarsN.txt"
Get-Content ".\envVarsN.txt" | Where-Object {$_ -ne ''} | Set-Content ".\video_creation\data\envvars.txt"
Remove-Item ".\envVarsbefSpl.txt"
Remove-Item ".\envVarsN.txt"
Write-Host $nowSplit
Loading…
Cancel
Save