toot: Add flag --add-mentions to add mentions when replying
authorMikael Berthe <mikael@lilotux.net>
Sat, 13 May 2017 09:55:07 +0200
changeset 129 11966471aac3
parent 128 e0621d1b9230
child 130 787bbbf4c5da
toot: Add flag --add-mentions to add mentions when replying Using --add-mentions with --in-reply-to will automatically prefix toot content with mentions for the specified status ID. (Feature suggested by @wxl)
README.md
cmd/status.go
cmd/toot.go
--- a/README.md	Sat May 13 09:49:05 2017 +0200
+++ b/README.md	Sat May 13 09:55:07 2017 +0200
@@ -106,6 +106,14 @@
 % echo "Hello from #madonctl" | madonctl toot --stdin
 ```
 
+Reply to a message:
+``` sh
+% madonctl toot --in-reply-to 1234 --visibility direct "@user1 @user2 response"
+% madonctl toot --in-reply-to 1234 --add-mentions "response"
+```
+The flag `--add-mentions` automatically adds mentions based on the toot you're
+replying to.
+
 Some **account-related commands**:
 ``` sh
 % madonctl accounts blocked                       # List blocked accounts
--- a/cmd/status.go	Sat May 13 09:49:05 2017 +0200
+++ b/cmd/status.go	Sat May 13 09:55:07 2017 +0200
@@ -29,6 +29,7 @@
 	mediaFilePath string
 	textFilePath  string
 	stdin         bool
+	addMentions   bool
 
 	// Used for several subcommands to limit the number of results
 	limit uint
@@ -62,6 +63,7 @@
 	statusPostSubcommand.Flags().StringVar(&statusOpts.textFilePath, "text-file", "", "Text file name (message content)")
 	statusPostSubcommand.Flags().Int64VarP(&statusOpts.inReplyToID, "in-reply-to", "r", 0, "Status ID to reply to")
 	statusPostSubcommand.Flags().BoolVar(&statusOpts.stdin, "stdin", false, "Read message content from standard input")
+	statusPostSubcommand.Flags().BoolVar(&statusOpts.addMentions, "add-mentions", false, "Add mentions when replying")
 
 	// Flag completion
 	annotation := make(map[string][]string)
@@ -163,6 +165,8 @@
   madonctl status toot --sensitive --file image.jpg Image
   madonctl status post --media-ids ID1,ID2,ID3 Image
   madonctl status toot --text-file message.txt
+  madonctl status post --in-reply-to STATUSID "@user response"
+  madonctl status post --in-reply-to STATUSID --add-mentions "response"
   echo "Hello from #madonctl" | madonctl status toot --stdin
 
 The default visibility can be set in the configuration file with the option
--- a/cmd/toot.go	Sat May 13 09:49:05 2017 +0200
+++ b/cmd/toot.go	Sat May 13 09:55:07 2017 +0200
@@ -6,6 +6,8 @@
 package cmd
 
 import (
+	"strings"
+
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
@@ -26,6 +28,7 @@
 	tootAliasCmd.Flags().StringVar(&statusOpts.textFilePath, "text-file", "", "Text file name (message content)")
 	tootAliasCmd.Flags().Int64VarP(&statusOpts.inReplyToID, "in-reply-to", "r", 0, "Status ID to reply to")
 	tootAliasCmd.Flags().BoolVar(&statusOpts.stdin, "stdin", false, "Read message content from standard input")
+	tootAliasCmd.Flags().BoolVar(&statusOpts.addMentions, "add-mentions", false, "Add mentions when replying")
 
 	// Flag completion
 	annotation := make(map[string][]string)
@@ -43,6 +46,8 @@
   madonctl status post --media-ids ID1,ID2 "Here are the photos"
   madonctl post --sensitive --file image.jpg Image
   madonctl toot --text-file message.txt
+  madonctl toot --in-reply-to STATUSID "@user response"
+  madonctl toot --in-reply-to STATUSID --add-mentions "response"
   echo "Hello from #madonctl" | madonctl toot --visibility unlisted --stdin
 
 The default visibility can be set in the configuration file with the option
@@ -81,6 +86,19 @@
 		return nil, errors.New("cannot parse media IDs")
 	}
 
+	if tootText == "" && len(ids) == 0 && opt.spoiler == "" && opt.mediaFilePath == "" {
+		return nil, errors.New("toot is empty")
+	}
+
+	if opt.addMentions && opt.inReplyToID > 0 {
+		mentions, err := mentionsList(opt.inReplyToID)
+		if err != nil {
+			return nil, err
+		}
+		tootText = mentions + tootText
+	}
+
+	// Uploading media file last
 	if opt.mediaFilePath != "" {
 		if len(ids) > 3 {
 			return nil, errors.New("too many media attachments")
@@ -95,9 +113,33 @@
 		}
 	}
 
-	if tootText == "" && len(ids) == 0 && opt.spoiler == "" {
-		return nil, errors.New("toot is empty")
+	return gClient.PostStatus(tootText, opt.inReplyToID, ids, opt.sensitive, opt.spoiler, opt.visibility)
+}
+
+func mentionsList(statusID int64) (string, error) {
+	a, err := gClient.GetCurrentAccount()
+	if err != nil {
+		return "", errors.Wrap(err, "cannot check account details")
+	}
+
+	s, err := gClient.GetStatus(statusID)
+	if err != nil {
+		return "", errors.Wrap(err, "cannot get mentions")
 	}
 
-	return gClient.PostStatus(tootText, opt.inReplyToID, ids, opt.sensitive, opt.spoiler, opt.visibility)
+	var mentions []string
+	// Add the sender if she is not the connected user
+	if s.Account.Acct != a.Acct {
+		mentions = append(mentions, "@"+s.Account.Acct)
+	}
+	for _, m := range s.Mentions {
+		if m.Acct != a.Acct {
+			mentions = append(mentions, "@"+m.Acct)
+		}
+	}
+	mentionsStr := strings.Join(mentions, " ")
+	if len(mentionsStr) > 0 {
+		return mentionsStr + " ", nil
+	}
+	return "", nil
 }