Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/cardano-community/koios-go-client/v3 v3.1.3
github.com/cenkalti/backoff/v4 v4.3.0
github.com/gorilla/websocket v1.5.3
github.com/michimani/gotwi v0.18.1
github.com/spf13/viper v1.21.0
gopkg.in/tucnak/telebot.v2 v2.5.0
)
Expand All @@ -21,7 +22,7 @@ require (
github.com/SundaeSwap-finance/ogmigo/v6 v6.2.0 // indirect
github.com/aws/aws-sdk-go v1.55.8 // indirect
github.com/bits-and-blooms/bitset v1.24.4 // indirect
github.com/blinklabs-io/gouroboros v0.148.0 // indirect
github.com/blinklabs-io/gouroboros v0.146.0 // indirect
github.com/blinklabs-io/plutigo v0.0.18 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.6 // indirect
github.com/btcsuite/btcd/btcutil v1.1.6 // indirect
Expand Down
28 changes: 4 additions & 24 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,28 +1,20 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 h1:1zYrtlhrZ6/b6SAjLSfKzWtdgqK0U+HtH/VcBWh1BaU=
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260112020553-64c30dda3cfd h1:ifR6oQZU+7Lqemu0dqf6X4pVWuzmMeKX6WtwZ87rH+M=
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260112020553-64c30dda3cfd/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
github.com/SundaeSwap-finance/kugo v1.3.0 h1:8+c+LJWJ0iByzRJXMMTGtWtsbWQmMIJxBb9mkId9XDU=
github.com/SundaeSwap-finance/kugo v1.3.0/go.mod h1:NZT9DzTSH8N8IM0Mzn/ISn8xASefO0Xqipw8TGGpMvg=
github.com/SundaeSwap-finance/ogmigo/v6 v6.2.0 h1:DshTW5GtTzUyktZnHvMLkBzxEVkZzAfG1062cZ455no=
github.com/SundaeSwap-finance/ogmigo/v6 v6.2.0/go.mod h1:ZBCnkjFoFoPO7XG26ikmZFhsy1mD46+0fQl6ALkSMZk=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/aws/aws-sdk-go v1.55.6 h1:cSg4pvZ3m8dgYcgqB97MrcdjUmZ1BeMYKUxMMB89IPk=
github.com/aws/aws-sdk-go v1.55.6/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
github.com/aws/aws-sdk-go v1.55.8 h1:JRmEUbU52aJQZ2AjX4q4Wu7t4uZjOu71uyNmaWlUkJQ=
github.com/aws/aws-sdk-go v1.55.8/go.mod h1:ZkViS9AqA6otK+JBBNH2++sx1sgxrPKcSzPPvQkUtXk=
github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU=
github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/bits-and-blooms/bitset v1.24.4 h1:95H15Og1clikBrKr/DuzMXkQzECs1M6hhoGXLwLQOZE=
github.com/bits-and-blooms/bitset v1.24.4/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/blinklabs-io/adder v0.35.0 h1:QKmXb7HsejqOKxauU2Siw0ekTMqNsFr2cxdLcOQvXWs=
github.com/blinklabs-io/adder v0.35.0/go.mod h1:90EQBbKoIhcCdyJ5OlE9tDT1cn69fW/ePYVatS62BKo=
github.com/blinklabs-io/gouroboros v0.147.0 h1:4A88jYoc1OvmC/EqPhvpk3cfmH8jCASOeQy9P6Ps/vg=
github.com/blinklabs-io/gouroboros v0.147.0/go.mod h1:qRfnn0az84aaPjsvtQK52yoApww0bxQsMu9LJgQ1ftg=
github.com/blinklabs-io/gouroboros v0.148.0 h1:B8+3oLKk+vSUim3arbl1euf39oCvfwZGgSAwVEydgck=
github.com/blinklabs-io/gouroboros v0.148.0/go.mod h1:UqNKi2y70+0s+0QxSwox+pdB++lq2RqUSWtErngs8NQ=
github.com/blinklabs-io/gouroboros v0.146.0 h1:bZD6GAbHpTRhaUEDFuD+s21eZwdAwWBJ5w5ebBRJKLk=
github.com/blinklabs-io/gouroboros v0.146.0/go.mod h1:qRfnn0az84aaPjsvtQK52yoApww0bxQsMu9LJgQ1ftg=
github.com/blinklabs-io/ouroboros-mock v0.4.0 h1:ppOcTMnC/2f5rYYSlvNqcGfAQOIpMCSDUrNh9K6a4mY=
github.com/blinklabs-io/ouroboros-mock v0.4.0/go.mod h1:e+Kck8bmdOuaN7IfkbVvbqAVlskXNXB95oHI3YlFG5g=
github.com/blinklabs-io/plutigo v0.0.18 h1:axw0QVrdiqEjt+ssKs5zY2ycogZ+j5r0IETHkAda+8Q=
Expand Down Expand Up @@ -72,8 +64,6 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn
github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8=
github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
Expand All @@ -87,8 +77,6 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
Expand Down Expand Up @@ -130,6 +118,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4=
github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c=
github.com/michimani/gotwi v0.18.1 h1:Tp7uia9qby8I0AXk9oDZRqaCPg31qyQ7NkeyiGDCDaE=
github.com/michimani/gotwi v0.18.1/go.mod h1:yz1cyV/30Uy/KGQyN8BVfXFPt/63Imzonykny8/SMi0=
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1aMrNhpgxHmow66XQtm0aQLY0AE=
Expand All @@ -155,8 +145,6 @@ github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0t
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4=
github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI=
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
Expand Down Expand Up @@ -194,8 +182,6 @@ golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand All @@ -215,19 +201,13 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
Expand Down
97 changes: 96 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/json"
"errors"
"fmt"
"io"
"log"
"net/http"
"os"
Expand All @@ -22,6 +23,9 @@ import (
koios "github.com/cardano-community/koios-go-client/v3"
"github.com/cenkalti/backoff/v4"
"github.com/gorilla/websocket"
"github.com/michimani/gotwi"
"github.com/michimani/gotwi/tweet/managetweet"
"github.com/michimani/gotwi/tweet/managetweet/types"
"github.com/spf13/viper"
telebot "gopkg.in/tucnak/telebot.v2"
)
Expand Down Expand Up @@ -69,6 +73,9 @@ type Indexer struct {
epoch int
networkMagic int
wg sync.WaitGroup
// Twitter fields
twitterClient *gotwi.Client
twitterEnabled bool
}

type BlockEvent struct {
Expand Down Expand Up @@ -138,6 +145,32 @@ func (i *Indexer) Start() error {
log.Fatalf("failed to start bot: %s", err)
}

// Initialize Twitter client if credentials are provided
twitterAPIKey := os.Getenv("TWITTER_API_KEY")
twitterAPISecret := os.Getenv("TWITTER_API_KEY_SECRET")
twitterAccessToken := os.Getenv("TWITTER_ACCESS_TOKEN")
twitterAccessTokenSecret := os.Getenv("TWITTER_ACCESS_TOKEN_SECRET")

if twitterAPIKey != "" && twitterAPISecret != "" &&
twitterAccessToken != "" && twitterAccessTokenSecret != "" {
in := &gotwi.NewClientInput{
AuthenticationMethod: gotwi.AuthenMethodOAuth1UserContext,
OAuthToken: twitterAccessToken,
OAuthTokenSecret: twitterAccessTokenSecret,
APIKey: twitterAPIKey,
APIKeySecret: twitterAPISecret,
}
i.twitterClient, err = gotwi.NewClient(in)
if err != nil {
log.Printf("failed to initialize Twitter client: %s", err)
} else {
i.twitterEnabled = true
log.Println("Twitter client initialized successfully")
}
} else {
log.Println("Twitter credentials not provided, Twitter notifications disabled")
}

/// Initialize the kois client based on networkMagic number
if i.networkMagic == 1 {
i.koios, e = koios.New(
Expand Down Expand Up @@ -357,16 +390,37 @@ func (i *Indexer) handleEvent(event event.Event) error {
timeDiffString, i.epochBlocks, i.totalBlocks,
blockEvent.Context.BlockNumber, blockEvent.Payload.BlockHash)

// Get duck image URL for both Telegram and Twitter
duckImageURL := getDuckImage()

// Send the message to the appropriate channel
channelID, err := strconv.ParseInt(i.telegramChannel, 10, 64)
if err != nil {
log.Fatalf("failed to parse telegram channel ID: %s", err)
}
photo := &telebot.Photo{File: telebot.FromURL(getDuckImage()), Caption: msg}
photo := &telebot.Photo{File: telebot.FromURL(duckImageURL), Caption: msg}
_, err = i.bot.Send(&telebot.Chat{ID: channelID}, photo)
if err != nil {
log.Printf("failed to send Telegram message: %s", err)
}

// 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)
}
}
Comment on lines +407 to +423
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.

}

// Print the received event information
Expand Down Expand Up @@ -432,6 +486,47 @@ func getDuckImage() string {
return imageURL
}

// Download image from URL to bytes
func downloadImage(imageURL string) ([]byte, error) {
resp, err := http.Get(imageURL)
if err != nil {
return nil, fmt.Errorf("failed to download image: %w", err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to download image: status %d", resp.StatusCode)
}

imageData, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read image data: %w", err)
}

return imageData, nil
}

// Send tweet with optional image
func (i *Indexer) sendTweet(text string, imageURL 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
}

// Convert to bech32 poolID
func convertToBech32(hash string) (string, error) {
bytes, err := hex.DecodeString(hash)
Expand Down
Loading