diff --git a/metabot/botconf.py b/metabot/botconf.py index e0e9020..469dd51 100644 --- a/metabot/botconf.py +++ b/metabot/botconf.py @@ -27,7 +27,7 @@ def __init__(self, confdir=None): # pylint: disable=too-many-branches if fname.endswith('.yaml'): self[fname[:-len('.yaml')]] = yamlutil.load(os.path.join(confdir, fname)) - # Schema update: Remove after 2019-03-26. + # Schema update: Remove after 2019-03-26 (https://github.com/nmlorg/metabot/issues/18). if not self['bots']: fname = os.path.join(confdir, 'multibot.json') data = jsonutil.load(fname) @@ -35,7 +35,7 @@ def __init__(self, confdir=None): # pylint: disable=too-many-branches self['bots'] = data logging.info('Converted %s to %s.', fname, os.path.join(confdir, 'bots.yaml')) - # Schema update: Remove after 2019-04-05. + # Schema update: Remove after 2019-04-05 (https://github.com/nmlorg/metabot/issues/18). for botconf in self['bots'].values(): for groupid, groupconf in botconf['moderator'].items(): groupid = int(groupid) @@ -43,7 +43,7 @@ def __init__(self, confdir=None): # pylint: disable=too-many-branches if k in groupconf: self['groups'][groupid][k] = groupconf[k] - # Schema update: Remove after 2019-06-12. + # Schema update: Remove after 2019-06-12 (https://github.com/nmlorg/metabot/issues/37). for botconf in self['bots'].values(): if botconf.get('telegram'): for modname in list(botconf): @@ -51,6 +51,16 @@ def __init__(self, confdir=None): # pylint: disable=too-many-branches botconf['issue37'][modname] = botconf[modname] botconf.pop(modname) + # Schema update: Remove after 2019-08-13 (https://github.com/nmlorg/metabot/issues/41). + for botconf in self['bots'].values(): + for command, message in botconf['issue37']['echo'].items(): + if not isinstance(message, dict): + botconf['issue37']['echo'][command] = { + 'text': message, + 'paginate': True, + 'private': '\n' in message, + } + self._fnames = set(self) @contextlib.contextmanager diff --git a/metabot/modules/echo.py b/metabot/modules/echo.py index b157114..6451035 100644 --- a/metabot/modules/echo.py +++ b/metabot/modules/echo.py @@ -2,9 +2,12 @@ from __future__ import absolute_import, division, print_function, unicode_literals +from metabot.util import adminui + def modhelp(unused_ctx, modconf, sections): # pylint: disable=missing-docstring - for command, message in modconf.items(): + for command, data in modconf.items(): + message = data['text'].replace('\n', ' ') if len(message) > 30: message = message[:29] + '\u2026' sections['commands'].add('/%s \u2013 "%s"' % (command, message)) @@ -17,55 +20,47 @@ def moddispatch(ctx, msg, modconf): # pylint: disable=missing-docstring return False -def echo(ctx, msg, message): # pylint: disable=missing-docstring - lines = [line for line in message.splitlines() if line.strip()] - page = ctx.text.isdigit() and int(ctx.text) or 1 - for line in lines[:page]: - msg.add('%s', line) - if page < len(lines): - ctx.private = True - msg.button('More (%i/%i)' % (page, len(lines)), '/%s %i' % (ctx.command, page + 1)) +def echo(ctx, msg, data): # pylint: disable=missing-docstring + ctx.private = data.get('private') + if not data.get('paginate'): + msg.add(data['text']) + else: + lines = [line for line in data['text'].splitlines() if line.strip()] + page = ctx.text.isdigit() and int(ctx.text) or 1 + for line in lines[:page]: + msg.add('%s', line) + if page < len(lines): + msg.button('More (%i/%i)' % (page, len(lines)), '/%s %i' % (ctx.command, page + 1)) def admin(ctx, msg, modconf): """Handle /admin BOTNAME echo.""" - command, message = ctx.split(2) + command, field, message = ctx.split(3) command = command.lower() - if ctx.document: - message = 'document:%s' % ctx.document - elif ctx.photo: - message = 'photo:%s' % ctx.photo - elif ctx.sticker: - message = 'sticker:%s' % ctx.sticker - - if command and message: - if message == 'remove': - if command not in modconf: - msg.add('/%s is not echoing anything.', command) - else: - msg.add('Removed /%s (%s).', command, modconf[command]) - modconf.pop(command) - command = message = None - else: - if command in modconf: - msg.add('Changed /%s from %s to %s.', command, - modconf[command], message) - else: - msg.add('/%s now echoes %s.', command, message) - modconf[command] = message - command = message = None - if not command: msg.action = 'Choose a command' msg.add( "Type the name of a command to add (like rules\u2014don't include a slash " - 'at the beginning!), or select an existing echo to remove.') - for command, message in sorted(modconf.items()): - msg.button('/%s (%s)' % (command, message), '%s remove' % command) + 'at the beginning!), or select an existing echo.') + for command, data in sorted(modconf.items()): + msg.button('/%s (%s)' % (command, data['text'].replace('\n', ' ')), command) return msg.path(command) - msg.action = 'Type the message for /' + command - msg.add('Type the text you want me to send in response to /%s:', command) + + if ctx.document: + message = 'document:%s' % ctx.document + elif ctx.photo: + message = 'photo:%s' % ctx.photo + elif ctx.sticker: + message = 'sticker:%s' % ctx.sticker + + fields = ( + ('text', adminui.freeform, + 'The message, sticker, or image to send in response to /%s.' % command), + ('paginate', adminui.bool, 'For multiline messages, display just one line at a time?'), + ('private', adminui.bool, 'Send the message in group chats, or just in private?'), + ) + return adminui.fields(ctx, msg, modconf[command], fields, field, message) diff --git a/metabot/modules/test_echo.py b/metabot/modules/test_echo.py index 0e2d35e..0e80e12 100644 --- a/metabot/modules/test_echo.py +++ b/metabot/modules/test_echo.py @@ -20,19 +20,37 @@ def test_echo(conversation): # pylint: disable=redefined-outer-name assert conversation.message('/myecho') == '' - conversation.multibot.conf['bots']['modulestestbot']['issue37']['echo']['myecho'] = ( - 'These are the rules: Have fun!') + conversation.multibot.conf['bots']['modulestestbot']['issue37']['echo']['myecho'] = { + 'text': 'These are the rules: Have fun!', + } assert conversation.message('/myecho') == """\ [chat_id=1000 disable_web_page_preview=True parse_mode=HTML] These are the rules: Have fun! """ - conversation.multibot.conf['bots']['modulestestbot']['issue37']['echo']['about'] = ( - 'First line.\n' - 'Second line.\n' - ' \n' - 'Last line.') + conversation.multibot.conf['bots']['modulestestbot']['issue37']['echo']['about'] = { + 'text': ('First line.\n' + 'Second line.\n' + ' \n' + 'Last line.'), + } + + assert conversation.message('/about') == """\ +[chat_id=1000 disable_web_page_preview=True parse_mode=HTML] +First line. +Second line. + +Last line. +""" + + conversation.multibot.conf['bots']['modulestestbot']['issue37']['echo']['about'] = { + 'text': ('First line.\n' + 'Second line.\n' + ' \n' + 'Last line.'), + 'paginate': True, + } assert conversation.message('/about') == """\ [chat_id=1000 disable_web_page_preview=True parse_mode=HTML] @@ -76,10 +94,12 @@ def test_echo(conversation): # pylint: disable=redefined-outer-name def test_help(conversation): # pylint: disable=redefined-outer-name """Test /help.""" - conversation.multibot.conf['bots']['modulestestbot']['issue37']['echo']['rules1'] = ( - 'These are the rules: Have fun!') - conversation.multibot.conf['bots']['modulestestbot']['issue37']['echo']['rules2'] = ( - 'These are the rules: Have fun!!') + conversation.multibot.conf['bots']['modulestestbot']['issue37']['echo']['rules1'] = { + 'text': 'These are the rules: Have fun!', + } + conversation.multibot.conf['bots']['modulestestbot']['issue37']['echo']['rules2'] = { + 'text': 'These are the rules: Have fun!!', + } assert conversation.message('/help', user_id=2000) == """\ [chat_id=2000 disable_web_page_preview=True parse_mode=HTML] @@ -98,56 +118,56 @@ def test_admin(conversation): # pylint: disable=redefined-outer-name [chat_id=1000 disable_web_page_preview=True parse_mode=HTML] Bot Admin \u203a modulestestbot \u203a echo: Choose a command -Type the name of a command to add (like rules\u2014don't include a slash at the beginning!), or select an existing echo to remove. +Type the name of a command to add (like rules\u2014don't include a slash at the beginning!), or select an existing echo. [Back | /admin modulestestbot] """ assert conversation.message('EchoTest') == """\ [chat_id=1000 disable_web_page_preview=True parse_mode=HTML] -Bot Admin \u203a modulestestbot \u203a echo \u203a echotest: Type the message for /echotest - -Type the text you want me to send in response to /echotest: +Bot Admin \u203a modulestestbot \u203a echo \u203a echotest: Choose a field +[text \u2022 The message, sticker, or image to send in response to /echotest. | /admin modulestestbot echo echotest text] +[paginate \u2022 For multiline messages, display just one line at a time? | /admin modulestestbot echo echotest paginate] +[private \u2022 Send the message in group chats, or just in private? | /admin modulestestbot echo echotest private] [Back | /admin modulestestbot echo] """ - assert conversation.message('my message') == """\ + assert conversation.message('text') == """\ [chat_id=1000 disable_web_page_preview=True parse_mode=HTML] -Bot Admin \u203a modulestestbot \u203a echo: Choose a command +Bot Admin \u203a modulestestbot \u203a echo \u203a echotest \u203a text: Type a new value for text -/echotest now echoes my message. +The message, sticker, or image to send in response to /echotest. -Type the name of a command to add (like rules\u2014don't include a slash at the beginning!), or select an existing echo to remove. -[/echotest (my message) | /admin modulestestbot echo echotest remove] -[Back | /admin modulestestbot] +Type your new value, or type "off" to disable/reset to default. +[Back | /admin modulestestbot echo echotest] """ - assert conversation.message('/admin modulestestbot echo echotest new message') == """\ + assert conversation.message('my message') == """\ [chat_id=1000 disable_web_page_preview=True parse_mode=HTML] -Bot Admin \u203a modulestestbot \u203a echo: Choose a command - -Changed /echotest from my message to new message. +Bot Admin \u203a modulestestbot \u203a echo \u203a echotest: Choose a field -Type the name of a command to add (like rules\u2014don't include a slash at the beginning!), or select an existing echo to remove. -[/echotest (new message) | /admin modulestestbot echo echotest remove] -[Back | /admin modulestestbot] +Set text to my message. +[text \u2022 The message, sticker, or image to send in response to /echotest. | /admin modulestestbot echo echotest text] +[paginate \u2022 For multiline messages, display just one line at a time? | /admin modulestestbot echo echotest paginate] +[private \u2022 Send the message in group chats, or just in private? | /admin modulestestbot echo echotest private] +[Back | /admin modulestestbot echo] """ - assert conversation.message('/admin modulestestbot echo echotest remove') == """\ + assert conversation.message('/admin modulestestbot echo echotest text new message') == """\ [chat_id=1000 disable_web_page_preview=True parse_mode=HTML] -Bot Admin \u203a modulestestbot \u203a echo: Choose a command +Bot Admin \u203a modulestestbot \u203a echo \u203a echotest: Choose a field -Removed /echotest (new message). - -Type the name of a command to add (like rules\u2014don't include a slash at the beginning!), or select an existing echo to remove. -[Back | /admin modulestestbot] +Changed text from my message to new message. +[text \u2022 The message, sticker, or image to send in response to /echotest. | /admin modulestestbot echo echotest text] +[paginate \u2022 For multiline messages, display just one line at a time? | /admin modulestestbot echo echotest paginate] +[private \u2022 Send the message in group chats, or just in private? | /admin modulestestbot echo echotest private] +[Back | /admin modulestestbot echo] """ - assert conversation.message('/admin modulestestbot echo bogus remove') == """\ + assert conversation.message('/admin modulestestbot echo') == """\ [chat_id=1000 disable_web_page_preview=True parse_mode=HTML] Bot Admin \u203a modulestestbot \u203a echo: Choose a command -/bogus is not echoing anything. - -Type the name of a command to add (like rules\u2014don't include a slash at the beginning!), or select an existing echo to remove. +Type the name of a command to add (like rules\u2014don't include a slash at the beginning!), or select an existing echo. +[/echotest (new message) | /admin modulestestbot echo echotest] [Back | /admin modulestestbot] """ diff --git a/metabot/util/adminui.py b/metabot/util/adminui.py index 644cf48..686b5f1 100644 --- a/metabot/util/adminui.py +++ b/metabot/util/adminui.py @@ -7,6 +7,13 @@ import pytz +def bool(unused_ctx, msg, subconf, field, unused_desc, unused_text): # pylint: disable=too-many-arguments,redefined-builtin + """Configure a toggle-able setting.""" + + subconf[field] = not subconf[field] + msg.add('Set %s to %s.', field, subconf[field]) + + def calendars(ctx, msg, subconf, field, desc, text): # pylint: disable=too-many-arguments """Configure a selection of calendars.""" diff --git a/setup.py b/setup.py index 9eb6f0e..8ddcc09 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ setuptools.setup( name='metabot', - version='0.1.0.2', + version='0.1.0.3', author='Daniel Reed', author_email='nmlorg@gmail.com', description='Modularized, multi-account bot.',