# HG changeset patch # User Mikael Berthe # Date 1675513037 -3600 # Node ID 4dd196a4ee7c70d1bf8ad38d5dc58eadcd33b221 # Parent 80973a656b81c7a52c3f716e268d69bdb872ade2# Parent 5b91a65ba95a3ea5d09710834e01ede404ed9cc9 Merge pull request #29 from rjp/fix/support-non-int-ids Update to handle non-int64 IDs committer: GitHub diff -r 80973a656b81 -r 4dd196a4ee7c cmd/accounts.go --- 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) diff -r 80973a656b81 -r 4dd196a4ee7c cmd/domainblocks.go --- 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 } diff -r 80973a656b81 -r 4dd196a4ee7c cmd/lists.go --- 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") diff -r 80973a656b81 -r 4dd196a4ee7c cmd/madon.go --- 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 } diff -r 80973a656b81 -r 4dd196a4ee7c cmd/media.go --- 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 } diff -r 80973a656b81 -r 4dd196a4ee7c cmd/notifications.go --- 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 { diff -r 80973a656b81 -r 4dd196a4ee7c cmd/status.go --- 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) }, } diff -r 80973a656b81 -r 4dd196a4ee7c cmd/suggestions.go --- 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") diff -r 80973a656b81 -r 4dd196a4ee7c cmd/timelines.go --- 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 } diff -r 80973a656b81 -r 4dd196a4ee7c cmd/toot.go --- 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) } } diff -r 80973a656b81 -r 4dd196a4ee7c printer/plainprinter.go --- 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 != "" { diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/.gitignore diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/LICENSE diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/README.md diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/account.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/api.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/app.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/domain.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/emoji.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/endorsements.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/go.mod diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/instance.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/lists.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/login.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/madon.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/media.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/notifications.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/report.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/search.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/status.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/streams.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/suggestions.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/timelines.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/McKael/madon/v3/types.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/fsnotify/fsnotify/system_bsd.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/fsnotify/fsnotify/system_darwin.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/pelletier/go-toml/v2/internal/characters/utf8.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/pelletier/go-toml/v2/unstable/ast.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/pelletier/go-toml/v2/unstable/kind.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/pelletier/go-toml/v2/unstable/parser.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/pelletier/go-toml/v2/unstable/scanner.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/github.com/spf13/viper/watch_unsupported.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s diff -r 80973a656b81 -r 4dd196a4ee7c vendor/golang.org/x/sys/unix/syscall_openbsd_ppc64.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/golang.org/x/sys/unix/syscall_openbsd_riscv64.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/golang.org/x/sys/unix/zerrors_openbsd_ppc64.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/golang.org/x/sys/unix/zerrors_openbsd_riscv64.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s diff -r 80973a656b81 -r 4dd196a4ee7c vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s diff -r 80973a656b81 -r 4dd196a4ee7c vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s diff -r 80973a656b81 -r 4dd196a4ee7c vendor/golang.org/x/sys/unix/zsysctl_openbsd_ppc64.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/golang.org/x/sys/unix/zsysctl_openbsd_riscv64.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/golang.org/x/sys/unix/zsysnum_openbsd_ppc64.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/golang.org/x/sys/unix/zsysnum_openbsd_riscv64.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/golang.org/x/sys/unix/ztypes_openbsd_ppc64.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/golang.org/x/sys/unix/ztypes_openbsd_riscv64.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/golang.org/x/sys/windows/aliases.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/golang.org/x/sys/windows/race.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/golang.org/x/sys/windows/race0.go diff -r 80973a656b81 -r 4dd196a4ee7c vendor/golang.org/x/sys/windows/syscall.go