mirror of
https://codeberg.org/june64/mrvc.git
synced 2026-01-10 16:06:33 +01:00
Move building of homeservers array into separate function to make Get function easier to follow.
181 lines
5.2 KiB
Go
181 lines
5.2 KiB
Go
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 getMembersByHomeserverByRoomID(roomIDs []id.RoomID, client *mautrix.Client) map[id.RoomID](map[string]uint) {
|
|
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 userID := range joinedMembers.Joined {
|
|
membersByHomeserver[userID.Homeserver()]++
|
|
}
|
|
membersByHomeserverByRoomID[roomID] = membersByHomeserver
|
|
}
|
|
|
|
return membersByHomeserverByRoomID
|
|
}
|
|
|
|
// Gets the homeservers appearing in the given membersByHomeserverByRoomID map tree.
|
|
func getHomeservers(membersByHomeserverByRoomID map[id.RoomID]map[string]uint) []string {
|
|
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)
|
|
}
|
|
|
|
return homeservers
|
|
}
|
|
|
|
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 {
|
|
membersByHomeserverByRoomID := getMembersByHomeserverByRoomID(roomIDs, client)
|
|
homeservers := getHomeservers(membersByHomeserverByRoomID)
|
|
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
|
|
}
|