2020-02-09 15:24:57 +02:00
|
|
|
import collections
|
2021-04-22 04:17:37 +03:00
|
|
|
import json
|
2020-02-02 23:08:15 +02:00
|
|
|
from datetime import datetime
|
2020-02-09 15:07:05 +02:00
|
|
|
|
2020-02-02 23:08:15 +02:00
|
|
|
from modules.common.module import BotModule
|
|
|
|
|
|
|
|
|
|
|
|
class MatrixModule(BotModule):
|
2020-01-05 00:28:57 +02:00
|
|
|
|
2020-02-06 21:56:53 +02:00
|
|
|
def __init__(self, name):
|
|
|
|
super().__init__(name)
|
2020-02-09 15:07:05 +02:00
|
|
|
self.starttime = None
|
|
|
|
self.can_be_disabled = False
|
2020-02-06 01:19:45 +02:00
|
|
|
|
2020-01-06 00:33:42 +02:00
|
|
|
def matrix_start(self, bot):
|
2020-02-06 21:56:53 +02:00
|
|
|
super().matrix_start(bot)
|
2020-01-06 00:33:42 +02:00
|
|
|
self.starttime = datetime.now()
|
2021-01-23 22:11:42 +02:00
|
|
|
|
2020-01-05 00:28:57 +02:00
|
|
|
async def matrix_message(self, bot, room, event):
|
2021-04-22 04:17:37 +03:00
|
|
|
args = event.body.split(None, 2)
|
2020-02-09 15:07:05 +02:00
|
|
|
|
2020-11-24 23:02:47 +02:00
|
|
|
if len(args) == 2:
|
2020-02-02 23:08:15 +02:00
|
|
|
if args[1] == 'quit':
|
2020-02-03 23:45:14 +02:00
|
|
|
await self.quit(bot, room, event)
|
2020-02-02 23:08:15 +02:00
|
|
|
elif args[1] == 'version':
|
2020-02-03 23:45:14 +02:00
|
|
|
await self.version(bot, room)
|
2020-02-02 23:08:15 +02:00
|
|
|
elif args[1] == 'reload':
|
2020-02-03 23:45:14 +02:00
|
|
|
await self.reload(bot, room, event)
|
2020-02-02 23:08:15 +02:00
|
|
|
elif args[1] == 'status':
|
2020-02-03 23:45:14 +02:00
|
|
|
await self.status(bot, room)
|
2020-02-02 23:08:15 +02:00
|
|
|
elif args[1] == 'stats':
|
2020-02-03 23:45:14 +02:00
|
|
|
await self.stats(bot, room)
|
2020-02-02 23:08:15 +02:00
|
|
|
elif args[1] == 'leave':
|
2020-02-03 23:45:14 +02:00
|
|
|
await self.leave(bot, room, event)
|
2020-02-06 01:19:45 +02:00
|
|
|
elif args[1] == 'modules':
|
|
|
|
await self.show_modules(bot, room)
|
2021-04-22 04:17:37 +03:00
|
|
|
elif args[1] == 'export':
|
|
|
|
await self.export_settings(bot, event)
|
2020-02-06 01:19:45 +02:00
|
|
|
|
|
|
|
elif len(args) == 3:
|
|
|
|
if args[1] == 'enable':
|
|
|
|
await self.enable_module(bot, room, event, args[2])
|
|
|
|
elif args[1] == 'disable':
|
|
|
|
await self.disable_module(bot, room, event, args[2])
|
2021-04-22 04:17:37 +03:00
|
|
|
elif args[1] == 'export':
|
|
|
|
await self.export_settings(bot, event, module_name=args[2])
|
|
|
|
elif args[1] == 'import':
|
|
|
|
await self.import_settings(bot, event)
|
2020-01-05 00:28:57 +02:00
|
|
|
else:
|
2020-02-16 14:23:20 +02:00
|
|
|
pass
|
|
|
|
|
|
|
|
# TODO: Make this configurable. By default don't say anything.
|
|
|
|
# await bot.send_text(room, 'Unknown command, sorry.')
|
2020-01-05 00:28:57 +02:00
|
|
|
|
2020-02-03 23:45:14 +02:00
|
|
|
async def leave(self, bot, room, event):
|
|
|
|
bot.must_be_admin(room, event)
|
2020-02-08 23:16:19 +02:00
|
|
|
self.logger.info(f'{event.sender} asked bot to leave room {room.room_id}')
|
2020-02-03 23:45:14 +02:00
|
|
|
await bot.send_text(room, f'By your command.')
|
|
|
|
await bot.client.room_leave(room.room_id)
|
|
|
|
|
|
|
|
async def stats(self, bot, room):
|
|
|
|
roomcount = len(bot.client.rooms)
|
|
|
|
usercount = 0
|
|
|
|
homeservers = dict()
|
|
|
|
for croomid in bot.client.rooms:
|
|
|
|
roomobj = bot.client.rooms[croomid]
|
|
|
|
usercount = usercount + len(roomobj.users)
|
|
|
|
for user in roomobj.users:
|
|
|
|
hs = user.split(':')[1]
|
|
|
|
if homeservers.get(hs):
|
|
|
|
homeservers[hs] = homeservers[hs] + 1
|
|
|
|
else:
|
|
|
|
homeservers[hs] = 1
|
|
|
|
homeservers = sorted(homeservers.items(), key=lambda kv: (kv[1], kv[0]), reverse=True)
|
|
|
|
if len(homeservers) > 10:
|
|
|
|
homeservers = homeservers[0:10]
|
|
|
|
await bot.send_text(room,
|
|
|
|
f'I\'m seeing {usercount} users in {roomcount} rooms. Top ten homeservers: {homeservers}')
|
|
|
|
|
|
|
|
async def status(self, bot, room):
|
|
|
|
uptime = datetime.now() - self.starttime
|
|
|
|
await bot.send_text(room,
|
|
|
|
f'Uptime {uptime} - system time is {datetime.now()} - loaded {len(bot.modules)} modules.')
|
|
|
|
|
|
|
|
async def reload(self, bot, room, event):
|
2020-11-24 23:02:47 +02:00
|
|
|
bot.must_be_owner(event)
|
2020-02-03 23:45:14 +02:00
|
|
|
await bot.send_text(room, f'Reloading modules..')
|
|
|
|
bot.stop()
|
|
|
|
bot.reload_modules()
|
|
|
|
bot.start()
|
|
|
|
|
|
|
|
async def version(self, bot, room):
|
|
|
|
await bot.send_text(room, f'Hemppa version {bot.version} - https://github.com/vranki/hemppa')
|
|
|
|
|
|
|
|
async def quit(self, bot, room, event):
|
2020-11-24 23:02:47 +02:00
|
|
|
bot.must_be_owner(event)
|
2020-02-03 23:45:14 +02:00
|
|
|
await bot.send_text(room, f'Quitting, as requested')
|
2020-02-08 23:16:19 +02:00
|
|
|
self.logger.info(f'{event.sender} commanded bot to quit, so quitting..')
|
2020-02-03 23:45:14 +02:00
|
|
|
bot.bot_task.cancel()
|
|
|
|
|
2020-02-06 01:19:45 +02:00
|
|
|
async def enable_module(self, bot, room, event, module_name):
|
2020-11-24 23:02:47 +02:00
|
|
|
bot.must_be_owner(event)
|
|
|
|
self.logger.info(f"Asked to enable {module_name}")
|
2020-02-06 01:19:45 +02:00
|
|
|
if bot.modules.get(module_name):
|
|
|
|
module = bot.modules.get(module_name)
|
|
|
|
module.enable()
|
|
|
|
module.matrix_start(bot)
|
|
|
|
bot.save_settings()
|
|
|
|
await bot.send_text(room, f"module {module_name} enabled")
|
|
|
|
else:
|
|
|
|
await bot.send_text(room, f"module with name {module_name} not found. execute !bot modules for a list of available modules")
|
|
|
|
|
|
|
|
async def disable_module(self, bot, room, event, module_name):
|
2020-11-24 23:02:47 +02:00
|
|
|
bot.must_be_owner(event)
|
2020-02-08 23:16:19 +02:00
|
|
|
self.logger.info(f"asked to disable {module_name}")
|
2020-02-06 01:19:45 +02:00
|
|
|
if bot.modules.get(module_name):
|
|
|
|
module = bot.modules.get(module_name)
|
2020-02-09 15:07:05 +02:00
|
|
|
if module.can_be_disabled:
|
|
|
|
module.disable()
|
|
|
|
module.matrix_stop(bot)
|
|
|
|
bot.save_settings()
|
|
|
|
await bot.send_text(room, f"module {module_name} disabled")
|
|
|
|
else:
|
|
|
|
await bot.send_text(room, f"module {module_name} cannot be disabled")
|
2020-02-06 01:19:45 +02:00
|
|
|
else:
|
|
|
|
await bot.send_text(room, f"module with name {module_name} not found. execute !bot modules for a list of available modules")
|
|
|
|
|
|
|
|
async def show_modules(self, bot, room):
|
2021-01-23 22:11:42 +02:00
|
|
|
modules_message = "Modules:\n"
|
2020-02-09 15:24:57 +02:00
|
|
|
for modulename, module in collections.OrderedDict(sorted(bot.modules.items())).items():
|
2020-02-10 01:04:34 +02:00
|
|
|
state = 'Enabled' if module.enabled else 'Disabled'
|
2021-01-23 22:11:42 +02:00
|
|
|
modules_message += f"{state}: {modulename} - {module.help()}\n"
|
|
|
|
await bot.send_text(room, modules_message)
|
2020-02-06 01:19:45 +02:00
|
|
|
|
2021-04-22 04:17:37 +03:00
|
|
|
async def export_settings(self, bot, event, module_name=None):
|
|
|
|
bot.must_be_owner(event)
|
|
|
|
data = bot.get_account_data()['module_settings']
|
|
|
|
if module_name:
|
|
|
|
data = data[module_name]
|
|
|
|
self.logger.info(f"{event.sender} is exporting settings for module {module_name}")
|
|
|
|
else:
|
|
|
|
self.logger.info(f"{event.sender} is exporting all settings")
|
|
|
|
await bot.send_msg(event.sender, f'Private message from {bot.matrix_user}', json.dumps(data))
|
|
|
|
|
|
|
|
async def import_settings(self, bot, event):
|
|
|
|
bot.must_be_owner(event)
|
|
|
|
|
|
|
|
self.logger.info(f"{event.sender} is importing settings")
|
|
|
|
try:
|
|
|
|
account_data = bot.get_account_data()
|
|
|
|
child = account_data['module_settings']
|
|
|
|
except KeyError: # no data yet
|
|
|
|
account_data['module_settings'] = dict()
|
|
|
|
child = account_data['module_settings']
|
|
|
|
|
|
|
|
key = None
|
|
|
|
data = event.body.split(None, 2)[2]
|
|
|
|
while not data.startswith('{'):
|
|
|
|
key, data = data.split(None, 1)
|
|
|
|
if child.get(key):
|
|
|
|
child = child[key]
|
|
|
|
key = None
|
|
|
|
else:
|
|
|
|
break
|
|
|
|
data = json.loads(data)
|
|
|
|
|
|
|
|
if not key:
|
|
|
|
child.update(data)
|
|
|
|
else:
|
|
|
|
child[key] = data
|
|
|
|
bot.load_settings(account_data)
|
|
|
|
bot.save_settings()
|
|
|
|
await bot.send_msg(event.sender, f'Private message from {bot.matrix_user}', 'Updated bot settings')
|
|
|
|
|
2020-01-05 00:28:57 +02:00
|
|
|
def help(self):
|
2020-02-06 01:19:45 +02:00
|
|
|
return 'Bot management commands. (quit, version, reload, status, stats, leave, modules, enable, disable)'
|
2021-04-12 22:39:23 +03:00
|
|
|
|
|
|
|
def long_help(self, bot=None, event=None, **kwargs):
|
|
|
|
text = self.help() + (
|
|
|
|
'\n- "!bot version": get bot version'
|
|
|
|
'\n- "!bot status": get bot uptime and status'
|
|
|
|
'\n- "!bot stats": get current users, rooms, and homeservers')
|
|
|
|
if bot and event and bot.is_owner(event):
|
|
|
|
text += ('\n- "!bot quit": kill the bot :('
|
|
|
|
'\n- "!bot reload": reload the bot modules'
|
|
|
|
'\n- "!bot enable [module]": enable a module'
|
|
|
|
'\n- "!bot disable [module]": disable a module')
|
|
|
|
return text
|
|
|
|
|