Skip to content

Commit

Permalink
WIP: Have metabot.modules.admin.default use metabot.util.adminui.fiel…
Browse files Browse the repository at this point in the history
…ds instead of custom code to select a module.

This changes the signature of all MODULE.admin functions to contain the parent's conf object (so modconf becomes botconf), the current frame's field's name in that conf (modconf = botconf[field]), and the current frame's description (currently unused).

Followups will likely continue this to have admin.default use adminui.fields even earlier (for bot selection), as well as places like moderator.admin (for group selection), but doing so would currently require the functions to be split into multiple callables. Thought should be given as to whether to go ahead and break adminui.fields into a callable adminui.Menu (as sort of a partial function).

This also requires field descriptions to be calculated every time the fields are processed, even if the descriptions are never used. Thought should be given as to whether to actually separate the field name and type list from the description list, or to maybe do something like:

    ('fieldname', adminui.fieldtype, lambda: 'field description'),

i.e. make the desc a callable. There's a similar concern about a theoretical invalid_msg and empty_msg standardization for adminui.fields (or adminui.Menu):  Right now admin.default actually opens a file on disk every time it displays the theoretical invalid_msg. If this becomes a string passed to adminui.fields/Menu, the file will be read every time the user navigates anywhere within /admin (not just at the top-level bot selection menu).

See #63.
  • Loading branch information
nmlorg committed Jul 4, 2019
1 parent d32e979 commit 225d002
Show file tree
Hide file tree
Showing 10 changed files with 37 additions and 34 deletions.
33 changes: 11 additions & 22 deletions metabot/modules/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import uuid

from metabot.util import adminui

BOOTSTRAP_TOKEN = uuid.uuid4().hex


Expand Down Expand Up @@ -37,7 +39,7 @@ def default(ctx, msg): # pylint: disable=missing-docstring

msg.path('/admin', 'Bot Admin')

username, modname, text = ctx.split(3)
username, text = ctx.split(2)

if username not in bots:
msg.action = 'Choose a bot'
Expand All @@ -53,33 +55,19 @@ def default(ctx, msg): # pylint: disable=missing-docstring
return

msg.path(username)
ctx.targetbotuser = username
ctx.targetbotconf = ctx.bot.multibot.conf['bots'][username]

modules = {
modname: module
for modname, module in ctx.bot.multibot.modules.items()
if hasattr(module, 'admin')
}
modules = sorted((modname, module.admin, module.__doc__.splitlines()[0].rstrip('.'))
for modname, module in ctx.bot.multibot.modules.items()
if hasattr(module, 'admin'))

if not modules: # pragma: no cover
return msg.add(
"Hi! There aren't any configurable modules installed. Contact a metabot admin to "
'install one.')

if modname not in modules:
msg.action = 'Choose a module'
for modname, module in sorted(modules.items()):
label = modname
if getattr(module, '__doc__', None):
label = '%s \u2022 %s' % (label, module.__doc__.splitlines()[0].rstrip('.'))
msg.button(label, '/admin %s %s' % (username, modname))
return

msg.path(modname)

admin_callback = modules[modname].admin
ctx.targetbotuser = username
ctx.targetbotconf = ctx.bot.multibot.conf['bots'][username]
return admin_callback(ctx, msg, ctx.targetbotconf['issue37'][modname], text)
return adminui.fields(ctx, msg, ctx.targetbotconf['issue37'], modules, text, what='module')


def bootstrap(ctx, msg, modconf):
Expand All @@ -90,9 +78,10 @@ def bootstrap(ctx, msg, modconf):
msg.add('Added %s to the admin list.', ctx.user['id'])


def admin(ctx, msg, modconf, text): # pylint: disable=too-many-branches
def admin(ctx, msg, botconf, field, unused_desc, text): # pylint: disable=too-many-branches
"""Handle /admin BOTNAME admin (configure the admin module itself)."""

modconf = botconf[field]
if 'admins' not in modconf: # pragma: no cover
modconf['admins'] = []

Expand Down
3 changes: 2 additions & 1 deletion metabot/modules/countdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,10 @@ def format_delta(seconds):
return '<b>NOW</b>'


def admin(unused_ctx, msg, modconf, text):
def admin(unused_ctx, msg, botconf, field, unused_desc, text):
"""Handle /admin BOTNAME countdown."""

modconf = botconf[field]
command, _, timestamp = text.partition(' ')
command = command.lower()

Expand Down
3 changes: 2 additions & 1 deletion metabot/modules/echo.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ def echo(ctx, msg, data): # pylint: disable=missing-docstring
msg.button('More (%i/%i)' % (page, len(lines)), '/%s %i' % (ctx.command, page + 1))


def admin(ctx, msg, modconf, text):
def admin(ctx, msg, botconf, field, unused_desc, text):
"""Handle /admin BOTNAME echo."""

modconf = botconf[field]
command, _, text = text.partition(' ')
command = command.lower()

Expand Down
3 changes: 2 additions & 1 deletion metabot/modules/groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,10 @@ def inline(ctx, modconf):
ctx.reply_inline(results, cache_time=60)


def admin(ctx, msg, modconf, text):
def admin(ctx, msg, botconf, field, unused_desc, text):
"""Handle /admin BOTNAME groups."""

modconf = botconf[field]
if text.startswith('remove '):
text = text[len('remove '):]
group = modconf['groups'].pop(text)
Expand Down
3 changes: 2 additions & 1 deletion metabot/modules/help.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ def default(ctx, msg, modconf): # pylint: disable=missing-docstring
msg.add('%s', line)


def admin(ctx, msg, modconf, text): # pylint: disable=too-many-branches
def admin(ctx, msg, botconf, field, unused_desc, text): # pylint: disable=too-many-branches
"""Handle /admin BOTNAME help."""

modconf = botconf[field]
action, _, modname = text.partition(' ')

hidden = set(modconf.get('hidden', '').split())
Expand Down
13 changes: 11 additions & 2 deletions metabot/modules/moderator.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,13 @@ def moddispatch(ctx, msg, modconf): # pylint: disable=missing-docstring
ctx.private = True
msg.path('/mod', 'Group Admin')
ctx.targetbotconf = ctx.bot.config
return admin(ctx, msg, modconf, ctx.text, botadmin=False)
return admin(ctx,
msg,
ctx.bot.config['issue37'],
'moderator',
'Group Admin',
ctx.text,
botadmin=False)

return False

Expand Down Expand Up @@ -105,17 +111,20 @@ def join(ctx, msg, modconf):
msg.add(greeting)


def admin(ctx, msg, modconf, text, botadmin=True):
def admin(ctx, msg, botconf, field, unused_desc, text, botadmin=True): # pylint: disable=too-many-arguments
"""Handle /admin BOTNAME moderator."""

modconf = botconf[field]
groups = sorted(
group_id for group_id in modconf
if botadmin or ctx.user['id'] in ctx.bot.multibot.conf['groups'][int(group_id)]['admins'])

if not groups:
if botadmin:
msg.action = 'Add me to a group'
return msg.add(
"I'm not in any groups! Add me to an existing group from its details screen.")
msg.action = 'Become a group admin'
return msg.add(
"Hi! You aren't an admin in any groups I'm in. If you should be, ask a current admin "
"to promote you from the group's members list.")
Expand Down
3 changes: 2 additions & 1 deletion metabot/modules/telegram.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
"""Manage the bot's Telegram state."""


def admin(ctx, msg, modconf, text):
def admin(ctx, msg, botconf, field, unused_desc, text):
"""Handle /admin BOTNAME telegram (manage the bot's Telegram state)."""

modconf = botconf[field]
username = ctx.targetbotuser
msg.action = 'Choose an action'

Expand Down
2 changes: 1 addition & 1 deletion metabot/modules/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def test_default(conversation): # pylint: disable=redefined-outer-name
assert conversation.message('/admin modulestestbot') == """\
[chat_id=1000 disable_web_page_preview=True parse_mode=HTML]
Bot Admin › modulestestbot: <b>Choose a module</b>
[admin • Manage the admin list | /admin modulestestbot admin]
[admin (…) • Manage the admin list | /admin modulestestbot admin]
[help • Return the list of commands and other bot features | /admin modulestestbot help]
[Back | /admin]
"""
Expand Down
4 changes: 2 additions & 2 deletions metabot/modules/test_moderator.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def test_mod(conversation): # pylint: disable=redefined-outer-name

assert conversation.message('/mod', user_id=2000) == """\
[chat_id=2000 disable_web_page_preview=True parse_mode=HTML]
Group Admin
Group Admin: <b>Become a group admin</b>
Hi! You aren't an admin in any groups I'm in. If you should be, ask a current admin to promote you from the group's members list.
"""
Expand Down Expand Up @@ -73,7 +73,7 @@ def test_admin(conversation): # pylint: disable=redefined-outer-name

assert conversation.message('/admin modulestestbot moderator') == """\
[chat_id=1000 disable_web_page_preview=True parse_mode=HTML]
Bot Admin › modulestestbot › moderator
Bot Admin › modulestestbot › moderator: <b>Add me to a group</b>
I'm not in any groups! Add me to an existing group from its details screen.
[Back | /admin modulestestbot]
Expand Down
4 changes: 2 additions & 2 deletions metabot/util/adminui.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def daysofweek(unused_ctx, msg, subconf, field, desc, text): # pylint: disable=
msg.buttons(buttons)


def fields(ctx, msg, subconf, fieldset, text): # pylint: disable=too-many-arguments
def fields(ctx, msg, subconf, fieldset, text, what='field'): # pylint: disable=too-many-arguments
"""Present a menu of fields to edit."""

field, _, text = text.partition(' ')
Expand All @@ -139,7 +139,7 @@ def fields(ctx, msg, subconf, fieldset, text): # pylint: disable=too-many-argum
msg.add("I can't set <code>%s</code>.", field)

if not msg.action:
msg.action = 'Choose a field'
msg.action = 'Choose a ' + what
for fieldname, uifunc, fielddesc in fieldset:
value = subconf.get(fieldname)
if uifunc is bool:
Expand Down

0 comments on commit 225d002

Please sign in to comment.