diff --git a/clients/twitch.py b/clients/twitch.py index 9ef1e9f..be8cf4b 100644 --- a/clients/twitch.py +++ b/clients/twitch.py @@ -31,6 +31,13 @@ QUOTE_REMOVED_PATTERN = re.compile(r'''^ Successfully\s+deleted\s+Quote\s+ \#(?P\d+)\.$''', re.VERBOSE) +# $giver, Thank you for gifting a sub to $receiver! So kind <3 ! +SUB_GIFTED_PATTERN = re.compile(r'''^ + (?P.+),\s+ + Thank\s+you\s+for\s+gifting\s+a\s+sub\s+to\s+ + (?P.+)!\s+ + So\s+kind\s+<3\s+!$''', re.VERBOSE) + class TwitchClient(irc.bot.SingleServerIRCBot): def __init__(self, config, logger, commands, extra_commands): @@ -42,11 +49,13 @@ class TwitchClient(irc.bot.SingleServerIRCBot): (QUOTE_ADDED_PATTERN, self._add_quote), (QUOTE_EDITED_PATTERN, self._edit_quote), (QUOTE_REMOVED_PATTERN, self._remove_quote), + (SUB_GIFTED_PATTERN, self._record_gifted_sub), ] self.supported_commands = [ (re.compile(r'^!lastquote$'), self._do_lastquote), (re.compile(r'^!findquote\s+(?P")?(?P.+)(?(q)")$'), self._do_findquote), (re.compile(r'^!syncquotes$'), self._do_syncquotes), + (re.compile(r'^!syncsubs$'), self._do_syncsubs), (re.compile(r'^!(bella(gram|pics)|insta(gram|bella))$'), self._do_bellagram), (re.compile(r'^!yt\s+(?P")?(?P.+)(?(q)")$'), self._do_yt), (re.compile(r'^!clip\s+(?P")?(?P.+)(?(q)")$'), self._do_clip), @@ -138,6 +147,13 @@ class TwitchClient(irc.bot.SingleServerIRCBot): except CommandError as e: self.logger.error('Failed to remove quote: %s', e) + def _record_gifted_sub(self, tags, send_response, giver, receiver, **kwargs): + self.logger.info('Recording gifted sub %s -> %s', giver, receiver) + try: + self.commands.record_gifted_sub(giver, receiver, kwargs.get('time')) + except CommandError as e: + self.logger.error('Failed to record gifted sub: %s', e) + def _do_lastquote(self, tags, send_response, **kwargs): try: quote = self.commands.last_quote() @@ -169,11 +185,27 @@ class TwitchClient(irc.bot.SingleServerIRCBot): except CommandError as e: self.logger.error('Failed to get quote messages: %s', e) else: - for message in messages: + for message, time in messages: + for pattern, action in self.patterns: + m = pattern.match(message) + if m: + action(tags, send_response, **m.groupdict(), time=time) + send_response('Sync finished, @{0}'.format(tags['display-name'])) + + def _do_syncsubs(self, tags, send_response, **kwargs): + if not self._is_mod(tags): + send_response('Sorry @{0}, you are not allowed to do this'.format(tags['display-name'])) + return + try: + messages = self.commands.get_gifted_sub_messages() + except CommandError as e: + self.logger.error('Failed to get gifted sub messages: %s', e) + else: + for message, time in messages: for pattern, action in self.patterns: m = pattern.match(message) if m: - action(tags, send_response, **m.groupdict()) + action(tags, send_response, **m.groupdict(), time=time) send_response('Sync finished, @{0}'.format(tags['display-name'])) def _do_bellagram(self, tags, send_response, **kwargs): diff --git a/commands.py b/commands.py index 0554a58..30f344e 100644 --- a/commands.py +++ b/commands.py @@ -47,18 +47,35 @@ class Commands(object): except requests.exceptions.HTTPError as e: raise CommandError(e) - def get_quote_messages(self): + def record_gifted_sub(self, giver, receiver, time=None): + if time is None: + time = datetime.datetime.utcnow() try: - messages = self._get_messages(dict( - commenter='bellateeny', - term='quote')).json() + self._post_gifted_subs(dict( + giver=giver, + receiver=receiver, + time=time.isoformat())) except requests.exceptions.HTTPError as e: raise CommandError(e) + + def get_quote_messages(self): + try: + messages = self._get_messages('bellateeny', 'quote') + except CommandError: + raise else: # quotes before this date can have wrong IDs threshold = datetime.datetime(2018, 5, 11) - messages = [m for m in messages if dateutil.parser.parse(m['created_at']) >= threshold] - return [m.get('message_body', '') for m in messages] + messages = [(m, t) for m, t in messages if t >= threshold] + return messages + + def get_gifted_sub_messages(self): + try: + messages = self._get_messages('bellateeny', 'gift') + except CommandError: + raise + else: + return messages def last_quote(self): try: @@ -137,14 +154,40 @@ class Commands(object): r = requests.delete('{0}/quotes/{1}'.format(api_url, id), headers={'X-Quotes-API-Key': api_key}) r.raise_for_status() + # FIXME: reindex subsequent quotes + return r + + def _post_gifted_subs(self, data): + api_url = self.config['GiftedSubs'].get('api_url') + api_key = self.config['GiftedSubs'].get('api_key') + r = requests.post('{0}/gifted-subs'.format(api_url), data=data, + headers={'X-Gifted-Subs-API-Key': api_key}) + r.raise_for_status() return r - def _get_messages(self, params): + def _get_comments(self, params): api_url = self.config['Twitch'].get('cache_api_url') r = requests.get('{0}/search'.format(api_url), params=params) r.raise_for_status() return r + def _get_messages(self, commenter, term): + def get_time(message): + recorded = message.get('video_recorded_at') + if not recorded: + return None + result = dateutil.parser.parse(recorded) + result += datetime.timedelta(seconds=float(message.get('offset', 0))) + return result + try: + messages = self._get_comments(dict( + commenter=commenter, + term=term)).json() + except requests.exceptions.HTTPError as e: + raise CommandError(e) + else: + return [(m.get('message_body', ''), get_time(m)) for m in messages] + def _get_clips(self, params): api_url = self.config['Twitch'].get('cache_api_url') r = requests.get('{0}/clips'.format(api_url), params=params) diff --git a/settings.cfg.example b/settings.cfg.example index 61cf857..c4aa298 100644 --- a/settings.cfg.example +++ b/settings.cfg.example @@ -42,3 +42,7 @@ channel_ids = UC5970RJMoEcRNZl0MNp8tlQ,UCHNjavmkFUf2n0uzWSgj16w api_url = https://ladylilia.com/quotes/api api_key = __QUOTES_API_KEY__ act_as_proxy = true + +[GiftedSubs] +api_url = https://ladylilia.com/gifted-subs/api +api_key = __GIFTED_SUBS_API_KEY__