Loading folders/messages.go +43 −2 Original line number Diff line number Diff line Loading @@ -8,8 +8,8 @@ import ( "git.lyda.ie/pp/bulletin/this" ) // CreateMessage creates a new folder. func CreateMessage(author, subject, message, folder string, permanent, shutdown int, expiration *time.Time) error { // CreateMessage creates a new message. func CreateMessage(author, subject, message, folder string, permanent, system, shutdown int, expiration *time.Time) error { ctx := storage.Context() if expiration == nil { days, err := this.Q.GetFolderExpire(ctx, folder) Loading @@ -34,12 +34,53 @@ func CreateMessage(author, subject, message, folder string, permanent, shutdown Subject: subject, Message: message, Permanent: int64(permanent), System: int64(system), Shutdown: int64(shutdown), Expiration: *expiration, }) return err } // CopyMessage copies a message from one folder to another. func CopyMessage(srcFolder, destFolder string, msgid int64) error { ctx := storage.Context() return this.Q.CopyMessage(ctx, destFolder, srcFolder, msgid) } // CopyMessages copies multiple messages from one folder to another. func CopyMessages(srcFolder, destFolder string, msgids []int64) error { for _, msgid := range msgids { if err := CopyMessage(srcFolder, destFolder, msgid); err != nil { return err } } return nil } // ListMessagesSeen lists messages seen by a user in a folder. func ListMessagesSeen(login, folder string) ([]storage.Message, error) { ctx := storage.Context() return this.Q.ListMessagesSeen(ctx, folder, login) } // ListMessagesUnseen lists messages not seen by a user in a folder. func ListMessagesUnseen(login, folder string) ([]storage.Message, error) { ctx := storage.Context() return this.Q.ListMessagesUnseen(ctx, folder, login) } // ListMessagesMarked lists messages marked by a user in a folder. func ListMessagesMarked(login, folder string) ([]storage.Message, error) { ctx := storage.Context() return this.Q.ListMessagesMarked(ctx, folder, login) } // ListMessagesUnmarked lists messages not marked by a user in a folder. func ListMessagesUnmarked(login, folder string) ([]storage.Message, error) { ctx := storage.Context() return this.Q.ListMessagesUnmarked(ctx, folder, login) } // GetMessage reads a message for a user. func GetMessage(login, folder string, msgid int64) (*storage.Message, error) { ctx := storage.Context() Loading repl/folders.go +36 −15 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ import ( "git.lyda.ie/pp/bulletin/ask" "git.lyda.ie/pp/bulletin/dclish" "git.lyda.ie/pp/bulletin/folders" "git.lyda.ie/pp/bulletin/pager" "git.lyda.ie/pp/bulletin/storage" "git.lyda.ie/pp/bulletin/this" ) Loading @@ -17,24 +18,44 @@ import ( // // This originally existed as the subroutine FULL_DIR in bulletin9.for. func ActionIndex(cmd *dclish.Command) error { if cmd.Flags["/RESTART"].Set { this.ReadFirstCall = true } // Check for filter flags - these filter messages in the current folder. var msgs []storage.Message var filterErr error filtered := false if cmd.Flags["/MARKED"].Set { return errors.New("not implemented yet") } if cmd.Flags["/NEW"].Set { return errors.New("not implemented yet") msgs, filterErr = folders.ListMessagesMarked(this.User.Login, this.Folder.Name) filtered = true } else if cmd.Flags["/UNMARKED"].Set { msgs, filterErr = folders.ListMessagesUnmarked(this.User.Login, this.Folder.Name) filtered = true } else if cmd.Flags["/SEEN"].Set { msgs, filterErr = folders.ListMessagesSeen(this.User.Login, this.Folder.Name) filtered = true } else if cmd.Flags["/NEW"].Set || cmd.Flags["/UNSEEN"].Set { msgs, filterErr = folders.ListMessagesUnseen(this.User.Login, this.Folder.Name) filtered = true } if cmd.Flags["/RESTART"].Set { return errors.New("not implemented yet") if filtered { if filterErr != nil { return filterErr } if cmd.Flags["/SEEN"].Set { return errors.New("not implemented yet") if len(msgs) == 0 { fmt.Println("There are no messages matching the filter.") return nil } if cmd.Flags["/UNMARKED"].Set { return errors.New("not implemented yet") buf := strings.Builder{} buf.WriteString(fmt.Sprintf("%4s %-43s %-12s %-10s\n", "#", "Subject", "From", "Date")) for _, msg := range msgs { buf.WriteString(fmt.Sprint(msg.OneLine(false))) } if cmd.Flags["/UNSEEN"].Set { return errors.New("not implemented yet") pager.Pager(buf.String()) return nil } rows, err := folders.ListFolder() Loading repl/messages.go +46 −21 Original line number Diff line number Diff line Loading @@ -89,15 +89,9 @@ func ActionAdd(cmd *dclish.Command) error { if cmd.Flags["/BELL"].Value == "true" { optBell = 1 } if cmd.Flags["/BELL"].Set { fmt.Printf("/BELL is not yet implemented - you set it to %d\n", optBell) } if cmd.Flags["/BROADCAST"].Value == "true" { optBroadcast = 1 } if cmd.Flags["/BROADCAST"].Set { fmt.Printf("/BROADCAST is not yet implemented - you set it to %d\n", optBroadcast) } if cmd.Flags["/EXPIRATION"].Value != "" { // dd-mmm-yyyy, or delta time: dddd exp, err := time.Parse("2006-01-02", cmd.Flags["/EXPIRATION"].Value) Loading @@ -115,18 +109,12 @@ func ActionAdd(cmd *dclish.Command) error { if cmd.Flags["/EXTRACT"].Value == "true" { optExtract = 1 } if cmd.Flags["/EXTRACT"].Set { fmt.Printf("/EXTRACT is not yet implemented - you set it to %d\n", optExtract) } if cmd.Flags["/FOLDER"].Value != "" { optFolder = strings.Split(cmd.Flags["/FOLDER"].Value, ",") } if cmd.Flags["/INDENT"].Value == "true" { optIndent = 1 } if cmd.Flags["/INDENT"].Set { fmt.Printf("/INDENT is not yet implemented - you set it to %d\n", optIndent) } if cmd.Flags["/PERMANENT"].Value == "true" { optPermanent = 1 } Loading @@ -136,18 +124,12 @@ func ActionAdd(cmd *dclish.Command) error { if cmd.Flags["/SIGNATURE"].Value == "true" { optSignature = 1 } if cmd.Flags["/SIGNATURE"].Set { fmt.Printf("/SIGNATURE is not yet implemented - you set it to %d\n", optSignature) } if cmd.Flags["/SUBJECT"].Value != "" { optSubject = cmd.Flags["/SUBJECT"].Value } if cmd.Flags["/SYSTEM"].Value == "true" { optSystem = 1 } if cmd.Flags["/SYSTEM"].Set { fmt.Printf("/SYSTEM is not yet implemented - you set it to %d\n", optSystem) } if len(optFolder) == 0 { optFolder = []string{this.Folder.Name} Loading @@ -171,21 +153,64 @@ func ActionAdd(cmd *dclish.Command) error { if optShutdown == 1 && this.User.Admin == 0 { return errors.New("must be an admin to set shutdown") } if optSystem == 1 { if this.User.Admin == 0 { return errors.New("must be an admin to set /SYSTEM") } if this.Folder.Name != "GENERAL" { return errors.New("/SYSTEM can only be used in the GENERAL folder") } } if optBroadcast == 1 && this.User.Admin == 0 { return errors.New("must be an admin to use /BROADCAST") } // Handle /EXTRACT and /INDENT: prepend current message text. origMsg := "" if optExtract == 1 && this.MsgID > 0 { original, err := folders.GetMessage(this.User.Login, this.Folder.Name, this.MsgID) if err != nil { return err } if optIndent == 1 { origMsg = "> " + strings.Join(strings.Split(original.Message, "\n"), "\n> ") } else { origMsg = original.Message } } message, err := editor.Editor( fmt.Sprintf("Enter message for '%s'...", optSubject), "Edit message", "") origMsg) if err != nil { return err } // Handle /SIGNATURE: append user's signature. if optSignature == 1 { sig, ok := this.User.Signature.(string) if ok && sig != "" { message = message + "\n--\n" + sig } } for i := range optFolder { err = folders.CreateMessage(this.User.Login, optSubject, message, optFolder[i], optPermanent, optShutdown, optExpiration) optFolder[i], optPermanent, optSystem, optShutdown, optExpiration) if err != nil { return err } } // Handle /BROADCAST and /BELL: create broadcast message. if optBroadcast == 1 { err = this.Q.CreateBroadcast(ctx, this.User.Login, int64(optBell), message) if err != nil { return err } } return nil } Loading Loading @@ -591,7 +616,7 @@ func ActionReply(cmd *dclish.Command) error { return nil } err = folders.CreateMessage(this.User.Login, subject, message, this.Folder.Name, 0, 0, nil) message, this.Folder.Name, 0, 0, 0, nil) if err != nil { fmt.Printf("ERROR: CreateMessage failure (%s).\n", err) return nil Loading repl/show.go +32 −14 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ package repl import ( "fmt" "strings" "time" "github.com/carlmjohnson/versioninfo" Loading Loading @@ -148,22 +149,21 @@ func ActionShowUser(cmd *dclish.Command) error { } } } /* TODO: need to add this. var since time.Time var err error hasSince := false if cmd.Flags["/SINCE"].Value != "" { if cmd.Flags["/LOGIN"].Set || cmd.Flags["/FOLDER"].Set { fmt.Println("ERROR: Must set /[NO]LOGIN or /FOLDER.") fmt.Println("ERROR: Can't use /SINCE with /LOGIN or /FOLDER.") return nil } var err error since, err = ParseDate(cmd.Flags["/SINCE"].Value) if err != nil { fmt.Println("ERROR: Invalid date specified.") return nil } hasSince = true } */ // Actually do the thing. ctx := storage.Context() Loading Loading @@ -205,6 +205,16 @@ func ActionShowUser(cmd *dclish.Command) error { for _, r := range rows { fmt.Printf("%-12s %s\n", r.Login, r.LastLogin.Format("2006-01-02 15:04:05")) } } else if cmd.Flags["/ALL"].Set && hasSince { rows, err := this.Q.GetLastLoginSince(ctx, since) if err != nil { fmt.Printf("ERROR: Failed to get list (%s).\n", err) return nil } fmt.Println("User Last Login") for _, r := range rows { fmt.Printf("%-12s %s\n", r.Login, r.LastLogin.Format("2006-01-02 15:04:05")) } } else if cmd.Flags["/ALL"].Set { rows, err := this.Q.GetLastLogin(ctx) if err != nil { Loading @@ -215,6 +225,14 @@ func ActionShowUser(cmd *dclish.Command) error { for _, r := range rows { fmt.Printf("%-12s %s\n", r.Login, r.LastLogin.Format("2006-01-02 15:04:05")) } } else if hasSince { r, err := this.Q.GetLastLoginByLoginSince(ctx, login, since) if err != nil { fmt.Printf("ERROR: Failed to get list (%s).\n", err) return nil } fmt.Println("User Last Login") fmt.Printf("%-12s %s\n", r.Login, r.LastLogin.Format("2006-01-02 15:04:05")) } else { r, err := this.Q.GetLastLoginByLogin(ctx, login) if err != nil { Loading repl/xfer.go +86 −16 Original line number Diff line number Diff line package repl import ( "errors" "fmt" "git.lyda.ie/pp/bulletin/dclish" "git.lyda.ie/pp/bulletin/folders" "git.lyda.ie/pp/bulletin/storage" "git.lyda.ie/pp/bulletin/this" ) // ActionCopy handles the `COPY` command. func ActionCopy(cmd *dclish.Command) error { ctx := storage.Context() folder := cmd.Args[0] destFolder, err := folders.FindFolder(folder) if err != nil || destFolder.Name == "" { return errors.New("destination folder does not exist") } writable, err := folders.IsFolderWriteable(destFolder.Name, this.User.Login) if err != nil { return err } if !writable { return errors.New("no write access to destination folder") } if cmd.Flags["/MERGE"].Set { fmt.Println("Warning: /MERGE is not yet implemented, messages will be appended.") } if cmd.Flags["/ORIGINAL"].Set { fmt.Println("Warning: /ORIGINAL is not yet implemented, messages will be owned by the copier.") } msgids := []int64{this.MsgID} if cmd.Flags["/ALL"].Value == "true" { if len(cmd.Args) == 2 { var err error return errors.New("can't provide a message list and /ALL") } msgids, err = this.Q.ListMessageIDs(ctx, this.Folder.Name) if err != nil { return err } } else if len(cmd.Args) == 2 { msgids, err = ParseNumberList(cmd.Args[1]) if err != nil { return err } } fmt.Printf("copy %+v to %s is not implemented\n", msgids, folder) /* msg, err := folders.ReadMessage(this.User.Login, this.Folder.Name, msgid) err = folders.CopyMessages(this.Folder.Name, destFolder.Name, msgids) if err != nil { return err } */ fmt.Printf("%d message(s) copied to %s.\n", len(msgids), destFolder.Name) return nil } // ActionMove handles the `MOVE` command. func ActionMove(cmd *dclish.Command) error { ctx := storage.Context() folder := cmd.Args[0] destFolder, err := folders.FindFolder(folder) if err != nil || destFolder.Name == "" { return errors.New("destination folder does not exist") } writable, err := folders.IsFolderWriteable(destFolder.Name, this.User.Login) if err != nil { return err } if !writable { return errors.New("no write access to destination folder") } // Check write access on source folder for deletion. srcWritable, err := folders.IsFolderWriteable(this.Folder.Name, this.User.Login) if err != nil { return err } if !srcWritable { return errors.New("no write access to source folder") } if cmd.Flags["/MERGE"].Set { fmt.Println("Warning: /MERGE is not yet implemented, messages will be appended.") } if cmd.Flags["/ORIGINAL"].Set { fmt.Println("Warning: /ORIGINAL is not yet implemented, messages will be owned by the mover.") } msgids := []int64{this.MsgID} if cmd.Flags["/ALL"].Value == "true" { if len(cmd.Args) == 2 { var err error return errors.New("can't provide a message list and /ALL") } msgids, err = this.Q.ListMessageIDs(ctx, this.Folder.Name) if err != nil { return err } } else if len(cmd.Args) == 2 { msgids, err = ParseNumberList(cmd.Args[1]) if err != nil { return err } } fmt.Printf("move %+v to %s is not implemented\n", msgids, folder) /* msg, err := folders.ReadMessage(this.User.Login, this.Folder.Name, msgid) err = folders.CopyMessages(this.Folder.Name, destFolder.Name, msgids) if err != nil { return err } err = folders.DeleteMessages(msgids) if err != nil { return err } */ fmt.Printf("%d message(s) moved to %s.\n", len(msgids), destFolder.Name) return nil } Loading
folders/messages.go +43 −2 Original line number Diff line number Diff line Loading @@ -8,8 +8,8 @@ import ( "git.lyda.ie/pp/bulletin/this" ) // CreateMessage creates a new folder. func CreateMessage(author, subject, message, folder string, permanent, shutdown int, expiration *time.Time) error { // CreateMessage creates a new message. func CreateMessage(author, subject, message, folder string, permanent, system, shutdown int, expiration *time.Time) error { ctx := storage.Context() if expiration == nil { days, err := this.Q.GetFolderExpire(ctx, folder) Loading @@ -34,12 +34,53 @@ func CreateMessage(author, subject, message, folder string, permanent, shutdown Subject: subject, Message: message, Permanent: int64(permanent), System: int64(system), Shutdown: int64(shutdown), Expiration: *expiration, }) return err } // CopyMessage copies a message from one folder to another. func CopyMessage(srcFolder, destFolder string, msgid int64) error { ctx := storage.Context() return this.Q.CopyMessage(ctx, destFolder, srcFolder, msgid) } // CopyMessages copies multiple messages from one folder to another. func CopyMessages(srcFolder, destFolder string, msgids []int64) error { for _, msgid := range msgids { if err := CopyMessage(srcFolder, destFolder, msgid); err != nil { return err } } return nil } // ListMessagesSeen lists messages seen by a user in a folder. func ListMessagesSeen(login, folder string) ([]storage.Message, error) { ctx := storage.Context() return this.Q.ListMessagesSeen(ctx, folder, login) } // ListMessagesUnseen lists messages not seen by a user in a folder. func ListMessagesUnseen(login, folder string) ([]storage.Message, error) { ctx := storage.Context() return this.Q.ListMessagesUnseen(ctx, folder, login) } // ListMessagesMarked lists messages marked by a user in a folder. func ListMessagesMarked(login, folder string) ([]storage.Message, error) { ctx := storage.Context() return this.Q.ListMessagesMarked(ctx, folder, login) } // ListMessagesUnmarked lists messages not marked by a user in a folder. func ListMessagesUnmarked(login, folder string) ([]storage.Message, error) { ctx := storage.Context() return this.Q.ListMessagesUnmarked(ctx, folder, login) } // GetMessage reads a message for a user. func GetMessage(login, folder string, msgid int64) (*storage.Message, error) { ctx := storage.Context() Loading
repl/folders.go +36 −15 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ import ( "git.lyda.ie/pp/bulletin/ask" "git.lyda.ie/pp/bulletin/dclish" "git.lyda.ie/pp/bulletin/folders" "git.lyda.ie/pp/bulletin/pager" "git.lyda.ie/pp/bulletin/storage" "git.lyda.ie/pp/bulletin/this" ) Loading @@ -17,24 +18,44 @@ import ( // // This originally existed as the subroutine FULL_DIR in bulletin9.for. func ActionIndex(cmd *dclish.Command) error { if cmd.Flags["/RESTART"].Set { this.ReadFirstCall = true } // Check for filter flags - these filter messages in the current folder. var msgs []storage.Message var filterErr error filtered := false if cmd.Flags["/MARKED"].Set { return errors.New("not implemented yet") } if cmd.Flags["/NEW"].Set { return errors.New("not implemented yet") msgs, filterErr = folders.ListMessagesMarked(this.User.Login, this.Folder.Name) filtered = true } else if cmd.Flags["/UNMARKED"].Set { msgs, filterErr = folders.ListMessagesUnmarked(this.User.Login, this.Folder.Name) filtered = true } else if cmd.Flags["/SEEN"].Set { msgs, filterErr = folders.ListMessagesSeen(this.User.Login, this.Folder.Name) filtered = true } else if cmd.Flags["/NEW"].Set || cmd.Flags["/UNSEEN"].Set { msgs, filterErr = folders.ListMessagesUnseen(this.User.Login, this.Folder.Name) filtered = true } if cmd.Flags["/RESTART"].Set { return errors.New("not implemented yet") if filtered { if filterErr != nil { return filterErr } if cmd.Flags["/SEEN"].Set { return errors.New("not implemented yet") if len(msgs) == 0 { fmt.Println("There are no messages matching the filter.") return nil } if cmd.Flags["/UNMARKED"].Set { return errors.New("not implemented yet") buf := strings.Builder{} buf.WriteString(fmt.Sprintf("%4s %-43s %-12s %-10s\n", "#", "Subject", "From", "Date")) for _, msg := range msgs { buf.WriteString(fmt.Sprint(msg.OneLine(false))) } if cmd.Flags["/UNSEEN"].Set { return errors.New("not implemented yet") pager.Pager(buf.String()) return nil } rows, err := folders.ListFolder() Loading
repl/messages.go +46 −21 Original line number Diff line number Diff line Loading @@ -89,15 +89,9 @@ func ActionAdd(cmd *dclish.Command) error { if cmd.Flags["/BELL"].Value == "true" { optBell = 1 } if cmd.Flags["/BELL"].Set { fmt.Printf("/BELL is not yet implemented - you set it to %d\n", optBell) } if cmd.Flags["/BROADCAST"].Value == "true" { optBroadcast = 1 } if cmd.Flags["/BROADCAST"].Set { fmt.Printf("/BROADCAST is not yet implemented - you set it to %d\n", optBroadcast) } if cmd.Flags["/EXPIRATION"].Value != "" { // dd-mmm-yyyy, or delta time: dddd exp, err := time.Parse("2006-01-02", cmd.Flags["/EXPIRATION"].Value) Loading @@ -115,18 +109,12 @@ func ActionAdd(cmd *dclish.Command) error { if cmd.Flags["/EXTRACT"].Value == "true" { optExtract = 1 } if cmd.Flags["/EXTRACT"].Set { fmt.Printf("/EXTRACT is not yet implemented - you set it to %d\n", optExtract) } if cmd.Flags["/FOLDER"].Value != "" { optFolder = strings.Split(cmd.Flags["/FOLDER"].Value, ",") } if cmd.Flags["/INDENT"].Value == "true" { optIndent = 1 } if cmd.Flags["/INDENT"].Set { fmt.Printf("/INDENT is not yet implemented - you set it to %d\n", optIndent) } if cmd.Flags["/PERMANENT"].Value == "true" { optPermanent = 1 } Loading @@ -136,18 +124,12 @@ func ActionAdd(cmd *dclish.Command) error { if cmd.Flags["/SIGNATURE"].Value == "true" { optSignature = 1 } if cmd.Flags["/SIGNATURE"].Set { fmt.Printf("/SIGNATURE is not yet implemented - you set it to %d\n", optSignature) } if cmd.Flags["/SUBJECT"].Value != "" { optSubject = cmd.Flags["/SUBJECT"].Value } if cmd.Flags["/SYSTEM"].Value == "true" { optSystem = 1 } if cmd.Flags["/SYSTEM"].Set { fmt.Printf("/SYSTEM is not yet implemented - you set it to %d\n", optSystem) } if len(optFolder) == 0 { optFolder = []string{this.Folder.Name} Loading @@ -171,21 +153,64 @@ func ActionAdd(cmd *dclish.Command) error { if optShutdown == 1 && this.User.Admin == 0 { return errors.New("must be an admin to set shutdown") } if optSystem == 1 { if this.User.Admin == 0 { return errors.New("must be an admin to set /SYSTEM") } if this.Folder.Name != "GENERAL" { return errors.New("/SYSTEM can only be used in the GENERAL folder") } } if optBroadcast == 1 && this.User.Admin == 0 { return errors.New("must be an admin to use /BROADCAST") } // Handle /EXTRACT and /INDENT: prepend current message text. origMsg := "" if optExtract == 1 && this.MsgID > 0 { original, err := folders.GetMessage(this.User.Login, this.Folder.Name, this.MsgID) if err != nil { return err } if optIndent == 1 { origMsg = "> " + strings.Join(strings.Split(original.Message, "\n"), "\n> ") } else { origMsg = original.Message } } message, err := editor.Editor( fmt.Sprintf("Enter message for '%s'...", optSubject), "Edit message", "") origMsg) if err != nil { return err } // Handle /SIGNATURE: append user's signature. if optSignature == 1 { sig, ok := this.User.Signature.(string) if ok && sig != "" { message = message + "\n--\n" + sig } } for i := range optFolder { err = folders.CreateMessage(this.User.Login, optSubject, message, optFolder[i], optPermanent, optShutdown, optExpiration) optFolder[i], optPermanent, optSystem, optShutdown, optExpiration) if err != nil { return err } } // Handle /BROADCAST and /BELL: create broadcast message. if optBroadcast == 1 { err = this.Q.CreateBroadcast(ctx, this.User.Login, int64(optBell), message) if err != nil { return err } } return nil } Loading Loading @@ -591,7 +616,7 @@ func ActionReply(cmd *dclish.Command) error { return nil } err = folders.CreateMessage(this.User.Login, subject, message, this.Folder.Name, 0, 0, nil) message, this.Folder.Name, 0, 0, 0, nil) if err != nil { fmt.Printf("ERROR: CreateMessage failure (%s).\n", err) return nil Loading
repl/show.go +32 −14 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ package repl import ( "fmt" "strings" "time" "github.com/carlmjohnson/versioninfo" Loading Loading @@ -148,22 +149,21 @@ func ActionShowUser(cmd *dclish.Command) error { } } } /* TODO: need to add this. var since time.Time var err error hasSince := false if cmd.Flags["/SINCE"].Value != "" { if cmd.Flags["/LOGIN"].Set || cmd.Flags["/FOLDER"].Set { fmt.Println("ERROR: Must set /[NO]LOGIN or /FOLDER.") fmt.Println("ERROR: Can't use /SINCE with /LOGIN or /FOLDER.") return nil } var err error since, err = ParseDate(cmd.Flags["/SINCE"].Value) if err != nil { fmt.Println("ERROR: Invalid date specified.") return nil } hasSince = true } */ // Actually do the thing. ctx := storage.Context() Loading Loading @@ -205,6 +205,16 @@ func ActionShowUser(cmd *dclish.Command) error { for _, r := range rows { fmt.Printf("%-12s %s\n", r.Login, r.LastLogin.Format("2006-01-02 15:04:05")) } } else if cmd.Flags["/ALL"].Set && hasSince { rows, err := this.Q.GetLastLoginSince(ctx, since) if err != nil { fmt.Printf("ERROR: Failed to get list (%s).\n", err) return nil } fmt.Println("User Last Login") for _, r := range rows { fmt.Printf("%-12s %s\n", r.Login, r.LastLogin.Format("2006-01-02 15:04:05")) } } else if cmd.Flags["/ALL"].Set { rows, err := this.Q.GetLastLogin(ctx) if err != nil { Loading @@ -215,6 +225,14 @@ func ActionShowUser(cmd *dclish.Command) error { for _, r := range rows { fmt.Printf("%-12s %s\n", r.Login, r.LastLogin.Format("2006-01-02 15:04:05")) } } else if hasSince { r, err := this.Q.GetLastLoginByLoginSince(ctx, login, since) if err != nil { fmt.Printf("ERROR: Failed to get list (%s).\n", err) return nil } fmt.Println("User Last Login") fmt.Printf("%-12s %s\n", r.Login, r.LastLogin.Format("2006-01-02 15:04:05")) } else { r, err := this.Q.GetLastLoginByLogin(ctx, login) if err != nil { Loading
repl/xfer.go +86 −16 Original line number Diff line number Diff line package repl import ( "errors" "fmt" "git.lyda.ie/pp/bulletin/dclish" "git.lyda.ie/pp/bulletin/folders" "git.lyda.ie/pp/bulletin/storage" "git.lyda.ie/pp/bulletin/this" ) // ActionCopy handles the `COPY` command. func ActionCopy(cmd *dclish.Command) error { ctx := storage.Context() folder := cmd.Args[0] destFolder, err := folders.FindFolder(folder) if err != nil || destFolder.Name == "" { return errors.New("destination folder does not exist") } writable, err := folders.IsFolderWriteable(destFolder.Name, this.User.Login) if err != nil { return err } if !writable { return errors.New("no write access to destination folder") } if cmd.Flags["/MERGE"].Set { fmt.Println("Warning: /MERGE is not yet implemented, messages will be appended.") } if cmd.Flags["/ORIGINAL"].Set { fmt.Println("Warning: /ORIGINAL is not yet implemented, messages will be owned by the copier.") } msgids := []int64{this.MsgID} if cmd.Flags["/ALL"].Value == "true" { if len(cmd.Args) == 2 { var err error return errors.New("can't provide a message list and /ALL") } msgids, err = this.Q.ListMessageIDs(ctx, this.Folder.Name) if err != nil { return err } } else if len(cmd.Args) == 2 { msgids, err = ParseNumberList(cmd.Args[1]) if err != nil { return err } } fmt.Printf("copy %+v to %s is not implemented\n", msgids, folder) /* msg, err := folders.ReadMessage(this.User.Login, this.Folder.Name, msgid) err = folders.CopyMessages(this.Folder.Name, destFolder.Name, msgids) if err != nil { return err } */ fmt.Printf("%d message(s) copied to %s.\n", len(msgids), destFolder.Name) return nil } // ActionMove handles the `MOVE` command. func ActionMove(cmd *dclish.Command) error { ctx := storage.Context() folder := cmd.Args[0] destFolder, err := folders.FindFolder(folder) if err != nil || destFolder.Name == "" { return errors.New("destination folder does not exist") } writable, err := folders.IsFolderWriteable(destFolder.Name, this.User.Login) if err != nil { return err } if !writable { return errors.New("no write access to destination folder") } // Check write access on source folder for deletion. srcWritable, err := folders.IsFolderWriteable(this.Folder.Name, this.User.Login) if err != nil { return err } if !srcWritable { return errors.New("no write access to source folder") } if cmd.Flags["/MERGE"].Set { fmt.Println("Warning: /MERGE is not yet implemented, messages will be appended.") } if cmd.Flags["/ORIGINAL"].Set { fmt.Println("Warning: /ORIGINAL is not yet implemented, messages will be owned by the mover.") } msgids := []int64{this.MsgID} if cmd.Flags["/ALL"].Value == "true" { if len(cmd.Args) == 2 { var err error return errors.New("can't provide a message list and /ALL") } msgids, err = this.Q.ListMessageIDs(ctx, this.Folder.Name) if err != nil { return err } } else if len(cmd.Args) == 2 { msgids, err = ParseNumberList(cmd.Args[1]) if err != nil { return err } } fmt.Printf("move %+v to %s is not implemented\n", msgids, folder) /* msg, err := folders.ReadMessage(this.User.Login, this.Folder.Name, msgid) err = folders.CopyMessages(this.Folder.Name, destFolder.Name, msgids) if err != nil { return err } err = folders.DeleteMessages(msgids) if err != nil { return err } */ fmt.Printf("%d message(s) moved to %s.\n", len(msgids), destFolder.Name) return nil }