1
0
Fork 0
mirror of https://codeberg.org/june64/mrvc.git synced 2026-01-10 16:06:33 +01:00

introduce support for checking multiple rooms in one go

This commit is contained in:
June 2025-08-17 18:38:04 +02:00
commit c42777e741
Signed by: june
SSH key fingerprint: SHA256:o9EAq4Y9N9K0pBQeBTqhSDrND5E7oB+60ZNx0U1yPe0
2 changed files with 142 additions and 89 deletions

View file

@ -10,6 +10,8 @@ import (
"time" "time"
) )
type rooms []string
type configOption[T any] struct { type configOption[T any] struct {
flagName string flagName string
flagDefaultValue T flagDefaultValue T
@ -20,7 +22,7 @@ type configOption[T any] struct {
type configOptions struct { type configOptions struct {
userID configOption[string] userID configOption[string]
token configOption[string] token configOption[string]
room configOption[string] rooms configOption[rooms]
printHomeserverMemberCount configOption[bool] printHomeserverMemberCount configOption[bool]
homeserverVersionInfoTimeout configOption[time.Duration] homeserverVersionInfoTimeout configOption[time.Duration]
} }
@ -28,7 +30,7 @@ type configOptions struct {
type Config struct { type Config struct {
UserID string UserID string
Token string Token string
Room string Rooms rooms
PrintHomeserverMemberCount bool PrintHomeserverMemberCount bool
HomeserverVersionInfoTimeout time.Duration HomeserverVersionInfoTimeout time.Duration
} }
@ -36,11 +38,20 @@ type Config struct {
var configOpts = configOptions{ var configOpts = configOptions{
userID: configOption[string]{"user-id", "", "The Matrix user ID to use.", "MRVC_USER_ID"}, userID: configOption[string]{"user-id", "", "The Matrix user ID to use.", "MRVC_USER_ID"},
token: configOption[string]{"token", "", "The Matrix access token to use.", "MRVC_TOKEN"}, token: configOption[string]{"token", "", "The Matrix access token to use.", "MRVC_TOKEN"},
room: configOption[string]{"room", "", "The Matrix room to check.", "MRVC_ROOM"}, rooms: configOption[rooms]{"room", []string{}, "The Matrix room to check. The flag can be set multiple times to check multiple rooms.", "MRVC_ROOM"},
printHomeserverMemberCount: configOption[bool]{"print-homeserver-member-count", false, "Print the member count for each homeserver.", "MRVC_PRINT_HOMESERVER_MEMBER_COUNT"}, printHomeserverMemberCount: configOption[bool]{"print-homeserver-member-count", false, "Print the member count for each homeserver.", "MRVC_PRINT_HOMESERVER_MEMBER_COUNT"},
homeserverVersionInfoTimeout: configOption[time.Duration]{"homeserver-version-info-timeout", time.Second * 5, "Timeout for getting the homeservers version information per homeserver.", "MRVC_HOMESERVER_VERSION_INFO_TIMEOUT"}, homeserverVersionInfoTimeout: configOption[time.Duration]{"homeserver-version-info-timeout", time.Second * 5, "Timeout for getting the homeservers version information per homeserver.", "MRVC_HOMESERVER_VERSION_INFO_TIMEOUT"},
} }
func (r *rooms) String() string {
return fmt.Sprint(*r)
}
func (r *rooms) Set(value string) error {
*r = append(*r, value)
return nil
}
func (configOpt configOption[T]) getFlagHelp() string { func (configOpt configOption[T]) getFlagHelp() string {
return fmt.Sprintf("%s (EnvVar: %s)", configOpt.flagHelpBase, configOpt.envVarName) return fmt.Sprintf("%s (EnvVar: %s)", configOpt.flagHelpBase, configOpt.envVarName)
} }
@ -74,10 +85,15 @@ func (configOpt configOption[T]) getConfigValueWithError(configFlag *T, visitedF
var userIdFlag = flag.String(configOpts.userID.getFlagArgs()) var userIdFlag = flag.String(configOpts.userID.getFlagArgs())
var tokenFlag = flag.String(configOpts.token.getFlagArgs()) var tokenFlag = flag.String(configOpts.token.getFlagArgs())
var roomFlag = flag.String(configOpts.room.getFlagArgs())
var printHomeserverMemberCountFlag = flag.Bool(configOpts.printHomeserverMemberCount.getFlagArgs()) var printHomeserverMemberCountFlag = flag.Bool(configOpts.printHomeserverMemberCount.getFlagArgs())
var homeserverVersionInfoTimeoutFlag = flag.Duration(configOpts.homeserverVersionInfoTimeout.getFlagArgs()) var homeserverVersionInfoTimeoutFlag = flag.Duration(configOpts.homeserverVersionInfoTimeout.getFlagArgs())
var roomsFlag rooms
func init() {
flag.Var(&roomsFlag, configOpts.rooms.flagName, configOpts.rooms.getFlagHelp())
}
func Get() Config { func Get() Config {
flag.Parse() flag.Parse()
@ -98,7 +114,7 @@ func Get() Config {
if err != nil { if err != nil {
log.Fatal("A Matrix access token must be provided.") log.Fatal("A Matrix access token must be provided.")
} }
config.Room, err = configOpts.room.getConfigValueWithError(roomFlag, visitedFlags, func(envVar string) string { return envVar }) config.Rooms, err = configOpts.rooms.getConfigValueWithError(&roomsFlag, visitedFlags, func(envVar string) rooms { return []string{envVar} })
if err != nil { if err != nil {
log.Fatal("A Matrix room must be provided.") log.Fatal("A Matrix room must be provided.")
} }

205
main.go
View file

@ -23,12 +23,19 @@ type HomeserverServerVersionInfo struct {
ServerVersionInfo fclient.Version ServerVersionInfo fclient.Version
} }
type MaxRoomVersionPath struct {
RoomID id.RoomID
MaxRoomVersion string
}
type ServerPath struct { type ServerPath struct {
RoomID id.RoomID
MaxRoomVersion string MaxRoomVersion string
Server string Server string
} }
type VersionPath struct { type VersionPath struct {
RoomID id.RoomID
MaxRoomVersion string MaxRoomVersion string
Server string Server string
Version string Version string
@ -308,119 +315,149 @@ func main() {
fclient.WithTimeout(config.HomeserverVersionInfoTimeout), fclient.WithTimeout(config.HomeserverVersionInfoTimeout),
) )
var roomId id.RoomID givenRoomsByRoomID := make(map[id.RoomID]string)
// Check, if given room is an alias and try to resolve it into a room id. for _, room := range config.Rooms {
if strings.HasPrefix(config.Room, "#") { // Check, if given room is an alias and try to resolve it into a room id.
resolvedAlias, err := client.ResolveAlias(context.Background(), id.RoomAlias(config.Room)) if strings.HasPrefix(room, "#") {
resolvedAlias, err := client.ResolveAlias(context.Background(), id.RoomAlias(room))
if err != nil {
log.Fatal(err)
}
givenRoomsByRoomID[resolvedAlias.RoomID] = room
} else {
givenRoomsByRoomID[id.RoomID(room)] = room
}
}
joinedMembersByRoomID := make(map[id.RoomID]*mautrix.RespJoinedMembers)
for roomID := range givenRoomsByRoomID {
joinedMembers, err := client.JoinedMembers(context.Background(), roomID)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
roomId = resolvedAlias.RoomID joinedMembersByRoomID[roomID] = joinedMembers
} else {
roomId = id.RoomID(config.Room)
} }
joinedMembers, err := client.JoinedMembers(context.Background(), roomId) membersByHomeserverByRoomID := make(map[id.RoomID](map[string]uint))
if err != nil { for roomID, joinedMembers := range joinedMembersByRoomID {
log.Fatal(err) membersByHomeserver := make(map[string]uint)
for key := range joinedMembers.Joined {
membersByHomeserver[key.Homeserver()]++
}
membersByHomeserverByRoomID[roomID] = membersByHomeserver
} }
membersByHomeservers := make(map[string]uint) homeserverSet := make(map[string]bool)
for key := range joinedMembers.Joined { for _, membersByHomeserver := range membersByHomeserverByRoomID {
membersByHomeservers[key.Homeserver()]++ for hs := range membersByHomeserver {
homeserverSet[hs] = true
}
} }
homeservers := make([]string, 0, len(membersByHomeservers)) homeservers := make([]string, 0, len(homeserverSet))
for hs := range membersByHomeservers { for hs := range homeserverSet {
homeservers = append(homeservers, hs) homeservers = append(homeservers, hs)
} }
serverVersionInfoByHomeserver := getServerVersionInfoByHomeserver(homeservers, federationClient) serverVersionInfoByHomeserver := getServerVersionInfoByHomeserver(homeservers, federationClient)
// Info map tree. // Info map tree.
maxRoomVersionInfo := make(map[string](map[string](map[string](map[string]uint)))) roomMaxVersionInfos := make(map[id.RoomID](map[string](map[string](map[string](map[string]uint)))))
// Member counters. // Member counters.
membersByMaxRoomVersion := make(map[string]uint) membersByRoomID := make(map[id.RoomID]uint)
membersByMaxRoomVersion := make(map[MaxRoomVersionPath]uint)
membersByServerPath := make(map[ServerPath]uint) membersByServerPath := make(map[ServerPath]uint)
membersByVersionPath := make(map[VersionPath]uint) membersByVersionPath := make(map[VersionPath]uint)
for key, value := range membersByHomeservers { for roomID, membersByHomeserver := range membersByHomeserverByRoomID {
serverVersionInfo := serverVersionInfoByHomeserver[key] for hs, members := range membersByHomeserver {
serverVersionInfo := serverVersionInfoByHomeserver[hs]
maxRoomVersion := getMaxRoomVersion(serverVersionInfo) maxRoomVersion := getMaxRoomVersion(serverVersionInfo)
// Add to counters. // Add to counters.
membersByMaxRoomVersion[maxRoomVersion] += value membersByRoomID[roomID] += members
membersByServerPath[ServerPath{maxRoomVersion, serverVersionInfo.Server.Name}] += value membersByMaxRoomVersion[MaxRoomVersionPath{roomID, maxRoomVersion}] += members
membersByVersionPath[VersionPath{maxRoomVersion, serverVersionInfo.Server.Name, serverVersionInfo.Server.Version}] += value membersByServerPath[ServerPath{roomID, maxRoomVersion, serverVersionInfo.Server.Name}] += members
membersByVersionPath[VersionPath{roomID, maxRoomVersion, serverVersionInfo.Server.Name, serverVersionInfo.Server.Version}] += members
// Sort into maxRoomVersionInfo map tree. // Sort into roomMaxVersionInfos map tree.
serverMap, ok := maxRoomVersionInfo[maxRoomVersion] maxRoomVersionMap, ok := roomMaxVersionInfos[roomID]
if !ok { if !ok {
serverMap = make(map[string](map[string](map[string]uint))) maxRoomVersionMap = make(map[string](map[string](map[string](map[string]uint))))
maxRoomVersionInfo[maxRoomVersion] = serverMap roomMaxVersionInfos[roomID] = maxRoomVersionMap
}
versionMap, ok := serverMap[serverVersionInfo.Server.Name]
if !ok {
versionMap = make(map[string](map[string]uint))
serverMap[serverVersionInfo.Server.Name] = versionMap
}
homeserverMap, ok := versionMap[serverVersionInfo.Server.Version]
if !ok {
homeserverMap = make(map[string]uint)
versionMap[serverVersionInfo.Server.Version] = homeserverMap
}
homeserverMap[key] = value
}
fmt.Println("Room:")
fmt.Printf("%s -> %d\n\n", config.Room, len(joinedMembers.Joined))
fmt.Println("Version Support:")
maxRoomVersionKeys := make([]string, 0, len(maxRoomVersionInfo))
for key := range maxRoomVersionInfo {
maxRoomVersionKeys = append(maxRoomVersionKeys, key)
}
slices.SortFunc(maxRoomVersionKeys, compareVersionStrings)
for _, maxRoomVersionKey := range maxRoomVersionKeys {
maxRoomVersionValue := maxRoomVersionInfo[maxRoomVersionKey]
fmt.Printf("%s -> %d\n", maxRoomVersionKey, membersByMaxRoomVersion[maxRoomVersionKey])
serverKeys := make([]string, 0, len(maxRoomVersionValue))
for key := range maxRoomVersionValue {
serverKeys = append(serverKeys, key)
}
sort.Strings(serverKeys)
for _, serverKey := range serverKeys {
serverValue := maxRoomVersionValue[serverKey]
fmt.Printf(" %s -> %d\n", serverKey, membersByServerPath[ServerPath{maxRoomVersionKey, serverKey}])
versionKeys := make([]string, 0, len(serverValue))
for key := range serverValue {
versionKeys = append(versionKeys, key)
} }
slices.SortFunc(versionKeys, compareVersionStrings) serverMap, ok := maxRoomVersionMap[maxRoomVersion]
for _, versionKey := range versionKeys { if !ok {
versionValue := serverValue[versionKey] serverMap = make(map[string](map[string](map[string]uint)))
maxRoomVersionMap[maxRoomVersion] = serverMap
}
versionMap, ok := serverMap[serverVersionInfo.Server.Name]
if !ok {
versionMap = make(map[string](map[string]uint))
serverMap[serverVersionInfo.Server.Name] = versionMap
}
homeserverMap, ok := versionMap[serverVersionInfo.Server.Version]
if !ok {
homeserverMap = make(map[string]uint)
versionMap[serverVersionInfo.Server.Version] = homeserverMap
}
homeserverMap[hs] = members
}
}
fmt.Printf(" %s -> %d\n", versionKey, membersByVersionPath[VersionPath{maxRoomVersionKey, serverKey, versionKey}]) for roomID, roomIDValue := range roomMaxVersionInfos {
fmt.Println("Room:")
fmt.Printf(" %s -> %d\n", givenRoomsByRoomID[roomID], membersByRoomID[roomID])
if config.PrintHomeserverMemberCount { fmt.Println("Version Support:")
homeserverKeys := make([]string, 0, len(versionValue))
for key := range versionValue {
homeserverKeys = append(homeserverKeys, key)
}
sort.Strings(homeserverKeys)
for _, homeserverKey := range homeserverKeys {
homeserverValue := versionValue[homeserverKey]
fmt.Printf(" %s -> %d\n", homeserverKey, homeserverValue) maxRoomVersionKeys := make([]string, 0, len(roomIDValue))
for key := range roomIDValue {
maxRoomVersionKeys = append(maxRoomVersionKeys, key)
}
slices.SortFunc(maxRoomVersionKeys, compareVersionStrings)
for _, maxRoomVersionKey := range maxRoomVersionKeys {
maxRoomVersionValue := roomIDValue[maxRoomVersionKey]
fmt.Printf(" %s -> %d\n", maxRoomVersionKey, membersByMaxRoomVersion[MaxRoomVersionPath{roomID, maxRoomVersionKey}])
serverKeys := make([]string, 0, len(maxRoomVersionValue))
for key := range maxRoomVersionValue {
serverKeys = append(serverKeys, key)
}
sort.Strings(serverKeys)
for _, serverKey := range serverKeys {
serverValue := maxRoomVersionValue[serverKey]
fmt.Printf(" %s -> %d\n", serverKey, membersByServerPath[ServerPath{roomID, maxRoomVersionKey, serverKey}])
versionKeys := make([]string, 0, len(serverValue))
for key := range serverValue {
versionKeys = append(versionKeys, key)
}
slices.SortFunc(versionKeys, compareVersionStrings)
for _, versionKey := range versionKeys {
versionValue := serverValue[versionKey]
fmt.Printf(" %s -> %d\n", versionKey, membersByVersionPath[VersionPath{roomID, maxRoomVersionKey, serverKey, versionKey}])
if config.PrintHomeserverMemberCount {
homeserverKeys := make([]string, 0, len(versionValue))
for key := range versionValue {
homeserverKeys = append(homeserverKeys, key)
}
sort.Strings(homeserverKeys)
for _, homeserverKey := range homeserverKeys {
homeserverValue := versionValue[homeserverKey]
fmt.Printf(" %s -> %d\n", homeserverKey, homeserverValue)
}
} }
} }
} }
} }
fmt.Println()
} }
} }