diff --git a/README.md b/README.md
index ca52744..6132129 100644
--- a/README.md
+++ b/README.md
@@ -774,7 +774,7 @@ class MatrixModule(BotModule):
# Echo what they said back
self.logger.debug(f"room: {room.name} sender: {event.sender} wants an echo")
- await bot.send_text(room, ' '.join(args))
+ await bot.send_text(room, ' '.join(args), event=None)
def help(self):
return 'Echoes back what user has said'
@@ -805,33 +805,36 @@ class Bot:
:return bool: Success upon sending the message
"""
- async def send_text(self, room, body, msgtype="m.notice", bot_ignore=False):
+ async def send_text(self, room, body, event=None, msgtype="m.notice", bot_ignore=False):
"""
:param room: A MatrixRoom the text should be send to
:param body: Textual content of the message
+ :param event: The event to reply to
:param msgtype: The message type for the room https://matrix.org/docs/spec/client_server/latest#m-room-message-msgtypes
:param bot_ignore: Flag to mark the message to be ignored by the bot
:return:
"""
- async def send_html(self, room, html, plaintext, msgtype="m.notice", bot_ignore=False):
+ async def send_html(self, room, html, plaintext, event=None, msgtype="m.notice", bot_ignore=False):
"""
:param room: A MatrixRoom the html should be send to
:param html: Html content of the message
:param plaintext: Plaintext content of the message
+ :param event: The event to reply to
:param msgtype: The message type for the room https://matrix.org/docs/spec/client_server/latest#m-room-message-msgtypes
:param bot_ignore: Flag to mark the message to be ignored by the bot
:return:
"""
- async def send_image(self, room, url, body, mimetype=None, width=None, height=None, size=None):
+ async def send_image(self, room, url, body, event=None, mimetype=None, width=None, height=None, size=None):
"""
:param room: A MatrixRoom the image should be send to
:param url: A MXC-Uri https://matrix.org/docs/spec/client_server/r0.6.0#mxc-uri
:param body: A textual representation of the image
+ :param event: The event to reply to
:param mimetype: The mimetype of the image
:param width: Width in pixel of the image
:param height: Height in pixel of the image
@@ -849,17 +852,18 @@ class Bot:
"""
- async def upload_and_send_image(self, room, url, text=None, blob=False, blob_content_type="image/png"):
+ async def upload_and_send_image(self, room, url, event=None, text=None, blob=False, blob_content_type="image/png"):
"""
:param room: A MatrixRoom the image should be send to after uploading
:param url: Url of binary content of the image to upload
+ :param event: The event to reply to
:param text: A textual representation of the image
:param blob: Flag to indicate if the second param is an url or a binary content
:param blob_content_type: Content type of the image in case of binary content
:return:
"""
- async def send_location(self, room, body, latitude, longitude, bot_ignore=False):
+ async def send_location(self, room, body, latitude, longitude, event=None bot_ignore=False):
"""
:param room: A MatrixRoom the html should be send to
@@ -867,6 +871,7 @@ class Bot:
:param body: Plaintext content of the message
:param latitude: Latitude in WGS84 coordinates (float)
:param longitude: Longitude in WGS84 coordinates (float)
+ :param event: The event to reply to
:param bot_ignore: Flag to mark the message to be ignored by the bot
:return:
"""
diff --git a/bot.py b/bot.py
index cdff094..a45b80e 100755
--- a/bot.py
+++ b/bot.py
@@ -92,7 +92,7 @@ def get_uri_cache(self, url, blob=False):
return self.uri_cache.get(cache_key)
- async def upload_and_send_image(self, room, url, text=None, blob=False, blob_content_type="image/png", no_cache=False):
+ async def upload_and_send_image(self, room, url, event=None, text=None, blob=False, blob_content_type="image/png", no_cache=False):
"""
:param room: A MatrixRoom the image should be send to after uploading
@@ -111,15 +111,30 @@ async def upload_and_send_image(self, room, url, text=None, blob=False, blob_con
if res:
try:
matrix_uri, mimetype, w, h, size = res
- return await self.send_image(room, matrix_uri, text, mimetype, w, h, size)
+ return await self.send_image(room, matrix_uri, text, event, mimetype, w, h, size)
except ValueError: # broken cache?
self.logger.warning(f"Image cache for {url} could not be unpacked, attempting to re-upload...")
try:
- matrix_uri, mimetype, w, h, size = await self.upload_image(url, blob=blob, no_cache=no_cache)
+ matrix_uri, mimetype, w, h, size = await self.upload_image(url, event=event, blob=blob, no_cache=no_cache)
except (UploadFailed, ValueError):
- return await self.send_text(room, f"Sorry. Something went wrong fetching {url} and uploading the image to matrix server :(")
+ return await self.send_text(room, f"Sorry. Something went wrong fetching {url} and uploading the image to matrix server :(", event=event)
- return await self.send_image(room, matrix_uri, text, mimetype, w, h, size)
+ return await self.send_image(room, matrix_uri, text, event, mimetype, w, h, size)
+
+ # Wrapper around matrix-nio's client.room_send
+ # Use src_event context to modify the msg
+ async def room_send(self, room_id, pre_event, msgtype, msg, **kwargs):
+ try:
+ # m.thread support
+ relates_to = pre_event.source['content']['m.relates_to']
+ if relates_to['rel_type'] == 'm.thread':
+ msg['m.relates_to'] = relates_to
+ msg['m.relates_to']['m.in_reply_to'] = {'event_id': pre_event.event_id}
+ except (AttributeError, KeyError):
+ self.logger.warning(f'No pre-event passed. This module may not be set up to support m.thread.')
+ pass
+
+ return await self.client.room_send(room_id, msgtype, msg, **kwargs)
# Helper function to upload a image from URL to homeserver. Use send_image() to actually send it to room.
# Throws exception if upload fails
@@ -169,7 +184,6 @@ async def upload_image(self, url_or_bytes, blob=False, blob_content_type="image/
res = [response.content_uri, content_type, i.size[0], i.size[1], image_length]
if cache_key:
self.uri_cache[cache_key] = res
- self.save_settings() # save cache
return res
else:
response: UploadError
@@ -177,7 +191,7 @@ async def upload_image(self, url_or_bytes, blob=False, blob_content_type="image/
raise UploadFailed
- async def send_text(self, room, body, msgtype="m.notice", bot_ignore=False):
+ async def send_text(self, room, body, event=None, msgtype="m.notice", bot_ignore=False):
"""
:param room: A MatrixRoom the text should be send to
@@ -194,9 +208,9 @@ async def send_text(self, room, body, msgtype="m.notice", bot_ignore=False):
if bot_ignore:
msg["org.vranki.hemppa.ignore"] = "true"
- return await self.client.room_send(room.room_id, 'm.room.message', msg)
+ return await self.room_send(room.room_id, event, 'm.room.message', msg)
- async def send_html(self, room, html, plaintext, msgtype="m.notice", bot_ignore=False):
+ async def send_html(self, room, html, plaintext, event=None, msgtype="m.notice", bot_ignore=False):
"""
:param room: A MatrixRoom the html should be send to
@@ -215,9 +229,9 @@ async def send_html(self, room, html, plaintext, msgtype="m.notice", bot_ignore=
}
if bot_ignore:
msg["org.vranki.hemppa.ignore"] = "true"
- await self.client.room_send(room.room_id, 'm.room.message', msg)
+ await self.room_send(room.room_id, event, 'm.room.message', msg)
- async def send_location(self, room, body, latitude, longitude, bot_ignore=False, asset='m.pin'):
+ async def send_location(self, room, body, latitude, longitude, event=None, bot_ignore=False, asset='m.pin'):
"""
:param room: A MatrixRoom the html should be send to
@@ -235,9 +249,9 @@ async def send_location(self, room, body, latitude, longitude, bot_ignore=False,
"msgtype": "m.location",
"org.matrix.msc3488.asset": { "type": asset }
}
- await self.client.room_send(room.room_id, 'm.room.message', locationmsg)
+ await self.room_send(room.room_id, event, 'm.room.message', locationmsg)
- async def send_image(self, room, url, body, mimetype=None, width=None, height=None, size=None):
+ async def send_image(self, room, url, body, event=None, mimetype=None, width=None, height=None, size=None):
"""
:param room: A MatrixRoom the image should be send to
@@ -268,7 +282,7 @@ async def send_image(self, room, url, body, mimetype=None, width=None, height=No
if size:
msg["info"]["size"] = size
- return await self.client.room_send(room.room_id, 'm.room.message', msg)
+ return await self.room_send(room.room_id, event, 'm.room.message', msg)
async def set_room_avatar(self, room, uri, mimetype=None, width=None, height=None, size=None):
"""
@@ -315,7 +329,7 @@ async def send_msg(self, mxid, roomname, message):
return False
# Send message to the room
- await self.send_text(msg_room, message)
+ await self.send_text(msg_room, None, message)
return True
async def find_or_create_private_msg(self, mxid, roomname):
@@ -423,7 +437,7 @@ async def message_cb(self, room, event):
if self.owners_only and not self.is_owner(event):
self.logger.info(f"Ignoring {event.sender}, because they're not an owner")
- await self.send_text(room, "Sorry, only bot owner can run commands.")
+ await self.send_text(room, "Sorry, only bot owner can run commands.", event=event)
return
# HACK to ignore messages for some time after joining.
@@ -446,11 +460,11 @@ async def message_cb(self, room, event):
try:
await moduleobject.matrix_message(self, room, event)
except CommandRequiresAdmin:
- await self.send_text(room, f'Sorry, you need admin power level in this room to run that command.')
+ await self.send_text(room, f'Sorry, you need admin power level in this room to run that command.', event=event)
except CommandRequiresOwner:
- await self.send_text(room, f'Sorry, only bot owner can run that command.')
+ await self.send_text(room, f'Sorry, only bot owner can run that command.', event=event)
except Exception:
- await self.send_text(room, f'Module {command} experienced difficulty: {sys.exc_info()[0]} - see log for details')
+ await self.send_text(room, f'Module {command} experienced difficulty: {sys.exc_info()[0]} - see log for details', event=event)
self.logger.exception(f'unhandled exception in !{command}')
else:
self.logger.error(f"Unknown command: {command}")
diff --git a/modules/alias.py b/modules/alias.py
index b690be5..f2fcfd5 100644
--- a/modules/alias.py
+++ b/modules/alias.py
@@ -33,7 +33,7 @@ async def matrix_message(self, bot, room, event):
bot.module_aliases.update({args[0]: args[1]})
self.aliases.update({args[0]: args[1]})
bot.save_settings()
- await bot.send_text(room, f'Aliased !{args[0]} to !{args[1]}')
+ await bot.send_text(room, f'Aliased !{args[0]} to !{args[1]}', event)
elif len(args) == 2:
if args.pop(0) in ['rm', 'remove']:
@@ -43,7 +43,7 @@ async def matrix_message(self, bot, room, event):
old = bot.module_aliases.pop(args[0])
self.aliases.pop(args[0])
bot.save_settings()
- await bot.send_text(room, f'Removed alias !{args[0]}')
+ await bot.send_text(room, f'Removed alias !{args[0]}', event)
elif len(args) == 1:
if args.pop(0) in ['ls', 'list']:
@@ -55,10 +55,10 @@ async def matrix_message(self, bot, room, event):
for k, v in inverted.items():
v = ', '.join(v)
msg.append(f'- {k} = {v}')
- await bot.send_text(room, '\n'.join(msg))
+ await bot.send_text(room, '\n'.join(msg), event)
elif args.pop(0) == 'help':
- await bot.send_text(room, self.long_help(bot=bot, event=event))
+ await bot.send_text(room, self.long_help(bot=bot, event=event), event)
def help(self):
return 'Manage command aliases'
diff --git a/modules/apod.py b/modules/apod.py
index 05b92e1..3068935 100644
--- a/modules/apod.py
+++ b/modules/apod.py
@@ -53,21 +53,21 @@ async def matrix_message(self, bot, room, event):
await self.send_apod(bot, room, self.apod_api_url)
elif len(args) == 2:
if args[1] == "stats":
- await self.send_stats(bot, room)
+ await self.send_stats(bot, room, event)
elif args[1] == "clear":
bot.must_be_owner(event)
- await self.clear_uri_cache(bot, room)
+ await self.clear_uri_cache(bot, room, event)
elif args[1] == "help":
- await self.command_help(bot, room)
+ await self.command_help(bot, room, event)
elif args[1] == "avatar":
- await self.send_apod(bot, room, self.apod_api_url, set_room_avatar=bot.is_admin(room, event))
+ await self.send_apod(bot, room, event, self.apod_api_url, set_room_avatar=bot.is_admin(room, event))
else:
date = args[1]
if re.match(self.APOD_DATE_PATTERN, date) is not None:
uri = self.apod_by_date_api_url + date
- await self.send_apod(bot, room, uri)
+ await self.send_apod(bot, room, event, uri)
else:
- await bot.send_text(room, "invalid date. accepted: YYYY-MM-DD")
+ await bot.send_text(room, "invalid date. accepted: YYYY-MM-DD", event)
elif len(args) == 3:
if args[1] == "apikey":
await self.update_api_key(bot, room, event, args[2])
@@ -75,21 +75,21 @@ async def matrix_message(self, bot, room, event):
date = args[2]
if re.match(self.APOD_DATE_PATTERN, date) is not None:
uri = self.apod_by_date_api_url + date
- await self.send_apod(bot, room, uri, set_room_avatar=bot.is_admin(room, event))
+ await self.send_apod(bot, room, event, uri, set_room_avatar=bot.is_admin(room, event))
else:
- await bot.send_text(room, "invalid date. accepted: YYYY-MM-DD")
+ await bot.send_text(room, "invalid date. accepted: YYYY-MM-DD", event)
- async def send_apod(self, bot, room, uri, set_room_avatar=False):
+ async def send_apod(self, bot, room, event, uri, set_room_avatar=False):
self.logger.debug(f"send request using uri {uri}")
response = requests.get(uri)
if response.status_code == 400:
self.logger.error("unable to request apod api. status: %d text: %s", response.status_code, response.text)
- return await bot.send_text(room, response.json().get("msg"))
+ return await bot.send_text(room, response.json().get("msg"), event)
if response.status_code != 200:
self.logger.error("unable to request apod api. response: [status: %d text: %s]", response.status_code, response.text)
- return await bot.send_text(room, "sorry. something went wrong accessing the api :(")
+ return await bot.send_text(room, "sorry. something went wrong accessing the api :(", event)
apod = Apod.create_from_json(response.json())
self.logger.debug(apod)
@@ -97,7 +97,7 @@ async def send_apod(self, bot, room, uri, set_room_avatar=False):
if apod.media_type != "image":
return await self.send_unknown_mediatype(room, bot, apod)
- await bot.send_html(room, f"{html.escape(apod.title)} ({html.escape(apod.date)})", f"{apod.title} ({apod.date})")
+ await bot.send_html(room, f"{html.escape(apod.title)} ({html.escape(apod.date)})", f"{apod.title} ({apod.date})", event)
try:
matrix_uri = None
matrix_uri, mimetype, w, h, size = bot.get_uri_cache(apod.hdurl)
@@ -106,9 +106,9 @@ async def send_apod(self, bot, room, uri, set_room_avatar=False):
try:
matrix_uri, mimetype, w, h, size = await bot.upload_image(apod.hdurl)
except (UploadFailed, TypeError, ValueError):
- await bot.send_text(room, f"Something went wrong uploading {apod.hdurl}.")
- await bot.send_image(room, matrix_uri, apod.hdurl, mimetype, w, h, size)
- await bot.send_text(room, f"{apod.explanation}")
+ await bot.send_text(room, f"Something went wrong uploading {apod.hdurl}.", event)
+ await bot.send_image(room, matrix_uri, apod.hdurl, mimetype, w, h, size, event)
+ await bot.send_text(room, f"{apod.explanation}", event)
if matrix_uri and set_room_avatar:
await bot.set_room_avatar(room, matrix_uri, mimetype, w, h, size)
@@ -138,16 +138,16 @@ def set_settings(self, data):
def help(self):
return 'Sends latest Astronomy Picture of the Day to the room. (https://apod.nasa.gov/apod/astropix.html)'
- async def send_stats(self, bot, room):
+ async def send_stats(self, bot, room, event):
msg = f"collected {len(self.matrix_uri_cache)} upload matrix uri's"
- await bot.send_text(room, msg)
+ await bot.send_text(room, msg, event)
- async def clear_uri_cache(self, bot, room):
+ async def clear_uri_cache(self, bot, room, event):
self.matrix_uri_cache.clear()
bot.save_settings()
- await bot.send_text(room, "cleared uri cache")
+ await bot.send_text(room, "cleared uri cache", event)
- async def command_help(self, bot, room):
+ async def command_help(self, bot, room, event):
msg = """commands:
- YYYY-MM-DD - date of the APOD image to retrieve (ex. 2020-03-15)
- stats - show information about uri cache
@@ -156,12 +156,12 @@ async def command_help(self, bot, room):
- help - show command help
- avatar, avatar YYYY-MM-DD - Additionally set the room's avatar to the fetched image (Must be done as admin)
"""
- await bot.send_text(room, msg)
+ await bot.send_text(room, msg, event)
async def update_api_key(self, bot, room, event, apikey):
bot.must_be_owner(event)
self.api_key = apikey
self.update_api_urls()
bot.save_settings()
- await bot.send_text(room, 'Api key set')
+ await bot.send_text(room, 'Api key set', event)
diff --git a/modules/bot.py b/modules/bot.py
index e28eec7..462c32d 100644
--- a/modules/bot.py
+++ b/modules/bot.py
@@ -77,7 +77,7 @@ async def matrix_message(self, bot, room, event):
pass
# TODO: Make this configurable. By default don't say anything.
- # await bot.send_text(room, 'Unknown command, sorry.')
+ # await bot.send_text(room, 'Unknown command, sorry.', event)
async def get_ping(self, bot, room, event):
self.logger.info(f'{event.sender} pinged the bot in {room.room_id}')
@@ -85,7 +85,7 @@ async def get_ping(self, bot, room, event):
# initial pong
serv_before = event.server_timestamp
local_before = time.time()
- pong = await bot.send_text(room, 'Pong!')
+ pong = await bot.send_text(room, 'Pong!', event)
local_delta = int((time.time() - local_before) * 1000)
# ask the server what the timestamp was on our pong
@@ -116,7 +116,7 @@ async def get_ping(self, bot, room, event):
async def leave(self, bot, room, event):
bot.must_be_admin(room, event)
self.logger.info(f'{event.sender} asked bot to leave room {room.room_id}')
- await bot.send_text(room, f'By your command.')
+ await bot.send_text(room, f'By your command.', event)
await bot.client.room_leave(room.room_id)
async def stats(self, bot, room):
@@ -141,7 +141,7 @@ async def stats(self, bot, room):
homeservers = ', '.join(['{} ({} users, {:.1f}%)'.format(hs[0], hs[1], 100.0 * hs[1] / usercount)
for hs in homeservers[:10]])
await bot.send_text(room, f'I\'m seeing {usercount} users in {roomcount} rooms.'
- f' Top ten homeservers (out of {hscount}): {homeservers}')
+ f' Top ten homeservers (out of {hscount}): {homeservers}', event)
async def status(self, bot, room):
systime = time.time()
@@ -150,11 +150,11 @@ async def status(self, bot, room):
enabled = sum(1 for module in bot.modules.values() if module.enabled)
return await bot.send_text(room, f'Uptime: {uptime} - System time: {systime} '
- f'- {enabled} modules enabled out of {len(bot.modules)} loaded.')
+ f'- {enabled} modules enabled out of {len(bot.modules)} loaded.', event)
async def reload(self, bot, room, event):
bot.must_be_owner(event)
- msg = await bot.send_text(room, f'Reloading modules...')
+ msg = await bot.send_text(room, f'Reloading modules...', event)
bot.stop()
bot.reload_modules()
bot.start()
@@ -174,11 +174,11 @@ async def reload(self, bot, room, event):
await bot.client.room_send(room.room_id, 'm.room.message', content)
async def version(self, bot, room):
- await bot.send_text(room, f'Hemppa version {bot.version} - https://github.com/vranki/hemppa')
+ await bot.send_text(room, f'Hemppa version {bot.version} - https://github.com/vranki/hemppa', event)
async def quit(self, bot, room, event):
bot.must_be_owner(event)
- await bot.send_text(room, f'Quitting, as requested')
+ await bot.send_text(room, f'Quitting, as requested', event)
self.logger.info(f'{event.sender} commanded bot to quit, so quitting..')
bot.bot_task.cancel()
@@ -190,8 +190,8 @@ async def enable_module(self, bot, room, event, module_name):
module.enable()
module.matrix_start(bot)
bot.save_settings()
- return await bot.send_text(room, f"Module {module_name} enabled")
- return await bot.send_text(room, f"Module with name {module_name} not found. Execute !bot modules for a list of available modules")
+ return await bot.send_text(room, f"Module {module_name} enabled", event)
+ return await bot.send_text(room, f"Module with name {module_name} not found. Execute !bot modules for a list of available modules", event)
async def disable_module(self, bot, room, event, module_name):
bot.must_be_owner(event)
@@ -201,20 +201,20 @@ async def disable_module(self, bot, room, event, module_name):
try:
module.disable()
except ModuleCannotBeDisabled:
- return await bot.send_text(room, f"Module {module_name} cannot be disabled.")
+ return await bot.send_text(room, f"Module {module_name} cannot be disabled.", event)
except Exception as e:
- return await bot.send_text(room, f"Module {module_name} was not disabled: {repr(e)}")
+ return await bot.send_text(room, f"Module {module_name} was not disabled: {repr(e)}", event)
module.matrix_stop(bot)
bot.save_settings()
- return await bot.send_text(room, f"Module {module_name} disabled")
- return await bot.send_text(room, f"Module with name {module_name} not found. Execute !bot modules for a list of available modules")
+ return await bot.send_text(room, f"Module {module_name} disabled", event)
+ return await bot.send_text(room, f"Module with name {module_name} not found. Execute !bot modules for a list of available modules", event)
async def show_modules(self, bot, room):
modules_message = "Modules:\n"
for modulename, module in collections.OrderedDict(sorted(bot.modules.items())).items():
state = 'Enabled' if module.enabled else 'Disabled'
modules_message += f"{state}: {modulename} - {module.help()}\n"
- await bot.send_text(room, modules_message)
+ await bot.send_text(room, modules_message, event)
async def export_settings(self, bot, event, module_name=None):
bot.must_be_owner(event)
@@ -224,7 +224,7 @@ async def export_settings(self, bot, event, module_name=None):
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))
+ await bot.send_msg(event.sender, f'Private message from {bot.matrix_user}', json.dumps(data), event)
async def import_settings(self, bot, event):
bot.must_be_owner(event)
@@ -254,7 +254,7 @@ async def import_settings(self, bot, event):
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')
+ await bot.send_msg(event.sender, f'Private message from {bot.matrix_user}', 'Updated bot settings', event)
async def last_logs(self, bot, room, event, target):
bot.must_be_owner(event)
@@ -278,13 +278,13 @@ async def last_logs(self, bot, room, event, target):
except (KeyError, TypeError):
pass
else:
- return await bot.send_text(msg_room, f'Unknown module {target}, or no logs yet')
+ return await bot.send_text(msg_room, f'Unknown module {target}, or no logs yet', event)
if count:
logs = logs[count:]
logs = '\n'.join([self.loghandler.format(record) for record in logs])
- return await bot.send_html(msg_room, f'Logs for {key}:\n
{escape(logs)}
', f'Logs for {key}:\n' + logs)
+ return await bot.send_html(msg_room, f'Logs for {key}:\n{escape(logs)}
', f'Logs for {key}:\n' + logs, event)
async def manage_uri_cache(self, bot, room, event, action):
bot.must_be_owner(event)
@@ -293,7 +293,7 @@ async def manage_uri_cache(self, bot, room, event, action):
msg = [f'uri cache size: {len(bot.uri_cache)}']
for key, val in bot.uri_cache.items():
msg.append('- ' + key + ': ' + val[0])
- return await bot.send_text(room, '\n'.join(msg))
+ return await bot.send_text(room, '\n'.join(msg), event)
if action in ['clean', 'clear']:
self.logger.info(f"{event.sender} wants to clear the uri cache")
bot.uri_cache = dict()
@@ -305,7 +305,7 @@ async def rooms(self, bot, room, event):
for croomid in bot.client.rooms:
roomobj = bot.get_room_by_id(croomid)
output = output + f' - {roomobj.display_name} ( {roomobj.machine_name} )\n'
- await bot.send_text(room, output)
+ await bot.send_text(room, output, event)
def disable(self):
raise ModuleCannotBeDisabled
diff --git a/modules/cmd.py b/modules/cmd.py
index 7fd4ec2..9d83428 100644
--- a/modules/cmd.py
+++ b/modules/cmd.py
@@ -25,11 +25,11 @@ async def matrix_message(self, bot, room, event):
command_name = args[1]
bot.must_be_owner(event)
if command_name in self.commands:
- await bot.send_text(room, f'Removed "{self.commands[command_name]}"')
+ await bot.send_text(room, f'Removed "{self.commands[command_name]}"', event)
del self.commands[command_name]
bot.save_settings()
else:
- await bot.send_text(room, f'Could not find command "{command_name}"')
+ await bot.send_text(room, f'Could not find command "{command_name}"', event)
# Message body possibilities:
# ["add", "command_name", "echo", "Hello", "world"]
elif args[0] == 'add':
@@ -38,18 +38,18 @@ async def matrix_message(self, bot, room, event):
bot.must_be_owner(event)
self.commands[command_name] = command_body
bot.save_settings()
- await bot.send_text(room, f'Added "{command_name}" -> "{command_body}".')
+ await bot.send_text(room, f'Added "{command_name}" -> "{command_body}".', event)
# Message body possibilities:
# ["list"]
elif args[0] == 'list':
if len(self.commands) == 0:
- await bot.send_text(room, "No known commands")
+ await bot.send_text(room, "No known commands", event)
else:
known_commands = "Known commands:\n"
for command_name in self.commands.keys():
command_body = self.commands[command_name]
known_commands += f' - "{command_name}" -> "{command_body}"\n'
- await bot.send_text(room, known_commands)
+ await bot.send_text(room, known_commands, event)
# Message body possibilities:
# ["command_name"]
else:
@@ -60,9 +60,9 @@ async def matrix_message(self, bot, room, event):
f"room: {room.display_name} sender: {event.sender} wants to run cmd {target_command}"
)
out = self.run_command(target_command, event.sender, room.display_name)
- await self.send_output(bot, room, out)
+ await self.send_output(bot, room, out, event)
else:
- await bot.send_text(room, 'Unknown command.')
+ await bot.send_text(room, 'Unknown command.', event)
def help(self):
return 'Runs shell commands'
@@ -96,10 +96,10 @@ def run_command(self, command, user, roomname):
processout = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=5, text=True, env=environment)
return processout.stdout
- async def send_output(self, bot, room, output):
+ async def send_output(self, bot, room, output, event):
html = output
if output.count('\n') > 1:
html = "" + output + "
"
if len(output) == 0:
output = html = '(No output returned)'
- await bot.send_html(room, html, output)
+ await bot.send_html(room, html, output, event)
diff --git a/modules/cron.py b/modules/cron.py
index 3564327..005da50 100644
--- a/modules/cron.py
+++ b/modules/cron.py
@@ -21,18 +21,18 @@ async def matrix_message(self, bot, room, event):
if not self.daily_commands.get(room.room_id):
self.daily_commands[room.room_id] = []
self.daily_commands[room.room_id].append(
- {'time': dailytime, 'command': dailycmd})
+ {'time': dailytime, 'command': dailycmd, 'pre-event': event})
bot.save_settings()
- await bot.send_text(room, 'Daily command added.')
+ await bot.send_text(room, 'Daily command added.', event)
elif len(args) == 1:
if args[0] == 'list':
- await bot.send_text(room, 'Daily commands on this room: ' + str(self.daily_commands.get(room.room_id)))
+ await bot.send_text(room, 'Daily commands on this room: ' + str(self.daily_commands.get(room.room_id)), event)
elif args[0] == 'clear':
self.daily_commands.pop(room.room_id, None)
bot.save_settings()
- await bot.send_text(room, 'Cleared commands on this room.')
+ await bot.send_text(room, 'Cleared commands on this room.', event)
elif args[0] == 'time':
- await bot.send_text(room, '{datetime} {timezone}'.format(datetime=datetime.now(), timezone=os.environ.get('TZ')))
+ await bot.send_text(room, '{datetime} {timezone}'.format(datetime=datetime.now(), timezone=os.environ.get('TZ')), event)
def help(self):
return ('Runs scheduled commands')
@@ -57,7 +57,7 @@ async def matrix_poll(self, bot, pollcount):
commands = self.daily_commands[room_id]
for command in commands:
if int(command['time']) == self.last_hour:
- await bot.send_text(bot.get_room_by_id(room_id), command['command'], 'm.text')
+ await bot.send_text(bot.get_room_by_id(room_id), command['command'], 'm.text', command.get('event'))
else:
delete_rooms.append(room_id)
diff --git a/modules/echo.py b/modules/echo.py
index b60e54e..02aab96 100644
--- a/modules/echo.py
+++ b/modules/echo.py
@@ -8,7 +8,7 @@ async def matrix_message(self, bot, room, event):
# Echo what they said back
self.logger.debug(f"room: {room.name} sender: {event.sender} wants an echo")
- await bot.send_text(room, ' '.join(args))
+ await bot.send_text(room, ' '.join(args), event)
def help(self):
return 'Echoes back what user has said'
diff --git a/modules/flog.py b/modules/flog.py
index 867e89b..3abe0d0 100644
--- a/modules/flog.py
+++ b/modules/flog.py
@@ -144,20 +144,20 @@ async def matrix_message(self, bot, room, event):
station = self.station_rooms[room.room_id]
await self.show_flog(bot, room, station)
else:
- await bot.send_text(room, 'No OGN station set for this room - set it first.')
+ await bot.send_text(room, 'No OGN station set for this room - set it first.', event)
elif len(args) == 2 and args[0] == "!flog":
if args[1] == 'rmstation':
bot.must_be_admin(room, event)
del self.station_rooms[room.room_id]
self.live_rooms.remove(room.room_id)
- await bot.send_text(room, f'Cleared OGN station for this room')
+ await bot.send_text(room, f'Cleared OGN station for this room', event)
elif args[1] == 'status':
print(self.logged_flights)
print(self.fb.device_cache)
bot.must_be_admin(room, event)
- await bot.send_text(room, f'OGN station for this room: {self.station_rooms.get(room.room_id)}, live updates enabled: {room.room_id in self.live_rooms}')
+ await bot.send_text(room, f'OGN station for this room: {self.station_rooms.get(room.room_id)}, live updates enabled: {room.room_id in self.live_rooms}', event)
elif args[1] == 'poll':
bot.must_be_admin(room, event)
@@ -167,13 +167,13 @@ async def matrix_message(self, bot, room, event):
bot.must_be_admin(room, event)
self.live_rooms.append(room.room_id)
bot.save_settings()
- await bot.send_text(room, f'Sending live updates for station {self.station_rooms.get(room.room_id)} to this room')
+ await bot.send_text(room, f'Sending live updates for station {self.station_rooms.get(room.room_id)} to this room', event)
elif args[1] == 'rmlive':
bot.must_be_admin(room, event)
self.live_rooms.remove(room.room_id)
bot.save_settings()
- await bot.send_text(room, f'Not sending live updates for station {self.station_rooms.get(room.room_id)} to this room anymore')
+ await bot.send_text(room, f'Not sending live updates for station {self.station_rooms.get(room.room_id)} to this room anymore', event)
else:
# Assume parameter is a station name
@@ -190,9 +190,9 @@ async def matrix_message(self, bot, room, event):
if address:
coords = self.get_coords_for_address(address)
if coords:
- await bot.send_location(room, f'{registration} ({coords["utc"]})', coords["lat"], coords["lng"])
+ await bot.send_location(room, f'{registration} ({coords["utc"]})', coords["lat"], coords["lng"], event)
else:
- await bot.send_text(room, f'No Flarm ID found for {registration}!')
+ await bot.send_text(room, f'No Flarm ID found for {registration}!', event)
elif len(args) == 3 and args[0] == "!flog":
if args[1] == 'station':
@@ -203,7 +203,7 @@ async def matrix_message(self, bot, room, event):
self.logger.info(f'Station now for this room {self.station_rooms.get(room.room_id)}')
bot.save_settings()
- await bot.send_text(room, f'Set OGN station {station} to this room')
+ await bot.send_text(room, f'Set OGN station {station} to this room', event)
def get_coords_for_address(self, address):
@@ -246,12 +246,12 @@ def html_flog(self, data, showtow):
out = out + ""
return out
- async def show_flog(self, bot, room, station):
+ async def show_flog(self, bot, room, event, station):
data = self.fb.get_flights(station)
if data:
- await bot.send_html(room, self.html_flog(data, False), self.text_flog(data, False))
+ await bot.send_html(room, self.html_flog(data, False), self.text_flog(data, False), event)
else:
- await bot.send_text(room, f"Failed to get flight log for {station}")
+ await bot.send_text(room, f"Failed to get flight log for {station}", event)
def get_settings(self):
data = super().get_settings()
diff --git a/modules/gfycat.py b/modules/gfycat.py
index 52efdbc..9f86416 100644
--- a/modules/gfycat.py
+++ b/modules/gfycat.py
@@ -85,16 +85,16 @@ async def matrix_message(self, bot, room, event):
try:
gifs = gfycat().search(query)
if len(gifs) < 1:
- await bot.send_text(room, gif_url)
+ await bot.send_text(room, gif_url, event)
return
gif_url = gifs.get(0)["content_urls"]["largeGif"]["url"]
await bot.upload_and_send_image(room, gif_url)
except Exception as exc:
gif_url = str(exc)
- await bot.send_text(room, gif_url)
+ await bot.send_text(room, gif_url, event)
else:
- await bot.send_text(room, 'Usage: !gfycat ')
+ await bot.send_text(room, 'Usage: !gfycat ', event)
def help(self):
return ('Gfycat bot')
diff --git a/modules/ghproj.py b/modules/ghproj.py
index 3450db4..bfe5869 100644
--- a/modules/ghproj.py
+++ b/modules/ghproj.py
@@ -81,11 +81,11 @@ async def matrix_message(self, bot, room, event):
if args[0] == 'rmrepo':
bot.must_be_admin(room, event)
del self.repo_rooms[room.room_id]
- await bot.send_text(room, 'Github repo removed from this room.')
+ await bot.send_text(room, 'Github repo removed from this room.', event)
bot.save_settings()
return
if args[0] == 'repo':
- await bot.send_text(room, f'Github repo for this room is {self.repo_rooms.get(room.room_id, "not set")}.')
+ await bot.send_text(room, f'Github repo for this room is {self.repo_rooms.get(room.room_id, "not set")}.', event)
return
domain = args[0]
@@ -93,11 +93,11 @@ async def matrix_message(self, bot, room, event):
if reponame:
issues, ok = GithubProject.get_domain(reponame, domain)
if issues or ok:
- await self.send_domain_status(bot, room, reponame, issues, ok)
+ await self.send_domain_status(bot, room, event, reponame, issues, ok)
else:
- await bot.send_text(room, f'No labels with domain {domain} found.')
+ await bot.send_text(room, f'No labels with domain {domain} found.', event)
else:
- await bot.send_text(room, f'No github repo set for this room. Use setrepo to set it.')
+ await bot.send_text(room, f'No github repo set for this room. Use setrepo to set it.', event)
return
if len(args) == 2:
@@ -108,16 +108,16 @@ async def matrix_message(self, bot, room, event):
self.logger.info(f'Adding repo {reponame} to room id {room.room_id}')
self.repo_rooms[room.room_id] = reponame
- await bot.send_text(room, f'Github repo {reponame} set to this room.')
+ await bot.send_text(room, f'Github repo {reponame} set to this room.', event)
bot.save_settings()
return
- await bot.send_text(room, 'Unknown command')
+ await bot.send_text(room, 'Unknown command', event)
- async def send_domain_status(self, bot, room, reponame, issues, ok):
+ async def send_domain_status(self, bot, room, event, reponame, issues, ok):
text_out = GithubProject.domain_to_string(reponame, issues, ok)
html_out = GithubProject.domain_to_html(reponame, issues, ok)
- await bot.send_html(room, html_out, text_out)
+ await bot.send_html(room, html_out, text_out, event)
def help(self):
diff --git a/modules/giphy.py b/modules/giphy.py
index a4f7224..4574113 100644
--- a/modules/giphy.py
+++ b/modules/giphy.py
@@ -21,7 +21,7 @@ async def matrix_message(self, bot, room, event):
self.api_key = args[2]
bot.save_settings()
- await bot.send_text(room, 'Api key set')
+ await bot.send_text(room, 'Api key set', event)
elif len(args) > 1:
gif_url = "No image found"
query = event.body[len(args[0])+1:]
@@ -34,7 +34,7 @@ async def matrix_message(self, bot, room, event):
except Exception:
pass
if len(gifs) < 1:
- await bot.send_text(room, gif_url)
+ await bot.send_text(room, gif_url, event)
return
gif_url = gifs[0].media_url
@@ -42,9 +42,9 @@ async def matrix_message(self, bot, room, event):
return
except Exception as exc:
gif_url = str(exc)
- await bot.send_text(room, gif_url)
+ await bot.send_text(room, gif_url, event)
else:
- await bot.send_text(room, 'Usage: !giphy ')
+ await bot.send_text(room, 'Usage: !giphy ', event)
def get_settings(self):
data = super().get_settings()
diff --git a/modules/googlecal.py b/modules/googlecal.py
index 588f506..fb40a68 100644
--- a/modules/googlecal.py
+++ b/modules/googlecal.py
@@ -67,7 +67,7 @@ def matrix_start(self, bot):
async def matrix_message(self, bot, room, event):
if not self.service:
- await bot.send_text(room, 'Google calendar not set up for this bot.')
+ await bot.send_text(room, 'Google calendar not set up for this bot.', event)
return
args = event.body.split()
events = []
@@ -79,7 +79,7 @@ async def matrix_message(self, bot, room, event):
self.logger.info(f'Listing events in cal {calid}')
events = events + self.list_today(calid)
if args[1] == 'list':
- await bot.send_text(room, 'Calendars in this room: ' + str(self.calendar_rooms.get(room.room_id)))
+ await bot.send_text(room, 'Calendars in this room: ' + str(self.calendar_rooms.get(room.room_id)), event)
return
elif len(args) == 3:
@@ -93,7 +93,7 @@ async def matrix_message(self, bot, room, event):
if calid not in self.calendar_rooms[room.room_id]:
self.calendar_rooms[room.room_id].append(calid)
else:
- await bot.send_text(room, 'This google calendar already added in this room!')
+ await bot.send_text(room, 'This google calendar already added in this room!', event)
return
else:
self.calendar_rooms[room.room_id] = [calid]
@@ -102,7 +102,7 @@ async def matrix_message(self, bot, room, event):
bot.save_settings()
- await bot.send_text(room, 'Added new google calendar to this room')
+ await bot.send_text(room, 'Added new google calendar to this room', event)
return
if args[1] == 'del':
@@ -118,7 +118,7 @@ async def matrix_message(self, bot, room, event):
bot.save_settings()
- await bot.send_text(room, 'Removed google calendar from this room')
+ await bot.send_text(room, 'Removed google calendar from this room', event)
return
else:
@@ -131,7 +131,7 @@ async def matrix_message(self, bot, room, event):
await self.send_events(bot, events, room)
else:
self.logger.info(f'No events found')
- await bot.send_text(room, 'No events found, try again later :)')
+ await bot.send_text(room, 'No events found, try again later :)', event)
async def send_events(self, bot, events, room):
for event in events:
diff --git a/modules/help.py b/modules/help.py
index 54d05d0..711acb6 100644
--- a/modules/help.py
+++ b/modules/help.py
@@ -42,7 +42,7 @@ async def matrix_message(self, bot, room, event):
msg = '!help info string set'
bot.save_settings()
else:
- await bot.send_text(room, f'Not a !help setting: {args[0]}')
+ await bot.send_text(room, f'Not a !help setting: {args[0]}', event)
return
elif len(args) == 1:
@@ -68,9 +68,9 @@ async def matrix_message(self, bot, room, event):
pass
msg = msg + '\n' + self.info
if self.msg_users:
- await bot.send_msg(event.sender, f'Chat with {bot.matrix_user}', msg)
+ await bot.send_msg(event.sender, f'Chat with {bot.matrix_user}', msg, event)
else:
- await bot.send_text(room, msg)
+ await bot.send_text(room, msg, event)
def help(self):
return 'Prints help on commands'
diff --git a/modules/ig.py b/modules/ig.py
index 83de68d..c20591f 100644
--- a/modules/ig.py
+++ b/modules/ig.py
@@ -26,7 +26,8 @@ async def poll_implementation(self, bot, account, roomid, send_messages):
if media.identifier not in self.known_ids:
await bot.send_html(bot.get_room_by_id(roomid),
f'Instagram {account}: {media.caption}',
- f'{account}: {media.caption} {media.link}')
+ f'{account}: {media.caption} {media.link}',
+ event)
self.known_ids.add(media.identifier)
except InstagramNotFoundException:
diff --git a/modules/jitsi.py b/modules/jitsi.py
index aa44cb5..3000ecf 100644
--- a/modules/jitsi.py
+++ b/modules/jitsi.py
@@ -34,7 +34,7 @@ async def unknownevent_cb(self, room, event):
plainMessage = f'{sender} started a {calltype}: {jitsiUrl}'
htmlMessage = f'{sender} started a {calltype}'
- await self.bot.send_html(room, htmlMessage, plainMessage)
+ await self.bot.send_html(room, htmlMessage, plainMessage, event)
except Exception as e:
self.logger.error(f"Failed parsing Jitsi event. Error: {e}")
diff --git a/modules/loc.py b/modules/loc.py
index a17e976..78a6a62 100644
--- a/modules/loc.py
+++ b/modules/loc.py
@@ -93,7 +93,7 @@ async def unknown_cb(self, room, event):
float(latlon[0])
float(latlon[1])
except Exception:
- self.bot.send_text(room, "Error: Invalid location " + geo_uri)
+ self.bot.send_text(room, "Error: Invalid location " + geo_uri, event)
return
osm_link = f"https://www.openstreetmap.org/?mlat={latlon[0]}&mlon={latlon[1]}"
@@ -101,26 +101,26 @@ async def unknown_cb(self, room, event):
plain = f'{sender} sent {location_text} {osm_link} 🚩'
html = f'{sender} sent {location_text} 🚩'
- await self.bot.send_html(room, html, plain)
+ await self.bot.send_html(room, html, plain, event)
async def matrix_message(self, bot, room, event):
args = event.body.split()
args.pop(0)
if len(args) == 0:
- await bot.send_text(room, 'Usage: !loc ')
+ await bot.send_text(room, 'Usage: !loc ', event)
return
elif len(args) == 1:
if args[0] == 'enable':
bot.must_be_admin(room, event)
self.enabled_rooms.append(room.room_id)
self.enabled_rooms = list(dict.fromkeys(self.enabled_rooms)) # Deduplicate
- await bot.send_text(room, "Ok, sending locations events here as text versions")
+ await bot.send_text(room, "Ok, sending locations events here as text versions", event)
bot.save_settings()
return
if args[0] == 'disable':
bot.must_be_admin(room, event)
self.enabled_rooms.remove(room.room_id)
- await bot.send_text(room, "Ok, disabled here")
+ await bot.send_text(room, "Ok, disabled here", event)
bot.save_settings()
return
@@ -130,9 +130,9 @@ async def matrix_message(self, bot, room, event):
location = geolocator.geocode(query)
self.logger.info('loc rx %s', location)
if location:
- await bot.send_location(room, location.address, location.latitude, location.longitude, "m.pin")
+ await bot.send_location(room, location.address, location.latitude, location.longitude, "m.pin", event)
else:
- await bot.send_text(room, "Can't find " + query + " on map!")
+ await bot.send_text(room, "Can't find " + query + " on map!", event)
def help(self):
return 'Search for locations and display Matrix location events as OSM links'
diff --git a/modules/md.py b/modules/md.py
index c0c9621..c814917 100644
--- a/modules/md.py
+++ b/modules/md.py
@@ -33,9 +33,9 @@ async def matrix_message(self, bot, room, event):
api_base_url = instanceurl
)
tootdict = toottodon.toot(toot_body)
- await bot.send_text(room, tootdict['url'])
+ await bot.send_text(room, tootdict['url'], event)
else:
- await bot.send_text(room, f'{event.sender} has not logged in yet with the bot. Please do so.')
+ await bot.send_text(room, f'{event.sender} has not logged in yet with the bot. Please do so.', event)
return
if len(args) == 4:
@@ -46,7 +46,7 @@ async def matrix_message(self, bot, room, event):
instanceurl = args[1]
username = args[2]
password = args[3]
- await self.register_app_if_necessary(bot, room, instanceurl)
+ await self.register_app_if_necessary(bot, room, instanceurl, event)
await self.login_to_account(bot, room, mxid, None, instanceurl, username, password)
return
if len(args) == 5:
@@ -59,10 +59,10 @@ async def matrix_message(self, bot, room, event):
password = args[4]
roomid = await bot.get_room_by_alias(roomalias)
if roomid:
- await self.register_app_if_necessary(bot, room, instanceurl)
+ await self.register_app_if_necessary(bot, room, instanceurl, event)
await self.login_to_account(bot, room, None, roomid, instanceurl, username, password)
else:
- await bot.send_text(room, f'Unknown room alias {roomalias} - invite bot to the room first.')
+ await bot.send_text(room, f'Unknown room alias {roomalias} - invite bot to the room first.', event)
return
if len(args) == 1:
if args[0] == "status":
@@ -74,44 +74,44 @@ async def matrix_message(self, bot, room, event):
for roomlogin in self.roomlogins:
out = out + f' - {roomlogin} as {self.roomlogins[roomlogin][0]} on {self.roomlogins[roomlogin][2]}\n'
- await bot.send_text(room, out)
+ await bot.send_text(room, out, event)
if args[0] == "logout":
if event.sender in self.logins.keys():
# TODO: Is there a way to invalidate the access token with API?
del self.logins[event.sender]
bot.save_settings()
- await bot.send_text(room, f'{event.sender} login data removed from the bot.')
+ await bot.send_text(room, f'{event.sender} login data removed from the bot.', event)
if args[0] == "roomlogout":
bot.must_be_admin(room, event)
if room.room_id in self.roomlogins.keys():
del self.roomlogins[room.room_id]
bot.save_settings()
- await bot.send_text(room, f'Login data for this room removed from the bot.')
+ await bot.send_text(room, f'Login data for this room removed from the bot.', event)
else:
- await bot.send_text(room, f'No login found for room id {room.room_id}.')
+ await bot.send_text(room, f'No login found for room id {room.room_id}.', event)
if args[0] == "clear":
bot.must_be_owner(event)
self.logins = dict()
self.roomlogins = dict()
bot.save_settings()
- await bot.send_text(room, f'All Mastodon logins cleared')
+ await bot.send_text(room, f'All Mastodon logins cleared', event)
if args[0] == "setpublic":
bot.must_be_owner(event)
self.public = True
bot.save_settings()
- await bot.send_text(room, f'Mastodon usage is now public use')
+ await bot.send_text(room, f'Mastodon usage is now public use', event)
if args[0] == "setprivate":
bot.must_be_owner(event)
self.public = False
bot.save_settings()
- await bot.send_text(room, f'Mastodon usage is now restricted to bot owners')
+ await bot.send_text(room, f'Mastodon usage is now restricted to bot owners', event)
- async def register_app_if_necessary(self, bot, room, instanceurl):
+ async def register_app_if_necessary(self, bot, room, instanceurl, event):
if not instanceurl in self.apps.keys():
app = Mastodon.create_app(f'Hemppa The Bot - {bot.client.user}', api_base_url = instanceurl)
self.apps[instanceurl] = [app[0], app[1]]
bot.save_settings()
- await bot.send_text(room, f'Registered Mastodon app on {instanceurl}')
+ await bot.send_text(room, f'Registered Mastodon app on {instanceurl}', event)
async def login_to_account(self, bot, room, mxid, roomid, instanceurl, username, password):
mastodon = Mastodon(client_id = self.apps[instanceurl][0], client_secret = self.apps[instanceurl][1], api_base_url = instanceurl)
@@ -119,10 +119,10 @@ async def login_to_account(self, bot, room, mxid, roomid, instanceurl, username,
print('login_To_account', mxid, roomid)
if mxid:
self.logins[mxid] = [username, access_token, instanceurl]
- await bot.send_text(room, f'Logged Matrix user {mxid} into {instanceurl} as {username}')
+ await bot.send_text(room, f'Logged Matrix user {mxid} into {instanceurl} as {username}', event)
elif roomid:
self.roomlogins[roomid] = [username, access_token, instanceurl]
- await bot.send_text(room, f'Set room {roomid} Mastodon user to {username} on {instanceurl}')
+ await bot.send_text(room, f'Set room {roomid} Mastodon user to {username} on {instanceurl}', event)
bot.save_settings()
diff --git a/modules/metar.py b/modules/metar.py
index 44ffb18..6e8dfe2 100644
--- a/modules/metar.py
+++ b/modules/metar.py
@@ -12,9 +12,9 @@ async def matrix_message(self, bot, room, event):
icao.upper() + ".TXT"
response = urllib.request.urlopen(metar_url)
lines = response.readlines()
- await bot.send_text(room, lines[1].decode("utf-8").strip())
+ await bot.send_text(room, lines[1].decode("utf-8").strip(), event)
else:
- await bot.send_text(room, 'Usage: !metar ')
+ await bot.send_text(room, 'Usage: !metar ', event)
def help(self):
return ('Metar data access (usage: !metar )')
diff --git a/modules/mumble.py b/modules/mumble.py
index cd54051..e16ff91 100644
--- a/modules/mumble.py
+++ b/modules/mumble.py
@@ -33,18 +33,18 @@ async def matrix_message(self, bot, room, event):
self.logger.info(f"room: {room.name} sender: {event.sender} is setting the server settings")
if len(args) < 3:
self.host = None
- return await bot.send_text(room, f'Usage: !{args[0]} {args[1]} [host] ([port])')
+ return await bot.send_text(room, f'Usage: !{args[0]} {args[1]} [host] ([port])', event)
self.host = args[2]
if len(args) > 3:
self.port = int(args[3])
if not self.port:
self.port = 64738
bot.save_settings()
- return await bot.send_text(room, f'Set server settings: host: {self.host} port: {self.port}')
+ return await bot.send_text(room, f'Set server settings: host: {self.host} port: {self.port}', event)
self.logger.info(f"room: {room.name} sender: {event.sender} wants mumble info")
if not self.host:
- return await bot.send_text(room, f'No mumble host info set!')
+ return await bot.send_text(room, f'No mumble host info set!', event)
try:
ret = self.mumble_ping()
@@ -56,10 +56,10 @@ async def matrix_message(self, bot, room, event):
# [7] = bandwidth
# [5] = users
# [6] = max users
- await bot.send_text(room, f'{self.host}:{self.port} (v{version}): {ret[5]} / {ret[6]} (ping: {ping}ms)')
+ await bot.send_text(room, f'{self.host}:{self.port} (v{version}): {ret[5]} / {ret[6]} (ping: {ping}ms)', event)
except socket.gaierror as e:
self.logger.error(f"room: {room.name}: mumble_ping failed: {e}")
- await bot.send_text(room, f'Could not get get mumble server info: {e}')
+ await bot.send_text(room, f'Could not get get mumble server info: {e}', event)
def mumble_ping(self):
addrinfo = socket.getaddrinfo(self.host, self.port, 0, 0, socket.SOL_UDP)
diff --git a/modules/mxma.py b/modules/mxma.py
index 7a4a980..76e6d06 100644
--- a/modules/mxma.py
+++ b/modules/mxma.py
@@ -21,7 +21,7 @@ async def poll_implementation(self, bot, account, roomid, send_messages):
if 'messages' in response.json():
messages = response.json()['messages']
for message in messages:
- success = await bot.send_msg(message['to'], message['title'], message['message'])
+ success = await bot.send_msg(message['to'], message['title'], message['message'], event)
except Exception:
self.logger.error('Polling MXMA failed:')
traceback.print_exc(file=sys.stderr)
diff --git a/modules/notam.py b/modules/notam.py
index 1c5012c..3302472 100644
--- a/modules/notam.py
+++ b/modules/notam.py
@@ -10,9 +10,9 @@ async def matrix_message(self, bot, room, event):
if len(args) == 2 and len(args[1]) == 4:
icao = args[1].upper()
notam = self.get_notam(icao)
- await bot.send_text(room, notam)
+ await bot.send_text(room, notam, event)
else:
- await bot.send_text(room, 'Usage: !notam ')
+ await bot.send_text(room, 'Usage: !notam ', event)
def help(self):
return ('NOTAM data access (usage: !notam ) - Currently Finnish airports only')
diff --git a/modules/printing.py b/modules/printing.py
index 9fc5902..29f34c7 100644
--- a/modules/printing.py
+++ b/modules/printing.py
@@ -44,14 +44,14 @@ async def file_cb(self, room, event):
self.logger.debug(f'RX filename {filename}')
conn = cups.Connection ()
conn.printFile(printer, filename, f"Printed from Matrix - {filename}", {'fit-to-page': 'TRUE', 'PageSize': self.paper_size})
- await self.bot.send_text(room, f'Printing file on {printer}..')
+ await self.bot.send_text(room, f'Printing file on {printer}..', event)
os.remove(filename) # Not sure if we should wait first?
else:
self.logger.debug(f'No printer configured for room {room.room_id}')
except:
self.logger.warning(f"File callback failure")
traceback.print_exc(file=sys.stderr)
- await self.bot.send_text(room, f'Printing failed, sorry. See log for details.')
+ await self.bot.send_text(room, f'Printing failed, sorry. See log for details.', event)
def matrix_start(self, bot):
super().matrix_start(bot)
@@ -80,25 +80,25 @@ async def matrix_message(self, bot, room, event):
if printerid == printer:
msg += f' <- room {roomid}'
msg += '\n'
- await bot.send_text(room, msg)
+ await bot.send_text(room, msg, event)
elif args[0] == 'rmroomprinter':
del self.printers[room.room_id]
- await bot.send_text(room, f'Deleted printer from this room.')
+ await bot.send_text(room, f'Deleted printer from this room.', event)
bot.save_settings()
if len(args) == 2:
if args[0] == 'setroomprinter':
printer = args[1]
if printer in printers:
- await bot.send_text(room, f'Printing with {printer} here.')
+ await bot.send_text(room, f'Printing with {printer} here.', event)
self.printers[room.room_id] = printer
bot.save_settings()
else:
- await bot.send_text(room, f'No printer called {printer} in your CUPS.')
+ await bot.send_text(room, f'No printer called {printer} in your CUPS.', event)
if args[0] == 'setpapersize':
self.paper_size = args[1]
bot.save_settings()
- await bot.send_text(room, f'Paper size set to {self.paper_size}.')
+ await bot.send_text(room, f'Paper size set to {self.paper_size}.', event)
def help(self):
return 'Print files from Matrix'
diff --git a/modules/pt.py b/modules/pt.py
index 4b4440c..2dcd0f9 100644
--- a/modules/pt.py
+++ b/modules/pt.py
@@ -10,6 +10,7 @@
class PeerTubeClient:
def __init__(self):
self.instance_url = 'https://sepiasearch.org/'
+ self.client = PeerTubeClient()
def search(self, search_string, count=0):
if count == 0:
@@ -19,6 +20,15 @@ def search(self, search_string, count=0):
response = urllib.request.urlopen(search_url)
data = json.loads(response.read().decode("utf-8"))
return data
+ def videos(self, params):
+ params = urlencode(params, quote_via=quote_plus)
+ query_url = self.instance_url + 'api/v1/videos?' + params
+ response = urllib.request.urlopen(query_url)
+ data = json.loads(response.read().decode("utf-8"))
+ return data
+
+ def getlive(self, count=1):
+ return self.videos({'isLive': 1, 'count': count})
class MatrixModule(BotModule):
def __init__(self, name):
@@ -29,19 +39,36 @@ def matrix_start(self, bot):
super().matrix_start(bot)
self.add_module_aliases(bot, ['ptall'])
+ def format_video(self, video):
+ video_url = video.get("url") or self.instance_url + 'videos/watch/' + video["uuid"]
+ duration = time.strftime('%H:%M:%S', time.gmtime(video["duration"]))
+ instancedata = video["account"]["host"]
+ html = f'{video["name"]} {video["description"] or ""} [{duration}] @ {instancedata}'
+ text = f'{video_url} : {video["name"]} {video.get("description") or ""} [{duration}]'
+ return (html, text)
+
async def matrix_message(self, bot, room, event):
args = event.body.split()
if len(args) == 3:
if args[1] == "setinstance":
bot.must_be_owner(event)
- self.instance_url = args[2]
+ self.client.instance_url = args[2]
bot.save_settings()
- await bot.send_text(room, 'Instance url set to ' + self.instance_url, bot_ignore=True)
+ await bot.send_text(room, 'Instance url set to ' + self.instance_url, bot_ignore=True, event=event)
+ return
+ if args[1] == "live":
+ data = self.client.getlive()
+ if len(data['data']):
+ for video in data['data']:
+ html, text = self.format_video(video)
+ await bot.send_html(room, event, html, text, bot_ignore=True)
+ else:
+ await bot.send_text(room, 'Sorry, no livestreams found.', bot_ignore=True, event=event)
return
if len(args) == 2:
if args[1] == "showinstance":
- await bot.send_text(room, 'Using instance at ' + self.instance_url, bot_ignore=True)
+ await bot.send_text(room, 'Using instance at ' + self.instance_url, bot_ignore=True, event)
return
if len(args) > 1:
@@ -59,22 +86,22 @@ async def matrix_message(self, bot, room, event):
instancedata = video["account"]["host"]
html = f'{video["name"]} {video["description"] or ""} [{duration}] @ {instancedata}'
text = f'{video_url} : {video["name"]} {video.get("description") or ""} [{duration}]'
- await bot.send_html(room, html, text, bot_ignore=True)
+ await bot.send_html(room, html, text, event, bot_ignore=True)
else:
- await bot.send_text(room, 'Sorry, no videos found found.', bot_ignore=True)
+ await bot.send_text(room, 'Sorry, no videos found found.', event, bot_ignore=True)
else:
- await bot.send_text(room, 'Usage: !pt or !ptall to return all results')
+ await bot.send_text(room, 'Usage: !pt or !ptall to return all results', event)
def get_settings(self):
data = super().get_settings()
- data['instance_url'] = self.instance_url
+ data['instance_url'] = self.client.instance_url
return data
def set_settings(self, data):
super().set_settings(data)
if data.get("instance_url"):
- self.instance_url = data["instance_url"]
+ self.client.instance_url = data["instance_url"]
def help(self):
return ('PeerTube search')
diff --git a/modules/rasp.py b/modules/rasp.py
index 1a2c3f5..005055d 100644
--- a/modules/rasp.py
+++ b/modules/rasp.py
@@ -13,7 +13,7 @@ async def matrix_message(self, bot, room, event):
hour = int(args[1])
imgurl = 'http://ennuste.ilmailuliitto.fi/' + str(day) + '/wstar_bsratio.curr.' + str(hour) + '00lst.d2.png'
- await bot.upload_and_send_image(room, imgurl, f"RASP Day {day+1} at {hour}:00", no_cache=True)
+ await bot.upload_and_send_image(room, imgurl, f"RASP Day {day+1} at {hour}:00", event=event, no_cache=True)
def help(self):
return 'RASP Gliding Weather forecast, Finland only'
diff --git a/modules/relay.py b/modules/relay.py
index e9a2153..26757c9 100644
--- a/modules/relay.py
+++ b/modules/relay.py
@@ -34,7 +34,7 @@ async def message_cb(self, room, event):
sendernick = target_room.user_name(event.sender)
if not sendernick:
sendernick = event.sender
- await self.bot.send_text(target_room, f'<{sendernick}> {event.body}', msgtype="m.text", bot_ignore=True)
+ await self.bot.send_text(target_room, f'<{sendernick}> {event.body}', msgtype="m.text", bot_ignore=True, event)
else:
self.logger.warning(f"Bot doesn't seem to be in bridged room {target_id}")
@@ -72,25 +72,25 @@ async def matrix_message(self, bot, room, event):
msg += f'{i}: {srcroom} <-> {tgtroom}'
i = i + 1
- await bot.send_text(room, msg)
+ await bot.send_text(room, msg, event)
if len(args) == 2:
if args[0] == 'bridge':
roomid = args[1]
room_to_bridge = bot.get_room_by_id(roomid)
if room_to_bridge:
- await bot.send_text(room, f'Bridging {room_to_bridge.display_name} here.')
+ await bot.send_text(room, f'Bridging {room_to_bridge.display_name} here.', event)
self.bridges[room.room_id] = roomid
bot.save_settings()
else:
- await bot.send_text(room, f'I am not on room with id {roomid} (note: use id, not alias)!')
+ await bot.send_text(room, f'I am not on room with id {roomid} (note: use id, not alias)!', event)
elif args[0] == 'unbridge':
idx = int(args[1]) - 1
i = 0
for src_id, tgt_id in self.bridges.items():
if i == idx:
del self.bridges[src_id]
- await bot.send_text(room, f'Unbridged {src_id} and {tgt_id}.')
+ await bot.send_text(room, f'Unbridged {src_id} and {tgt_id}.', event)
bot.save_settings()
return
i = i + 1
diff --git a/modules/taf.py b/modules/taf.py
index dfe018a..6094393 100644
--- a/modules/taf.py
+++ b/modules/taf.py
@@ -13,11 +13,11 @@ async def matrix_message(self, bot, room, event):
lines = response.readlines()
if len(lines) > 6:
taf = lines[6].decode("utf-8").split(',')[0]
- await bot.send_text(room, taf.strip())
+ await bot.send_text(room, taf.strip(), event)
else:
- await bot.send_text(room, 'Cannot find taf for ' + icao)
+ await bot.send_text(room, 'Cannot find taf for ' + icao, event)
else:
- await bot.send_text(room, 'Usage: !taf ')
+ await bot.send_text(room, 'Usage: !taf ', event)
def help(self):
return ('Taf data access (usage: !taf )')
diff --git a/modules/tautulli.py b/modules/tautulli.py
index 89c1e3c..2d7aba8 100644
--- a/modules/tautulli.py
+++ b/modules/tautulli.py
@@ -174,11 +174,11 @@ async def matrix_message(self, bot, room, event):
self.api_key = args[2]
bot.save_settings()
- await bot.send_text(room, 'Api key set')
+ await bot.send_text(room, 'Api key set', event)
elif len(args) == 2:
media_type = args[1]
if media_type != "movie" and media_type != "show" and media_type != "artist":
- await bot.send_text(room, "media type '%s' provided not valid" % media_type)
+ await bot.send_text(room, "media type '%s' provided not valid" % media_type, event)
return
try:
@@ -187,7 +187,7 @@ async def matrix_message(self, bot, room, event):
connection = urllib.request.urlopen(req).read()
entries = json.loads(connection)
if "response" not in entries and "data" not in entries["response"] and "recently_added" not in entries["response"]["data"]:
- await bot.send_text(room, "no recently added for %s" % media_type)
+ await bot.send_text(room, "no recently added for %s" % media_type, event)
return
for entry in entries["response"]["data"]["recently_added"]:
@@ -197,24 +197,24 @@ async def matrix_message(self, bot, room, event):
raise ValueError(err.read())
except Exception as exc:
message = str(exc)
- await bot.send_text(room, message)
+ await bot.send_text(room, message, event)
elif len(args) == 4:
if args[1] == "add" or args[1] == "remove":
room_id = args[2]
encrypted = args[3]
if args[1] == "add":
self.rooms[room_id] = encrypted == "encrypted"
- await bot.send_text(room, f"Added {room_id} to rooms notification list")
+ await bot.send_text(room, f"Added {room_id} to rooms notification list", event)
else:
del self.rooms[room_id]
- await bot.send_text(room, f"Removed {room_id} to rooms notification list")
+ await bot.send_text(room, f"Removed {room_id} to rooms notification list", event)
bot.save_settings()
self.httpd.rooms = self.rooms
else:
- await bot.send_text(room, 'Usage: !tautulli | %room_id% %encrypted%')
+ await bot.send_text(room, 'Usage: !tautulli | %room_id% %encrypted%', event)
else:
- await bot.send_text(room, 'Usage: !tautulli | %room_id% %encrypted%')
+ await bot.send_text(room, 'Usage: !tautulli | %room_id% %encrypted%', event)
def get_settings(self):
data = super().get_settings()
diff --git a/modules/teamup.py b/modules/teamup.py
index 2333a17..1b03f23 100644
--- a/modules/teamup.py
+++ b/modules/teamup.py
@@ -38,10 +38,10 @@ async def matrix_message(self, bot, room, event):
"%H:%M") + ' (' + str(event.duration) + ' min)'
s = s + ' ' + event.title + \
" " + (event.notes or '')
- await bot.send_html(room, s, s)
+ await bot.send_html(room, s, s, event)
elif len(args) == 2:
if args[1] == 'list':
- await bot.send_text(room, f'Calendars in this room: {self.calendar_rooms.get(room.room_id) or []}')
+ await bot.send_text(room, f'Calendars in this room: {self.calendar_rooms.get(room.room_id) or []}', event)
elif args[1] == 'poll':
bot.must_be_owner(event)
await self.poll_all_calendars(bot)
@@ -56,7 +56,7 @@ async def matrix_message(self, bot, room, event):
if calid not in self.calendar_rooms[room.room_id]:
self.calendar_rooms[room.room_id].append(calid)
else:
- await bot.send_text(room, 'This teamup calendar already added in this room!')
+ await bot.send_text(room, 'This teamup calendar already added in this room!', event)
return
else:
self.calendar_rooms[room.room_id] = [calid]
@@ -65,7 +65,7 @@ async def matrix_message(self, bot, room, event):
bot.save_settings()
self.setup_calendars()
- await bot.send_text(room, 'Added new teamup calendar to this room')
+ await bot.send_text(room, 'Added new teamup calendar to this room', event)
if args[1] == 'del':
bot.must_be_admin(room, event)
@@ -79,14 +79,14 @@ async def matrix_message(self, bot, room, event):
bot.save_settings()
self.setup_calendars()
- await bot.send_text(room, 'Removed teamup calendar from this room')
+ await bot.send_text(room, 'Removed teamup calendar from this room', event)
if args[1] == 'apikey':
bot.must_be_owner(event)
self.api_key = args[2]
bot.save_settings()
self.setup_calendars()
- await bot.send_text(room, 'Api key set')
+ await bot.send_text(room, 'Api key set', event)
def help(self):
return ('Polls teamup calendar.')
diff --git a/modules/url.py b/modules/url.py
index 954890b..61a9e0e 100644
--- a/modules/url.py
+++ b/modules/url.py
@@ -144,7 +144,7 @@ async def text_cb(self, room, event):
msg = f"Description: {description}"
if msg.strip(): # Evaluates to true on non-empty strings
- await self.bot.send_text(room, msg, msgtype=self.type, bot_ignore=True)
+ await self.bot.send_text(room, msg, msgtype=self.type, bot_ignore=True, event)
except Exception as e:
self.logger.warning(f"Unexpected error in url module text_cb: {e}")
traceback.print_exc(file=sys.stderr)
@@ -257,7 +257,7 @@ async def matrix_message(self, bot, room, event):
bot.must_be_owner(event)
self.type = "m.notice"
bot.save_settings()
- await bot.send_text(room, "Sending titles as notices from now on.")
+ await bot.send_text(room, "Sending titles as notices from now on.", event)
return
# show status
@@ -265,7 +265,7 @@ async def matrix_message(self, bot, room, event):
bot.must_be_owner(event)
self.type = "m.text"
bot.save_settings()
- await bot.send_text(room, "Sending titles as text from now on.")
+ await bot.send_text(room, "Sending titles as text from now on.", event)
return
# set blacklist
@@ -276,7 +276,7 @@ async def matrix_message(self, bot, room, event):
else:
self.blacklist = args[1].split(',')
bot.save_settings()
- await bot.send_text(room, f"Blacklisted URLs set to {self.blacklist}")
+ await bot.send_text(room, f"Blacklisted URLs set to {self.blacklist}", event)
return
# invalid command
diff --git a/modules/users.py b/modules/users.py
index c36651c..4ca6d38 100644
--- a/modules/users.py
+++ b/modules/users.py
@@ -21,7 +21,7 @@ async def matrix_message(self, bot, room, event):
allusers = self.get_users(bot, room.room_id)
total = len(allusers)
if total == 0:
- await bot.send_text(room, "I don't see any users. How did this happen?")
+ await bot.send_text(room, "I don't see any users. How did this happen?", event)
return
matched = 0
@@ -31,7 +31,7 @@ async def matrix_message(self, bot, room, event):
if match:
stats[name] = stats[name] + 1
matched = matched + 1
-
+
stats['Matrix'] = total - matched
stats = dict(sorted(stats.items(), key=lambda item: item[1], reverse=True))
@@ -42,7 +42,7 @@ async def matrix_message(self, bot, room, event):
for name in stats:
if stats[name] > 0:
reply = reply + f' - {name}: {stats[name]} ({round(stats[name] / total * 100, 2)}%)\n'
- await bot.send_text(room, reply)
+ await bot.send_text(room, reply, event)
return
if len(args) == 2:
if args[0] == 'list' or args[0] == 'listall':
@@ -53,9 +53,9 @@ async def matrix_message(self, bot, room, event):
allusers = self.get_users(bot, search_room)
users = fnmatch.filter(allusers, args[1])
if len(users):
- await bot.send_text(room, ' '.join(users))
+ await bot.send_text(room, ' '.join(users), event)
else:
- await bot.send_text(room, 'No matching users found!')
+ await bot.send_text(room, 'No matching users found!', event)
return
if args[0] == 'kick':
bot.must_be_admin(room, event)
@@ -66,11 +66,11 @@ async def matrix_message(self, bot, room, event):
self.logger.debug(f"Kicking {user} from {room.room_id} as requested by {event.sender}")
await bot.client.room_kick(room.room_id, user)
else:
- await bot.send_text(room, 'No matching users found!')
+ await bot.send_text(room, 'No matching users found!', event)
return
if args[0] == 'classify':
if args[1] == 'list':
- await bot.send_text(room, f'Classes in use: {self.classes}.')
+ await bot.send_text(room, f'Classes in use: {self.classes}.', event)
return
elif len(args) == 4:
if args[0] == 'classify':
@@ -79,7 +79,7 @@ async def matrix_message(self, bot, room, event):
name = args[2]
pattern = args[3]
self.classes[name] = pattern
- await bot.send_text(room, f'Added class {name} pattern {pattern}.')
+ await bot.send_text(room, f'Added class {name} pattern {pattern}.', event)
bot.save_settings()
return
elif len(args) == 3:
@@ -88,11 +88,11 @@ async def matrix_message(self, bot, room, event):
bot.must_be_owner(event)
name = args[2]
del self.classes[name]
- await bot.send_text(room, f'Deleted class {name}.')
+ await bot.send_text(room, f'Deleted class {name}.', event)
bot.save_settings()
return
- await bot.send_text(room, 'Unknown command - please see readme')
+ await bot.send_text(room, 'Unknown command - please see readme', event)
def get_users(self, bot, roomid=None):
allusers = []
@@ -127,4 +127,4 @@ def set_settings(self, data):
def matrix_start(self, bot):
super().matrix_start(bot)
- self.bot = bot
\ No newline at end of file
+ self.bot = bot
diff --git a/modules/wa.py b/modules/wa.py
index 5b38fb1..a11118f 100644
--- a/modules/wa.py
+++ b/modules/wa.py
@@ -19,12 +19,12 @@ async def matrix_message(self, bot, room, event):
bot.must_be_owner(event)
self.app_id = args[2]
bot.save_settings()
- await bot.send_text(room, 'App id set')
+ await bot.send_text(room, 'App id set', event)
return
if len(args) > 1:
if self.app_id == '':
- await bot.send_text(room, 'Please get and set a appid: https://products.wolframalpha.com/simple-api/documentation/')
+ await bot.send_text(room, 'Please get and set a appid: https://products.wolframalpha.com/simple-api/documentation/', event)
return
query = event.body[len(args[0])+1:]
@@ -43,9 +43,9 @@ async def matrix_message(self, bot, room, event):
else:
plain = 'Could not find response for ' + query
html = plain
- await bot.send_html(room, html, plain)
+ await bot.send_html(room, html, plain, event)
else:
- await bot.send_text(room, 'Usage: !wa ')
+ await bot.send_text(room, 'Usage: !wa ', event)
def get_settings(self):
data = super().get_settings()