|
|
@ -1,5 +1,7 @@
|
|
|
|
|
|
|
|
import datetime
|
|
|
|
import functools
|
|
|
|
import functools
|
|
|
|
import re
|
|
|
|
import re
|
|
|
|
|
|
|
|
import time
|
|
|
|
import unicodedata
|
|
|
|
import unicodedata
|
|
|
|
|
|
|
|
|
|
|
|
import irc.bot
|
|
|
|
import irc.bot
|
|
|
@ -52,6 +54,17 @@ SUB_GIFTED_PATTERN = re.compile(r'''^
|
|
|
|
(?P<receiver>.+)!\s+
|
|
|
|
(?P<receiver>.+)!\s+
|
|
|
|
So\s+kind\s+<3\s+!$''', re.VERBOSE)
|
|
|
|
So\s+kind\s+<3\s+!$''', re.VERBOSE)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# A giveaway for: $prize has started! $entitled can join!
|
|
|
|
|
|
|
|
GIVEAWAY_STARTED_PATTERN = re.compile(r'''^
|
|
|
|
|
|
|
|
A\s+giveaway\s+for:\s+
|
|
|
|
|
|
|
|
(?P<prize>.+)\s+has\s+started!\s+
|
|
|
|
|
|
|
|
(?P<entitled>.+)\s+can\s+[jJ]oin!?$''', re.VERBOSE)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Entries have stopped for the giveaway! You can no longer enter!
|
|
|
|
|
|
|
|
GIVEAWAY_ENDED_PATTERN = re.compile(r'''^
|
|
|
|
|
|
|
|
Entries\s+have\s+stopped\s+for\s+the\s+giveaway!\s+
|
|
|
|
|
|
|
|
You\s+can\s+no\s+longer\s+enter!$''', re.VERBOSE)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TwitchClient(irc.bot.SingleServerIRCBot):
|
|
|
|
class TwitchClient(irc.bot.SingleServerIRCBot):
|
|
|
|
def __init__(self, config, logger, commands, extra_commands):
|
|
|
|
def __init__(self, config, logger, commands, extra_commands):
|
|
|
@ -59,6 +72,7 @@ class TwitchClient(irc.bot.SingleServerIRCBot):
|
|
|
|
self.logger = logger
|
|
|
|
self.logger = logger
|
|
|
|
self.commands = commands
|
|
|
|
self.commands = commands
|
|
|
|
self.extra_commands = extra_commands
|
|
|
|
self.extra_commands = extra_commands
|
|
|
|
|
|
|
|
self.giveaway = None
|
|
|
|
self.patterns = [
|
|
|
|
self.patterns = [
|
|
|
|
(QUOTE_ADDED_PATTERN, self._add_quote),
|
|
|
|
(QUOTE_ADDED_PATTERN, self._add_quote),
|
|
|
|
(QUOTE_EDITED_PATTERN, self._edit_quote),
|
|
|
|
(QUOTE_EDITED_PATTERN, self._edit_quote),
|
|
|
@ -66,6 +80,8 @@ class TwitchClient(irc.bot.SingleServerIRCBot):
|
|
|
|
(SUB_PATTERN, self._record_sub),
|
|
|
|
(SUB_PATTERN, self._record_sub),
|
|
|
|
(RESUB_PATTERN, self._record_resub),
|
|
|
|
(RESUB_PATTERN, self._record_resub),
|
|
|
|
(SUB_GIFTED_PATTERN, self._record_gifted_sub),
|
|
|
|
(SUB_GIFTED_PATTERN, self._record_gifted_sub),
|
|
|
|
|
|
|
|
(GIVEAWAY_STARTED_PATTERN, self._process_giveaway_start),
|
|
|
|
|
|
|
|
(GIVEAWAY_ENDED_PATTERN, self._process_giveaway_end),
|
|
|
|
]
|
|
|
|
]
|
|
|
|
self.supported_commands = [
|
|
|
|
self.supported_commands = [
|
|
|
|
(re.compile(r'^!lastquote$'), self._do_lastquote),
|
|
|
|
(re.compile(r'^!lastquote$'), self._do_lastquote),
|
|
|
@ -75,6 +91,7 @@ class TwitchClient(irc.bot.SingleServerIRCBot):
|
|
|
|
(re.compile(r'^!(bella(gram|pics)|insta(gram|bella))$'), self._do_bellagram),
|
|
|
|
(re.compile(r'^!(bella(gram|pics)|insta(gram|bella))$'), self._do_bellagram),
|
|
|
|
(re.compile(r'^!yt\s+(?P<q>")?(?P<query>.+)(?(q)")$'), self._do_yt),
|
|
|
|
(re.compile(r'^!yt\s+(?P<q>")?(?P<query>.+)(?(q)")$'), self._do_yt),
|
|
|
|
(re.compile(r'^!clip\s+(?P<q>")?(?P<filter>.+)(?(q)")$'), self._do_clip),
|
|
|
|
(re.compile(r'^!clip\s+(?P<q>")?(?P<filter>.+)(?(q)")$'), self._do_clip),
|
|
|
|
|
|
|
|
(re.compile(r'^!giveaway$'), self._do_giveaway),
|
|
|
|
(re.compile(r'^!command\s+set\s+(?P<q1>")?(?P<cmd>.+?)(?(q1)")\s+'
|
|
|
|
(re.compile(r'^!command\s+set\s+(?P<q1>")?(?P<cmd>.+?)(?(q1)")\s+'
|
|
|
|
r'(?P<q2>")?(?P<resp>.+)(?(q2)")$'), self._do_command_set),
|
|
|
|
r'(?P<q2>")?(?P<resp>.+)(?(q2)")$'), self._do_command_set),
|
|
|
|
(re.compile(r'^!command\s+unset\s+(?P<q>")?(?P<cmd>.+)(?(q)")$'), self._do_command_unset),
|
|
|
|
(re.compile(r'^!command\s+unset\s+(?P<q>")?(?P<cmd>.+)(?(q)")$'), self._do_command_unset),
|
|
|
@ -186,6 +203,13 @@ class TwitchClient(irc.bot.SingleServerIRCBot):
|
|
|
|
except CommandError as e:
|
|
|
|
except CommandError as e:
|
|
|
|
self.logger.error('Failed to record gifted sub: %s', e)
|
|
|
|
self.logger.error('Failed to record gifted sub: %s', e)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _process_giveaway_start(self, tags, send_response, prize, entitled, **kwargs):
|
|
|
|
|
|
|
|
starttime = kwargs.get('time', datetime.datetime.utcnow())
|
|
|
|
|
|
|
|
self.giveaway = (starttime, prize, entitled)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _process_giveaway_end(self, tags, send_response, **kwargs):
|
|
|
|
|
|
|
|
self.giveaway = None
|
|
|
|
|
|
|
|
|
|
|
|
def _do_lastquote(self, tags, send_response, **kwargs):
|
|
|
|
def _do_lastquote(self, tags, send_response, **kwargs):
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
quote = self.commands.last_quote()
|
|
|
|
quote = self.commands.last_quote()
|
|
|
@ -264,6 +288,19 @@ class TwitchClient(irc.bot.SingleServerIRCBot):
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
send_response('{0}: {1}'.format(result['title'], result['url']))
|
|
|
|
send_response('{0}: {1}'.format(result['title'], result['url']))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _do_giveaway(self, tags, send_response, **kwargs):
|
|
|
|
|
|
|
|
if not self.giveaway:
|
|
|
|
|
|
|
|
send_response('There is currently no giveaway in progress')
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
starttime, prize, entitled = self.giveaway
|
|
|
|
|
|
|
|
elapsed = (datetime.datetime.utcnow() - starttime).total_seconds()
|
|
|
|
|
|
|
|
if elapsed > 2 * 60 * 60:
|
|
|
|
|
|
|
|
self.giveaway = None
|
|
|
|
|
|
|
|
send_response('There is currently no giveaway in progress')
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
elapsed = time.strftime('%H:%M', time.gmtime(elapsed))
|
|
|
|
|
|
|
|
send_response('Giveaway for {0} is open (for {1})! {2} can join!'.format(prize, elapsed, entitled))
|
|
|
|
|
|
|
|
|
|
|
|
def _do_command_set(self, tags, send_response, cmd, resp, **kwargs):
|
|
|
|
def _do_command_set(self, tags, send_response, cmd, resp, **kwargs):
|
|
|
|
if not self._is_mod(tags):
|
|
|
|
if not self._is_mod(tags):
|
|
|
|
send_response('Sorry @{0}, you are not allowed to do this'.format(tags['display-name']))
|
|
|
|
send_response('Sorry @{0}, you are not allowed to do this'.format(tags['display-name']))
|
|
|
|