Expose Application flag to displayname templates

Fixes #94
This commit is contained in:
Tulir Asokan
2023-06-21 01:38:56 +03:00
parent d39499cdcf
commit 200c4fc9d0
11 changed files with 61 additions and 36 deletions

View File

@@ -254,11 +254,11 @@ func (portal *Portal) convertMessageBatch(log zerolog.Logger, source *User, mess
for _, msg := range messages { for _, msg := range messages {
for _, mention := range msg.Mentions { for _, mention := range msg.Mentions {
puppet := portal.bridge.GetPuppetByID(mention.ID) puppet := portal.bridge.GetPuppetByID(mention.ID)
puppet.UpdateInfo(nil, mention, "") puppet.UpdateInfo(nil, mention, nil)
} }
puppet := portal.bridge.GetPuppetByID(msg.Author.ID) puppet := portal.bridge.GetPuppetByID(msg.Author.ID)
puppet.UpdateInfo(source, msg.Author, msg.WebhookID) puppet.UpdateInfo(source, msg.Author, msg)
intent := puppet.IntentFor(portal) intent := puppet.IntentFor(portal)
replyTo := portal.getReplyTarget(source, discordThreadID, msg.MessageReference, msg.Embeds, true) replyTo := portal.getReplyTarget(source, discordThreadID, msg.MessageReference, msg.Embeds, true)
mentions := portal.convertDiscordMentions(msg, false) mentions := portal.convertDiscordMentions(msg, false)

View File

@@ -292,12 +292,17 @@ func (bc BridgeConfig) FormatUsername(userID string) string {
type DisplaynameParams struct { type DisplaynameParams struct {
*discordgo.User *discordgo.User
Webhook bool Webhook bool
Application bool
} }
func (bc BridgeConfig) FormatDisplayname(user *discordgo.User, webhook bool) string { func (bc BridgeConfig) FormatDisplayname(user *discordgo.User, webhook, application bool) string {
var buffer strings.Builder var buffer strings.Builder
_ = bc.displaynameTemplate.Execute(&buffer, &DisplaynameParams{user, webhook}) _ = bc.displaynameTemplate.Execute(&buffer, &DisplaynameParams{
User: user,
Webhook: webhook,
Application: application,
})
return buffer.String() return buffer.String()
} }

View File

@@ -11,7 +11,7 @@ import (
const ( const (
puppetSelect = "SELECT id, name, name_set, avatar, avatar_url, avatar_set," + puppetSelect = "SELECT id, name, name_set, avatar, avatar_url, avatar_set," +
" contact_info_set, global_name, username, discriminator, is_bot, is_webhook, custom_mxid, access_token, next_batch" + " contact_info_set, global_name, username, discriminator, is_bot, is_webhook, is_application, custom_mxid, access_token, next_batch" +
" FROM puppet " " FROM puppet "
) )
@@ -80,6 +80,7 @@ type Puppet struct {
Discriminator string Discriminator string
IsBot bool IsBot bool
IsWebhook bool IsWebhook bool
IsApplication bool
CustomMXID id.UserID CustomMXID id.UserID
AccessToken string AccessToken string
@@ -91,7 +92,7 @@ func (p *Puppet) Scan(row dbutil.Scannable) *Puppet {
var customMXID, accessToken, nextBatch sql.NullString var customMXID, accessToken, nextBatch sql.NullString
err := row.Scan(&p.ID, &p.Name, &p.NameSet, &p.Avatar, &avatarURL, &p.AvatarSet, &p.ContactInfoSet, err := row.Scan(&p.ID, &p.Name, &p.NameSet, &p.Avatar, &avatarURL, &p.AvatarSet, &p.ContactInfoSet,
&p.GlobalName, &p.Username, &p.Discriminator, &p.IsBot, &p.IsWebhook, &customMXID, &accessToken, &nextBatch) &p.GlobalName, &p.Username, &p.Discriminator, &p.IsBot, &p.IsWebhook, &p.IsApplication, &customMXID, &accessToken, &nextBatch)
if err != nil { if err != nil {
if err != sql.ErrNoRows { if err != sql.ErrNoRows {
@@ -114,13 +115,13 @@ func (p *Puppet) Insert() {
query := ` query := `
INSERT INTO puppet ( INSERT INTO puppet (
id, name, name_set, avatar, avatar_url, avatar_set, contact_info_set, id, name, name_set, avatar, avatar_url, avatar_set, contact_info_set,
global_name, username, discriminator, is_bot, is_webhook, global_name, username, discriminator, is_bot, is_webhook, is_application,
custom_mxid, access_token, next_batch custom_mxid, access_token, next_batch
) )
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
` `
_, err := p.db.Exec(query, p.ID, p.Name, p.NameSet, p.Avatar, p.AvatarURL.String(), p.AvatarSet, p.ContactInfoSet, _, err := p.db.Exec(query, p.ID, p.Name, p.NameSet, p.Avatar, p.AvatarURL.String(), p.AvatarSet, p.ContactInfoSet,
p.GlobalName, p.Username, p.Discriminator, p.IsBot, p.IsWebhook, p.GlobalName, p.Username, p.Discriminator, p.IsBot, p.IsWebhook, p.IsApplication,
strPtr(p.CustomMXID), strPtr(p.AccessToken), strPtr(p.NextBatch)) strPtr(p.CustomMXID), strPtr(p.AccessToken), strPtr(p.NextBatch))
if err != nil { if err != nil {
@@ -132,14 +133,14 @@ func (p *Puppet) Insert() {
func (p *Puppet) Update() { func (p *Puppet) Update() {
query := ` query := `
UPDATE puppet SET name=$1, name_set=$2, avatar=$3, avatar_url=$4, avatar_set=$5, contact_info_set=$6, UPDATE puppet SET name=$1, name_set=$2, avatar=$3, avatar_url=$4, avatar_set=$5, contact_info_set=$6,
global_name=$7, username=$8, discriminator=$9, is_bot=$10, is_webhook=$11, global_name=$7, username=$8, discriminator=$9, is_bot=$10, is_webhook=$11, is_application=$12,
custom_mxid=$12, access_token=$13, next_batch=$14 custom_mxid=$13, access_token=$14, next_batch=$15
WHERE id=$15 WHERE id=$16
` `
_, err := p.db.Exec( _, err := p.db.Exec(
query, query,
p.Name, p.NameSet, p.Avatar, p.AvatarURL.String(), p.AvatarSet, p.ContactInfoSet, p.Name, p.NameSet, p.Avatar, p.AvatarURL.String(), p.AvatarSet, p.ContactInfoSet,
p.GlobalName, p.Username, p.Discriminator, p.IsBot, p.IsWebhook, p.GlobalName, p.Username, p.Discriminator, p.IsBot, p.IsWebhook, p.IsApplication,
strPtr(p.CustomMXID), strPtr(p.AccessToken), strPtr(p.NextBatch), strPtr(p.CustomMXID), strPtr(p.AccessToken), strPtr(p.NextBatch),
p.ID, p.ID,
) )

View File

@@ -1,4 +1,4 @@
-- v0 -> v22 (compatible with v19+): Latest revision -- v0 -> v23 (compatible with v19+): Latest revision
CREATE TABLE guild ( CREATE TABLE guild (
dcid TEXT PRIMARY KEY, dcid TEXT PRIMARY KEY,
@@ -71,11 +71,12 @@ CREATE TABLE puppet (
contact_info_set BOOLEAN NOT NULL DEFAULT false, contact_info_set BOOLEAN NOT NULL DEFAULT false,
global_name TEXT NOT NULL DEFAULT '', global_name TEXT NOT NULL DEFAULT '',
username TEXT NOT NULL DEFAULT '', username TEXT NOT NULL DEFAULT '',
discriminator TEXT NOT NULL DEFAULT '', discriminator TEXT NOT NULL DEFAULT '',
is_bot BOOLEAN NOT NULL DEFAULT false, is_bot BOOLEAN NOT NULL DEFAULT false,
is_webhook BOOLEAN NOT NULL DEFAULT false, is_webhook BOOLEAN NOT NULL DEFAULT false,
is_application BOOLEAN NOT NULL DEFAULT false,
custom_mxid TEXT, custom_mxid TEXT,
access_token TEXT, access_token TEXT,

View File

@@ -0,0 +1,2 @@
-- v23 (compatible with v19+): Store is application status for puppets
ALTER TABLE puppet ADD COLUMN is_application BOOLEAN NOT NULL DEFAULT false;

View File

@@ -92,7 +92,8 @@ bridge:
# .Discriminator - The 4 numbers after the name on Discord # .Discriminator - The 4 numbers after the name on Discord
# .Bot - Whether the user is a bot # .Bot - Whether the user is a bot
# .System - Whether the user is an official system user # .System - Whether the user is an official system user
# .Webhook - Whether the user is a webhook # .Webhook - Whether the user is a webhook and is not an application
# .Application - Whether the user is an application
displayname_template: '{{or .GlobalName .Username}}{{if .Bot}} (bot){{end}}' displayname_template: '{{or .GlobalName .Username}}{{if .Bot}} (bot){{end}}'
# Displayname template for Discord channels (bridged as rooms, or spaces when type=4). # Displayname template for Discord channels (bridged as rooms, or spaces when type=4).
# Available variables: # Available variables:

2
go.mod
View File

@@ -38,4 +38,4 @@ require (
maunium.net/go/mauflag v1.0.0 // indirect maunium.net/go/mauflag v1.0.0 // indirect
) )
replace github.com/bwmarrin/discordgo => github.com/beeper/discordgo v0.0.0-20230618183737-3c7afd8d8596 replace github.com/bwmarrin/discordgo => github.com/beeper/discordgo v0.0.0-20230620222529-2cb9d9280e37

4
go.sum
View File

@@ -1,6 +1,6 @@
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
github.com/beeper/discordgo v0.0.0-20230618183737-3c7afd8d8596 h1:PxtbetWbVi2OlACDNtx6YJahhXt/rhiEsGqtOOLSx4o= github.com/beeper/discordgo v0.0.0-20230620222529-2cb9d9280e37 h1:N0c/439VcoHGc+gL1lb3vUjr6vUbXz+vor7SLnBOhJU=
github.com/beeper/discordgo v0.0.0-20230618183737-3c7afd8d8596/go.mod h1:59+AOzzjmL6onAh62nuLXmn7dJCaC/owDLWbGtjTcFA= github.com/beeper/discordgo v0.0.0-20230620222529-2cb9d9280e37/go.mod h1:59+AOzzjmL6onAh62nuLXmn7dJCaC/owDLWbGtjTcFA=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=

View File

@@ -625,7 +625,7 @@ func (portal *Portal) handleDiscordMessageCreate(user *User, msg *discordgo.Mess
log.Debug().Msg("Starting handling of Discord message") log.Debug().Msg("Starting handling of Discord message")
puppet := portal.bridge.GetPuppetByID(msg.Author.ID) puppet := portal.bridge.GetPuppetByID(msg.Author.ID)
puppet.UpdateInfo(user, msg.Author, msg.WebhookID) puppet.UpdateInfo(user, msg.Author, msg)
intent := puppet.IntentFor(portal) intent := puppet.IntentFor(portal)
var discordThreadID string var discordThreadID string
@@ -990,7 +990,7 @@ func (portal *Portal) handleDiscordTyping(evt *discordgo.TypingStart) {
func (portal *Portal) syncParticipant(source *User, participant *discordgo.User, remove bool) { func (portal *Portal) syncParticipant(source *User, participant *discordgo.User, remove bool) {
puppet := portal.bridge.GetPuppetByID(participant.ID) puppet := portal.bridge.GetPuppetByID(participant.ID)
puppet.UpdateInfo(source, participant, "") puppet.UpdateInfo(source, participant, nil)
log := portal.log.With(). log := portal.log.With().
Str("participant_id", participant.ID). Str("participant_id", participant.ID).
Str("ghost_mxid", puppet.MXID.String()). Str("ghost_mxid", puppet.MXID.String()).
@@ -1017,7 +1017,7 @@ func (portal *Portal) syncParticipant(source *User, participant *discordgo.User,
func (portal *Portal) syncParticipants(source *User, participants []*discordgo.User) { func (portal *Portal) syncParticipants(source *User, participants []*discordgo.User) {
for _, participant := range participants { for _, participant := range participants {
puppet := portal.bridge.GetPuppetByID(participant.ID) puppet := portal.bridge.GetPuppetByID(participant.ID)
puppet.UpdateInfo(source, participant, "") puppet.UpdateInfo(source, participant, nil)
user := portal.bridge.GetUserByID(participant.ID) user := portal.bridge.GetUserByID(participant.ID)
if user != nil { if user != nil {
@@ -1847,7 +1847,7 @@ func (portal *Portal) handleMatrixReaction(sender *User, evt *event.Event) {
func (portal *Portal) handleDiscordReaction(user *User, reaction *discordgo.MessageReaction, add bool, thread *Thread, member *discordgo.Member) { func (portal *Portal) handleDiscordReaction(user *User, reaction *discordgo.MessageReaction, add bool, thread *Thread, member *discordgo.Member) {
puppet := portal.bridge.GetPuppetByID(reaction.UserID) puppet := portal.bridge.GetPuppetByID(reaction.UserID)
if member != nil { if member != nil {
puppet.UpdateInfo(user, member.User, "") puppet.UpdateInfo(user, member.User, nil)
} }
intent := puppet.IntentFor(portal) intent := puppet.IntentFor(portal)

View File

@@ -628,7 +628,7 @@ func (portal *Portal) convertDiscordMentions(msg *discordgo.Message, syncGhosts
for _, mention := range msg.Mentions { for _, mention := range msg.Mentions {
puppet := portal.bridge.GetPuppetByID(mention.ID) puppet := portal.bridge.GetPuppetByID(mention.ID)
if syncGhosts { if syncGhosts {
puppet.UpdateInfo(nil, mention, "") puppet.UpdateInfo(nil, mention, nil)
} }
user := portal.bridge.GetUserByID(mention.ID) user := portal.bridge.GetUserByID(mention.ID)
if user != nil { if user != nil {
@@ -661,7 +661,7 @@ func (portal *Portal) convertDiscordTextMessage(ctx context.Context, intent *app
var htmlParts []string var htmlParts []string
if msg.Interaction != nil { if msg.Interaction != nil {
puppet := portal.bridge.GetPuppetByID(msg.Interaction.User.ID) puppet := portal.bridge.GetPuppetByID(msg.Interaction.User.ID)
puppet.UpdateInfo(nil, msg.Interaction.User, "") puppet.UpdateInfo(nil, msg.Interaction.User, nil)
htmlParts = append(htmlParts, fmt.Sprintf(msgInteractionTemplateHTML, puppet.MXID, puppet.Name, msg.Interaction.Name)) htmlParts = append(htmlParts, fmt.Sprintf(msgInteractionTemplateHTML, puppet.MXID, puppet.Name, msg.Interaction.Name))
} }
if msg.Content != "" && !isPlainGifMessage(msg) { if msg.Content != "" && !isPlainGifMessage(msg) {
@@ -708,7 +708,7 @@ func (portal *Portal) convertDiscordTextMessage(ctx context.Context, intent *app
"com.beeper.linkpreviews": previews, "com.beeper.linkpreviews": previews,
} }
if msg.WebhookID != "" && portal.bridge.Config.Bridge.PrefixWebhookMessages { if msg.WebhookID != "" && msg.ApplicationID == "" && portal.bridge.Config.Bridge.PrefixWebhookMessages {
content.EnsureHasHTML() content.EnsureHasHTML()
content.Body = fmt.Sprintf("%s: %s", msg.Author.Username, content.Body) content.Body = fmt.Sprintf("%s: %s", msg.Author.Username, content.Body)
content.FormattedBody = fmt.Sprintf("<strong>%s</strong>: %s", html.EscapeString(msg.Author.Username), content.FormattedBody) content.FormattedBody = fmt.Sprintf("<strong>%s</strong>: %s", html.EscapeString(msg.Author.Username), content.FormattedBody)

View File

@@ -195,7 +195,7 @@ func (puppet *Puppet) updatePortalMeta(meta func(portal *Portal)) {
} }
func (puppet *Puppet) UpdateName(info *discordgo.User) bool { func (puppet *Puppet) UpdateName(info *discordgo.User) bool {
newName := puppet.bridge.Config.Bridge.FormatDisplayname(info, puppet.IsWebhook) newName := puppet.bridge.Config.Bridge.FormatDisplayname(info, puppet.IsWebhook, puppet.IsApplication)
if puppet.Name == newName && puppet.NameSet { if puppet.Name == newName && puppet.NameSet {
return false return false
} }
@@ -285,7 +285,7 @@ func (puppet *Puppet) UpdateAvatar(info *discordgo.User) bool {
return true return true
} }
func (puppet *Puppet) UpdateInfo(source *User, info *discordgo.User, webhookID string) { func (puppet *Puppet) UpdateInfo(source *User, info *discordgo.User, message *discordgo.Message) {
puppet.syncLock.Lock() puppet.syncLock.Lock()
defer puppet.syncLock.Unlock() defer puppet.syncLock.Unlock()
@@ -308,9 +308,24 @@ func (puppet *Puppet) UpdateInfo(source *User, info *discordgo.User, webhookID s
} }
changed := false changed := false
if webhookID != "" && webhookID == info.ID && !puppet.IsWebhook { if message != nil {
puppet.IsWebhook = true if message.WebhookID != "" && message.ApplicationID == "" && !puppet.IsWebhook {
changed = true puppet.log.Debug().
Str("message_id", message.ID).
Str("webhook_id", message.WebhookID).
Msg("Found webhook ID in message, marking ghost as a webhook")
puppet.IsWebhook = true
changed = true
}
if message.ApplicationID != "" && !puppet.IsApplication {
puppet.log.Debug().
Str("message_id", message.ID).
Str("application_id", message.ApplicationID).
Msg("Found application ID in message, marking ghost as an application")
puppet.IsApplication = true
puppet.IsWebhook = false
changed = true
}
} }
changed = puppet.UpdateContactInfo(info) || changed changed = puppet.UpdateContactInfo(info) || changed
changed = puppet.UpdateName(info) || changed changed = puppet.UpdateName(info) || changed