add stop and start message to BotModule class. add remove_callback

This commit is contained in:
Frank Becker 2020-02-06 20:56:53 +01:00
parent b1f428517e
commit 2f9d7a708e
10 changed files with 81 additions and 64 deletions

72
bot.py
View File

@ -53,6 +53,12 @@ class Bot:
} }
await self.client.room_send(room.room_id, 'm.room.message', msg) await self.client.room_send(room.room_id, 'm.room.message', msg)
def remove_callback(self, callback):
for cb_object in bot.client.event_callbacks:
if cb_object.func == callback:
print("remove callback")
bot.client.event_callbacks.remove(cb_object)
def get_room_by_id(self, room_id): def get_room_by_id(self, room_id):
return self.client.rooms[room_id] return self.client.rooms[room_id]
@ -82,11 +88,10 @@ class Bot:
def save_settings(self): def save_settings(self):
module_settings = dict() module_settings = dict()
for modulename, moduleobject in self.modules.items(): for modulename, moduleobject in self.modules.items():
if "get_settings" in dir(moduleobject): try:
try: module_settings[modulename] = moduleobject.get_settings()
module_settings[modulename] = moduleobject.get_settings() except Exception:
except Exception: traceback.print_exc(file=sys.stderr)
traceback.print_exc(file=sys.stderr)
data = {self.appid: self.version, 'module_settings': module_settings} data = {self.appid: self.version, 'module_settings': module_settings}
self.set_account_data(data) self.set_account_data(data)
@ -97,12 +102,11 @@ class Bot:
return return
for modulename, moduleobject in self.modules.items(): for modulename, moduleobject in self.modules.items():
if data['module_settings'].get(modulename): if data['module_settings'].get(modulename):
if "set_settings" in dir(moduleobject): try:
try: moduleobject.set_settings(
moduleobject.set_settings( data['module_settings'][modulename])
data['module_settings'][modulename]) except Exception:
except Exception: traceback.print_exc(file=sys.stderr)
traceback.print_exc(file=sys.stderr)
async def message_cb(self, room, event): async def message_cb(self, room, event):
# Figure out the command # Figure out the command
@ -119,7 +123,7 @@ class Bot:
moduleobject = self.modules.get(command) moduleobject = self.modules.get(command)
if moduleobject.enabled and ("matrix_message" in dir(moduleobject)): if moduleobject.enabled:
try: try:
await moduleobject.matrix_message(bot, room, event) await moduleobject.matrix_message(bot, room, event)
except CommandRequiresAdmin: except CommandRequiresAdmin:
@ -154,7 +158,7 @@ class Bot:
module = importlib.import_module('modules.' + modulename) module = importlib.import_module('modules.' + modulename)
module = reload(module) module = reload(module)
cls = getattr(module, 'MatrixModule') cls = getattr(module, 'MatrixModule')
return cls() return cls(modulename)
except ModuleNotFoundError: except ModuleNotFoundError:
print('Module ', modulename, ' failed to load!') print('Module ', modulename, ' failed to load!')
traceback.print_exc(file=sys.stderr) traceback.print_exc(file=sys.stderr)
@ -184,11 +188,10 @@ class Bot:
self.pollcount = self.pollcount + 1 self.pollcount = self.pollcount + 1
for modulename, moduleobject in self.modules.items(): for modulename, moduleobject in self.modules.items():
if moduleobject.enabled: if moduleobject.enabled:
if "matrix_poll" in dir(moduleobject): try:
try: await moduleobject.matrix_poll(bot, self.pollcount)
await moduleobject.matrix_poll(bot, self.pollcount) except Exception:
except Exception: traceback.print_exc(file=sys.stderr)
traceback.print_exc(file=sys.stderr)
await asyncio.sleep(10) await asyncio.sleep(10)
def set_account_data(self, data): def set_account_data(self, data):
@ -222,15 +225,14 @@ class Bot:
print("NOTE: check MATRIX_ACCESS_TOKEN or set MATRIX_PASSWORD") print("NOTE: check MATRIX_ACCESS_TOKEN or set MATRIX_PASSWORD")
sys.exit(2) sys.exit(2)
def init(self): def init(self):
self.matrix_user = os.getenv('MATRIX_USER') self.matrix_user = os.getenv('MATRIX_USER')
self.matrix_pass = os.getenv('MATRIX_PASSWORD') self.matrix_pass = os.getenv('MATRIX_PASSWORD')
matrix_server = os.getenv('MATRIX_SERVER') matrix_server = os.getenv('MATRIX_SERVER')
bot_owners = os.getenv('BOT_OWNERS') bot_owners = os.getenv('BOT_OWNERS')
access_token = os.getenv('MATRIX_ACCESS_TOKEN') access_token = os.getenv('MATRIX_ACCESS_TOKEN')
join_on_invite = os.getenv('JOIN_ON_INVITE') join_on_invite = os.getenv('JOIN_ON_INVITE')
if matrix_server and self.matrix_user and bot_owners: if matrix_server and self.matrix_user and bot_owners:
self.client = AsyncClient(matrix_server, self.matrix_user) self.client = AsyncClient(matrix_server, self.matrix_user)
@ -256,22 +258,18 @@ class Bot:
print(f'Starting {len(enabled_modules)} modules..') print(f'Starting {len(enabled_modules)} modules..')
for modulename, moduleobject in self.modules.items(): for modulename, moduleobject in self.modules.items():
if moduleobject.enabled: if moduleobject.enabled:
print('Starting', modulename, '..') try:
if "matrix_start" in dir(moduleobject): moduleobject.matrix_start(bot)
try: except Exception:
moduleobject.matrix_start(bot) traceback.print_exc(file=sys.stderr)
except Exception:
traceback.print_exc(file=sys.stderr)
def stop(self): def stop(self):
print(f'Stopping {len(self.modules)} modules..') print(f'Stopping {len(self.modules)} modules..')
for modulename, moduleobject in self.modules.items(): for modulename, moduleobject in self.modules.items():
print('Stopping', modulename, '..') try:
if "matrix_stop" in dir(moduleobject): moduleobject.matrix_stop(bot)
try: except Exception:
moduleobject.matrix_stop(bot) traceback.print_exc(file=sys.stderr)
except Exception:
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:

View File

@ -4,11 +4,12 @@ from modules.common.module import BotModule
class MatrixModule(BotModule): class MatrixModule(BotModule):
def __init__(self): def __init__(self, name):
super().__init__() super().__init__(name)
self.enable() self.enable()
def matrix_start(self, bot): def matrix_start(self, bot):
super().matrix_start(bot)
self.starttime = datetime.now() self.starttime = datetime.now()
async def matrix_message(self, bot, room, event): async def matrix_message(self, bot, room, event):

View File

@ -25,8 +25,9 @@ class BotModule(ABC):
""" """
def __init__(self): def __init__(self, name):
self.enabled = False self.enabled = False
self.name = name
def matrix_start(self, bot): def matrix_start(self, bot):
"""Called once on startup """Called once on startup
@ -34,7 +35,7 @@ class BotModule(ABC):
:param bot: a reference to the bot :param bot: a reference to the bot
:type bot: Bot :type bot: Bot
""" """
pass print('Starting', self.name, '..')
@abstractmethod @abstractmethod
async def matrix_message(self, bot, room, event): async def matrix_message(self, bot, room, event):
@ -55,7 +56,7 @@ class BotModule(ABC):
:param bot: a reference to the bot :param bot: a reference to the bot
:type bot: Bot :type bot: Bot
""" """
pass print('Stopping', self.name, '..')
async def matrix_poll(self, bot, pollcount): async def matrix_poll(self, bot, pollcount):
"""Called every 10 seconds """Called every 10 seconds

View File

@ -5,7 +5,8 @@ from modules.common.module import BotModule
class PollingService(BotModule): class PollingService(BotModule):
def __init__(self): def __init__(self, name):
super().__init__(name)
self.known_ids = set() self.known_ids = set()
self.account_rooms = dict() # Roomid -> [account, account..] self.account_rooms = dict() # Roomid -> [account, account..]
self.next_poll_time = dict() # Roomid -> datetime, None = not polled yet self.next_poll_time = dict() # Roomid -> datetime, None = not polled yet

View File

@ -21,13 +21,17 @@ from modules.common.module import BotModule
class MatrixModule(BotModule): class MatrixModule(BotModule):
def matrix_start(self, bot): def __init__(self, name):
self.bot = bot super().__init__(name)
self.SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
self.credentials_file = "credentials.json" self.credentials_file = "credentials.json"
self.SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
self.bot = None
self.service = None self.service = None
self.calendar_rooms = dict() # Contains room_id -> [calid, calid] .. self.calendar_rooms = dict() # Contains room_id -> [calid, calid] ..
def matrix_start(self, bot):
super().matrix_start(bot)
self.bot = bot
creds = None creds = None
if not os.path.exists(self.credentials_file) or os.path.getsize(self.credentials_file) == 0: if not os.path.exists(self.credentials_file) or os.path.getsize(self.credentials_file) == 0:
@ -43,8 +47,7 @@ class MatrixModule(BotModule):
if creds and creds.expired and creds.refresh_token: if creds and creds.expired and creds.refresh_token:
creds.refresh(Request()) creds.refresh(Request())
else: else:
flow = InstalledAppFlow.from_client_secrets_file( flow = InstalledAppFlow.from_client_secrets_file(self.credentials_file, self.SCOPES)
self.credentials_file, self.SCOPES)
# urn:ietf:wg:oauth:2.0:oob # urn:ietf:wg:oauth:2.0:oob
creds = flow.run_local_server(port=0) creds = flow.run_local_server(port=0)
# Save the credentials for the next run # Save the credentials for the next run

View File

@ -3,8 +3,8 @@ from modules.common.module import BotModule
class MatrixModule(BotModule): class MatrixModule(BotModule):
def __init__(self): def __init__(self, name):
super().__init__() super().__init__(name)
self.enable() self.enable()
async def matrix_message(self, bot, room, event): async def matrix_message(self, bot, room, event):
@ -17,7 +17,7 @@ class MatrixModule(BotModule):
msg = msg + ' - ' + moduleobject.help() + '\n' msg = msg + ' - ' + moduleobject.help() + '\n'
except AttributeError: except AttributeError:
pass pass
msg + msg + '\n' msg = msg + '\n'
msg = msg + "\nAdd your own commands at https://github.com/vranki/hemppa" msg = msg + "\nAdd your own commands at https://github.com/vranki/hemppa"
await bot.send_text(room, msg) await bot.send_text(room, msg)

View File

@ -11,8 +11,8 @@ from modules.common.pollingservice import PollingService
class MatrixModule(PollingService): class MatrixModule(PollingService):
def __init__(self): def __init__(self, name):
super().__init__() super().__init__(name)
self.instagram = Instagram() self.instagram = Instagram()
self.service_name = 'Instagram' self.service_name = 'Instagram'

View File

@ -7,9 +7,14 @@ class MatrixModule(BotModule):
bot = None bot = None
def matrix_start(self, bot): def matrix_start(self, bot):
super().matrix_start(bot)
self.bot = bot self.bot = bot
bot.client.add_event_callback(self.unknown_cb, RoomMessageUnknown) bot.client.add_event_callback(self.unknown_cb, RoomMessageUnknown)
def matrix_stop(self, bot):
super().matrix_stop(bot)
bot.remove_callback(self.unknown_cb)
async def unknown_cb(self, room, event): async def unknown_cb(self, room, event):
if event.msgtype != 'm.location': if event.msgtype != 'm.location':
return return

View File

@ -9,8 +9,8 @@ from modules.common.pollingservice import PollingService
# https://github.com/taspinar/twitterscraper/tree/master/twitterscraper # https://github.com/taspinar/twitterscraper/tree/master/twitterscraper
class MatrixModule(PollingService): class MatrixModule(PollingService):
def __init__(self): def __init__(self, name):
super().__init__() super().__init__(name)
self.service_name = 'Twitter' self.service_name = 'Twitter'
async def poll_implementation(self, bot, account, roomid, send_messages): async def poll_implementation(self, bot, account, roomid, send_messages):

View File

@ -4,7 +4,7 @@ from functools import lru_cache
import httpx import httpx
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from nio import RoomMessageText from nio import RoomMessageText, AsyncClient
from modules.common.module import BotModule from modules.common.module import BotModule
@ -16,23 +16,31 @@ class MatrixModule(BotModule):
Everytime a url is seen in a message we do http request to it and try to get a title tag contents to spit out to the room. Everytime a url is seen in a message we do http request to it and try to get a title tag contents to spit out to the room.
""" """
bot = None def __init__(self, name):
status = dict() # room_id -> what to do with urls super().__init__(name)
STATUSES = { self.bot = None
"OFF": "Not spamming this channel", self.status = dict() # room_id -> what to do with urls
"TITLE": "Spamming this channel with titles",
"DESCRIPTION": "Spamming this channel with descriptions", self.STATUSES = {
"BOTH": "Spamming this channel with both title and description", "OFF": "Not spamming this channel",
} "TITLE": "Spamming this channel with titles",
"DESCRIPTION": "Spamming this channel with descriptions",
"BOTH": "Spamming this channel with both title and description",
}
def matrix_start(self, bot): def matrix_start(self, bot):
""" """
Register callback for all RoomMessageText events on startup Register callback for all RoomMessageText events on startup
""" """
super().matrix_start(bot)
self.bot = bot self.bot = bot
bot.client.add_event_callback(self.text_cb, RoomMessageText) bot.client.add_event_callback(self.text_cb, RoomMessageText)
def matrix_stop(self, bot):
super().matrix_stop(bot)
bot.remove_callback(self.text_cb)
async def text_cb(self, room, event): async def text_cb(self, room, event):
""" """
Handle client callbacks for all room text events Handle client callbacks for all room text events