diff options
Diffstat (limited to 'youtube')
-rw-r--r-- | youtube/static/subscription_manager.css | 39 | ||||
-rw-r--r-- | youtube/subscriptions.py | 44 | ||||
-rw-r--r-- | youtube/templates/subscription_manager.html | 22 | ||||
-rw-r--r-- | youtube/templates/subscriptions.xml | 9 |
4 files changed, 107 insertions, 7 deletions
diff --git a/youtube/static/subscription_manager.css b/youtube/static/subscription_manager.css index 1e260d8..7ddd90e 100644 --- a/youtube/static/subscription_manager.css +++ b/youtube/static/subscription_manager.css @@ -227,7 +227,8 @@ hr { grid-template-columns: 1fr; margin: auto; grid-template-areas: - "subscriptions-import-form"; + "subscriptions-import-form" + "subscriptions-export-form"; align-items: center; justify-items: center; justify-content: center; @@ -237,12 +238,30 @@ hr { text-align: center; } +.subscriptions-import-options { + display: grid; + grid-template-columns: repeat(1, auto); + margin: auto; +} + +.subscriptions-export-form { + grid-area: subscriptions-export-form; + text-align: center; +} + +.subscriptions-export-options { + display: grid; + grid-template-columns: repeat(1, auto); + margin: auto; +} + .sub-list-controls { display: grid; grid-row-gap: 0.2rem; } .subscriptions-import-form input[type='submit'], +.subscriptions-export-form input[type='submit'], .sub-list-controls button[type='submit'], .sub-list-controls input[type='reset'] { cursor: pointer; @@ -323,6 +342,24 @@ hr { .title { font-size: 1rem; } + .subscriptions-import-options { + display: grid; + grid-template-columns: repeat(2, auto); + margin: auto; + align-items: center; + justify-items: center; + justify-content: center; + grid-column-gap: 0.5rem; + } + .subscriptions-export-options { + display: grid; + grid-template-columns: repeat(4, auto); + margin: auto; + align-items: center; + justify-items: center; + justify-content: center; + grid-column-gap: 0.5rem; + } } @media (min-width: 600px) { diff --git a/youtube/subscriptions.py b/youtube/subscriptions.py index c18f822..f540e35 100644 --- a/youtube/subscriptions.py +++ b/youtube/subscriptions.py @@ -732,6 +732,50 @@ def import_subscriptions(): return flask.redirect(util.URL_ORIGIN + '/subscription_manager', 303) +@yt_app.route('/export_subscriptions', methods=['POST']) +def export_subscriptions(): + include_muted = request.values.get('include_muted') == 'on' + with open_database() as connection: + with connection as cursor: + sub_list = [] + for channel_name, channel_id, muted in ( + _get_subscribed_channels(cursor)): + if muted and not include_muted: + continue + if request.values['export_format'] == 'json': + sub_list.append({ + 'kind': 'youtube#subscription', + 'snippet': { + 'muted': bool(muted), + 'resourceId': { + 'channelId': channel_id, + 'kind': 'youtube#channel', + }, + 'tags': _get_tags(cursor, channel_id), + 'title': channel_name, + }, + }) + elif request.values['export_format'] == 'opml': + sub_list.append({ + 'channel_name': channel_name, + 'channel_id': channel_id, + }) + if request.values['export_format'] == 'json': + r = flask.Response(json.dumps(sub_list), mimetype='text/json') + cd = 'attachment; filename="subscriptions.json"' + r.headers['Content-Disposition'] = cd + return r + elif request.values['export_format'] == 'opml': + r = flask.Response( + flask.render_template('subscriptions.xml', sub_list=sub_list), + mimetype='text/xml') + cd = 'attachment; filename="subscriptions.xml"' + r.headers['Content-Disposition'] = cd + return r + else: + return '400 Bad Request', 400 + + @yt_app.route('/subscription_manager', methods=['GET']) def get_subscription_manager_page(): group_by_tags = request.args.get('group_by_tags', '0') == '1' diff --git a/youtube/templates/subscription_manager.html b/youtube/templates/subscription_manager.html index 92cd024..62a8bed 100644 --- a/youtube/templates/subscription_manager.html +++ b/youtube/templates/subscription_manager.html @@ -19,14 +19,24 @@ <div class="import-export"> <form class="subscriptions-import-form" enctype="multipart/form-data" action="/youtube.com/import_subscriptions" method="POST"> <h2>Import subscriptions</h2> - <input type="file" id="subscriptions-import" accept="application/json, application/xml, text/x-opml" name="subscriptions_file"> - <input type="submit" value="Import" class="import-submit-button"> + <div class="subscriptions-import-options"> + <input type="file" id="subscriptions-import" accept="application/json, application/xml, text/x-opml" name="subscriptions_file"> + <input type="submit" value="Import"> + </div> </form> - <!--<ul class="subscriptions-export-links"> - <li><a href="/youtube.com/subscriptions.opml">Export subscriptions (OPML)</a></li> - <li><a href="/youtube.com/subscriptions.xml">Export subscriptions (RSS)</a></li> - </ul>--> + <form class="subscriptions-export-form" action="/youtube.com/export_subscriptions" method="POST"> + <h2>Export subscriptions</h2> + <div class="subscriptions-export-options"> + <select id="export-type" name="export_format" title="Export format"> + <option value="json">JSON</option> + <option value="opml">OPML (RSS, no tags)</option> + </select> + <label for="include-muted">Include muted</label> + <input id="include-muted" type="checkbox" name="include_muted" checked> + <input type="submit" value="Export"> + </div> + </form> </div> <hr> diff --git a/youtube/templates/subscriptions.xml b/youtube/templates/subscriptions.xml new file mode 100644 index 0000000..5365da1 --- /dev/null +++ b/youtube/templates/subscriptions.xml @@ -0,0 +1,9 @@ +<opml version="1.1"> + <body> + <outline text="YouTube Subscriptions" title="YouTube Subscriptions"> + {% for sub in sub_list %} + <outline text="{{sub['channel_name']}}" title="{{sub['channel_name']}}" type="rss" xmlUrl="https://www.youtube.com/feeds/videos.xml?channel_id={{sub['channel_id']}}" /> + {%- endfor %} + </outline> + </body> +</opml> |