1
0
Fork 0
forked from Mirrors/gomuks

web/widget: implement delayed state events

This commit is contained in:
Tulir Asokan 2025-03-06 01:29:37 +02:00
parent 23f2699909
commit f79678a87f
8 changed files with 60 additions and 25 deletions

View file

@ -79,7 +79,7 @@ require (
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
maunium.net/go/mautrix v0.23.2-0.20250304004736-7d3791ace3b7 // indirect maunium.net/go/mautrix v0.23.2-0.20250305232906-e306c2817edd // indirect
mvdan.cc/xurls/v2 v2.6.0 // indirect mvdan.cc/xurls/v2 v2.6.0 // indirect
) )

View file

@ -261,7 +261,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
maunium.net/go/mautrix v0.23.2-0.20250304004736-7d3791ace3b7 h1:AeNHqITptzOpmfMxnqmQRw6xN7DUDCgsN00BaPyRd4k= maunium.net/go/mautrix v0.23.2-0.20250305232906-e306c2817edd h1:kQVkgTP/V19Eo4E6NH1QsMzNh7RJ2Ye1oUO9x307PFQ=
maunium.net/go/mautrix v0.23.2-0.20250304004736-7d3791ace3b7/go.mod h1:IHMaSJh7YIxMrZSDVefS+nLdr3RbeLowsCSa6ibONZ0= maunium.net/go/mautrix v0.23.2-0.20250305232906-e306c2817edd/go.mod h1:IHMaSJh7YIxMrZSDVefS+nLdr3RbeLowsCSa6ibONZ0=
mvdan.cc/xurls/v2 v2.6.0 h1:3NTZpeTxYVWNSokW3MKeyVkz/j7uYXYiMtXRUfmjbgI= mvdan.cc/xurls/v2 v2.6.0 h1:3NTZpeTxYVWNSokW3MKeyVkz/j7uYXYiMtXRUfmjbgI=
mvdan.cc/xurls/v2 v2.6.0/go.mod h1:bCvEZ1XvdA6wDnxY7jPPjEmigDtvtvPXAD/Exa9IMSk= mvdan.cc/xurls/v2 v2.6.0/go.mod h1:bCvEZ1XvdA6wDnxY7jPPjEmigDtvtvPXAD/Exa9IMSk=

2
go.mod
View file

@ -27,7 +27,7 @@ require (
golang.org/x/text v0.22.0 golang.org/x/text v0.22.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
maunium.net/go/mauflag v1.0.0 maunium.net/go/mauflag v1.0.0
maunium.net/go/mautrix v0.23.2-0.20250304004736-7d3791ace3b7 maunium.net/go/mautrix v0.23.2-0.20250305232906-e306c2817edd
mvdan.cc/xurls/v2 v2.6.0 mvdan.cc/xurls/v2 v2.6.0
) )

4
go.sum
View file

@ -100,7 +100,7 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M= maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M=
maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA= maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA=
maunium.net/go/mautrix v0.23.2-0.20250304004736-7d3791ace3b7 h1:AeNHqITptzOpmfMxnqmQRw6xN7DUDCgsN00BaPyRd4k= maunium.net/go/mautrix v0.23.2-0.20250305232906-e306c2817edd h1:kQVkgTP/V19Eo4E6NH1QsMzNh7RJ2Ye1oUO9x307PFQ=
maunium.net/go/mautrix v0.23.2-0.20250304004736-7d3791ace3b7/go.mod h1:IHMaSJh7YIxMrZSDVefS+nLdr3RbeLowsCSa6ibONZ0= maunium.net/go/mautrix v0.23.2-0.20250305232906-e306c2817edd/go.mod h1:IHMaSJh7YIxMrZSDVefS+nLdr3RbeLowsCSa6ibONZ0=
mvdan.cc/xurls/v2 v2.6.0 h1:3NTZpeTxYVWNSokW3MKeyVkz/j7uYXYiMtXRUfmjbgI= mvdan.cc/xurls/v2 v2.6.0 h1:3NTZpeTxYVWNSokW3MKeyVkz/j7uYXYiMtXRUfmjbgI=
mvdan.cc/xurls/v2 v2.6.0/go.mod h1:bCvEZ1XvdA6wDnxY7jPPjEmigDtvtvPXAD/Exa9IMSk= mvdan.cc/xurls/v2 v2.6.0/go.mod h1:bCvEZ1XvdA6wDnxY7jPPjEmigDtvtvPXAD/Exa9IMSk=

View file

@ -65,7 +65,16 @@ func (h *HiClient) handleJSONCommand(ctx context.Context, req *JSONCommand) (any
}) })
case "set_state": case "set_state":
return unmarshalAndCall(req.Data, func(params *sendStateEventParams) (id.EventID, error) { return unmarshalAndCall(req.Data, func(params *sendStateEventParams) (id.EventID, error) {
return h.SetState(ctx, params.RoomID, params.EventType, params.StateKey, params.Content) return h.SetState(ctx, params.RoomID, params.EventType, params.StateKey, params.Content, mautrix.ReqSendEvent{
UnstableDelay: time.Duration(params.DelayMS) * time.Millisecond,
})
})
case "update_delayed_event":
return unmarshalAndCall(req.Data, func(params *updateDelayedEventParams) (*mautrix.RespUpdateDelayedEvent, error) {
return h.Client.UpdateDelayedEvent(ctx, &mautrix.ReqUpdateDelayedEvent{
DelayID: params.DelayID,
Action: params.Action,
})
}) })
case "set_membership": case "set_membership":
return unmarshalAndCall(req.Data, func(params *setMembershipParams) (any, error) { return unmarshalAndCall(req.Data, func(params *setMembershipParams) (any, error) {
@ -308,6 +317,12 @@ type sendStateEventParams struct {
EventType event.Type `json:"type"` EventType event.Type `json:"type"`
StateKey string `json:"state_key"` StateKey string `json:"state_key"`
Content json.RawMessage `json:"content"` Content json.RawMessage `json:"content"`
DelayMS int `json:"delay_ms"`
}
type updateDelayedEventParams struct {
DelayID string `json:"delay_id"`
Action string `json:"action"`
} }
type setMembershipParams struct { type setMembershipParams struct {

View file

@ -226,6 +226,7 @@ func (h *HiClient) SetState(
evtType event.Type, evtType event.Type,
stateKey string, stateKey string,
content any, content any,
extra ...mautrix.ReqSendEvent,
) (id.EventID, error) { ) (id.EventID, error) {
room, err := h.DB.Room.Get(ctx, roomID) room, err := h.DB.Room.Get(ctx, roomID)
if err != nil { if err != nil {
@ -233,10 +234,14 @@ func (h *HiClient) SetState(
} else if room == nil { } else if room == nil {
return "", fmt.Errorf("unknown room") return "", fmt.Errorf("unknown room")
} }
resp, err := h.Client.SendStateEvent(ctx, room.ID, evtType, stateKey, content) resp, err := h.Client.SendStateEvent(ctx, room.ID, evtType, stateKey, content, extra...)
if err != nil { if err != nil {
return "", err return "", err
} }
if resp.UnstableDelayID != "" {
// Mildly hacky, but it's fine'
return id.EventID(resp.UnstableDelayID), nil
}
return resp.EventID, nil return resp.EventID, nil
} }

View file

@ -174,8 +174,13 @@ export default abstract class RPCClient {
setState( setState(
room_id: RoomID, type: EventType, state_key: string, content: Record<string, unknown>, room_id: RoomID, type: EventType, state_key: string, content: Record<string, unknown>,
extra: { delay_ms?: number } = {},
): Promise<EventID> { ): Promise<EventID> {
return this.request("set_state", { room_id, type, state_key, content }) return this.request("set_state", { room_id, type, state_key, content, ...extra })
}
updateDelayedEvent(delay_id: string, action: string): Promise<void> {
return this.request("update_delayed_event", { delay_id, action })
} }
setMembership(room_id: RoomID, user_id: UserID, action: MembershipAction, reason?: string): Promise<void> { setMembership(room_id: RoomID, user_id: UserID, action: MembershipAction, reason?: string): Promise<void> {

View file

@ -19,11 +19,13 @@ import {
IOpenIDUpdate, IOpenIDUpdate,
IRoomAccountData, IRoomAccountData,
IRoomEvent, IRoomEvent,
ISendDelayedEventDetails,
ISendEventDetails, ISendEventDetails,
ITurnServer, ITurnServer,
OpenIDRequestState, OpenIDRequestState,
SimpleObservable, SimpleObservable,
Symbols, Symbols,
UpdateDelayedEventAction,
WidgetDriver, WidgetDriver,
} from "matrix-widget-api" } from "matrix-widget-api"
import Client from "@/api/client.ts" import Client from "@/api/client.ts"
@ -62,23 +64,31 @@ class GomuksWidgetDriver extends WidgetDriver {
} }
} }
// async sendDelayedEvent( async sendDelayedEvent(
// delay: number | null, delay: number | null,
// parentDelayID: string | null, parentDelayID: string | null,
// eventType: string, eventType: string,
// content: unknown, content: unknown,
// stateKey: string | null = null, stateKey: string | null = null,
// roomID: string | null = null, roomID: string | null = null,
// ): Promise<ISendDelayedEventDetails> { ): Promise<ISendDelayedEventDetails> {
// if (!isRecord(content)) { if (!isRecord(content)) {
// throw new Error("Content must be an object") throw new Error("Content must be an object")
// } } else if (stateKey === null) {
// throw new Error("Delayed events are not supported") throw new Error("Non-state delayed events are not supported")
// } } else if (parentDelayID !== null) {
throw new Error("Parent delayed events are not supported")
} else if (!delay) {
throw new Error("Delay must be a number")
}
roomID = roomID ?? this.room.roomID
const delayID = await this.client.rpc.setState(roomID, eventType, stateKey, content, { delay_ms: delay })
return { delayId: delayID, roomId: roomID }
}
// async updateDelayedEvent(delayID: string, action: UpdateDelayedEventAction): Promise<void> { async updateDelayedEvent(delayID: string, action: UpdateDelayedEventAction): Promise<void> {
// throw new Error("Delayed events are not supported") await this.client.rpc.updateDelayedEvent(delayID, action)
// } }
async sendToDevice( async sendToDevice(
eventType: string, eventType: string,