From 62cfedea55cc414262724a5c37155b3595b24964 Mon Sep 17 00:00:00 2001 From: Kevin Lyda <kevin@lyda.ie> Date: Fri, 16 May 2025 21:50:23 +0100 Subject: [PATCH] Implement MARK and UNMARK --- NOTES.md | 20 ++++++++++---------- folders/messages.go | 28 ++++++++++++++++++++++++++++ repl/command.go | 19 ++++++++----------- repl/messages.go | 34 ++++++++++++++++++++++++++++++++++ storage/queries/standard.sql | 2 +- storage/standard.sql.go | 11 ++++++++--- 6 files changed, 89 insertions(+), 25 deletions(-) diff --git a/NOTES.md b/NOTES.md index 536d4a0..7651e96 100644 --- a/NOTES.md +++ b/NOTES.md @@ -21,23 +21,17 @@ Switch between MAIL and BULLETIN modes? MAIL commands are documented ## Things to do * Run [godoc](http://localhost:6060/) and then review where the help text is lacking. - * ~~Move to a storage layer.~~ * Implement each command. - * Next: folder commands - ~~CREATE~~, ~~REMOVE~~, MODIFY, ~~INDEX~~, ~~SELECT~~ - * Messages: ~~ADD~~, ~~CURRENT~~, ~~DIRECTORY~~, ~~BACK~~, CHANGE, - ~~FIRST~~, ~~NEXT~~, ~~READ~~, ~~DELETE~~ - * Messages edit: CHANGE, REPLY, FORWARD + * Next: folder commands - MODIFY + * Messages edit: CHANGE, REPLY * Moving messages: COPY, MOVE + * Mark messages: MARK, UNMARK * Compound commands: SET and SHOW - make HELP work for them. - * Mail: MAIL, FORWARD, + * Mail: MAIL, FORWARD, RESPOND * Run this.Skew.Safe() before... each command? each write? * Handle broadcast messages - have bulletin watch a directory and display files from it. Then have them delete the file if it's older than 5 minutes (allow for failure) - * Cleanup help output. - * Remove the node/cluster/newsgroup/mailing-list related flags. - * Remove BBOARD references. - * format with `par w72j1` * Database * trigger to limit values for 'visibility'? * Add commands: @@ -46,6 +40,7 @@ Switch between MAIL and BULLETIN modes? MAIL commands are documented * Commands for a local mail system? * Commands to connect to Mattermost or mastodon? * Commands to manage users. + * Handle MARK for SELECT and DIRECTORY. Done: @@ -66,6 +61,11 @@ Done: * ~~this.Folder should be a storage.Folder.~~ * ~~Add some of the early announcements from the sources - see the conversion branch - to the GENERAL folder.~~ + * ~~Move to a storage layer.~~ + * ~~Cleanup help output.~~ + * ~~Remove the node/cluster/newsgroup/mailing-list related flags.~~ + * ~~Remove BBOARD references.~~ + * ~~format with `par w72j1`~~ ## Module links diff --git a/folders/messages.go b/folders/messages.go index d05b8e4..c787c4b 100644 --- a/folders/messages.go +++ b/folders/messages.go @@ -158,3 +158,31 @@ func DeleteAllMessages() error { this.Q.DeleteAllMessages(ctx, this.Folder.Name) return nil } + +// SetMark sets a mark for message(s). +func SetMark(msgids []int64) error { + ctx := storage.Context() + + for _, msgid := range msgids { + this.Q.AddMark(ctx, storage.AddMarkParams{ + Folder: this.Folder.Name, + Login: this.User.Login, + Msgid: msgid, + }) + } + return nil +} + +// UnsetMark sets a mark for message(s). +func UnsetMark(msgids []int64) error { + ctx := storage.Context() + + for _, msgid := range msgids { + this.Q.DeleteMark(ctx, storage.DeleteMarkParams{ + Folder: this.Folder.Name, + Login: this.User.Login, + Msgid: msgid, + }) + } + return nil +} diff --git a/repl/command.go b/repl/command.go index 1552160..5368143 100644 --- a/repl/command.go +++ b/repl/command.go @@ -267,7 +267,7 @@ topic are grouped separately, or to restrict reading of certain messages to specified users. Once created, that message is automatically selected (see information on SELECT command). The commands that can be used to modify the folder's characteristics are: MODIFY, REMOVE, SET -ACCESS, SET BBOARD, SET NODE, and SET SYSTEM. +ACCESS, and SET SYSTEM. Format: CREATE folder-name @@ -703,6 +703,7 @@ information. Format: MARK [message-number or numbers]`, MaxArgs: 1, + Action: ActionMark, }, "UNMARK": { Description: `Sets the current or message-id message as unmarked. @@ -710,6 +711,7 @@ information. Format: UNMARK [message-number or numbers]`, MaxArgs: 1, + Action: ActionUnmark, }, "MODIFY": { Description: `Modifies the database information for the current folder. Only the owner @@ -1324,10 +1326,9 @@ privileged qualifier.`, }, }, "DEFAULT_EXPIRE": { - Description: `Specifies the number of days the message created by BBOARD (or direct -PMDF path) is to be retained. The default is 14 days. The highest -limit that can be specified is 30 days. This can be overridden by a -user with privileges. + Description: `Specifies the number of days the message is to be retained. The default +is 14 days. The highest limit that can be specified is 30 days. This can +be overridden by a user with privileges. This also specifies the default expiration date when adding a message. If no expiration date is entered when prompted for a date, or if @@ -1339,11 +1340,7 @@ used. If -1 is specified, messages will become permanent. If 0 is specified, no default expiration date will be present. The latter should never be -specified for a folder with a BBOARD, or else the messages will -disappear. - -NOTE: This value is the same value that SET BBOARD/EXPIRATION specifies. -If one is changed, the other will change also.`, +specified for a folder or else the messages will disappear.`, MinArgs: 1, MaxArgs: 1, }, @@ -1597,7 +1594,7 @@ the SELECT command, information about that folder is shown. "/FULL": { Description: ` Control whether all information of the folder is displayed. This includes the SYSTEM setting, the access list if the folder is private, - and BBOARD information. This information is only those who have access + and other information. This information is only those who have access to that folder.`, }, }, diff --git a/repl/messages.go b/repl/messages.go index 13b9763..b0cd69c 100644 --- a/repl/messages.go +++ b/repl/messages.go @@ -323,3 +323,37 @@ func ActionDelete(cmd *dclish.Command) error { } return nil } + +// ActionMark handles the `MARK` command. +func ActionMark(cmd *dclish.Command) error { + var err error + msgids := []int64{this.MsgID} + if len(cmd.Args) == 1 { + msgids, err = ParseNumberList(cmd.Args[0]) + if err != nil { + return err + } + } + err = folders.SetMark(msgids) + if err != nil { + fmt.Printf("ERROR: %s.\n", err) + } + return nil +} + +// ActionUnmark handles the `UNMARK` command. +func ActionUnmark(cmd *dclish.Command) error { + var err error + msgids := []int64{this.MsgID} + if len(cmd.Args) == 1 { + msgids, err = ParseNumberList(cmd.Args[0]) + if err != nil { + return err + } + } + err = folders.UnsetMark(msgids) + if err != nil { + fmt.Printf("ERROR: %s.\n", err) + } + return nil +} diff --git a/storage/queries/standard.sql b/storage/queries/standard.sql index 8edc1bb..3af1772 100644 --- a/storage/queries/standard.sql +++ b/storage/queries/standard.sql @@ -59,7 +59,7 @@ DELETE FROM seen WHERE folder = ? AND login = ? AND msgid = ?; INSERT INTO marks (folder, login, msgid) VALUES (?, ?, ?); -- name: ListMark :many -SELECT * FROM marks; +SELECT * FROM marks WHERE folder = ? AND login = ?; -- name: GetMark :one SELECT * FROM marks WHERE folder = ? AND login = ? AND msgid = ?; diff --git a/storage/standard.sql.go b/storage/standard.sql.go index 0c05956..8ddd2c8 100644 --- a/storage/standard.sql.go +++ b/storage/standard.sql.go @@ -508,11 +508,16 @@ func (q *Queries) ListFolders(ctx context.Context) ([]Folder, error) { } const listMark = `-- name: ListMark :many -SELECT login, folder, msgid FROM marks +SELECT login, folder, msgid FROM marks WHERE folder = ? AND login = ? ` -func (q *Queries) ListMark(ctx context.Context) ([]Mark, error) { - rows, err := q.db.QueryContext(ctx, listMark) +type ListMarkParams struct { + Folder string + Login string +} + +func (q *Queries) ListMark(ctx context.Context, arg ListMarkParams) ([]Mark, error) { + rows, err := q.db.QueryContext(ctx, listMark, arg.Folder, arg.Login) if err != nil { return nil, err } -- GitLab