From 4964485d29bf382e58f27a1fac61fd04d3412fed Mon Sep 17 00:00:00 2001 From: June Date: Tue, 19 Aug 2025 21:21:39 +0200 Subject: [PATCH] introduce option for JSON output Also rename printHomeserverMemberCount option accordingly to fit new output type. --- README.md | 1 + config/config.go | 24 ++++++++++++++++++------ main.go | 6 +++++- output/json.go | 30 ++++++++++++++++++++++++++++++ output/print.go | 4 ++-- roominfotree/roominfotree.go | 22 +++++++++++----------- 6 files changed, 67 insertions(+), 20 deletions(-) create mode 100644 output/json.go diff --git a/README.md b/README.md index f993024..e7792ad 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,7 @@ Version Support: - Show member count broken down by maximum room version, Matrix server implementation and version and optionally homeserver name. - Check multiple rooms at once by setting the `--room` flag multiple times. - Recursively check all the child rooms for the given rooms (spaces) by setting the `--recursive` flag. +- Output the results as JSON by setting the `--json` flag. ## Usage diff --git a/config/config.go b/config/config.go index 6fba285..6447f71 100644 --- a/config/config.go +++ b/config/config.go @@ -26,7 +26,8 @@ type configOptions struct { recursive configOption[bool] recursionMaxDepth configOption[int] recursionSuggestedOnly configOption[bool] - printHomeserverMemberCount configOption[bool] + json configOption[bool] + outputHomeserverMemberCount configOption[bool] homeserverVersionInfoTimeout configOption[time.Duration] } @@ -37,7 +38,8 @@ type Config struct { Recursive bool RecursionMaxDepth *int RecursionSuggestedOnly bool - PrintHomeserverMemberCount bool + JSON bool + OutputHomeserverMemberCount bool HomeserverVersionInfoTimeout time.Duration } @@ -48,7 +50,8 @@ var configOpts = configOptions{ recursive: configOption[bool]{"recursive", false, "Recursively check the child rooms for the given rooms (spaces) as well.", "MRVC_RECURSIVE"}, recursionMaxDepth: configOption[int]{"recursion-max-depth", 0, "The maximum depth when recursively getting child rooms. Defaults to 0, which gets interpreted as the servers default.", "MRVC_RECURSION_MAX_DEPTH"}, recursionSuggestedOnly: configOption[bool]{"recursion-suggested-only", false, "Only include the suggested children, when recursively getting child rooms.", "MRVC_RECURSION_SUGGESTED_ONLY"}, - printHomeserverMemberCount: configOption[bool]{"print-homeserver-member-count", false, "Print the member count for each homeserver.", "MRVC_PRINT_HOMESERVER_MEMBER_COUNT"}, + json: configOption[bool]{"json", false, "Output result as JSON.", "MRVC_JSON"}, + outputHomeserverMemberCount: configOption[bool]{"output-homeserver-member-count", false, "Output the member count for each homeserver.", "MRVC_OUTPUT_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"}, } @@ -97,7 +100,8 @@ var tokenFlag = flag.String(configOpts.token.getFlagArgs()) var recursiveFlag = flag.Bool(configOpts.recursive.getFlagArgs()) var recursionMaxDepthFlag = flag.Int(configOpts.recursionMaxDepth.getFlagArgs()) var recursionSuggestedOnlyFlag = flag.Bool(configOpts.recursionSuggestedOnly.getFlagArgs()) -var printHomeserverMemberCountFlag = flag.Bool(configOpts.printHomeserverMemberCount.getFlagArgs()) +var jsonFlag = flag.Bool(configOpts.json.getFlagArgs()) +var outputHomeserverMemberCountFlag = flag.Bool(configOpts.outputHomeserverMemberCount.getFlagArgs()) var homeserverVersionInfoTimeoutFlag = flag.Duration(configOpts.homeserverVersionInfoTimeout.getFlagArgs()) var roomsFlag rooms @@ -160,10 +164,18 @@ func Get() Config { } return parsedEnvVar }) - config.PrintHomeserverMemberCount = configOpts.printHomeserverMemberCount.getConfigValueWithDefault(printHomeserverMemberCountFlag, visitedFlags, func(envVar string) bool { + config.JSON = configOpts.json.getConfigValueWithDefault(jsonFlag, visitedFlags, func(envVar string) bool { parsedEnvVar, err := strconv.ParseBool(envVar) if err != nil { - log.Printf("Error parsing %s:\n", configOpts.printHomeserverMemberCount.envVarName) + log.Printf("Error parsing %s:\n", configOpts.json.envVarName) + log.Fatal(err) + } + return parsedEnvVar + }) + config.OutputHomeserverMemberCount = configOpts.outputHomeserverMemberCount.getConfigValueWithDefault(outputHomeserverMemberCountFlag, visitedFlags, func(envVar string) bool { + parsedEnvVar, err := strconv.ParseBool(envVar) + if err != nil { + log.Printf("Error parsing %s:\n", configOpts.outputHomeserverMemberCount.envVarName) log.Fatal(err) } return parsedEnvVar diff --git a/main.go b/main.go index 0da4436..86931cc 100644 --- a/main.go +++ b/main.go @@ -43,5 +43,9 @@ func main() { roomInfoTree := roominfotree.Get(config.Rooms, config.Recursive, config.RecursionMaxDepth, config.RecursionSuggestedOnly, client, federationClient) - output.Print(roomInfoTree, config.PrintHomeserverMemberCount) + if config.JSON { + output.PrintJSON(roomInfoTree, config.OutputHomeserverMemberCount) + } else { + output.Print(roomInfoTree, config.OutputHomeserverMemberCount) + } } diff --git a/output/json.go b/output/json.go new file mode 100644 index 0000000..5e813c4 --- /dev/null +++ b/output/json.go @@ -0,0 +1,30 @@ +package output + +import ( + "encoding/json" + "log" + "os" + + "codeberg.org/june64/mrvc/roominfotree" +) + +func PrintJSON(roomInfoTree roominfotree.RoomInfoTree, outputHomeserverMemberCount bool) { + if !outputHomeserverMemberCount { + for _, roomInfo := range roomInfoTree { + for _, maxRoomVersionInfo := range roomInfo.MaxRoomVersions { + for _, serverInfo := range maxRoomVersionInfo.Servers { + for _, versionInfo := range serverInfo.Versions { + versionInfo.Homeservers = nil + } + } + } + } + } + + json, err := json.Marshal(roomInfoTree) + if err != nil { + log.Fatal(err) + } + + os.Stdout.Write(json) +} diff --git a/output/print.go b/output/print.go index ffec167..d1c6be5 100644 --- a/output/print.go +++ b/output/print.go @@ -39,7 +39,7 @@ func compareVersionStrings(a, b string) int { } } -func Print(roomInfoTree roominfotree.RoomInfoTree, printHomeserverMemberCount bool) { +func Print(roomInfoTree roominfotree.RoomInfoTree, outputHomeserverMemberCount bool) { for roomID, roomInfo := range roomInfoTree { fmt.Println("Room:") fmt.Printf(" %s -> %d\n", roomID, roomInfo.MemberCount) @@ -90,7 +90,7 @@ func Print(roomInfoTree roominfotree.RoomInfoTree, printHomeserverMemberCount bo fmt.Printf(" %s -> %d\n", versionKey, versionInfo.MemberCount) - if printHomeserverMemberCount { + if outputHomeserverMemberCount { homeserverKeys := make([]string, 0, len(versionInfo.Homeservers)) for key := range versionInfo.Homeservers { homeserverKeys = append(homeserverKeys, key) diff --git a/roominfotree/roominfotree.go b/roominfotree/roominfotree.go index 1097f19..cb2fdac 100644 --- a/roominfotree/roominfotree.go +++ b/roominfotree/roominfotree.go @@ -20,29 +20,29 @@ type homeserverServerVersionInfo struct { type RoomInfoTree map[id.RoomID](*RoomInfo) type RoomInfo struct { - MemberCount uint - GivenAliases []string - Aliases []string - MaxRoomVersions map[string](*MaxRoomVersionInfo) + MemberCount uint `json:"memberCount"` + GivenAliases []string `json:"givenAliases"` + Aliases []string `json:"aliases"` + MaxRoomVersions map[string](*MaxRoomVersionInfo) `json:"maxRoomVersions"` } type MaxRoomVersionInfo struct { - MemberCount uint - Servers map[string](*ServerInfo) + MemberCount uint `json:"memberCount"` + Servers map[string](*ServerInfo) `json:"servers"` } type ServerInfo struct { - MemberCount uint - Versions map[string](*VersionInfo) + MemberCount uint `json:"memberCount"` + Versions map[string](*VersionInfo) `json:"versions"` } type VersionInfo struct { - MemberCount uint - Homeservers map[string](*HomeserverInfo) + MemberCount uint `json:"memberCount"` + Homeservers map[string](*HomeserverInfo) `json:"homeservers,omitempty"` } type HomeserverInfo struct { - MemberCount uint + MemberCount uint `json:"memberCount"` } var unknownServerVersionInfo = fclient.Version{