feat(channels/buzz): implement ReactionCapable for 👀 emoji reactions
Add ReactToMessage method that publishes a NIP-25 kind:7 reaction event with content 👀, scoped to the same channel via the h tag and pointing at the inbound message via the e tag. The undo function is a no-op since NIP-25 does not define a standard way to remove a reaction. This enables the BaseChannel auto-reaction pipeline: when a message arrives on a Buzz channel, the bot reacts with 👀 before processing, giving the Emperor visual confirmation that the message was received.
This commit is contained in:
parent
a3dd7fca24
commit
5acf91a136
1 changed files with 41 additions and 0 deletions
|
|
@ -280,6 +280,47 @@ func (c *BuzzChannel) Send(ctx context.Context, msg bus.OutboundMessage) ([]stri
|
||||||
return []string{evt.ID}, nil
|
return []string{evt.ID}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// kindReaction is the NIP-25 reaction event kind.
|
||||||
|
const kindReaction = 7
|
||||||
|
|
||||||
|
// ReactToMessage implements channels.ReactionCapable.
|
||||||
|
// It publishes a NIP-25 kind:7 reaction event with content 👀 scoped to the
|
||||||
|
// same channel as the reacted message. The undo function is a no-op because
|
||||||
|
// NIP-25 does not define a standard way to remove a reaction.
|
||||||
|
func (c *BuzzChannel) ReactToMessage(ctx context.Context, chatID, messageID string) (func(), error) {
|
||||||
|
if !c.IsRunning() {
|
||||||
|
return func() {}, channels.ErrNotRunning
|
||||||
|
}
|
||||||
|
if messageID == "" {
|
||||||
|
return func() {}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
evt := nostr.Event{
|
||||||
|
PubKey: c.publicKey,
|
||||||
|
CreatedAt: nostr.Now(),
|
||||||
|
Kind: kindReaction,
|
||||||
|
Tags: nostr.Tags{
|
||||||
|
nostr.Tag{"e", messageID},
|
||||||
|
nostr.Tag{"h", chatID},
|
||||||
|
},
|
||||||
|
Content: "👀",
|
||||||
|
}
|
||||||
|
if err := evt.Sign(c.secretKey); err != nil {
|
||||||
|
return func() {}, fmt.Errorf("buzz reaction sign failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.relay.Publish(ctx, evt); err != nil {
|
||||||
|
return func() {}, fmt.Errorf("buzz reaction publish failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.DebugCF("buzz", "Reaction sent", map[string]any{
|
||||||
|
"channel": chatID,
|
||||||
|
"event_id": evt.ID,
|
||||||
|
"target_id": messageID,
|
||||||
|
})
|
||||||
|
return func() {}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// errJoin wraps err so that errors.Is(result, sentinel) holds for the sentinel
|
// errJoin wraps err so that errors.Is(result, sentinel) holds for the sentinel
|
||||||
// while preserving the underlying cause in the message.
|
// while preserving the underlying cause in the message.
|
||||||
func errJoin(err, sentinel error) error {
|
func errJoin(err, sentinel error) error {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue