From 683e03c68dd43d55d4c36a136947c61e09755771 Mon Sep 17 00:00:00 2001 From: dechert Date: Fri, 20 Jan 2023 19:13:17 +0100 Subject: [PATCH] basic code to generate podcast feed. Add buttons to generate and open feed. Validate input URLs --- README.md | 4 ++- requirements.txt | 2 ++ rest_server.py | 48 ++++++++++++++++++++++++++++-------- templates/index.html | 8 ------ templates/yt.html | 13 ++++++++-- yt2podcast/feed_generator.py | 33 +++++++++++++++++++++++++ yt2podcast/ytdl_handler.py | 3 ++- 7 files changed, 89 insertions(+), 22 deletions(-) delete mode 100644 templates/index.html create mode 100644 yt2podcast/feed_generator.py diff --git a/README.md b/README.md index 705f046..d1e9973 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,9 @@ ### Use Python Library to generate RSS Feed https://github.com/lkiesow/python-feedgen - Serve xml file via same Flask app? - +2 buttons: + - Copy podcast link to clipboard + - open podcast.xml admin test123 diff --git a/requirements.txt b/requirements.txt index 46cfccd..ccc9b01 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,3 +12,5 @@ Werkzeug==2.0.0 jinja2==3.0.3 requests==2.28.2 PyYAML==6.0 +feedgen==0.9.0 +validators==0.20.0 diff --git a/rest_server.py b/rest_server.py index 192f307..c817e72 100644 --- a/rest_server.py +++ b/rest_server.py @@ -1,7 +1,7 @@ import os import flask -from flask import render_template +from flask import render_template, send_from_directory, redirect from flask import request from flask import url_for from flask_cors import CORS @@ -13,6 +13,7 @@ from werkzeug.security import check_password_hash import config_parser # from yt2podcast.ytdownloader import call_youtubedl from yt2podcast.ytdl_handler import call_youtubedl +from yt2podcast.feed_generator import generate_feed_for_yt_file app = flask.Flask(__name__) auth = HTTPBasicAuth() @@ -30,23 +31,50 @@ def verify_password(username, password): return username -@app.route(URL_BASE_PATH + 'home', methods=['GET']) -# @auth.login_required -def api_show_form(): - return render_template("index.html") - - @app.route(URL_BASE_PATH, methods=['POST', 'GET']) @auth.login_required def handle_yt_url(): if request.method == "POST": + if request.form.get('generate-feed') == 'generate-feed': + generate_feed_for_yt_file() + return render_template("yt.html", isValidUrl=True) + + # if request.form.get('open-podcast') == 'open-podcast': + # return redirect(url_for('serve_static'), path='podcast.xml') + # return url_for('static', filename='podcast.xml') + # from flask import Response + # xml = 'foo' + # resp = app.make_response(xml) + # resp.mimetype = "text/xml" + # return resp + # r = Response(response='./feed/podcast.xml', status=200, mimetype="application/xml") + # r.headers["Content-Type"] = "text/xml; charset=utf-8" + # return r + # return app.send_static_file('./feed/podcast.xml') + user_input = request.form['ytlink'] # return redirect(url_for("return_result", ytlink=user_input)) print(user_input) - call_youtubedl(user_input) - return render_template("yt.html") + # TODO verify its a url + import validators + + is_valid_url=validators.url(user_input) + if is_valid_url: + call_youtubedl(user_input) + + + return render_template("yt.html", isValidUrl=is_valid_url) else: - return render_template("yt.html") + return render_template("yt.html", isValidUrl=True) + + +# @app.route(URL_BASE_PATH + 'podcast', methods=['GET']) +# def serve_podcast_xml(): +# return app.send_static_file('podcast.xml') + +@app.route('/static/') +def serve_static(path): + return send_from_directory('static', path) if __name__ == '__main__': diff --git a/templates/index.html b/templates/index.html deleted file mode 100644 index bd8eec3..0000000 --- a/templates/index.html +++ /dev/null @@ -1,8 +0,0 @@ -{% extends "base.html" %} -{% block content %} Home Page {% endblock %} - - - - - - diff --git a/templates/yt.html b/templates/yt.html index 9e94838..0adae5b 100644 --- a/templates/yt.html +++ b/templates/yt.html @@ -4,10 +4,19 @@ {% block content %} -

Input youtube URL

+

Input youtube URL:

-

+

+{% if not isValidUrl %} + +{% endif %}

+ +{##} +{#Open Podcast Feed#} +Open Podcast Feed + +{##}
{% endblock %} diff --git a/yt2podcast/feed_generator.py b/yt2podcast/feed_generator.py new file mode 100644 index 0000000..7296e13 --- /dev/null +++ b/yt2podcast/feed_generator.py @@ -0,0 +1,33 @@ +from feedgen.feed import FeedGenerator + +def generate_feed_for_yt_file(): + + print("generating podcast feed...") + fg = FeedGenerator() + fg.id('http://lernfunk.de/media/654321') + fg.title('Some Testfeed') + fg.author( {'name':'John Doe','email':'john@example.de'} ) + fg.link( href='http://example.com', rel='alternate' ) + fg.logo('http://ex.com/logo.jpg') + fg.subtitle('This is a cool feed!') + fg.link( href='http://larskiesow.de/test.atom', rel='self' ) + fg.language('en') + + add_entry(fg) + +def add_entry(fg): + from feedgen.feed import FeedGenerator + # fg = FeedGenerator() + fg.load_extension('podcast') + # fg.podcast.itunes_category('Technology', 'Podcasting') + + fe = fg.add_entry() + fe.id('http://lernfunk.de/media/654321/1/file.mp3') + fe.title('The First Episode') + fe.description('Enjoy our first episode.') + fe.enclosure('http://lernfunk.de/media/654321/1/file.mp3', 0, 'audio/mpeg') + + fg.rss_str(pretty=True) + print("generating xml file...") + fg.rss_file('podcast.xml') + fg.rss_file('./feed/podcast.xml') diff --git a/yt2podcast/ytdl_handler.py b/yt2podcast/ytdl_handler.py index 7120ccd..91eb5ab 100644 --- a/yt2podcast/ytdl_handler.py +++ b/yt2podcast/ytdl_handler.py @@ -9,7 +9,7 @@ def call_youtubedl(url): print(url) download_audio(url) # thread = Thread(args=(, )) - thread = threading.Thread(target=download_audio, args=(url, "first_test"), daemon=True) + thread = threading.Thread(target=download_audio, args=(url,), daemon=True) thread.start() thread.join() @@ -20,6 +20,7 @@ def call_youtubedl(url): # print("thread finished...exiting") def download_audio(url): + # based on https://www.programcreek.com/python/?code=DuckBoss%2FJJMumbleBot%2FJJMumbleBot-master%2FJJMumbleBot%2Fplugins%2Fextensions%2Fsound_board%2Futility%2Fsound_board_utility.py ydl_opts = { 'format': 'bestaudio/best', 'outtmpl': f'/output/%(title)s.mp3', # Template for output names. Needed to change the file extension