Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #!/usr/bin/env python3
  2. import os
  3. import sys
  4. import json
  5. import requests
  6. from mastodon import Mastodon
  7. def load_config():
  8. with open(os.getenv('MR_CONFIG', 'config.json'), 'r') as f:
  9. return json.loads(f.read())
  10. def load_recents():
  11. try:
  12. with open(os.getenv('MR_RECENTS', 'recents.json'), 'r') as f:
  13. return json.loads(f.read())
  14. except NotFound:
  15. return []
  16. def save_recents(recents):
  17. with open(os.getenv('MR_RECENTS'), 'w') as f:
  18. f.write(json.dumps(recents))
  19. def make_masto(config):
  20. baseurl = 'https://%s' % config['hostname']
  21. return Mastodon(access_token=config['token'], api_base_url=baseurl)
  22. def make_post(masto, data):
  23. body = '%s\n\nby /u/%s at https://old.reddit.com/%s' % (data['title'], data['username'], data['rid'])
  24. #if len(data['attachments']) > 4:
  25. # data['attachments'] = data['attachments'][:4]
  26. image_resps = None
  27. #if data['attachments'] is not None:
  28. # for a in data['attachments']:
  29. # res = masto.media_post(a)
  30. # res.raise_for_status()
  31. # image_resps.append(res)
  32. #else:
  33. # image_resps = None
  34. masto.status_post(body, media_ids=image_resps)
  35. def extract_media_urls(data):
  36. if 'selftext' in data:
  37. return []
  38. if 'post_hint' not in data:
  39. if 'gallery_data' in data:
  40. gd = data['gallery_data']['items']
  41. mmd = data['media_metadata']
  42. ents = []
  43. for ent in gd:
  44. mid = ent['media_id']
  45. mime = mmd[mid]['m']
  46. _, ext = mime.split('/')
  47. url = 'https://i.redd.it/%s.%s' % (mid, ext)
  48. ents.append(url)
  49. return ents
  50. else:
  51. raise ValueError('no hint type and missing gallery')
  52. hint = data['post_hint']
  53. if hint == 'link':
  54. if 'crosspost_parent_list' in data:
  55. return extract_media_urls(data['crosspost_parent_list'][0])
  56. else:
  57. # Not a reddit crosspost.
  58. return []
  59. if hint == 'hosted:video':
  60. return [data['secure_media']['reddit_video']['fallback_url']]
  61. if hint == 'image':
  62. return [data['url']]
  63. if hint == 'rich:video':
  64. # TODO maybe use thumbnail?
  65. print('got a video at', data['url'], 'but ignoring')
  66. raise ValueError('unknown hint type ' + hint)
  67. def query_tops(config):
  68. url = 'https://www.reddit.com/r/%s/top.json?sort=top&t=day' % config['subreddit']
  69. resp = requests.get(url, headers = {'User-agent': 'mastoreddit'})
  70. resp.raise_for_status()
  71. j = resp.json()
  72. posts = []
  73. for post in j['data']['children']:
  74. if post['kind'] != 't3':
  75. print('found post of kind', post['kind'])
  76. d = post['data']
  77. media = None
  78. try:
  79. media = extract_media_urls(d)
  80. except Exception as e:
  81. print('error processing ' + d['id'] + ': ' + str(e))
  82. posts.append({
  83. 'rid': d['id'],
  84. 'title': d['title'],
  85. 'username': d['author'],
  86. 'score': d['ups'],
  87. 'media': media
  88. })
  89. return posts
  90. def just_toot(config, msg):
  91. masto = make_masto(config)
  92. masto.toot(msg)
  93. def main():
  94. config = load_config()
  95. masto = make_masto(config)
  96. # make_post(masto, {'title': sys.argv[1], 'username': 'nobody', 'rid': 'none', 'attachments': [sys.argv[2]]})
  97. res = query_tops(config)
  98. for r in res[:5]:
  99. print('posting', r['rid'], '-', r['title'])
  100. make_post(masto, r)
  101. if __name__ == '__main__':
  102. main()