commit to not forget code
This commit is contained in:
parent
804bc24908
commit
b774e0d04c
51
glados.py
Normal file
51
glados.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*
|
||||||
|
|
||||||
|
from matrix_client.client import MatrixClient
|
||||||
|
from matrix_client.api import MatrixRequestError
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
config = __import__(sys.argv[1])
|
||||||
|
else:
|
||||||
|
import config
|
||||||
|
|
||||||
|
class Bot:
|
||||||
|
def __init__(self):
|
||||||
|
self.client = MatrixClient(config.BOT_SERVER)
|
||||||
|
try:
|
||||||
|
self.client.login_with_password(config.BOT_USERNAME, config.BOT_PASSWORD)
|
||||||
|
except MatrixRequestError as e:
|
||||||
|
print(e)
|
||||||
|
if e.code == 403:
|
||||||
|
print("Bad username/password")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
self.plugin_manager = PluginManager(self, config)
|
||||||
|
self.rooms = {}
|
||||||
|
for room_id, room_data in config.rooms.items():
|
||||||
|
self.rooms[room_id] = self.client.join_room(room_id)
|
||||||
|
self.rooms[room_id].add_listener(self.callback)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.client.start_listener_thread()
|
||||||
|
#return client.sync_thread
|
||||||
|
|
||||||
|
while True:
|
||||||
|
input()
|
||||||
|
|
||||||
|
def callback(self, room, event):
|
||||||
|
if "@" + config.BOT_USERNAME in event['sender']:
|
||||||
|
return
|
||||||
|
|
||||||
|
if event['type'] == "m.room.message":
|
||||||
|
self.plugin_manager.notify_message(room, event)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
bot = Bot()
|
||||||
|
bot.run()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
0
plugins/__init__.py
Normal file
0
plugins/__init__.py
Normal file
23
plugins/admin.py
Normal file
23
plugins/admin.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from plugins.plugin import Plugin
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
class Admin(Plugin):
|
||||||
|
def activate(self):
|
||||||
|
super(Admin, self).activate()
|
||||||
|
|
||||||
|
def deactivate(self):
|
||||||
|
super(Admin, self).deactivate()
|
||||||
|
|
||||||
|
@Plugin.command(admin=True)
|
||||||
|
def admin_reload_plugins(self, msg, args):
|
||||||
|
"""Reload plugins"""
|
||||||
|
self.plugin_manager.reload_plugins()
|
||||||
|
return "Plugins reloaded"
|
||||||
|
|
||||||
|
@Plugin.command(admin=True)
|
||||||
|
def admin_test(self, msg, args):
|
||||||
|
"""Simple test"""
|
||||||
|
return "You are admin"
|
31
plugins/help.py
Normal file
31
plugins/help.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from plugins.plugin import Plugin
|
||||||
|
|
||||||
|
|
||||||
|
class Help(Plugin):
|
||||||
|
def activate(self):
|
||||||
|
super(Help, self).activate()
|
||||||
|
|
||||||
|
def deactivate(self):
|
||||||
|
super(Help, self).deactivate()
|
||||||
|
|
||||||
|
@Plugin.command()
|
||||||
|
def help(self, room, event, args):
|
||||||
|
"""Show list of commands (or only CMD) doc => !help [CMD]"""
|
||||||
|
command_names = []
|
||||||
|
if len(args) >= 1:
|
||||||
|
help_command = ' '.join(args)
|
||||||
|
if help_command[0] != '!':
|
||||||
|
help_command = '!' + help_command
|
||||||
|
if help_command in self.plugin_manager.commands.keys():
|
||||||
|
command_names = [help_command]
|
||||||
|
if not command_names:
|
||||||
|
command_names = self.plugin_manager.commands.keys()
|
||||||
|
reply = ['Usage:']
|
||||||
|
for command_name in command_names:
|
||||||
|
command = self.plugin_manager.commands[command_name]
|
||||||
|
if not self.plugin_manager.is_admin_command(command_name) or self.plugin_manager.is_sender_admin(msg):
|
||||||
|
reply.append('{0}: {1}'.format(command_name, command['function'].__doc__ or 'N/A'))
|
||||||
|
room.send_text("\n".join(reply))
|
||||||
|
return True
|
22
plugins/plugin.py
Normal file
22
plugins/plugin.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(object):
|
||||||
|
def __init__(self, plugin_manager):
|
||||||
|
self.plugin_manager = plugin_manager
|
||||||
|
|
||||||
|
def activate(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def deactivate(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def notify_message(self, room, event):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def command(*args, **options):
|
||||||
|
def decorator(f):
|
||||||
|
f._plugin_command = {'options': options}
|
||||||
|
return f
|
||||||
|
return decorator
|
109
plugins/plugin_manager.py
Normal file
109
plugins/plugin_manager.py
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import importlib
|
||||||
|
import inspect
|
||||||
|
from collections import OrderedDict
|
||||||
|
from plugins.plugin import Plugin
|
||||||
|
|
||||||
|
|
||||||
|
class PluginManager:
|
||||||
|
def __init__(self, bot, config):
|
||||||
|
self.bot = bot
|
||||||
|
self.config = config
|
||||||
|
self.plugins = OrderedDict()
|
||||||
|
self.commands = OrderedDict()
|
||||||
|
self.command_names = []
|
||||||
|
|
||||||
|
def load_plugin(self, name):
|
||||||
|
mod = importlib.import_module('plugins.{0}'.format(name))
|
||||||
|
|
||||||
|
classes = inspect.getmembers(mod, inspect.isclass)
|
||||||
|
|
||||||
|
for class_name, c in classes:
|
||||||
|
if c != Plugin and issubclass(c, Plugin):
|
||||||
|
self.plugins[name] = c(self)
|
||||||
|
self.plugins[name]._module = mod
|
||||||
|
for method_name, method in inspect.getmembers(self.plugins[name], inspect.ismethod):
|
||||||
|
if getattr(method, '_plugin_command', False):
|
||||||
|
options = method._plugin_command['options']
|
||||||
|
command = options.pop('command', None)
|
||||||
|
if command is None:
|
||||||
|
command = ' '.join(method.__name__.split('_'))
|
||||||
|
self.add_command(command, method, **options)
|
||||||
|
self.plugins[name].config = self.config
|
||||||
|
|
||||||
|
# Only for debug
|
||||||
|
def reload_plugins(self):
|
||||||
|
plugin_names = self.plugins.keys()
|
||||||
|
self.deactivate_plugins()
|
||||||
|
importlib.invalidate_caches()
|
||||||
|
|
||||||
|
# Force rebuilding modules
|
||||||
|
for plugin in self.plugins.values():
|
||||||
|
importlib.reload(plugin._module)
|
||||||
|
|
||||||
|
self.plugins = OrderedDict()
|
||||||
|
self.commands = OrderedDict()
|
||||||
|
self.command_names = []
|
||||||
|
|
||||||
|
for plugin_name in plugin_names:
|
||||||
|
self.load_plugin(plugin_name)
|
||||||
|
|
||||||
|
self.activate_plugins()
|
||||||
|
|
||||||
|
def activate_plugins(self):
|
||||||
|
for k, plugin in self.plugins.items():
|
||||||
|
plugin.activate()
|
||||||
|
|
||||||
|
def deactivate_plugins(self):
|
||||||
|
for k, plugin in self.plugins.items():
|
||||||
|
plugin.deactivate()
|
||||||
|
|
||||||
|
def notify_message(self, room, event, private=False):
|
||||||
|
# for k, plugin in self.plugins.items():
|
||||||
|
# reply = plugin.notify_message(event, private)
|
||||||
|
# if reply:
|
||||||
|
# self.bot.send_message(mto=message['from'].full if private else message['from'].bare, mbody=reply, mtype='chat' if private else 'groupchat')
|
||||||
|
body = event['content']['body']
|
||||||
|
if body.startswith('!'):
|
||||||
|
command_found = False
|
||||||
|
for command in self.command_names:
|
||||||
|
command_chain = command.split(' ')
|
||||||
|
body_chain = body.split(' ')
|
||||||
|
if len(body_chain) >= len(command_chain) and body_chain[:len(command_chain)] == command_chain:
|
||||||
|
admin_needed = self.commands[command]['options'].get('admin', False)
|
||||||
|
if admin_needed and not self.is_sender_admin(event):
|
||||||
|
reply = "Unauthorized"
|
||||||
|
else:
|
||||||
|
args = [a for a in body[len(command):].strip().split(' ') if a]
|
||||||
|
f = self.commands[command]['function']
|
||||||
|
reply = f(room, event, args)
|
||||||
|
command_found = True
|
||||||
|
break
|
||||||
|
if not command_found:
|
||||||
|
reply = 'Unknown command'
|
||||||
|
if reply and isinstance(reply, str):
|
||||||
|
room.send_text(reply)
|
||||||
|
|
||||||
|
def is_sender_admin(self, event):
|
||||||
|
return False
|
||||||
|
"""Checks if author is admin"""
|
||||||
|
if message['type'] == 'groupchat':
|
||||||
|
# We don't know the jid. Either there's a problem or it's an anonymous room
|
||||||
|
if message['from'].full not in self.bot.presences:
|
||||||
|
return False
|
||||||
|
jid = self.bot.presences[message['from'].full]
|
||||||
|
else:
|
||||||
|
jid = message['from'].full.split('/')[0]
|
||||||
|
return jid in self.config.ADMINS
|
||||||
|
|
||||||
|
def is_admin_command(self, command):
|
||||||
|
return command in self.commands and self.commands[command]['options'].get('admin', False)
|
||||||
|
|
||||||
|
def add_command(self, command, function, **options):
|
||||||
|
# TODO: check the command doesn't exist. If not, try another name
|
||||||
|
command_name = '!{0}'.format(command)
|
||||||
|
class_name = inspect.getmro(function.__self__.__class__)[0].__name__
|
||||||
|
self.commands[command_name] = {'function': function, 'class': class_name, 'options': options}
|
||||||
|
self.command_names.append(command_name)
|
||||||
|
self.command_names.sort(key=len, reverse=True)
|
27
plugins/say.py
Normal file
27
plugins/say.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from plugins.plugin import Plugin
|
||||||
|
|
||||||
|
|
||||||
|
class Say(Plugin):
|
||||||
|
def activate(self):
|
||||||
|
super(Say, self).activate()
|
||||||
|
|
||||||
|
def deactivate(self):
|
||||||
|
super(Say, self).deactivate()
|
||||||
|
|
||||||
|
@Plugin.command()
|
||||||
|
def say(self, room, event, args):
|
||||||
|
"""Make glados say something => !say SOMETHING"""
|
||||||
|
if len(args) < 1:
|
||||||
|
return Say.say.__doc__
|
||||||
|
|
||||||
|
room.send_text(' '.join(args[0:]))
|
||||||
|
|
||||||
|
@Plugin.command()
|
||||||
|
def rsay(self, room, event, args):
|
||||||
|
"""Make glados say something on a given room => !say ROOM_JID SOMETHING"""
|
||||||
|
if len(args) < 2:
|
||||||
|
return Say.say.__doc__
|
||||||
|
|
||||||
|
return {'to': args[0], 'msg': ' '.join(args[1:])}
|
Loading…
x
Reference in New Issue
Block a user