Skip to content

feat(twitter posts): long live duckBot#13

Merged
wcatz merged 2 commits intomasterfrom
duckx
Jan 20, 2026
Merged

feat(twitter posts): long live duckBot#13
wcatz merged 2 commits intomasterfrom
duckx

Conversation

@wcatz
Copy link
Copy Markdown
Owner

@wcatz wcatz commented Jan 14, 2026

Summary by CodeRabbit

  • New Features
    • Optional Twitter posting: enable by providing Twitter API credentials to allow cross-posting.
    • Block event notifications now include generated images for richer media posts.
    • Messages can be delivered across multiple platforms (Telegram and Twitter) when enabled.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jan 14, 2026

📝 Walkthrough

Walkthrough

Added Twitter integration to the indexer: new direct dependency on github.com/michimani/gotwi and updates to main.go to initialize a Twitter client (conditional on credentials), download/generate duck images, send Telegram photo messages, and post tweets when enabled.

Changes

Cohort / File(s) Summary
Dependency Management
go.mod
Added direct dependency github.com/michimani/gotwi v0.18.1 for Twitter API integration.
Twitter Integration
main.go
Extended Indexer with twitterClient and twitterEnabled; initialize Twitter client in Start() when credentials present; generate duck image URL per event, download image, send Telegram photo, and post tweets via new sendTweet helper; added downloadImage helper and imported gotwi tweet packages.

Sequence Diagram

sequenceDiagram
    participant Indexer
    participant ImageService
    participant TelegramAPI as Telegram API
    participant TwitterAPI as Twitter API

    Indexer->>Indexer: Start (check TWITTER_* envs)
    alt credentials present
        Indexer->>TwitterAPI: Initialize client
        TwitterAPI-->>Indexer: Client ready
    end

    loop on block event
        Indexer->>ImageService: getDuckImage()
        ImageService-->>Indexer: duckImageURL
        Indexer->>ImageService: downloadImage(duckImageURL)
        ImageService-->>Indexer: image bytes
        Indexer->>TelegramAPI: send photo with image
        alt twitterEnabled
            Indexer->>TwitterAPI: sendTweet(text[, image])
            TwitterAPI-->>Indexer: post response
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I hopped a patch and found a key,

Ducks in pixels, tweets set free,
Telegram flutters, Twitter sings,
I stitched the web with tiny wings,
A rabbit's hop—now social glee! 🎉

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: adding Twitter posting functionality to duckBot, which aligns with the primary modifications in main.go adding Twitter integration.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
main.go (1)

477-487: log.Fatal will crash the application on transient API failures.

Using log.Fatal in getDuckImage will terminate the entire indexer if the random-d.uk API is temporarily unavailable. Additionally, the type assertion on line 485 can panic if the response doesn't contain a "url" string field.

Suggested fix: Return error and use fallback
-func getDuckImage() string {
+func getDuckImage() (string, error) {
+       const fallbackImage = "https://random-d.uk/api/1.gif" // or your preferred fallback
        resp, err := http.Get("https://random-d.uk/api/v2/random")
        if err != nil {
-               log.Fatal(err)
+               return fallbackImage, fmt.Errorf("failed to fetch duck image: %w", err)
        }
        defer resp.Body.Close()
+       
+       if resp.StatusCode != http.StatusOK {
+               return fallbackImage, fmt.Errorf("duck API returned status %d", resp.StatusCode)
+       }
+       
        var result map[string]interface{}
-       json.NewDecoder(resp.Body).Decode(&result)
-       imageURL := result["url"].(string)
-       return imageURL
+       if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
+               return fallbackImage, fmt.Errorf("failed to decode duck response: %w", err)
+       }
+       
+       imageURL, ok := result["url"].(string)
+       if !ok || imageURL == "" {
+               return fallbackImage, fmt.Errorf("invalid url in duck response")
+       }
+       return imageURL, nil
}

Then update the caller in handleEvent to handle the error appropriately.

🤖 Fix all issues with AI agents
In `@main.go`:
- Around line 407-423: The call to i.sendTweet(tweetMsg, duckImageURL) passes an
image URL that sendTweet ignores; either remove the unused duckImageURL
parameter from the call and update the sendTweet method signature (and all
callers) to accept only the message, or implement media upload support inside
sendTweet (use Twitter media upload API, attach returned media_id when posting)
so the duckImageURL is actually uploaded and attached; locate the sendTweet
method and update its signature and implementation (and any other callers)
accordingly to keep signatures consistent.
🧹 Nitpick comments (2)
main.go (2)

489-507: Unused function: downloadImage is never called.

This function appears to have been added for Twitter media upload support, but it's not used anywhere in the codebase. Consider either:

  1. Removing it if image upload isn't planned
  2. Integrating it into sendTweet if image attachment is intended
#!/bin/bash
# Verify downloadImage is not called anywhere
rg -n "downloadImage" --type go

509-528: Unused imageURL parameter should be removed or implemented.

The imageURL parameter in sendTweet is declared but never used. This creates confusion about the function's intended behavior.

If text-only tweets are the final design
-func (i *Indexer) sendTweet(text string, imageURL string) error {
+func (i *Indexer) sendTweet(text string) error {
        if !i.twitterEnabled || i.twitterClient == nil {
                return nil
        }

        // Create tweet request
        input := &types.CreateInput{
                Text: gotwi.String(text),
        }

        // Post the tweet
        _, err := managetweet.Create(context.Background(), i.twitterClient, input)
        if err != nil {
                return fmt.Errorf("failed to post tweet: %w", err)
        }

        log.Println("Tweet posted successfully")
        return nil
}
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c42ecfa and a3cce21.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (2)
  • go.mod
  • main.go
🔇 Additional comments (4)
main.go (2)

76-78: LGTM!

The new Twitter-related fields are appropriately added to the Indexer struct. Using a separate twitterEnabled flag alongside the client pointer provides a clean guard for conditional Twitter functionality.


148-172: Good graceful degradation pattern.

The Twitter client initialization properly handles missing credentials and initialization failures without crashing the application. The conditional check for all four environment variables before attempting initialization is appropriate.

go.mod (2)

25-25: Verify if the adder v0.35.0 update intentionally requires gouroboros v0.146.0.

The gouroboros version is an indirect dependency determined by github.com/blinklabs-io/adder v0.35.0. Check the adder changelog or go.mod to confirm whether the v0.146.0 requirement is intentional and compatible with your use case.


13-13: v0.18.1 is a valid release and the API usage in main.go aligns with this version. No action needed.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread main.go
Comment on lines +407 to +423
// Send tweet if Twitter is enabled (shorter format for 280 char limit)
if i.twitterEnabled {
tweetMsg := fmt.Sprintf(
"🦆 New Block!\n\n"+
"Pool: %s\n"+
"Tx: %d | Size: %.2fKB\n"+
"Epoch: %d | Lifetime: %d\n\n"+
"pooltool.io/realtime/%d",
i.poolName, blockEvent.Payload.TransactionCount, blockSizeKB,
i.epochBlocks, i.totalBlocks,
blockEvent.Context.BlockNumber)

err = i.sendTweet(tweetMsg, duckImageURL)
if err != nil {
log.Printf("failed to send tweet: %s", err)
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

The imageURL parameter is passed but not used.

The duckImageURL is passed to sendTweet() but the function ignores it and only posts text. If image attachment is intended, the Twitter media upload API needs to be integrated. If text-only tweets are the goal, consider removing the unused parameter to avoid confusion.

Option 1: Remove unused parameter if text-only is intended
-                       err = i.sendTweet(tweetMsg, duckImageURL)
+                       err = i.sendTweet(tweetMsg)

And update the function signature accordingly.

🤖 Prompt for AI Agents
In `@main.go` around lines 407 - 423, The call to i.sendTweet(tweetMsg,
duckImageURL) passes an image URL that sendTweet ignores; either remove the
unused duckImageURL parameter from the call and update the sendTweet method
signature (and all callers) to accept only the message, or implement media
upload support inside sendTweet (use Twitter media upload API, attach returned
media_id when posting) so the duckImageURL is actually uploaded and attached;
locate the sendTweet method and update its signature and implementation (and any
other callers) accordingly to keep signatures consistent.

@wcatz wcatz merged commit 8ea19b8 into master Jan 20, 2026
2 checks passed
@wcatz wcatz deleted the duckx branch February 6, 2026 10:32
@coderabbitai coderabbitai bot mentioned this pull request Feb 8, 2026
5 tasks
wcatz added a commit that referenced this pull request Feb 18, 2026
feat(twitter posts): long live duckBot
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant