From 2d417fb3bbd155583179d2ad172e1b3c1f5e9eaf Mon Sep 17 00:00:00 2001 From: girst Date: Sun, 18 Oct 2020 01:13:41 +0200 Subject: [PATCH] better / algorithm note: using strict_slashes=False instread of two route decorators to avoid useless redirect. --- app/youtube/__init__.py | 19 +++++++++++-------- app/youtube/lib.py | 8 ++++++++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/app/youtube/__init__.py b/app/youtube/__init__.py index 4421cff..899c35c 100644 --- a/app/youtube/__init__.py +++ b/app/youtube/__init__.py @@ -6,6 +6,7 @@ from urllib.parse import urlparse #from flask_login import current_user, login_required from flask_login import LoginManager, UserMixin, current_user, login_user, logout_user, login_required from flask import Blueprint, render_template, request, redirect, flash, url_for, jsonify, g +from werkzeug.exceptions import NotFound from ..common.common import * from .lib import * @@ -149,16 +150,18 @@ def watch(): def embed(video_id): return redirect(url_for('.watch', v=video_id, t=request.args.get('start'))) -@frontend.route('/') -@frontend.route('//') +@frontend.route('/', strict_slashes=False) def plain_user_or_video(something): - # yt.com redirects those to channels, but we also want to catch invidious - # short-urls. a "just-a-variable-endpoint" has lowest priority, so this - # shouldn't interfere with anything. - if re.match(r"^[-_0-9A-Za-z]{11}$", something): # looks like a video id - return redirect(url_for('.watch', v=something, t=request.args.get('t'))) - else: # maybe a channel/user name? + # yt.com interprets this as a username, but we also want to catch youtu.be + # short-urls. so we check if it's a channel by querying the RSS feed (this + # shoudn't be rate-limited); if that fails, check if it looks like a video + # id; or finally give up. + if channel_exists(something): return redirect(url_for('.channel', channel_id=something)) + elif re.match(r"^[-_0-9A-Za-z]{11}$", something): # looks like a video id + return redirect(url_for('.watch', v=something, t=request.args.get('t'))) + else: # ¯\_(ツ)_/¯ + raise NotFound @frontend.route('/channel//') @frontend.route('/user//') diff --git a/app/youtube/lib.py b/app/youtube/lib.py index d49c38b..9bc23ca 100644 --- a/app/youtube/lib.py +++ b/app/youtube/lib.py @@ -1,3 +1,5 @@ +import re +import requests from urllib.parse import urlparse from ..common.common import video_metadata @@ -92,3 +94,9 @@ def prepare_metadata(metadata): 'subtitles': subtitles, } +def channel_exists(feed_id): + feed_type = "channel_id" if re.match(r"^UC[A-Za-z0-9_-]{22}$", feed_id) else "user" + r = requests.head("https://www.youtube.com/feeds/videos.xml", params={ + feed_type: feed_id, + }) + return r.ok -- 2.39.3