Skip to content

Commit

Permalink
Explicitly mark whether to paginate and/or force echo responses to be…
Browse files Browse the repository at this point in the history
… private (see #41).

Create a new adminui widget to handle toggles.

A followup should tweak adminui.fields (or maybe the code in echo.admin that generates fields?) to
show what the current values for paginate and private are (right now you can only tell by toggling
them (twice)). I almost went ahead and added an adminui.multiline widget (see #29), but backed out
at the last minute.
  • Loading branch information
nmlorg committed May 14, 2019
1 parent 6223d4c commit 85ec3e1
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 81 deletions.
16 changes: 13 additions & 3 deletions metabot/botconf.py
Expand Up @@ -27,30 +27,40 @@ 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)
if data:
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)
for k in ('title', 'type', 'username'):
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):
if modname != 'issue37':
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
Expand Down
73 changes: 34 additions & 39 deletions metabot/modules/echo.py
Expand Up @@ -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))
Expand All @@ -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 (<code>%s</code>).', command, modconf[command])
modconf.pop(command)
command = message = None
else:
if command in modconf:
msg.add('Changed /%s from <code>%s</code> to <code>%s</code>.', command,
modconf[command], message)
else:
msg.add('/%s now echoes <code>%s</code>.', 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 <code>rules</code>\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 <code>/%s</code>:', 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)
96 changes: 58 additions & 38 deletions metabot/modules/test_echo.py
Expand Up @@ -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]
Expand Down Expand Up @@ -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]
Expand All @@ -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: <b>Choose a command</b>
Type the name of a command to add (like <code>rules</code>\u2014don't include a slash at the beginning!), or select an existing echo to remove.
Type the name of a command to add (like <code>rules</code>\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: <b>Type the message for /echotest</b>
Type the text you want me to send in response to <code>/echotest</code>:
Bot Admin \u203a modulestestbot \u203a echo \u203a echotest: <b>Choose a field</b>
[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: <b>Choose a command</b>
Bot Admin \u203a modulestestbot \u203a echo \u203a echotest \u203a text: <b>Type a new value for text</b>
/echotest now echoes <code>my message</code>.
The message, sticker, or image to send in response to /echotest.
Type the name of a command to add (like <code>rules</code>\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: <b>Choose a command</b>
Changed /echotest from <code>my message</code> to <code>new message</code>.
Bot Admin \u203a modulestestbot \u203a echo \u203a echotest: <b>Choose a field</b>
Type the name of a command to add (like <code>rules</code>\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 <code>text</code> to <code>my message</code>.
[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: <b>Choose a command</b>
Bot Admin \u203a modulestestbot \u203a echo \u203a echotest: <b>Choose a field</b>
Removed /echotest (<code>new message</code>).
Type the name of a command to add (like <code>rules</code>\u2014don't include a slash at the beginning!), or select an existing echo to remove.
[Back | /admin modulestestbot]
Changed <code>text</code> from <code>my message</code> to <code>new message</code>.
[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: <b>Choose a command</b>
/bogus is not echoing anything.
Type the name of a command to add (like <code>rules</code>\u2014don't include a slash at the beginning!), or select an existing echo to remove.
Type the name of a command to add (like <code>rules</code>\u2014don't include a slash at the beginning!), or select an existing echo.
[/echotest (new message) | /admin modulestestbot echo echotest]
[Back | /admin modulestestbot]
"""
7 changes: 7 additions & 0 deletions metabot/util/adminui.py
Expand Up @@ -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 <code>%s</code> to <code>%s</code>.', field, subconf[field])


def calendars(ctx, msg, subconf, field, desc, text): # pylint: disable=too-many-arguments
"""Configure a selection of calendars."""

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -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.',
Expand Down

0 comments on commit 85ec3e1

Please sign in to comment.