Merge pull request #29 from rjp/fix/support-non-int-ids
Update to handle non-int64 IDs
committer: GitHub <noreply@github.com>
--- a/cmd/accounts.go Sat Feb 04 11:00:55 2023 +0000
+++ b/cmd/accounts.go Sat Feb 04 13:17:17 2023 +0100
@@ -20,30 +20,30 @@
var accountUpdateFlags, accountMuteFlags, accountFollowFlags *flag.FlagSet
var accountsOpts struct {
- accountID int64
+ accountID madon.ActivityID
accountUID string
- unset bool // TODO remove eventually?
- limit, keep uint // Limit the results
- sinceID, maxID int64 // Query boundaries
- all bool // Try to fetch all results
- onlyMedia, onlyPinned bool // For acccount statuses
- excludeReplies bool // For acccount statuses
- remoteUID string // For account follow
- reblogs bool // For account follow
- acceptFR, rejectFR bool // For account follow_requests
- list bool // For account follow_requests/reports
- accountIDs string // For account relationships
- statusIDs string // For account reports
- comment string // For account reports
- displayName, note string // For account update
- profileFields []string // For account update
- avatar, header string // For account update
- defaultLanguage string // For account update
- defaultPrivacy string // For account update
- defaultSensitive bool // For account update
- locked, bot bool // For account update
- muteNotifications bool // For account mute
- following bool // For account search
+ unset bool // TODO remove eventually?
+ limit, keep uint // Limit the results
+ sinceID, maxID madon.ActivityID // Query boundaries
+ all bool // Try to fetch all results
+ onlyMedia, onlyPinned bool // For acccount statuses
+ excludeReplies bool // For acccount statuses
+ remoteUID string // For account follow
+ reblogs bool // For account follow
+ acceptFR, rejectFR bool // For account follow_requests
+ list bool // For account follow_requests/reports
+ accountIDs string // For account relationships
+ statusIDs string // For account reports
+ comment string // For account reports
+ displayName, note string // For account update
+ profileFields []string // For account update
+ avatar, header string // For account update
+ defaultLanguage string // For account update
+ defaultPrivacy string // For account update
+ defaultSensitive bool // For account update
+ locked, bot bool // For account update
+ muteNotifications bool // For account mute
+ following bool // For account search
}
func init() {
@@ -53,12 +53,12 @@
accountsCmd.AddCommand(accountSubcommands...)
// Global flags
- accountsCmd.PersistentFlags().Int64VarP(&accountsOpts.accountID, "account-id", "a", 0, "Account ID number")
+ accountsCmd.PersistentFlags().StringVarP(&accountsOpts.accountID, "account-id", "a", "", "Account ID number")
accountsCmd.PersistentFlags().StringVarP(&accountsOpts.accountUID, "user-id", "u", "", "Account user ID")
accountsCmd.PersistentFlags().UintVarP(&accountsOpts.limit, "limit", "l", 0, "Limit number of API results")
accountsCmd.PersistentFlags().UintVarP(&accountsOpts.keep, "keep", "k", 0, "Limit number of results")
- accountsCmd.PersistentFlags().Int64Var(&accountsOpts.sinceID, "since-id", 0, "Request IDs greater than a value")
- accountsCmd.PersistentFlags().Int64Var(&accountsOpts.maxID, "max-id", 0, "Request IDs less (or equal) than a value")
+ accountsCmd.PersistentFlags().StringVar(&accountsOpts.sinceID, "since-id", "", "Request IDs greater than a value")
+ accountsCmd.PersistentFlags().StringVar(&accountsOpts.maxID, "max-id", "", "Request IDs less (or equal) than a value")
accountsCmd.PersistentFlags().BoolVar(&accountsOpts.all, "all", false, "Fetch all results")
// Subcommand flags
@@ -377,7 +377,7 @@
// Check account is provided in only one way
aCounter := 0
- if opt.accountID > 0 {
+ if opt.accountID != "" {
aCounter++
}
if opt.accountUID != "" {
@@ -396,8 +396,8 @@
if userInArg {
// Is the argument an account ID?
- if n, err := strconv.ParseInt(args[0], 10, 64); err == nil {
- opt.accountID = n
+ if _, err := strconv.ParseInt(args[0], 10, 64); err == nil {
+ opt.accountID = args[0]
} else if strings.HasPrefix(args[0], "https://") || strings.HasPrefix(args[0], "http://") {
// That is not a remote UID scheme
opt.accountUID = args[0]
@@ -417,7 +417,7 @@
}
if opt.accountUID != "" {
- if opt.accountID > 0 {
+ if opt.accountID != "" {
return errors.New("cannot use both account ID and UID")
}
// Sign in early to look the user id up
@@ -426,7 +426,7 @@
return err
}
opt.accountID, err = accountLookupUser(opt.accountUID)
- if err != nil || opt.accountID < 1 {
+ if err != nil || opt.accountID == "" {
if err != nil {
errPrint("Cannot find user '%s': %v", opt.accountUID, err)
} else {
@@ -441,18 +441,18 @@
// These subcommands do not require an account ID
case "favourites", "blocks", "mutes", "pinned":
// Those subcommands can not use an account ID
- if opt.accountID > 0 {
+ if opt.accountID != "" {
return errors.New("useless account ID")
}
case "follow", "unfollow":
// We need an account ID or a remote UID
- if opt.accountID < 1 && opt.remoteUID == "" {
+ if opt.accountID == "" && opt.remoteUID == "" {
return errors.New("missing account ID or URI")
}
- if opt.accountID > 0 && opt.remoteUID != "" {
+ if opt.accountID != "" && opt.remoteUID != "" {
return errors.New("cannot use both account ID and URI")
}
- if (opt.unset || subcmd == "unfollow") && opt.accountID < 1 {
+ if (opt.unset || subcmd == "unfollow") && opt.accountID == "" {
return errors.New("unfollowing requires an account ID")
}
case "follow-requests":
@@ -468,27 +468,27 @@
if opt.acceptFR && opt.rejectFR {
return errors.New("incompatible options")
}
- if opt.accountID < 1 {
+ if opt.accountID == "" {
return errors.New("missing account ID")
}
}
case "relationships":
- if opt.accountID < 1 && len(opt.accountIDs) == 0 {
+ if opt.accountID == "" && len(opt.accountIDs) == 0 {
return errors.New("missing account IDs")
}
- if opt.accountID > 0 && len(opt.accountIDs) > 0 {
+ if opt.accountID != "" && len(opt.accountIDs) > 0 {
return errors.New("incompatible options")
}
case "reports":
if opt.list {
break // No argument needed
}
- if opt.accountID < 1 || len(opt.statusIDs) == 0 || opt.comment == "" {
+ if opt.accountID == "" || len(opt.statusIDs) == 0 || opt.comment == "" {
return errors.New("missing parameter")
}
case "followers", "following", "statuses":
// If the user's account ID is missing, get it
- if opt.accountID < 1 {
+ if opt.accountID == "" {
// Sign in now to look the user id up
if err := madonInit(true); err != nil {
return err
@@ -504,13 +504,13 @@
}
default:
// The other subcommands here require an account ID
- if opt.accountID < 1 {
+ if opt.accountID == "" {
return errors.New("missing account ID")
}
}
var limOpts *madon.LimitParams
- if opt.all || opt.limit > 0 || opt.sinceID > 0 || opt.maxID > 0 {
+ if opt.all || opt.limit > 0 || opt.sinceID != "" || opt.maxID != "" {
limOpts = new(madon.LimitParams)
limOpts.All = opt.all
}
@@ -518,10 +518,10 @@
if opt.limit > 0 {
limOpts.Limit = int(opt.limit)
}
- if opt.maxID > 0 {
+ if opt.maxID != "" {
limOpts.MaxID = opt.maxID
}
- if opt.sinceID > 0 {
+ if opt.sinceID != "" {
limOpts.SinceID = opt.sinceID
}
@@ -536,7 +536,7 @@
switch subcmd {
case "show":
var account *madon.Account
- if opt.accountID > 0 {
+ if opt.accountID != "" {
account, err = gClient.GetAccount(opt.accountID)
} else {
account, err = gClient.GetCurrentAccount()
@@ -574,7 +574,7 @@
obj = relationship
break
}
- if opt.accountID <= 0 {
+ if opt.accountID == "" {
if opt.remoteUID != "" {
// Remote account
var account *madon.Account
@@ -597,7 +597,7 @@
if opt.list {
var followRequests []madon.Account
followRequests, err = gClient.GetAccountFollowRequests(limOpts)
- if opt.accountID > 0 { // Display a specific request
+ if opt.accountID != "" { // Display a specific request
var fRequest *madon.Account
for _, fr := range followRequests {
if fr.ID == opt.accountID {
@@ -676,13 +676,13 @@
}
obj = accountList
case "relationships":
- var ids []int64
+ var ids []madon.ActivityID
ids, err = splitIDs(opt.accountIDs)
if err != nil {
return errors.New("cannot parse account IDs")
}
- if opt.accountID > 0 { // Allow --account-id
- ids = []int64{opt.accountID}
+ if opt.accountID != "" { // Allow --account-id
+ ids = []madon.ActivityID{opt.accountID}
}
if len(ids) < 1 {
return errors.New("missing account IDs")
@@ -701,7 +701,7 @@
break
}
// Send a report
- var ids []int64
+ var ids []madon.ActivityID
ids, err = splitIDs(opt.statusIDs)
if err != nil {
return errors.New("cannot parse status IDs")
@@ -807,17 +807,17 @@
// accountLookupUser tries to find a (single) user matching 'user'
// If the user is an HTTP URL, it will use the search API, else
// it will use the accounts/search API.
-func accountLookupUser(user string) (int64, error) {
- var accID int64
+func accountLookupUser(user string) (madon.ActivityID, error) {
+ var accID madon.ActivityID
if strings.HasPrefix(user, "https://") || strings.HasPrefix(user, "http://") {
res, err := gClient.Search(user, true)
if err != nil {
- return 0, err
+ return "", err
}
if res != nil {
if len(res.Accounts) > 1 {
- return 0, errors.New("several results")
+ return "", errors.New("several results")
}
if len(res.Accounts) == 1 {
accID = res.Accounts[0].ID
@@ -829,7 +829,7 @@
accList, err := gClient.SearchAccounts(user, false, &madon.LimitParams{Limit: 2})
if err != nil {
- return 0, err
+ return "", err
}
for _, u := range accList {
if u.Acct == user {
@@ -839,8 +839,8 @@
}
}
- if accID < 1 {
- return 0, errors.New("user not found")
+ if accID == "" {
+ return "", errors.New("user not found")
}
if verbose {
errPrint("User '%s' is account ID %d", user, user)
--- a/cmd/domainblocks.go Sat Feb 04 11:00:55 2023 +0000
+++ b/cmd/domainblocks.go Sat Feb 04 13:17:17 2023 +0100
@@ -17,9 +17,9 @@
var domainBlocksOpts struct {
show, block, unblock bool
- limit uint // Limit the results
- sinceID, maxID int64 // Query boundaries
- all bool // Try to fetch all results
+ limit uint // Limit the results
+ sinceID, maxID madon.ActivityID // Query boundaries
+ all bool // Try to fetch all results
}
// timelinesCmd represents the timelines command
@@ -41,8 +41,8 @@
domainBlocksCmd.Flags().BoolVar(&domainBlocksOpts.unblock, "unblock", false, "Unblock domain")
domainBlocksCmd.Flags().UintVarP(&domainBlocksOpts.limit, "limit", "l", 0, "Limit number of results")
- domainBlocksCmd.Flags().Int64Var(&domainBlocksOpts.sinceID, "since-id", 0, "Request IDs greater than a value")
- domainBlocksCmd.Flags().Int64Var(&domainBlocksOpts.maxID, "max-id", 0, "Request IDs less (or equal) than a value")
+ domainBlocksCmd.Flags().StringVar(&domainBlocksOpts.sinceID, "since-id", "", "Request IDs greater than a value")
+ domainBlocksCmd.Flags().StringVar(&domainBlocksOpts.maxID, "max-id", "", "Request IDs less (or equal) than a value")
domainBlocksCmd.Flags().BoolVar(&domainBlocksOpts.all, "all", false, "Fetch all results")
}
@@ -71,17 +71,17 @@
// Set up LimitParams
var limOpts *madon.LimitParams
- if opt.all || opt.limit > 0 || opt.sinceID > 0 || opt.maxID > 0 {
+ if opt.all || opt.limit > 0 || opt.sinceID != "" || opt.maxID != "" {
limOpts = new(madon.LimitParams)
limOpts.All = opt.all
}
if opt.limit > 0 {
limOpts.Limit = int(opt.limit)
}
- if opt.maxID > 0 {
+ if opt.maxID != "" {
limOpts.MaxID = opt.maxID
}
- if opt.sinceID > 0 {
+ if opt.sinceID != "" {
limOpts.SinceID = opt.sinceID
}
--- a/cmd/lists.go Sat Feb 04 11:00:55 2023 +0000
+++ b/cmd/lists.go Sat Feb 04 13:17:17 2023 +0100
@@ -15,8 +15,8 @@
)
var listsOpts struct {
- listID int64
- accountID int64
+ listID madon.ActivityID
+ accountID madon.ActivityID
accountIDs string
title string
@@ -51,20 +51,20 @@
listsCmd.PersistentFlags().UintVarP(&listsOpts.keep, "keep", "k", 0, "Limit number of results")
listsCmd.PersistentFlags().BoolVar(&listsOpts.all, "all", false, "Fetch all results")
- listsCmd.PersistentFlags().Int64VarP(&listsOpts.listID, "list-id", "G", 0, "List ID")
+ listsCmd.PersistentFlags().StringVarP(&listsOpts.listID, "list-id", "G", "", "List ID")
- listsGetSubcommand.Flags().Int64VarP(&listsOpts.accountID, "account-id", "a", 0, "Account ID number")
+ listsGetSubcommand.Flags().StringVarP(&listsOpts.accountID, "account-id", "a", "", "Account ID number")
// XXX accountUID?
- listsGetAccountsSubcommand.Flags().Int64VarP(&listsOpts.listID, "list-id", "G", 0, "List ID")
+ listsGetAccountsSubcommand.Flags().StringVarP(&listsOpts.listID, "list-id", "G", "", "List ID")
listsCreateSubcommand.Flags().StringVar(&listsOpts.title, "title", "", "List title")
listsUpdateSubcommand.Flags().StringVar(&listsOpts.title, "title", "", "List title")
listsAddAccountsSubcommand.Flags().StringVar(&listsOpts.accountIDs, "account-ids", "", "Comma-separated list of account IDs")
- listsAddAccountsSubcommand.Flags().Int64VarP(&listsOpts.accountID, "account-id", "a", 0, "Account ID number")
+ listsAddAccountsSubcommand.Flags().StringVarP(&listsOpts.accountID, "account-id", "a", "", "Account ID number")
listsRemoveAccountsSubcommand.Flags().StringVar(&listsOpts.accountIDs, "account-ids", "", "Comma-separated list of account IDs")
- listsRemoveAccountsSubcommand.Flags().Int64VarP(&listsOpts.accountID, "account-id", "a", 0, "Account ID number")
+ listsRemoveAccountsSubcommand.Flags().StringVarP(&listsOpts.accountID, "account-id", "a", "", "Account ID number")
}
var listsSubcommands = []*cobra.Command{
@@ -145,7 +145,7 @@
var obj interface{}
var err error
- if opt.listID > 0 {
+ if opt.listID != "" {
var list *madon.List
list, err = gClient.GetList(opt.listID)
obj = list
@@ -178,7 +178,7 @@
func listsGetAccountsRunE(cmd *cobra.Command, args []string) error {
opt := listsOpts
- if opt.listID <= 0 {
+ if opt.listID == "" {
return errors.New("missing list ID")
}
@@ -237,12 +237,12 @@
switch cmd.Name() {
case "create":
- if opt.listID > 0 {
+ if opt.listID != "" {
return errors.New("list ID should not be provided with create")
}
action = actionCreate
case "update":
- if opt.listID <= 0 {
+ if opt.listID == "" {
return errors.New("list ID is required")
}
action = actionUpdate
@@ -300,19 +300,19 @@
func listsAddRemoveAccountsRunE(cmd *cobra.Command, args []string) error {
opt := listsOpts
- if opt.listID <= 0 {
+ if opt.listID == "" {
return errors.New("missing list ID")
}
- var ids []int64
+ var ids []madon.ActivityID
var err error
ids, err = splitIDs(opt.accountIDs)
if err != nil {
return errors.New("cannot parse account IDs")
}
- if opt.accountID > 0 { // Allow --account-id
- ids = []int64{opt.accountID}
+ if opt.accountID != "" { // Allow --account-id
+ ids = []madon.ActivityID{opt.accountID}
}
if len(ids) < 1 {
return errors.New("missing account IDs")
--- a/cmd/madon.go Sat Feb 04 11:00:55 2023 +0000
+++ b/cmd/madon.go Sat Feb 04 13:17:17 2023 +0100
@@ -6,7 +6,6 @@
package cmd
import (
- "strconv"
"strings"
"github.com/McKael/madon/v3"
@@ -104,18 +103,16 @@
}
// splitIDs splits a list of IDs into an int64 array
-func splitIDs(ids string) (list []int64, err error) {
- var i int64
+func splitIDs(ids string) (list []madon.ActivityID, err error) {
if ids == "" {
return
}
l := strings.Split(ids, ",")
for _, s := range l {
- i, err = strconv.ParseInt(s, 10, 64)
- if err != nil {
+ if s == "" {
return
}
- list = append(list, i)
+ list = append(list, s)
}
return
}
--- a/cmd/media.go Sat Feb 04 11:00:55 2023 +0000
+++ b/cmd/media.go Sat Feb 04 13:17:17 2023 +0100
@@ -18,7 +18,7 @@
var mediaFlags *flag.FlagSet
var mediaOpts struct {
- mediaID int64
+ mediaID madon.ActivityID
filePath string
description string
focus string
@@ -48,7 +48,7 @@
RootCmd.AddCommand(mediaCmd)
mediaCmd.Flags().StringVar(&mediaOpts.filePath, "file", "", "Path of the media file")
- mediaCmd.Flags().Int64Var(&mediaOpts.mediaID, "update", 0, "Media to update (ID)")
+ mediaCmd.Flags().StringVar(&mediaOpts.mediaID, "update", "", "Media to update (ID)")
mediaCmd.Flags().StringVar(&mediaOpts.description, "description", "", "Plain text description")
mediaCmd.Flags().StringVar(&mediaOpts.focus, "focus", "", "Focal point")
@@ -61,10 +61,10 @@
opt := mediaOpts
if opt.filePath == "" {
- if opt.mediaID < 1 {
+ if opt.mediaID == "" {
return errors.New("no media file name provided")
}
- } else if opt.mediaID > 0 {
+ } else if opt.mediaID != "" {
return errors.New("cannot use both --file and --update")
}
@@ -102,13 +102,13 @@
}
// uploadFile uploads a media file and returns the attachment ID
-func uploadFile(filePath string) (int64, error) {
+func uploadFile(filePath string) (madon.ActivityID, error) {
attachment, err := gClient.UploadMedia(filePath, "", "")
if err != nil {
- return 0, err
+ return "", err
}
if attachment == nil {
- return 0, nil
+ return "", nil
}
return attachment.ID, nil
}
--- a/cmd/notifications.go Sat Feb 04 11:00:55 2023 +0000
+++ b/cmd/notifications.go Sat Feb 04 13:17:17 2023 +0100
@@ -17,7 +17,7 @@
var notificationsOpts struct {
list, clear, dismiss bool
- notifID int64
+ notifID madon.ActivityID
types string
excludeTypes string
}
@@ -50,7 +50,7 @@
notificationsCmd.Flags().BoolVar(¬ificationsOpts.list, "list", false, "List all current notifications")
notificationsCmd.Flags().BoolVar(¬ificationsOpts.clear, "clear", false, "Clear all current notifications")
notificationsCmd.Flags().BoolVar(¬ificationsOpts.dismiss, "dismiss", false, "Delete a notification")
- notificationsCmd.Flags().Int64Var(¬ificationsOpts.notifID, "notification-id", 0, "Get a notification")
+ notificationsCmd.Flags().StringVar(¬ificationsOpts.notifID, "notification-id", "", "Get a notification")
notificationsCmd.Flags().StringVar(¬ificationsOpts.types, "notification-types", "", "Filter notifications (mention, favourite, reblog, follow)")
notificationsCmd.Flags().StringVar(¬ificationsOpts.excludeTypes, "exclude-types", "", "Exclude notifications types (mention, favourite, reblog, follow)")
}
@@ -58,7 +58,7 @@
func notificationRunE(cmd *cobra.Command, args []string) error {
opt := notificationsOpts
- if !opt.list && !opt.clear && opt.notifID < 1 {
+ if !opt.list && !opt.clear && opt.notifID == "" {
return errors.New("missing parameters")
}
@@ -67,7 +67,7 @@
}
var limOpts *madon.LimitParams
- if accountsOpts.all || accountsOpts.limit > 0 || accountsOpts.sinceID > 0 || accountsOpts.maxID > 0 {
+ if accountsOpts.all || accountsOpts.limit > 0 || accountsOpts.sinceID != "" || accountsOpts.maxID != "" {
limOpts = new(madon.LimitParams)
limOpts.All = accountsOpts.all
}
@@ -75,11 +75,11 @@
if accountsOpts.limit > 0 {
limOpts.Limit = int(accountsOpts.limit)
}
- if accountsOpts.maxID > 0 {
- limOpts.MaxID = int64(accountsOpts.maxID)
+ if accountsOpts.maxID != "" {
+ limOpts.MaxID = accountsOpts.maxID
}
- if accountsOpts.sinceID > 0 {
- limOpts.SinceID = int64(accountsOpts.sinceID)
+ if accountsOpts.sinceID != "" {
+ limOpts.SinceID = accountsOpts.sinceID
}
var filterMap *map[string]bool
@@ -123,7 +123,7 @@
notifications = notifications[:accountsOpts.keep]
}
obj = notifications
- } else if opt.notifID > 0 {
+ } else if opt.notifID != "" {
if opt.dismiss {
err = gClient.DismissNotification(opt.notifID)
} else {
--- a/cmd/status.go Sat Feb 04 11:00:55 2023 +0000
+++ b/cmd/status.go Sat Feb 04 13:17:17 2023 +0100
@@ -20,14 +20,14 @@
var statusPostFlags *flag.FlagSet
var statusOpts struct {
- statusID int64
+ statusID madon.ActivityID
unset bool // TODO remove eventually?
// The following fields are used for the post/toot command
visibility string
sensitive bool
spoiler string
- inReplyToID int64
+ inReplyToID madon.ActivityID
mediaIDs string
mediaFilePath string
textFilePath string
@@ -39,6 +39,9 @@
limit, keep uint
//sinceID, maxID int64
all bool
+
+ // Used to indicate whether `in-reply-to` flag is present or not.
+ _hasReplyTo bool
}
func init() {
@@ -48,7 +51,7 @@
statusCmd.AddCommand(statusSubcommands...)
// Global flags
- statusCmd.PersistentFlags().Int64VarP(&statusOpts.statusID, "status-id", "s", 0, "Status ID number")
+ statusCmd.PersistentFlags().StringVarP(&statusOpts.statusID, "status-id", "s", "", "Status ID number")
statusCmd.PersistentFlags().UintVarP(&statusOpts.limit, "limit", "l", 0, "Limit number of API results")
statusCmd.PersistentFlags().UintVarP(&statusOpts.keep, "keep", "k", 0, "Limit number of results")
//statusCmd.PersistentFlags().Int64Var(&statusOpts.sinceID, "since-id", 0, "Request IDs greater than a value")
@@ -65,7 +68,7 @@
statusPostSubcommand.Flags().StringVar(&statusOpts.mediaIDs, "media-ids", "", "Comma-separated list of media IDs")
statusPostSubcommand.Flags().StringVarP(&statusOpts.mediaFilePath, "file", "f", "", "Media file name")
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().StringVarP(&statusOpts.inReplyToID, "in-reply-to", "r", "", "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")
statusPostSubcommand.Flags().BoolVar(&statusOpts.sameVisibility, "same-visibility", false, "Use same visibility as original message (for replies)")
@@ -94,7 +97,7 @@
//Long: `TBW...`, // TODO
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
// This is common to status and all status subcommands but "post"
- if statusOpts.statusID < 1 && cmd.Name() != "post" {
+ if statusOpts.statusID == "" && cmd.Name() != "post" {
return errors.New("missing status ID")
}
return madonInit(true)
@@ -241,6 +244,8 @@
The default visibility can be set in the configuration file with the option
'default_visibility' (or with an environmnent variable).`,
RunE: func(cmd *cobra.Command, args []string) error {
+ // Update the extra flag to reflect if `in-reply-to` was present or not
+ statusOpts._hasReplyTo = cmd.Flags().Lookup("in-reply-to").Changed
return statusSubcommandRunE(cmd.Name(), args)
},
}
--- a/cmd/suggestions.go Sat Feb 04 11:00:55 2023 +0000
+++ b/cmd/suggestions.go Sat Feb 04 13:17:17 2023 +0100
@@ -15,7 +15,7 @@
)
var suggestionsOpts struct {
- accountID int64
+ accountID madon.ActivityID
accountIDs string
//limit uint
@@ -41,7 +41,7 @@
suggestionsGetSubcommand.Flags().UintVarP(&suggestionsOpts.keep, "keep", "k", 0, "Limit number of results")
//suggestionsGetSubcommand.Flags().BoolVar(&suggestionsOpts.all, "all", false, "Fetch all results")
- suggestionsDeleteSubcommand.Flags().Int64VarP(&suggestionsOpts.accountID, "account-id", "a", 0, "Account ID number")
+ suggestionsDeleteSubcommand.Flags().StringVarP(&suggestionsOpts.accountID, "account-id", "a", "", "Account ID number")
suggestionsDeleteSubcommand.Flags().StringVar(&suggestionsOpts.accountIDs, "account-ids", "", "Comma-separated list of account IDs")
}
@@ -116,13 +116,13 @@
func suggestionsDeleteRunE(cmd *cobra.Command, args []string) error {
opt := suggestionsOpts
- var ids []int64
+ var ids []madon.ActivityID
var err error
- if opt.accountID < 1 && len(opt.accountIDs) == 0 {
+ if opt.accountID == "" && len(opt.accountIDs) == 0 {
return errors.New("missing account IDs")
}
- if opt.accountID > 0 && len(opt.accountIDs) > 0 {
+ if opt.accountID != "" && len(opt.accountIDs) > 0 {
return errors.New("incompatible options")
}
@@ -130,8 +130,8 @@
if err != nil {
return errors.New("cannot parse account IDs")
}
- if opt.accountID > 0 { // Allow --account-id
- ids = []int64{opt.accountID}
+ if opt.accountID != "" { // Allow --account-id
+ ids = []madon.ActivityID{opt.accountID}
}
if len(ids) < 1 {
return errors.New("missing account IDs")
--- a/cmd/timelines.go Sat Feb 04 11:00:55 2023 +0000
+++ b/cmd/timelines.go Sat Feb 04 13:17:17 2023 +0100
@@ -17,7 +17,7 @@
var timelineOpts struct {
local, onlyMedia bool
limit, keep uint
- sinceID, maxID int64
+ sinceID, maxID madon.ActivityID
}
// timelineCmd represents the timelines command
@@ -47,25 +47,25 @@
timelineCmd.Flags().BoolVar(&timelineOpts.onlyMedia, "only-media", false, "Only statuses with media attachments")
timelineCmd.Flags().UintVarP(&timelineOpts.limit, "limit", "l", 0, "Limit number of API results")
timelineCmd.Flags().UintVarP(&timelineOpts.keep, "keep", "k", 0, "Limit number of results")
- timelineCmd.PersistentFlags().Int64Var(&timelineOpts.sinceID, "since-id", 0, "Request IDs greater than a value")
- timelineCmd.PersistentFlags().Int64Var(&timelineOpts.maxID, "max-id", 0, "Request IDs less (or equal) than a value")
+ timelineCmd.PersistentFlags().StringVar(&timelineOpts.sinceID, "since-id", "", "Request IDs greater than a value")
+ timelineCmd.PersistentFlags().StringVar(&timelineOpts.maxID, "max-id", "", "Request IDs less (or equal) than a value")
}
func timelineRunE(cmd *cobra.Command, args []string) error {
opt := timelineOpts
var limOpts *madon.LimitParams
- if opt.limit > 0 || opt.sinceID > 0 || opt.maxID > 0 {
+ if opt.limit > 0 || opt.sinceID != "" || opt.maxID != "" {
limOpts = new(madon.LimitParams)
}
if opt.limit > 0 {
limOpts.Limit = int(opt.limit)
}
- if opt.maxID > 0 {
+ if opt.maxID != "" {
limOpts.MaxID = opt.maxID
}
- if opt.sinceID > 0 {
+ if opt.sinceID != "" {
limOpts.SinceID = opt.sinceID
}
--- a/cmd/toot.go Sat Feb 04 11:00:55 2023 +0000
+++ b/cmd/toot.go Sat Feb 04 13:17:17 2023 +0100
@@ -29,7 +29,7 @@
tootAliasCmd.Flags().StringVar(&statusOpts.mediaIDs, "media-ids", "", "Comma-separated list of media IDs")
tootAliasCmd.Flags().StringVarP(&statusOpts.mediaFilePath, "file", "f", "", "Media attachment file name")
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().StringVarP(&statusOpts.inReplyToID, "in-reply-to", "r", "", "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")
tootAliasCmd.Flags().BoolVar(&statusOpts.sameVisibility, "same-visibility", false, "Use same visibility as original message (for replies)")
@@ -64,6 +64,8 @@
if err := madonInit(true); err != nil {
return err
}
+ // Update the extra flag to reflect if `in-reply-to` was present or not
+ statusOpts._hasReplyTo = cmd.Flags().Lookup("in-reply-to").Changed
return statusSubcommandRunE("post", args)
},
}
@@ -85,7 +87,12 @@
return nil, errors.Errorf("invalid visibility argument value '%s'", opt.visibility)
}
- if opt.inReplyToID < 0 {
+ // Bit of a fudge but there's no easy way to tell if a string flag
+ // is empty by default or empty by assignment. Can't use a pointer
+ // and have `nil` be "unset" because Cobra will crash if we send it
+ // a `nil` as the recepient for a flag variable. Hence using an
+ // extra struct member as a flag to indicate set/unset.
+ if opt._hasReplyTo && opt.inReplyToID == "" {
return nil, errors.New("invalid in-reply-to argument value")
}
@@ -98,7 +105,7 @@
return nil, errors.New("toot is empty")
}
- if opt.inReplyToID > 0 {
+ if opt.inReplyToID != "" {
var initialStatus *madon.Status
var preserveVis bool
if opt.sameVisibility &&
@@ -143,7 +150,7 @@
if err != nil {
return nil, errors.Wrap(err, "cannot attach media file")
}
- if fileMediaID > 0 {
+ if fileMediaID != "" {
ids = append(ids, fileMediaID)
}
}
--- a/printer/plainprinter.go Sat Feb 04 11:00:55 2023 +0000
+++ b/printer/plainprinter.go Sat Feb 04 13:17:17 2023 +0100
@@ -175,7 +175,7 @@
}
func (p *PlainPrinter) plainPrintAccount(a *madon.Account, w io.Writer, indent string) error {
- indentedPrint(w, indent, true, false, "Account ID", "%d (%s)", a.ID, a.Username)
+ indentedPrint(w, indent, true, false, "Account ID", "%s (%s)", a.ID, a.Username)
indentedPrint(w, indent, false, false, "User ID", "%s", a.Acct)
indentedPrint(w, indent, false, false, "Display name", "%s", a.DisplayName)
indentedPrint(w, indent, false, false, "Creation date", "%v", a.CreatedAt.Local())
@@ -192,7 +192,7 @@
indentedPrint(w, indent, false, true, "User note", "%s", html2string(a.Note)) // XXX too long?
if a.Moved != nil {
m := a.Moved
- indentedPrint(w, indent+p.Indent, true, false, "Moved to account ID", "%d (%s)", m.ID, m.Username)
+ indentedPrint(w, indent+p.Indent, true, false, "Moved to account ID", "%s (%s)", m.ID, m.Username)
indentedPrint(w, indent+p.Indent, false, false, "New user ID", "%s", m.Acct)
indentedPrint(w, indent+p.Indent, false, false, "New display name", "%s", m.DisplayName)
}
@@ -218,7 +218,7 @@
}
func (p *PlainPrinter) plainPrintAttachment(a *madon.Attachment, w io.Writer, indent string) error {
- indentedPrint(w, indent, true, false, "Attachment ID", "%d", a.ID)
+ indentedPrint(w, indent, true, false, "Attachment ID", "%s", a.ID)
indentedPrint(w, indent, false, false, "Type", "%s", a.Type)
indentedPrint(w, indent, false, false, "Local URL", "%s", a.URL)
if a.RemoteURL != nil {
@@ -269,7 +269,7 @@
indentedPrint(w, indent, false, true, "Version", "%s", i.Version)
if i.ContactAccount != nil {
c := i.ContactAccount
- indentedPrint(w, indent+p.Indent, true, false, "Contact account ID", "%d (%s)", c.ID, c.Username)
+ indentedPrint(w, indent+p.Indent, true, false, "Contact account ID", "%s (%s)", c.ID, c.Username)
indentedPrint(w, indent+p.Indent, false, false, "Contact user ID", "%s", c.Acct)
indentedPrint(w, indent+p.Indent, false, false, "Contact display name", "%s", c.DisplayName)
}
@@ -282,17 +282,17 @@
}
func (p *PlainPrinter) plainPrintList(l *madon.List, w io.Writer, indent string) error {
- indentedPrint(w, indent, true, false, "List ID", "%d", l.ID)
+ indentedPrint(w, indent, true, false, "List ID", "%s", l.ID)
indentedPrint(w, indent, false, false, "Title", "%s", l.Title)
return nil
}
func (p *PlainPrinter) plainPrintNotification(n *madon.Notification, w io.Writer, indent string) error {
- indentedPrint(w, indent, true, false, "Notification ID", "%d", n.ID)
+ indentedPrint(w, indent, true, false, "Notification ID", "%s", n.ID)
indentedPrint(w, indent, false, false, "Type", "%s", n.Type)
indentedPrint(w, indent, false, false, "Timestamp", "%v", n.CreatedAt.Local())
if n.Account != nil {
- indentedPrint(w, indent+p.Indent, true, false, "Account", "(%d) @%s - %s",
+ indentedPrint(w, indent+p.Indent, true, false, "Account", "(%s) @%s - %s",
n.Account.ID, n.Account.Acct, n.Account.DisplayName)
}
if n.Status != nil {
@@ -302,7 +302,7 @@
}
func (p *PlainPrinter) plainPrintRelationship(r *madon.Relationship, w io.Writer, indent string) error {
- indentedPrint(w, indent, true, false, "Account ID", "%d", r.ID)
+ indentedPrint(w, indent, true, false, "Account ID", "%s", r.ID)
indentedPrint(w, indent, false, false, "Following", "%v", r.Following)
//indentedPrint(w, indent, false, false, "Showing reblogs", "%v", r.ShowingReblogs)
indentedPrint(w, indent, false, false, "Followed-by", "%v", r.FollowedBy)
@@ -315,7 +315,7 @@
}
func (p *PlainPrinter) plainPrintReport(r *madon.Report, w io.Writer, indent string) error {
- indentedPrint(w, indent, true, false, "Report ID", "%d", r.ID)
+ indentedPrint(w, indent, true, false, "Report ID", "%s", r.ID)
indentedPrint(w, indent, false, false, "Action taken", "%s", r.ActionTaken)
return nil
}
@@ -342,7 +342,7 @@
}
func (p *PlainPrinter) plainPrintStatus(s *madon.Status, w io.Writer, indent string) error {
- indentedPrint(w, indent, true, false, "Status ID", "%d", s.ID)
+ indentedPrint(w, indent, true, false, "Status ID", "%s", s.ID)
if s.Account != nil {
author := s.Account.Acct
if s.Account.DisplayName != "" {
@@ -370,8 +370,8 @@
}
indentedPrint(w, indent, false, false, "Contents", "%s", html2string(s.Content))
- if s.InReplyToID != nil && *s.InReplyToID > 0 {
- indentedPrint(w, indent, false, false, "In-Reply-To", "%d", *s.InReplyToID)
+ if s.InReplyToID != nil && *s.InReplyToID != "" {
+ indentedPrint(w, indent, false, false, "In-Reply-To", "%s", *s.InReplyToID)
}
if s.Reblogged {
indentedPrint(w, indent, false, false, "Reblogged", "%v", s.Reblogged)
@@ -380,7 +380,7 @@
// Display minimum details of attachments
//return p.PrintObj(s.MediaAttachments, w, indent+p.Indent)
for _, a := range s.MediaAttachments {
- indentedPrint(w, indent+p.Indent, true, false, "Attachment ID", "%d", a.ID)
+ indentedPrint(w, indent+p.Indent, true, false, "Attachment ID", "%s", a.ID)
if a.TextURL != nil && *a.TextURL != "" {
indentedPrint(w, indent+p.Indent, true, false, "Text URL", "%s", *a.TextURL)
} else if a.URL != "" {