Added echo module

This commit is contained in:
Ville Ranki 2019-12-09 20:24:51 +02:00
parent b2ca334a51
commit a1b7d0b1ab
3 changed files with 96 additions and 6 deletions

View File

@ -1,5 +1,14 @@
# Hemppa - generic Matrix bot # Hemppa - generic Matrix bot
## Module list
Write !modulename in Matrix room where the bot is to use modules.
### Echo
Simple example module that just echoes what user said. Can be used as an
example for writing own modules.
## First ## First
* Create a Matrix user * Create a Matrix user

77
bot.py
View File

@ -1,14 +1,20 @@
import asyncio import asyncio
import os import os
import json import json
import glob
import traceback
import importlib
import sys
import re
from nio import (AsyncClient, RoomMessageText, RoomMessageUnknown, JoinError, InviteEvent) from nio import (AsyncClient, RoomMessageText, RoomMessageUnknown, JoinError, InviteEvent)
class Bot: class Bot:
client = None client = None
join_on_invite = False join_on_invite = False
modules = dict()
async def send_html(self, body, client, room): async def send_text(self, room, body):
msg = { msg = {
"body": body, "body": body,
"msgtype": "m.text" "msgtype": "m.text"
@ -16,14 +22,29 @@ class Bot:
await self.client.room_send(self.get_room_id(room), 'm.room.message', msg) await self.client.room_send(self.get_room_id(room), 'm.room.message', msg)
def get_room_id(self, room): def get_room_id(self, room):
for roomid in client.rooms: for roomid in self.client.rooms:
if self.client.rooms[roomid].named_room_name() == room.named_room_name(): if self.client.rooms[roomid].named_room_name() == room.named_room_name():
return roomid return roomid
print('Cannot find id for room', room.named_room_name(), ' - is the bot on it?') print('Cannot find id for room', room.named_room_name(), ' - is the bot on it?')
return None return None
async def message_cb(self, room, event): async def message_cb(self, room, event):
pass # Figure out the command
body = event.body
if len(body) == 0:
return
command = body.split().pop(0)
# Strip away non-alphanumeric characters, including leading ! for security
command = re.sub(r'\W+', '', command)
moduleobject = self.modules.get(command)
if "matrix_message" in dir(moduleobject):
try:
await moduleobject.matrix_message(bot, room, event)
except:
traceback.print_exc(file=sys.stderr)
async def unknown_cb(self, room, event): async def unknown_cb(self, room, event):
if event.msgtype != 'm.location': if event.msgtype != 'm.location':
@ -40,15 +61,56 @@ class Bot:
else: else:
break break
def load_module(self, modulename):
try:
module = importlib.import_module('modules.' + modulename)
cls = getattr(module, 'MatrixModule')
return cls()
except ModuleNotFoundError:
print('Module ', modulename, ' failed to load!')
traceback.print_exc(file=sys.stderr)
return None
def get_modules(self):
modulefiles = glob.glob('./modules/*.py')
for modulefile in modulefiles:
modulename = os.path.splitext(os.path.basename(modulefile))[0]
moduleobject = self.load_module(modulename)
if moduleobject:
self.modules[modulename] = moduleobject
def init(self): def init(self):
self.client = AsyncClient(os.environ['MATRIX_SERVER'], os.environ['MATRIX_USER']) self.client = AsyncClient(os.environ['MATRIX_SERVER'], os.environ['MATRIX_USER'])
self.client.access_token = os.getenv('MATRIX_ACCESS_TOKEN') self.client.access_token = os.getenv('MATRIX_ACCESS_TOKEN')
self.join_on_invite = os.getenv('JOIN_ON_INVITE') self.join_on_invite = os.getenv('JOIN_ON_INVITE')
self.get_modules()
print(f'Starting {len(self.modules)} modules..')
for modulename, moduleobject in self.modules.items():
print(modulename + '..')
if "matrix_start" in dir(moduleobject):
try:
moduleobject.matrix_start(bot)
except:
traceback.print_exc(file=sys.stderr)
def stop(self):
print(f'Stopping {len(self.modules)} modules..')
for modulename, moduleobject in self.modules.items():
print(modulename + '..')
if "matrix_stop" in dir(moduleobject):
try:
moduleobject.matrix_stop(bot)
except:
traceback.print_exc(file=sys.stderr)
async def run(self): async def run(self):
if not self.client.access_token: if not self.client.access_token:
await self.client.login(os.environ['MATRIX_PASSWORD']) await self.client.login(os.environ['MATRIX_PASSWORD'])
print("Logged in with password, access token:", client.access_token) print("Logged in with password, access token:", self.client.access_token)
await self.client.sync() await self.client.sync()
@ -66,5 +128,8 @@ class Bot:
bot = Bot() bot = Bot()
bot.init() bot.init()
try:
asyncio.get_event_loop().run_until_complete(bot.run()) asyncio.get_event_loop().run_until_complete(bot.run())
except KeyboardInterrupt:
pass
bot.stop()

16
modules/echo.py Normal file
View File

@ -0,0 +1,16 @@
class MatrixModule:
def matrix_start(self, bot):
print("Echo start!")
def matrix_stop(self, bot):
print("Echo stop!")
async def matrix_message(self, bot, room, event):
args = event.body.split()
args.pop(0)
# Echo what they said back
await bot.send_text(room, ' '.join(args))
def help(self):
return('Echoes back what user has said')