vojo/apps/ai-bot/events.go

73 lines
2.3 KiB
Go

package main
import "encoding/json"
// Event is a Matrix ClientEvent as delivered in an appservice transaction. Each
// event carries its own room_id (unlike /sync, where it's implied by the room
// bucket). Content stays raw so each handler decodes only the shape it needs.
type Event struct {
Type string `json:"type"`
RoomID string `json:"room_id"`
Sender string `json:"sender"`
EventID string `json:"event_id"`
OriginServerTS int64 `json:"origin_server_ts"`
StateKey *string `json:"state_key,omitempty"`
Content json.RawMessage `json:"content"`
}
// Mentions is the MSC3952 intentional-mentions block. It can legitimately be the
// empty object `{}` (cinny writes it on every send), so UserIDs may be nil —
// callers must safe-deref (F29).
type Mentions struct {
UserIDs []string `json:"user_ids"`
Room bool `json:"room"`
}
type InReplyTo struct {
EventID string `json:"event_id"`
}
type RelatesTo struct {
RelType string `json:"rel_type"`
EventID string `json:"event_id"`
InReplyTo *InReplyTo `json:"m.in_reply_to"`
}
// MessageContent is the decoded m.room.message content we care about.
type MessageContent struct {
MsgType string `json:"msgtype"`
Body string `json:"body"`
Format string `json:"format"`
FormattedBody string `json:"formatted_body"`
Mentions *Mentions `json:"m.mentions"`
RelatesTo *RelatesTo `json:"m.relates_to"`
NewContent json.RawMessage `json:"m.new_content"`
}
func (e *Event) DecodeMessage() (*MessageContent, bool) {
if e.Type != "m.room.message" {
return nil, false
}
var mc MessageContent
if err := json.Unmarshal(e.Content, &mc); err != nil {
return nil, false
}
return &mc, true
}
// IsReplace reports whether the message is an `m.replace` edit. Edits re-carry
// m.mentions and must NOT re-trigger or double-bill (F16).
func (mc *MessageContent) IsReplace() bool {
return mc.RelatesTo != nil && mc.RelatesTo.RelType == "m.replace"
}
// membershipOf extracts the membership from an m.room.member event content.
func (e *Event) membershipOf() string {
var m struct {
Membership string `json:"membership"`
}
if json.Unmarshal(e.Content, &m) != nil {
return ""
}
return m.Membership
}