]> git.gir.st - subscriptionfeed.git/blob - app/browse/lib.py
hackily implement @usernames
[subscriptionfeed.git] / app / browse / lib.py
1 import re
2 import requests
3 from datetime import datetime, timezone
4
5 from ..common.innertube import G
6
7 def fetch_ajax(endpoint, **kwargs):
8 """
9 fetch data using a continuation protobuf
10 """
11 # TODO: handle auto_generated!
12 today = datetime.now(timezone.utc).strftime("%Y%m%d")
13
14 # TODO: this is not cached any more! -> https://github.com/reclosedev/requests-cache/issues/154
15 # Note: this 'innertube' API key exists since at least 2015: https://stackoverflow.com/q/33511165
16 r = requests.post(f"https://www.youtube.com/youtubei/v1/{endpoint}?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8", json={
17 **kwargs,
18 'context': {'client': {
19 'gl': 'US',
20 'hl': 'en',
21 'clientName': 'WEB',
22 'clientVersion': f'2.{today}.01.01',
23 }},
24 })
25
26 if not r.ok:
27 return None
28
29 return r.json()
30
31 def canonicalize_channel(name, typ="c"):
32 if re.fullmatch(r"(UC[A-Za-z0-9_-]{22})", name):
33 return name
34
35 # get UCID of /c/ (vanity URLs):
36 today = datetime.now(timezone.utc).strftime("%Y%m%d")
37 typ += "/" if typ != "@" else ""
38 r = requests.get(f'https://www.youtube.com/{typ}{name}/about?pbj=1&hl=en_US', headers={
39 'x-youtube-client-name': '1',
40 'x-youtube-client-version': f'2.{today}.01.01', # see fetch_searchresults()
41 })
42 try:
43 return r.json()[1]['response']['metadata']['channelMetadataRenderer']['rssUrl'].split("=")[1]
44 except:
45 pass
46
47 # unable to extract:
48 return None
49
50 def find_and_parse_error(result):
51 error_obj = (
52 result|G('responseContext')|G('errors')|G('error')|G(0)
53 or result|G('alerts')|G(0)|G('alertRenderer')
54 or result|G('error')
55 )
56 if error_obj is None:
57 return None
58
59 error_type = error_obj|G('code', 'type', 'status') or 'Error'
60 error = (
61 error_obj|G('debugInfo', 'externalErrorMessage')
62 or error_obj|G('text')|G.text
63 or error_obj|G('message')
64 or "unknown error"
65 )
66 return f"{error_type}: {error.rstrip('.')}"
Imprint / Impressum