Merge branch 'sineckers-translate' of https://github.com/sineckers/RedditVideoMakerBot into sineckers-translate

pull/564/head
SinecKers 2 years ago
commit b43c32413f

@ -1,37 +1,82 @@
# This can be found in the email that reddit sent you when you created the app
REDDIT_CLIENT_ID=""
REDDIT_CLIENT_SECRET=""
REDDIT_USERNAME=""
REDDIT_PASSWORD=""
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.
# If no, it will ask you a thread link to extract the thread, if yes it will randomize it. Default: "no"
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.
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
# If you want to translate the comments to another language, set the language code here.
# If empty, no translation will be done.
POSTLANG=""
#EXPLANATION Activates the translation feature, set the language code gor translate or leave blank
# see TTSwrapper.py for all valid options
# see different voice options: todo: add docs
VOICE="Matthew" # e.g. en_us_002
#EXPLANATION sets the voice the TTS uses
TTsChoice="polly" # todo add docs
#EXPLANATION the backend used for TTS, default is polly
# IMPORTANT NOTE: if you use translate, you need to set this gtts or set tiktok and use custom voice in your language
# IN-PROGRESS - not yet implemented
#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
steps:
- name: Checkout repository
uses: actions/checkout@v3
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
# 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.
steps:
- name: Checkout repository
uses: actions/checkout@v3
# 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
# 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
# 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

@ -1,4 +1,4 @@
import time
#!/usr/bin/env python
from subprocess import Popen
from dotenv import load_dotenv
@ -6,12 +6,15 @@ 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 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)

@ -1,67 +1,190 @@
#!/usr/bin/env python
import os
import subprocess
import tempfile
from os import path
from sys import platform
from rich.console import Console
from rich.table import Table
from rich import box
import re
import dotenv
from utils.console import handle_input
ACCEPTABLE_TO_BE_LEFT_BLANK = ["RANDOM_THREAD", "TIMES_TO_RUN"]
console = Console()
def envUpdate():
if path.exists(".env.template"): # if .env.template exists and .env does not exist
if platform == "win32" or platform == "cygwin":
runPS("utils/scripts/FileGrabber.ps1")
with open(".\\video_creation\\data\\envvars.txt", "rb") as f:
envTemplate = f.read()
elif platform == "darwin" or platform == "linux":
envTemplate = subprocess.check_output(
"awk -F '=' 'NF {print $1}' .env.template | grep --regexp=^[a-zA-Z]",
shell=True,
)
else:
raise OSError("Unsupported platform")
elif path.exists(".env"):
if platform == "win32" or platform == "cygwin":
runPS("utils/scripts/FileGrabberenv.ps1")
with open(".\\video_creation\\data\\envvars.txt", "rb") as f:
envTemplate = f.read()
elif platform == "darwin" or platform == "linux":
envTemplate = subprocess.check_output(
"awk -F '=' 'NF {print $1}' .env | grep --regexp=^[a-zA-Z]",
shell=True,
)
else:
raise OSError("Unsupported platform")
else:
raise FileNotFoundError("No .env or .env.template file found")
tempEnv = tempfile.TemporaryFile()
tempEnv.write(envTemplate)
tempEnv.seek(0)
envVars = tempEnv.readlines()
missing = []
isMissingEnvs = False
for env in envVars:
try:
env = env.decode("utf-8").strip()
except AttributeError:
env = env.strip()
if env not in os.environ:
if str(env) in ACCEPTABLE_TO_BE_LEFT_BLANK:
continue
isMissingEnvs = True
missing.append(env)
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 isMissingEnvs:
printstr = ""
[printstr + str(var) for var in missing]
print(
f"The following environment variables are missing: {printstr}. Please add them to the .env file."
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",
)
exit(-1)
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
def runPS(cmd):
completed = subprocess.run(["powershell", "-Command", cmd], capture_output=True)
return completed
if __name__ == "__main__":
check_env()

@ -4,6 +4,7 @@ from rich.markdown import Markdown
from rich.padding import Padding
from rich.panel import Panel
from rich.text import Text
import re
console = Console()
@ -25,3 +26,44 @@ def print_step(text):
def print_substep(text, style=""):
"""Prints a rich info message without the panelling."""
console.print(text, style=style)
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