Switch to TOML

This commit is contained in:
夜坂雅 2023-02-01 20:48:51 +08:00
parent c752e52ade
commit da637a2ba3
11 changed files with 107 additions and 84 deletions

2
.gitignore vendored
View File

@ -20,7 +20,7 @@ build/
dist/
# Config file
config.yaml
nyx_bot.toml
# Log files
*.log

View File

@ -43,7 +43,7 @@ You can install [libolm](https://gitlab.matrix.org/matrix-org/olm) from source,
or alternatively, check your system's package manager. Version `3.0.0` or
greater is required.
**(Optional) postgres development headers**
#### (Optional) postgres development headers
By default, the bot uses SQLite as its storage backend. This is fine for a few
hundred users, but if you plan to support a much higher volume of requests, you
@ -100,6 +100,8 @@ command to install postgres dependencies alongside those that are necessary:
```
pip install -e ".[postgres]"
# Using requirements.txt
pip install -r requirements-postgres.txt
```
## Install fonts
@ -121,30 +123,30 @@ You can also use the Python one located in `cutword/nyx_bot-cutword.py`.
## Configuration
Copy the sample configuration file to a new `config.yaml` file.
Copy the sample configuration file to a new `nyx_bot.toml` file.
```
cp sample.config.yaml config.yaml
cp sample.config.toml nyx_bot.toml
```
Edit the config file. The `matrix` section must be modified at least.
#### (Optional) Set up a Postgres database
### (Optional) Set up a Postgres database
Create a postgres user and database for matrix-reminder-bot:
Create a postgres user and database for it:
```
sudo -u postgresql psql createuser nio-template -W # prompts for a password
sudo -u postgresql psql createdb -O nio-template nio-template
sudo -u postgresql psql createuser nyx_bot -W # prompts for a password
sudo -u postgresql psql createdb -O nyx_bot nyx_bot
```
Edit the `storage.database` config option, replacing the `sqlite://...` string with `postgres://...`. The syntax is:
```
database: "postgres://username:password@localhost/dbname?sslmode=disable"
database = "postgres://username:password@localhost/dbname?sslmode=disable"
```
See also the comments in `sample.config.yaml`.
See also the comments in `sample.config.toml`.
## Running
@ -171,11 +173,11 @@ it comes time to modifying the code for your own purposes, you are expected to
replace every instance of "nyx-bot" and its variances with your own
project's name.
By default, the bot will run with the config file at `./config.yaml`. However, an
By default, the bot will run with the config file at `./nyx_bot.toml`. However, an
alternative relative or absolute filepath can be specified after the command:
```
nyx-bot other-config.yaml
nyx-bot other-config.toml
```
## Final steps

View File

@ -22,6 +22,7 @@ from nyx_bot.utils import (
get_reply_to,
is_bot_event,
make_datetime,
should_record_message_content,
strip_beginning_quote,
)
@ -38,9 +39,7 @@ class Callbacks:
"""
self.client = client
self.config = config
self.disable_jerryxiao_for = config.disable_jerryxiao_for
self.disable_randomdraw_for = config.disable_randomdraw_for
self.record_message_content_for = config.record_message_content_for
self.room_features = config.room_features
self.command_prefix = config.command_prefix
self.replace_map = {}
@ -71,7 +70,7 @@ class Callbacks:
# Record this message.
timestamp = make_datetime(event.server_timestamp)
external_url = get_external_url(event)
if room.room_id not in self.record_message_content_for:
if not should_record_message_content(self.room_features, room.room_id):
include_text = False
MatrixMessage.update_message(
room, event, external_url, timestamp, event_replace, include_text
@ -98,21 +97,14 @@ class Callbacks:
# Record this message.
timestamp = make_datetime(event.server_timestamp)
external_url = get_external_url(event)
if room.room_id not in self.record_message_content_for:
if not should_record_message_content(self.room_features, room.room_id):
include_text = False
MatrixMessage.update_message(
room, event, external_url, timestamp, event_replace, include_text
)
# General message listener
message = Message(
self.client,
self.config,
msg,
room,
event,
reply_to,
self.disable_jerryxiao_for,
self.disable_randomdraw_for,
self.client, self.config, msg, room, event, reply_to, self.room_features
)
try:
await message.process()

View File

@ -2,13 +2,17 @@ import logging
import os
import re
import sys
from collections import defaultdict
from typing import Any, List, Optional
import yaml
try:
import tomllib
except ModuleNotFoundError:
import tomli as tomllib
from nyx_bot.errors import ConfigError
logger = logging.getLogger()
logger = logging.getLogger(__name__)
logging.getLogger("peewee").setLevel(
logging.INFO
) # Prevent debug messages from peewee lib
@ -24,7 +28,7 @@ class Config:
# Load in the config file at the given filepath
with open(filepath) as file_stream:
self.config_dict = yaml.safe_load(file_stream.read())
self.config_dict = tomllib.loads(file_stream.read())
# Parse and validate config options
self._parse_config_values()
@ -108,15 +112,29 @@ class Config:
self.command_prefix = self._get_cfg(["command_prefix"], default="!c") + " "
self.disable_jerryxiao_for = self._get_cfg(
["disable_jerryxiao_for"], [], required=False
)
self.disable_randomdraw_for = self._get_cfg(
["disable_randomdraw_for"], [], required=False
)
self.record_message_content_for = self._get_cfg(
["record_message_content_for"], [], required=False
)
room_features_dict = self._get_cfg(["room_features"])
room_features_default = {
"jerryxiao": False,
"randomdraw": False,
"record_messages": False,
}
if "jerryxiao" in room_features_dict:
room_features_default["jerryxiao"] = room_features_dict["jerryxiao"]
del room_features_dict["jerryxiao"]
if "randomdraw" in room_features_dict:
room_features_default["randomdraw"] = room_features_dict["randomdraw"]
del room_features_dict["randomdraw"]
if "record_messages" in room_features_dict:
room_features_default["record_messages"] = room_features_dict[
"record_messages"
]
del room_features_dict["record_messages"]
self.room_features = defaultdict(lambda: room_features_default)
for k, v in room_features_dict.items():
if isinstance(v, dict):
features_override = v
self.room_features[k] = room_features_default | features_override
self.encryption = self._get_cfg(["encryption"], False, required=False)
def _get_cfg(

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python3
import asyncio
import logging
import os.path
import sys
@ -44,7 +43,7 @@ async def main():
if len(sys.argv) > 1:
config_path = sys.argv[1]
else:
config_path = "config.yaml"
config_path = "nyx_bot.toml"
# Read the parsed config file and create a Config object
config = Config(config_path)
@ -140,7 +139,3 @@ async def main():
finally:
# Make sure to close the client connection on disconnect
await client.close()
# Run the main function in an asyncio event loop
asyncio.get_event_loop().run_until_complete(main())

View File

@ -8,6 +8,7 @@ from nyx_bot.chat_functions import gen_result_randomdraw, send_text_to_room
from nyx_bot.config import Config
from nyx_bot.jerryxiao import send_jerryxiao
from nyx_bot.trpg_dicer import get_trpg_dice_result
from nyx_bot.utils import should_enable_jerryxiao, should_enable_randomdraw
logger = logging.getLogger(__name__)
@ -21,8 +22,7 @@ class Message:
room: MatrixRoom,
event: RoomMessageText,
reply_to: str,
disable_jerryxiao_for,
disable_randomdraw_for,
room_features,
):
"""Initialize a new Message
@ -43,8 +43,7 @@ class Message:
self.room = room
self.event = event
self.reply_to = reply_to
self.disable_jerryxiao_for = disable_jerryxiao_for
self.disable_randomdraw_for = disable_randomdraw_for
self.room_features = room_features
async def process(self) -> None:
"""Process and possibly respond to the message"""
@ -61,7 +60,7 @@ class Message:
await self._trpg_dicer(query)
async def _randomdraw(self, query: str, prob: bool) -> None:
if self.room.room_id in self.disable_randomdraw_for:
if not should_enable_randomdraw(self.room_features, self.room.room_id):
return
sender = self.event.sender
msg = gen_result_randomdraw(
@ -95,7 +94,7 @@ class Message:
async def _jerryxiao(self) -> None:
"""Performs features similar to the bot created by Jerry Xiao"""
if self.room.room_id in self.disable_jerryxiao_for:
if not should_enable_jerryxiao(self.room_features, self.room.room_id):
return
msg = self.message_content

View File

@ -39,7 +39,7 @@ class MatrixMessage(Model):
external_url: Optional[str],
timestamp: datetime,
event_replace: Optional[str] = None,
include_text: Optional[str] = False,
include_text: Optional[bool] = False,
):
message_db_item = MatrixMessage.get_or_none(
(MatrixMessage.room_id == room.room_id)

View File

@ -3,7 +3,7 @@ from datetime import datetime
from html.parser import HTMLParser
from io import BytesIO, StringIO
from random import Random
from typing import Optional, Tuple
from typing import Dict, Optional, Tuple
from urllib.parse import unquote, urlparse
from zlib import crc32
@ -56,7 +56,7 @@ async def get_body(
async def get_formatted_body(
client: AsyncClient, room: MatrixRoom, event_id: str, replace_map: str
client: AsyncClient, room: MatrixRoom, event_id: str, replace_map: Dict[str, str]
) -> Optional[str]:
if event_id not in replace_map:
target_response = await client.room_get_event(room.room_id, event_id)
@ -143,12 +143,12 @@ def parse_matrixdotto_link(link: str):
# Named Room
type_ = "room_named"
identifier = f"#{parsed.fragment}"
return (type_, identifier, None)
return type_, identifier, None
elif len(paths) == 3:
# Must be an event ID
room = unquote(paths[1])
event_id = unquote(paths[2])
return ("event", room, event_id)
return "event", room, event_id
async def make_single_quote_image(
@ -271,4 +271,16 @@ async def parse_wordcloud_args(
else:
raise NyxBotRuntimeError("Argument is not valid.")
return (sender, days)
return sender, days
def should_record_message_content(room_features, room_id: str) -> bool:
return room_features[room_id]["record_messages"]
def should_enable_jerryxiao(room_features, room_id: str) -> bool:
return room_features[room_id]["jerryxiao"]
def should_enable_randomdraw(room_features, room_id: str) -> bool:
return room_features[room_id]["randomdraw"]

View File

@ -12,6 +12,7 @@ dependencies = [
"matrix-nio>=0.10.0",
"Markdown>=3.1.1",
"PyYAML>=5.1.2",
"tomli >= 1.1.0; python_version < \"3.11\"",
"Wand",
"python-magic",
"peewee",

View File

@ -1,6 +1,7 @@
matrix-nio[e2e]>=0.10.0
matrix-nio>=0.10.0
Markdown>=3.1.1
PyYAML>=5.1.2
tomli>=1.1.0; python_version < "3.11"
Wand
python-magic
peewee

View File

@ -3,62 +3,65 @@
# Default values are shown
# The string to prefix messages with to talk to the bot in group chats
command_prefix: "!c"
command_prefix= "!c"
# Enable E2EE room support ?
encryption: False
encryption = false
# Options for connecting to the bot's Matrix account
matrix:
[matrix]
# The Matrix User ID of the bot account
user_id: "@bot:example.com"
user_id = "@bot:example.com"
# Matrix account password (optional if access token used)
user_password: ""
user_password = ""
# Matrix account access token (optional if password used)
# Use the provided get_access_token.py script to get one
#user_token: ""
#user_token = ""
# The URL of the homeserver to connect to
homeserver_url: https://example.com
homeserver_url = "https://example.com"
# The device ID that is **non pre-existing** device
# If this device ID already exists, messages will be dropped silently in encrypted rooms
device_id: ABCDEFGHIJ
device_id = "ABCDEFGHIJ"
# What to name the logged in device
device_name: my-project-name
device_name = "my-project-name"
storage:
[storage]
# The database connection string
# For SQLite3, this would look like:
# database: "sqlite://bot.db"
# For Postgres, this would look like:
# database: "postgres://username:password@localhost/dbname?sslmode=disable"
database: "sqlite://bot.db"
database = "sqlite://bot.db"
# The path to a directory for internal bot storage
# containing encryption keys, sync tokens, etc.
store_path: "./store"
store_path = "./store"
# Logging setup
logging:
[logging]
# Logging level
# Allowed levels are 'INFO', 'WARNING', 'ERROR', 'DEBUG' where DEBUG is most verbose
level: INFO
level = "INFO"
# Configure logging to a file
file_logging:
[logging.file_logging]
# Whether logging to a file is enabled
enabled: false
enabled = false
# The path to the file to log to. May be relative or absolute
filepath: bot.log
filepath = "bot.log"
# Configure logging to the console output
console_logging:
[logging.console_logging]
# Whether logging to the console is enabled
enabled: true
enabled = true
# Disable Jerry Xiao like feature for the following room ID
disable_jerryxiao_for:
- '!XXXXXXXXXXXXXXXXXX:example.com'
# Room features switch.
# These are the default that can be overriden by subkeys.
[room_features]
jerryxiao = false # Controls Jerry Xiao like feature.
randomdraw = false
record_messages = false # Controls recording message content.
disable_randomdraw_for:
- '!XXXXXXXXXXXXXXXXXX:example.com'
# Record message content for the following rooms
record_message_content_for:
- '!XXXXXXXXXXXXXXXXXX:example.com'
# # Toogle this room's room features.
# # You don't need to specify all of them.
# [room_features."!XXXXXXXXXXXXXXXXXX:example.com"]
# jerryxiao = false
# randomdraw = false
# record_messages = false