This commit releases a custom Matrix Python SDK. This means that the most important classes---MatrixClient, Room, and MatrixHttpApi---are inherited by Custom classes. This enables us to change behaviour or add new features in a well structured and predictable way. The first issue that is solved with this new custom SDK is the problem that was introduced in #2.
This commit is contained in:
parent
e4d325955c
commit
9e139a0f3e
10
matrix_bot_api/custom_matrix_client/api.py
Normal file
10
matrix_bot_api/custom_matrix_client/api.py
Normal file
@ -0,0 +1,10 @@
|
||||
from matrix_client.api import MatrixHttpApi
|
||||
|
||||
class CustomMatrixHttpApi(MatrixHttpApi):
|
||||
def __init__(
|
||||
self, base_url, token=None, identity=None,
|
||||
default_429_wait_ms=5000,
|
||||
use_authorization_header=True
|
||||
):
|
||||
|
||||
super().__init__(base_url, token, identity, default_429_wait_ms)
|
76
matrix_bot_api/custom_matrix_client/client.py
Normal file
76
matrix_bot_api/custom_matrix_client/client.py
Normal file
@ -0,0 +1,76 @@
|
||||
import os
|
||||
import hjson
|
||||
|
||||
from matrix_client.client import MatrixClient
|
||||
|
||||
from .api import CustomMatrixHttpApi
|
||||
from .room import CustomRoom
|
||||
|
||||
MESSAGES_DIR = os.path.join(os.path.dirname(__file__), 'messages')
|
||||
MESSAGES_LOCATION = MESSAGES_DIR + '/messages.dutch.hjson'
|
||||
|
||||
class CustomMatrixClient(MatrixClient):
|
||||
def __init__(self, base_url, token=None):
|
||||
super().__init__(base_url, token)
|
||||
|
||||
self.api = CustomMatrixHttpApi(base_url, token)
|
||||
|
||||
# Load messages
|
||||
with open(MESSAGES_LOCATION) as hjson_data:
|
||||
self.messages = hjson.load(hjson_data)
|
||||
|
||||
|
||||
def _mkroom(self, room_id):
|
||||
room = CustomRoom(self, room_id)
|
||||
|
||||
self.rooms[room_id] = room
|
||||
return self.rooms[room_id]
|
||||
|
||||
def create_direct_room(self, invitees=None):
|
||||
content = {
|
||||
"visibility": "private",
|
||||
"is_direct": True,
|
||||
"invite": [invitees]
|
||||
}
|
||||
|
||||
room_dict = self.api._send("POST", "/createRoom", content)
|
||||
|
||||
return self._mkroom(room_dict["room_id"])
|
||||
|
||||
|
||||
def send_message_private_public(self, room, event, message):
|
||||
"""This method takes a room, event, and message and makes sure
|
||||
that the message is sent in a private room and not in a public
|
||||
room. If no private room exists, it will create a private room
|
||||
with the sender of the event.
|
||||
"""
|
||||
|
||||
orig_room = room
|
||||
found_room = False
|
||||
|
||||
for room_id, room in self.rooms.items():
|
||||
joined_members = room.get_joined_members()
|
||||
|
||||
# Check for rooms with only two members
|
||||
if len(joined_members) == 2:
|
||||
# Check if sender is in that room
|
||||
for member in joined_members:
|
||||
if event['sender'] == member.user_id:
|
||||
found_room = True
|
||||
|
||||
if found_room:
|
||||
# If the flag is set, we do not need to check further rooms
|
||||
break
|
||||
|
||||
# Send help message to an existing room or to a new room
|
||||
if found_room:
|
||||
room.send_html(message)
|
||||
else:
|
||||
room = self.create_direct_room(event['sender']);
|
||||
room.send_html(message)
|
||||
|
||||
if room != orig_room:
|
||||
display_name_sender = self.api.get_display_name(event['sender'])
|
||||
orig_room.send_text(self.messages['private_message'].format(
|
||||
display_name_sender))
|
||||
|
6
matrix_bot_api/custom_matrix_client/room.py
Normal file
6
matrix_bot_api/custom_matrix_client/room.py
Normal file
@ -0,0 +1,6 @@
|
||||
from matrix_client.room import Room
|
||||
|
||||
|
||||
class CustomRoom(Room):
|
||||
def __init__(self, client, room_id):
|
||||
super().__init__(client, room_id)
|
@ -9,17 +9,16 @@ import datetime as dt
|
||||
|
||||
from pip._internal import main as pipmain
|
||||
|
||||
from matrix_client.client import MatrixClient
|
||||
from matrix_client.api import MatrixRequestError, MatrixHttpApi
|
||||
from matrix_client.user import User
|
||||
|
||||
from matrix_client.api import MatrixRequestError
|
||||
from matrix_bot_api.mregex_handler import MRegexHandler
|
||||
|
||||
from .custom_matrix_client.api import CustomMatrixHttpApi
|
||||
from .custom_matrix_client.client import CustomMatrixClient
|
||||
|
||||
MESSAGES_DIR = os.path.join(os.path.dirname(__file__), 'messages')
|
||||
DATA_LOCATION = os.path.join(os.path.dirname(__file__), '../data/bot.db')
|
||||
|
||||
HELP_LOCATION = MESSAGES_DIR + '/help'
|
||||
MESSAGES_LOCATION = MESSAGES_DIR + '/messages.dutch.hjson'
|
||||
|
||||
def eprint(*args, **kwargs):
|
||||
"""Print error messages to stderr"""
|
||||
@ -32,7 +31,8 @@ class MatrixBotAPI:
|
||||
self.username = self.config['bot_credentials']['username']
|
||||
|
||||
# Authenticate with given credentials
|
||||
self.client = MatrixClient(self.config['bot_credentials']['server'])
|
||||
self.client = CustomMatrixClient(
|
||||
self.config['bot_credentials']['server'])
|
||||
try:
|
||||
self.token = self.client.login_with_password(
|
||||
self.config['bot_credentials']['username'],
|
||||
@ -41,13 +41,11 @@ class MatrixBotAPI:
|
||||
print(e)
|
||||
if e.code == 403:
|
||||
print("Bad username/password")
|
||||
sys.exit()
|
||||
except Exception as e:
|
||||
print("Invalid server URL")
|
||||
traceback.print_exc()
|
||||
|
||||
self.api = MatrixHttpApi(
|
||||
self.config['bot_credentials']['server'],
|
||||
token=self.token)
|
||||
sys.exit()
|
||||
|
||||
# Store allowed rooms
|
||||
self.rooms = rooms
|
||||
@ -63,7 +61,7 @@ class MatrixBotAPI:
|
||||
|
||||
# Add all rooms we're currently in to self.rooms and add their
|
||||
# callbacks
|
||||
for room_id, room in self.client.get_rooms().items():
|
||||
for room_id, room in self.client.rooms.items():
|
||||
room.add_listener(self.handle_message)
|
||||
self.rooms.append(room_id)
|
||||
else:
|
||||
@ -86,10 +84,6 @@ class MatrixBotAPI:
|
||||
self.config['triggers']['help'], self.help)
|
||||
self.add_handler(self.help_handler)
|
||||
|
||||
# Load messages
|
||||
with open(MESSAGES_LOCATION) as hjson_data:
|
||||
self.messages = hjson.load(hjson_data)
|
||||
|
||||
|
||||
def add_plugins(self):
|
||||
"""Acquire list of plugins from configuration, load them,
|
||||
@ -103,30 +97,31 @@ class MatrixBotAPI:
|
||||
# ./plugins directory
|
||||
modules = []
|
||||
|
||||
#try:
|
||||
try:
|
||||
# Loop through the available plugins, install their requirements,
|
||||
# load them as module, run their setup, append them to a list,
|
||||
# and add their handler variables
|
||||
for i, plugin in enumerate(self.config['plugins']):
|
||||
# Install requirements
|
||||
self.install_requirements(plugin)
|
||||
for i, plugin in enumerate(self.config['plugins']):
|
||||
# Install requirements
|
||||
self.install_requirements(plugin)
|
||||
|
||||
# Dynamically load the module
|
||||
modules.append(
|
||||
importlib.import_module(
|
||||
"plugins.{0}.{0}".format(plugin), package = None))
|
||||
# Dynamically load the module
|
||||
modules.append(
|
||||
importlib.import_module(
|
||||
"plugins.{0}.{0}".format(plugin), package = None))
|
||||
|
||||
# Run the module's setup function and save that it got installed
|
||||
self.setup_plugin(modules[i])
|
||||
# Run the module's setup function and save that it got installed
|
||||
self.setup_plugin(modules[i])
|
||||
|
||||
# Create new instance of plugin and append to plugin_objects array
|
||||
self.plugin_objects.append(modules[i].Plugin(self))
|
||||
# Create new instance of plugin and append to plugin_objects array
|
||||
self.plugin_objects.append(modules[i].Plugin(self))
|
||||
|
||||
# Add handler of newly created instance to bot
|
||||
self.add_handler(self.plugin_objects[i].handler)
|
||||
#except:
|
||||
# eprint("Importing one or more of the plugins did not go well!")
|
||||
# sys.exit()
|
||||
# Add handler of newly created instance to bot
|
||||
self.add_handler(self.plugin_objects[i].handler)
|
||||
except:
|
||||
eprint("Importing one or more of the plugins did not go well!")
|
||||
traceback.print_exc()
|
||||
sys.exit()
|
||||
|
||||
def check_installation_plugin(self, module_name):
|
||||
"""Function returns 0 if a plugin with that name is not
|
||||
@ -175,10 +170,10 @@ class MatrixBotAPI:
|
||||
print(f"Running installation of {module_name}.")
|
||||
|
||||
# Run module's install method
|
||||
#try:
|
||||
module.setup()
|
||||
#except:
|
||||
# print(f"{module_name} did not specify setup(). Skipping...")
|
||||
try:
|
||||
module.setup()
|
||||
except:
|
||||
print(f"{module_name} did not specify setup(). Skipping...")
|
||||
|
||||
# Save in database that we installed this plugin
|
||||
datetime_added = dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
@ -238,42 +233,6 @@ class MatrixBotAPI:
|
||||
# Do nothing, data directory already exists
|
||||
pass
|
||||
|
||||
def send_message_private_public(self, room, event, message):
|
||||
"""This method takes a room, event, and message and makes sure
|
||||
that the message is sent in a private room and not in a public
|
||||
room. If no private room exists, it will create a private room
|
||||
with the sender of the event.
|
||||
"""
|
||||
|
||||
orig_room = room
|
||||
found_room = False
|
||||
|
||||
for room_id, room in self.client.get_rooms().items():
|
||||
joined_members = room.get_joined_members()
|
||||
|
||||
# Check for rooms with only two members
|
||||
if len(joined_members) == 2:
|
||||
# Check if sender is in that room
|
||||
for member in joined_members:
|
||||
if event['sender'] == member.user_id:
|
||||
found_room = True
|
||||
|
||||
if found_room:
|
||||
# If the flag is set, we do not need to check further rooms
|
||||
break
|
||||
|
||||
# Send help message to an existing room or to a new room
|
||||
if found_room:
|
||||
room.send_html(message)
|
||||
else:
|
||||
room = self.client.create_room(invitees=[event['sender']]);
|
||||
room.send_html(message)
|
||||
|
||||
if room != orig_room:
|
||||
display_name_sender = self.api.get_display_name(event['sender'])
|
||||
orig_room.send_text(self.messages['private_message'].format(
|
||||
display_name_sender))
|
||||
|
||||
def help(self, room, event):
|
||||
"""Prints a general help message and then grabs all help
|
||||
messages from the different plugins
|
||||
@ -288,7 +247,7 @@ class MatrixBotAPI:
|
||||
# The plugin probably returned 0, ignore it
|
||||
pass
|
||||
|
||||
self.send_message_private_public(room, event, help_text)
|
||||
self.client.send_message_private_public(room, event, help_text)
|
||||
|
||||
def add_handler(self, handler):
|
||||
try:
|
||||
@ -327,4 +286,5 @@ class MatrixBotAPI:
|
||||
def start_polling(self):
|
||||
# Starts polling for messages
|
||||
self.client.start_listener_thread()
|
||||
|
||||
return self.client.sync_thread
|
||||
|
@ -146,7 +146,7 @@ class Plugin:
|
||||
if row[1] in mapping[0]:
|
||||
# We got a winner!
|
||||
|
||||
for i, room in self.bot.client.get_rooms().items():
|
||||
for i, room in self.bot.client.rooms.items():
|
||||
if room.display_name in mapping[1]:
|
||||
room.send_html(
|
||||
self.messages["new_event"].format(
|
||||
|
Loading…
Reference in New Issue
Block a user