bridge basic emoji reactions from gateway to matrix

This commit is contained in:
Skip R
2025-12-11 19:17:57 -08:00
parent 25b73bd7cb
commit 506f42f93b
2 changed files with 97 additions and 4 deletions

View File

@@ -234,14 +234,18 @@ func makeChannelAvatar(ch *discordgo.Channel) *bridgev2.Avatar {
}
}
func (d *DiscordClient) makeEventSender(user *discordgo.User) bridgev2.EventSender {
func (d *DiscordClient) makeEventSenderWithID(userID string) bridgev2.EventSender {
return bridgev2.EventSender{
IsFromMe: user.ID == d.Session.State.User.ID,
SenderLogin: networkid.UserLoginID(user.ID),
Sender: networkid.UserID(user.ID),
IsFromMe: userID == d.Session.State.User.ID,
SenderLogin: networkid.UserLoginID(userID),
Sender: networkid.UserID(userID),
}
}
func (d *DiscordClient) makeEventSender(user *discordgo.User) bridgev2.EventSender {
return d.makeEventSenderWithID(user.ID)
}
func (d *DiscordClient) syncChannel(_ context.Context, ch *discordgo.Channel, selfIsInChannel bool) {
isGroup := len(ch.RecipientIDs) > 1

View File

@@ -18,6 +18,7 @@ package connector
import (
"context"
"fmt"
"runtime/debug"
"github.com/bwmarrin/discordgo"
@@ -86,6 +87,79 @@ func (d *DiscordClient) wrapDiscordMessage(evt *discordgo.MessageCreate) Discord
}
}
type DiscordReaction struct {
*DiscordEventMeta
Reaction *discordgo.MessageReaction
Client *DiscordClient
}
func (r *DiscordReaction) GetSender() bridgev2.EventSender {
return r.Client.makeEventSenderWithID(r.Reaction.UserID)
}
func (r *DiscordReaction) GetTargetMessage() networkid.MessageID {
return networkid.MessageID(r.Reaction.MessageID)
}
func (r *DiscordReaction) GetRemovedEmojiID() networkid.EmojiID {
return networkid.EmojiID(r.Reaction.Emoji.Name)
}
var (
_ bridgev2.RemoteReaction = (*DiscordReaction)(nil)
_ bridgev2.RemoteReactionRemove = (*DiscordReaction)(nil)
_ bridgev2.RemoteReactionWithExtraContent = (*DiscordReaction)(nil)
)
func (r *DiscordReaction) GetReactionEmoji() (string, networkid.EmojiID) {
// name is either a grapheme cluster consisting of a Unicode emoji, or the
// name of a custom emoji.
name := r.Reaction.Emoji.Name
return name, networkid.EmojiID(name)
}
func (r *DiscordReaction) GetReactionExtraContent() map[string]any {
extra := make(map[string]any)
reaction := r.Reaction
emoji := reaction.Emoji
if emoji.ID != "" {
// The emoji is a custom emoji.
extra["fi.mau.discord.reaction"] = map[string]any{
"id": emoji.ID,
"name": emoji.Name,
// FIXME Handle custom emoji.
// "mxc": reaction,
}
wrappedShortcode := fmt.Sprintf(":%s:", reaction.Emoji.Name)
extra["com.beeper.reaction.shortcode"] = wrappedShortcode
}
return extra
}
func (d *DiscordClient) wrapDiscordReaction(reaction *discordgo.MessageReaction, beingAdded bool) DiscordReaction {
evtType := bridgev2.RemoteEventReaction
if !beingAdded {
evtType = bridgev2.RemoteEventReactionRemove
}
return DiscordReaction{
DiscordEventMeta: &DiscordEventMeta{
Type: evtType,
PortalKey: networkid.PortalKey{
ID: networkid.PortalID(reaction.ChannelID),
Receiver: d.UserLogin.ID,
},
},
Reaction: reaction,
Client: d,
}
}
func (d *DiscordClient) handleDiscordEvent(rawEvt any) {
if d.UserLogin == nil {
// Our event handlers are able to assume that a UserLogin is available.
@@ -97,6 +171,13 @@ func (d *DiscordClient) handleDiscordEvent(rawEvt any) {
return
}
if d.Session == nil || d.Session.State == nil || d.Session.State.User == nil {
// Our event handlers are able to assume that we've fully connected to the
// gateway.
d.UserLogin.Log.Debug().Msg("Dropping Discord event received before READY or RESUMED")
return
}
defer func() {
err := recover()
if err != nil {
@@ -115,6 +196,14 @@ func (d *DiscordClient) handleDiscordEvent(rawEvt any) {
case *discordgo.MessageCreate:
wrappedEvt := d.wrapDiscordMessage(evt)
d.UserLogin.Bridge.QueueRemoteEvent(d.UserLogin, &wrappedEvt)
case *discordgo.MessageReactionAdd:
wrappedEvt := d.wrapDiscordReaction(evt.MessageReaction, true)
d.UserLogin.Bridge.QueueRemoteEvent(d.UserLogin, &wrappedEvt)
case *discordgo.MessageReactionRemove:
wrappedEvt := d.wrapDiscordReaction(evt.MessageReaction, false)
d.UserLogin.Bridge.QueueRemoteEvent(d.UserLogin, &wrappedEvt)
// TODO case *discordgo.MessageReactionRemoveAll:
// TODO case *discordgo.MessageReactionRemoveEmoji: (needs impl. in discordgo)
case *discordgo.PresenceUpdate:
return
case *discordgo.Event: