api.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import httpx
  2. import api_common
  3. import api_1_1
  4. import api_2
  5. import api_graph
  6. import config
  7. import redis_decorator
  8. import authman
  9. @redis_decorator.cache(ttl_secs=60*15)
  10. def get_guest_token():
  11. return request(api_1_1.guest_token()).json()["guest_token"]
  12. def gen_guest_token_headers():
  13. return {"x-guest-token": get_guest_token()}
  14. auth_man = authman.AuthManager([api_common.gen_authenticated_headers_base(auth) for auth in config.auth], gen_guest_token_headers)
  15. def add_base_request_params(params):
  16. params['headers'] = params.get('headers', {}) | api_common.gen_headers_base()
  17. params['method'] = params.get('method', 'get')
  18. def request(params):
  19. add_base_request_params(params)
  20. resp = httpx.request(**params)
  21. resp.raise_for_status()
  22. return resp
  23. def request_as_guest(params):
  24. params['headers'] = params.get('headers', {}) | gen_guest_token_headers()
  25. resp = request(params)
  26. if resp.headers['x-rate-limit-remaining'] == '1':
  27. get_guest_token.invalidate_cache()
  28. return resp
  29. def request_as_user(params):
  30. add_base_request_params(params)
  31. while True:
  32. params['headers'] = params.get('headers', {}) | auth_man.get()
  33. resp = httpx.request(**params)
  34. if resp.status_code == 429:
  35. auth_man.block_last()
  36. continue
  37. resp.raise_for_status()
  38. return resp
  39. @redis_decorator.cache(ttl_secs=60*60)
  40. def get_user(username):
  41. return request_as_guest(api_graph.user_by_screen_name(username)).json()
  42. def get_user_id(username):
  43. user = get_user(username)
  44. return user['data']['user']['result']['rest_id']
  45. @redis_decorator.cache(ttl_secs=60*60)
  46. def get_likes(username, cursor=None):
  47. return request_as_user(api_graph.likes(get_user_id(username), cursor)).json()
  48. def get_appropriate_request_func(username):
  49. user = get_user(username)
  50. if user['data']['user']['result']['legacy']['possibly_sensitive']:
  51. return request_as_user
  52. return request_as_guest
  53. @redis_decorator.cache(ttl_secs=60*60)
  54. def get_user_tweets(username, cursor=None):
  55. request_func = get_appropriate_request_func(username)
  56. return request_func(api_graph.user_tweets(get_user_id(username), cursor)).json()
  57. @redis_decorator.cache(ttl_secs=60*60)
  58. def get_tweet(tweet_id, username, cursor=None):
  59. request_func = get_appropriate_request_func(username)
  60. return request_func(api_graph.tweet_detail(tweet_id, cursor)).json()
  61. @redis_decorator.cache(ttl_secs=60*60)
  62. def get_favoriters(tweet_id, cursor=None):
  63. return request_as_user(api_graph.favoriters(tweet_id, cursor)).json()
  64. @redis_decorator.cache(ttl_secs=60*60)
  65. def get_retweeters(tweet_id, cursor=None):
  66. return request_as_user(api_graph.retweeters(tweet_id, cursor)).json()
  67. @redis_decorator.cache(ttl_secs=60*60)
  68. def get_followers(user_id, cursor=None):
  69. return request_as_user(api_graph.followers(user_id, cursor)).json()
  70. @redis_decorator.cache(ttl_secs=60*60)
  71. def get_following(user_id, cursor=None):
  72. return request_as_user(api_graph.following(user_id, cursor)).json()
  73. @redis_decorator.cache(ttl_secs=60*60)
  74. def search(query, cursor=None):
  75. try:
  76. return {
  77. 'search': request_as_user(api_graph.search(query, cursor)).json(),
  78. 'version': 'graphql'
  79. }
  80. except httpx.HTTPStatusError:
  81. #TODO implement cursor
  82. return {
  83. 'search': request_as_user(api_2.search(query)).json(),
  84. 'version': '2'
  85. }