From c8f724f5fe31fade3b288f0937d189e2ff17593e Mon Sep 17 00:00:00 2001 From: gutmet Date: Thu, 17 Sep 2020 16:56:18 +0200 Subject: [PATCH] move status update to 'status' subcommand, new 'mentions' subcommand --- Readme.md | 13 +++++++-- drivel.go | 79 ++++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 78 insertions(+), 14 deletions(-) diff --git a/Readme.md b/Readme.md index ee210c2..0854fff 100644 --- a/Readme.md +++ b/Readme.md @@ -1,7 +1,7 @@ drivel ======== -drivel is a Twitter command line interface for status updates and media upload. +drivel is a Twitter command line interface for status updates, media upload and mentions. My personal opinion is that you shouldn't be on Twitter in the first place, but anyway... @@ -21,8 +21,17 @@ go build drivel.go credentials.go usage ----- +To get your last 100 mentions: + ``` -drivel STATUS [FILE1, FILE2, ...] +drivel mentions +``` + +To update your status with optional media upload: + + +``` +drivel status STATUS [FILE1, FILE2, ...] ``` with any number of files, as long as they are .jpg, .png, .gif or .mp4 and smaller than 5 MB each. On first use, drivel will ask you to go to [https://apps.twitter.com/app/new](https://apps.twitter.com/app/new), register a new app and create an access token. Those values will be stored in HOME/.drivel/ for later use. diff --git a/drivel.go b/drivel.go index 7b3c84a..5d7b0f5 100644 --- a/drivel.go +++ b/drivel.go @@ -16,10 +16,11 @@ import ( ) const ( - MAX_BYTES = 5 * 1024 * 1024 - CHARACTER_LIMIT = 280 - UPLOAD_ENDPOINT = "https://upload.twitter.com/1.1/media/upload.json" - STATUS_ENDPOINT = "https://api.twitter.com/1.1/statuses/update.json" + MAX_BYTES = 5 * 1024 * 1024 + CHARACTER_LIMIT = 280 + UPLOAD_ENDPOINT = "https://upload.twitter.com/1.1/media/upload.json" + STATUS_ENDPOINT = "https://api.twitter.com/1.1/statuses/update.json" + MENTIONS_ENDPOINT = "https://api.twitter.com/1.1/statuses/mentions_timeline.json?tweet_mode=extended&count=100" ) func optLogFatal(decorum string, err error) { @@ -122,12 +123,26 @@ func getMimetype(file string) string { } } +func get(client *http.Client, url string) []byte { + return _send(client, url, nil, false) +} + func send(client *http.Client, url string, vals url.Values) []byte { + return _send(client, url, vals, true) +} + +func _send(client *http.Client, url string, vals url.Values, usePost bool) []byte { log := func(err error) { v, _ := json.Marshal(vals) optLogFatal("send "+url+" "+string(v), err) } - resp, err := client.PostForm(url, vals) + var resp *http.Response + var err error + if usePost { + resp, err = client.PostForm(url, vals) + } else { + resp, err = client.Get(url) + } log(err) defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) @@ -238,14 +253,14 @@ func exitIfInvalid(path string) { } } -func splitArguments() data { - if len(os.Args) < 2 { - fmt.Fprintln(os.Stderr, "Usage: drivel STATUS [FILE1, FILE2, ...]") +func splitArguments(args []string) data { + if len(args) < 1 { + fmt.Fprintln(os.Stderr, "Usage: drivel status STATUS [FILE1, FILE2, ...]") os.Exit(-1) } d := data{} - d.status = splitStatus(os.Args[1]) - for _, arg := range os.Args[2:] { + d.status = splitStatus(args[0]) + for _, arg := range args[1:] { exitIfInvalid(arg) switch kind(arg) { case PIC: @@ -344,8 +359,48 @@ func (d *data) push(client *http.Client) { } } -func main() { - d := splitArguments() +func status(args []string) error { + d := splitArguments(args) httpClient := getClient() d.push(httpClient) + return nil +} + +type Mention struct { + Full_text string + User MentionUser +} + +func (m Mention) String() string { + return m.User.Name + ":\n" + m.Full_text +} + +type MentionUser struct { + Name string +} + +func mentions(args []string) error { + log := func(err error) { optLogFatal("mentions", err) } + client := getClient() + body := get(client, MENTIONS_ENDPOINT) + var mentions []Mention + err := json.Unmarshal(body, &mentions) + log(err) + for _, mention := range mentions { + fmt.Println(mention) + fmt.Println("---------") + } + return nil +} + +func main() { + commands := []goutil.Command{ + goutil.NewCommand("status", status, "post a status with message and/or media"), + goutil.NewCommand("mentions", mentions, "get your mentions"), + } + err := goutil.Execute(commands) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } }