Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ MAX_STORED_MESSAGES=5
INSTANCE_ID=abcdefghijklmnopqrstuvwxyz
ENVIRONMENT=production

REDIS_HOST=redis
REDIS_PORT=6379

SENTRY_DSN=
SENTRY_TRACES_SAMPLE_RATE=1
SENTRY_PROFILES_SAMPLE_RATE=1

MATRIX_CHAT_ENABLED=false

MATRIX_PING_MESSAGE_PREFIX="@matrixping"
MATRIX_PING_HOMESERVER=
MATRIX_PING_ROOMID=
MATRIX_PING_TOKEN=
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,8 @@ Each of them has a `"type"` key based on which it is possible to parse them :
> `RULES` environment variable describes the instance's rules. Useful information that users should know, even when skimming content.
> `MAX_IMAGE_SIZE` environment variable describes the max size of image in pixels. The server will resize images based on this value.
> `MAX_GEOJSON_FEATURES` environment variable describes the max number of features allowed in a `geojson` message. If there is more feature, the message will not be considered and the server will respond with a `uncompliant` message.
> `MATRIX_CHAT_ENABLED` environment variable describes if the instance should serve the matrix-related websocket endpoints.
> `MATRIX_PING_*` environment variables describe the matrix settings to ping a room when a message starts with the `MATRIX_PING_MESSAGE_PREFIX`.

1. Install `docker` using [the official documentation](https://docs.docker.com/engine/install/)
1. Create a `docker-compose.yaml` file on your server:
Expand All @@ -243,6 +245,11 @@ Each of them has a `"type"` key based on which it is possible to parse them :
- MAX_GEOJSON_FEATURES=500
- MAX_STORED_MESSAGES=5
- REDIS_HOST=redis
- MATRIX_CHAT_ENABLED=false
- MATRIX_PING_MESSAGE_PREFIX="@matrixping"
- MATRIX_PING_HOMESERVER=https://my.matrix.server.net
- MATRIX_PING_ROOMID=!id:my.matrix.server.net
- MATRIX_PING_TOKEN=mat_token
ports:
- 8000:8000
restart: unless-stopped
Expand Down
22 changes: 19 additions & 3 deletions gischat/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,15 @@
from gischat.dispatchers import (
MatrixDispatcher,
RedisDispatcher,
forward_message_to_matrix_channel,
get_redis_channel_key,
)
from gischat.env import (
MATRIX_ENABLED,
MATRIX_CHAT_ENABLED,
MATRIX_PING_HOMESERVER,
MATRIX_PING_MESSAGE_PREFIX,
MATRIX_PING_ROOMID,
MATRIX_PING_TOKEN,
REDIS_HOST,
REDIS_PORT,
REDIS_URL,
Expand Down Expand Up @@ -283,6 +288,18 @@ async def websocket_endpoint(websocket: WebSocket, channel: str) -> None:
if message.text not in QCHAT_CHEATCODES:
redis_dispatcher.store_message(channel, message)

if (
message.text.startswith(MATRIX_PING_MESSAGE_PREFIX)
and MATRIX_PING_MESSAGE_PREFIX
and MATRIX_PING_HOMESERVER
and MATRIX_PING_ROOMID
and MATRIX_PING_TOKEN
):
logger.info(
f"🏓 [{channel}]: Matrix ping received, forwarding to Matrix channel."
)
await forward_message_to_matrix_channel(message, channel)

# image message
if message.type == QChatMessageTypeEnum.IMAGE:
message = QChatImageMessage(**payload)
Expand Down Expand Up @@ -420,7 +437,7 @@ async def websocket_endpoint(websocket: WebSocket, channel: str) -> None:
matrix_dispatcher = MatrixDispatcher.instance()


if MATRIX_ENABLED:
if MATRIX_CHAT_ENABLED:

@app.get("/matrix", response_class=HTMLResponse)
async def get_matrix_ws_page(request: Request):
Expand Down Expand Up @@ -475,7 +492,6 @@ async def matrix_websocket_endpoint(websocket: WebSocket, request_id: UUID) -> N

# text message
if message.type == QChatMessageTypeEnum.TEXT:
print("payload: ", payload)
message = QMatrixChatTextMessage(**payload)

logger.info(
Expand Down
36 changes: 36 additions & 0 deletions gischat/dispatchers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from functools import partial
from uuid import UUID, uuid4

import markdown
from fastapi import WebSocket
from fastapi.encoders import jsonable_encoder
from nio import AsyncClient, MatrixRoom, RoomMessageText
Expand All @@ -11,6 +12,9 @@
from gischat.env import (
INSTANCE_CHANNELS,
INSTANCE_ID,
MATRIX_PING_HOMESERVER,
MATRIX_PING_ROOMID,
MATRIX_PING_TOKEN,
MAX_STORED_MESSAGES,
REDIS_HOST,
REDIS_PORT,
Expand All @@ -22,6 +26,7 @@
QChatMessageModel,
QChatNbUsersMessage,
QChatNewcomerMessage,
QChatTextMessage,
QMatrixChatTextMessage,
parse_qchat_message,
)
Expand Down Expand Up @@ -407,3 +412,34 @@ async def on_matrix_text_message_received(
)

await websocket.send_json(jsonable_encoder(message))


async def forward_message_to_matrix_channel(
message: QChatTextMessage, channel: str
) -> None:
"""
Forwards a QChat text message to a Matrix channel.
:param message: QChat text message to forward.
:param channel: QChat channel where the message originated.
"""

client = AsyncClient(homeserver=MATRIX_PING_HOMESERVER)
client.access_token = MATRIX_PING_TOKEN

try:
body_md = f"""💬 QChat message in channel **{channel}** by _{message.author}_:
{message.text}"""
body_html = markdown.markdown(body_md)

await client.room_send(
room_id=MATRIX_PING_ROOMID,
message_type="m.room.message",
content={
"msgtype": "m.text",
"body": body_md,
"format": "org.matrix.custom.html",
"formatted_body": body_html,
},
)
finally:
await client.close()
11 changes: 10 additions & 1 deletion gischat/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,13 @@
REDIS_PORT = int(os.getenv("REDIS_PORT", "6379"))
REDIS_URL = f"redis://{REDIS_HOST}:{REDIS_PORT}"

MATRIX_ENABLED = os.getenv("MATRIX_ENABLED", "false").lower() in ("true", "1", "yes")
MATRIX_CHAT_ENABLED = os.getenv("MATRIX_CHAT_ENABLED", "false").lower() in (
"true",
"1",
"yes",
)

MATRIX_PING_MESSAGE_PREFIX = os.getenv("MATRIX_PING_MESSAGE_PREFIX", "@matrixping")
MATRIX_PING_HOMESERVER = os.getenv("MATRIX_PING_HOMESERVER", "")
MATRIX_PING_ROOMID = os.getenv("MATRIX_PING_ROOMID", "")
MATRIX_PING_TOKEN = os.getenv("MATRIX_PING_TOKEN", "")
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ dependencies = [
"redis>=7.1.0,<8",
"asyncio>=4.0.0,<5",
"matrix-nio>=0.25.2,<0.26",
"markdown>=3.10",
]

[dependency-groups]
Expand Down
11 changes: 11 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading