mastodon.py 2.5 KB

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