1package admin23import (4 "bytes"5 "database/sql"6 "fmt"7 "io"89 gomail "net/mail"1011 "git.lin.moe/go/mlisting/storage"12 "github.com/emersion/go-mbox"13 "github.com/spf13/cobra"14)1516func init() {17 msgDelCmd := &cobra.Command{18 Use: "delete {group_address} {msg_id ...}",19 Aliases: []string{"del"},20 Short: "delete messages recursive",21 Args: cobra.MatchAll(cobra.MinimumNArgs(2), cobra.OnlyValidArgs),22 RunE: msgDel,23 }24 msgSearchCmd := &cobra.Command{25 Use: "search {group_address} {keyword}",26 Short: "search messages",27 Args: cobra.MatchAll(cobra.RangeArgs(1, 2)),28 RunE: msgSearch,29 }30 msgSearchCmd.Flags().Uint("offset", 0, "messages search offset")31 msgSearchCmd.Flags().Uint("limit", 50, "messages search limit")3233 msgImportCmd := &cobra.Command{34 Use: "import {group_address}",35 Short: "import messages from stdin(mbox)",36 Args: cobra.MatchAll(cobra.ExactArgs(1)),37 RunE: msgImport,38 }3940 msgCmd := &cobra.Command{41 Use: "message",42 Aliases: []string{"msg"},43 Short: "messages management",44 }4546 msgCmd.AddCommand(msgDelCmd)47 msgCmd.AddCommand(msgSearchCmd)48 msgCmd.AddCommand(msgImportCmd)4950 cmd.AddCommand(msgCmd)51}5253func msgDel(cmd *cobra.Command, args []string) error {54 st, ok := storage.FromContext(cmd.Context())55 if !ok {56 return fmt.Errorf("storage not found")57 }58 list, err := st.GetList(cmd.Context(), args[0])59 if err != nil {60 if err == sql.ErrNoRows {61 return fmt.Errorf("not found list %s", args[0])62 }63 return err64 }6566 for _, msg_id := range args[1:] {67 msg, err := list.Message(cmd.Context(), msg_id)68 if err != nil {69 cmd.PrintErrf("query message [%s] failed: %v", msg_id, err)70 continue71 }72 submsgs, err := msg.SubMessages(cmd.Context(), true)73 if err != nil {74 cmd.PrintErrf("query submessage of [%s] failed: %v", msg_id, err)75 continue76 }7778 if !ask(cmd,79 fmt.Sprintf("Delete message [%s] and it's %d submessages, continue? [y/N]",80 msg.Subject(), len(submsgs)), false) {81 continue82 }83 msgs, err := list.DelMessagesRecursive(cmd.Context(), msg)84 if err != nil {85 cmd.PrintErrf("delete message [%s] failed: %v", msg_id, err)86 continue87 }88 for _, msg := range msgs {89 cmd.Printf("deleted message [%s]\n", msg.Subject())90 }91 }9293 return nil94}9596func msgSearch(cmd *cobra.Command, args []string) error {97 st, ok := storage.FromContext(cmd.Context())98 if !ok {99 return fmt.Errorf("storage not found")100 }101 list, err := st.GetList(cmd.Context(), args[0])102 if err != nil {103 if err == sql.ErrNoRows {104 return fmt.Errorf("not found list %s", args[0])105 }106 return err107 }108 offset, _ := cmd.Flags().GetUint("offset")109 limit, _ := cmd.Flags().GetUint("limit")110 var key string = ""111 if len(args) > 1 {112 key = args[1]113 }114115 msgs, _, err := list.Messages(cmd.Context(), false, key, offset, limit)116 if err != nil {117 return err118 }119 cmd.Printf("results %d:\n", len(msgs))120 for _, msg := range msgs {121 header := msg.Header()122 msgID, _ := header.MessageID()123124 cmd.Printf("<%s>: %s\n", msgID, msg.Subject())125 }126127 return nil128}129130func msgImport(cmd *cobra.Command, args []string) error {131 st, ok := storage.FromContext(cmd.Context())132 if !ok {133 return fmt.Errorf("storage not found")134 }135136 list, err := st.GetList(cmd.Context(), args[0])137 if err != nil {138 if err == sql.ErrNoRows {139 return fmt.Errorf("not found list %s", args[0])140 }141 return err142 }143144 box_r := mbox.NewReader(cmd.InOrStdin())145 var msgs []*gomail.Message146 for {147 msg_reader, err := box_r.NextMessage()148 if err != nil {149 if err == io.EOF {150 break151 } else {152 return err153 }154 }155 msg_raw, err := io.ReadAll(msg_reader)156 if err != nil {157 return err158 }159160 msg, err := gomail.ReadMessage(bytes.NewReader(msg_raw))161 if err != nil {162 return err163 }164165 msgs = append(msgs, msg)166 }167168 for i, msg := range msgs {169 subj := msg.Header.Get("Subject")170 body, err := io.ReadAll(msg.Body)171 if err != nil {172 return fmt.Errorf("read message[%d][%s] body: %v", i, subj, err)173 }174175 if _, err = list.AddMessage(cmd.Context(), msg.Header, body); err != nil {176 return fmt.Errorf("add message[%d][%s]: %v", i, subj, err)177 }178 cmd.Printf("[%d]add message [%s]\n", i, subj)179 }180181 return nil182}