parent
adb12549ff
commit
ce63c9316d
@ -1,128 +1,431 @@
|
||||
import json
|
||||
import re
|
||||
import webbrowser
|
||||
from pathlib import Path
|
||||
|
||||
# Used "tomlkit" instead of "toml" because it doesn't change formatting on "dump"
|
||||
import tomlkit
|
||||
from flask import (
|
||||
Flask,
|
||||
flash,
|
||||
redirect,
|
||||
render_template,
|
||||
request,
|
||||
send_from_directory,
|
||||
url_for,
|
||||
)
|
||||
|
||||
# Set the hostname
|
||||
HOST = "localhost"
|
||||
# Set the port number
|
||||
PORT = 4000
|
||||
|
||||
# Configure application
|
||||
app = Flask(__name__, template_folder="GUI")
|
||||
|
||||
# Configure secret key only to use 'flash'
|
||||
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'
|
||||
|
||||
|
||||
# Ensure responses aren't cached
|
||||
@app.after_request
|
||||
def after_request(response):
|
||||
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
|
||||
response.headers["Expires"] = 0
|
||||
response.headers["Pragma"] = "no-cache"
|
||||
return response
|
||||
|
||||
|
||||
# Display index.html
|
||||
@app.route("/")
|
||||
def index():
|
||||
return render_template("index.html")
|
||||
|
||||
|
||||
# Make videos.json accessible
|
||||
@app.route("/videos.json")
|
||||
def videos_json():
|
||||
return send_from_directory("video_creation/data", "videos.json")
|
||||
|
||||
|
||||
# Make videos in results folder accessible
|
||||
@app.route("/results/<path:name>")
|
||||
def results(name):
|
||||
return send_from_directory("results", name, as_attachment=True)
|
||||
|
||||
|
||||
@app.route("/add_background", methods=["POST"])
|
||||
def add_background():
|
||||
# Get form values
|
||||
youtube_uri = request.form.get("youtube_uri").strip()
|
||||
filename = request.form.get("filename").strip()
|
||||
citation = request.form.get("citation").strip()
|
||||
position = request.form.get("position").strip()
|
||||
|
||||
# Validate YouTube URI
|
||||
regex = re.compile(
|
||||
r"(?:\/|%3D|v=|vi=)([0-9A-z-_]{11})(?:[%#?&]|$)"
|
||||
).search(youtube_uri)
|
||||
|
||||
if not regex:
|
||||
flash("YouTube URI is invalid!", "error")
|
||||
return redirect(url_for("index"))
|
||||
|
||||
youtube_uri = f"https://www.youtube.com/watch?v={regex.group(1)}"
|
||||
|
||||
# Check if position is valid
|
||||
if position == "" or position == "center":
|
||||
position = "center"
|
||||
|
||||
elif position.isdecimal():
|
||||
position = int(position)
|
||||
|
||||
else:
|
||||
flash('Position is invalid! It can be "center" or decimal number.', "error")
|
||||
return redirect(url_for("index"))
|
||||
|
||||
# Sanitize filename
|
||||
filename = filename.replace(" ", "-").split(".")[0]
|
||||
|
||||
# Check if background doesn't already exist
|
||||
with open("utils/backgrounds.json", "r", encoding="utf-8") as backgrounds:
|
||||
data = json.load(backgrounds)
|
||||
|
||||
# Check if key isn't already taken
|
||||
if filename in list(data.keys()):
|
||||
flash("Background video with this name already exist!", "error")
|
||||
return redirect(url_for("index"))
|
||||
|
||||
# Check if the YouTube URI isn't already used under different name
|
||||
if youtube_uri in [data[i][0] for i in list(data.keys())]:
|
||||
flash("Background video with this YouTube URI is already added!", "error")
|
||||
return redirect(url_for("index"))
|
||||
|
||||
# Add background video to json file
|
||||
with open("utils/backgrounds.json", "r+", encoding="utf-8") as backgrounds:
|
||||
data = json.load(backgrounds)
|
||||
|
||||
data[filename] = [youtube_uri, filename + ".mp4", citation, position]
|
||||
backgrounds.seek(0)
|
||||
json.dump(data, backgrounds, ensure_ascii=False, indent=4)
|
||||
|
||||
# Add background video to ".config.template.toml" to make it accessible
|
||||
config = tomlkit.loads(Path("utils/.config.template.toml").read_text())
|
||||
config["settings"]["background"]["background_choice"]["options"].append(filename)
|
||||
|
||||
with Path("utils/.config.template.toml").open("w") as toml_file:
|
||||
toml_file.write(tomlkit.dumps(config))
|
||||
|
||||
flash(f'Added "{citation}-{filename}.mp4" as a new background video!')
|
||||
|
||||
return redirect(url_for("index"))
|
||||
|
||||
|
||||
# Run browser and start the app
|
||||
if __name__ == "__main__":
|
||||
webbrowser.open(f"http://{HOST}:{PORT}", new=2)
|
||||
print("Website opened in new tab. Refresh if it didn't load.")
|
||||
app.run(port=PORT)
|
||||
from main import main, shutdown
|
||||
|
||||
from doctest import master
|
||||
import tkinter
|
||||
import tkinter.messagebox
|
||||
import customtkinter
|
||||
from utils.settings import settings
|
||||
|
||||
customtkinter.set_appearance_mode("System") # Modes: "System" (standard), "Dark", "Light"
|
||||
customtkinter.set_default_color_theme("blue") # Themes: "blue" (standard), "green", "dark-blue"
|
||||
|
||||
|
||||
class App(customtkinter.CTk):
|
||||
|
||||
WIDTH = 1200
|
||||
HEIGHT = 600
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.title("Reddit Video Maker Bot GUI")
|
||||
self.geometry(f"{App.WIDTH}x{App.HEIGHT}")
|
||||
self.resizable(False, False)
|
||||
self.protocol("WM_DELETE_WINDOW", self.on_closing) # call .on_closing() when app gets closed
|
||||
self.resizable(False, False)
|
||||
|
||||
# ============ create two frames ============
|
||||
|
||||
# configure grid layout (2x1)
|
||||
self.grid_columnconfigure(1, weight=1)
|
||||
self.grid_rowconfigure(0, weight=1)
|
||||
|
||||
self.frame_left = customtkinter.CTkFrame(master=self,
|
||||
width=180,
|
||||
corner_radius=0)
|
||||
self.frame_left.grid(row=0, column=0, sticky="nswe")
|
||||
|
||||
# Results Frame
|
||||
self.frame_results = customtkinter.CTkFrame(master=self)
|
||||
self.frame_results.grid(row=0, column=1, sticky="nswe", padx=20, pady=20)
|
||||
|
||||
# Settings Frame
|
||||
self.frame_settings = customtkinter.CTkFrame(master=self)
|
||||
self.frame_settings.grid(row=0, column=1, sticky="nswe", padx=20, pady=20)
|
||||
|
||||
# Home Frame
|
||||
self.frame_home = customtkinter.CTkFrame(master=self)
|
||||
self.frame_home.grid(row=0, column=1, sticky="nswe", padx=20, pady=20)
|
||||
|
||||
# ============ frame_left ============
|
||||
|
||||
# configure grid layout (1x11)
|
||||
self.frame_left.grid_rowconfigure(0, minsize=10) # empty row with minsize as spacing
|
||||
self.frame_left.grid_rowconfigure(5, weight=1) # empty row as spacing
|
||||
self.frame_left.grid_rowconfigure(8, minsize=20) # empty row with minsize as spacing
|
||||
self.frame_left.grid_rowconfigure(11, minsize=10) # empty row with minsize as spacing
|
||||
|
||||
self.label_1 = customtkinter.CTkLabel(master=self.frame_left,
|
||||
text="Reddit Video Maker Bot",
|
||||
text_font=("Roboto Medium", -16)) # font name and size in px
|
||||
self.label_1.grid(row=1, column=0, pady=10, padx=10)
|
||||
|
||||
# Home Btn
|
||||
self.home_btn = customtkinter.CTkButton(master=self.frame_left,
|
||||
text="Home",
|
||||
command=self.btn_home)
|
||||
self.home_btn.grid(row=2, column=0, pady=10, padx=20)
|
||||
|
||||
# Settings Btn
|
||||
self.settings_btn = customtkinter.CTkButton(master=self.frame_left,
|
||||
text="Settings",
|
||||
command=self.btn_settings)
|
||||
self.settings_btn.grid(row=3, column=0, pady=10, padx=20)
|
||||
|
||||
# Results Btn
|
||||
self.results_btn = customtkinter.CTkButton(master=self.frame_left,
|
||||
text="Results",
|
||||
command=self.btn_results)
|
||||
self.results_btn.grid(row=4, column=0, pady=10, padx=20)
|
||||
|
||||
# Start Btn
|
||||
self.start_btn = customtkinter.CTkButton(master=self.frame_left,
|
||||
text="Start",
|
||||
command=self.btn_start)
|
||||
self.start_btn.grid(row=5, column=0, pady=10, padx=40)
|
||||
|
||||
|
||||
|
||||
# Appeareance Stuff
|
||||
self.label_mode = customtkinter.CTkLabel(master=self.frame_left, text="Appearance Mode:")
|
||||
self.label_mode.grid(row=9, column=0, pady=10, padx=20, sticky="w")
|
||||
|
||||
self.optionmenu_1 = customtkinter.CTkOptionMenu(master=self.frame_left,
|
||||
values=["Light", "Dark", "System"],
|
||||
command=self.change_appearance_mode)
|
||||
self.optionmenu_1.grid(row=10, column=0, pady=0, padx=20, sticky="w")
|
||||
|
||||
### Adds all the stuff for frame_settings ###
|
||||
|
||||
# Background within frame
|
||||
self.frame_bg_settings = customtkinter.CTkFrame(master=self.frame_settings)
|
||||
self.frame_bg_settings.grid(row=0, column=0, pady=15, padx=15, sticky=("nswe"))
|
||||
|
||||
self.frame_bg_settings.rowconfigure(10, weight=1)
|
||||
self.frame_bg_settings.columnconfigure(10, weight=1)
|
||||
|
||||
# Title
|
||||
self.settings_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Settings",
|
||||
text_font=("Courier_Bold", 24)
|
||||
)
|
||||
self.settings_title.grid(row=0, column=0, columnspan=8, pady=15, padx=15)
|
||||
|
||||
## USER SETTINGS ##
|
||||
|
||||
# User settings title
|
||||
self.user_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="User Settings",
|
||||
text_font=("Courier_Bold", 14)
|
||||
)
|
||||
self.user_title.grid(row=1, column=0, columnspan=2, pady=10)
|
||||
|
||||
# Client secret title
|
||||
self.client_secret_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Client Secrect"
|
||||
)
|
||||
self.client_secret_title.grid(row=2, column=0, padx=15)
|
||||
|
||||
# Client secret input box
|
||||
self.client_secret = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text = "Client Secret"
|
||||
)
|
||||
self.client_secret.grid(row=3, column=0, padx=15)
|
||||
|
||||
# Client id title
|
||||
self.client_id_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text = "Client Id"
|
||||
)
|
||||
self.client_id_title.grid(row=4, column=0, padx=15)
|
||||
|
||||
# Client id input box
|
||||
self.client_id = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text="Client Id"
|
||||
)
|
||||
self.client_id.grid(row=5, column=0, padx=15)
|
||||
|
||||
# Username title
|
||||
self.user_name_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Username"
|
||||
)
|
||||
self.user_name_title.grid(row=2, column=1, padx=15)
|
||||
|
||||
# Username input box
|
||||
self.user_name = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text="Username"
|
||||
)
|
||||
self.user_name.grid(row=3, column=1, padx=15)
|
||||
|
||||
# Password title
|
||||
self.user_password_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Password"
|
||||
)
|
||||
self.user_password_title.grid(row=4, column=1, padx=15)
|
||||
|
||||
# Password input box
|
||||
self.user_password = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text="Password"
|
||||
)
|
||||
self.user_password.grid(row=5, column=1, padx=15)
|
||||
|
||||
# 2fa label
|
||||
self.user_2fa_label = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text = "2FA enabled?"
|
||||
)
|
||||
self.user_2fa_label.grid(row=6, column=0, padx=15)
|
||||
|
||||
# 2fa option menu
|
||||
self.user_2fa = customtkinter.CTkOptionMenu(
|
||||
master=self.frame_bg_settings,
|
||||
values=["false", "true"]
|
||||
)
|
||||
self.user_2fa.grid(row=7, column=0, padx=15)
|
||||
|
||||
# Thread Settings
|
||||
|
||||
# Thread settings title
|
||||
self.thread_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Thread Settings",
|
||||
text_font=("Courier_Bold", 14)
|
||||
)
|
||||
self.thread_title.grid(row=1, column=2, columnspan=2, pady=10)
|
||||
|
||||
# Random Title
|
||||
self.thread_random_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Random"
|
||||
)
|
||||
self.thread_random_title.grid(row=2, column=2, padx=15)
|
||||
|
||||
# Random option menu
|
||||
self.thread_random = customtkinter.CTkOptionMenu(
|
||||
master=self.frame_bg_settings,
|
||||
values=["false", "true"]
|
||||
)
|
||||
self.thread_random.grid(row=3, column=2, padx=15)
|
||||
|
||||
# Subreddit title
|
||||
self.thread_subreddit_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Subreddit"
|
||||
)
|
||||
self.thread_subreddit_title.grid(row=2, column=3, padx=15)
|
||||
|
||||
# Subreddit input box
|
||||
self.thread_subreddit = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text="Subreddit"
|
||||
)
|
||||
self.thread_subreddit.grid(row=3, column=3, padx=15)
|
||||
|
||||
# Post id title
|
||||
self.thread_post_id_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Post Id"
|
||||
)
|
||||
self.thread_post_id_title.grid(row=4, column=2, padx=15)
|
||||
|
||||
# Post id input box
|
||||
self.thread_post_id = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text="Post Id"
|
||||
)
|
||||
self.thread_post_id.grid(row=5, column=2, padx=15)
|
||||
|
||||
# Max comment length title
|
||||
self.thread_max_comment_length_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Max comment length"
|
||||
)
|
||||
self.thread_max_comment_length_title.grid(row=4, column=3, padx=15)
|
||||
|
||||
# Max comment length
|
||||
self.thread_max_comment_length = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text="Max comment length (NUM)"
|
||||
)
|
||||
self.thread_max_comment_length.grid(row=5, column=3, padx=15)
|
||||
|
||||
# Post lang title
|
||||
self.thread_post_lang_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Post language"
|
||||
)
|
||||
self.thread_post_lang_title.grid(row=6, column=2, padx=15)
|
||||
|
||||
# Post lang
|
||||
self.thread_post_lang = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text="Post language (en/cr)"
|
||||
)
|
||||
self.thread_post_lang.grid(row=7, column=2, padx=15)
|
||||
|
||||
# Min comment length title
|
||||
self.thread_min_comment_length_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Min comment length (NUM)"
|
||||
)
|
||||
self.thread_min_comment_length_title.grid(row=6, column=3, padx=15)
|
||||
|
||||
# Min comment length
|
||||
self.thread_min_comment_length = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text="Min comment length"
|
||||
)
|
||||
self.thread_min_comment_length.grid(row=7, column=3, padx=15)
|
||||
|
||||
# Misc Settings
|
||||
|
||||
# Misc settings title
|
||||
self.misc_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Misc Settings",
|
||||
text_font=("Courier_Bold", 14)
|
||||
)
|
||||
self.misc_title.grid(row=8, column=0, columnspan=2, pady=10)
|
||||
|
||||
# Allow nsfw title
|
||||
self.misc_allow_nsfw_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Allow NSFW"
|
||||
)
|
||||
self.misc_allow_nsfw_title.grid(row=9, column=0, padx=15)
|
||||
|
||||
# Allow nsfw option box
|
||||
self.misc_allow_nsfw = customtkinter.CTkOptionMenu(
|
||||
master=self.frame_bg_settings,
|
||||
values=["False", "True"]
|
||||
)
|
||||
self.misc_allow_nsfw.grid(row=10, column=0, padx=15)
|
||||
|
||||
# Theme title
|
||||
self.misc_theme_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Theme"
|
||||
)
|
||||
self.misc_theme_title.grid(row=9, column=1, padx=15)
|
||||
|
||||
# Theme
|
||||
self.misc_theme = customtkinter.CTkOptionMenu(
|
||||
master=self.frame_bg_settings,
|
||||
values=["dark", "light"]
|
||||
)
|
||||
self.misc_theme.grid(row=10, column=1, padx=15)
|
||||
|
||||
# Times to run title
|
||||
self.misc_times_to_run_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Times to run (NUM)"
|
||||
)
|
||||
self.misc_times_to_run_title.grid(row=11, column=0, padx=15)
|
||||
|
||||
# Times to run
|
||||
self.misc_times_to_run = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text="Times to run"
|
||||
)
|
||||
self.misc_times_to_run.grid(row=12, column=0, padx=15)
|
||||
|
||||
# Opacity title
|
||||
self.misc_opacity_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Opacity (NUM 0.1-0.9)"
|
||||
)
|
||||
self.misc_opacity_title.grid(row=11, column=1, padx=15)
|
||||
|
||||
# Opcaity
|
||||
self.misc_opacity = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text="Opacity"
|
||||
)
|
||||
self.misc_opacity.grid(row=12, column=1, padx=15)
|
||||
|
||||
|
||||
# configure grid layout (3x7)
|
||||
|
||||
self.frame_info = customtkinter.CTkFrame(master=self.frame_home)
|
||||
self.frame_info.grid(row=0, column=0, columnspan=2, rowspan=4, pady=20, padx=20, sticky="nsew")
|
||||
|
||||
# ============ frame_info ============
|
||||
|
||||
# configure grid layout (1x1)
|
||||
self.frame_info.rowconfigure(0, weight=1)
|
||||
self.frame_info.columnconfigure(0, weight=1)
|
||||
|
||||
self.label_info_1 = customtkinter.CTkLabel(master=self.frame_info,
|
||||
text="Thanks for using this tool! \n" +
|
||||
"Feel free to contribute to this project on GitHub!\n"+
|
||||
"If you have any questions, feel free to reach out to\nme on Twitter or submit a GitHub issue. \n"+
|
||||
"You can find solutions to many common problems in the Documentation\nhttps://reddit-video-maker-bot.netlify.app/" ,
|
||||
height=100,
|
||||
corner_radius=6, # <- custom corner radius
|
||||
fg_color=("white", "gray38"), # <- custom tuple-color
|
||||
justify=tkinter.LEFT)
|
||||
self.label_info_1.grid(column=0, row=0, sticky="nwe", padx=15, pady=15)
|
||||
|
||||
self.progressbar = customtkinter.CTkProgressBar(master=self.frame_info)
|
||||
self.progressbar.grid(row=1, column=0, sticky="ew", padx=15, pady=15)
|
||||
|
||||
|
||||
# set default values
|
||||
self.optionmenu_1.set("Dark")
|
||||
###self.button_3.configure(state="disabled", text="Disabled CTkButton")
|
||||
###self.combobox_1.set("CTkCombobox")
|
||||
###self.radio_button_1.select()
|
||||
###self.slider_1.set(0.2)
|
||||
###self.slider_2.set(0.7)
|
||||
###self.progressbar.set(0.5)
|
||||
###self.switch_2.select()
|
||||
###self.radio_button_3.configure(state=tkinter.DISABLED)
|
||||
###self.check_box_1.configure(state=tkinter.DISABLED, text="CheckBox disabled")
|
||||
###self.check_box_2.select()
|
||||
|
||||
def load_value_from_toml(self):
|
||||
self.client_secret.set(config["settings"]["times_to_run"])
|
||||
# Show frame
|
||||
def showFrame(self, frame):
|
||||
frame.tkraise()
|
||||
|
||||
# Home button event
|
||||
def btn_home(self):
|
||||
self.showFrame(self.frame_home)
|
||||
|
||||
# Settings button event
|
||||
def btn_settings(self):
|
||||
self.showFrame(self.frame_settings)
|
||||
|
||||
# Results button event
|
||||
def btn_results(self):
|
||||
print("Results Pressed!")
|
||||
|
||||
# Start button event
|
||||
def btn_start(self):
|
||||
print("Start Pressed!")
|
||||
|
||||
# Appearance event
|
||||
def change_appearance_mode(self, new_appearance_mode):
|
||||
customtkinter.set_appearance_mode(new_appearance_mode)
|
||||
|
||||
# Close event
|
||||
def on_closing(self, event=0):
|
||||
self.destroy()
|
||||
shutdown()
|
||||
|
||||
def start():
|
||||
if __name__ == "__main__":
|
||||
app = App()
|
||||
app.mainloop()
|
||||
|
||||
start()
|
@ -1,428 +0,0 @@
|
||||
from main import main, shutdown
|
||||
|
||||
from doctest import master
|
||||
import tkinter
|
||||
import tkinter.messagebox
|
||||
import customtkinter
|
||||
|
||||
customtkinter.set_appearance_mode("System") # Modes: "System" (standard), "Dark", "Light"
|
||||
customtkinter.set_default_color_theme("blue") # Themes: "blue" (standard), "green", "dark-blue"
|
||||
|
||||
|
||||
class App(customtkinter.CTk):
|
||||
|
||||
WIDTH = 1200
|
||||
HEIGHT = 600
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.title("Reddit Video Maker Bot GUI")
|
||||
self.geometry(f"{App.WIDTH}x{App.HEIGHT}")
|
||||
self.resizable(False, False)
|
||||
self.protocol("WM_DELETE_WINDOW", self.on_closing) # call .on_closing() when app gets closed
|
||||
self.resizable(False, False)
|
||||
|
||||
# ============ create two frames ============
|
||||
|
||||
# configure grid layout (2x1)
|
||||
self.grid_columnconfigure(1, weight=1)
|
||||
self.grid_rowconfigure(0, weight=1)
|
||||
|
||||
self.frame_left = customtkinter.CTkFrame(master=self,
|
||||
width=180,
|
||||
corner_radius=0)
|
||||
self.frame_left.grid(row=0, column=0, sticky="nswe")
|
||||
|
||||
# Results Frame
|
||||
self.frame_results = customtkinter.CTkFrame(master=self)
|
||||
self.frame_results.grid(row=0, column=1, sticky="nswe", padx=20, pady=20)
|
||||
|
||||
# Settings Frame
|
||||
self.frame_settings = customtkinter.CTkFrame(master=self)
|
||||
self.frame_settings.grid(row=0, column=1, sticky="nswe", padx=20, pady=20)
|
||||
|
||||
# Home Frame
|
||||
self.frame_home = customtkinter.CTkFrame(master=self)
|
||||
self.frame_home.grid(row=0, column=1, sticky="nswe", padx=20, pady=20)
|
||||
|
||||
# ============ frame_left ============
|
||||
|
||||
# configure grid layout (1x11)
|
||||
self.frame_left.grid_rowconfigure(0, minsize=10) # empty row with minsize as spacing
|
||||
self.frame_left.grid_rowconfigure(5, weight=1) # empty row as spacing
|
||||
self.frame_left.grid_rowconfigure(8, minsize=20) # empty row with minsize as spacing
|
||||
self.frame_left.grid_rowconfigure(11, minsize=10) # empty row with minsize as spacing
|
||||
|
||||
self.label_1 = customtkinter.CTkLabel(master=self.frame_left,
|
||||
text="Reddit Video Maker Bot",
|
||||
text_font=("Roboto Medium", -16)) # font name and size in px
|
||||
self.label_1.grid(row=1, column=0, pady=10, padx=10)
|
||||
|
||||
# Home Btn
|
||||
self.home_btn = customtkinter.CTkButton(master=self.frame_left,
|
||||
text="Home",
|
||||
command=self.btn_home)
|
||||
self.home_btn.grid(row=2, column=0, pady=10, padx=20)
|
||||
|
||||
# Settings Btn
|
||||
self.settings_btn = customtkinter.CTkButton(master=self.frame_left,
|
||||
text="Settings",
|
||||
command=self.btn_settings)
|
||||
self.settings_btn.grid(row=3, column=0, pady=10, padx=20)
|
||||
|
||||
# Results Btn
|
||||
self.results_btn = customtkinter.CTkButton(master=self.frame_left,
|
||||
text="Results",
|
||||
command=self.btn_results)
|
||||
self.results_btn.grid(row=4, column=0, pady=10, padx=20)
|
||||
|
||||
# Start Btn
|
||||
self.start_btn = customtkinter.CTkButton(master=self.frame_left,
|
||||
text="Start",
|
||||
command=self.btn_start)
|
||||
self.start_btn.grid(row=5, column=0, pady=10, padx=40)
|
||||
|
||||
|
||||
|
||||
# Appeareance Stuff
|
||||
self.label_mode = customtkinter.CTkLabel(master=self.frame_left, text="Appearance Mode:")
|
||||
self.label_mode.grid(row=9, column=0, pady=10, padx=20, sticky="w")
|
||||
|
||||
self.optionmenu_1 = customtkinter.CTkOptionMenu(master=self.frame_left,
|
||||
values=["Light", "Dark", "System"],
|
||||
command=self.change_appearance_mode)
|
||||
self.optionmenu_1.grid(row=10, column=0, pady=0, padx=20, sticky="w")
|
||||
|
||||
### Adds all the stuff for frame_settings ###
|
||||
|
||||
# Background within frame
|
||||
self.frame_bg_settings = customtkinter.CTkFrame(master=self.frame_settings)
|
||||
self.frame_bg_settings.grid(row=0, column=0, pady=15, padx=15, sticky=("nswe"))
|
||||
|
||||
self.frame_bg_settings.rowconfigure(10, weight=1)
|
||||
self.frame_bg_settings.columnconfigure(10, weight=1)
|
||||
|
||||
# Title
|
||||
self.settings_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Settings",
|
||||
text_font=("Courier_Bold", 24)
|
||||
)
|
||||
self.settings_title.grid(row=0, column=0, columnspan=8, pady=15, padx=15)
|
||||
|
||||
## USER SETTINGS ##
|
||||
|
||||
# User settings title
|
||||
self.user_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="User Settings",
|
||||
text_font=("Courier_Bold", 14)
|
||||
)
|
||||
self.user_title.grid(row=1, column=0, columnspan=2, pady=10)
|
||||
|
||||
# Client secret title
|
||||
self.client_secret_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Client Secrect"
|
||||
)
|
||||
self.client_secret_title.grid(row=2, column=0, padx=15)
|
||||
|
||||
# Client secret input box
|
||||
self.client_secret = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text = "Client Secret"
|
||||
)
|
||||
self.client_secret.grid(row=3, column=0, padx=15)
|
||||
|
||||
# Client id title
|
||||
self.client_id_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text = "Client Id"
|
||||
)
|
||||
self.client_id_title.grid(row=4, column=0, padx=15)
|
||||
|
||||
# Client id input box
|
||||
self.client_id = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text="Client Id"
|
||||
)
|
||||
self.client_id.grid(row=5, column=0, padx=15)
|
||||
|
||||
# Username title
|
||||
self.user_name_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Username"
|
||||
)
|
||||
self.user_name_title.grid(row=2, column=1, padx=15)
|
||||
|
||||
# Username input box
|
||||
self.user_name = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text="Username"
|
||||
)
|
||||
self.user_name.grid(row=3, column=1, padx=15)
|
||||
|
||||
# Password title
|
||||
self.user_password_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Password"
|
||||
)
|
||||
self.user_password_title.grid(row=4, column=1, padx=15)
|
||||
|
||||
# Password input box
|
||||
self.user_password = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text="Password"
|
||||
)
|
||||
self.user_password.grid(row=5, column=1, padx=15)
|
||||
|
||||
# 2fa label
|
||||
self.user_2fa_label = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text = "2FA enabled?"
|
||||
)
|
||||
self.user_2fa_label.grid(row=6, column=0, padx=15)
|
||||
|
||||
# 2fa option menu
|
||||
self.user_2fa = customtkinter.CTkOptionMenu(
|
||||
master=self.frame_bg_settings,
|
||||
values=["false", "true"]
|
||||
)
|
||||
self.user_2fa.grid(row=7, column=0, padx=15)
|
||||
|
||||
# Thread Settings
|
||||
|
||||
# Thread settings title
|
||||
self.thread_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Thread Settings",
|
||||
text_font=("Courier_Bold", 14)
|
||||
)
|
||||
self.thread_title.grid(row=1, column=2, columnspan=2, pady=10)
|
||||
|
||||
# Random Title
|
||||
self.thread_random_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Random"
|
||||
)
|
||||
self.thread_random_title.grid(row=2, column=2, padx=15)
|
||||
|
||||
# Random option menu
|
||||
self.thread_random = customtkinter.CTkOptionMenu(
|
||||
master=self.frame_bg_settings,
|
||||
values=["false", "true"]
|
||||
)
|
||||
self.thread_random.grid(row=3, column=2, padx=15)
|
||||
|
||||
# Subreddit title
|
||||
self.thread_subreddit_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Subreddit"
|
||||
)
|
||||
self.thread_subreddit_title.grid(row=2, column=3, padx=15)
|
||||
|
||||
# Subreddit input box
|
||||
self.thread_subreddit = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text="Subreddit"
|
||||
)
|
||||
self.thread_subreddit.grid(row=3, column=3, padx=15)
|
||||
|
||||
# Post id title
|
||||
self.thread_post_id_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Post Id"
|
||||
)
|
||||
self.thread_post_id_title.grid(row=4, column=2, padx=15)
|
||||
|
||||
# Post id input box
|
||||
self.thread_post_id = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text="Post Id"
|
||||
)
|
||||
self.thread_post_id.grid(row=5, column=2, padx=15)
|
||||
|
||||
# Max comment length title
|
||||
self.thread_max_comment_length_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Max comment length"
|
||||
)
|
||||
self.thread_max_comment_length_title.grid(row=4, column=3, padx=15)
|
||||
|
||||
# Max comment length
|
||||
self.thread_max_comment_length = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text="Max comment length (NUM)"
|
||||
)
|
||||
self.thread_max_comment_length.grid(row=5, column=3, padx=15)
|
||||
|
||||
# Post lang title
|
||||
self.thread_post_lang_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Post language"
|
||||
)
|
||||
self.thread_post_lang_title.grid(row=6, column=2, padx=15)
|
||||
|
||||
# Post lang
|
||||
self.thread_post_lang = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text="Post language (en/cr)"
|
||||
)
|
||||
self.thread_post_lang.grid(row=7, column=2, padx=15)
|
||||
|
||||
# Min comment length title
|
||||
self.thread_min_comment_length_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Min comment length (NUM)"
|
||||
)
|
||||
self.thread_min_comment_length_title.grid(row=6, column=3, padx=15)
|
||||
|
||||
# Min comment length
|
||||
self.thread_min_comment_length = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text="Min comment length"
|
||||
)
|
||||
self.thread_min_comment_length.grid(row=7, column=3, padx=15)
|
||||
|
||||
# Misc Settings
|
||||
|
||||
# Misc settings title
|
||||
self.misc_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Misc Settings",
|
||||
text_font=("Courier_Bold", 14)
|
||||
)
|
||||
self.misc_title.grid(row=8, column=0, columnspan=2, pady=10)
|
||||
|
||||
# Allow nsfw title
|
||||
self.misc_allow_nsfw_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Allow NSFW"
|
||||
)
|
||||
self.misc_allow_nsfw_title.grid(row=9, column=0, padx=15)
|
||||
|
||||
# Allow nsfw option box
|
||||
self.misc_allow_nsfw = customtkinter.CTkOptionMenu(
|
||||
master=self.frame_bg_settings,
|
||||
values=["False", "True"]
|
||||
)
|
||||
self.misc_allow_nsfw.grid(row=10, column=0, padx=15)
|
||||
|
||||
# Theme title
|
||||
self.misc_theme_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Theme"
|
||||
)
|
||||
self.misc_theme_title.grid(row=9, column=1, padx=15)
|
||||
|
||||
# Theme
|
||||
self.misc_theme = customtkinter.CTkOptionMenu(
|
||||
master=self.frame_bg_settings,
|
||||
values=["dark", "light"]
|
||||
)
|
||||
self.misc_theme.grid(row=10, column=1, padx=15)
|
||||
|
||||
# Times to run title
|
||||
self.misc_times_to_run_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Times to run (NUM)"
|
||||
)
|
||||
self.misc_times_to_run_title.grid(row=11, column=0, padx=15)
|
||||
|
||||
# Times to run
|
||||
self.misc_times_to_run = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text="Times to run"
|
||||
)
|
||||
self.misc_times_to_run.grid(row=12, column=0, padx=15)
|
||||
|
||||
# Opacity title
|
||||
self.misc_opacity_title = customtkinter.CTkLabel(
|
||||
master=self.frame_bg_settings,
|
||||
text="Opacity (NUM 0.1-0.9)"
|
||||
)
|
||||
self.misc_opacity_title.grid(row=11, column=1, padx=15)
|
||||
|
||||
# Opcaity
|
||||
self.misc_opacity = customtkinter.CTkEntry(
|
||||
master=self.frame_bg_settings,
|
||||
placeholder_text="Opacity"
|
||||
)
|
||||
self.misc_opacity.grid(row=12, column=1, padx=15)
|
||||
|
||||
|
||||
# configure grid layout (3x7)
|
||||
|
||||
self.frame_info = customtkinter.CTkFrame(master=self.frame_home)
|
||||
self.frame_info.grid(row=0, column=0, columnspan=2, rowspan=4, pady=20, padx=20, sticky="nsew")
|
||||
|
||||
# ============ frame_info ============
|
||||
|
||||
# configure grid layout (1x1)
|
||||
self.frame_info.rowconfigure(0, weight=1)
|
||||
self.frame_info.columnconfigure(0, weight=1)
|
||||
|
||||
self.label_info_1 = customtkinter.CTkLabel(master=self.frame_info,
|
||||
text="Thanks for using this tool! \n" +
|
||||
"Feel free to contribute to this project on GitHub!\n"+
|
||||
"If you have any questions, feel free to reach out to\nme on Twitter or submit a GitHub issue. \n"+
|
||||
"You can find solutions to many common problems in the Documentation\nhttps://reddit-video-maker-bot.netlify.app/" ,
|
||||
height=100,
|
||||
corner_radius=6, # <- custom corner radius
|
||||
fg_color=("white", "gray38"), # <- custom tuple-color
|
||||
justify=tkinter.LEFT)
|
||||
self.label_info_1.grid(column=0, row=0, sticky="nwe", padx=15, pady=15)
|
||||
|
||||
self.progressbar = customtkinter.CTkProgressBar(master=self.frame_info)
|
||||
self.progressbar.grid(row=1, column=0, sticky="ew", padx=15, pady=15)
|
||||
|
||||
|
||||
# set default values
|
||||
self.optionmenu_1.set("Dark")
|
||||
###self.button_3.configure(state="disabled", text="Disabled CTkButton")
|
||||
###self.combobox_1.set("CTkCombobox")
|
||||
###self.radio_button_1.select()
|
||||
###self.slider_1.set(0.2)
|
||||
###self.slider_2.set(0.7)
|
||||
###self.progressbar.set(0.5)
|
||||
###self.switch_2.select()
|
||||
###self.radio_button_3.configure(state=tkinter.DISABLED)
|
||||
###self.check_box_1.configure(state=tkinter.DISABLED, text="CheckBox disabled")
|
||||
###self.check_box_2.select()
|
||||
|
||||
# Show frame
|
||||
def showFrame(self, frame):
|
||||
frame.tkraise()
|
||||
|
||||
# Home button event
|
||||
def btn_home(self):
|
||||
self.showFrame(self.frame_home)
|
||||
|
||||
# Settings button event
|
||||
def btn_settings(self):
|
||||
self.showFrame(self.frame_settings)
|
||||
|
||||
# Results button event
|
||||
def btn_results(self):
|
||||
print("Results Pressed!")
|
||||
|
||||
# Start button event
|
||||
def btn_start(self):
|
||||
print("Start Pressed!")
|
||||
|
||||
# Appearance event
|
||||
def change_appearance_mode(self, new_appearance_mode):
|
||||
customtkinter.set_appearance_mode(new_appearance_mode)
|
||||
|
||||
# Close event
|
||||
def on_closing(self, event=0):
|
||||
self.destroy()
|
||||
shutdown()
|
||||
|
||||
def start():
|
||||
if __name__ == "__main__":
|
||||
app = App()
|
||||
app.mainloop()
|
||||
|
||||
start()
|
@ -1,404 +0,0 @@
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="cache-control" content="no-cache" />
|
||||
<title>RedditVideoMakerBot</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.1.3/dist/css/bootstrap.min.css"
|
||||
integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://getbootstrap.com/docs/5.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.3/font/bootstrap-icons.css">
|
||||
|
||||
<style>
|
||||
.bd-placeholder-img {
|
||||
font-size: 1.125rem;
|
||||
text-anchor: middle;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.bd-placeholder-img-lg {
|
||||
font-size: 3.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.b-example-divider {
|
||||
height: 3rem;
|
||||
background-color: rgba(0, 0, 0, .1);
|
||||
border: solid rgba(0, 0, 0, .15);
|
||||
border-width: 1px 0;
|
||||
box-shadow: inset 0 .5em 1.5em rgba(0, 0, 0, .1), inset 0 .125em .5em rgba(0, 0, 0, .15);
|
||||
}
|
||||
|
||||
.b-example-vr {
|
||||
flex-shrink: 0;
|
||||
width: 1.5rem;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.bi {
|
||||
vertical-align: -.125em;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
.nav-scroller {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
height: 2.75rem;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.nav-scroller .nav {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
padding-bottom: 1rem;
|
||||
margin-top: -1px;
|
||||
overflow-x: auto;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
#tooltip {
|
||||
background-color: #333;
|
||||
color: white;
|
||||
padding: 5px 10px;
|
||||
border-radius: 4px;
|
||||
font-size: 13px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<header>
|
||||
{% if get_flashed_messages() %}
|
||||
{% for category, message in get_flashed_messages(with_categories=true) %}
|
||||
|
||||
{% if category == "error" %}
|
||||
<div class="alert alert-danger mb-0 text-center" role="alert">
|
||||
{{ message }}
|
||||
</div>
|
||||
|
||||
{% else %}
|
||||
<div class="alert alert-success mb-0 text-center" role="alert">
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<div class="navbar navbar-dark bg-dark shadow-sm">
|
||||
<div class="container">
|
||||
<a href="#" class="navbar-brand d-flex align-items-center">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor"
|
||||
stroke-linecap="round" stroke-linejoin="round" stroke-width="2" aria-hidden="true" class="me-2"
|
||||
viewBox="0 0 24 24">
|
||||
<path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z" />
|
||||
<circle cx="12" cy="13" r="4" />
|
||||
</svg>
|
||||
<strong>RedditVideoMakerBot</strong>
|
||||
</a>
|
||||
<!-- Button trigger modal -->
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#backgroundModal">
|
||||
Add background video
|
||||
</button>
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="backgroundModal" tabindex="-1" role="dialog" aria-labelledby="backgroundModalLabel"
|
||||
aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="backgroundModalLabel">Add Background Video</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
<!-- Add video form -->
|
||||
<form action="/add_background" method="post">
|
||||
<div class="form-group row">
|
||||
<label class="col-4 col-form-label" for="youtube_uri">YouTube URI</label>
|
||||
<div class="col-8">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<i class="bi bi-youtube"></i>
|
||||
</div>
|
||||
</div>
|
||||
<input id="youtube_uri" name="youtube_uri" placeholder="https://www.youtube.com/watch?v=..."
|
||||
type="text" class="form-control" required="required">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="filename" class="col-4 col-form-label">Filename</label>
|
||||
<div class="col-8">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<i class="bi bi-file-earmark"></i>
|
||||
</div>
|
||||
</div>
|
||||
<input id="filename" name="filename" placeholder="example: cool-background" type="text"
|
||||
aria-describedby="filenameHelpBlock" required="required" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="citation" class="col-4 col-form-label">Credits (owner of the video)</label>
|
||||
<div class="col-8">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<i class="bi bi-person-circle"></i>
|
||||
</div>
|
||||
</div>
|
||||
<input id="citation" name="citation" placeholder="YouTube Channel" type="text"
|
||||
class="form-control" required="required" aria-describedby="citationHelpBlock">
|
||||
</div>
|
||||
<span id="citationHelpBlock" class="form-text text-muted">Include the channel name of the owner of
|
||||
the background video you are adding.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="position" class="col-4 col-form-label">Position of screenshots</label>
|
||||
<div class="col-8">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<i class="bi bi-arrows-fullscreen"></i>
|
||||
</div>
|
||||
</div>
|
||||
<input id="position" name="position" placeholder="Example: center" type="text"
|
||||
class="form-control" aria-describedby="positionHelpBlock">
|
||||
</div>
|
||||
<span id="positionHelpBlock" class="form-text text-muted">Advanced option (you can leave it
|
||||
empty). Valid options are "center" and decimal numbers</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||
<button name="submit" type="submit" class="btn btn-primary">Add background</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<div class="album py-2 bg-light">
|
||||
<div class="container">
|
||||
|
||||
<div class="row mt-2">
|
||||
<div class="col-12 col-md-3 mb-3">
|
||||
<input type="text" class="form-control" placeholder="Search videos" aria-label="Search videos"
|
||||
onkeyup="searchFilter()">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3" id="videos">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="text-muted py-5">
|
||||
<div class="container">
|
||||
<p class="float-end mb-1">
|
||||
<a href="#">Back to top</a>
|
||||
</p>
|
||||
<p class="mb-1"><a href="https://getbootstrap.com/docs/5.2/examples/album/" target="_blank">Album</a> Example
|
||||
Theme by © Bootstrap. <a
|
||||
href="https://github.com/elebumm/RedditVideoMakerBot/blob/master/README.md#developers-and-maintainers"
|
||||
target="_blank">Developers and Maintainers</a></p>
|
||||
<p class="mb-0">If your data is not refreshing, try to hard reload(Ctrl + F5) and visit your local <a
|
||||
href="../video_creation/data/videos.json" target="_blank">videos.json</a> file.</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.1.1.js" integrity="sha256-16cdPddA6VdVInumRGo6IbivbERE8p7CQR3HzTBuELA="
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.14.3/dist/umd/popper.min.js"
|
||||
integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.1.3/dist/js/bootstrap.min.js"
|
||||
integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.10/clipboard.min.js"></script>
|
||||
<script src="https://unpkg.com/isotope-layout@3/dist/isotope.pkgd.js"></script>
|
||||
|
||||
<script>
|
||||
const intervals = [
|
||||
{ label: 'year', seconds: 31536000 },
|
||||
{ label: 'month', seconds: 2592000 },
|
||||
{ label: 'day', seconds: 86400 },
|
||||
{ label: 'hour', seconds: 3600 },
|
||||
{ label: 'minute', seconds: 60 },
|
||||
{ label: 'second', seconds: 1 }
|
||||
];
|
||||
|
||||
function timeSince(date) {
|
||||
const seconds = Math.floor((Date.now() / 1000 - date));
|
||||
const interval = intervals.find(i => i.seconds < seconds);
|
||||
const count = Math.floor(seconds / interval.seconds);
|
||||
return `${count} ${interval.label}${count !== 1 ? 's' : ''} ago`;
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$.getJSON("videos.json",
|
||||
function (data) {
|
||||
data.sort((b, a) => a['time'] - b['time'])
|
||||
var video = '';
|
||||
$.each(data, function (key, value) {
|
||||
|
||||
video += '<div class="col">';
|
||||
video += '<div class="card shadow-sm">';
|
||||
//keeping original themed image card for future thumbnail usage video += '<svg class="bd-placeholder-img card-img-top" width="100%" height="225" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Placeholder: Thumbnail" preserveAspectRatio="xMidYMid slice" focusable="false"><title>Placeholder</title><rect width="100%" height="100%" fill="#55595c"/><text x="50%" y="50%" fill="#eceeef" dy=".3em">r/'+value.subreddit+'</text></svg>';
|
||||
|
||||
video += '<div class="card-body">';
|
||||
video += '<p class="card-text">r/' + value.subreddit + ' • ' + checkTitle(value.reddit_title, value.filename) + '</p>';
|
||||
video += '<div class="d-flex justify-content-between align-items-center">';
|
||||
video += '<div class="btn-group">';
|
||||
video += '<a href="https://www.reddit.com/r/' + value.subreddit + '/comments/' + value.id + '/" class="btn btn-sm btn-outline-secondary" target="_blank">View</a>';
|
||||
video += '<a href="http://localhost:4000/results/' + value.subreddit + '/' + value.filename + '" class="btn btn-sm btn-outline-secondary" download>Download</a>';
|
||||
video += '</div>';
|
||||
video += '<div class="btn-group">';
|
||||
video += '<button type="button" data-toggle="tooltip" id="copy" data-original-title="Copy to clipboard" class="btn btn-sm btn-outline-secondary" data-clipboard-text="' + getCopyData(value.subreddit, value.reddit_title, value.filename, value.background_credit) + '"><i class="bi bi-card-text"></i></button>';
|
||||
video += '<button type="button" data-toggle="tooltip" id="copy" data-original-title="Copy to clipboard" class="btn btn-sm btn-outline-secondary" data-clipboard-text="' + checkTitle(value.reddit_title, value.filename) + ' #Shorts #reddit"><i class="bi bi-youtube"></i></button>';
|
||||
video += '<button type="button" data-toggle="tooltip" id="copy" data-original-title="Copy to clipboard" class="btn btn-sm btn-outline-secondary" data-clipboard-text="' + checkTitle(value.reddit_title, value.filename) + ' #reddit"><i class="bi bi-instagram"></i></button>';
|
||||
video += '</div>';
|
||||
video += '<small class="text-muted">' + timeSince(value.time) + '</small>';
|
||||
video += '</div>';
|
||||
video += '</div>';
|
||||
video += '</div>';
|
||||
video += '</div>';
|
||||
|
||||
});
|
||||
|
||||
$('#videos').append(video);
|
||||
});
|
||||
});
|
||||
|
||||
$(document).ready(function () {
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
$('[data-toggle="tooltip"]').on('click', function () {
|
||||
$(this).tooltip('hide');
|
||||
});
|
||||
});
|
||||
|
||||
$('#copy').tooltip({
|
||||
trigger: 'click',
|
||||
placement: 'bottom'
|
||||
});
|
||||
|
||||
function setTooltip(btn, message) {
|
||||
$(btn).tooltip('hide')
|
||||
.attr('data-original-title', message)
|
||||
.tooltip('show');
|
||||
}
|
||||
|
||||
function hoverTooltip(btn, message) {
|
||||
$(btn).tooltip('hide')
|
||||
.attr('data-original-title', message)
|
||||
.tooltip('show');
|
||||
}
|
||||
|
||||
function hideTooltip(btn) {
|
||||
setTimeout(function () {
|
||||
$(btn).tooltip('hide');
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function disposeTooltip(btn) {
|
||||
setTimeout(function () {
|
||||
$(btn).tooltip('dispose');
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
var clipboard = new ClipboardJS('#copy');
|
||||
|
||||
clipboard.on('success', function (e) {
|
||||
e.clearSelection();
|
||||
console.info('Action:', e.action);
|
||||
console.info('Text:', e.text);
|
||||
console.info('Trigger:', e.trigger);
|
||||
setTooltip(e.trigger, 'Copied!');
|
||||
hideTooltip(e.trigger);
|
||||
disposeTooltip(e.trigger);
|
||||
});
|
||||
|
||||
clipboard.on('error', function (e) {
|
||||
console.error('Action:', e.action);
|
||||
console.error('Trigger:', e.trigger);
|
||||
setTooltip(e.trigger, fallbackMessage(e.action));
|
||||
hideTooltip(e.trigger);
|
||||
});
|
||||
|
||||
function getCopyData(subreddit, reddit_title, filename, background_credit) {
|
||||
|
||||
if (subreddit == undefined) {
|
||||
subredditCopy = "";
|
||||
} else {
|
||||
subredditCopy = "r/" + subreddit + "\n\n";
|
||||
}
|
||||
|
||||
const file = filename.slice(0, -4);
|
||||
if (reddit_title == file) {
|
||||
titleCopy = reddit_title;
|
||||
} else {
|
||||
titleCopy = file;
|
||||
}
|
||||
|
||||
var copyData = "";
|
||||
copyData += subredditCopy;
|
||||
copyData += titleCopy;
|
||||
copyData += "\n\nBackground credit: " + background_credit;
|
||||
return copyData;
|
||||
}
|
||||
|
||||
function getLink(subreddit, id, reddit_title) {
|
||||
if (subreddit == undefined) {
|
||||
return reddit_title;
|
||||
} else {
|
||||
return "<a target='_blank' href='https://www.reddit.com/r/" + subreddit + "/comments/" + id + "/'>" + reddit_title + "</a>";
|
||||
}
|
||||
}
|
||||
|
||||
function checkTitle(reddit_title, filename) {
|
||||
const file = filename.slice(0, -4);
|
||||
if (reddit_title == file) {
|
||||
return reddit_title;
|
||||
} else {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
var searchFilter = () => {
|
||||
const input = document.querySelector(".form-control");
|
||||
const cards = document.getElementsByClassName("col");
|
||||
console.log(cards[1])
|
||||
let filter = input.value
|
||||
for (let i = 0; i < cards.length; i++) {
|
||||
let title = cards[i].querySelector(".card-text");
|
||||
if (title.innerText.toLowerCase().indexOf(filter.toLowerCase()) > -1) {
|
||||
cards[i].classList.remove("d-none")
|
||||
} else {
|
||||
cards[i].classList.add("d-none")
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
Loading…
Reference in new issue