comments.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. # -*- coding: utf-8 -*-
  2. import time
  3. import json
  4. import codecs
  5. import sys
  6. from socket import timeout, error as SocketError
  7. from ssl import SSLError
  8. try:
  9. # py2
  10. from urllib2 import URLError
  11. from httplib import HTTPException
  12. except ImportError:
  13. # py3
  14. from urllib.error import URLError
  15. from http.client import HTTPException
  16. from instagram_private_api import ClientError
  17. from .logger import log, seperator
  18. """
  19. This feature of PyInstaLive was originally written by https://github.com/taengstagram
  20. The code below and in downloader.py that's related to the comment downloading
  21. feature is modified by https://github.com/notcammy
  22. """
  23. class CommentsDownloader(object):
  24. def __init__(self, api, broadcast, destination_file):
  25. self.api = api
  26. self.broadcast = broadcast
  27. self.destination_file = destination_file
  28. self.comments = []
  29. def get_live(self, first_comment_created_at=0):
  30. comments_collected = self.comments
  31. before_count = len(comments_collected)
  32. try:
  33. comments_res = self.api.broadcast_comments(
  34. self.broadcast['id'], last_comment_ts=first_comment_created_at)
  35. comments = comments_res.get('comments', [])
  36. first_comment_created_at = (
  37. comments[0]['created_at_utc'] if comments else int(time.time() - 5))
  38. comments_collected.extend(comments)
  39. after_count = len(comments_collected)
  40. if after_count > before_count:
  41. broadcast = self.broadcast.copy()
  42. broadcast.pop('segments', None) # save space
  43. broadcast['comments'] = comments_collected
  44. with open(self.destination_file, 'w') as outfile:
  45. json.dump(broadcast, outfile, indent=2)
  46. self.comments = comments_collected
  47. except (SSLError, timeout, URLError, HTTPException, SocketError) as e:
  48. log('[W] Comment downloading error: %s' % e, "YELLOW")
  49. except ClientError as e:
  50. if e.code == 500:
  51. log('[W] Comment downloading ClientError: %d %s' % (e.code, e.error_response), "YELLOW")
  52. elif e.code == 400 and not e.msg:
  53. log('[W] Comment downloading ClientError: %d %s' % (e.code, e.error_response), "YELLOW")
  54. else:
  55. raise e
  56. finally:
  57. try:
  58. time.sleep(4)
  59. except KeyboardInterrupt:
  60. return first_comment_created_at
  61. return first_comment_created_at
  62. def get_replay(self):
  63. comments_collected = []
  64. starting_offset = 0
  65. encoding_tag = self.broadcast['encoding_tag']
  66. while True:
  67. comments_res = self.api.replay_broadcast_comments(
  68. self.broadcast['id'], starting_offset=starting_offset, encoding_tag=encoding_tag)
  69. starting_offset = comments_res.get('ending_offset', 0)
  70. comments = comments_res.get('comments', [])
  71. comments_collected.extend(comments)
  72. if not comments_res.get('comments') or not starting_offset:
  73. break
  74. time.sleep(4)
  75. if comments_collected:
  76. self.broadcast['comments'] = comments_collected
  77. self.broadcast['initial_buffered_duration'] = 0
  78. with open(self.destination_file, 'w') as outfile:
  79. json.dump(self.broadcast, outfile, indent=2)
  80. self.comments = comments_collected
  81. def save(self):
  82. broadcast = self.broadcast.copy()
  83. broadcast.pop('segments', None)
  84. broadcast['comments'] = self.comments
  85. with open(self.destination_file, 'w') as outfile:
  86. json.dump(broadcast, outfile, indent=2)
  87. @staticmethod
  88. def generate_log(comments, download_start_time, srt_file, comments_delay=10.0):
  89. python_version = sys.version.split(' ')[0]
  90. subtitles_timeline = {}
  91. for i, c in enumerate(comments):
  92. if 'offset' in c:
  93. for k in c['comment'].keys():
  94. c[k] = c['comment'][k]
  95. c['created_at_utc'] = download_start_time + c['offset']
  96. created_at_utc = str(2 * (c['created_at_utc'] // 2))
  97. comment_list = subtitles_timeline.get(created_at_utc) or []
  98. comment_list.append(c)
  99. subtitles_timeline[created_at_utc] = comment_list
  100. if subtitles_timeline:
  101. timestamps = sorted(subtitles_timeline.keys())
  102. mememe = False
  103. subs = []
  104. for i, tc in enumerate(timestamps):
  105. t = subtitles_timeline[tc]
  106. clip_start = int(tc) - int(download_start_time) + int(comments_delay)
  107. if clip_start < 0:
  108. clip_start = 0
  109. srt = ''
  110. for c in t:
  111. if (c['user']['is_verified']):
  112. srt += '{}{}\n\n'.format(time.strftime('%H:%M:%S\n', time.gmtime(clip_start)), '{} {}: {}'.format(c['user']['username'], "(v)", c['text']))
  113. else:
  114. srt += '{}{}\n\n'.format(time.strftime('%H:%M:%S\n', time.gmtime(clip_start)), '{}: {}'.format(c['user']['username'], c['text']))
  115. subs.append(srt)
  116. with codecs.open(srt_file, 'w', 'utf-8-sig') as srt_outfile:
  117. srt_outfile.write(''.join(subs))