ソースを参照

Store username/discriminator/bot status in puppet table

Tulir Asokan 2 年 前
コミット
0e5faa5510

+ 3 - 2
database/database.go

@@ -68,9 +68,10 @@ func New(baseDB *dbutil.Database, log maulogger.Logger) *Database {
 	return db
 }
 
-func strPtr(val string) *string {
+func strPtr[T ~string](val T) *string {
 	if val == "" {
 		return nil
 	}
-	return &val
+	valStr := string(val)
+	return &valStr
 }

+ 21 - 16
database/puppet.go

@@ -11,7 +11,7 @@ import (
 
 const (
 	puppetSelect = "SELECT id, name, name_set, avatar, avatar_url, avatar_set," +
-		" contact_info_set, custom_mxid, access_token, next_batch" +
+		" contact_info_set, username, discriminator, is_bot, custom_mxid, access_token, next_batch" +
 		" FROM puppet "
 )
 
@@ -66,14 +66,19 @@ type Puppet struct {
 	db  *Database
 	log log.Logger
 
-	ID             string
-	Name           string
-	NameSet        bool
-	Avatar         string
-	AvatarURL      id.ContentURI
-	AvatarSet      bool
+	ID        string
+	Name      string
+	NameSet   bool
+	Avatar    string
+	AvatarURL id.ContentURI
+	AvatarSet bool
+
 	ContactInfoSet bool
 
+	Username      string
+	Discriminator string
+	IsBot         bool
+
 	CustomMXID  id.UserID
 	AccessToken string
 	NextBatch   string
@@ -84,7 +89,7 @@ func (p *Puppet) Scan(row dbutil.Scannable) *Puppet {
 	var customMXID, accessToken, nextBatch sql.NullString
 
 	err := row.Scan(&p.ID, &p.Name, &p.NameSet, &p.Avatar, &avatarURL, &p.AvatarSet, &p.ContactInfoSet,
-		&customMXID, &accessToken, &nextBatch)
+		&p.Username, &p.Discriminator, &p.IsBot, &customMXID, &accessToken, &nextBatch)
 
 	if err != nil {
 		if err != sql.ErrNoRows {
@@ -105,11 +110,11 @@ func (p *Puppet) Scan(row dbutil.Scannable) *Puppet {
 
 func (p *Puppet) Insert() {
 	query := `
-		INSERT INTO puppet (id, name, name_set, avatar, avatar_url, avatar_set, contact_info_set, custom_mxid, access_token, next_batch)
-		VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
+		INSERT INTO puppet (id, name, name_set, avatar, avatar_url, avatar_set, contact_info_set, username, discriminator, is_bot, custom_mxid, access_token, next_batch)
+		VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
 	`
 	_, err := p.db.Exec(query, p.ID, p.Name, p.NameSet, p.Avatar, p.AvatarURL.String(), p.AvatarSet, p.ContactInfoSet,
-		strPtr(string(p.CustomMXID)), strPtr(p.AccessToken), strPtr(p.NextBatch))
+		p.Username, p.Discriminator, p.IsBot, strPtr(p.CustomMXID), strPtr(p.AccessToken), strPtr(p.NextBatch))
 
 	if err != nil {
 		p.log.Warnfln("Failed to insert %s: %v", p.ID, err)
@@ -119,12 +124,12 @@ func (p *Puppet) Insert() {
 
 func (p *Puppet) Update() {
 	query := `
-		UPDATE puppet SET name=$1, name_set=$2, avatar=$3, avatar_url=$4, avatar_set=$5,
-		                  contact_info_set=$6, custom_mxid=$7, access_token=$8, next_batch=$9
-		WHERE id=$10
+		UPDATE puppet SET name=$1, name_set=$2, avatar=$3, avatar_url=$4, avatar_set=$5, contact_info_set=$6,
+		                  username=$7, discriminator=$8, is_bot=$9, custom_mxid=$10, access_token=$11, next_batch=$12
+		WHERE id=$13
 	`
-	_, err := p.db.Exec(query, p.Name, p.NameSet, p.Avatar, p.AvatarURL.String(), p.AvatarSet,
-		p.ContactInfoSet, strPtr(string(p.CustomMXID)), strPtr(p.AccessToken), strPtr(p.NextBatch),
+	_, err := p.db.Exec(query, p.Name, p.NameSet, p.Avatar, p.AvatarURL.String(), p.AvatarSet, p.ContactInfoSet,
+		p.Username, p.Discriminator, p.IsBot, strPtr(p.CustomMXID), strPtr(p.AccessToken), strPtr(p.NextBatch),
 		p.ID)
 
 	if err != nil {

+ 6 - 1
database/upgrades/00-latest-revision.sql

@@ -1,4 +1,4 @@
--- v0 -> v17: Latest revision
+-- v0 -> v18: Latest revision
 
 CREATE TABLE guild (
     dcid       TEXT PRIMARY KEY,
@@ -68,8 +68,13 @@ CREATE TABLE puppet (
     avatar           TEXT NOT NULL,
     avatar_url       TEXT NOT NULL,
     avatar_set       BOOLEAN NOT NULL DEFAULT false,
+
     contact_info_set BOOLEAN NOT NULL DEFAULT false,
 
+    username      TEXT NOT NULL DEFAULT '',
+    discriminator TEXT NOT NULL DEFAULT '',
+    is_bot        BOOLEAN NOT NULL DEFAULT false,
+
     custom_mxid  TEXT,
     access_token TEXT,
     next_batch   TEXT

+ 4 - 0
database/upgrades/18-extra-ghost-metadata.sql

@@ -0,0 +1,4 @@
+-- v18: Store additional metadata for ghosts
+ALTER TABLE puppet ADD COLUMN username TEXT NOT NULL DEFAULT '';
+ALTER TABLE puppet ADD COLUMN discriminator TEXT NOT NULL DEFAULT '';
+ALTER TABLE puppet ADD COLUMN is_bot BOOLEAN NOT NULL DEFAULT false;

+ 27 - 11
puppet.go

@@ -281,7 +281,8 @@ func (puppet *Puppet) UpdateInfo(source *User, info *discordgo.User) {
 		puppet.log.Error().Err(err).Msg("Failed to ensure registered")
 	}
 
-	changed := puppet.UpdateContactInfo(source, info)
+	changed := false
+	changed = puppet.UpdateContactInfo(info) || changed
 	changed = puppet.UpdateName(info) || changed
 	changed = puppet.UpdateAvatar(info) || changed
 	if changed {
@@ -289,30 +290,45 @@ func (puppet *Puppet) UpdateInfo(source *User, info *discordgo.User) {
 	}
 }
 
-func (puppet *Puppet) UpdateContactInfo(source *User, info *discordgo.User) bool {
-	if puppet.bridge.Config.Homeserver.Software != bridgeconfig.SoftwareHungry {
-		return false
+func (puppet *Puppet) UpdateContactInfo(info *discordgo.User) bool {
+	changed := false
+	if puppet.Username != info.Username {
+		puppet.Username = info.Username
+		changed = true
 	}
-
-	if puppet.ContactInfoSet {
-		return false
+	if puppet.Discriminator != info.Discriminator {
+		puppet.Discriminator = info.Discriminator
+		changed = true
 	}
+	if puppet.IsBot != info.Bot {
+		puppet.IsBot = info.Bot
+		changed = true
+	}
+	if changed {
+		puppet.ContactInfoSet = false
+		puppet.ResendContactInfo()
+		return true
+	}
+	return false
+}
 
+func (puppet *Puppet) ResendContactInfo() {
+	if puppet.bridge.Config.Homeserver.Software != bridgeconfig.SoftwareHungry || puppet.ContactInfoSet {
+		return
+	}
 	contactInfo := map[string]any{
 		"com.beeper.bridge.identifiers": []string{
-			fmt.Sprintf("discord:%s#%s", info.Username, info.Discriminator),
+			fmt.Sprintf("discord:%s#%s", puppet.Username, puppet.Discriminator),
 		},
 		"com.beeper.bridge.remote_id":      puppet.ID,
 		"com.beeper.bridge.service":        puppet.bridge.BeeperServiceName,
 		"com.beeper.bridge.network":        puppet.bridge.BeeperNetworkName,
-		"com.beeper.bridge.is_network_bot": info.Bot,
+		"com.beeper.bridge.is_network_bot": puppet.IsBot,
 	}
 	err := puppet.DefaultIntent().BeeperUpdateProfile(contactInfo)
 	if err != nil {
 		puppet.log.Warn().Err(err).Msg("Failed to store custom contact info in profile")
-		return false
 	} else {
 		puppet.ContactInfoSet = true
-		return true
 	}
 }