From 8fd56ade57bfe04e9be186b6cd7172886b123a92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=9C=E5=9D=82=E9=9B=85?= <23130178+ShadowRZ@users.noreply.github.com> Date: Fri, 9 Sep 2022 14:47:13 +0800 Subject: [PATCH] Update --- nyx_bot/bot_commands.py | 11 ++-- nyx_bot/callbacks.py | 12 ++-- nyx_bot/chat_functions.py | 2 +- nyx_bot/config.py | 15 +++++ nyx_bot/errors.py | 10 ++++ nyx_bot/exceptions.py | 8 --- nyx_bot/main.py | 21 ++----- nyx_bot/quote_image.py | 2 +- nyx_bot/storage.py | 123 +------------------------------------- sample.config.yaml | 4 ++ setup.py | 3 +- 11 files changed, 48 insertions(+), 163 deletions(-) delete mode 100644 nyx_bot/exceptions.py diff --git a/nyx_bot/bot_commands.py b/nyx_bot/bot_commands.py index 45b7fa7..418963a 100644 --- a/nyx_bot/bot_commands.py +++ b/nyx_bot/bot_commands.py @@ -4,8 +4,7 @@ from nio import AsyncClient, MatrixRoom, RoomMessageImage, RoomMessageText, Stic from nyx_bot.chat_functions import send_quote_image, send_text_to_room, send_user_image from nyx_bot.config import Config -from nyx_bot.exceptions import NyxBotValueError -from nyx_bot.storage import Storage +from nyx_bot.errors import NyxBotValueError logger = logging.getLogger(__name__) @@ -14,7 +13,6 @@ class Command: def __init__( self, client: AsyncClient, - store: Storage, config: Config, command: str, room: MatrixRoom, @@ -27,8 +25,6 @@ class Command: Args: client: The client to communicate to matrix with. - store: Bot storage. - config: Bot configuration parameters. command: The command and arguments. @@ -38,7 +34,6 @@ class Command: event: The event describing the command. """ self.client = client - self.store = store self.config = config self.command = command self.room = room @@ -107,7 +102,9 @@ class Command: f"https://matrix.to/#/{self.room.room_id}/{target_event.event_id}" ) content["body"] = f"Sticker of {matrixdotto_url}" - content["m.relates_to"] = {"m.in_reply_to": {"event_id": self.event.event_id}} + content["m.relates_to"] = { + "m.in_reply_to": {"event_id": self.event.event_id} + } await self.client.room_send( self.room.room_id, message_type="m.sticker", content=content ) diff --git a/nyx_bot/callbacks.py b/nyx_bot/callbacks.py index 92c32e5..38314bc 100644 --- a/nyx_bot/callbacks.py +++ b/nyx_bot/callbacks.py @@ -14,25 +14,22 @@ from nio import ( from nyx_bot.bot_commands import Command from nyx_bot.chat_functions import send_exception, send_jerryxiao from nyx_bot.config import Config -from nyx_bot.storage import Storage from nyx_bot.utils import get_reply_to logger = logging.getLogger(__name__) class Callbacks: - def __init__(self, client: AsyncClient, store: Storage, config: Config): + def __init__(self, client: AsyncClient, config: Config): """ Args: client: nio client used to interact with matrix. - store: Bot storage. - config: Bot configuration parameters. """ self.client = client - self.store = store self.config = config + self.disable_jerryxiao_for = config.disable_jerryxiao_for self.command_prefix = config.command_prefix self.replace_map = {} @@ -85,6 +82,10 @@ class Callbacks: msg = i break + if room.room_id in self.disable_jerryxiao_for: + # Stop considering JerryXiao prefix. + has_jerryxiao_prefix = False + if has_jerryxiao_prefix and reply_to: if msg.startswith("/"): await send_jerryxiao(self.client, room, event, "/", reply_to, msg) @@ -106,7 +107,6 @@ class Callbacks: command = Command( self.client, - self.store, self.config, msg, room, diff --git a/nyx_bot/chat_functions.py b/nyx_bot/chat_functions.py index 76e4bb7..88ec409 100644 --- a/nyx_bot/chat_functions.py +++ b/nyx_bot/chat_functions.py @@ -18,7 +18,7 @@ from nio import ( ) from wand.image import Image -from nyx_bot.exceptions import NyxBotRuntimeError, NyxBotValueError +from nyx_bot.errors import NyxBotRuntimeError, NyxBotValueError from nyx_bot.parsers import MatrixHTMLParser from nyx_bot.quote_image import make_quote_image from nyx_bot.utils import ( diff --git a/nyx_bot/config.py b/nyx_bot/config.py index 1385b9c..a21b32e 100644 --- a/nyx_bot/config.py +++ b/nyx_bot/config.py @@ -105,6 +105,10 @@ class Config: self.command_prefix = self._get_cfg(["command_prefix"], default="!c") + " " + self.disable_jerryxiao_for = self._get_cfg(['disable_jerryxiao_for'], []) + if isinstance(self.disable_jerryxiao_for, list): + raise ConfigError("disable_jerryxiao_for should be a list of room ID") + def _get_cfg( self, path: List[str], @@ -134,3 +138,14 @@ class Config: # We found the option. Return it. return config + + +# Read user-configured options from a config file. +# A different config file path can be specified as the first command line argument +if len(sys.argv) > 1: + config_path = sys.argv[1] +else: + config_path = "config.yaml" + +# Read the parsed config file and create a Config object +config = Config(config_path) diff --git a/nyx_bot/errors.py b/nyx_bot/errors.py index 7ec2414..2a476a5 100644 --- a/nyx_bot/errors.py +++ b/nyx_bot/errors.py @@ -10,3 +10,13 @@ class ConfigError(RuntimeError): def __init__(self, msg: str): super(ConfigError, self).__init__("%s" % (msg,)) + + +class NyxBotValueError(ValueError): + def __init__(self, reason): + super().__init__(reason) + + +class NyxBotRuntimeError(RuntimeError): + def __init__(self, reason): + super().__init__(reason) diff --git a/nyx_bot/exceptions.py b/nyx_bot/exceptions.py deleted file mode 100644 index 4ab5da5..0000000 --- a/nyx_bot/exceptions.py +++ /dev/null @@ -1,8 +0,0 @@ -class NyxBotValueError(ValueError): - def __init__(self, reason): - super().__init__(reason) - - -class NyxBotRuntimeError(RuntimeError): - def __init__(self, reason): - super().__init__(reason) diff --git a/nyx_bot/main.py b/nyx_bot/main.py index 9ef13fe..4f096b3 100644 --- a/nyx_bot/main.py +++ b/nyx_bot/main.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 import asyncio import logging -import sys from asyncio.exceptions import TimeoutError from time import sleep @@ -15,10 +14,10 @@ from nio import ( RoomMessageText, UnknownEvent, ) +from nio.store.database import DefaultStore from nyx_bot.callbacks import Callbacks -from nyx_bot.config import Config -from nyx_bot.storage import Storage +from nyx_bot.config import config logger = logging.getLogger(__name__) @@ -26,23 +25,11 @@ logger = logging.getLogger(__name__) async def main(): """The first function that is run when starting the bot""" - # Read user-configured options from a config file. - # A different config file path can be specified as the first command line argument - if len(sys.argv) > 1: - config_path = sys.argv[1] - else: - config_path = "config.yaml" - - # Read the parsed config file and create a Config object - config = Config(config_path) - - # Configure the database - store = Storage(config.database) - # Configuration options for the AsyncClient client_config = AsyncClientConfig( max_limit_exceeded=0, max_timeouts=0, + store=DefaultStore, store_sync_tokens=True, encryption_enabled=False, ) @@ -61,7 +48,7 @@ async def main(): client.user_id = config.user_id # Set up event callbacks - callbacks = Callbacks(client, store, config) + callbacks = Callbacks(client, config) client.add_event_callback(callbacks.message, (RoomMessageText,)) client.add_event_callback(callbacks.unknown, (UnknownEvent,)) client.add_event_callback( diff --git a/nyx_bot/quote_image.py b/nyx_bot/quote_image.py index 88c6fe7..b7de8d5 100644 --- a/nyx_bot/quote_image.py +++ b/nyx_bot/quote_image.py @@ -22,7 +22,7 @@ BORDER_MARGIN = 8 MASK_FILE = os.path.join(nyx_bot.__path__[0], "mask.png") PANGO_MARKUP_TEMPLATE = """\ -{} +{} {} """ diff --git a/nyx_bot/storage.py b/nyx_bot/storage.py index 580ebd1..fa46564 100644 --- a/nyx_bot/storage.py +++ b/nyx_bot/storage.py @@ -1,126 +1,5 @@ import logging -from typing import Any, Dict -# The latest migration version of the database. -# -# Database migrations are applied starting from the number specified in the database's -# `migration_version` table + 1 (or from 0 if this table does not yet exist) up until -# the version specified here. -# -# When a migration is performed, the `migration_version` table should be incremented. -latest_migration_version = 0 +# from peewee import Model, PostgresqlDatabase, SqliteDatabase, TextField logger = logging.getLogger(__name__) - - -class Storage: - def __init__(self, database_config: Dict[str, str]): - """Setup the database. - - Runs an initial setup or migrations depending on whether a database file has already - been created. - - Args: - database_config: a dictionary containing the following keys: - * type: A string, one of "sqlite" or "postgres". - * connection_string: A string, featuring a connection string that - be fed to each respective db library's `connect` method. - """ - self.conn = self._get_database_connection( - database_config["type"], database_config["connection_string"] - ) - self.cursor = self.conn.cursor() - self.db_type = database_config["type"] - - # Try to check the current migration version - migration_level = 0 - try: - self._execute("SELECT version FROM migration_version") - row = self.cursor.fetchone() - migration_level = row[0] - except Exception: - self._initial_setup() - finally: - if migration_level < latest_migration_version: - self._run_migrations(migration_level) - - logger.info(f"Database initialization of type '{self.db_type}' complete") - - def _get_database_connection( - self, database_type: str, connection_string: str - ) -> Any: - """Creates and returns a connection to the database""" - if database_type == "sqlite": - import sqlite3 - - # Initialize a connection to the database, with autocommit on - return sqlite3.connect(connection_string, isolation_level=None) - elif database_type == "postgres": - import psycopg2 - - conn = psycopg2.connect(connection_string) - - # Autocommit on - conn.set_isolation_level(0) - - return conn - - def _initial_setup(self) -> None: - """Initial setup of the database""" - logger.info("Performing initial database setup...") - - # Set up the migration_version table - self._execute( - """ - CREATE TABLE migration_version ( - version INTEGER PRIMARY KEY - ) - """ - ) - - # Initially set the migration version to 0 - self._execute( - """ - INSERT INTO migration_version ( - version - ) VALUES (?) - """, - (0,), - ) - - # Set up any other necessary database tables here - - logger.info("Database setup complete") - - def _run_migrations(self, current_migration_version: int) -> None: - """Execute database migrations. Migrates the database to the - `latest_migration_version`. - - Args: - current_migration_version: The migration version that the database is - currently at. - """ - logger.debug("Checking for necessary database migrations...") - - # if current_migration_version < 1: - # logger.info("Migrating the database from v0 to v1...") - # - # # Add new table, delete old ones, etc. - # - # # Update the stored migration version - # self._execute("UPDATE migration_version SET version = 1") - # - # logger.info("Database migrated to v1") - - def _execute(self, *args) -> None: - """A wrapper around cursor.execute that transforms placeholder ?'s to %s for postgres. - - This allows for the support of queries that are compatible with both postgres and sqlite. - - Args: - args: Arguments passed to cursor.execute. - """ - if self.db_type == "postgres": - self.cursor.execute(args[0].replace("?", "%s"), *args[1:]) - else: - self.cursor.execute(*args) diff --git a/sample.config.yaml b/sample.config.yaml index d33538e..14a556a 100644 --- a/sample.config.yaml +++ b/sample.config.yaml @@ -47,3 +47,7 @@ logging: console_logging: # Whether logging to the console is enabled enabled: true + +# Disable Jerry Xiao like feature for the following room ID +disable_jerryxiao_for: + - '!XXXXXXXXXXXXXXXXXX:example.com' diff --git a/setup.py b/setup.py index ff19174..202afde 100644 --- a/setup.py +++ b/setup.py @@ -31,11 +31,12 @@ setup( description="A matrix bot to do amazing things!", packages=find_packages(exclude=["tests", "tests.*"]), install_requires=[ - "matrix-nio>=0.10.0", + "matrix-nio[e2e]>=0.10.0", "Markdown>=3.1.1", "PyYAML>=5.1.2", "Wand", "python-magic", + "peewee", ], extras_require={ "postgres": ["psycopg2>=2.8.5"],