New function in GUI

"Add background video" option added to GUI
pull/1158/head
RiveN000 2 years ago
parent 1189f84bd8
commit 2da3d95959

146
GUI.py

@ -1,32 +1,128 @@
# Import the server module import json
import http.server import re
import webbrowser 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 # Set the hostname
HOST = "localhost" HOST = "localhost"
# Set the port number # Set the port number
PORT = 4000 PORT = 4000
# Define class to display the index page of the web server # Configure application
class PythonServer(http.server.SimpleHTTPRequestHandler): app = Flask(__name__, template_folder="GUI")
def do_GET(self):
if self.path == "/GUI": # Configure secret key only to use 'flash'
self.path = "index.html" app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'
return http.server.SimpleHTTPRequestHandler.do_GET(self)
# Ensure responses aren't cached
# Declare object of the class @app.after_request
webServer = http.server.HTTPServer((HOST, PORT), PythonServer) def after_request(response):
# Print the URL of the webserver, new =2 opens in a new tab response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
print(f"Server started at http://{HOST}:{PORT}/GUI/") response.headers["Expires"] = 0
webbrowser.open(f"http://{HOST}:{PORT}/GUI/", new=2) response.headers["Pragma"] = "no-cache"
print("Website opened in new tab") return response
print("Press Ctrl+C to quit")
try:
# Run the web server # Display index.html
webServer.serve_forever() @app.route("/")
except KeyboardInterrupt: def index():
# Stop the web server return render_template("index.html")
webServer.server_close()
print("The server is stopped.")
exit() # 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"(?:https?:\/\/)?(?:www\.)?youtu\.?be(?:\.com)?\/?.*(?:watch|embed)?(?:.*v=|v\/|\/)([\w\-_]+)\&?"
).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)

@ -1,141 +1,263 @@
<html lang="en"> <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 { <head>
height: 3rem; <meta charset="utf-8">
background-color: rgba(0, 0, 0, .1); <meta name="viewport" content="width=device-width, initial-scale=1">
border: solid rgba(0, 0, 0, .15); <meta http-equiv="cache-control" content="no-cache" />
border-width: 1px 0; <title>RedditVideoMakerBot</title>
box-shadow: inset 0 .5em 1.5em rgba(0, 0, 0, .1), inset 0 .125em .5em rgba(0, 0, 0, .15); <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;
}
.b-example-vr { @media (min-width: 768px) {
flex-shrink: 0; .bd-placeholder-img-lg {
width: 1.5rem; font-size: 3.5rem;
height: 100vh; }
} }
.bi { .b-example-divider {
vertical-align: -.125em; height: 3rem;
fill: currentColor; 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);
}
.nav-scroller { .b-example-vr {
position: relative; flex-shrink: 0;
z-index: 2; width: 1.5rem;
height: 2.75rem; height: 100vh;
overflow-y: hidden; }
}
.nav-scroller .nav { .bi {
display: flex; vertical-align: -.125em;
flex-wrap: nowrap; fill: currentColor;
padding-bottom: 1rem; }
margin-top: -1px;
overflow-x: auto;
text-align: center;
white-space: nowrap;
-webkit-overflow-scrolling: touch;
}
#tooltip { .nav-scroller {
background-color: #333; position: relative;
color: white; z-index: 2;
padding: 5px 10px; height: 2.75rem;
border-radius: 4px; overflow-y: hidden;
font-size: 13px; }
}
</style>
</head>
<body>
<header>
<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>
</div>
</div>
</header>
<main> .nav-scroller .nav {
<div class="album py-2 bg-light"> display: flex;
<div class="container"> flex-wrap: nowrap;
padding-bottom: 1rem;
margin-top: -1px;
overflow-x: auto;
text-align: center;
white-space: nowrap;
-webkit-overflow-scrolling: touch;
}
<div class="row mt-2"> #tooltip {
<div class="col-12 col-md-3 mb-3"> background-color: #333;
<input type="text" class="form-control" placeholder="Search videos" aria-label="Search videos" onkeyup="searchFilter()"> 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">&times;</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>
<div class="grid row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3" id="videos"> </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> </div>
</div>
</main>
<footer class="text-muted py-5"> <div class="grid row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3" id="videos">
<div class="container">
<p class="float-end mb-1"> </div>
<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 &copy; 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> </div>
</footer> </div>
</main>
<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> <footer class="text-muted py-5">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.1.3/dist/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script> <div class="container">
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.10/clipboard.min.js"></script> <p class="float-end mb-1">
<script src="https://unpkg.com/isotope-layout@3/dist/isotope.pkgd.js"></script> <a href="#">Back to top</a>
</p>
<script> <p class="mb-1"><a href="https://getbootstrap.com/docs/5.2/examples/album/" target="_blank">Album</a> Example
const intervals = [ Theme by &copy; Bootstrap. <a
{ label: 'year', seconds: 31536000 }, href="https://github.com/elebumm/RedditVideoMakerBot/blob/master/README.md#developers-and-maintainers"
{ label: 'month', seconds: 2592000 }, target="_blank">Developers and Maintainers</a></p>
{ label: 'day', seconds: 86400 }, <p class="mb-0">If your data is not refreshing, try to hard reload(Ctrl + F5) and visit your local <a
{ label: 'hour', seconds: 3600 }, href="../video_creation/data/videos.json" target="_blank">videos.json</a> file.</p>
{ label: 'minute', seconds: 60 }, </div>
{ label: 'second', seconds: 1 } </footer>
];
<script src="https://code.jquery.com/jquery-3.1.1.js" integrity="sha256-16cdPddA6VdVInumRGo6IbivbERE8p7CQR3HzTBuELA="
function timeSince(date) { crossorigin="anonymous"></script>
const seconds = Math.floor((Date.now() / 1000 - date)); <script src="https://cdn.jsdelivr.net/npm/popper.js@1.14.3/dist/umd/popper.min.js"
const interval = intervals.find(i => i.seconds < seconds); integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49"
const count = Math.floor(seconds / interval.seconds); crossorigin="anonymous"></script>
return `${count} ${interval.label}${count !== 1 ? 's' : ''} ago`; <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 () { $(document).ready(function () {
$.getJSON("../video_creation/data/videos.json", $.getJSON("videos.json",
function (data) { function (data) {
data.sort((b, a) => a['time'] - b['time']) data.sort((b, a) => a['time'] - b['time'])
var video = ''; var video = '';
$.each(data, function (key, value) { $.each(data, function (key, value) {
@ -145,18 +267,18 @@
//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>'; //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 += '<div class="card-body">';
video += '<p class="card-text">r/'+value.subreddit+' • '+checkTitle(value.reddit_title, value.filename)+'</p>'; 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="d-flex justify-content-between align-items-center">';
video += '<div class="btn-group">'; 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="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 += '<a href="http://localhost:4000/results/' + value.subreddit + '/' + value.filename + '" class="btn btn-sm btn-outline-secondary" download>Download</a>';
video += '</div>'; video += '</div>';
video += '<div class="btn-group">'; 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="' + 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) + ' #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 += '<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 += '</div>';
video += '<small class="text-muted">'+timeSince(value.time)+'</small>'; video += '<small class="text-muted">' + timeSince(value.time) + '</small>';
video += '</div>'; video += '</div>';
video += '</div>'; video += '</div>';
video += '</div>'; video += '</div>';
@ -166,116 +288,117 @@
$('#videos').append(video); $('#videos').append(video);
}); });
}); });
$(document).ready(function(){ $(document).ready(function () {
$('[data-toggle="tooltip"]').tooltip(); $('[data-toggle="tooltip"]').tooltip();
$('[data-toggle="tooltip"]').on('click', function(){ $('[data-toggle="tooltip"]').on('click', function () {
$(this).tooltip('hide'); $(this).tooltip('hide');
});
}); });
});
$('#copy').tooltip({ $('#copy').tooltip({
trigger: 'click', trigger: 'click',
placement: 'bottom' 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) { function setTooltip(btn, message) {
setTimeout(function() { $(btn).tooltip('hide')
$(btn).tooltip('hide'); .attr('data-original-title', message)
}, 1000); .tooltip('show');
} }
function disposeTooltip(btn) { function hoverTooltip(btn, message) {
setTimeout(function() { $(btn).tooltip('hide')
$(btn).tooltip('dispose'); .attr('data-original-title', message)
}, 1500); .tooltip('show');
} }
var clipboard = new ClipboardJS('#copy'); function hideTooltip(btn) {
setTimeout(function () {
$(btn).tooltip('hide');
}, 1000);
}
clipboard.on('success', function(e) { function disposeTooltip(btn) {
e.clearSelection(); setTimeout(function () {
console.info('Action:', e.action); $(btn).tooltip('dispose');
console.info('Text:', e.text); }, 1500);
console.info('Trigger:', e.trigger); }
setTooltip(e.trigger, 'Copied!');
hideTooltip(e.trigger);
disposeTooltip(e.trigger);
});
clipboard.on('error', function(e) { var clipboard = new ClipboardJS('#copy');
console.error('Action:', e.action);
console.error('Trigger:', e.trigger); clipboard.on('success', function (e) {
setTooltip(e.trigger, fallbackMessage(e.action)); e.clearSelection();
hideTooltip(e.trigger); 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";
}
function getCopyData(subreddit, reddit_title, filename, background_credit){ const file = filename.slice(0, -4);
if (reddit_title == file) {
titleCopy = reddit_title;
} else {
titleCopy = file;
}
if (subreddit == undefined) { var copyData = "";
subredditCopy = ""; copyData += subredditCopy;
} else { copyData += titleCopy;
subredditCopy = "r/" + subreddit + "\n\n"; copyData += "\n\nBackground credit: " + background_credit;
} return copyData;
}
const file = filename.slice(0, -4); function getLink(subreddit, id, reddit_title) {
if (reddit_title == file) { if (subreddit == undefined) {
titleCopy = reddit_title; return reddit_title;
} else { } else {
titleCopy = file; return "<a target='_blank' href='https://www.reddit.com/r/" + subreddit + "/comments/" + id + "/'>" + reddit_title + "</a>";
} }
}
var copyData = ""; function checkTitle(reddit_title, filename) {
copyData += subredditCopy; const file = filename.slice(0, -4);
copyData += titleCopy; if (reddit_title == file) {
copyData += "\n\nBackground credit: " + background_credit; return reddit_title;
return copyData; } else {
return file;
}
} }
function getLink(subreddit, id, reddit_title) { var searchFilter = () => {
if (subreddit == undefined) { const input = document.querySelector(".form-control");
return reddit_title; 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 { } else {
return "<a target='_blank' href='https://www.reddit.com/r/" + subreddit + "/comments/" + id + "/'>"+ reddit_title +"</a>"; cards[i].classList.add("d-none")
}
} }
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> </script>
</body>
</html> </html>

@ -11,3 +11,5 @@ toml==0.10.2
translators==5.3.1 translators==5.3.1
pyttsx3==2.90 pyttsx3==2.90
Pillow~=9.1.1 Pillow~=9.1.1
tomlkit==0.11.4
Flask==2.2.2

@ -1,45 +0,0 @@
# Supported Background. Can add/remove background video here....
# <key>-<value> : key -> used as keyword for TOML file. value -> background configuration
# Format (value):
# 1. Youtube URI
# 2. filename
# 3. Citation (owner of the video)
# 4. Position of image clips in the background. See moviepy reference for more information. (https://zulko.github.io/moviepy/ref/VideoClip/VideoClip.html#moviepy.video.VideoClip.VideoClip.set_position)
background_options = {
"motor-gta": ( # Motor-GTA Racing
"https://www.youtube.com/watch?v=vw5L4xCPy9Q",
"bike-parkour-gta.mp4",
"Achy Gaming",
lambda t: ("center", 480 + t),
),
"rocket-league": ( # Rocket League
"https://www.youtube.com/watch?v=2X9QGY__0II",
"rocket_league.mp4",
"Orbital Gameplay",
lambda t: ("center", 200 + t),
),
"minecraft": ( # Minecraft parkour
"https://www.youtube.com/watch?v=n_Dv4JMiwK8",
"parkour.mp4",
"bbswitzer",
"center",
),
"gta": ( # GTA Stunt Race
"https://www.youtube.com/watch?v=qGa9kWREOnE",
"gta-stunt-race.mp4",
"Achy Gaming",
lambda t: ("center", 480 + t),
),
"csgo-surf": ( # CSGO Surf
"https://www.youtube.com/watch?v=E-8JlyO59Io",
"csgo-surf.mp4",
"Aki",
"center",
),
"cluster-truck": ( # Cluster Truck Gameplay
"https://www.youtube.com/watch?v=uVKxtdMgJVU",
"cluster_truck.mp4",
"No Copyright Gameplay",
lambda t: ("center", 480 + t),
),
}

@ -0,0 +1,38 @@
{
"motor-gta": [
"https://www.youtube.com/watch?v=vw5L4xCPy9Q",
"bike-parkour-gta.mp4",
"Achy Gaming",
480
],
"rocket-league": [
"https://www.youtube.com/watch?v=2X9QGY__0II",
"rocket_league.mp4",
"Orbital Gameplay",
200
],
"minecraft": [
"https://www.youtube.com/watch?v=n_Dv4JMiwK8",
"parkour.mp4",
"bbswitzer",
"center"
],
"gta": [
"https://www.youtube.com/watch?v=qGa9kWREOnE",
"gta-stunt-race.mp4",
"Achy Gaming",
480
],
"csgo-surf": [
"https://www.youtube.com/watch?v=E-8JlyO59Io",
"csgo-surf.mp4",
"Aki",
"center"
],
"cluster-truck": [
"https://www.youtube.com/watch?v=uVKxtdMgJVU",
"cluster_truck.mp4",
"No Copyright Gameplay",
480
]
}

@ -1,3 +1,4 @@
import json
import random import random
import re import re
from pathlib import Path from pathlib import Path
@ -8,11 +9,23 @@ from moviepy.editor import VideoFileClip
from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip
from pytube import YouTube from pytube import YouTube
from pytube.cli import on_progress from pytube.cli import on_progress
from utils import settings from utils import settings
from utils.CONSTANTS import background_options
from utils.console import print_step, print_substep from utils.console import print_step, print_substep
# Supported Background.
# (https://zulko.github.io/moviepy/ref/VideoClip/VideoClip.html#moviepy.video.VideoClip.VideoClip.set_position)
# Load background videos
with open("utils/backgrounds.json") as json_file:
background_options = json.load(json_file)
# Add position lambda function
for name in list(background_options.keys()):
pos = background_options[name][3]
if pos != "center":
background_options[name][3] = lambda t: ("center", pos + t)
def get_start_and_end_times(video_length: int, length_of_clip: int) -> Tuple[int, int]: def get_start_and_end_times(video_length: int, length_of_clip: int) -> Tuple[int, int]:
"""Generates a random interval of time to be used as the background of the video. """Generates a random interval of time to be used as the background of the video.

Loading…
Cancel
Save