mirror of
https://codeberg.org/june64/mrvc.git
synced 2026-01-11 16:23:49 +01:00
refactor RoomInfoTree building into separate package for better org.
This commit is contained in:
parent
d7ca2f4a00
commit
5b3df2a619
3 changed files with 351 additions and 323 deletions
327
main.go
327
main.go
|
|
@ -7,266 +7,16 @@ import (
|
||||||
"slices"
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/hashicorp/go-version"
|
"github.com/hashicorp/go-version"
|
||||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
|
||||||
"maunium.net/go/mautrix"
|
"maunium.net/go/mautrix"
|
||||||
"maunium.net/go/mautrix/id"
|
"maunium.net/go/mautrix/id"
|
||||||
|
|
||||||
"codeberg.org/june64/mrvc/config"
|
"codeberg.org/june64/mrvc/config"
|
||||||
|
"codeberg.org/june64/mrvc/roominfotree"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HomeserverServerVersionInfo struct {
|
|
||||||
Homeserver string
|
|
||||||
ServerVersionInfo fclient.Version
|
|
||||||
}
|
|
||||||
|
|
||||||
type RoomInfoTree map[id.RoomID](*RoomInfo)
|
|
||||||
|
|
||||||
type RoomInfo struct {
|
|
||||||
MemberCount uint
|
|
||||||
MaxRoomVersions map[string](*MaxRoomVersionInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
type MaxRoomVersionInfo struct {
|
|
||||||
MemberCount uint
|
|
||||||
Servers map[string](*ServerInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
type ServerInfo struct {
|
|
||||||
MemberCount uint
|
|
||||||
Versions map[string](*VersionInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
type VersionInfo struct {
|
|
||||||
MemberCount uint
|
|
||||||
Homeservers map[string](*HomeserverInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
type HomeserverInfo struct {
|
|
||||||
MemberCount uint
|
|
||||||
}
|
|
||||||
|
|
||||||
var unknownServerVersionInfo = fclient.Version{
|
|
||||||
Server: struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Version string `json:"version"`
|
|
||||||
}{
|
|
||||||
Name: "unknown",
|
|
||||||
Version: "unknown",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func getServerVersionInfoByHomeserver(homeservers []string, federationClient *fclient.Client) map[string](fclient.Version) {
|
|
||||||
homeserverChannel := make(chan string)
|
|
||||||
go func() {
|
|
||||||
for _, hs := range homeservers {
|
|
||||||
homeserverChannel <- hs
|
|
||||||
}
|
|
||||||
close(homeserverChannel)
|
|
||||||
}()
|
|
||||||
|
|
||||||
homeserverSVInfoChannel := make(chan HomeserverServerVersionInfo)
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
const numHomeserverSVInfoReceivers = 100
|
|
||||||
wg.Add(numHomeserverSVInfoReceivers)
|
|
||||||
for i := 0; i < numHomeserverSVInfoReceivers; i++ {
|
|
||||||
go func() {
|
|
||||||
for hs := range homeserverChannel {
|
|
||||||
serverVersionInfo, err := federationClient.GetVersion(context.Background(), spec.ServerName(hs))
|
|
||||||
if err != nil {
|
|
||||||
serverVersionInfo = unknownServerVersionInfo
|
|
||||||
}
|
|
||||||
homeserverSVInfoChannel <- HomeserverServerVersionInfo{hs, serverVersionInfo}
|
|
||||||
}
|
|
||||||
wg.Done()
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
wg.Wait()
|
|
||||||
close(homeserverSVInfoChannel)
|
|
||||||
}()
|
|
||||||
|
|
||||||
serverVersionInfoByHomeserver := make(map[string](fclient.Version))
|
|
||||||
for homeserverSVInfo := range homeserverSVInfoChannel {
|
|
||||||
serverVersionInfoByHomeserver[homeserverSVInfo.Homeserver] = homeserverSVInfo.ServerVersionInfo
|
|
||||||
}
|
|
||||||
return serverVersionInfoByHomeserver
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets the maximum supported room version for the given server-version-pair.
|
|
||||||
func getMaxRoomVersion(serverVersionInfo fclient.Version) string {
|
|
||||||
// Use only the first part of the version string as sometimes there are suffixes after a space, like " (<commit>)", which then can't be parsed.
|
|
||||||
serverVersion, err := version.NewVersion(strings.Split(serverVersionInfo.Server.Version, " ")[0])
|
|
||||||
if err != nil {
|
|
||||||
return "unkown"
|
|
||||||
}
|
|
||||||
|
|
||||||
switch serverVersionInfo.Server.Name {
|
|
||||||
case "Conduit":
|
|
||||||
// https://conduit.rs/
|
|
||||||
// https://conduit.rs/changelog/
|
|
||||||
// https://gitlab.com/famedly/conduit
|
|
||||||
switch {
|
|
||||||
// https://conduit.rs/changelog/#v0-10-8-2025-08-11
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.10.8"))):
|
|
||||||
return "v12"
|
|
||||||
// https://conduit.rs/changelog/#v0-7-0-2024-04-25
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.7.0"))):
|
|
||||||
return "v11"
|
|
||||||
// https://conduit.rs/changelog/#v0-5-0-2022-12-21
|
|
||||||
// Includes MR 400:
|
|
||||||
// https://gitlab.com/famedly/conduit/-/merge_requests/400/commits
|
|
||||||
// MR 400 includes a commit, which specifies v10 as stable.
|
|
||||||
// https://gitlab.com/famedly/conduit/-/commit/1e1a144dfa98429ef9f02d16045796b73013830d
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.5.0"))):
|
|
||||||
return "v10"
|
|
||||||
// https://conduit.rs/changelog/#v0-4-0-2022-06-23
|
|
||||||
// Includes MR 257:
|
|
||||||
// https://gitlab.com/famedly/conduit/-/merge_requests/257/commits
|
|
||||||
// MR 257 includes a commit, which specifies added support v7 to v9.
|
|
||||||
// https://gitlab.com/famedly/conduit/-/commit/0ae39807a478370a769217d01fa33514299a2b35
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.4.0"))):
|
|
||||||
return "v9"
|
|
||||||
// https://conduit.rs/changelog/#v0-2-0-2021-09-01
|
|
||||||
default:
|
|
||||||
return "v6"
|
|
||||||
}
|
|
||||||
case "conduwuit", "Conduwuit":
|
|
||||||
// Using continuwuitys source (history) as a reference:
|
|
||||||
// https://forgejo.ellis.link/continuwuation/continuwuity
|
|
||||||
|
|
||||||
// History from first commit on "continuwuity":
|
|
||||||
// https://forgejo.ellis.link/continuwuation/continuwuity/commits/commit/e054a56b3286a6fb3091bedd5261089435ed26d1
|
|
||||||
// Last commit on "conduwuit"/"Conduwuit":
|
|
||||||
// https://forgejo.ellis.link/continuwuation/continuwuity/src/commit/d8311a5ff672fdc4729d956af5e3af8646b0670d
|
|
||||||
// Last version was "0.5.0":
|
|
||||||
// https://forgejo.ellis.link/continuwuation/continuwuity/src/commit/d8311a5ff672fdc4729d956af5e3af8646b0670d/Cargo.toml
|
|
||||||
|
|
||||||
// Matching both "conduwuit" and "Conduwuit" as the capitalization got changed.
|
|
||||||
// https://forgejo.ellis.link/continuwuation/continuwuity/commit/5b5ccba64e3d36a9235f4e0d449f40d859046dad
|
|
||||||
|
|
||||||
switch {
|
|
||||||
// Since the version went from "0.7.0-<something>" to "0.3.0" and the last version was "0.5.0", give all versions greater than "0.7.0" a lower max room version.
|
|
||||||
// https://forgejo.ellis.link/continuwuation/continuwuity/commit/af0b81f5fb737d3550cf22fbcf8d8b8eb1947408
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.7.0"))):
|
|
||||||
return "v10"
|
|
||||||
// v11 support (shows there as included in tag "v0.3.0"):
|
|
||||||
// https://forgejo.ellis.link/continuwuation/continuwuity/commit/223f05c922ea6f3085d386f0758df550459a25c3
|
|
||||||
// Tag "v0.3.0":
|
|
||||||
// https://forgejo.ellis.link/continuwuation/continuwuity/src/tag/v0.3.0/src/service/globals/mod.rs#L130
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.3.0"))):
|
|
||||||
return "v11"
|
|
||||||
// First version named "Conduwuit"/"conduwuit":
|
|
||||||
// https://forgejo.ellis.link/continuwuation/continuwuity/commit/e71855cd0b59d9274e8528a4c1ee480f99006c3c
|
|
||||||
// v10 support at first version named "Conduwuit"/"conduwuit":
|
|
||||||
// https://forgejo.ellis.link/continuwuation/continuwuity/src/commit/e71855cd0b59d9274e8528a4c1ee480f99006c3c/src/service/globals/mod.rs#L187
|
|
||||||
// And shows first version as "0.7.0-alpha+conduwuit-0.1.3":
|
|
||||||
// https://forgejo.ellis.link/continuwuation/continuwuity/src/commit/e71855cd0b59d9274e8528a4c1ee480f99006c3c/Cargo.toml
|
|
||||||
// Because of this versioning and the match on "0.7.0" before, this default should never match, but it is included for clarity.
|
|
||||||
default:
|
|
||||||
return "v10"
|
|
||||||
}
|
|
||||||
case "continuwuity":
|
|
||||||
// https://continuwuity.org/
|
|
||||||
// https://forgejo.ellis.link/continuwuation/continuwuity
|
|
||||||
|
|
||||||
// First version named "continuwuity":
|
|
||||||
// https://forgejo.ellis.link/continuwuation/continuwuity/commit/dc599db19c48ad3cbae15fc419c4a531d217ed05
|
|
||||||
// v11 support at first version named "continuwuity":
|
|
||||||
// https://forgejo.ellis.link/continuwuation/continuwuity/src/commit/dc599db19c48ad3cbae15fc419c4a531d217ed05/src/core/info/room_version.rs
|
|
||||||
return "v11"
|
|
||||||
case "Dendrite":
|
|
||||||
// https://github.com/element-hq/dendrite
|
|
||||||
// https://element-hq.github.io/dendrite/
|
|
||||||
// https://github.com/element-hq/dendrite/blob/main/CHANGES.md
|
|
||||||
switch {
|
|
||||||
// https://github.com/element-hq/dendrite/blob/v0.15.0/CHANGES.md#dendrite-0150-2025-08-12
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.15.0"))):
|
|
||||||
return "v12"
|
|
||||||
// https://github.com/matrix-org/dendrite/blob/v0.13.3/CHANGES.md#dendrite-0133-2023-09-28
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.13.3"))):
|
|
||||||
return "v11"
|
|
||||||
// https://github.com/matrix-org/dendrite/blob/v0.8.7/CHANGES.md#dendrite-087-2022-06-01
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.8.7"))):
|
|
||||||
return "v10"
|
|
||||||
// https://github.com/matrix-org/dendrite/blob/v0.8.6/CHANGES.md#dendrite-086-2022-05-26
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.8.6"))):
|
|
||||||
return "v9"
|
|
||||||
// https://github.com/matrix-org/dendrite/blob/v0.8.6/CHANGES.md#dendrite-086-2022-05-26
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.8.6"))):
|
|
||||||
return "v8"
|
|
||||||
// https://github.com/matrix-org/dendrite/blob/v0.4.1/CHANGES.md#dendrite-041-2021-07-26
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.4.1"))):
|
|
||||||
return "v7"
|
|
||||||
// https://github.com/matrix-org/dendrite/blob/v0.1.0/CHANGES.md#dendrite-010-2020-10-08
|
|
||||||
default:
|
|
||||||
return "v6"
|
|
||||||
}
|
|
||||||
case "Synapse":
|
|
||||||
// https://github.com/element-hq/synapse/
|
|
||||||
// https://element-hq.github.io/synapse/latest/
|
|
||||||
// https://github.com/element-hq/synapse/blob/develop/CHANGES.md
|
|
||||||
// https://github.com/element-hq/synapse/blob/develop/docs/changelogs/
|
|
||||||
switch {
|
|
||||||
// https://github.com/element-hq/synapse/blob/v1.135.1/CHANGES.md#synapse-11351-2025-08-11
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("1.135.1"))):
|
|
||||||
return "v12"
|
|
||||||
// https://github.com/element-hq/synapse/blob/v1.89.0rc1/CHANGES.md#synapse-1890rc1-2023-07-25
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("1.89.0rc1"))):
|
|
||||||
return "v11"
|
|
||||||
// https://github.com/element-hq/synapse/blob/v1.64.0rc1/CHANGES.md#synapse-1640rc1-2022-07-26
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("1.64.0rc1"))):
|
|
||||||
return "v10"
|
|
||||||
// https://github.com/element-hq/synapse/blob/v1.42.0rc2/CHANGES.md#synapse-1420rc2-2021-09-06
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("1.42.0rc2"))):
|
|
||||||
return "v9"
|
|
||||||
// https://github.com/element-hq/synapse/blob/v1.40.0rc3/CHANGES.md#synapse-1400rc3-2021-08-09
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("1.40.0rc3"))):
|
|
||||||
return "v8"
|
|
||||||
// https://github.com/element-hq/synapse/blob/v1.37.0rc1/CHANGES.md#synapse-1370rc1-2021-06-24
|
|
||||||
// https://github.com/matrix-org/synapse/pull/10167
|
|
||||||
// https://github.com/matrix-org/synapse/pull/10167/files#diff-8e36e2fc4dec5d84357ee3d140ad223b66fb36e630c25bbb45382ca59cdb0f40
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("1.37.0rc1"))):
|
|
||||||
return "v7"
|
|
||||||
// https://github.com/element-hq/synapse/blob/v1.14.0rc1/CHANGES.md#synapse-1140rc1-2020-05-26
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("1.14.0rc1"))):
|
|
||||||
return "v6"
|
|
||||||
// https://github.com/element-hq/synapse/blob/v1.0.0rc1/CHANGES.md#synapse-100rc1-2019-06-07
|
|
||||||
// https://github.com/matrix-org/synapse/pull/5354
|
|
||||||
// https://github.com/matrix-org/synapse/pull/5354/files#diff-8e36e2fc4dec5d84357ee3d140ad223b66fb36e630c25bbb45382ca59cdb0f40
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("1.0.0rc1"))):
|
|
||||||
return "v5"
|
|
||||||
// https://github.com/element-hq/synapse/blob/v0.99.5rc1/CHANGES.md#synapse-0995rc1-2019-05-21
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.99.5rc1"))):
|
|
||||||
return "v4"
|
|
||||||
// https://github.com/element-hq/synapse/blob/v0.99.0rc1/CHANGES.md#synapse-0990rc1-2019-01-30
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.99.0rc1"))):
|
|
||||||
return "v3"
|
|
||||||
// https://github.com/element-hq/synapse/blob/v0.34.1rc1/CHANGES.md#synapse-0341rc1-2019-01-08
|
|
||||||
// https://github.com/matrix-org/synapse/pull/4307
|
|
||||||
// https://github.com/matrix-org/synapse/pull/4307/files#diff-32e0f096397b0e3545054c51c42b5be4f0db953083b60d76a047cb1618f6b877
|
|
||||||
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.34.1rc1"))):
|
|
||||||
return "v2"
|
|
||||||
default:
|
|
||||||
return "v1"
|
|
||||||
}
|
|
||||||
case "Tuwunel":
|
|
||||||
// https://github.com/matrix-construct/tuwunel
|
|
||||||
|
|
||||||
// First version named "Tuwunel":
|
|
||||||
// https://github.com/matrix-construct/tuwunel/commit/9b658d86b2f49d01ba8d2f5ae7f263a104e8f282#diff-d58f31e506570d0bcb7629251ec1b350c5dde4a205a338349f154f3fd3187e93
|
|
||||||
// v11 support at first version named "Tuwunel":
|
|
||||||
// https://github.com/matrix-construct/tuwunel/blob/9b658d86b2f49d01ba8d2f5ae7f263a104e8f282/src/core/info/room_version.rs
|
|
||||||
return "v11"
|
|
||||||
default:
|
|
||||||
return "unkown"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func compareVersionStrings(a, b string) int {
|
func compareVersionStrings(a, b string) int {
|
||||||
// Try to parse a and b as versions.
|
// Try to parse a and b as versions.
|
||||||
// Use only the first part of the version string as sometimes there are suffixes after a space, like " (<commit>)", which then can't be parsed.
|
// Use only the first part of the version string as sometimes there are suffixes after a space, like " (<commit>)", which then can't be parsed.
|
||||||
|
|
@ -337,81 +87,12 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
joinedMembersByRoomID := make(map[id.RoomID]*mautrix.RespJoinedMembers)
|
roomIDs := make([]id.RoomID, 0, len(givenRoomsByRoomID))
|
||||||
for roomID := range givenRoomsByRoomID {
|
for roomID := range givenRoomsByRoomID {
|
||||||
joinedMembers, err := client.JoinedMembers(context.Background(), roomID)
|
roomIDs = append(roomIDs, roomID)
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
joinedMembersByRoomID[roomID] = joinedMembers
|
|
||||||
}
|
}
|
||||||
|
|
||||||
membersByHomeserverByRoomID := make(map[id.RoomID](map[string]uint))
|
roomInfoTree := roominfotree.Get(roomIDs, client, federationClient)
|
||||||
for roomID, joinedMembers := range joinedMembersByRoomID {
|
|
||||||
membersByHomeserver := make(map[string]uint)
|
|
||||||
for key := range joinedMembers.Joined {
|
|
||||||
membersByHomeserver[key.Homeserver()]++
|
|
||||||
}
|
|
||||||
membersByHomeserverByRoomID[roomID] = membersByHomeserver
|
|
||||||
}
|
|
||||||
|
|
||||||
homeserverSet := make(map[string]bool)
|
|
||||||
for _, membersByHomeserver := range membersByHomeserverByRoomID {
|
|
||||||
for hs := range membersByHomeserver {
|
|
||||||
homeserverSet[hs] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
homeservers := make([]string, 0, len(homeserverSet))
|
|
||||||
for hs := range homeserverSet {
|
|
||||||
homeservers = append(homeservers, hs)
|
|
||||||
}
|
|
||||||
|
|
||||||
serverVersionInfoByHomeserver := getServerVersionInfoByHomeserver(homeservers, federationClient)
|
|
||||||
|
|
||||||
// Info map tree.
|
|
||||||
roomInfoTree := make(RoomInfoTree)
|
|
||||||
|
|
||||||
for roomID, membersByHomeserver := range membersByHomeserverByRoomID {
|
|
||||||
for hs, members := range membersByHomeserver {
|
|
||||||
serverVersionInfo := serverVersionInfoByHomeserver[hs]
|
|
||||||
|
|
||||||
maxRoomVersion := getMaxRoomVersion(serverVersionInfo)
|
|
||||||
|
|
||||||
// Sort into roomInfoTree and add to counters.
|
|
||||||
roomInfo, ok := roomInfoTree[roomID]
|
|
||||||
if !ok {
|
|
||||||
roomInfo = &RoomInfo{MaxRoomVersions: make(map[string]*MaxRoomVersionInfo)}
|
|
||||||
roomInfoTree[roomID] = roomInfo
|
|
||||||
}
|
|
||||||
maxRoomVersionInfo, ok := roomInfo.MaxRoomVersions[maxRoomVersion]
|
|
||||||
if !ok {
|
|
||||||
maxRoomVersionInfo = &MaxRoomVersionInfo{Servers: make(map[string]*ServerInfo)}
|
|
||||||
roomInfo.MaxRoomVersions[maxRoomVersion] = maxRoomVersionInfo
|
|
||||||
}
|
|
||||||
serverInfo, ok := maxRoomVersionInfo.Servers[serverVersionInfo.Server.Name]
|
|
||||||
if !ok {
|
|
||||||
serverInfo = &ServerInfo{Versions: make(map[string]*VersionInfo)}
|
|
||||||
maxRoomVersionInfo.Servers[serverVersionInfo.Server.Name] = serverInfo
|
|
||||||
}
|
|
||||||
versionInfo, ok := serverInfo.Versions[serverVersionInfo.Server.Version]
|
|
||||||
if !ok {
|
|
||||||
versionInfo = &VersionInfo{Homeservers: make(map[string]*HomeserverInfo)}
|
|
||||||
serverInfo.Versions[serverVersionInfo.Server.Version] = versionInfo
|
|
||||||
}
|
|
||||||
homeserverInfo, ok := versionInfo.Homeservers[hs]
|
|
||||||
if !ok {
|
|
||||||
homeserverInfo = &HomeserverInfo{}
|
|
||||||
versionInfo.Homeservers[hs] = homeserverInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
homeserverInfo.MemberCount = members
|
|
||||||
versionInfo.MemberCount += members
|
|
||||||
serverInfo.MemberCount += members
|
|
||||||
maxRoomVersionInfo.MemberCount += members
|
|
||||||
roomInfo.MemberCount += members
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for roomID, roomInfo := range roomInfoTree {
|
for roomID, roomInfo := range roomInfoTree {
|
||||||
fmt.Println("Room:")
|
fmt.Println("Room:")
|
||||||
|
|
|
||||||
178
roominfotree/maxroomversion.go
Normal file
178
roominfotree/maxroomversion.go
Normal file
|
|
@ -0,0 +1,178 @@
|
||||||
|
package roominfotree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-version"
|
||||||
|
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Gets the maximum supported room version for the given server-version-pair.
|
||||||
|
func getMaxRoomVersion(serverVersionInfo fclient.Version) string {
|
||||||
|
// Use only the first part of the version string as sometimes there are suffixes after a space, like " (<commit>)", which then can't be parsed.
|
||||||
|
serverVersion, err := version.NewVersion(strings.Split(serverVersionInfo.Server.Version, " ")[0])
|
||||||
|
if err != nil {
|
||||||
|
return "unkown"
|
||||||
|
}
|
||||||
|
|
||||||
|
switch serverVersionInfo.Server.Name {
|
||||||
|
case "Conduit":
|
||||||
|
// https://conduit.rs/
|
||||||
|
// https://conduit.rs/changelog/
|
||||||
|
// https://gitlab.com/famedly/conduit
|
||||||
|
switch {
|
||||||
|
// https://conduit.rs/changelog/#v0-10-8-2025-08-11
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.10.8"))):
|
||||||
|
return "v12"
|
||||||
|
// https://conduit.rs/changelog/#v0-7-0-2024-04-25
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.7.0"))):
|
||||||
|
return "v11"
|
||||||
|
// https://conduit.rs/changelog/#v0-5-0-2022-12-21
|
||||||
|
// Includes MR 400:
|
||||||
|
// https://gitlab.com/famedly/conduit/-/merge_requests/400/commits
|
||||||
|
// MR 400 includes a commit, which specifies v10 as stable.
|
||||||
|
// https://gitlab.com/famedly/conduit/-/commit/1e1a144dfa98429ef9f02d16045796b73013830d
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.5.0"))):
|
||||||
|
return "v10"
|
||||||
|
// https://conduit.rs/changelog/#v0-4-0-2022-06-23
|
||||||
|
// Includes MR 257:
|
||||||
|
// https://gitlab.com/famedly/conduit/-/merge_requests/257/commits
|
||||||
|
// MR 257 includes a commit, which specifies added support v7 to v9.
|
||||||
|
// https://gitlab.com/famedly/conduit/-/commit/0ae39807a478370a769217d01fa33514299a2b35
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.4.0"))):
|
||||||
|
return "v9"
|
||||||
|
// https://conduit.rs/changelog/#v0-2-0-2021-09-01
|
||||||
|
default:
|
||||||
|
return "v6"
|
||||||
|
}
|
||||||
|
case "conduwuit", "Conduwuit":
|
||||||
|
// Using continuwuitys source (history) as a reference:
|
||||||
|
// https://forgejo.ellis.link/continuwuation/continuwuity
|
||||||
|
|
||||||
|
// History from first commit on "continuwuity":
|
||||||
|
// https://forgejo.ellis.link/continuwuation/continuwuity/commits/commit/e054a56b3286a6fb3091bedd5261089435ed26d1
|
||||||
|
// Last commit on "conduwuit"/"Conduwuit":
|
||||||
|
// https://forgejo.ellis.link/continuwuation/continuwuity/src/commit/d8311a5ff672fdc4729d956af5e3af8646b0670d
|
||||||
|
// Last version was "0.5.0":
|
||||||
|
// https://forgejo.ellis.link/continuwuation/continuwuity/src/commit/d8311a5ff672fdc4729d956af5e3af8646b0670d/Cargo.toml
|
||||||
|
|
||||||
|
// Matching both "conduwuit" and "Conduwuit" as the capitalization got changed.
|
||||||
|
// https://forgejo.ellis.link/continuwuation/continuwuity/commit/5b5ccba64e3d36a9235f4e0d449f40d859046dad
|
||||||
|
|
||||||
|
switch {
|
||||||
|
// Since the version went from "0.7.0-<something>" to "0.3.0" and the last version was "0.5.0", give all versions greater than "0.7.0" a lower max room version.
|
||||||
|
// https://forgejo.ellis.link/continuwuation/continuwuity/commit/af0b81f5fb737d3550cf22fbcf8d8b8eb1947408
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.7.0"))):
|
||||||
|
return "v10"
|
||||||
|
// v11 support (shows there as included in tag "v0.3.0"):
|
||||||
|
// https://forgejo.ellis.link/continuwuation/continuwuity/commit/223f05c922ea6f3085d386f0758df550459a25c3
|
||||||
|
// Tag "v0.3.0":
|
||||||
|
// https://forgejo.ellis.link/continuwuation/continuwuity/src/tag/v0.3.0/src/service/globals/mod.rs#L130
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.3.0"))):
|
||||||
|
return "v11"
|
||||||
|
// First version named "Conduwuit"/"conduwuit":
|
||||||
|
// https://forgejo.ellis.link/continuwuation/continuwuity/commit/e71855cd0b59d9274e8528a4c1ee480f99006c3c
|
||||||
|
// v10 support at first version named "Conduwuit"/"conduwuit":
|
||||||
|
// https://forgejo.ellis.link/continuwuation/continuwuity/src/commit/e71855cd0b59d9274e8528a4c1ee480f99006c3c/src/service/globals/mod.rs#L187
|
||||||
|
// And shows first version as "0.7.0-alpha+conduwuit-0.1.3":
|
||||||
|
// https://forgejo.ellis.link/continuwuation/continuwuity/src/commit/e71855cd0b59d9274e8528a4c1ee480f99006c3c/Cargo.toml
|
||||||
|
// Because of this versioning and the match on "0.7.0" before, this default should never match, but it is included for clarity.
|
||||||
|
default:
|
||||||
|
return "v10"
|
||||||
|
}
|
||||||
|
case "continuwuity":
|
||||||
|
// https://continuwuity.org/
|
||||||
|
// https://forgejo.ellis.link/continuwuation/continuwuity
|
||||||
|
|
||||||
|
// First version named "continuwuity":
|
||||||
|
// https://forgejo.ellis.link/continuwuation/continuwuity/commit/dc599db19c48ad3cbae15fc419c4a531d217ed05
|
||||||
|
// v11 support at first version named "continuwuity":
|
||||||
|
// https://forgejo.ellis.link/continuwuation/continuwuity/src/commit/dc599db19c48ad3cbae15fc419c4a531d217ed05/src/core/info/room_version.rs
|
||||||
|
return "v11"
|
||||||
|
case "Dendrite":
|
||||||
|
// https://github.com/element-hq/dendrite
|
||||||
|
// https://element-hq.github.io/dendrite/
|
||||||
|
// https://github.com/element-hq/dendrite/blob/main/CHANGES.md
|
||||||
|
switch {
|
||||||
|
// https://github.com/element-hq/dendrite/blob/v0.15.0/CHANGES.md#dendrite-0150-2025-08-12
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.15.0"))):
|
||||||
|
return "v12"
|
||||||
|
// https://github.com/matrix-org/dendrite/blob/v0.13.3/CHANGES.md#dendrite-0133-2023-09-28
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.13.3"))):
|
||||||
|
return "v11"
|
||||||
|
// https://github.com/matrix-org/dendrite/blob/v0.8.7/CHANGES.md#dendrite-087-2022-06-01
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.8.7"))):
|
||||||
|
return "v10"
|
||||||
|
// https://github.com/matrix-org/dendrite/blob/v0.8.6/CHANGES.md#dendrite-086-2022-05-26
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.8.6"))):
|
||||||
|
return "v9"
|
||||||
|
// https://github.com/matrix-org/dendrite/blob/v0.8.6/CHANGES.md#dendrite-086-2022-05-26
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.8.6"))):
|
||||||
|
return "v8"
|
||||||
|
// https://github.com/matrix-org/dendrite/blob/v0.4.1/CHANGES.md#dendrite-041-2021-07-26
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.4.1"))):
|
||||||
|
return "v7"
|
||||||
|
// https://github.com/matrix-org/dendrite/blob/v0.1.0/CHANGES.md#dendrite-010-2020-10-08
|
||||||
|
default:
|
||||||
|
return "v6"
|
||||||
|
}
|
||||||
|
case "Synapse":
|
||||||
|
// https://github.com/element-hq/synapse/
|
||||||
|
// https://element-hq.github.io/synapse/latest/
|
||||||
|
// https://github.com/element-hq/synapse/blob/develop/CHANGES.md
|
||||||
|
// https://github.com/element-hq/synapse/blob/develop/docs/changelogs/
|
||||||
|
switch {
|
||||||
|
// https://github.com/element-hq/synapse/blob/v1.135.1/CHANGES.md#synapse-11351-2025-08-11
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("1.135.1"))):
|
||||||
|
return "v12"
|
||||||
|
// https://github.com/element-hq/synapse/blob/v1.89.0rc1/CHANGES.md#synapse-1890rc1-2023-07-25
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("1.89.0rc1"))):
|
||||||
|
return "v11"
|
||||||
|
// https://github.com/element-hq/synapse/blob/v1.64.0rc1/CHANGES.md#synapse-1640rc1-2022-07-26
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("1.64.0rc1"))):
|
||||||
|
return "v10"
|
||||||
|
// https://github.com/element-hq/synapse/blob/v1.42.0rc2/CHANGES.md#synapse-1420rc2-2021-09-06
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("1.42.0rc2"))):
|
||||||
|
return "v9"
|
||||||
|
// https://github.com/element-hq/synapse/blob/v1.40.0rc3/CHANGES.md#synapse-1400rc3-2021-08-09
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("1.40.0rc3"))):
|
||||||
|
return "v8"
|
||||||
|
// https://github.com/element-hq/synapse/blob/v1.37.0rc1/CHANGES.md#synapse-1370rc1-2021-06-24
|
||||||
|
// https://github.com/matrix-org/synapse/pull/10167
|
||||||
|
// https://github.com/matrix-org/synapse/pull/10167/files#diff-8e36e2fc4dec5d84357ee3d140ad223b66fb36e630c25bbb45382ca59cdb0f40
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("1.37.0rc1"))):
|
||||||
|
return "v7"
|
||||||
|
// https://github.com/element-hq/synapse/blob/v1.14.0rc1/CHANGES.md#synapse-1140rc1-2020-05-26
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("1.14.0rc1"))):
|
||||||
|
return "v6"
|
||||||
|
// https://github.com/element-hq/synapse/blob/v1.0.0rc1/CHANGES.md#synapse-100rc1-2019-06-07
|
||||||
|
// https://github.com/matrix-org/synapse/pull/5354
|
||||||
|
// https://github.com/matrix-org/synapse/pull/5354/files#diff-8e36e2fc4dec5d84357ee3d140ad223b66fb36e630c25bbb45382ca59cdb0f40
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("1.0.0rc1"))):
|
||||||
|
return "v5"
|
||||||
|
// https://github.com/element-hq/synapse/blob/v0.99.5rc1/CHANGES.md#synapse-0995rc1-2019-05-21
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.99.5rc1"))):
|
||||||
|
return "v4"
|
||||||
|
// https://github.com/element-hq/synapse/blob/v0.99.0rc1/CHANGES.md#synapse-0990rc1-2019-01-30
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.99.0rc1"))):
|
||||||
|
return "v3"
|
||||||
|
// https://github.com/element-hq/synapse/blob/v0.34.1rc1/CHANGES.md#synapse-0341rc1-2019-01-08
|
||||||
|
// https://github.com/matrix-org/synapse/pull/4307
|
||||||
|
// https://github.com/matrix-org/synapse/pull/4307/files#diff-32e0f096397b0e3545054c51c42b5be4f0db953083b60d76a047cb1618f6b877
|
||||||
|
case serverVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.34.1rc1"))):
|
||||||
|
return "v2"
|
||||||
|
default:
|
||||||
|
return "v1"
|
||||||
|
}
|
||||||
|
case "Tuwunel":
|
||||||
|
// https://github.com/matrix-construct/tuwunel
|
||||||
|
|
||||||
|
// First version named "Tuwunel":
|
||||||
|
// https://github.com/matrix-construct/tuwunel/commit/9b658d86b2f49d01ba8d2f5ae7f263a104e8f282#diff-d58f31e506570d0bcb7629251ec1b350c5dde4a205a338349f154f3fd3187e93
|
||||||
|
// v11 support at first version named "Tuwunel":
|
||||||
|
// https://github.com/matrix-construct/tuwunel/blob/9b658d86b2f49d01ba8d2f5ae7f263a104e8f282/src/core/info/room_version.rs
|
||||||
|
return "v11"
|
||||||
|
default:
|
||||||
|
return "unkown"
|
||||||
|
}
|
||||||
|
}
|
||||||
169
roominfotree/roominfotree.go
Normal file
169
roominfotree/roominfotree.go
Normal file
|
|
@ -0,0 +1,169 @@
|
||||||
|
package roominfotree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"log"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||||
|
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||||
|
"maunium.net/go/mautrix"
|
||||||
|
"maunium.net/go/mautrix/id"
|
||||||
|
)
|
||||||
|
|
||||||
|
type homeserverServerVersionInfo struct {
|
||||||
|
homeserver string
|
||||||
|
serverVersionInfo fclient.Version
|
||||||
|
}
|
||||||
|
|
||||||
|
type RoomInfoTree map[id.RoomID](*RoomInfo)
|
||||||
|
|
||||||
|
type RoomInfo struct {
|
||||||
|
MemberCount uint
|
||||||
|
MaxRoomVersions map[string](*MaxRoomVersionInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
type MaxRoomVersionInfo struct {
|
||||||
|
MemberCount uint
|
||||||
|
Servers map[string](*ServerInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServerInfo struct {
|
||||||
|
MemberCount uint
|
||||||
|
Versions map[string](*VersionInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
type VersionInfo struct {
|
||||||
|
MemberCount uint
|
||||||
|
Homeservers map[string](*HomeserverInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
type HomeserverInfo struct {
|
||||||
|
MemberCount uint
|
||||||
|
}
|
||||||
|
|
||||||
|
var unknownServerVersionInfo = fclient.Version{
|
||||||
|
Server: struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
}{
|
||||||
|
Name: "unknown",
|
||||||
|
Version: "unknown",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func getServerVersionInfoByHomeserver(homeservers []string, federationClient *fclient.Client) map[string](fclient.Version) {
|
||||||
|
homeserverChannel := make(chan string)
|
||||||
|
go func() {
|
||||||
|
for _, hs := range homeservers {
|
||||||
|
homeserverChannel <- hs
|
||||||
|
}
|
||||||
|
close(homeserverChannel)
|
||||||
|
}()
|
||||||
|
|
||||||
|
homeserverSVInfoChannel := make(chan homeserverServerVersionInfo)
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
const numHomeserverSVInfoReceivers = 100
|
||||||
|
wg.Add(numHomeserverSVInfoReceivers)
|
||||||
|
for i := 0; i < numHomeserverSVInfoReceivers; i++ {
|
||||||
|
go func() {
|
||||||
|
for hs := range homeserverChannel {
|
||||||
|
serverVersionInfo, err := federationClient.GetVersion(context.Background(), spec.ServerName(hs))
|
||||||
|
if err != nil {
|
||||||
|
serverVersionInfo = unknownServerVersionInfo
|
||||||
|
}
|
||||||
|
homeserverSVInfoChannel <- homeserverServerVersionInfo{hs, serverVersionInfo}
|
||||||
|
}
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(homeserverSVInfoChannel)
|
||||||
|
}()
|
||||||
|
|
||||||
|
serverVersionInfoByHomeserver := make(map[string](fclient.Version))
|
||||||
|
for homeserverSVInfo := range homeserverSVInfoChannel {
|
||||||
|
serverVersionInfoByHomeserver[homeserverSVInfo.homeserver] = homeserverSVInfo.serverVersionInfo
|
||||||
|
}
|
||||||
|
return serverVersionInfoByHomeserver
|
||||||
|
}
|
||||||
|
|
||||||
|
func Get(roomIDs []id.RoomID, client *mautrix.Client, federationClient *fclient.Client) RoomInfoTree {
|
||||||
|
joinedMembersByRoomID := make(map[id.RoomID]*mautrix.RespJoinedMembers)
|
||||||
|
for _, roomID := range roomIDs {
|
||||||
|
joinedMembers, err := client.JoinedMembers(context.Background(), roomID)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
joinedMembersByRoomID[roomID] = joinedMembers
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
homeserverSet := make(map[string]bool)
|
||||||
|
for _, membersByHomeserver := range membersByHomeserverByRoomID {
|
||||||
|
for hs := range membersByHomeserver {
|
||||||
|
homeserverSet[hs] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
homeservers := make([]string, 0, len(homeserverSet))
|
||||||
|
for hs := range homeserverSet {
|
||||||
|
homeservers = append(homeservers, hs)
|
||||||
|
}
|
||||||
|
|
||||||
|
serverVersionInfoByHomeserver := getServerVersionInfoByHomeserver(homeservers, federationClient)
|
||||||
|
|
||||||
|
roomInfoTree := make(RoomInfoTree)
|
||||||
|
|
||||||
|
for roomID, membersByHomeserver := range membersByHomeserverByRoomID {
|
||||||
|
for hs, members := range membersByHomeserver {
|
||||||
|
serverVersionInfo := serverVersionInfoByHomeserver[hs]
|
||||||
|
|
||||||
|
maxRoomVersion := getMaxRoomVersion(serverVersionInfo)
|
||||||
|
|
||||||
|
// Sort into roomInfoTree and add to counters.
|
||||||
|
roomInfo, ok := roomInfoTree[roomID]
|
||||||
|
if !ok {
|
||||||
|
roomInfo = &RoomInfo{MaxRoomVersions: make(map[string]*MaxRoomVersionInfo)}
|
||||||
|
roomInfoTree[roomID] = roomInfo
|
||||||
|
}
|
||||||
|
maxRoomVersionInfo, ok := roomInfo.MaxRoomVersions[maxRoomVersion]
|
||||||
|
if !ok {
|
||||||
|
maxRoomVersionInfo = &MaxRoomVersionInfo{Servers: make(map[string]*ServerInfo)}
|
||||||
|
roomInfo.MaxRoomVersions[maxRoomVersion] = maxRoomVersionInfo
|
||||||
|
}
|
||||||
|
serverInfo, ok := maxRoomVersionInfo.Servers[serverVersionInfo.Server.Name]
|
||||||
|
if !ok {
|
||||||
|
serverInfo = &ServerInfo{Versions: make(map[string]*VersionInfo)}
|
||||||
|
maxRoomVersionInfo.Servers[serverVersionInfo.Server.Name] = serverInfo
|
||||||
|
}
|
||||||
|
versionInfo, ok := serverInfo.Versions[serverVersionInfo.Server.Version]
|
||||||
|
if !ok {
|
||||||
|
versionInfo = &VersionInfo{Homeservers: make(map[string]*HomeserverInfo)}
|
||||||
|
serverInfo.Versions[serverVersionInfo.Server.Version] = versionInfo
|
||||||
|
}
|
||||||
|
homeserverInfo, ok := versionInfo.Homeservers[hs]
|
||||||
|
if !ok {
|
||||||
|
homeserverInfo = &HomeserverInfo{}
|
||||||
|
versionInfo.Homeservers[hs] = homeserverInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
homeserverInfo.MemberCount = members
|
||||||
|
versionInfo.MemberCount += members
|
||||||
|
serverInfo.MemberCount += members
|
||||||
|
maxRoomVersionInfo.MemberCount += members
|
||||||
|
roomInfo.MemberCount += members
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return roomInfoTree
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue