From 03d847c9698fd48a0b5b35599d0d70a9a5a78d25 Mon Sep 17 00:00:00 2001 From: sirrow Date: Sat, 15 Mar 2025 19:35:48 +0900 Subject: [PATCH] add bluesky post --- go.mod | 52 +++++++++++++++++++++++++++++++++++++- main.go | 8 ++++-- output/bluesky.go | 64 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 output/bluesky.go diff --git a/go.mod b/go.mod index 499e458..a19aa32 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,57 @@ module tweetdistributor go 1.24.1 -require github.com/bwmarrin/discordgo v0.28.1 +require ( + github.com/bluesky-social/indigo v0.0.0-20250313000755-d9a74f690c90 + github.com/bwmarrin/discordgo v0.28.1 +) + +require ( + github.com/carlmjohnson/versioninfo v0.22.5 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/google/uuid v1.4.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-retryablehttp v0.7.5 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect + github.com/ipfs/bbloom v0.0.4 // indirect + github.com/ipfs/go-block-format v0.2.0 // indirect + github.com/ipfs/go-cid v0.4.1 // indirect + github.com/ipfs/go-datastore v0.6.0 // indirect + github.com/ipfs/go-ipfs-blockstore v1.3.1 // indirect + github.com/ipfs/go-ipfs-ds-help v1.1.1 // indirect + github.com/ipfs/go-ipfs-util v0.0.3 // indirect + github.com/ipfs/go-ipld-cbor v0.1.0 // indirect + github.com/ipfs/go-ipld-format v0.6.0 // indirect + github.com/ipfs/go-log v1.0.5 // indirect + github.com/ipfs/go-log/v2 v2.5.1 // indirect + github.com/ipfs/go-metrics-interface v0.0.1 // indirect + github.com/jbenet/goprocess v0.1.4 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/minio/sha256-simd v1.0.1 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/multiformats/go-base32 v0.1.0 // indirect + github.com/multiformats/go-base36 v0.2.0 // indirect + github.com/multiformats/go-multibase v0.2.0 // indirect + github.com/multiformats/go-multihash v0.2.3 // indirect + github.com/multiformats/go-varint v0.0.7 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect + github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect + go.opentelemetry.io/otel v1.21.0 // indirect + go.opentelemetry.io/otel/metric v1.21.0 // indirect + go.opentelemetry.io/otel/trace v1.21.0 // indirect + go.uber.org/atomic v1.11.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.26.0 // indirect + golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect + lukechampine.com/blake3 v1.2.1 // indirect +) require ( github.com/gorilla/websocket v1.5.3 // indirect diff --git a/main.go b/main.go index f28efea..4057932 100644 --- a/main.go +++ b/main.go @@ -14,10 +14,14 @@ func main() { tweetchannel := make(chan string, 1) d.BeginRead(tweetchannel) - output := output.TwitterOutput(os.Getenv("TW_ACCESS_TOKEN"), os.Getenv("TW_ACCESS_SECRET")) + var outputs []output.OutputInterface + outputs = append(outputs, output.TwitterOutput(os.Getenv("TW_ACCESS_TOKEN"), os.Getenv("TW_ACCESS_SECRET"))) + outputs = append(outputs, output.BlueskyOutput(os.Getenv("BSKY_IDENTIFIER"), os.Getenv("BSKY_PASSWORD"))) for tweet := range tweetchannel { fmt.Println(tweet) - output.Write(tweet) + for _, output := range outputs { + output.Write(tweet) + } } } diff --git a/output/bluesky.go b/output/bluesky.go new file mode 100644 index 0000000..631d695 --- /dev/null +++ b/output/bluesky.go @@ -0,0 +1,64 @@ +package output + +import ( + "context" + "log" + "time" + + "github.com/bluesky-social/indigo/api/atproto" + "github.com/bluesky-social/indigo/api/bsky" + lexutil "github.com/bluesky-social/indigo/lex/util" + "github.com/bluesky-social/indigo/util" + "github.com/bluesky-social/indigo/xrpc" +) + +type blueskyoutput struct { + identifier string + password string + client *xrpc.Client +} + +func BlueskyOutput(identifier string, password string) *blueskyoutput { + blueskyoutput := &blueskyoutput{ + identifier: identifier, + password: password, + } + + cli := &xrpc.Client{ + Host: "https://bsky.social", + } + + input := &atproto.ServerCreateSession_Input{ + Identifier: blueskyoutput.identifier, + Password: blueskyoutput.password, + } + + output, err := atproto.ServerCreateSession(context.TODO(), cli, input) + if err != nil { + log.Fatal(err) + } + cli.Auth = &xrpc.AuthInfo{ + AccessJwt: output.AccessJwt, + RefreshJwt: output.RefreshJwt, + Handle: output.Handle, + Did: output.Did, + } + + blueskyoutput.client = cli + + return blueskyoutput +} + +func (bo *blueskyoutput) Write(str string) error { + Recordinput := &atproto.RepoCreateRecord_Input{ + Collection: "app.bsky.feed.post", + Repo: bo.client.Auth.Did, // "matope.bsky.social" のDID + Record: &lexutil.LexiconTypeDecoder{&bsky.FeedPost{ + Text: str, + CreatedAt: time.Now().Format(util.ISO8601), + Langs: []string{"ja"}, + }}, + } + _, recerr := atproto.RepoCreateRecord(context.TODO(), bo.client, Recordinput) + return recerr +}