feat: 🎸 Add support for receiving reactions#17
Conversation
There was a problem hiding this comment.
Pull request overview
This pull request adds support for receiving paid reactions from LINE Messenger. When users send paid emoji reactions (sticker-based reactions) in LINE, the bridge now detects these events, downloads the reaction image, uploads it to Matrix, and creates a Matrix reaction event using the image URL.
Changes:
- Added new structs and parser for LINE reaction events
- Implemented handler for operation type 140 (reaction events) that downloads reaction images and bridges them to Matrix
- Updated documentation to reflect that reaction support is now available (receive-only)
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 8 comments.
| File | Description |
|---|---|
| pkg/line/reaction.go | New file defining structs for parsing LINE reaction events from operation parameters |
| pkg/connector/client.go | Added reaction event handler (type 140) that downloads reaction images and creates Matrix reaction events; also changed handleOperation signature to accept context |
| README.md | Updated feature checklist to mark reaction support as implemented (receive-only) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| type ReactionParam2 struct { | ||
| ChatMid string `json:"chatMid"` | ||
| Curr *ReactionDetail `json:"curr,omitempty"` | ||
| } | ||
|
|
There was a problem hiding this comment.
The struct name "ReactionParam2" is unclear and not descriptive. The "2" suffix appears to refer to the Operation.Param2 field from which this is parsed, but this makes the name opaque to readers. Consider renaming to something more descriptive like "ReactionEvent" or "ReactionPayload" that describes what the struct represents rather than where it comes from.
| type ReactionParam2 struct { | |
| ChatMid string `json:"chatMid"` | |
| Curr *ReactionDetail `json:"curr,omitempty"` | |
| } | |
| // ReactionPayload represents the reaction-related payload parsed from the operation. | |
| type ReactionPayload struct { | |
| ChatMid string `json:"chatMid"` | |
| Curr *ReactionDetail `json:"curr,omitempty"` | |
| } | |
| // ReactionParam2 is retained as an alias for backward compatibility. | |
| // Prefer using ReactionPayload in new code. | |
| type ReactionParam2 = ReactionPayload |
|
|
||
| if op.Type == 140 { | ||
| go func() { | ||
| bgCtx := context.Background() |
There was a problem hiding this comment.
The goroutine creates a new background context instead of using the passed context from the handler. This breaks context cancellation and deadline propagation. If the client is shutting down, this goroutine will continue running and potentially attempt operations after cleanup. Use the passed 'ctx' parameter instead of 'context.Background()' to properly handle cancellation.
| type ReactionParam2 struct { | ||
| ChatMid string `json:"chatMid"` | ||
| Curr *ReactionDetail `json:"curr,omitempty"` |
There was a problem hiding this comment.
The struct fields lack documentation. It's unclear what "ChatMid" represents (chat message ID? chat member ID?) and what "Curr" means (current reaction?). Consider adding field comments to explain what each field represents, especially since this appears to be parsing data from an external LINE API.
| type ReactionParam2 struct { | |
| ChatMid string `json:"chatMid"` | |
| Curr *ReactionDetail `json:"curr,omitempty"` | |
| // ReactionParam2 represents the reaction-related parameters received from the LINE API. | |
| type ReactionParam2 struct { | |
| // ChatMid is the identifier of the chat (conversation or message context) this reaction belongs to. | |
| ChatMid string `json:"chatMid"` | |
| // Curr contains the details of the current reaction associated with the chat/message. | |
| Curr *ReactionDetail `json:"curr,omitempty"` |
| Version int `json:"version"` | ||
| } | ||
|
|
||
| func ParseReactionParam2(data string) (*ReactionParam2, error) { |
There was a problem hiding this comment.
The function name "ParseReactionParam2" is unclear and not descriptive. The "Param2" suffix appears to refer to where this is used rather than what it does. Consider renaming to something more descriptive like "ParseReactionEvent" or "UnmarshalReaction" that describes the function's purpose.
| func ParseReactionParam2(data string) (*ReactionParam2, error) { | |
| func ParseReactionEvent(data string) (*ReactionParam2, error) { |
Removed extra spawned in context Renamed param2 to payload in reaction
No description provided.