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

@@ -293,11 +293,16 @@ 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,
@@ -76,6 +76,7 @@ CREATE TABLE puppet (
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,10 +308,25 @@ 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 {
if message.WebhookID != "" && message.ApplicationID == "" && !puppet.IsWebhook {
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 puppet.IsWebhook = true
changed = 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
changed = puppet.UpdateAvatar(info) || changed changed = puppet.UpdateAvatar(info) || changed