Skip to content

Commit

Permalink
Add NewPipe subscriptions import and export
Browse files Browse the repository at this point in the history
Closes #82
  • Loading branch information
user234683 committed Sep 2, 2021
1 parent 03e2f74 commit 807c589
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 12 deletions.
57 changes: 47 additions & 10 deletions youtube/subscriptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ def check_specific_channels(channel_ids):
check_channels_if_necessary(channel_ids)



CHANNEL_ID_RE = re.compile(r'UC[-_\w]{22}')
@yt_app.route('/import_subscriptions', methods=['POST'])
def import_subscriptions():

Expand All @@ -681,15 +681,36 @@ def import_subscriptions():
mime_type = file.mimetype

if mime_type == 'application/json':
file = file.read().decode('utf-8')
info = file.read().decode('utf-8')
if info == '':
return '400 Bad Request: File is empty', 400
try:
file = json.loads(file)
info = json.loads(info)
except json.decoder.JSONDecodeError:
traceback.print_exc()
return '400 Bad Request: Invalid json file', 400

channels = []
try:
channels = ( (item['snippet']['resourceId']['channelId'], item['snippet']['title']) for item in file)
if 'app_version_int' in info: # NewPipe Format
for item in info['subscriptions']:
# Other service, such as SoundCloud
if item.get('service_id', 0) != 0:
continue
channel_url = item['url']
channel_id_match = CHANNEL_ID_RE.search(channel_url)
if channel_id_match:
channel_id = channel_id_match.group(0)
else:
print('WARNING: Could not find channel id in url',
channel_url)
continue
channels.append((channel_id, item['name']))
else: # Old Google Takeout format
for item in info:
snippet = item['snippet']
channel_id = snippet['resourceId']['channelId']
channels.append((channel_id, snippet['title']))
except (KeyError, IndexError):
traceback.print_exc()
return '400 Bad Request: Unknown json structure', 400
Expand Down Expand Up @@ -718,8 +739,7 @@ def import_subscriptions():
for row in reader:
if not row or row[0].lower().strip() == 'channel id':
continue
elif len(row) > 1 and re.fullmatch(r'UC[-_\w]{22}',
row[0].strip()):
elif len(row) > 1 and CHANNEL_ID_RE.fullmatch(row[0].strip()):
channels.append( (row[0], row[-1]) )
else:
print('WARNING: Unknown row format:', row)
Expand Down Expand Up @@ -747,7 +767,7 @@ def export_subscriptions():
_get_subscribed_channels(cursor)):
if muted and not include_muted:
continue
if request.values['export_format'] == 'json':
if request.values['export_format'] == 'json_google_takeout':
sub_list.append({
'kind': 'youtube#subscription',
'snippet': {
Expand All @@ -760,21 +780,38 @@ def export_subscriptions():
'title': channel_name,
},
})
elif request.values['export_format'] == 'json_newpipe':
sub_list.append({
'service_id': 0,
'url': 'https://www.youtube.com/channel/' + channel_id,
'name': 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':
date_time = time.strftime('%Y%m%d%H%M', time.localtime())
if request.values['export_format'] == 'json_google_takeout':
r = flask.Response(json.dumps(sub_list), mimetype='text/json')
cd = 'attachment; filename="subscriptions.json"'
cd = 'attachment; filename="subscriptions_%s.json"' % date_time
r.headers['Content-Disposition'] = cd
return r
elif request.values['export_format'] == 'json_newpipe':
r = flask.Response(json.dumps({
'app_version': '0.21.9',
'app_version_int': 975,
'subscriptions': sub_list,
}), mimetype='text/json')
file_name = 'newpipe_subscriptions_%s_youtube-local.json' % date_time
cd = 'attachment; filename="%s"' % file_name
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"'
cd = 'attachment; filename="subscriptions_%s.xml"' % date_time
r.headers['Content-Disposition'] = cd
return r
else:
Expand Down
5 changes: 3 additions & 2 deletions youtube/templates/subscription_manager.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
display: flex;
flex-direction: column;
align-items: flex-start;
max-width: 400px;
max-width: 600px;
padding:10px;
margin-left: 10px;
margin-bottom: 10px;
Expand Down Expand Up @@ -111,7 +111,8 @@ <h2>Import subscriptions</h2>
<h2>Export subscriptions</h2>
<div>
<select id="export-type" name="export_format" title="Export format">
<option value="json">JSON</option>
<option value="json_newpipe">JSON (NewPipe)</option>
<option value="json_google_takeout">JSON (Old Google Takeout Format)</option>
<option value="opml">OPML (RSS, no tags)</option>
</select>
<label for="include-muted">Include muted</label>
Expand Down

0 comments on commit 807c589

Please sign in to comment.