logo

oasis-root

Compiled tree of Oasis Linux based on own branch at <https://hacktivis.me/git/oasis/> git clone https://anongit.hacktivis.me/git/oasis-root.git

telewebion.py (5433B)


  1. from __future__ import annotations
  2. import functools
  3. import json
  4. import textwrap
  5. from .common import InfoExtractor
  6. from ..utils import ExtractorError, format_field, int_or_none, parse_iso8601
  7. from ..utils.traversal import traverse_obj
  8. def _fmt_url(url):
  9. return format_field(template=url, default=None)
  10. class TelewebionIE(InfoExtractor):
  11. _WORKING = False
  12. _VALID_URL = r'https?://(?:www\.)?telewebion\.com/episode/(?P<id>(?:0x[a-fA-F\d]+|\d+))'
  13. _TESTS = [{
  14. 'url': 'http://www.telewebion.com/episode/0x1b3139c/',
  15. 'info_dict': {
  16. 'id': '0x1b3139c',
  17. 'ext': 'mp4',
  18. 'title': 'قرعه‌کشی لیگ قهرمانان اروپا',
  19. 'series': '+ فوتبال',
  20. 'series_id': '0x1b2505c',
  21. 'channel': 'شبکه 3',
  22. 'channel_id': '0x1b1a761',
  23. 'channel_url': 'https://telewebion.com/live/tv3',
  24. 'timestamp': 1425522414,
  25. 'upload_date': '20150305',
  26. 'release_timestamp': 1425517020,
  27. 'release_date': '20150305',
  28. 'duration': 420,
  29. 'view_count': int,
  30. 'tags': ['ورزشی', 'لیگ اروپا', 'اروپا'],
  31. 'thumbnail': 'https://static.telewebion.com/episodeImages/YjFhM2MxMDBkMDNiZTU0MjE5YjQ3ZDY0Mjk1ZDE0ZmUwZWU3OTE3OWRmMDAyODNhNzNkNjdmMWMzMWIyM2NmMA/default',
  32. },
  33. 'skip_download': 'm3u8',
  34. }, {
  35. 'url': 'https://telewebion.com/episode/162175536',
  36. 'info_dict': {
  37. 'id': '0x9aa9a30',
  38. 'ext': 'mp4',
  39. 'title': 'کارما یعنی این !',
  40. 'series': 'پاورقی',
  41. 'series_id': '0x29a7426',
  42. 'channel': 'شبکه 2',
  43. 'channel_id': '0x1b1a719',
  44. 'channel_url': 'https://telewebion.com/live/tv2',
  45. 'timestamp': 1699979968,
  46. 'upload_date': '20231114',
  47. 'release_timestamp': 1699991638,
  48. 'release_date': '20231114',
  49. 'duration': 78,
  50. 'view_count': int,
  51. 'tags': ['کلیپ های منتخب', ' کلیپ طنز ', ' کلیپ سیاست ', 'پاورقی', 'ویژه فلسطین'],
  52. 'thumbnail': 'https://static.telewebion.com/episodeImages/871e9455-7567-49a5-9648-34c22c197f5f/default',
  53. },
  54. 'skip_download': 'm3u8',
  55. }]
  56. def _call_graphql_api(
  57. self, operation, video_id, query,
  58. variables: dict[str, tuple[str, str]] | None = None,
  59. note='Downloading GraphQL JSON metadata',
  60. ):
  61. parameters = ''
  62. if variables:
  63. parameters = ', '.join(f'${name}: {type_}' for name, (type_, _) in variables.items())
  64. parameters = f'({parameters})'
  65. result = self._download_json('https://graph.telewebion.com/graphql', video_id, note, data=json.dumps({
  66. 'operationName': operation,
  67. 'query': f'query {operation}{parameters} @cacheControl(maxAge: 60) {{{query}\n}}\n',
  68. 'variables': {name: value for name, (_, value) in (variables or {}).items()},
  69. }, separators=(',', ':')).encode(), headers={
  70. 'Content-Type': 'application/json',
  71. 'Accept': 'application/json',
  72. })
  73. if not result or traverse_obj(result, 'errors'):
  74. message = ', '.join(traverse_obj(result, ('errors', ..., 'message', {str})))
  75. raise ExtractorError(message or 'Unknown GraphQL API error')
  76. return result['data']
  77. def _real_extract(self, url):
  78. video_id = self._match_id(url)
  79. if not video_id.startswith('0x'):
  80. video_id = hex(int(video_id))
  81. episode_data = self._call_graphql_api('getEpisodeDetail', video_id, textwrap.dedent('''
  82. queryEpisode(filter: {EpisodeID: $EpisodeId}, first: 1) {
  83. title
  84. program {
  85. ProgramID
  86. title
  87. }
  88. image
  89. view_count
  90. duration
  91. started_at
  92. created_at
  93. channel {
  94. ChannelID
  95. name
  96. descriptor
  97. }
  98. tags {
  99. name
  100. }
  101. }
  102. '''), {'EpisodeId': ('[ID!]', video_id)})
  103. info_dict = traverse_obj(episode_data, ('queryEpisode', 0, {
  104. 'title': ('title', {str}),
  105. 'view_count': ('view_count', {int_or_none}),
  106. 'duration': ('duration', {int_or_none}),
  107. 'tags': ('tags', ..., 'name', {str}),
  108. 'release_timestamp': ('started_at', {parse_iso8601}),
  109. 'timestamp': ('created_at', {parse_iso8601}),
  110. 'series': ('program', 'title', {str}),
  111. 'series_id': ('program', 'ProgramID', {str}),
  112. 'channel': ('channel', 'name', {str}),
  113. 'channel_id': ('channel', 'ChannelID', {str}),
  114. 'channel_url': ('channel', 'descriptor', {_fmt_url('https://telewebion.com/live/%s')}),
  115. 'thumbnail': ('image', {_fmt_url('https://static.telewebion.com/episodeImages/%s/default')}),
  116. 'formats': (
  117. 'channel', 'descriptor', {str},
  118. {_fmt_url(f'https://cdna.telewebion.com/%s/episode/{video_id}/playlist.m3u8')},
  119. {functools.partial(self._extract_m3u8_formats, video_id=video_id, ext='mp4', m3u8_id='hls')}),
  120. }))
  121. info_dict['id'] = video_id
  122. return info_dict