From 0afa5f9933181598def3ef90b46af1c5dfa1517f Mon Sep 17 00:00:00 2001 From: gutmet Date: Tue, 22 Sep 2020 08:09:34 +0200 Subject: [PATCH] display in_reply_to stuff, new lookup subcommand --- Readme.md | 12 ++++++++--- drivel.go | 63 ++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/Readme.md b/Readme.md index 1fae1dc..d659d68 100644 --- a/Readme.md +++ b/Readme.md @@ -49,24 +49,30 @@ To retweet a tweet with a specific ID: drivel retweet TWEET_ID ``` +To lookup tweets with specific IDs: + +``` +drivel lookup TWEET_ID1 [TWEET_ID2 TWEET_ID3 ...] +``` + To update your status with optional media upload: ``` -drivel status STATUS [FILE1, FILE2, ...] +drivel status STATUS [FILE1 FILE2 ...] ``` To reply to a tweet with a specific ID: ``` -drivel reply TWEET_ID MESSAGE [FILE1, FILE2, ...] +drivel reply TWEET_ID MESSAGE [FILE1 FILE2 ...] ``` To quote a tweet with a specific ID: ``` -drivel quote TWEET_ID MESSAGE [FILE1, FILE2, ...] +drivel quote TWEET_ID MESSAGE [FILE1 FILE2 ...] ``` diff --git a/drivel.go b/drivel.go index dcbdf35..eed454b 100644 --- a/drivel.go +++ b/drivel.go @@ -369,7 +369,7 @@ func exitIfInvalid(path string) { func splitArguments(args []string) data { if len(args) < 1 { - fmt.Fprintln(os.Stderr, "Usage: drivel status STATUS [FILE1, FILE2, ...]") + fmt.Fprintln(os.Stderr, "Usage: drivel status STATUS [FILE1 FILE2 ...]") os.Exit(-1) } d := data{} @@ -476,7 +476,7 @@ func updateStatus(args []string, previous ObjectID, embedTweet ObjectID) { d := splitArguments(args) httpClient := getClient() if embedTweet != "" { - tweets := lookup(httpClient, []string{string(embedTweet)}) + tweets := _lookup(httpClient, []string{string(embedTweet)}) if len(tweets) == 1 { d.status[0] += " " + tweets[0].URL() } @@ -491,7 +491,7 @@ func status(args []string) error { func reply(args []string) error { if len(args) < 2 { - fmt.Fprintln(os.Stderr, "Usage: drivel reply TWEET_ID MESSAGE [FILE1, FILE2, ...]") + fmt.Fprintln(os.Stderr, "Usage: drivel reply TWEET_ID MESSAGE [FILE1 FILE2 ...]") os.Exit(-1) } updateStatus(args[1:], ObjectID(args[0]), "") @@ -500,7 +500,7 @@ func reply(args []string) error { func quote(args []string) error { if len(args) < 2 { - fmt.Println(os.Stderr, "Usage: drivel quote TWEET_ID MESSAGE [FILE1, FILE2, ...]") + fmt.Println(os.Stderr, "Usage: drivel quote TWEET_ID MESSAGE [FILE1 FILE2 ...]") os.Exit(-1) } updateStatus(args[1:], "", ObjectID(args[0])) @@ -508,12 +508,14 @@ func quote(args []string) error { } type Status struct { - Full_text string - Id_str string - User StatusUser - Quoted_status *Status - Retweeted_status *Status - Extended_entities Entities + Full_text string + Id_str string + In_reply_to_screen_name string + In_reply_to_status_id_str string + User StatusUser + Quoted_status *Status + Retweeted_status *Status + Extended_entities Entities } type Entities struct { @@ -524,11 +526,23 @@ type Media struct { Media_url string } +func (m Status) InReplyTo() string { + if m.In_reply_to_status_id_str != "" { + return m.In_reply_to_screen_name + " (" + m.In_reply_to_status_id_str + ")" + } else { + return "" + } +} + func (m Status) String() string { if m.Retweeted_status != nil { return m.User.Screen_name + " retweeted " + m.Retweeted_status.String() } - s := m.User.Screen_name + " " + "(" + m.Id_str + ")" + ":\n" + m.Full_text + s := m.User.Screen_name + " " + "(" + m.Id_str + ")" + if replyTo := m.InReplyTo(); replyTo != "" { + s += " in reply to " + replyTo + } + s += ":\n" + m.Full_text allMedia := m.Extended_entities.Media if len(allMedia) > 0 { s += "\n\nMedia:" @@ -542,6 +556,13 @@ func (m Status) String() string { return s } +func PrintTweets(tweets []Status) { + for _, tweet := range tweets { + fmt.Println(tweet) + fmt.Println("---------") + } +} + func (m Status) URL() string { return "https://twitter.com/" + m.User.Screen_name + "/status/" + m.Id_str } @@ -551,7 +572,7 @@ type StatusUser struct { Screen_name string } -func lookup(client *http.Client, ids []string) []Status { +func _lookup(client *http.Client, ids []string) []Status { log := func(err error) { optLogFatal("lookup "+strings.Join(ids, ","), err) } body := get(client, LOOKUP_ENDPOINT+LookupParameters(ids)) var tweets []Status @@ -560,6 +581,16 @@ func lookup(client *http.Client, ids []string) []Status { return tweets } +func lookup(args []string) error { + if len(args) < 1 { + fmt.Fprintln(os.Stderr, "USAGE: drivel lookup TWEET_ID1 [TWEET_ID2 TWEET_ID3 ...]") + os.Exit(-1) + } + tweets := _lookup(getClient(), args) + PrintTweets(tweets) + return nil +} + func timeline(endpoint string) { log := func(err error) { optLogFatal("timeline", err) } client := getClient() @@ -567,10 +598,7 @@ func timeline(endpoint string) { var tweets []Status err := json.Unmarshal(body, &tweets) log(err) - for _, tweet := range tweets { - fmt.Println(tweet) - fmt.Println("---------") - } + PrintTweets(tweets) } func mentions(args []string) error { @@ -604,7 +632,7 @@ func retweet(args []string) error { } client := getClient() id := args[0] - tweets := lookup(client, []string{id}) + tweets := _lookup(client, []string{id}) if len(tweets) != 1 { log(errors.New("Could not find tweet " + id)) } @@ -644,6 +672,7 @@ func main() { goutil.NewCommand("home", home, "get your home timeline"), goutil.NewCommand("mentions", mentions, "get your mention timeline"), goutil.NewCommand("timeline", userTimeline, "get timeline of a specific user"), + goutil.NewCommand("lookup", lookup, "lookup tweets with specific IDs"), goutil.NewCommand("reply", reply, "reply to a tweet with a specific ID"), goutil.NewCommand("quote", quote, "quote retweet a tweet with a specific ID"), goutil.NewCommand("retweet", retweet, "retweet a tweet with a specific ID"),