]> git.gir.st - subscriptionfeed.git/blob - app/browse/lib.py
use resolve_url endpoint for channel canonicalisation
[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 # TODO: replace host with youtubei.googleapis.com (used by android)?
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(path):
32 if re.fullmatch(r"(UC[A-Za-z0-9_-]{22})", path):
33 return path
34
35 # Note: for /watch, append query string, then return .endpoint.watchEndpoint.videoId
36 resolved = fetch_ajax("navigation/resolve_url", url=f"https://www.youtube.com/{path}")
37 channel_id = resolved.get('endpoint',{}).get('browseEndpoint',{}).get('browseId')
38 return channel_id
39
40 def find_and_parse_error(result):
41 error_obj = (
42 result|G('responseContext')|G('errors')|G('error')|G(0)
43 or result|G('alerts')|G(0)|G('alertRenderer')
44 or result|G('error')
45 )
46 if error_obj is None:
47 return None
48
49 error_type = error_obj|G('code', 'type', 'status') or 'Error'
50 error = (
51 error_obj|G('debugInfo', 'externalErrorMessage')
52 or error_obj|G('text')|G.text
53 or error_obj|G('message')
54 or "unknown error"
55 )
56 return f"{error_type}: {error.rstrip('.')}"
Imprint / Impressum