dailymotion.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. # SPDX-License-Identifier: AGPL-3.0-or-later
  2. """Dailymotion (Videos)
  3. """
  4. from typing import Set
  5. from datetime import datetime, timedelta
  6. from urllib.parse import urlencode
  7. import time
  8. import babel
  9. from searx.exceptions import SearxEngineAPIException
  10. from searx.network import raise_for_httperror
  11. from searx.utils import html_to_text
  12. # about
  13. about = {
  14. "website": 'https://www.dailymotion.com',
  15. "wikidata_id": 'Q769222',
  16. "official_api_documentation": 'https://www.dailymotion.com/developer',
  17. "use_official_api": True,
  18. "require_api_key": False,
  19. "results": 'JSON',
  20. }
  21. # engine dependent config
  22. categories = ['videos']
  23. paging = True
  24. number_of_results = 10
  25. time_range_support = True
  26. time_delta_dict = {
  27. "day": timedelta(days=1),
  28. "week": timedelta(days=7),
  29. "month": timedelta(days=31),
  30. "year": timedelta(days=365),
  31. }
  32. safesearch = True
  33. safesearch_params = {2: '&is_created_for_kids=true', 1: '&is_created_for_kids=true', 0: ''}
  34. # search-url
  35. # - https://developers.dailymotion.com/tools/
  36. # - https://www.dailymotion.com/doc/api/obj-video.html
  37. result_fields = [
  38. 'allow_embed',
  39. 'description',
  40. 'title',
  41. 'created_time',
  42. 'duration',
  43. 'url',
  44. 'thumbnail_360_url',
  45. 'id',
  46. ]
  47. search_url = (
  48. 'https://api.dailymotion.com/videos?'
  49. 'fields={fields}&password_protected={password_protected}&private={private}&sort={sort}&limit={limit}'
  50. ).format(
  51. fields=','.join(result_fields),
  52. password_protected= 'false',
  53. private='false',
  54. sort='relevance',
  55. limit=number_of_results,
  56. )
  57. iframe_src = "https://www.dailymotion.com/embed/video/{video_id}"
  58. # The request query filters by 'languages' & 'country', therefore instead of
  59. # fetching only languages we need to fetch locales.
  60. supported_languages_url = 'https://api.dailymotion.com/locales'
  61. supported_languages_iso639: Set[str] = set()
  62. def init(_engine_settings):
  63. global supported_languages_iso639
  64. supported_languages_iso639 = set([language.split('_')[0] for language in supported_languages])
  65. def request(query, params):
  66. if not query:
  67. return False
  68. language = params['language']
  69. if language == 'all':
  70. language = 'en-US'
  71. locale = babel.Locale.parse(language, sep='-')
  72. language_iso639 = locale.language
  73. if locale.language not in supported_languages_iso639:
  74. language_iso639 = 'en'
  75. query_args = {
  76. 'search': query,
  77. 'languages': language_iso639,
  78. 'page': params['pageno'],
  79. }
  80. if locale.territory:
  81. localization = locale.language + '_' + locale.territory
  82. if localization in supported_languages:
  83. query_args['country'] = locale.territory
  84. time_delta = time_delta_dict.get(params["time_range"])
  85. if time_delta:
  86. created_after = datetime.now() - time_delta
  87. query_args['created_after'] = datetime.timestamp(created_after)
  88. query_str = urlencode(query_args)
  89. params['url'] = search_url + '&' + query_str + safesearch_params.get(params['safesearch'], '')
  90. params['raise_for_httperror'] = False
  91. return params
  92. # get response from search-request
  93. def response(resp):
  94. results = []
  95. search_res = resp.json()
  96. # check for an API error
  97. if 'error' in search_res:
  98. raise SearxEngineAPIException(search_res['error'].get('message'))
  99. raise_for_httperror(resp)
  100. # parse results
  101. for res in search_res.get('list', []):
  102. title = res['title']
  103. url = res['url']
  104. content = html_to_text(res['description'])
  105. if len(content) > 300:
  106. content = content[:300] + '...'
  107. publishedDate = datetime.fromtimestamp(res['created_time'], None)
  108. length = time.gmtime(res.get('duration'))
  109. if length.tm_hour:
  110. length = time.strftime("%H:%M:%S", length)
  111. else:
  112. length = time.strftime("%M:%S", length)
  113. thumbnail = res['thumbnail_360_url']
  114. thumbnail = thumbnail.replace("http://", "https://")
  115. item = {
  116. 'template': 'videos.html',
  117. 'url': url,
  118. 'title': title,
  119. 'content': content,
  120. 'publishedDate': publishedDate,
  121. 'length': length,
  122. 'thumbnail': thumbnail,
  123. }
  124. # HINT: no mater what the value is, without API token videos can't shown
  125. # embedded
  126. if res['allow_embed']:
  127. item['iframe_src'] = iframe_src.format(video_id=res['id'])
  128. results.append(item)
  129. # return results
  130. return results
  131. # get supported languages from their site
  132. def _fetch_supported_languages(resp):
  133. response_json = resp.json()
  134. return [
  135. item['locale']
  136. for item in response_json['list']
  137. ]