discordid,connector: remember which guilds were bridged
This commit is contained in:
@@ -21,6 +21,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"maps"
|
||||
"net/http"
|
||||
"slices"
|
||||
"sync"
|
||||
@@ -276,8 +277,30 @@ func (d *DiscordClient) syncGuildSpace(_ context.Context, guild *discordgo.Guild
|
||||
})
|
||||
}
|
||||
|
||||
// bridgedGuildIDs returns a set of guild IDs that should be bridged. Note that
|
||||
// presence in the returned set does not imply that the rooms for the guild have
|
||||
// already been created.
|
||||
func (d *DiscordClient) bridgedGuildIDs() map[string]struct{} {
|
||||
meta := d.UserLogin.Metadata.(*discordid.UserLoginMetadata)
|
||||
bridgingGuildIDs := map[string]struct{}{}
|
||||
|
||||
// guilds that were bridged via the provisioning api
|
||||
for guildID, bridged := range meta.BridgedGuildIDs {
|
||||
if bridged {
|
||||
bridgingGuildIDs[guildID] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// guilds that were declared in the configuration file
|
||||
for _, guildID := range d.connector.Config.Guilds.BridgingGuildIDs {
|
||||
bridgingGuildIDs[guildID] = struct{}{}
|
||||
}
|
||||
|
||||
return bridgingGuildIDs
|
||||
}
|
||||
|
||||
func (d *DiscordClient) syncGuilds(ctx context.Context) {
|
||||
guildIDs := d.connector.Config.Guilds.BridgingGuildIDs
|
||||
guildIDs := slices.Sorted(maps.Keys(d.bridgedGuildIDs()))
|
||||
|
||||
for _, guildID := range guildIDs {
|
||||
log := zerolog.Ctx(ctx).With().
|
||||
@@ -298,6 +321,7 @@ func (d *DiscordClient) bridgeGuild(ctx context.Context, guildID string) error {
|
||||
guild, err := d.Session.State.Guild(guildID)
|
||||
if errors.Is(err, discordgo.ErrStateNotFound) || guild == nil {
|
||||
log.Err(err).Msg("Couldn't find guild, user isn't a member?")
|
||||
// TODO likely left/kicked/banned from guild; nuke the portals
|
||||
return errors.New("couldn't find guild in state")
|
||||
}
|
||||
|
||||
|
||||
@@ -117,18 +117,32 @@ func (p *ProvisioningAPI) makeHandler(handler func(http.ResponseWriter, *http.Re
|
||||
}
|
||||
|
||||
func (p *ProvisioningAPI) guildsList(w http.ResponseWriter, r *http.Request, login *bridgev2.UserLogin, client *DiscordClient) {
|
||||
ctx := r.Context()
|
||||
p.log.Info().Str("login_id", discordid.ParseUserLoginID(login.ID)).Msg("guilds list requested via provisioning api")
|
||||
|
||||
var resp respGuildsList
|
||||
resp.Guilds = []guildEntry{}
|
||||
for _, guild := range client.Session.State.Guilds {
|
||||
portalKey := client.guildPortalKeyFromID(guild.ID)
|
||||
portal, err := p.connector.Bridge.GetExistingPortalByKey(ctx, portalKey)
|
||||
if err != nil {
|
||||
p.log.Err(err).
|
||||
Str("guild_id", guild.ID).
|
||||
Msg("Failed to get guild portal for provisioning list")
|
||||
}
|
||||
|
||||
mxid := ""
|
||||
if portal != nil {
|
||||
mxid = portal.MXID.String()
|
||||
}
|
||||
|
||||
resp.Guilds = append(resp.Guilds, guildEntry{
|
||||
ID: guild.ID,
|
||||
Name: guild.Name,
|
||||
AvatarURL: discordgo.EndpointGuildIcon(guild.ID, guild.Icon),
|
||||
|
||||
MXID: mxid,
|
||||
BridgingMode: "everything",
|
||||
|
||||
Available: !guild.Unavailable,
|
||||
})
|
||||
}
|
||||
@@ -148,10 +162,27 @@ func (p *ProvisioningAPI) bridgeGuild(w http.ResponseWriter, r *http.Request, lo
|
||||
Str("guild_id", guildID).
|
||||
Msg("requested to bridge guild via provisioning api")
|
||||
|
||||
// TODO detect guild already bridged
|
||||
meta := login.Metadata.(*discordid.UserLoginMetadata)
|
||||
|
||||
if meta.BridgedGuildIDs == nil {
|
||||
meta.BridgedGuildIDs = map[string]bool{}
|
||||
}
|
||||
_, alreadyBridged := meta.BridgedGuildIDs[guildID]
|
||||
meta.BridgedGuildIDs[guildID] = true
|
||||
|
||||
if err := login.Save(r.Context()); err != nil {
|
||||
p.log.Err(err).Msg("Failed to save login after guild bridge request")
|
||||
mautrix.MUnknown.WithMessage("failed to save login: %v", err).Write(w)
|
||||
return
|
||||
}
|
||||
|
||||
go client.bridgeGuild(context.TODO(), guildID)
|
||||
|
||||
exhttp.WriteJSONResponse(w, 201, nil)
|
||||
responseStatus := 201
|
||||
if alreadyBridged {
|
||||
responseStatus = 200
|
||||
}
|
||||
exhttp.WriteJSONResponse(w, responseStatus, nil)
|
||||
}
|
||||
|
||||
func (p *ProvisioningAPI) unbridgeGuild(w http.ResponseWriter, r *http.Request, login *bridgev2.UserLogin, client *DiscordClient) {
|
||||
@@ -166,6 +197,16 @@ func (p *ProvisioningAPI) unbridgeGuild(w http.ResponseWriter, r *http.Request,
|
||||
Str("guild_id", guildID).
|
||||
Msg("requested to unbridge guild via provisioning api")
|
||||
|
||||
meta := login.Metadata.(*discordid.UserLoginMetadata)
|
||||
if meta.BridgedGuildIDs != nil {
|
||||
delete(meta.BridgedGuildIDs, guildID)
|
||||
}
|
||||
if err := login.Save(r.Context()); err != nil {
|
||||
p.log.Err(err).Msg("Failed to save login after guild unbridge request")
|
||||
mautrix.MUnknown.WithMessage("failed to save login: %v", err).Write(w)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.TODO()
|
||||
|
||||
portalKey := client.guildPortalKeyFromID(guildID)
|
||||
|
||||
@@ -30,4 +30,5 @@ type PortalMetadata struct {
|
||||
type UserLoginMetadata struct {
|
||||
Token string `json:"token"`
|
||||
HeartbeatSession discordgo.HeartbeatSession `json:"heartbeat_session"`
|
||||
BridgedGuildIDs map[string]bool `json:"bridged_guild_ids,omitempty"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user