]> jfr.im git - yt-dlp.git/blob - youtube_dlc/extractor/lbry.py
Update to release 2020.11.24 except youtube and skyit extractors
[yt-dlp.git] / youtube_dlc / extractor / lbry.py
1 # coding: utf-8
2 from __future__ import unicode_literals
3
4 import json
5
6 from .common import InfoExtractor
7 from ..compat import compat_str
8 from ..utils import (
9 determine_ext,
10 ExtractorError,
11 int_or_none,
12 mimetype2ext,
13 try_get,
14 )
15
16
17 class LBRYIE(InfoExtractor):
18 IE_NAME = 'lbry.tv'
19 _VALID_URL = r'https?://(?:www\.)?(?:lbry\.tv|odysee\.com)/(?P<id>@[^:]+:[0-9a-z]+/[^:]+:[0-9a-z])'
20 _TESTS = [{
21 # Video
22 'url': 'https://lbry.tv/@Mantega:1/First-day-LBRY:1',
23 'md5': '65bd7ec1f6744ada55da8e4c48a2edf9',
24 'info_dict': {
25 'id': '17f983b61f53091fb8ea58a9c56804e4ff8cff4d',
26 'ext': 'mp4',
27 'title': 'First day in LBRY? Start HERE!',
28 'description': 'md5:f6cb5c704b332d37f5119313c2c98f51',
29 'timestamp': 1595694354,
30 'upload_date': '20200725',
31 }
32 }, {
33 # Audio
34 'url': 'https://lbry.tv/@LBRYFoundation:0/Episode-1:e',
35 'md5': 'c94017d3eba9b49ce085a8fad6b98d00',
36 'info_dict': {
37 'id': 'e7d93d772bd87e2b62d5ab993c1c3ced86ebb396',
38 'ext': 'mp3',
39 'title': 'The LBRY Foundation Community Podcast Episode 1 - Introduction, Streaming on LBRY, Transcoding',
40 'description': 'md5:661ac4f1db09f31728931d7b88807a61',
41 'timestamp': 1591312601,
42 'upload_date': '20200604',
43 }
44 }, {
45 'url': 'https://odysee.com/@BrodieRobertson:5/apple-is-tracking-everything-you-do-on:e',
46 'only_matching': True,
47 }, {
48 'url': "https://odysee.com/@ScammerRevolts:b0/I-SYSKEY'D-THE-SAME-SCAMMERS-3-TIMES!:b",
49 'only_matching': True,
50 }]
51
52 def _call_api_proxy(self, method, display_id, params):
53 return self._download_json(
54 'https://api.lbry.tv/api/v1/proxy', display_id,
55 headers={'Content-Type': 'application/json-rpc'},
56 data=json.dumps({
57 'method': method,
58 'params': params,
59 }).encode())['result']
60
61 def _real_extract(self, url):
62 display_id = self._match_id(url).replace(':', '#')
63 uri = 'lbry://' + display_id
64 result = self._call_api_proxy(
65 'resolve', display_id, {'urls': [uri]})[uri]
66 result_value = result['value']
67 if result_value.get('stream_type') not in ('video', 'audio'):
68 raise ExtractorError('Unsupported URL', expected=True)
69 streaming_url = self._call_api_proxy(
70 'get', display_id, {'uri': uri})['streaming_url']
71 source = result_value.get('source') or {}
72 media = result_value.get('video') or result_value.get('audio') or {}
73 signing_channel = result_value.get('signing_channel') or {}
74
75 return {
76 'id': result['claim_id'],
77 'title': result_value['title'],
78 'thumbnail': try_get(result_value, lambda x: x['thumbnail']['url'], compat_str),
79 'description': result_value.get('description'),
80 'license': result_value.get('license'),
81 'timestamp': int_or_none(result.get('timestamp')),
82 'tags': result_value.get('tags'),
83 'width': int_or_none(media.get('width')),
84 'height': int_or_none(media.get('height')),
85 'duration': int_or_none(media.get('duration')),
86 'channel': signing_channel.get('name'),
87 'channel_id': signing_channel.get('claim_id'),
88 'ext': determine_ext(source.get('name')) or mimetype2ext(source.get('media_type')),
89 'filesize': int_or_none(source.get('size')),
90 'url': streaming_url,
91 }