Skip to content

[refactor]use line bot sdk#500

Open
xiaket wants to merge 4 commits intosipeed:mainfrom
xiaket:xiaket-line-sdk
Open

[refactor]use line bot sdk#500
xiaket wants to merge 4 commits intosipeed:mainfrom
xiaket:xiaket-line-sdk

Conversation

@xiaket
Copy link
Copy Markdown
Collaborator

@xiaket xiaket commented Feb 19, 2026

📝 Description

Use official line bot sdk to reduce maintenance burden

🗣️ Type of Change

  • 🐞 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 📖 Documentation update
  • ⚡ Code refactoring (no functional changes, no api changes)

🤖 AI Code Generation

  • 🤖 Fully AI-generated (100% AI, 0% Human)
  • 🛠️ Mostly AI-generated (AI draft, Human verified/modified)
  • 👨‍💻 Mostly Human-written (Human lead, AI assisted or none)

☑️ Checklist

  • My code/docs follow the style of this project.
  • I have performed a self-review of my own changes.
  • I have updated the documentation accordingly.

Copy link
Copy Markdown

@nikolasdehor nikolasdehor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great refactor — replacing 270 lines of hand-rolled HTTP/HMAC/JSON code with the official LINE SDK. This significantly reduces maintenance burden and eliminates potential bugs in signature verification, request construction, and response parsing.

A few observations:

  1. reflect usage for message ID extraction — Line 229 uses reflect.Indirect(reflect.ValueOf(msgEvent.Message)).FieldByName("Id") to get the message ID. This is fragile — if the SDK renames the field or changes the struct layout, this silently fails (f.IsValid() returns false and messageID stays empty, meaning content downloads would fail with an empty URL). Consider checking if the SDK's message types have a common interface or method for getting the ID. If not, a type switch (similar to what's already done for the message content) would be safer:
switch msg := msgEvent.Message.(type) {
case webhook.TextMessageContent:
    messageID = msg.Id
case webhook.ImageMessageContent:
    messageID = msg.Id
// etc.
}
  1. downloadContent still uses raw HTTP — The media download still constructs a raw URL with lineContentEndpoint. The LINE SDK may have a content download API that handles auth headers automatically. Worth checking messaging_api.GetContent() or similar.

  2. sendLoading no longer uses context — The old code passed c.ctx to callAPI, but the new SDK call to ShowLoadingAnimation does not accept a context. This means the loading indicator request cannot be cancelled if the channel is stopped. This is a minor behavioral change, and may be an SDK limitation.

  3. Error handling in webhookHandler — The new webhook.ParseRequest handles both body reading and signature verification in one call. Clean improvement.

  4. Group message handling — The refactored isBotMentioned now uses type switches on webhook.AllMentionee / webhook.UserMentionee, which is more idiomatic than string-based type checks.

LGTM — the reflect usage is the main concern but not a blocker.

@alexhoshina
Copy link
Copy Markdown
Collaborator

Please develop based on the refactor branch. The refactor branch is about to be merged, and PRs developed based on main before the merge will not be reviewed.

The refactor branch is scheduled to be merged during the daytime of February 28, 2026, Beijing Time (GMT+8), with the exact time yet to be determined. You may wait until after the merge to request a PR review Or complete the review before finishing the merge; I will review your PR as quickly as possible We have provided comprehensive migration documentation for the new channel system.

@alexhoshina
Copy link
Copy Markdown
Collaborator

The refactored branch has been merged, you can now develop directly based on main

@alexhoshina alexhoshina removed this from the Refactor Channel milestone Feb 27, 2026
xiaket added 3 commits March 1, 2026 17:18
Signed-off-by: Kai Xia <kaix+github@fastmail.com>
Signed-off-by: Kai Xia <kaix+github@fastmail.com>
Signed-off-by: Kai Xia <kaix+github@fastmail.com>
@xiaket xiaket force-pushed the xiaket-line-sdk branch from 223c15b to f5c97a1 Compare March 1, 2026 06:19
Copy link
Copy Markdown
Collaborator

@yinwm yinwm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

This is a good refactoring direction - using the official LINE Bot SDK reduces maintenance burden significantly (~130 lines reduced). However, I found a few issues that should be addressed before merging.

Critical Issues 🔴

1. Context is lost in API calls

The SDK supports context via WithContext() method, but the PR doesn't use it. This means timeout control from the original callAPI(ctx, ...) is lost.

// Current (loses context)
_, err := c.client.ReplyMessage(...)

// Should be:
_, err := c.client.WithContext(ctx).ReplyMessage(...)

2. Variable shadowing bug in isMentioned

In processEvent, line ~244, := creates a new local variable instead of assigning to the outer isMentioned:

// Line ~244 - this declares a NEW local variable!
if isGroup {
    isMentioned := c.isBotMentioned(msg)  // Bug: shadows outer variable

Should use = instead of := since isMentioned is already declared above.

Code Quality Improvements 🟡

3. Using reflection to get Id is unnecessary

The SDK doesn't have GetId() on the interface, but each concrete type (TextMessageContent, ImageMessageContent, etc.) has Id as an embedded field. Instead of reflection, get it directly in the switch:

switch msg := msgEvent.Message.(type) {
case webhook.TextMessageContent:
    messageID = msg.Id  // Direct access, cleaner than reflection
    content = msg.Text
    isMentioned = c.isBotMentioned(msg)
case webhook.ImageMessageContent:
    messageID = msg.Id
    // ...
}

4. downloadContent still uses manual HTTP

The SDK provides MessagingApiBlobAPI.GetMessageContent() for downloading message content. Consider using it for consistency:

blobClient, _ := messaging_api.NewMessagingApiBlobAPI(cfg.ChannelAccessToken)
resp, err := blobClient.GetMessageContent(messageID)

5. resolveSource default behavior changed

Original code falls back to source.UserID for unknown types, new code returns "unknown". This might break edge cases. Consider keeping the original behavior or adding a warning log.

6. Error classification lost

The original code used channels.ClassifyNetError() and channels.ClassifySendError() for error handling. The new code returns SDK errors directly. Consider wrapping errors to maintain consistent error classification behavior.


Overall, the direction is correct, but please address the two critical issues (context and variable shadowing) before merging.

@@ -341,7 +244,6 @@ func (c *LINEChannel) processEvent(event lineEvent) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 Bug: Variable shadowing

:= creates a new local variable isMentioned that shadows the outer one declared above. The outer isMentioned will always be false.

Fix: Use = instead of :=:

isMentioned = c.isBotMentioned(msg)  // No colon

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this comment is questionable, here we are removing this line, not adding it.

Signed-off-by: Kai Xia <kaix+github@fastmail.com>
@xiaket xiaket requested a review from yinwm March 2, 2026 11:26
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Mar 5, 2026

CLA assistant check
All committers have signed the CLA.

@yinwm
Copy link
Copy Markdown
Collaborator

yinwm commented Mar 18, 2026

PR Review Feedback

Issues to Address

1. Branch is 533 commits behind main

This PR was created on 2026-03-01, but #1413 (body size limit) was merged on 2026-03-12. Please rebase onto the latest main:

git fetch origin
git rebase origin/main

2. Expected Merge Conflicts

#1413 added io.LimitReader body size check, but this PR replaces the entire webhook handling with SDK's webhook.ParseRequest. After rebase, you'll need to decide:

  • Keep io.LimitReader check + SDK parsing, OR
  • Verify if the SDK has built-in body size limiting

3. Test Compatibility

Tests in line_test.go (e.g., TestWebhookRejectsOversizedBody) depend on body size checking logic. Please verify all tests pass after refactoring.

Recommendations

  1. Rebase onto latest main
  2. Resolve merge conflicts (preserve body size security check)
  3. Run go test ./pkg/channels/line/... to ensure tests pass
  4. Request merge after fixes are complete

Thanks for contributing! Using the official SDK is the right direction 👍

@ex-takashima
Copy link
Copy Markdown
Contributor

Hi @xiaket, just checking in — are you still planning to work on this PR? I noticed it's been a while since the last update, and there are merge conflicts with main now (particularly with #1413 body size limit).

No rush at all, but if you're busy I'd be happy to pick it up from here. I have a rebased version with the review feedback addressed (context via WithContext(), variable shadowing fix, reflect removal, body size limit integration with http.MaxBytesReader).

Let me know either way!

Copy link
Copy Markdown
Collaborator

@yinwm yinwm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code quality looks good after addressing previous review feedback (context via WithContext(), variable shadowing fix, reflect removal). However, this PR cannot be merged in its current state:

  1. Merge conflicts — This branch is behind main by 533+ commits. Specifically, #1413 added io.LimitReader body size checking which conflicts with the SDK-based webhook.ParseRequest replacement.

  2. Rebase required — Please rebase onto latest main:

    git fetch origin
    git rebase origin/main

    After rebase, ensure the body size security check is preserved (either via http.MaxBytesReader before SDK parsing, or verify SDK handles this internally).

  3. Tests must pass — Run go test ./pkg/channels/line/... to confirm all tests pass after rebase.

If you're no longer able to work on this, @ex-takashima has offered to pick it up. Please let us know either way.

ex-takashima added a commit to ex-takashima/picoclaw that referenced this pull request Apr 7, 2026
Replace hand-rolled HTTP/HMAC/JSON code (~270 lines) with the official
line-bot-sdk-go v8, reducing maintenance burden and eliminating potential
bugs in signature verification, request construction, and response parsing.

This continues the work started in sipeed#500 by @xiaket, addressing all review
feedback and rebasing onto current main.

Changes:
- Replace bytes/crypto/json/io imports with line-bot-sdk-go/v8
- Use webhook.ParseRequest for body reading + signature verification
- Use messaging_api.MessagingApiAPI for ReplyMessage/PushMessage/ShowLoadingAnimation/GetBotInfo
- Type-switch on webhook.MessageEvent message types (TextMessageContent,
  ImageMessageContent, etc.) instead of JSON unmarshalling
- Type-switch on webhook.SourceInterface (UserSource/GroupSource/RoomSource)
- Type-switch on webhook.Mentionee (UserMentionee/AllMentionee)

Review feedback addressed (from sipeed#500):
- Use WithContext(ctx) on all SDK calls to preserve cancellation/timeout
- Fix variable shadowing of isMentioned (declared at function scope)
- Remove reflect-based message ID extraction (use type switch + msg.Id)
- Use mentionee.IsSelf for cleaner bot mention detection
- Preserve body size security check via http.MaxBytesReader before
  webhook.ParseRequest (compatible with sipeed#1413)

All existing tests pass without modification.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants