From 2081b334a8eb9e92537b0d97adb98e2dbbae29fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Forr=C3=B3?= Date: Fri, 22 Mar 2019 17:59:13 +0100 Subject: [PATCH] Add !roll to Twitch --- clients/twitch.py | 9 +++++++++ commands.py | 4 ++-- services/roll20.py | 43 +++++++++++++++++++++++++++++-------------- 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/clients/twitch.py b/clients/twitch.py index fef4e89..1fee551 100644 --- a/clients/twitch.py +++ b/clients/twitch.py @@ -103,6 +103,7 @@ class TwitchClient(irc.bot.SingleServerIRCBot): (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'^!(find)?clip\s+(?P")?(?P.+)(?(q)")$'), self._do_clip), + (re.compile(r'^!roll(\s+(?P")?(?P.+)(?(q)"))?$'), self._do_roll), (re.compile(r'^!giveaway$'), self._do_giveaway), (re.compile(r'^!command\s+set\s+(?P")?(?P.+?)(?(q1)")\s+' r'(?P")?(?P.+)(?(q2)")$'), self._do_command_set), @@ -318,6 +319,14 @@ class TwitchClient(irc.bot.SingleServerIRCBot): else: send_response('{0}: {1}'.format(result['title'], result['url'])) + def _do_roll(self, tags, send_response, formula, **kwargs): + try: + result = self.commands.roll(formula, True) + except CommandError as e: + send_response('Sorry @{0}, {1}'.format(tags['display-name'], e)) + else: + send_response(result) + def _do_giveaway(self, tags, send_response, **kwargs): if not self.giveaway or not self.giveaway['active']: send_response('There is currently no giveaway in progress') diff --git a/commands.py b/commands.py index ee706b8..f70ad71 100644 --- a/commands.py +++ b/commands.py @@ -192,11 +192,11 @@ class Commands(object): else: return event - def roll(self, formula): + def roll(self, formula, plaintext=False): if not formula: formula = self.last_roll_formula try: - result = Roll20.execute(formula) + result = Roll20.execute(formula, plaintext) except Roll20Error: raise CommandError('failed to interpret or execute the formula') else: diff --git a/services/roll20.py b/services/roll20.py index f395762..30dfe1a 100644 --- a/services/roll20.py +++ b/services/roll20.py @@ -17,8 +17,9 @@ def num(x): class Group(object): - def __init__(self, items): + def __init__(self, items, plaintext=False): self.items = items + self.plaintext = plaintext self.keep = None self.drop = None self.succ = None @@ -34,7 +35,9 @@ class Group(object): result = [] for i, x in enumerate(self.items): if i in kept: - if len(self.items) > 1 and self.succ: + if self.plaintext: + result.append(str(x)) + elif len(self.items) > 1 and self.succ: if self.succ(calculated[i]): result.append('__{0}__'.format(x)) elif self.fail and self.fail(calculated[i]): @@ -43,9 +46,12 @@ class Group(object): result.append(str(x)) else: result.append(str(x)) - else: + elif not self.plaintext: result.append('~~*{0}*~~'.format(x)) - return '**{{** {0} **}}**'.format(' + '.join(result)) + if self.plaintext: + return '{{ {0} }}'.format(' + '.join(result)) + else: + return '**{{** {0} **}}**'.format(' + '.join(result)) def _subrolls(self, tree): def traverse(node, subrolls): @@ -206,8 +212,9 @@ class Operation2(object): class Roll(object): - def __init__(self, result): + def __init__(self, result, plaintext=False): self.result = result + self.plaintext = plaintext self.label = None self.keep = None self.drop = None @@ -224,7 +231,9 @@ class Roll(object): result = [] for i, x in enumerate(self.result): if i in kept: - if self.succ: + if self.plaintext: + result.append(str(x)) + elif self.succ: if self.succ(x): result.append('__{0}__'.format(x)) elif self.fail and self.fail(x): @@ -233,9 +242,12 @@ class Roll(object): result.append(str(x)) else: result.append(str(x)) - else: + elif not self.plaintext: result.append('~~*{0}*~~'.format(x)) - return '**(** {0} **)**'.format(' + '.join(result)) + if self.plaintext: + return '( {0} )'.format(' + '.join(result)) + else: + return '**(** {0} **)**'.format(' + '.join(result)) def kept(self, ignore_group=False): if not ignore_group and self.group_kept is not None: @@ -284,7 +296,7 @@ class Parser(object): return expression.parse(formula) @classmethod - def parse(cls, tokens): + def parse(cls, tokens, plaintext=False): @parsy.generate def group_failures(): result = yield group_successes @@ -329,7 +341,7 @@ class Parser(object): yield parsy.match_item('{') #result = yield group_simple result = yield function | expression_additive - result = Group([result]) + result = Group([result], plaintext) while True: end = yield parsy.match_item('}') | parsy.success('') if end: @@ -474,7 +486,7 @@ class Parser(object): else: for modify in m: result, dice = modify(result, dice) - return Roll(result) + return Roll(result, plaintext) @parsy.generate def sort(): @@ -667,14 +679,17 @@ class Roll20Error(Exception): class Roll20(object): @classmethod - def execute(cls, formula): + def execute(cls, formula, plaintext=False): try: tokens = Parser.tokenize(formula) - result = Parser.parse(tokens) + result = Parser.parse(tokens, plaintext) try: calculated = result.calc() except AttributeError: calculated = num(result) - return '{0} = __**{1}**__'.format(str(result), calculated) + if plaintext: + return '{0} = {1}'.format(str(result), calculated) + else: + return '{0} = __**{1}**__'.format(str(result), calculated) except (parsy.ParseError, TypeError, RuntimeError) as e: raise Roll20Error(str(e))