Basic backlogging
This commit is contained in:
parent
e1b838d304
commit
b0644c3a17
5 changed files with 51 additions and 5 deletions
|
@ -230,7 +230,7 @@ func (a *Account) eventInternal(event *Event) error {
|
||||||
err = mx.RoomInvite(mx_room_id, mx_user_id)
|
err = mx.RoomInvite(mx_room_id, mx_user_id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.Contains(err.Error(), "already in the room") {
|
if strings.Contains(err.Error(), "already in the room") {
|
||||||
err = nil
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -260,6 +260,16 @@ func (a *Account) eventInternal(event *Event) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if event.Id != "" {
|
||||||
|
cache_key := fmt.Sprintf("%s/event_seen/%s/%s",
|
||||||
|
a.Protocol, mx_room_id, event.Id)
|
||||||
|
if !dbCacheTestAndSet(cache_key, "yes") {
|
||||||
|
// false: cache key was not modified, meaning we
|
||||||
|
// already saw the event
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
typ := "m.text"
|
typ := "m.text"
|
||||||
if event.Type == EVENT_ACTION {
|
if event.Type == EVENT_ACTION {
|
||||||
typ = "m.emote"
|
typ = "m.emote"
|
||||||
|
|
|
@ -98,6 +98,11 @@ const (
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Type EventType
|
Type EventType
|
||||||
|
|
||||||
|
// If non-empty, the event Id is used to deduplicate events in a channel
|
||||||
|
// This is usefull for backends that provide a backlog of channel messages
|
||||||
|
// when (re-)joining a room
|
||||||
|
Id string
|
||||||
|
|
||||||
// UserID of the user that sent the event
|
// UserID of the user that sent the event
|
||||||
// If this is a direct message event, this event can only have been authored
|
// If this is a direct message event, this event can only have been authored
|
||||||
// by the user we are talking to (and not by ourself)
|
// by the user we are talking to (and not by ourself)
|
||||||
|
@ -120,12 +125,18 @@ type Event struct {
|
||||||
|
|
||||||
type UserInfo struct {
|
type UserInfo struct {
|
||||||
DisplayName string
|
DisplayName string
|
||||||
|
|
||||||
|
// If non-empty, the Filename of the avatar object will be used by Easybridge
|
||||||
|
// to deduplicate the update events and prevent needless reuploads.
|
||||||
|
// Example strategy that works for the mattermost backend: use the update timestamp as fictious file name
|
||||||
Avatar MediaObject
|
Avatar MediaObject
|
||||||
}
|
}
|
||||||
|
|
||||||
type RoomInfo struct {
|
type RoomInfo struct {
|
||||||
Name string
|
Name string
|
||||||
Topic string
|
Topic string
|
||||||
|
|
||||||
|
// Same deduplication comment as for UserInfo.Avatar
|
||||||
Picture MediaObject
|
Picture MediaObject
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -354,6 +354,22 @@ func (mm *Mattermost) handleConnected() {
|
||||||
} else {
|
} else {
|
||||||
log.Warnf("Could not get channel members: %s", resp.Error)
|
log.Warnf("Could not get channel members: %s", resp.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read backlog
|
||||||
|
// TODO: remember what was the last seen post in this channel
|
||||||
|
backlog, resp := mm.conn.Client.GetPostsForChannel(ch.Id, 0, 1000, "")
|
||||||
|
if resp.Error == nil {
|
||||||
|
for i := 0; i < len(backlog.Order); i++ {
|
||||||
|
post_id := backlog.Order[len(backlog.Order)-i-1]
|
||||||
|
post := backlog.Posts[post_id]
|
||||||
|
post_time := time.Unix(post.CreateAt/1000, 0)
|
||||||
|
post.Message = fmt.Sprintf("[%s] %s",
|
||||||
|
post_time.Format("2006-01-02 15:04:05 MST"), post.Message)
|
||||||
|
mm.handlePost(ch.Name, post, true)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Warnf("Could not get channel backlog: %s", resp.Error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,6 +441,10 @@ func (mm *Mattermost) handlePosted(msg *model.WebSocketEvent) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return mm.handlePost(channel_name, &post, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mm *Mattermost) handlePost(channel_name string, post *model.Post, only_messages bool) error {
|
||||||
// Skip self messages
|
// Skip self messages
|
||||||
if post.UserId == mm.conn.User.Id {
|
if post.UserId == mm.conn.User.Id {
|
||||||
return nil
|
return nil
|
||||||
|
@ -440,6 +460,7 @@ func (mm *Mattermost) handlePosted(msg *model.WebSocketEvent) error {
|
||||||
|
|
||||||
// Build message event
|
// Build message event
|
||||||
msg_ev := &Event{
|
msg_ev := &Event{
|
||||||
|
Id: post.Id,
|
||||||
Author: userId,
|
Author: userId,
|
||||||
Text: post.Message,
|
Text: post.Message,
|
||||||
Type: EVENT_MESSAGE,
|
Type: EVENT_MESSAGE,
|
||||||
|
@ -489,10 +510,12 @@ func (mm *Mattermost) handlePosted(msg *model.WebSocketEvent) error {
|
||||||
mm.ensureJoined(user, roomId)
|
mm.ensureJoined(user, roomId)
|
||||||
|
|
||||||
if post.Type == "system_header_change" {
|
if post.Type == "system_header_change" {
|
||||||
new_header := post.Props["new_header"].(string)
|
if !only_messages {
|
||||||
mm.handler.RoomInfoUpdated(roomId, userId, &RoomInfo{
|
new_header := post.Props["new_header"].(string)
|
||||||
Topic: new_header,
|
mm.handler.RoomInfoUpdated(roomId, userId, &RoomInfo{
|
||||||
})
|
Topic: new_header,
|
||||||
|
})
|
||||||
|
}
|
||||||
} else if post.Type == "" || post.Type == "me" {
|
} else if post.Type == "" || post.Type == "me" {
|
||||||
msg_ev.Room = roomId
|
msg_ev.Room = roomId
|
||||||
mm.handler.Event(msg_ev)
|
mm.handler.Event(msg_ev)
|
||||||
|
|
1
main.go
1
main.go
|
@ -102,6 +102,7 @@ func readRegistration(file string) mxlib.Registration {
|
||||||
AsToken: hex.EncodeToString(rnd[:32]),
|
AsToken: hex.EncodeToString(rnd[:32]),
|
||||||
HsToken: hex.EncodeToString(rnd[32:]),
|
HsToken: hex.EncodeToString(rnd[32:]),
|
||||||
SenderLocalpart: "_ezbr_",
|
SenderLocalpart: "_ezbr_",
|
||||||
|
RateLimited: false,
|
||||||
Namespaces: mxlib.RegistrationNamespaceSet{
|
Namespaces: mxlib.RegistrationNamespaceSet{
|
||||||
Users: []mxlib.RegistrationNamespace{
|
Users: []mxlib.RegistrationNamespace{
|
||||||
mxlib.RegistrationNamespace{
|
mxlib.RegistrationNamespace{
|
||||||
|
|
|
@ -10,6 +10,7 @@ type Registration struct {
|
||||||
AsToken string `yaml:"as_token"`
|
AsToken string `yaml:"as_token"`
|
||||||
HsToken string `yaml:"hs_token"`
|
HsToken string `yaml:"hs_token"`
|
||||||
SenderLocalpart string `yaml:"sender_localpart"`
|
SenderLocalpart string `yaml:"sender_localpart"`
|
||||||
|
RateLimited bool `yaml:"rate_limited"`
|
||||||
Namespaces RegistrationNamespaceSet `yaml:"namespaces"`
|
Namespaces RegistrationNamespaceSet `yaml:"namespaces"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue