]> git.gir.st - subscriptionfeed.git/blob - app/invidious/__init__.py
better /<something> algorithm
[subscriptionfeed.git] / app / invidious / __init__.py
1 import requests
2 from flask import Blueprint, render_template, request, flash, g, url_for
3
4 from ..common.common import fallback_route
5
6 frontend = Blueprint('invidious', __name__,
7 template_folder='templates',
8 static_folder='static',
9 static_url_path='/static/iv')
10
11 # TODO: minimal implementation (invidio.us hardcoded, videos only, no optional_params)
12 @frontend.route('/search')
13 def search():
14 #token = getattr(current_user, 'token', 'guest')
15 q = request.args.get('q')
16 page = int(request.args.get('page', 1))
17 provider = request.args.get('provider', 'invidio.us:443')
18
19 """
20 sort_by: "relevance", "rating", "upload_date", "view_count"
21 date: "hour", "today", "week", "month", "year"
22 duration: "short", "long"
23 type: "video", "playlist", "channel", "all", (default: video)
24 features: "hd", "subtitles", "creative_commons", "3d", "live",
25 "purchased", "4k", "360", "location", "hdr" (comma separated)
26 region: ISO 3166 country code (default: "US")
27 """
28 optional_params = {
29 p: request.args.get(p)
30 for p in ['sort_by', 'date', 'duration', 'type', 'features', 'region']
31 }
32
33 if q:
34 r = requests.get(f"https://invidio.us/api/v1/search", {
35 'q': q,
36 'page': page,
37 # **optional_params,
38 })
39 if not r.ok:
40 return "error fetching search results", 502 # TODO: better
41 # XXX: should check r.json if it really are search results (if other provider)
42 # XXX: should transform invidious-json to our naming scheme
43 results = r.json()
44 else:
45 results = None
46
47 return render_template('search.html.j2', rows=results, query=q, page=page,
48 optional_params=optional_params)
49
50 @frontend.route('/channel/<channel_id>')
51 @frontend.route('/user/<channel_id>')
52 def channel(channel_id):
53 page = int(request.args.get('page', 1))
54 sort_by = request.args.get('sort_by', 'newest')
55 provider = request.args.get('provider', 'invidio.us:443')
56
57 r = requests.get(f"https://invidio.us/api/v1/channels/{channel_id}/videos", {
58 'sort_by': sort_by,
59 'page': page,
60 }, allow_redirects=False)
61 if not r.ok or r.status_code != 200:
62 flash("invidious did not find the channel or is blocked. showing minimal response", "error")
63 return fallback_route(channel_id)
64
65 return render_template('channel.html.j2', rows=r.json(), sort_by=sort_by, page=page)
66
67 @frontend.route('/playlist')
68 def playlist():
69 playlist_id = request.args.get('list')
70 if not playlist_id:
71 return "bad list id", 400 # todo
72
73 page = int(request.args.get('page', 1))
74 provider = request.args.get('provider', 'invidio.us:443')
75
76 r = requests.get(f"https://invidio.us/api/v1/playlists/{playlist_id}", {
77 'page': page,
78 }, allow_redirects=False)
79 if not r.ok or r.status_code != 200:
80 flash("invidious did not find the channel or is blocked. showing minimal response", "error")
81 return fallback_route()
82
83 return render_template('channel.html.j2', rows=r.json().get('videos',[]), page=page)
84
85 @frontend.before_app_request
86 def inject_search_button():
87 if not 'header_items' in g:
88 g.header_items = []
89 g.header_items.append({
90 'name': 'search',
91 'url': url_for('invidious.search'),
92 'parent': frontend.name,
93 'priority': 10,
94 })
Imprint / Impressum