mastodon.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. # SPDX-License-Identifier: AGPL-3.0-or-later
  2. # lint: pylint
  3. """Mastodon_ is an open source alternative to large social media platforms like
  4. Twitter/X, Facebook, ...
  5. Since it's federated and self-hostable, there's a large amount of available
  6. instances, which can be chosen instead by modifying ``base_url``.
  7. We use their official API_ for searching, but unfortunately, their Search API_
  8. forbids pagination without OAuth.
  9. That's why we use tootfinder.ch for finding posts, which doesn't support searching
  10. for users, accounts or other types of content on Mastodon however.
  11. .. _Mastodon: https://mastodon.social
  12. .. _API: https://docs.joinmastodon.org/api/
  13. """
  14. from urllib.parse import urlencode
  15. from datetime import datetime
  16. about = {
  17. "website": 'https://joinmastodon.org/',
  18. "wikidata_id": 'Q27986619',
  19. "official_api_documentation": 'https://docs.joinmastodon.org/api/',
  20. "use_official_api": True,
  21. "require_api_key": False,
  22. "results": 'JSON',
  23. }
  24. categories = ['social media']
  25. base_url = "https://mastodon.social"
  26. mastodon_type = "accounts"
  27. # https://github.com/searxng/searxng/pull/2857#issuecomment-1741713999
  28. page_size = 40
  29. def request(query, params):
  30. args = {
  31. 'q': query,
  32. 'resolve': 'false',
  33. 'type': mastodon_type,
  34. 'limit': page_size,
  35. }
  36. params['url'] = f"{base_url}/api/v2/search?{urlencode(args)}"
  37. return params
  38. def response(resp):
  39. results = []
  40. json = resp.json()
  41. for result in json[mastodon_type]:
  42. if mastodon_type == "accounts":
  43. results.append(
  44. {
  45. 'url': result['uri'],
  46. 'title': result['username'] + f" ({result['followers_count']} followers)",
  47. 'content': result['note'],
  48. 'thumbnail': result.get('avatar'),
  49. 'publishedDate': datetime.strptime(result['created_at'][:10], "%Y-%m-%d"),
  50. }
  51. )
  52. elif mastodon_type == "hashtags":
  53. uses_count = sum(int(entry['uses']) for entry in result['history'])
  54. user_count = sum(int(entry['accounts']) for entry in result['history'])
  55. results.append(
  56. {
  57. 'url': result['url'],
  58. 'title': result['name'],
  59. 'content': f"Hashtag has been used {uses_count} times by {user_count} different users",
  60. }
  61. )
  62. else:
  63. raise ValueError(f"Unsupported mastodon type: {mastodon_type}")
  64. return results