Decouple layers 🚀
This commit is contained in:
parent
0ccb1226fc
commit
a1b10758cd
|
@ -0,0 +1,52 @@
|
|||
package cfg
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
MASTODON_ACCESS_TOKEN = "MASTODON_ACCESS_TOKEN"
|
||||
MASTODON_SERVER_ADDRESS = "MASTODON_SERVER_ADDRESS"
|
||||
MASTODON_TOOT_FOOTER = "MASTODON_TOOT_FOOTER"
|
||||
MASTODON_TOOT_MAX_CHARACTERS = "MASTODON_TOOT_MAX_CHARACTERS"
|
||||
MASTODON_TOOT_VISIBILITY = "MASTODON_TOOT_VISIBILITY"
|
||||
TELEGRAM_BOT_TOKEN = "TELEGRAM_BOT_TOKEN"
|
||||
TELEGRAM_CHAT_ID = "TELEGRAM_CHAT_ID"
|
||||
TELEGRAM_DEBUG = "TELEGRAM_DEBUG"
|
||||
)
|
||||
|
||||
// Check the specified Mastodon visibility and return it if valid or return
|
||||
// unlisted if it's not valid.
|
||||
// The specified string will be cheched case unsensitive.
|
||||
func parseMastodonVisibility(s string) string {
|
||||
s = strings.ToLower(s)
|
||||
// Keep sorted since we search inside.
|
||||
visibilities := []string{"direct", "private", "public", "unlisted"}
|
||||
r := sort.SearchStrings(visibilities, s)
|
||||
if r < len(visibilities) && visibilities[r] == s {
|
||||
return s
|
||||
}
|
||||
|
||||
return "unlisted"
|
||||
}
|
||||
|
||||
// Return configured Mastodon visibility for toot.
|
||||
func GetMastodonVisibility() string {
|
||||
return parseMastodonVisibility(os.Getenv(MASTODON_TOOT_VISIBILITY))
|
||||
}
|
||||
|
||||
// Parse Mastodon max characters and return 500 as default in case of errors.
|
||||
func parseMastodonMaxCharacters(s string) int {
|
||||
if n, err := strconv.ParseUint(s, 10, 32); err == nil {
|
||||
return int(n)
|
||||
}
|
||||
|
||||
return 500
|
||||
}
|
||||
|
||||
func GetMastodonMaxCharacters() int {
|
||||
return parseMastodonMaxCharacters(os.Getenv(MASTODON_TOOT_MAX_CHARACTERS))
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package cfg
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/alecthomas/assert"
|
||||
)
|
||||
|
||||
func TestParseMastodonVisibility(t *testing.T) {
|
||||
assert.Equal(t, parseMastodonVisibility("public"), "public")
|
||||
assert.Equal(t, parseMastodonVisibility("direct"), "direct")
|
||||
assert.Equal(t, parseMastodonVisibility("unlisted"), "unlisted")
|
||||
assert.Equal(t, parseMastodonVisibility("private"), "private")
|
||||
|
||||
assert.Equal(t, parseMastodonVisibility("Public"), "public")
|
||||
assert.Equal(t, parseMastodonVisibility("diRect"), "direct")
|
||||
assert.Equal(t, parseMastodonVisibility("unlisTED"), "unlisted")
|
||||
assert.Equal(t, parseMastodonVisibility("PRIVATE"), "private")
|
||||
|
||||
assert.Equal(t, parseMastodonVisibility("True"), "unlisted")
|
||||
assert.Equal(t, parseMastodonVisibility("eriol"), "unlisted")
|
||||
assert.Equal(t, parseMastodonVisibility(""), "unlisted")
|
||||
assert.Equal(t, parseMastodonVisibility(" "), "unlisted")
|
||||
}
|
||||
|
||||
func TestParseMastodonMaxCharacters(t *testing.T) {
|
||||
assert.Equal(t, parseMastodonMaxCharacters("42"), 42)
|
||||
assert.Equal(t, parseMastodonMaxCharacters("-42"), 500)
|
||||
assert.Equal(t, parseMastodonMaxCharacters("hello"), 500)
|
||||
}
|
104
cmd/run.go
104
cmd/run.go
|
@ -1,20 +1,19 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/cking/go-mastodon"
|
||||
mastodonapi "github.com/cking/go-mastodon"
|
||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"noa.mornie.org/eriol/telegram-group2mastodon/cfg"
|
||||
"noa.mornie.org/eriol/telegram-group2mastodon/mastodon"
|
||||
"noa.mornie.org/eriol/telegram-group2mastodon/utils"
|
||||
)
|
||||
|
||||
|
@ -23,7 +22,6 @@ const (
|
|||
MASTODON_SERVER_ADDRESS = "MASTODON_SERVER_ADDRESS"
|
||||
MASTODON_TOOT_FOOTER = "MASTODON_TOOT_FOOTER"
|
||||
MASTODON_TOOT_MAX_CHARACTERS = "MASTODON_TOOT_MAX_CHARACTERS"
|
||||
MASTODON_TOOT_VISIBILITY = "MASTODON_TOOT_VISIBILITY"
|
||||
TELEGRAM_BOT_TOKEN = "TELEGRAM_BOT_TOKEN"
|
||||
TELEGRAM_CHAT_ID = "TELEGRAM_CHAT_ID"
|
||||
TELEGRAM_DEBUG = "TELEGRAM_DEBUG"
|
||||
|
@ -38,15 +36,14 @@ var runCmd = &cobra.Command{
|
|||
Every messages posted in the Telegram groups the bot is in will be posted into
|
||||
the specified Mastodon account.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
mastodon_instance := os.Getenv(MASTODON_SERVER_ADDRESS)
|
||||
c := mastodon.NewClient(&mastodon.Config{
|
||||
Server: mastodon_instance,
|
||||
mastodonInstance := os.Getenv(MASTODON_SERVER_ADDRESS)
|
||||
c := mastodonapi.NewClient(&mastodonapi.Config{
|
||||
Server: mastodonInstance,
|
||||
AccessToken: os.Getenv(MASTODON_ACCESS_TOKEN),
|
||||
})
|
||||
log.Println("Crating a new client for mastondon istance:", mastodon_instance)
|
||||
max_characters := parseMastodonMaxCharacters(os.Getenv(MASTODON_TOOT_MAX_CHARACTERS))
|
||||
allowed_telegram_chat := parseTelegramChatID(os.Getenv(TELEGRAM_CHAT_ID))
|
||||
log.Println("Allowed telegram chat id:", allowed_telegram_chat)
|
||||
log.Println("Crating a new client for mastondon istance:", mastodonInstance)
|
||||
allowedTelegramChat := parseTelegramChatID(os.Getenv(TELEGRAM_CHAT_ID))
|
||||
log.Println("Allowed telegram chat id:", allowedTelegramChat)
|
||||
|
||||
bot, err := tgbotapi.NewBotAPI(os.Getenv(TELEGRAM_BOT_TOKEN))
|
||||
if err != nil {
|
||||
|
@ -62,39 +59,26 @@ the specified Mastodon account.`,
|
|||
|
||||
for update := range updates {
|
||||
chatID := update.Message.Chat.ID
|
||||
if chatID != allowed_telegram_chat {
|
||||
if chatID != allowedTelegramChat {
|
||||
log.Printf("Error: telegram chat %d is not the allowed one: %d\n",
|
||||
chatID,
|
||||
allowed_telegram_chat,
|
||||
allowedTelegramChat,
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
if update.Message != nil {
|
||||
messageID := update.Message.MessageID
|
||||
maxChars := cfg.GetMastodonMaxCharacters()
|
||||
tootVisibility := cfg.GetMastodonVisibility()
|
||||
tootFooter := os.Getenv(MASTODON_TOOT_FOOTER)
|
||||
|
||||
if update.Message.Text != "" {
|
||||
log.Printf("Text message received. Message id: %d\n", messageID)
|
||||
|
||||
text := update.Message.Text
|
||||
in_reply_to := ""
|
||||
|
||||
toot_footer := os.Getenv(MASTODON_TOOT_FOOTER)
|
||||
|
||||
messages := utils.SplitTextAtChunk(text, max_characters, toot_footer)
|
||||
for _, message := range messages {
|
||||
status, err := c.PostStatus(context.Background(), &mastodon.Toot{
|
||||
Status: message,
|
||||
Visibility: parseMastodonVisibility(os.Getenv(MASTODON_TOOT_VISIBILITY)),
|
||||
InReplyToID: mastodon.ID(in_reply_to),
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Could not post status: %v", err)
|
||||
continue
|
||||
}
|
||||
log.Printf("Posted status %s", status.URL)
|
||||
in_reply_to = string(status.ID)
|
||||
}
|
||||
messages := utils.SplitTextAtChunk(text, maxChars, tootFooter)
|
||||
mastodon.PostToots(c, messages, tootVisibility)
|
||||
|
||||
} else if update.Message.Photo != nil {
|
||||
log.Printf("Photo received. Message id: %d\n", messageID)
|
||||
|
@ -116,32 +100,14 @@ the specified Mastodon account.`,
|
|||
log.Printf("Could not download file: %v", err)
|
||||
continue
|
||||
}
|
||||
attachment, err := c.UploadMediaFromReader(
|
||||
context.Background(), file)
|
||||
if err != nil {
|
||||
log.Printf("Could not upload media: %v", err)
|
||||
continue
|
||||
}
|
||||
file.Close()
|
||||
log.Printf("Posted attachment %s", attachment.TextURL)
|
||||
|
||||
mediaIds := [...]mastodon.ID{attachment.ID}
|
||||
caption := update.Message.Caption
|
||||
if len(caption) > max_characters {
|
||||
caption = caption[:max_characters]
|
||||
}
|
||||
status, err := c.PostStatus(context.Background(), &mastodon.Toot{
|
||||
// Write the caption in the toot because it almost probably
|
||||
// doesn't describe the image.
|
||||
Status: caption,
|
||||
MediaIDs: mediaIds[:],
|
||||
Visibility: parseMastodonVisibility(os.Getenv(MASTODON_TOOT_VISIBILITY)),
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Could not post status: %v", err)
|
||||
continue
|
||||
}
|
||||
log.Printf("Posted status %s", status.URL)
|
||||
mastodon.PostPhoto(
|
||||
c,
|
||||
file,
|
||||
update.Message.Caption,
|
||||
maxChars,
|
||||
tootVisibility,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -161,21 +127,6 @@ func parseBoolOrFalse(s string) bool {
|
|||
return r
|
||||
}
|
||||
|
||||
// Check the specified Mastodon visibility and return it if valid or return
|
||||
// unlisted if it's not valid.
|
||||
// The specified string will be cheched case unsensitive.
|
||||
func parseMastodonVisibility(s string) string {
|
||||
s = strings.ToLower(s)
|
||||
// Keep sorted since we search inside.
|
||||
visibilities := []string{"direct", "private", "public", "unlisted"}
|
||||
r := sort.SearchStrings(visibilities, s)
|
||||
if r < len(visibilities) && visibilities[r] == s {
|
||||
return s
|
||||
}
|
||||
|
||||
return "unlisted"
|
||||
}
|
||||
|
||||
func downloadFile(url string) (io.ReadCloser, error) {
|
||||
response, err := http.Get(url)
|
||||
if err != nil {
|
||||
|
@ -189,15 +140,6 @@ func downloadFile(url string) (io.ReadCloser, error) {
|
|||
return response.Body, nil
|
||||
}
|
||||
|
||||
// Parse Mastodon max characters and return 500 as default in case of errors.
|
||||
func parseMastodonMaxCharacters(s string) int {
|
||||
if n, err := strconv.ParseUint(s, 10, 32); err == nil {
|
||||
return int(n)
|
||||
}
|
||||
|
||||
return 500
|
||||
}
|
||||
|
||||
func parseTelegramChatID(s string) int64 {
|
||||
r, err := strconv.ParseInt(s, 10, 64)
|
||||
if err != nil {
|
||||
|
|
|
@ -15,26 +15,3 @@ func TestParseBoolOrFalse(t *testing.T) {
|
|||
assert.Equal(t, parseBoolOrFalse("FALSE"), false)
|
||||
assert.Equal(t, parseBoolOrFalse("false"), false)
|
||||
}
|
||||
|
||||
func TestParseMastodonVisibility(t *testing.T) {
|
||||
assert.Equal(t, parseMastodonVisibility("public"), "public")
|
||||
assert.Equal(t, parseMastodonVisibility("direct"), "direct")
|
||||
assert.Equal(t, parseMastodonVisibility("unlisted"), "unlisted")
|
||||
assert.Equal(t, parseMastodonVisibility("private"), "private")
|
||||
|
||||
assert.Equal(t, parseMastodonVisibility("Public"), "public")
|
||||
assert.Equal(t, parseMastodonVisibility("diRect"), "direct")
|
||||
assert.Equal(t, parseMastodonVisibility("unlisTED"), "unlisted")
|
||||
assert.Equal(t, parseMastodonVisibility("PRIVATE"), "private")
|
||||
|
||||
assert.Equal(t, parseMastodonVisibility("True"), "unlisted")
|
||||
assert.Equal(t, parseMastodonVisibility("eriol"), "unlisted")
|
||||
assert.Equal(t, parseMastodonVisibility(""), "unlisted")
|
||||
assert.Equal(t, parseMastodonVisibility(" "), "unlisted")
|
||||
}
|
||||
|
||||
func TestParseMastodonMaxCharacters(t *testing.T) {
|
||||
assert.Equal(t, parseMastodonMaxCharacters("42"), 42)
|
||||
assert.Equal(t, parseMastodonMaxCharacters("-42"), 500)
|
||||
assert.Equal(t, parseMastodonMaxCharacters("hello"), 500)
|
||||
}
|
||||
|
|
6
go.mod
6
go.mod
|
@ -3,6 +3,7 @@ module noa.mornie.org/eriol/telegram-group2mastodon
|
|||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/alecthomas/assert v1.0.0
|
||||
github.com/cking/go-mastodon v0.0.6
|
||||
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1
|
||||
github.com/spf13/cobra v1.3.0
|
||||
|
@ -10,11 +11,16 @@ require (
|
|||
)
|
||||
|
||||
require (
|
||||
github.com/alecthomas/colour v0.1.0 // indirect
|
||||
github.com/alecthomas/repr v0.0.0-20210801044451-80ca428c5142 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/gorilla/websocket v1.4.1 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/sergi/go-diff v1.2.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 // indirect
|
||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
)
|
||||
|
|
10
go.sum
10
go.sum
|
@ -51,6 +51,12 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
|
|||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg=
|
||||
github.com/alecthomas/assert v1.0.0 h1:3XmGh/PSuLzDbK3W2gUbRXwgW5lqPkuqvRgeQ30FI5o=
|
||||
github.com/alecthomas/assert v1.0.0/go.mod h1:va/d2JC+M7F6s+80kl/R3G7FUiW6JzUO+hPhLyJ36ZY=
|
||||
github.com/alecthomas/colour v0.1.0 h1:nOE9rJm6dsZ66RGWYSFrXw461ZIt9A6+nHgL7FRrDUk=
|
||||
github.com/alecthomas/colour v0.1.0/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
|
||||
github.com/alecthomas/repr v0.0.0-20210801044451-80ca428c5142 h1:8Uy0oSf5co/NZXje7U1z8Mpep++QJOldL2hs/sBQf48=
|
||||
github.com/alecthomas/repr v0.0.0-20210801044451-80ca428c5142/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
|
@ -263,6 +269,7 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
|
|||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0=
|
||||
|
@ -310,6 +317,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
|
|||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
||||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
|
@ -536,6 +545,7 @@ golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7qVW4r4ctbWpURyuOD0E=
|
||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package mastodon
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"log"
|
||||
|
||||
mastodonapi "github.com/cking/go-mastodon"
|
||||
)
|
||||
|
||||
// Post one or more toots.
|
||||
func PostToots(client *mastodonapi.Client, messages []string, visibility string) {
|
||||
in_reply_to := ""
|
||||
for _, message := range messages {
|
||||
status, err := client.PostStatus(context.Background(), &mastodonapi.Toot{
|
||||
Status: message,
|
||||
Visibility: visibility,
|
||||
InReplyToID: mastodonapi.ID(in_reply_to),
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Could not post status: %v", err)
|
||||
continue
|
||||
}
|
||||
log.Printf("Posted status %s", status.URL)
|
||||
in_reply_to = string(status.ID)
|
||||
}
|
||||
}
|
||||
|
||||
// Post a photo on mastodon with caption.
|
||||
func PostPhoto(
|
||||
client *mastodonapi.Client,
|
||||
file io.ReadCloser,
|
||||
caption string,
|
||||
maxCharacters int,
|
||||
visibility string) {
|
||||
attachment, err := client.UploadMediaFromReader(
|
||||
context.Background(), file)
|
||||
if err != nil {
|
||||
log.Printf("Could not upload media: %v", err)
|
||||
}
|
||||
file.Close()
|
||||
log.Printf("Posted attachment %s", attachment.TextURL)
|
||||
|
||||
mediaIds := [...]mastodonapi.ID{attachment.ID}
|
||||
if len(caption) > maxCharacters {
|
||||
caption = caption[:maxCharacters]
|
||||
}
|
||||
status, err := client.PostStatus(context.Background(), &mastodonapi.Toot{
|
||||
// Write the caption in the toot because it almost probably
|
||||
// doesn't describe the image.
|
||||
Status: caption,
|
||||
MediaIDs: mediaIds[:],
|
||||
Visibility: visibility,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Could not post status: %v", err)
|
||||
}
|
||||
log.Printf("Posted status %s", status.URL)
|
||||
}
|
Loading…
Reference in New Issue