package cmd import ( "fmt" "code.gitea.io/sdk/gitea" "forgejo.zerova.net/public/fgj-sid/internal/api" "forgejo.zerova.net/public/fgj-sid/internal/config" "github.com/spf13/cobra" ) var notificationCmd = &cobra.Command{ Use: "notification", Aliases: []string{"notifications", "n"}, Short: "Manage user notifications", Long: "List and mark notifications for the authenticated user.", } var notificationListCmd = &cobra.Command{ Use: "list", Aliases: []string{"ls"}, Short: "List notifications", Long: "List notifications for the authenticated user. Shows unread by default.", Example: ` # List unread notifications fgj notification list # Include read and pinned notifications fgj notification list --all # Limit number of results fgj notification list -L 50 # Output as JSON fgj notification list --json`, RunE: runNotificationList, } var notificationReadCmd = &cobra.Command{ Use: "read ", Aliases: []string{"r"}, Short: "Mark a notification as read", Long: "Mark a single notification thread as read by its ID.", Args: cobra.ExactArgs(1), RunE: runNotificationRead, } func init() { rootCmd.AddCommand(notificationCmd) notificationCmd.AddCommand(notificationListCmd) notificationCmd.AddCommand(notificationReadCmd) notificationListCmd.Flags().Bool("all", false, "Include read and pinned notifications (not just unread)") notificationListCmd.Flags().IntP("limit", "L", 30, "Maximum number of notifications to list") addJSONFlags(notificationListCmd, "Output as JSON") } func runNotificationList(cmd *cobra.Command, args []string) error { cfg, err := config.Load() if err != nil { return err } client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd()) if err != nil { return err } all, _ := cmd.Flags().GetBool("all") limit, _ := cmd.Flags().GetInt("limit") if limit <= 0 { limit = 30 } opt := gitea.ListNotificationOptions{ ListOptions: gitea.ListOptions{PageSize: limit}, Status: []gitea.NotifyStatus{gitea.NotifyStatusUnread}, } if all { opt.Status = []gitea.NotifyStatus{gitea.NotifyStatusUnread, gitea.NotifyStatusRead, gitea.NotifyStatusPinned} } threads, _, err := client.ListNotifications(opt) if err != nil { return fmt.Errorf("failed to list notifications: %w", err) } if wantJSON(cmd) { return outputJSON(cmd, threads) } if len(threads) == 0 { fmt.Fprintln(ios.Out, "No notifications.") return nil } tp := ios.NewTablePrinter() tp.AddHeader("ID", "REPO", "TYPE", "STATE", "TITLE") for _, t := range threads { repo := "" if t.Repository != nil { repo = t.Repository.FullName } subjType, subjState, title := "", "", "" if t.Subject != nil { subjType = string(t.Subject.Type) subjState = string(t.Subject.State) title = t.Subject.Title } tp.AddRow(fmt.Sprintf("%d", t.ID), repo, subjType, subjState, title) } return tp.Render() } func runNotificationRead(cmd *cobra.Command, args []string) error { id, err := parseIssueArg(args[0]) if err != nil { return fmt.Errorf("invalid notification id %q: %w", args[0], err) } cfg, err := config.Load() if err != nil { return err } client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd()) if err != nil { return err } if _, _, err := client.ReadNotification(id, gitea.NotifyStatusRead); err != nil { return fmt.Errorf("failed to mark notification %d as read: %w", id, err) } cs := ios.ColorScheme() fmt.Fprintf(ios.Out, "%s Marked notification %d as read\n", cs.SuccessIcon(), id) return nil }