mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-12-10 16:33:11 -06:00
Write membership updates
This commit is contained in:
parent
21e47b8fd2
commit
dab501854a
|
|
@ -21,8 +21,14 @@ import (
|
||||||
// An OutputType is a type of roomserver output.
|
// An OutputType is a type of roomserver output.
|
||||||
type OutputType string
|
type OutputType string
|
||||||
|
|
||||||
// OutputTypeNewRoomEvent indicates that the event is an OutputNewRoomEvent
|
const (
|
||||||
const OutputTypeNewRoomEvent OutputType = "new_room_event"
|
// OutputTypeNewRoomEvent indicates that the event is an OutputNewRoomEvent
|
||||||
|
OutputTypeNewRoomEvent OutputType = "new_room_event"
|
||||||
|
// OutputTypeNewInviteEvent indicates that the event is an OutputNewInviteEvent
|
||||||
|
OutputTypeNewInviteEvent OutputType = "new_invite_event"
|
||||||
|
// OutputTypeRetireInviteEvent indicates that the event is an OutputRetireInviteEvent
|
||||||
|
OutputTypeRetireInviteEvent OutputType = "retire_invite_event"
|
||||||
|
)
|
||||||
|
|
||||||
// An OutputEvent is an entry in the roomserver output kafka log.
|
// An OutputEvent is an entry in the roomserver output kafka log.
|
||||||
// Consumers should check the type field when consuming this event.
|
// Consumers should check the type field when consuming this event.
|
||||||
|
|
@ -31,6 +37,10 @@ type OutputEvent struct {
|
||||||
Type OutputType `json:"type"`
|
Type OutputType `json:"type"`
|
||||||
// The content of event with type OutputTypeNewRoomEvent
|
// The content of event with type OutputTypeNewRoomEvent
|
||||||
NewRoomEvent *OutputNewRoomEvent `json:"new_room_event,omitempty"`
|
NewRoomEvent *OutputNewRoomEvent `json:"new_room_event,omitempty"`
|
||||||
|
// The content of event with type OutputTypeNewInviteEvent
|
||||||
|
NewInviteEvent *OutputNewInviteEvent `json:"new_invite_event,omitempty"`
|
||||||
|
// The content of event with type OutputTypeRetireInviteEvent
|
||||||
|
RetireInviteEvent *OutputRetireInviteEvent `json:"retire_invite_event,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// An OutputNewRoomEvent is written when the roomserver receives a new event.
|
// An OutputNewRoomEvent is written when the roomserver receives a new event.
|
||||||
|
|
@ -111,14 +121,12 @@ type OutputNewInviteEvent struct {
|
||||||
// active. An invite stops being active if the user joins the room or if the
|
// active. An invite stops being active if the user joins the room or if the
|
||||||
// invite is rejected by the user.
|
// invite is rejected by the user.
|
||||||
type OutputRetireInviteEvent struct {
|
type OutputRetireInviteEvent struct {
|
||||||
// The room ID of the "m.room.member" invite event.
|
|
||||||
RoomID string
|
|
||||||
// The ID of the "m.room.member" invite event.
|
// The ID of the "m.room.member" invite event.
|
||||||
EventID string
|
EventID string
|
||||||
// Optional event ID of the event that replaced the invite.
|
// Optional event ID of the event that replaced the invite.
|
||||||
// This can be empty if the invite was rejected locally and we were unable
|
// This can be empty if the invite was rejected locally and we were unable
|
||||||
// to reach the server that originally sent the invite.
|
// to reach the server that originally sent the invite.
|
||||||
ReplacedByEventID string
|
RetiredByEventID string
|
||||||
// The "membership" of the user after retiring the invite. One of "join"
|
// The "membership" of the user after retiring the invite. One of "join"
|
||||||
// "leave" or "ban".
|
// "leave" or "ban".
|
||||||
Membership string
|
Membership string
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,8 @@ type RoomEventDatabase interface {
|
||||||
|
|
||||||
// OutputRoomEventWriter has the APIs needed to write an event to the output logs.
|
// OutputRoomEventWriter has the APIs needed to write an event to the output logs.
|
||||||
type OutputRoomEventWriter interface {
|
type OutputRoomEventWriter interface {
|
||||||
// Write an event.
|
// Write a list of events for a room
|
||||||
WriteOutputRoomEvent(output api.OutputNewRoomEvent) error
|
WriteOutputEvents(roomID string, updates []api.OutputEvent) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func processRoomEvent(db RoomEventDatabase, ow OutputRoomEventWriter, input api.InputRoomEvent) error {
|
func processRoomEvent(db RoomEventDatabase, ow OutputRoomEventWriter, input api.InputRoomEvent) error {
|
||||||
|
|
|
||||||
|
|
@ -46,22 +46,21 @@ type RoomserverInputAPI struct {
|
||||||
processed int64
|
processed int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteOutputRoomEvent implements OutputRoomEventWriter
|
// WriteOutputEvents implements OutputRoomEventWriter
|
||||||
func (r *RoomserverInputAPI) WriteOutputRoomEvent(output api.OutputNewRoomEvent) error {
|
func (r *RoomserverInputAPI) WriteOutputEvents(roomID string, updates []api.OutputEvent) error {
|
||||||
var m sarama.ProducerMessage
|
messages := make([]*sarama.ProducerMessage, len(updates))
|
||||||
oe := api.OutputEvent{
|
for i := range updates {
|
||||||
Type: api.OutputTypeNewRoomEvent,
|
value, err := json.Marshal(updates[i])
|
||||||
NewRoomEvent: &output,
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
messages[i] = &sarama.ProducerMessage{
|
||||||
|
Topic: r.OutputRoomEventTopic,
|
||||||
|
Key: sarama.StringEncoder(roomID),
|
||||||
|
Value: sarama.ByteEncoder(value),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
value, err := json.Marshal(oe)
|
return r.Producer.SendMessages(messages)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
m.Topic = r.OutputRoomEventTopic
|
|
||||||
m.Key = sarama.StringEncoder("")
|
|
||||||
m.Value = sarama.ByteEncoder(value)
|
|
||||||
_, _, err = r.Producer.SendMessage(&m)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// InputRoomEvents implements api.RoomserverInputAPI
|
// InputRoomEvents implements api.RoomserverInputAPI
|
||||||
|
|
|
||||||
|
|
@ -66,69 +66,76 @@ func updateLatestEvents(
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
err = doUpdateLatestEvents(db, updater, ow, roomNID, stateAtEvent, event, sendAsServer)
|
u := latestEventsUpdater{
|
||||||
return
|
db: db, updater: updater, ow: ow, roomNID: roomNID,
|
||||||
|
stateAtEvent: stateAtEvent, event: event, sendAsServer: sendAsServer,
|
||||||
|
}
|
||||||
|
return u.doUpdateLatestEvents()
|
||||||
}
|
}
|
||||||
|
|
||||||
func doUpdateLatestEvents(
|
type latestEventsUpdater struct {
|
||||||
db RoomEventDatabase,
|
db RoomEventDatabase
|
||||||
updater types.RoomRecentEventsUpdater,
|
updater types.RoomRecentEventsUpdater
|
||||||
ow OutputRoomEventWriter,
|
ow OutputRoomEventWriter
|
||||||
roomNID types.RoomNID,
|
roomNID types.RoomNID
|
||||||
stateAtEvent types.StateAtEvent,
|
stateAtEvent types.StateAtEvent
|
||||||
event gomatrixserverlib.Event,
|
event gomatrixserverlib.Event
|
||||||
sendAsServer string,
|
sendAsServer string
|
||||||
) error {
|
lastEventIDSent string
|
||||||
|
latest []types.StateAtEventAndReference
|
||||||
|
removed []types.StateEntry
|
||||||
|
added []types.StateEntry
|
||||||
|
stateBeforeEventRemoves []types.StateEntry
|
||||||
|
stateBeforeEventAdds []types.StateEntry
|
||||||
|
oldStateNID types.StateSnapshotNID
|
||||||
|
newStateNID types.StateSnapshotNID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *latestEventsUpdater) doUpdateLatestEvents() error {
|
||||||
var err error
|
var err error
|
||||||
var prevEvents []gomatrixserverlib.EventReference
|
var prevEvents []gomatrixserverlib.EventReference
|
||||||
prevEvents = event.PrevEvents()
|
prevEvents = u.event.PrevEvents()
|
||||||
oldLatest := updater.LatestEvents()
|
oldLatest := u.updater.LatestEvents()
|
||||||
lastEventIDSent := updater.LastEventIDSent()
|
u.lastEventIDSent = u.updater.LastEventIDSent()
|
||||||
oldStateNID := updater.CurrentStateSnapshotNID()
|
u.oldStateNID = u.updater.CurrentStateSnapshotNID()
|
||||||
|
|
||||||
if hasBeenSent, err := updater.HasEventBeenSent(stateAtEvent.EventNID); err != nil {
|
if hasBeenSent, err := u.updater.HasEventBeenSent(u.stateAtEvent.EventNID); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if hasBeenSent {
|
} else if hasBeenSent {
|
||||||
// Already sent this event so we can stop processing
|
// Already sent this event so we can stop processing
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = updater.StorePreviousEvents(stateAtEvent.EventNID, prevEvents); err != nil {
|
if err = u.updater.StorePreviousEvents(u.stateAtEvent.EventNID, prevEvents); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
eventReference := event.EventReference()
|
eventReference := u.event.EventReference()
|
||||||
// Check if this event is already referenced by another event in the room.
|
// Check if this event is already referenced by another event in the room.
|
||||||
var alreadyReferenced bool
|
var alreadyReferenced bool
|
||||||
if alreadyReferenced, err = updater.IsReferenced(eventReference); err != nil {
|
if alreadyReferenced, err = u.updater.IsReferenced(eventReference); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
newLatest := calculateLatest(oldLatest, alreadyReferenced, prevEvents, types.StateAtEventAndReference{
|
u.latest = calculateLatest(oldLatest, alreadyReferenced, prevEvents, types.StateAtEventAndReference{
|
||||||
EventReference: eventReference,
|
EventReference: eventReference,
|
||||||
StateAtEvent: stateAtEvent,
|
StateAtEvent: u.stateAtEvent,
|
||||||
})
|
})
|
||||||
|
|
||||||
latestStateAtEvents := make([]types.StateAtEvent, len(newLatest))
|
if err = u.latestState(); err != nil {
|
||||||
for i := range newLatest {
|
return err
|
||||||
latestStateAtEvents[i] = newLatest[i].StateAtEvent
|
|
||||||
}
|
}
|
||||||
newStateNID, err := state.CalculateAndStoreStateAfterEvents(db, roomNID, latestStateAtEvents)
|
|
||||||
|
updates, err := updateMemberships(u.db, u.updater, u.removed, u.added)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
removed, added, err := state.DifferenceBetweeenStateSnapshots(db, oldStateNID, newStateNID)
|
update, err := u.makeOutputNewRoomEvent()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
stateBeforeEventRemoves, stateBeforeEventAdds, err := state.DifferenceBetweeenStateSnapshots(
|
|
||||||
db, newStateNID, stateAtEvent.BeforeStateSnapshotNID,
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
updates = append(updates, *update)
|
||||||
|
|
||||||
// Send the event to the output logs.
|
// Send the event to the output logs.
|
||||||
// We do this inside the database transaction to ensure that we only mark an event as sent if we sent it.
|
// We do this inside the database transaction to ensure that we only mark an event as sent if we sent it.
|
||||||
|
|
@ -138,24 +145,47 @@ func doUpdateLatestEvents(
|
||||||
// send the event asynchronously but we would need to ensure that 1) the events are written to the log in
|
// send the event asynchronously but we would need to ensure that 1) the events are written to the log in
|
||||||
// the correct order, 2) that pending writes are resent across restarts. In order to avoid writing all the
|
// the correct order, 2) that pending writes are resent across restarts. In order to avoid writing all the
|
||||||
// necessary bookkeeping we'll keep the event sending synchronous for now.
|
// necessary bookkeeping we'll keep the event sending synchronous for now.
|
||||||
if err = writeEvent(
|
if err = u.ow.WriteOutputEvents(u.event.RoomID(), updates); err != nil {
|
||||||
db, ow, lastEventIDSent, event, newLatest, removed, added,
|
|
||||||
stateBeforeEventRemoves, stateBeforeEventAdds, sendAsServer,
|
|
||||||
); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = updater.SetLatestEvents(roomNID, newLatest, stateAtEvent.EventNID, newStateNID); err != nil {
|
if err = u.updater.SetLatestEvents(u.roomNID, u.latest, u.stateAtEvent.EventNID, u.newStateNID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = updater.MarkEventAsSent(stateAtEvent.EventNID); err != nil {
|
if err = u.updater.MarkEventAsSent(u.stateAtEvent.EventNID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *latestEventsUpdater) latestState() error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
latestStateAtEvents := make([]types.StateAtEvent, len(u.latest))
|
||||||
|
for i := range u.latest {
|
||||||
|
latestStateAtEvents[i] = u.latest[i].StateAtEvent
|
||||||
|
}
|
||||||
|
u.newStateNID, err = state.CalculateAndStoreStateAfterEvents(u.db, u.roomNID, latestStateAtEvents)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
u.removed, u.added, err = state.DifferenceBetweeenStateSnapshots(u.db, u.oldStateNID, u.newStateNID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
u.stateBeforeEventRemoves, u.stateBeforeEventAdds, err = state.DifferenceBetweeenStateSnapshots(
|
||||||
|
u.db, u.newStateNID, u.stateAtEvent.BeforeStateSnapshotNID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func calculateLatest(oldLatest []types.StateAtEventAndReference, alreadyReferenced bool, prevEvents []gomatrixserverlib.EventReference, newEvent types.StateAtEventAndReference) []types.StateAtEventAndReference {
|
func calculateLatest(oldLatest []types.StateAtEventAndReference, alreadyReferenced bool, prevEvents []gomatrixserverlib.EventReference, newEvent types.StateAtEventAndReference) []types.StateAtEventAndReference {
|
||||||
var alreadyInLatest bool
|
var alreadyInLatest bool
|
||||||
var newLatest []types.StateAtEventAndReference
|
var newLatest []types.StateAtEventAndReference
|
||||||
|
|
@ -189,57 +219,55 @@ func calculateLatest(oldLatest []types.StateAtEventAndReference, alreadyReferenc
|
||||||
return newLatest
|
return newLatest
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeEvent(
|
func (u *latestEventsUpdater) makeOutputNewRoomEvent() (*api.OutputEvent, error) {
|
||||||
db RoomEventDatabase, ow OutputRoomEventWriter, lastEventIDSent string,
|
|
||||||
event gomatrixserverlib.Event, latest []types.StateAtEventAndReference,
|
|
||||||
removed, added []types.StateEntry,
|
|
||||||
stateBeforeEventRemoves, stateBeforeEventAdds []types.StateEntry,
|
|
||||||
sendAsServer string,
|
|
||||||
) error {
|
|
||||||
|
|
||||||
latestEventIDs := make([]string, len(latest))
|
latestEventIDs := make([]string, len(u.latest))
|
||||||
for i := range latest {
|
for i := range u.latest {
|
||||||
latestEventIDs[i] = latest[i].EventID
|
latestEventIDs[i] = u.latest[i].EventID
|
||||||
}
|
}
|
||||||
|
|
||||||
ore := api.OutputNewRoomEvent{
|
ore := api.OutputNewRoomEvent{
|
||||||
Event: event,
|
Event: u.event,
|
||||||
LastSentEventID: lastEventIDSent,
|
LastSentEventID: u.lastEventIDSent,
|
||||||
LatestEventIDs: latestEventIDs,
|
LatestEventIDs: latestEventIDs,
|
||||||
}
|
}
|
||||||
|
|
||||||
var stateEventNIDs []types.EventNID
|
var stateEventNIDs []types.EventNID
|
||||||
for _, entry := range added {
|
for _, entry := range u.added {
|
||||||
stateEventNIDs = append(stateEventNIDs, entry.EventNID)
|
stateEventNIDs = append(stateEventNIDs, entry.EventNID)
|
||||||
}
|
}
|
||||||
for _, entry := range removed {
|
for _, entry := range u.removed {
|
||||||
stateEventNIDs = append(stateEventNIDs, entry.EventNID)
|
stateEventNIDs = append(stateEventNIDs, entry.EventNID)
|
||||||
}
|
}
|
||||||
for _, entry := range stateBeforeEventRemoves {
|
for _, entry := range u.stateBeforeEventRemoves {
|
||||||
stateEventNIDs = append(stateEventNIDs, entry.EventNID)
|
stateEventNIDs = append(stateEventNIDs, entry.EventNID)
|
||||||
}
|
}
|
||||||
for _, entry := range stateBeforeEventAdds {
|
for _, entry := range u.stateBeforeEventAdds {
|
||||||
stateEventNIDs = append(stateEventNIDs, entry.EventNID)
|
stateEventNIDs = append(stateEventNIDs, entry.EventNID)
|
||||||
}
|
}
|
||||||
stateEventNIDs = stateEventNIDs[:util.SortAndUnique(eventNIDSorter(stateEventNIDs))]
|
stateEventNIDs = stateEventNIDs[:util.SortAndUnique(eventNIDSorter(stateEventNIDs))]
|
||||||
eventIDMap, err := db.EventIDs(stateEventNIDs)
|
eventIDMap, err := u.db.EventIDs(stateEventNIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, entry := range added {
|
for _, entry := range u.added {
|
||||||
ore.AddsStateEventIDs = append(ore.AddsStateEventIDs, eventIDMap[entry.EventNID])
|
ore.AddsStateEventIDs = append(ore.AddsStateEventIDs, eventIDMap[entry.EventNID])
|
||||||
}
|
}
|
||||||
for _, entry := range removed {
|
for _, entry := range u.removed {
|
||||||
ore.RemovesStateEventIDs = append(ore.RemovesStateEventIDs, eventIDMap[entry.EventNID])
|
ore.RemovesStateEventIDs = append(ore.RemovesStateEventIDs, eventIDMap[entry.EventNID])
|
||||||
}
|
}
|
||||||
for _, entry := range stateBeforeEventRemoves {
|
for _, entry := range u.stateBeforeEventRemoves {
|
||||||
ore.StateBeforeRemovesEventIDs = append(ore.StateBeforeRemovesEventIDs, eventIDMap[entry.EventNID])
|
ore.StateBeforeRemovesEventIDs = append(ore.StateBeforeRemovesEventIDs, eventIDMap[entry.EventNID])
|
||||||
}
|
}
|
||||||
for _, entry := range stateBeforeEventAdds {
|
for _, entry := range u.stateBeforeEventAdds {
|
||||||
ore.StateBeforeAddsEventIDs = append(ore.StateBeforeAddsEventIDs, eventIDMap[entry.EventNID])
|
ore.StateBeforeAddsEventIDs = append(ore.StateBeforeAddsEventIDs, eventIDMap[entry.EventNID])
|
||||||
}
|
}
|
||||||
ore.SendAsServer = sendAsServer
|
ore.SendAsServer = u.sendAsServer
|
||||||
return ow.WriteOutputRoomEvent(ore)
|
|
||||||
|
return &api.OutputEvent{
|
||||||
|
Type: api.OutputTypeNewRoomEvent,
|
||||||
|
NewRoomEvent: &ore,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type eventNIDSorter []types.EventNID
|
type eventNIDSorter []types.EventNID
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,16 @@
|
||||||
package input
|
package input
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/dendrite/roomserver/types"
|
"github.com/matrix-org/dendrite/roomserver/types"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func updateMemberships(
|
func updateMemberships(
|
||||||
db RoomEventDatabase, updater types.RoomRecentEventsUpdater, removed, added []types.StateEntry,
|
db RoomEventDatabase, updater types.RoomRecentEventsUpdater, removed, added []types.StateEntry,
|
||||||
) error {
|
) ([]api.OutputEvent, error) {
|
||||||
changes := membershipChanges(removed, added)
|
changes := membershipChanges(removed, added)
|
||||||
var eventNIDs []types.EventNID
|
var eventNIDs []types.EventNID
|
||||||
for _, change := range changes {
|
for _, change := range changes {
|
||||||
|
|
@ -34,9 +37,11 @@ func updateMemberships(
|
||||||
}
|
}
|
||||||
events, err := db.Events(eventNIDs)
|
events, err := db.Events(eventNIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var updates []api.OutputEvent
|
||||||
|
|
||||||
for _, change := range changes {
|
for _, change := range changes {
|
||||||
var ae *gomatrixserverlib.Event
|
var ae *gomatrixserverlib.Event
|
||||||
var re *gomatrixserverlib.Event
|
var re *gomatrixserverlib.Event
|
||||||
|
|
@ -55,16 +60,18 @@ func updateMemberships(
|
||||||
}
|
}
|
||||||
targetNID = change.added.EventStateKeyNID
|
targetNID = change.added.EventStateKeyNID
|
||||||
}
|
}
|
||||||
if err := updateMembership(updater, targetNID, re, ae); err != nil {
|
if updates, err = updateMembership(updater, targetNID, re, ae, updates); err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateMembership(
|
func updateMembership(
|
||||||
updater types.RoomRecentEventsUpdater, targetNID types.EventStateKeyNID, remove *gomatrixserverlib.Event, add *gomatrixserverlib.Event,
|
updater types.RoomRecentEventsUpdater, targetNID types.EventStateKeyNID,
|
||||||
) error {
|
remove *gomatrixserverlib.Event, add *gomatrixserverlib.Event,
|
||||||
|
updates []api.OutputEvent,
|
||||||
|
) ([]api.OutputEvent, error) {
|
||||||
var err error
|
var err error
|
||||||
old := "leave"
|
old := "leave"
|
||||||
new := "leave"
|
new := "leave"
|
||||||
|
|
@ -72,40 +79,95 @@ func updateMembership(
|
||||||
if remove != nil {
|
if remove != nil {
|
||||||
old, err = remove.Membership()
|
old, err = remove.Membership()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if add != nil {
|
if add != nil {
|
||||||
new, err = add.Membership()
|
new, err = add.Membership()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if old == new {
|
if old == new {
|
||||||
return nil
|
return updates, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
mu, err := updater.MembershipUpdater(targetNID)
|
mu, err := updater.MembershipUpdater(targetNID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch new {
|
return updateWithNewMembership(mu, new, add, updates)
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateWithNewMembership(
|
||||||
|
mu types.MembershipUpdater, newMembership string, add *gomatrixserverlib.Event,
|
||||||
|
updates []api.OutputEvent,
|
||||||
|
) ([]api.OutputEvent, error) {
|
||||||
|
switch newMembership {
|
||||||
case "invite":
|
case "invite":
|
||||||
_, err := mu.SetToInvite(*add)
|
needsSending, err := mu.SetToInvite(*add)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if needsSending {
|
||||||
|
updates = appendInviteUpdate(updates, add)
|
||||||
|
}
|
||||||
|
return updates, nil
|
||||||
case "join":
|
case "join":
|
||||||
if !mu.IsJoin() {
|
if mu.IsJoin() {
|
||||||
mu.SetToJoin(add.Sender())
|
return updates, nil
|
||||||
}
|
}
|
||||||
case "leave":
|
retired, err := mu.SetToJoin(add.Sender())
|
||||||
if !mu.IsLeave() {
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return appendRetireUpdates(updates, add, newMembership, retired), nil
|
||||||
|
case "leave", "ban":
|
||||||
|
if mu.IsLeave() {
|
||||||
|
return updates, nil
|
||||||
|
}
|
||||||
|
retired, err := mu.SetToLeave(add.Sender())
|
||||||
|
if err != nil {
|
||||||
mu.SetToLeave(add.Sender())
|
mu.SetToLeave(add.Sender())
|
||||||
}
|
}
|
||||||
|
return appendRetireUpdates(updates, add, newMembership, retired), nil
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf(
|
||||||
|
"input: membership %q is not one of the allowed values", newMembership,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
return nil
|
}
|
||||||
|
|
||||||
|
func appendInviteUpdate(
|
||||||
|
updates []api.OutputEvent, add *gomatrixserverlib.Event,
|
||||||
|
) []api.OutputEvent {
|
||||||
|
onie := api.OutputNewInviteEvent{
|
||||||
|
Event: *add,
|
||||||
|
}
|
||||||
|
return append(updates, api.OutputEvent{
|
||||||
|
Type: api.OutputTypeNewInviteEvent,
|
||||||
|
NewInviteEvent: &onie,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendRetireUpdates(
|
||||||
|
updates []api.OutputEvent, add *gomatrixserverlib.Event, membership string, retired []string,
|
||||||
|
) []api.OutputEvent {
|
||||||
|
for _, eventID := range retired {
|
||||||
|
orie := api.OutputRetireInviteEvent{
|
||||||
|
EventID: eventID,
|
||||||
|
Membership: membership,
|
||||||
|
}
|
||||||
|
if add != nil {
|
||||||
|
orie.RetiredByEventID = add.EventID()
|
||||||
|
}
|
||||||
|
updates = append(updates, api.OutputEvent{
|
||||||
|
Type: api.OutputTypeRetireInviteEvent,
|
||||||
|
RetireInviteEvent: &orie,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return updates
|
||||||
}
|
}
|
||||||
|
|
||||||
type stateChange struct {
|
type stateChange struct {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue