Add subscriptions export

plus design by heckyel
This commit is contained in:
Jesús 2021-05-06 15:18:19 -05:00
parent f9d1bfe05f
commit 7feea3f839
No known key found for this signature in database
GPG Key ID: F6EE7BC59A315766
4 changed files with 107 additions and 7 deletions

View File

@ -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) {

View File

@ -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'

View File

@ -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>

View File

@ -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>