const (
syncInterval = time.Minute
- syncForceFrequency = 24 * 60
+ syncForceFrequency = int(7 * 24 * time.Hour / syncInterval)
)
+type Room struct {
+ ID id.RoomID `json:"id"`
+ Name string `json:"name",omitempty`
+}
+
type Config struct {
- Homeserver string `json:"homeserver"`
- UserID id.UserID `json:"user_id"`
- Password string `json:"password,omitempty"`
- DeviceID id.DeviceID `json:"device_id,omitempty"`
- AccessToken string `json:"access_token,omitempty"`
- Rooms [][]id.RoomID `json:"rooms"`
+ Homeserver string `json:"homeserver"`
+ UserID id.UserID `json:"user_id"`
+ Password string `json:"password,omitempty"`
+ DeviceID id.DeviceID `json:"device_id,omitempty"`
+ AccessToken string `json:"access_token,omitempty"`
+ Rooms [][]Room `json:"rooms"`
}
func (c *Config) Load() error {
}
func Login(config *Config) (*mautrix.Client, error) {
+ configMu.Lock()
+ defer configMu.Unlock()
+
// Note: we have to lower case the user ID for Matrix protocol communication.
uid := id.UserID(strings.ToLower(string(config.UserID)))
client, err := mautrix.NewClient(config.Homeserver, uid, config.AccessToken)
}
var (
- roomUsers = map[id.RoomID]map[id.UserID]struct{}{}
- roomUsersMu sync.RWMutex
+ configMu sync.Mutex
+
+ roomUsersMu sync.RWMutex
+ roomUsers = map[id.RoomID]map[id.UserID]struct{}{}
+
fullySynced bool
roomPowerLevels = map[id.RoomID]*event.PowerLevelsEventContent{}
)
}
for _, group := range config.Rooms {
for _, room := range group {
- roomUsers[room] = map[id.UserID]struct{}{}
+ roomUsers[room.ID] = map[id.UserID]struct{}{}
}
}
client, err := Login(config)
return fmt.Errorf("failed to login: %v", err)
}
syncer := newSyncer()
+ syncer.OnEventType(event.StateTombstone, func(source mautrix.EventSource, evt *event.Event) {
+ if !isRoom(evt.RoomID) {
+ return
+ }
+ tomb := evt.Content.AsTombstone()
+ if tomb.ReplacementRoom == "" {
+ log.Printf("Replacement room in tombstone event is not set - not handling: %v", evt)
+ return
+ }
+ for _, group := range config.Rooms {
+ for i := range group {
+ room := &group[i]
+ if room.ID == evt.RoomID {
+ configMu.Lock()
+ defer configMu.Unlock()
+ room.ID = tomb.ReplacementRoom
+ err := config.Save()
+ if err != nil {
+ log.Printf("failed to save config: %v", err)
+ }
+ log.Fatalf("room upgrade for %v handled from %v to %v - need restart", room.Name, evt.RoomID, tomb.ReplacementRoom)
+ }
+ }
+ }
+ log.Printf("Room not found in config, so not doing room upgrade: %v", evt)
+ })
syncer.OnEventType(event.EventMessage, func(source mautrix.EventSource, evt *event.Event) {
if !isRoom(evt.RoomID) {
return
if since != "" && !fullySynced {
log.Print("Fully synced.")
for room, users := range roomUsers {
- if len(users) == 0 {
+ if _, found := users[config.UserID]; !found {
log.Printf("Not actually joined %v yet...", room)
_, err := client.JoinRoom(string(room), "", nil)
if err != nil {
}
for _, group := range config.Rooms {
for _, room := range group {
- syncPowerLevels(client, room, group, scoreData, counter%syncForceFrequency == 0)
+ syncPowerLevels(client, room.ID, group, scoreData, counter%syncForceFrequency == 0)
}
}
roomUsersMu.RUnlock()