mirror of
https://github.com/maubot/maubot
synced 2025-08-29 06:40:37 +00:00
Compare commits
13 commits
Author | SHA1 | Date | |
---|---|---|---|
|
b771b79b91 | ||
|
87bb7fc854 | ||
|
94c4e5aaaf | ||
|
beaba079ca | ||
|
905c91c285 | ||
|
93e0ebd24e | ||
|
ff19278d24 | ||
|
43a14513f0 | ||
|
97dc989394 | ||
|
4c01a49310 | ||
|
a4a39b7f90 | ||
|
10383d526f | ||
|
ac3f0c34cc |
8 changed files with 43 additions and 14 deletions
|
@ -10,7 +10,7 @@ default:
|
|||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
|
||||
build frontend:
|
||||
image: node:22-alpine
|
||||
image: node:24-alpine
|
||||
stage: build frontend
|
||||
before_script: []
|
||||
variables:
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
FROM node:22 AS frontend-builder
|
||||
FROM node:24 AS frontend-builder
|
||||
|
||||
COPY ./maubot/management/frontend /frontend
|
||||
RUN cd /frontend && yarn --prod && yarn build
|
||||
|
||||
FROM alpine:3.21
|
||||
FROM alpine:3.22
|
||||
|
||||
RUN apk add --no-cache \
|
||||
python3 py3-pip py3-setuptools py3-wheel \
|
||||
|
@ -11,6 +11,8 @@ RUN apk add --no-cache \
|
|||
su-exec \
|
||||
yq \
|
||||
py3-aiohttp \
|
||||
py3-aiodns \
|
||||
py3-brotli \
|
||||
py3-attrs \
|
||||
py3-bcrypt \
|
||||
py3-cffi \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM alpine:3.21
|
||||
FROM alpine:3.22
|
||||
|
||||
RUN apk add --no-cache \
|
||||
python3 py3-pip py3-setuptools py3-wheel \
|
||||
|
|
|
@ -350,6 +350,8 @@ class Client(DBClient):
|
|||
}
|
||||
|
||||
async def _handle_tombstone(self, evt: StateEvent) -> None:
|
||||
if evt.state_key != "":
|
||||
return
|
||||
if not evt.content.replacement_room:
|
||||
self.log.info(f"{evt.room_id} tombstoned with no replacement, ignoring")
|
||||
return
|
||||
|
@ -370,7 +372,10 @@ class Client(DBClient):
|
|||
_, server = self.client.parse_user_id(evt.sender)
|
||||
room_id = await self.client.join_room(evt.content.replacement_room, servers=[server])
|
||||
power_levels = await self.client.get_state_event(room_id, EventType.ROOM_POWER_LEVELS)
|
||||
if power_levels.get_user_level(evt.sender) < power_levels.invite:
|
||||
create_event = await self.client.get_state_event(
|
||||
room_id, EventType.ROOM_CREATE, format="event"
|
||||
)
|
||||
if power_levels.get_user_level(evt.sender, create_event) < power_levels.invite:
|
||||
self.log.warning(
|
||||
f"{evt.room_id} was tombstoned into {room_id} by {evt.sender},"
|
||||
" but the sender doesn't have invite power levels, leaving..."
|
||||
|
@ -499,8 +504,14 @@ class Client(DBClient):
|
|||
self.start_sync()
|
||||
|
||||
async def _update_remote_profile(self) -> None:
|
||||
try:
|
||||
profile = await self.client.get_profile(self.id)
|
||||
self.remote_displayname, self.remote_avatar_url = profile.displayname, profile.avatar_url
|
||||
self.remote_displayname, self.remote_avatar_url = (
|
||||
profile.displayname,
|
||||
profile.avatar_url,
|
||||
)
|
||||
except Exception:
|
||||
self.log.warning("Failed to update own profile from server", exc_info=True)
|
||||
|
||||
async def delete(self) -> None:
|
||||
try:
|
||||
|
|
|
@ -54,7 +54,8 @@ server:
|
|||
port: 29316
|
||||
# Public base URL where the server is visible.
|
||||
public_url: https://example.com
|
||||
# The base path for the UI.
|
||||
# The base path for the UI. Note that this does not change the API path.
|
||||
# Add a path prefix to public_url if you want everything on a subpath.
|
||||
ui_base_path: /_matrix/maubot
|
||||
# The base path for plugin endpoints. The instance ID will be appended directly.
|
||||
plugin_base_path: /_matrix/maubot/plugin/
|
||||
|
|
|
@ -70,9 +70,9 @@ class Client extends BaseMainView {
|
|||
get initialState() {
|
||||
return {
|
||||
id: "",
|
||||
displayname: "",
|
||||
displayname: "disable",
|
||||
homeserver: "",
|
||||
avatar_url: "",
|
||||
avatar_url: "disable",
|
||||
access_token: "",
|
||||
device_id: "",
|
||||
fingerprint: null,
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Awaitable
|
||||
from typing import Any, Awaitable
|
||||
from html import escape
|
||||
import asyncio
|
||||
|
||||
|
@ -63,7 +63,7 @@ async def parse_formatted(
|
|||
else:
|
||||
return message, escape(message)
|
||||
text = (await MaubotHTMLParser().parse(html)).text
|
||||
if len(text) + len(html) > 60000:
|
||||
if len(text) > 100 and len(text) + len(html) > 40000:
|
||||
text = text[:100] + "[long message cut off]"
|
||||
return text, html
|
||||
|
||||
|
@ -88,6 +88,7 @@ class MaubotMessageEvent(MessageEvent):
|
|||
reply: bool | str = False,
|
||||
in_thread: bool | None = None,
|
||||
edits: EventID | MessageEvent | None = None,
|
||||
extra_content: dict[str, Any] | None = None,
|
||||
) -> EventID:
|
||||
"""
|
||||
Respond to the message.
|
||||
|
@ -107,6 +108,7 @@ class MaubotMessageEvent(MessageEvent):
|
|||
the root if necessary.
|
||||
edits: An event ID or MessageEvent to edit. If set, the reply and in_thread parameters
|
||||
are ignored, as edits can't change the reply or thread status.
|
||||
extra_content: Extra content to add to the event.
|
||||
|
||||
Returns:
|
||||
The ID of the response event.
|
||||
|
@ -143,6 +145,9 @@ class MaubotMessageEvent(MessageEvent):
|
|||
)
|
||||
else:
|
||||
content.set_reply(self)
|
||||
if extra_content:
|
||||
for k, v in extra_content.items():
|
||||
content[k] = v
|
||||
return await self.client.send_message_event(self.room_id, event_type, content)
|
||||
|
||||
def reply(
|
||||
|
@ -152,6 +157,7 @@ class MaubotMessageEvent(MessageEvent):
|
|||
markdown: bool = True,
|
||||
allow_html: bool = False,
|
||||
in_thread: bool | None = None,
|
||||
extra_content: dict[str, Any] | None = None,
|
||||
) -> Awaitable[EventID]:
|
||||
"""
|
||||
Reply to the message. The parameters are the same as :meth:`respond`,
|
||||
|
@ -169,6 +175,7 @@ class MaubotMessageEvent(MessageEvent):
|
|||
thread. If set to ``False``, the response will never be in a thread. If set to
|
||||
``True``, the response will always be in a thread, creating one with this event as
|
||||
the root if necessary.
|
||||
extra_content: Extra content to add to the event.
|
||||
|
||||
Returns:
|
||||
The ID of the response event.
|
||||
|
@ -180,6 +187,7 @@ class MaubotMessageEvent(MessageEvent):
|
|||
reply=True,
|
||||
in_thread=in_thread,
|
||||
allow_html=allow_html,
|
||||
extra_content=extra_content,
|
||||
)
|
||||
|
||||
def mark_read(self) -> Awaitable[None]:
|
||||
|
@ -256,14 +264,18 @@ class MaubotMatrixClient(MatrixClient):
|
|||
markdown: str,
|
||||
*,
|
||||
allow_html: bool = False,
|
||||
render_markdown: bool = True,
|
||||
msgtype: MessageType = MessageType.TEXT,
|
||||
edits: EventID | MessageEvent | None = None,
|
||||
relates_to: RelatesTo | None = None,
|
||||
extra_content: dict[str, Any] = None,
|
||||
**kwargs,
|
||||
) -> EventID:
|
||||
content = TextMessageEventContent(msgtype=msgtype, format=Format.HTML)
|
||||
content.body, content.formatted_body = await parse_formatted(
|
||||
markdown, allow_html=allow_html
|
||||
markdown,
|
||||
allow_html=allow_html,
|
||||
render_markdown=render_markdown,
|
||||
)
|
||||
if relates_to:
|
||||
if edits:
|
||||
|
@ -271,6 +283,9 @@ class MaubotMatrixClient(MatrixClient):
|
|||
content.relates_to = relates_to
|
||||
elif edits:
|
||||
content.set_edit(edits)
|
||||
if extra_content:
|
||||
for k, v in extra_content.items():
|
||||
content[k] = v
|
||||
return await self.send_message(room_id, content, **kwargs)
|
||||
|
||||
def dispatch_event(self, event: Event, source: SyncStream) -> list[asyncio.Task]:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
mautrix>=0.20.7,<0.21
|
||||
mautrix>=0.20.9rc3,<0.21
|
||||
aiohttp>=3,<4
|
||||
yarl>=1,<2
|
||||
asyncpg>=0.20,<1
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue