]> git.gir.st - subscriptionfeed.git/blob - app/dangerous/__init__.py
add /results as alias for /search
[subscriptionfeed.git] / app / dangerous / __init__.py
1 # this is an alternative to proxying through invidious. the search endpoint has only been (loosely) tested by
2 #17:50 < perflyst[m]> appears to be working
3 #, so i hopeā„¢ this works. if not, that's why it's in the 'dangerous' blueprint
4 import requests
5 from flask import Blueprint, render_template, request, flash, g, url_for, redirect
6
7 from ..common.common import *
8 from ..common.innertube import *
9 from .lib import *
10 from .protobuf import make_sp, make_channel_params, make_playlist_params
11
12 frontend = Blueprint('dangerous', __name__,
13 template_folder='templates',
14 static_folder='static',
15 static_url_path='/static/ys')
16
17 @frontend.route('/results')
18 @frontend.route('/search')
19 def search():
20 #token = getattr(current_user, 'token', 'guest')
21 q = request.args.get('q') or request.args.get('search_query')
22 page = int(request.args.get('page', 1))
23
24 sp = make_sp(**{
25 k:v for k,v in request.args.items()
26 if k in ['sort','date','type','len']
27 }, extras=['dont_fix_spelling']*0) # extras disabled
28
29 if q:
30 yt_results = fetch_searchresults(q, page, sp)
31
32 results, extras = prepare_searchresults(yt_results)
33
34 for extra in extras:
35 flash(extra, 'info')
36 else:
37 results = None
38
39 return render_template('search.html.j2', rows=results, query=q, page=page)
40
41 # TODO: channels, playlists:
42 # https://github.com/iv-org/invidious/blob/452d1e8307d6344dd51c5437ccd032a566291c34/src/invidious/channels.cr#L399
43
44 @frontend.route('/channel/<channel_id>/')
45 @frontend.route('/channel/<channel_id>/<subpage>')
46 def channel(channel_id, subpage="videos"):
47 if subpage == "videos":
48 page = int(request.args.get('page', 1))
49 sort_by = request.args.get('sort', "newest")
50 query = None
51 elif subpage == "playlists":
52 page = None # TODO: cursor
53 sort_by = request.args.get('sort', "modified")
54 query = None
55 elif subpage == "search":
56 query = request.args.get('q')
57 page = int(request.args.get('page', 1))
58 sort_by = None
59 else: # we don't support /home, /about, ..., so redirect to /videos.
60 return redirect(url_for('.channel', channel_id=channel_id))
61
62 result = fetch_ajax(make_channel_params(channel_id, subpage, page, sort_by, query))
63
64 # Note: as of 2020-08-15, using the v1 format sometimes returns an error. if that's the case, try v2.
65 alert = listget(listget(result,1,{}).get('response',{}).get('alerts',[]),0,{}).get('alertRenderer',{})
66 if alert.get('type','') == "ERROR": # alert['text']['simpleText'] == "Unknown error."
67 result = fetch_ajax(make_channel_params(channel_id, subpage, page, sort_by, query, v2=True))
68
69 title, descr, thumb, rows, more = prepare_channel(result, channel_id)
70 # TODO: add is_pinned/is_hidden
71
72 if title is None: # if both v1 and v2 failed, fall back to xmlfeed:
73 flash("unable to fetch results from ajax; displaying fallback results (15 newest)", "error")
74 return fallback_route(channel_id, subpage)
75
76 return render_template('channel.html.j2',
77 title=title,
78 subpage=subpage,
79 rows=rows,
80 channel_id=channel_id,
81 channel_img=thumb,
82 channel_desc=descr,
83 page=page,
84 has_more=more)
85
86 @frontend.route('/user/<user>')
87 @frontend.route('/user/<user>/<subpage>')
88 @frontend.route('/c/<user>')
89 @frontend.route('/c/<user>/<subpage>')
90 def channel_redirect(user, subpage=None):
91 """
92 The browse_ajax 'API' needs the UCID. We can get that from the RSS feeds.
93 """
94 xmlfeed = fetch_xml("user", user)
95 _, _, _, channel_id, _ = parse_xml(xmlfeed)
96 return redirect(
97 url_for('.channel', channel_id=channel_id, subpage=subpage), 308
98 )
99
100 @frontend.route('/playlist')
101 def playlist():
102 #TODO: if anything goes wrong, fall back to xmlfeed
103 playlist_id = request.args.get('list')
104 if not playlist_id:
105 return "bad list id", 400 # todo
106 page = int(request.args.get('page', 1))
107
108 xmlfeed = fetch_xml("playlist_id", playlist_id)
109 if not xmlfeed:
110 return "not found or something", 404 # XXX
111 title, author, _, channel_id, _ = parse_xml(xmlfeed)
112
113 offset = (page-1)*100 # each call returns 100 items
114 result = fetch_ajax(make_playlist_params(playlist_id, offset))
115
116 rows, more = prepare_playlist(result)
117
118 return render_template('playlist.html.j2',
119 title=title,
120 author=author,
121 channel_id=channel_id,
122 rows=rows,
123 page=page,
124 has_more=more)
125
126 @frontend.before_app_request
127 def inject_button():
128 if not 'header_items' in g:
129 g.header_items = []
130 g.header_items.append({
131 'name': 'search',
132 'url': url_for('dangerous.search'),
133 'parent': frontend.name,
134 'priority': 15,
135 })
Imprint / Impressum