dailymotion.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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. def request(query, params):
  62. if not query:
  63. return False
  64. language = params['language']
  65. if language == 'all':
  66. language = 'en-US'
  67. locale = babel.Locale.parse(language, sep='-')
  68. query_args = {
  69. 'search': query,
  70. 'languages': locale.language,
  71. 'page': params['pageno'],
  72. }
  73. if locale.territory:
  74. localization = locale.language + '_' + locale.territory
  75. if localization in supported_languages:
  76. query_args['country'] = locale.territory
  77. time_delta = time_delta_dict.get(params["time_range"])
  78. if time_delta:
  79. created_after = datetime.now() - time_delta
  80. query_args['created_after'] = datetime.timestamp(created_after)
  81. query_str = urlencode(query_args)
  82. params['url'] = search_url + '&' + query_str + safesearch_params.get(params['safesearch'], '')
  83. params['raise_for_httperror'] = False
  84. return params
  85. # get response from search-request
  86. def response(resp):
  87. results = []
  88. search_res = resp.json()
  89. # check for an API error
  90. if 'error' in search_res:
  91. raise SearxEngineAPIException(search_res['error'].get('message'))
  92. raise_for_httperror(resp)
  93. # parse results
  94. for res in search_res.get('list', []):
  95. title = res['title']
  96. url = res['url']
  97. content = html_to_text(res['description'])
  98. if len(content) > 300:
  99. content = content[:300] + '...'
  100. publishedDate = datetime.fromtimestamp(res['created_time'], None)
  101. length = time.gmtime(res.get('duration'))
  102. if length.tm_hour:
  103. length = time.strftime("%H:%M:%S", length)
  104. else:
  105. length = time.strftime("%M:%S", length)
  106. thumbnail = res['thumbnail_360_url']
  107. thumbnail = thumbnail.replace("http://", "https://")
  108. item = {
  109. 'template': 'videos.html',
  110. 'url': url,
  111. 'title': title,
  112. 'content': content,
  113. 'publishedDate': publishedDate,
  114. 'length': length,
  115. 'thumbnail': thumbnail,
  116. }
  117. # HINT: no mater what the value is, without API token videos can't shown
  118. # embedded
  119. if res['allow_embed']:
  120. item['iframe_src'] = iframe_src.format(video_id=res['id'])
  121. results.append(item)
  122. # return results
  123. return results
  124. # get supported languages from their site
  125. def _fetch_supported_languages(resp):
  126. response_json = resp.json()
  127. return [
  128. item['locale']
  129. for item in response_json['list']
  130. ]