107 lines
2.9 KiB
Python
107 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
|
|
|
"""
|
|
YouTube-RSS is a simple script to build RSS feeds from YouTube links.
|
|
You can pass links to channels, play-lists or even user pages.
|
|
The script is modular, so any new entity could be added easily.
|
|
"""
|
|
|
|
|
|
import argparse
|
|
import sys
|
|
|
|
from urllib.error import HTTPError
|
|
from urllib.request import Request, urlopen
|
|
from urllib.parse import parse_qs, urlparse, urlencode
|
|
|
|
|
|
# YouTube has only one URL to generate RSS feeds.
|
|
# GET parameters will change the output accordingly.
|
|
RSS_FEEDS_BASE_URL = r"https://www.youtube.com/feeds/videos.xml"
|
|
|
|
|
|
def get_feed(entity, token):
|
|
"""Returns a well-formatted RSS feed URL based on the constant above"""
|
|
return "{0}?{1}".format(
|
|
RSS_FEEDS_BASE_URL,
|
|
urlencode({entity: token}) # Parameters should already be URL-encoded, but who knows ?
|
|
)
|
|
|
|
|
|
def process_link(i, link):
|
|
"""Main logic, parse and analyze the link and compute RSS feed"""
|
|
|
|
# Parse the passed link.
|
|
parsing = urlparse(link)
|
|
|
|
# Parse the GET parameters (if any).
|
|
get_params = parse_qs(parsing.query)
|
|
|
|
# Check that the provided link belongs to YouTube.
|
|
if not parsing.netloc.endswith('youtube.com') and \
|
|
not parsing.netloc.endswith('youtu.be'):
|
|
print(
|
|
"[{0}] The provided link is not a YouTube link. Skipping.".format(i),
|
|
file=sys.stderr
|
|
)
|
|
return
|
|
|
|
# Starts URL pattern matching.
|
|
if parsing.path.startswith('/user/'):
|
|
rss_feed = get_feed('user', parsing.path.split('/')[2])
|
|
|
|
elif parsing.path.startswith('/channel/'):
|
|
rss_feed = get_feed('channel_id', parsing.path.split('/')[2])
|
|
|
|
elif 'list' in get_params:
|
|
rss_feed = get_feed('playlist_id', get_params.get('list')[0])
|
|
|
|
else:
|
|
print(
|
|
"[{0}] The provided link has an unknown format. Skipping.".format(i),
|
|
file=sys.stderr
|
|
)
|
|
return
|
|
|
|
# Let's verify that the built RSS feed is valid upstream.
|
|
try:
|
|
_ = urlopen(Request(rss_feed, method='HEAD'))
|
|
print("[{0}] <{1}>".format(i, rss_feed))
|
|
|
|
except HTTPError as error:
|
|
print(
|
|
"[{0}] No responding RSS feed could be retrieved ({1}).".format(
|
|
i,
|
|
error.code
|
|
),
|
|
file=sys.stderr
|
|
)
|
|
|
|
|
|
def main():
|
|
"""Simple entry point"""
|
|
parser = argparse.ArgumentParser(
|
|
description="A simple RSS feeds generation for YouTube entities",
|
|
prog="YouTube-RSS"
|
|
)
|
|
parser.add_argument(
|
|
'links',
|
|
type=str,
|
|
nargs='+',
|
|
help="YouTube link(s) to convert to RSS feed(s)"
|
|
)
|
|
parser.add_argument(
|
|
'--version',
|
|
action='version', version="%(prog)s : 1.0"
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
|
|
# Iterate over passed links and process them.
|
|
for i, link in enumerate(args.links):
|
|
process_link(i, link)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|