NeoMutt  2021-02-05-666-ge300cd
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 "pattern/lib.h"
39 #include "context.h"
40 #include "init.h"
41 #include "mutt_commands.h"
42 #include "mutt_globals.h"
43 #include "mutt_thread.h"
44 #include "options.h"
45 #include "protos.h"
46 
50 struct Score
51 {
52  char *str;
53  struct PatternList *pat;
54  int val;
55  bool exact;
56  struct Score *next;
57 };
58 
59 static struct Score *ScoreList = NULL;
60 
65 void mutt_check_rescore(struct Mailbox *m)
66 {
67  const bool c_score = cs_subset_bool(NeoMutt->sub, "score");
68  if (OptNeedRescore && c_score)
69  {
70  const short c_sort = cs_subset_sort(NeoMutt->sub, "sort");
71  const short c_sort_aux = cs_subset_sort(NeoMutt->sub, "sort_aux");
72  if (((c_sort & SORT_MASK) == SORT_SCORE) || ((c_sort_aux & SORT_MASK) == SORT_SCORE))
73  {
74  OptNeedResort = true;
75  if (mutt_using_threads())
76  OptSortSubthreads = true;
77  }
78 
79  mutt_debug(LL_NOTIFY, "NT_SCORE: %p\n", m);
80  notify_send(m->notify, NT_SCORE, 0, NULL);
81  }
82  OptNeedRescore = false;
83 }
84 
88 enum CommandResult mutt_parse_score(struct Buffer *buf, struct Buffer *s,
89  intptr_t data, struct Buffer *err)
90 {
91  struct Score *ptr = NULL, *last = NULL;
92  char *pattern = NULL, *pc = NULL;
93 
95  if (!MoreArgs(s))
96  {
97  mutt_buffer_printf(err, _("%s: too few arguments"), "score");
98  return MUTT_CMD_WARNING;
99  }
100  pattern = mutt_buffer_strdup(buf);
102  if (MoreArgs(s))
103  {
104  FREE(&pattern);
105  mutt_buffer_printf(err, _("%s: too many arguments"), "score");
106  return MUTT_CMD_WARNING;
107  }
108 
109  /* look for an existing entry and update the value, else add it to the end
110  * of the list */
111  for (ptr = ScoreList, last = NULL; ptr; last = ptr, ptr = ptr->next)
112  if (mutt_str_equal(pattern, ptr->str))
113  break;
114  if (!ptr)
115  {
116  struct PatternList *pat =
118  pattern, MUTT_PC_NO_FLAGS, err);
119  if (!pat)
120  {
121  FREE(&pattern);
122  return MUTT_CMD_ERROR;
123  }
124  ptr = mutt_mem_calloc(1, sizeof(struct Score));
125  if (last)
126  last->next = ptr;
127  else
128  ScoreList = ptr;
129  ptr->pat = pat;
130  ptr->str = pattern;
131  }
132  else
133  {
134  /* 'buf' arg was cleared and 'pattern' holds the only reference;
135  * as here 'ptr' != NULL -> update the value only in which case
136  * ptr->str already has the string, so pattern should be freed. */
137  FREE(&pattern);
138  }
139  pc = buf->data;
140  if (*pc == '=')
141  {
142  ptr->exact = true;
143  pc++;
144  }
145  if (mutt_str_atoi(pc, &ptr->val) < 0)
146  {
147  FREE(&pattern);
148  mutt_buffer_strcpy(err, _("Error: score: invalid number"));
149  return MUTT_CMD_ERROR;
150  }
151  OptNeedRescore = true;
152  return MUTT_CMD_SUCCESS;
153 }
154 
161 void 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 =
183  cs_subset_number(NeoMutt->sub, "score_threshold_delete");
184  const short c_score_threshold_flag =
185  cs_subset_number(NeoMutt->sub, "score_threshold_flag");
186  const short c_score_threshold_read =
187  cs_subset_number(NeoMutt->sub, "score_threshold_read");
188 
189  if (e->score <= c_score_threshold_delete)
190  mutt_set_flag_update(m, e, MUTT_DELETE, true, upd_mbox);
191  if (e->score <= c_score_threshold_read)
192  mutt_set_flag_update(m, e, MUTT_READ, true, upd_mbox);
193  if (e->score >= c_score_threshold_flag)
194  mutt_set_flag_update(m, e, MUTT_FLAG, true, upd_mbox);
195 }
196 
200 enum CommandResult mutt_parse_unscore(struct Buffer *buf, struct Buffer *s,
201  intptr_t data, struct Buffer *err)
202 {
203  struct Score *tmp = NULL, *last = NULL;
204 
205  while (MoreArgs(s))
206  {
208  if (mutt_str_equal("*", buf->data))
209  {
210  for (tmp = ScoreList; tmp;)
211  {
212  last = tmp;
213  tmp = tmp->next;
214  mutt_pattern_free(&last->pat);
215  FREE(&last);
216  }
217  ScoreList = NULL;
218  }
219  else
220  {
221  for (tmp = ScoreList; tmp; last = tmp, tmp = tmp->next)
222  {
223  if (mutt_str_equal(buf->data, tmp->str))
224  {
225  if (last)
226  last->next = tmp->next;
227  else
228  ScoreList = tmp->next;
229  mutt_pattern_free(&tmp->pat);
230  FREE(&tmp);
231  /* there should only be one score per pattern, so we can stop here */
232  break;
233  }
234  }
235  }
236  }
237  OptNeedRescore = true;
238  return MUTT_CMD_SUCCESS;
239 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
The "current" mailbox.
Definition: context.h:37
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
int mutt_str_atoi(const char *str, int *dst)
Convert ASCII string to an integer.
Definition: string.c:252
The envelope/body of an email.
Definition: email.h:37
CommandResult
Error codes for command_t parse functions.
Definition: mutt_commands.h:34
Config/command parsing.
struct Mailbox * ctx_mailbox(struct Context *ctx)
wrapper to get the mailbox in a Context, or NULL
Definition: context.c:444
Error: Can&#39;t help the user.
Definition: mutt_commands.h:36
Log of notifications.
Definition: logging.h:45
Structs that make up an email.
The "currently-open" mailbox.
struct PatternList * pat
Definition: score.c:53
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
void mutt_check_rescore(struct Mailbox *m)
Do the emails need to have their scores recalculated?
Definition: score.c:65
WHERE bool OptNeedResort
(pseudo) used to force a re-sort
Definition: options.h:42
String manipulation buffer.
Definition: buffer.h:33
void mutt_score_message(struct Mailbox *m, struct Email *e, bool upd_mbox)
Apply scoring to an email.
Definition: score.c:161
Flagged messages.
Definition: mutt.h:98
#define _(a)
Definition: message.h:28
Sort by the email&#39;s score.
Definition: sort2.h:52
enum CommandResult mutt_parse_score(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;score&#39; command - Implements Command::parse() -.
Definition: score.c:88
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
WHERE bool OptNeedRescore
(pseudo) set when the &#39;score&#39; command is used
Definition: options.h:41
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
Container for Accounts, Notifications.
Definition: neomutt.h:36
Convenience wrapper for the config headers.
char * str
Definition: score.c:52
#define MoreArgs(buf)
Definition: buffer.h:40
void mutt_set_flag_update(struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool upd_mbox)
Set a flag on an email.
Definition: flags.c:51
int val
Definition: score.c:54
Many unsorted constants and some structs.
Convenience wrapper for the core headers.
struct Menu * menu
Needed for pattern compilation.
Definition: context.h:45
int score
Message score.
Definition: email.h:89
struct PatternList * mutt_pattern_comp(struct Mailbox *m, struct Menu *menu, const char *s, PatternCompFlags flags, struct Buffer *err)
Create a Pattern.
Definition: compile.c:1092
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
Prototypes for many functions.
#define SLIST_FIRST(head)
Definition: queue.h:229
Create/manipulate threading in emails.
Messages to be deleted.
Definition: mutt.h:94
A mailbox.
Definition: mailbox.h:81
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:395
#define MUTT_PC_NO_FLAGS
No flags are set.
Definition: lib.h:60
Match patterns to emails.
char * data
Pointer to data.
Definition: buffer.h:35
Messages that have been read.
Definition: mutt.h:92
Definitions of NeoMutt commands.
enum CommandResult mutt_parse_unscore(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;unscore&#39; command - Implements Command::parse() -.
Definition: score.c:200
Scoring rule for email.
Definition: score.c:50
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Routines for adding user scores to emails.
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
#define mutt_using_threads()
Definition: mutt_thread.h:95
int 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:1097
Success: Command worked.
Definition: mutt_commands.h:38
Warning: Help given to the user.
Definition: mutt_commands.h:37
Email scoring has changed.
Definition: notify_type.h:51
#define FREE(x)
Definition: memory.h:40
struct Score * next
Definition: score.c:56
WHERE bool OptSortSubthreads
(pseudo) used when $sort_aux changes
Definition: options.h:53
Hundreds of global variables to back the user variables.
Handling of global boolean variables.
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
struct Notify * notify
Notifications: NotifyMailbox, EventMailbox.
Definition: mailbox.h:148
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition: compile.c:1038
Cache commonly-used patterns.
Definition: lib.h:105
Convenience wrapper for the library headers.
bool exact
if this rule matches, don&#39;t evaluate any more
Definition: score.c:55
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: lib.h:95
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:78
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
Definition: mutt.h:66
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