NeoMutt  2023-05-17-56-ga67199
Teaching an old dog new tricks
DOXYGEN
score.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <stdbool.h>
31#include <stdlib.h>
32#include "mutt/lib.h"
33#include "config/lib.h"
34#include "email/lib.h"
35#include "core/lib.h"
36#include "mutt.h"
37#include "score.h"
38#include "index/lib.h"
39#include "parse/lib.h"
40#include "pattern/lib.h"
41#include "globals.h" // IWYU pragma: keep
42#include "mutt_thread.h"
43#include "protos.h"
44
48struct Score
49{
50 char *str;
51 struct PatternList *pat;
52 int val;
53 bool exact;
54 struct Score *next;
55};
56
58static struct Score *ScoreList = NULL;
59
65{
66 const bool c_score = cs_subset_bool(NeoMutt->sub, "score");
67 if (OptNeedRescore && c_score)
68 {
69 const enum SortType c_sort = cs_subset_sort(NeoMutt->sub, "sort");
70 const enum SortType c_sort_aux = cs_subset_sort(NeoMutt->sub, "sort_aux");
71 if (((c_sort & SORT_MASK) == SORT_SCORE) || ((c_sort_aux & SORT_MASK) == SORT_SCORE))
72 {
73 OptNeedResort = true;
75 OptSortSubthreads = true;
76 }
77
78 mutt_debug(LL_NOTIFY, "NT_SCORE: %p\n", m);
79 notify_send(m->notify, NT_SCORE, 0, NULL);
80 }
81 OptNeedRescore = false;
82}
83
87enum CommandResult mutt_parse_score(struct Buffer *buf, struct Buffer *s,
88 intptr_t data, struct Buffer *err)
89{
90 struct Score *ptr = NULL, *last = NULL;
91 char *pattern = NULL, *pc = NULL;
92
94 if (!MoreArgs(s))
95 {
96 buf_printf(err, _("%s: too few arguments"), "score");
97 return MUTT_CMD_WARNING;
98 }
99 pattern = buf_strdup(buf);
101 if (MoreArgs(s))
102 {
103 FREE(&pattern);
104 buf_printf(err, _("%s: too many arguments"), "score");
105 return MUTT_CMD_WARNING;
106 }
107
108 /* look for an existing entry and update the value, else add it to the end
109 * of the list */
110 for (ptr = ScoreList, last = NULL; ptr; last = ptr, ptr = ptr->next)
111 if (mutt_str_equal(pattern, ptr->str))
112 break;
113
114 if (ptr)
115 {
116 /* 'buf' arg was cleared and 'pattern' holds the only reference;
117 * as here 'ptr' != NULL -> update the value only in which case
118 * ptr->str already has the string, so pattern should be freed. */
119 FREE(&pattern);
120 }
121 else
122 {
123 struct MailboxView *mv_cur = get_current_mailbox_view();
124 struct Menu *menu = get_current_menu();
125 struct PatternList *pat = mutt_pattern_comp(mv_cur, menu, pattern, MUTT_PC_NO_FLAGS, err);
126 if (!pat)
127 {
128 FREE(&pattern);
129 return MUTT_CMD_ERROR;
130 }
131 ptr = mutt_mem_calloc(1, sizeof(struct Score));
132 if (last)
133 last->next = ptr;
134 else
135 ScoreList = ptr;
136 ptr->pat = pat;
137 ptr->str = pattern;
138 }
139 pc = buf->data;
140 if (*pc == '=')
141 {
142 ptr->exact = true;
143 pc++;
144 }
145 if (!mutt_str_atoi_full(pc, &ptr->val))
146 {
147 FREE(&pattern);
148 buf_strcpy(err, _("Error: score: invalid number"));
149 return MUTT_CMD_ERROR;
150 }
151 OptNeedRescore = true;
152 return MUTT_CMD_SUCCESS;
153}
154
161void mutt_score_message(struct Mailbox *m, struct Email *e, bool upd_mbox)
162{
163 struct Score *tmp = NULL;
164 struct PatternCache cache = { 0 };
165
166 e->score = 0; /* in case of re-scoring */
167 for (tmp = ScoreList; tmp; tmp = tmp->next)
168 {
169 if (mutt_pattern_exec(SLIST_FIRST(tmp->pat), MUTT_MATCH_FULL_ADDRESS, NULL, e, &cache) > 0)
170 {
171 if (tmp->exact || (tmp->val == 9999) || (tmp->val == -9999))
172 {
173 e->score = tmp->val;
174 break;
175 }
176 e->score += tmp->val;
177 }
178 }
179 if (e->score < 0)
180 e->score = 0;
181
182 const short c_score_threshold_delete = cs_subset_number(NeoMutt->sub, "score_threshold_delete");
183 const short c_score_threshold_flag = cs_subset_number(NeoMutt->sub, "score_threshold_flag");
184 const short c_score_threshold_read = cs_subset_number(NeoMutt->sub, "score_threshold_read");
185
186 if (e->score <= c_score_threshold_delete)
187 mutt_set_flag(m, e, MUTT_DELETE, true, upd_mbox);
188 if (e->score <= c_score_threshold_read)
189 mutt_set_flag(m, e, MUTT_READ, true, upd_mbox);
190 if (e->score >= c_score_threshold_flag)
191 mutt_set_flag(m, e, MUTT_FLAG, true, upd_mbox);
192}
193
197enum CommandResult mutt_parse_unscore(struct Buffer *buf, struct Buffer *s,
198 intptr_t data, struct Buffer *err)
199{
200 struct Score *tmp = NULL, *last = NULL;
201
202 while (MoreArgs(s))
203 {
205 if (mutt_str_equal("*", buf->data))
206 {
207 for (tmp = ScoreList; tmp;)
208 {
209 last = tmp;
210 tmp = tmp->next;
211 mutt_pattern_free(&last->pat);
212 FREE(&last);
213 }
214 ScoreList = NULL;
215 }
216 else
217 {
218 for (tmp = ScoreList; tmp; last = tmp, tmp = tmp->next)
219 {
220 if (mutt_str_equal(buf->data, tmp->str))
221 {
222 if (last)
223 last->next = tmp->next;
224 else
225 ScoreList = tmp->next;
226 mutt_pattern_free(&tmp->pat);
227 FREE(&tmp);
228 /* there should only be one score per pattern, so we can stop here */
229 break;
230 }
231 }
232 }
233 }
234 OptNeedRescore = true;
235 return MUTT_CMD_SUCCESS;
236}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:173
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:401
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:536
CommandResult
Error codes for command_t parse functions.
Definition: command.h:36
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition: command.h:39
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition: command.h:37
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition: command.h:38
struct PatternList * mutt_pattern_comp(struct MailboxView *mv, struct Menu *menu, const char *s, PatternCompFlags flags, struct Buffer *err)
Create a Pattern.
Definition: compile.c:905
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition: compile.c:777
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
Structs that make up an email.
bool mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: exec.c:1133
int parse_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: extract.c:47
#define MoreArgs(buf)
Definition: extract.h:30
#define TOKEN_NO_FLAGS
No flags are set.
Definition: extract.h:44
void mutt_set_flag(struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool upd_mbox)
Set a flag on an email.
Definition: flags.c:52
bool OptNeedRescore
(pseudo) set when the 'score' command is used
Definition: globals.c:76
bool OptSortSubthreads
(pseudo) used when $sort_aux changes
Definition: globals.c:88
bool OptNeedResort
(pseudo) used to force a re-sort
Definition: globals.c:77
Global variables.
enum CommandResult mutt_parse_unscore(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'unscore' command - Implements Command::parse() -.
Definition: score.c:197
enum CommandResult mutt_parse_score(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'score' command - Implements Command::parse() -.
Definition: score.c:87
#define mutt_debug(LEVEL,...)
Definition: logging2.h:87
GUI manage the main index (list of emails)
struct MailboxView * get_current_mailbox_view(void)
Get the current Mailbox view.
Definition: index.c:630
struct Menu * get_current_menu(void)
Get the current Menu.
Definition: index.c:678
@ LL_NOTIFY
Log of notifications.
Definition: logging2.h:48
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define FREE(x)
Definition: memory.h:43
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:171
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
Many unsorted constants and some structs.
@ MUTT_READ
Messages that have been read.
Definition: mutt.h:81
@ MUTT_FLAG
Flagged messages.
Definition: mutt.h:87
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:83
Create/manipulate threading in emails.
#define mutt_using_threads()
Definition: mutt_thread.h:112
@ NT_SCORE
Email scoring has changed.
Definition: notify_type.h:53
Text parsing functions.
Match patterns to emails.
#define MUTT_PC_NO_FLAGS
No flags are set.
Definition: lib.h:62
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: lib.h:100
Prototypes for many functions.
#define SLIST_FIRST(head)
Definition: queue.h:229
void mutt_check_rescore(struct Mailbox *m)
Do the emails need to have their scores recalculated?
Definition: score.c:64
static struct Score * ScoreList
Linked list of email scoring rules.
Definition: score.c:58
void mutt_score_message(struct Mailbox *m, struct Email *e, bool upd_mbox)
Apply scoring to an email.
Definition: score.c:161
Routines for adding user scores to emails.
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:74
SortType
Methods for sorting.
Definition: sort2.h:38
@ SORT_SCORE
Sort by the email's score.
Definition: sort2.h:48
String manipulation buffer.
Definition: buffer.h:34
char * data
Pointer to data.
Definition: buffer.h:35
The envelope/body of an email.
Definition: email.h:37
int score
Message score.
Definition: email.h:112
View of a Mailbox.
Definition: mview.h:39
A mailbox.
Definition: mailbox.h:79
struct Notify * notify
Notifications: NotifyMailbox, EventMailbox.
Definition: mailbox.h:143
Definition: lib.h:70
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Cache commonly-used patterns.
Definition: lib.h:111
Scoring rule for email.
Definition: score.c:49
bool exact
If this rule matches, don't evaluate any more.
Definition: score.c:53
char * str
Definition: score.c:50
struct PatternList * pat
Definition: score.c:51
int val
Definition: score.c:52
struct Score * next
Linked list.
Definition: score.c:54