Add subscriptions export
plus design by heckyel
This commit is contained in:
parent
f9d1bfe05f
commit
7feea3f839
@ -227,7 +227,8 @@ hr {
|
|||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"subscriptions-import-form";
|
"subscriptions-import-form"
|
||||||
|
"subscriptions-export-form";
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-items: center;
|
justify-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@ -237,12 +238,30 @@ hr {
|
|||||||
text-align: center;
|
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 {
|
.sub-list-controls {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-row-gap: 0.2rem;
|
grid-row-gap: 0.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.subscriptions-import-form input[type='submit'],
|
.subscriptions-import-form input[type='submit'],
|
||||||
|
.subscriptions-export-form input[type='submit'],
|
||||||
.sub-list-controls button[type='submit'],
|
.sub-list-controls button[type='submit'],
|
||||||
.sub-list-controls input[type='reset'] {
|
.sub-list-controls input[type='reset'] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -323,6 +342,24 @@ hr {
|
|||||||
.title {
|
.title {
|
||||||
font-size: 1rem;
|
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) {
|
@media (min-width: 600px) {
|
||||||
|
@ -732,6 +732,50 @@ def import_subscriptions():
|
|||||||
return flask.redirect(util.URL_ORIGIN + '/subscription_manager', 303)
|
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'])
|
@yt_app.route('/subscription_manager', methods=['GET'])
|
||||||
def get_subscription_manager_page():
|
def get_subscription_manager_page():
|
||||||
group_by_tags = request.args.get('group_by_tags', '0') == '1'
|
group_by_tags = request.args.get('group_by_tags', '0') == '1'
|
||||||
|
@ -19,14 +19,24 @@
|
|||||||
<div class="import-export">
|
<div class="import-export">
|
||||||
<form class="subscriptions-import-form" enctype="multipart/form-data" action="/youtube.com/import_subscriptions" method="POST">
|
<form class="subscriptions-import-form" enctype="multipart/form-data" action="/youtube.com/import_subscriptions" method="POST">
|
||||||
<h2>Import subscriptions</h2>
|
<h2>Import subscriptions</h2>
|
||||||
<input type="file" id="subscriptions-import" accept="application/json, application/xml, text/x-opml" name="subscriptions_file">
|
<div class="subscriptions-import-options">
|
||||||
<input type="submit" value="Import" class="import-submit-button">
|
<input type="file" id="subscriptions-import" accept="application/json, application/xml, text/x-opml" name="subscriptions_file">
|
||||||
|
<input type="submit" value="Import">
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<!--<ul class="subscriptions-export-links">
|
<form class="subscriptions-export-form" action="/youtube.com/export_subscriptions" method="POST">
|
||||||
<li><a href="/youtube.com/subscriptions.opml">Export subscriptions (OPML)</a></li>
|
<h2>Export subscriptions</h2>
|
||||||
<li><a href="/youtube.com/subscriptions.xml">Export subscriptions (RSS)</a></li>
|
<div class="subscriptions-export-options">
|
||||||
</ul>-->
|
<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>
|
</div>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
9
youtube/templates/subscriptions.xml
Normal file
9
youtube/templates/subscriptions.xml
Normal 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>
|
Loading…
x
Reference in New Issue
Block a user