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"
)
type rooms []string
type configOption[T any] struct {
flagName string
flagDefaultValue T
@ -20,7 +22,7 @@ type configOption[T any] struct {
type configOptions struct {
userID configOption[string]
token configOption[string]
room configOption[string]
rooms configOption[rooms]
printHomeserverMemberCount configOption[bool]
homeserverVersionInfoTimeout configOption[time.Duration]
}
@ -28,7 +30,7 @@ type configOptions struct {
type Config struct {
UserID string
Token string
Room string
Rooms rooms
PrintHomeserverMemberCount bool
HomeserverVersionInfoTimeout time.Duration
}
@ -36,11 +38,20 @@ type Config struct {
var configOpts = configOptions{
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"},
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"},
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 {
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 tokenFlag = flag.String(configOpts.token.getFlagArgs())
var roomFlag = flag.String(configOpts.room.getFlagArgs())
var printHomeserverMemberCountFlag = flag.Bool(configOpts.printHomeserverMemberCount.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 {
flag.Parse()
@ -98,7 +114,7 @@ func Get() Config {
if err != nil {
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 {
log.Fatal("A Matrix room must be provided.")
}

205
main.go
View file

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