2018-11-22 04:35:51 +01:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
2020-10-04 03:19:10 +02:00
|
|
|
"strings"
|
2018-11-22 04:35:51 +01:00
|
|
|
|
|
|
|
mastodon "github.com/mattn/go-mastodon"
|
2019-08-11 21:46:42 +02:00
|
|
|
"github.com/spf13/cobra"
|
2018-11-22 04:35:51 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2019-08-11 21:46:42 +02:00
|
|
|
client *mastodon.Client
|
|
|
|
self *mastodon.Account
|
|
|
|
configFile string
|
|
|
|
|
2020-08-23 12:09:38 +02:00
|
|
|
// RootCmd is the core command used for cli-arg parsing.
|
2019-08-11 21:46:42 +02:00
|
|
|
RootCmd = &cobra.Command{
|
|
|
|
Use: "mastotool",
|
|
|
|
Short: "mastotool offers a collection of tools to work with your Mastodon account",
|
|
|
|
SilenceErrors: true,
|
|
|
|
SilenceUsage: true,
|
2020-10-06 04:07:22 +02:00
|
|
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
|
|
|
if err := initClient(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var err error
|
|
|
|
self, err = client.GetAccountCurrentUser(context.Background())
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Can't retrieve user: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
},
|
2019-08-11 21:46:42 +02:00
|
|
|
}
|
2018-11-22 04:35:51 +01:00
|
|
|
)
|
|
|
|
|
2020-08-23 12:09:54 +02:00
|
|
|
const (
|
|
|
|
progressBarWidth = 40
|
|
|
|
)
|
|
|
|
|
2018-11-22 22:25:08 +01:00
|
|
|
func registerApp(config *Config) (string, error) {
|
2018-11-22 04:35:51 +01:00
|
|
|
app, err := mastodon.RegisterApp(context.Background(), &mastodon.AppConfig{
|
|
|
|
Server: config.Value("instance").(string),
|
2019-08-11 04:12:37 +02:00
|
|
|
ClientName: "mastotool",
|
2018-11-22 22:25:08 +01:00
|
|
|
Scopes: "read",
|
2018-11-22 04:35:51 +01:00
|
|
|
Website: "",
|
|
|
|
})
|
|
|
|
if err != nil {
|
2018-11-22 22:25:08 +01:00
|
|
|
return "", err
|
2018-11-22 04:35:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
config.Set("id", app.ClientID)
|
|
|
|
config.Set("secret", app.ClientSecret)
|
2018-11-22 22:25:08 +01:00
|
|
|
config.Set("redirectURI", app.RedirectURI)
|
|
|
|
|
|
|
|
return app.AuthURI, nil
|
2018-11-22 04:35:51 +01:00
|
|
|
}
|
|
|
|
|
2019-08-08 06:18:20 +02:00
|
|
|
func initClient() error {
|
2018-11-22 04:35:51 +01:00
|
|
|
var err error
|
2018-11-22 22:25:08 +01:00
|
|
|
var instance, token, redirectURI, authURI, id, secret string
|
2019-08-11 21:46:42 +02:00
|
|
|
config, err := LoadConfig(configFile)
|
2018-11-22 04:35:51 +01:00
|
|
|
if err == nil {
|
|
|
|
instance = config.Value("instance").(string)
|
|
|
|
id = config.Value("id").(string)
|
2018-11-22 22:25:08 +01:00
|
|
|
secret = config.Value("secret").(string)
|
|
|
|
token = config.Value("token").(string)
|
|
|
|
redirectURI = config.Value("redirectURI").(string)
|
2018-11-22 04:35:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
scanner := bufio.NewScanner(os.Stdin)
|
|
|
|
if len(instance) == 0 {
|
|
|
|
fmt.Print("Which instance to connect to (e.g. https://mastodon.social): ")
|
|
|
|
scanner.Scan()
|
|
|
|
if scanner.Err() != nil {
|
2019-08-08 06:18:20 +02:00
|
|
|
return fmt.Errorf("Can't open input: %s", err)
|
2018-11-22 04:35:51 +01:00
|
|
|
}
|
2020-10-04 03:19:10 +02:00
|
|
|
|
2018-11-22 04:35:51 +01:00
|
|
|
instance = scanner.Text()
|
2020-10-04 03:19:10 +02:00
|
|
|
if !strings.HasPrefix(instance, "http") {
|
|
|
|
instance = "https://" + instance
|
|
|
|
}
|
|
|
|
|
2018-11-22 22:25:08 +01:00
|
|
|
config.Set("instance", instance)
|
2018-11-22 04:35:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if len(id) == 0 {
|
2018-11-22 22:25:08 +01:00
|
|
|
authURI, err = registerApp(&config)
|
2018-11-22 04:35:51 +01:00
|
|
|
if err != nil {
|
2019-08-08 06:18:20 +02:00
|
|
|
return fmt.Errorf("Can't register app: %s", err)
|
2018-11-22 04:35:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
id = config.Value("id").(string)
|
|
|
|
secret = config.Value("secret").(string)
|
2018-11-22 22:25:08 +01:00
|
|
|
redirectURI = config.Value("redirectURI").(string)
|
2018-11-22 04:35:51 +01:00
|
|
|
}
|
|
|
|
|
2018-11-22 22:25:08 +01:00
|
|
|
mConfig := &mastodon.Config{
|
|
|
|
AccessToken: token,
|
|
|
|
Server: instance,
|
|
|
|
ClientID: id,
|
|
|
|
ClientSecret: secret,
|
|
|
|
}
|
|
|
|
client = mastodon.NewClient(mConfig)
|
|
|
|
|
|
|
|
if len(mConfig.AccessToken) == 0 {
|
|
|
|
fmt.Printf("Please visit %s and enter the generated token: ", authURI)
|
|
|
|
scanner.Scan()
|
|
|
|
if scanner.Err() != nil {
|
2019-08-08 06:18:20 +02:00
|
|
|
return fmt.Errorf("Can't open input: %s", err)
|
2018-11-22 22:25:08 +01:00
|
|
|
}
|
|
|
|
code := scanner.Text()
|
|
|
|
|
|
|
|
err = client.AuthenticateToken(context.Background(), code, redirectURI)
|
2018-11-22 04:35:51 +01:00
|
|
|
if err != nil {
|
2019-08-08 06:18:20 +02:00
|
|
|
return fmt.Errorf("Can't retrieve authentication token: %s", err)
|
2018-11-22 04:35:51 +01:00
|
|
|
}
|
|
|
|
|
2018-11-22 22:25:08 +01:00
|
|
|
config.Set("token", mConfig.AccessToken)
|
2019-08-11 21:46:42 +02:00
|
|
|
err = config.Save(configFile)
|
2019-08-08 06:18:20 +02:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Can't save config: %s", err)
|
|
|
|
}
|
2018-11-22 04:35:51 +01:00
|
|
|
}
|
|
|
|
|
2019-08-08 06:18:20 +02:00
|
|
|
return nil
|
|
|
|
}
|
2018-11-22 06:48:21 +01:00
|
|
|
|
2019-08-08 06:18:20 +02:00
|
|
|
func main() {
|
2019-08-11 21:46:42 +02:00
|
|
|
RootCmd.PersistentFlags().StringVarP(&configFile, "config", "c", "mastodon.json", "uses the specified config file")
|
|
|
|
|
|
|
|
if err := RootCmd.Execute(); err != nil {
|
2019-08-08 06:18:20 +02:00
|
|
|
fmt.Println(err)
|
2020-10-06 04:07:22 +02:00
|
|
|
os.Exit(1)
|
2019-08-08 06:18:20 +02:00
|
|
|
}
|
2018-11-22 04:35:51 +01:00
|
|
|
}
|