Tweeting images with Golang
Introduction
X (the website formerly known as Twitter) has gone through certain “changes” in recent years. At some point they introduced the v2 API but the functionality isn’t complete.
The v1 API needs to be used for uploading media and getting the resulting media ID. We then need to use the v2 API to reference the uploaded media ID to finalize the post.
Media upload
For the v1 API media upload I utilize this library: github.com/drswork/go-twitter/
This is actually a fork of the now archived github.com/dghubble/go-twitter library who unfortunately did not merge this PR to add media upload functionality. Side note is that I also had an unrelated PR that was never merged :(.
Implementation
Error handling has been removed for brevity.
package main
import (
"context"
"encoding/base64"
"log"
"os"
// X API v1
"github.com/dghubble/oauth1"
"github.com/drswork/go-twitter/twitter"
// X API v2
"github.com/michimani/gotwi"
"github.com/michimani/gotwi/tweet/managetweet"
gotwiTypes "github.com/michimani/gotwi/tweet/managetweet/types"
)
const (
OAuthTokenEnvKeyName = "GOTWI_ACCESS_TOKEN"
OAuthTokenSecretEnvKeyName = "GOTWI_ACCESS_TOKEN_SECRET"
)
func main() {
// A single pixel PNG image
base64Image := "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAACklEQVR4AWNgAAAAAgABc3UBGAAAAABJRU5ErkJggg=="
// Decode to []byte
image, _ := base64.StdEncoding.DecodeString(base64Image)
postTweetWithMedia("Tweet text", image)
}
func postTweetWithMedia(xMsg string, image []byte) {
config := oauth1.NewConfig(os.Getenv("GOTWI_API_KEY"), os.Getenv("GOTWI_API_KEY_SECRET"))
token := oauth1.NewToken(os.Getenv(OAuthTokenEnvKeyName), os.Getenv(OAuthTokenSecretEnvKeyName))
httpClient := config.Client(oauth1.NoContext, token)
// v1 API - Upload media
clientV1 := twitter.NewClient(httpClient)
media, _, _ := clientV1.Media.Upload(image, "tweet_image")
// v2 API - Post Tweet with Media
in := &gotwi.NewClientInput{
AuthenticationMethod: gotwi.AuthenMethodOAuth1UserContext,
OAuthToken: os.Getenv(OAuthTokenEnvKeyName),
OAuthTokenSecret: os.Getenv(OAuthTokenSecretEnvKeyName),
}
clientV2, _ := gotwi.NewClient(in)
m := &gotwiTypes.CreateInputMedia{MediaIDs: []string{media.MediaIDString}, TaggedUserID: nil}
p := &gotwiTypes.CreateInput{
Text: gotwi.String(xMsg),
Media: m,
}
output, _ := managetweet.Create(context.Background(), clientV2, p)
log.Println("Tweet Output:", output.Data.ID)
}