attach image
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
package output
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"log"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/bluesky-social/indigo/api/atproto"
|
||||
@@ -26,7 +27,7 @@ func BlueskyOutput(identifier string, password string) *blueskyoutput {
|
||||
return blueskyoutput
|
||||
}
|
||||
|
||||
func (bo *blueskyoutput) Write(str string) error {
|
||||
func (bo *blueskyoutput) Write(str string, images []Image) error {
|
||||
cli := &xrpc.Client{
|
||||
Host: "https://bsky.social",
|
||||
}
|
||||
@@ -38,7 +39,7 @@ func (bo *blueskyoutput) Write(str string) error {
|
||||
|
||||
output, err := atproto.ServerCreateSession(context.TODO(), cli, input)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return err
|
||||
}
|
||||
cli.Auth = &xrpc.AuthInfo{
|
||||
AccessJwt: output.AccessJwt,
|
||||
@@ -47,14 +48,35 @@ func (bo *blueskyoutput) Write(str string) error {
|
||||
Did: output.Did,
|
||||
}
|
||||
|
||||
post := &bsky.FeedPost{
|
||||
Text: str,
|
||||
CreatedAt: time.Now().Format(util.ISO8601),
|
||||
Langs: []string{"ja"},
|
||||
}
|
||||
|
||||
if len(images) > 0 {
|
||||
embedimages := make([]*bsky.EmbedImages_Image, 0, len(images))
|
||||
for _, img := range images {
|
||||
blob, err := atproto.RepoUploadBlob(context.TODO(), cli, bytes.NewReader(img.Data))
|
||||
if err != nil {
|
||||
return fmt.Errorf("uploading %s: %w", img.Filename, err)
|
||||
}
|
||||
embedimages = append(embedimages, &bsky.EmbedImages_Image{
|
||||
Alt: img.Filename,
|
||||
Image: blob.Blob,
|
||||
})
|
||||
}
|
||||
post.Embed = &bsky.FeedPost_Embed{
|
||||
EmbedImages: &bsky.EmbedImages{
|
||||
Images: embedimages,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Recordinput := &atproto.RepoCreateRecord_Input{
|
||||
Collection: "app.bsky.feed.post",
|
||||
Repo: cli.Auth.Did, // "matope.bsky.social" のDID
|
||||
Record: &lexutil.LexiconTypeDecoder{&bsky.FeedPost{
|
||||
Text: str,
|
||||
CreatedAt: time.Now().Format(util.ISO8601),
|
||||
Langs: []string{"ja"},
|
||||
}},
|
||||
Record: &lexutil.LexiconTypeDecoder{Val: post},
|
||||
}
|
||||
_, recerr := atproto.RepoCreateRecord(context.TODO(), cli, Recordinput)
|
||||
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
package output
|
||||
|
||||
type Image struct {
|
||||
Data []byte
|
||||
ContentType string
|
||||
Filename string
|
||||
}
|
||||
|
||||
type OutputInterface interface {
|
||||
Write(string) error
|
||||
Write(string, []Image) error
|
||||
GetName() string
|
||||
}
|
||||
|
||||
@@ -11,8 +11,11 @@ func StdOutput() *stdoutput {
|
||||
return &stdoutput{}
|
||||
}
|
||||
|
||||
func (so *stdoutput) Write(str string) error {
|
||||
func (so *stdoutput) Write(str string, images []Image) error {
|
||||
fmt.Println(str)
|
||||
for _, img := range images {
|
||||
fmt.Printf("[image: %s (%s, %d bytes)]\n", img.Filename, img.ContentType, len(img.Data))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package output
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/michimani/gotwi"
|
||||
"github.com/michimani/gotwi/media/upload"
|
||||
uploadtypes "github.com/michimani/gotwi/media/upload/types"
|
||||
"github.com/michimani/gotwi/tweet/managetweet"
|
||||
"github.com/michimani/gotwi/tweet/managetweet/types"
|
||||
)
|
||||
@@ -41,15 +44,61 @@ func (to *twitteroutput) newOAuth1Client(accessToken, accessSecret string) error
|
||||
return err
|
||||
}
|
||||
|
||||
func (to *twitteroutput) Write(str string) error {
|
||||
func (to *twitteroutput) Write(str string, images []Image) error {
|
||||
mediaIDs := make([]string, 0, len(images))
|
||||
for _, img := range images {
|
||||
mediaID, err := to.uploadImage(img)
|
||||
if err != nil {
|
||||
return fmt.Errorf("uploading %s: %w", img.Filename, err)
|
||||
}
|
||||
mediaIDs = append(mediaIDs, mediaID)
|
||||
}
|
||||
|
||||
p := &types.CreateInput{
|
||||
Text: gotwi.String(str),
|
||||
}
|
||||
if len(mediaIDs) > 0 {
|
||||
p.Media = &types.CreateInputMedia{
|
||||
MediaIDs: mediaIDs,
|
||||
}
|
||||
}
|
||||
|
||||
_, err := managetweet.Create(context.Background(), to.client, p)
|
||||
return err
|
||||
}
|
||||
|
||||
func (to *twitteroutput) uploadImage(img Image) (string, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
initialized, err := upload.Initialize(ctx, to.client, &uploadtypes.InitializeInput{
|
||||
MediaCategory: uploadtypes.MediaCategoryTweetImage,
|
||||
MediaType: uploadtypes.MediaType(img.ContentType),
|
||||
TotalBytes: len(img.Data),
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
mediaID := initialized.Data.MediaID
|
||||
|
||||
_, err = upload.Append(ctx, to.client, &uploadtypes.AppendInput{
|
||||
MediaID: mediaID,
|
||||
Media: bytes.NewReader(img.Data),
|
||||
SegmentIndex: 0,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
_, err = upload.Finalize(ctx, to.client, &uploadtypes.FinalizeInput{
|
||||
MediaID: mediaID,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return mediaID, nil
|
||||
}
|
||||
|
||||
func (to *twitteroutput) GetName() string {
|
||||
return "twitter"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user