-
-
Save rptb1/cba49b801825ef3fffe4698dd96e360e to your computer and use it in GitHub Desktop.
*~ |
# youtube-subs-to-opml.py -- Convert YouTube subscriptions exported | |
# via Google Takeout into OPML | |
# | |
# See <https://www.reddit.com/r/youtube/comments/jqlks2/where_did_opml_export_go/gcdii2n/>. | |
# | |
# Usage: | |
# python3 youtube-subs-to-opml.py < ~/Downloads/Takeout/YouTube\ and\ YouTube\ Music/subscriptions/subscriptions.json > yt-subs.opml | |
import sys | |
import json | |
from xml.sax.saxutils import escape | |
subs = json.load(sys.stdin) | |
if len(subs) > 0: | |
parent = escape(subs[0]['snippet']['channelId']) | |
print(f'''<?xml version="1.0" encoding="UTF-8"?> | |
<opml version="1.0"> | |
<body> | |
<outline title="YouTube {parent}" text="YouTube {parent}"> | |
''') | |
for sub in subs: | |
title = escape(sub['snippet']['title']) | |
channelId = escape(sub['snippet']['resourceId']['channelId']) | |
print(f''' <outline title="{title}" | |
text="{title}" | |
xmlUrl="https://www.youtube.com/feeds/videos.xml?channel_id={channelId}" | |
htmlUrl="https://www.youtube.com/channel/{channelId}" /> | |
''') | |
print(''' | |
</outline> | |
</body> | |
</opml> | |
''') | |
# Open source under BSD-2-Clause | |
# <https://opensource.org/licenses/BSD-2-Clause> | |
# | |
# Copyright 2021 Richard Brooksby <rptb1> | |
# | |
# Redistribution and use in source and binary forms, with or without | |
# modification, are permitted provided that the following conditions | |
# are met: | |
# | |
# 1. Redistributions of source code must retain the above copyright | |
# notice, this list of conditions and the following disclaimer. | |
# | |
# 2. Redistributions in binary form must reproduce the above copyright | |
# notice, this list of conditions and the following disclaimer in | |
# the documentation and/or other materials provided with the | |
# distribution. | |
# | |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
# POSSIBILITY OF SUCH DAMAGE. |
Pretty useful, thanks a lot. Although I had to manually add a
</opml>
after the</body>
before feedly would accept the file as valid OPML
Oops! I think my reader didn't care, so I didn't notice this. Fixed. Thanks.
Hello i'm pretty new to python, i'm trying to run your .py file.
I checked python is running well, I also put the json file in the correct place as you noted above. I used cmd to run the python but it has no feedback/return.
Is there any way to know if it's running correctly? Or perhaps my json file is a little big and it will take some time?
Please help because youtube subscription really messed up now, Thank you in advanced.
Since the last time I used this, YouTube changed the subscription list to csv instead of json. I created a fork here to support both json and csv
Pretty useful, thanks a lot. Although I had to manually add a
</opml>
after the</body>
before feedly would accept the file as valid OPML