commit 0a6cfba
default
·
2024-05-15 11:29:07 +0000 UTC
parent ff8d49a
Moved functions around.
1 files changed,
+109,
-111
M
data.c
M
data.c
+109,
-111
1@@ -2270,7 +2270,7 @@ int instance_unblock(const char *instance)
2 }
3
4
5-/** content filtering **/
6+/** operations by content **/
7
8 int content_check(const char *file, const xs_dict *msg)
9 /* checks if a message's content matches any of the regexes in file */
10@@ -2307,6 +2307,114 @@ int content_check(const char *file, const xs_dict *msg)
11 }
12
13
14+xs_list *content_search(snac *user, const char *regex,
15+ int priv, int skip, int show, int max_secs, int *timeout)
16+/* returns a list of posts which content matches the regex */
17+{
18+ if (regex == NULL || *regex == '\0')
19+ return xs_list_new();
20+
21+ xs *i_regex = xs_tolower_i(xs_dup(regex));
22+
23+ xs_set seen;
24+
25+ xs_set_init(&seen);
26+
27+ if (max_secs == 0)
28+ max_secs = 3;
29+
30+ time_t t = time(NULL) + max_secs;
31+ *timeout = 0;
32+
33+ /* iterate all timelines simultaneously */
34+ xs_list *tls[3] = {0};
35+ char *md5s[3] = {0};
36+ int c[3] = {0};
37+
38+ tls[0] = timeline_simple_list(user, "public", 0, XS_ALL); /* public */
39+ tls[1] = timeline_instance_list(0, XS_ALL); /* instance */
40+ tls[2] = priv ? timeline_simple_list(user, "private", 0, XS_ALL) : xs_list_new(); /* private or none */
41+
42+ /* first positioning */
43+ for (int n = 0; n < 3; n++)
44+ xs_list_next(tls[n], &md5s[n], &c[n]);
45+
46+ show += skip;
47+
48+ while (show > 0) {
49+ /* timeout? */
50+ if (time(NULL) > t) {
51+ *timeout = 1;
52+ break;
53+ }
54+
55+ /* find the newest post */
56+ int newest = -1;
57+ double mtime = 0.0;
58+
59+ for (int n = 0; n < 3; n++) {
60+ if (md5s[n] != NULL) {
61+ xs *fn = _object_fn_by_md5(md5s[n], "content_search");
62+ double mt = mtime(fn);
63+
64+ if (mt > mtime) {
65+ newest = n;
66+ mtime = mt;
67+ }
68+ }
69+ }
70+
71+ if (newest == -1)
72+ break;
73+
74+ char *md5 = md5s[newest];
75+
76+ /* advance the chosen timeline */
77+ if (!xs_list_next(tls[newest], &md5s[newest], &c[newest]))
78+ md5s[newest] = NULL;
79+
80+ xs *post = NULL;
81+
82+ if (!valid_status(object_get_by_md5(md5, &post)))
83+ continue;
84+
85+ if (!xs_match(xs_dict_get_def(post, "type", "-"), POSTLIKE_OBJECT_TYPE))
86+ continue;
87+
88+ char *content = xs_dict_get(post, "content");
89+
90+ if (xs_is_null(content))
91+ continue;
92+
93+ /* strip HTML */
94+ xs *c = xs_regex_replace(content, "<[^>]+>", " ");
95+ c = xs_regex_replace_i(c, " {2,}", " ");
96+ c = xs_tolower_i(c);
97+
98+ /* apply regex */
99+ if (xs_regex_match(c, i_regex)) {
100+ if (xs_set_add(&seen, md5) == 1)
101+ show--;
102+ }
103+ }
104+
105+ xs_list *r = xs_set_result(&seen);
106+
107+ if (skip) {
108+ /* BAD */
109+ while (skip--) {
110+ r = xs_list_del(r, 0);
111+ }
112+ }
113+
114+ xs_free(tls[0]);
115+ xs_free(tls[1]);
116+ xs_free(tls[2]);
117+
118+ return r;
119+}
120+
121+
122 /** notifications **/
123
124 xs_str *notify_check_time(snac *snac, int reset)
125@@ -2485,116 +2593,6 @@ void notify_clear(snac *snac)
126 }
127
128
129-/** searches **/
130-
131-xs_list *content_search(snac *user, const char *regex,
132- int priv, int skip, int show, int max_secs, int *timeout)
133-/* returns a list of posts which content matches the regex */
134-{
135- if (regex == NULL || *regex == '\0')
136- return xs_list_new();
137-
138- xs *i_regex = xs_tolower_i(xs_dup(regex));
139-
140- xs_set seen;
141-
142- xs_set_init(&seen);
143-
144- if (max_secs == 0)
145- max_secs = 3;
146-
147- time_t t = time(NULL) + max_secs;
148- *timeout = 0;
149-
150- /* iterate all timelines simultaneously */
151- xs_list *tls[3] = {0};
152- char *md5s[3] = {0};
153- int c[3] = {0};
154-
155- tls[0] = timeline_simple_list(user, "public", 0, XS_ALL); /* public */
156- tls[1] = timeline_instance_list(0, XS_ALL); /* instance */
157- tls[2] = priv ? timeline_simple_list(user, "private", 0, XS_ALL) : xs_list_new(); /* private or none */
158-
159- /* first positioning */
160- for (int n = 0; n < 3; n++)
161- xs_list_next(tls[n], &md5s[n], &c[n]);
162-
163- show += skip;
164-
165- while (show > 0) {
166- /* timeout? */
167- if (time(NULL) > t) {
168- *timeout = 1;
169- break;
170- }
171-
172- /* find the newest post */
173- int newest = -1;
174- double mtime = 0.0;
175-
176- for (int n = 0; n < 3; n++) {
177- if (md5s[n] != NULL) {
178- xs *fn = _object_fn_by_md5(md5s[n], "content_search");
179- double mt = mtime(fn);
180-
181- if (mt > mtime) {
182- newest = n;
183- mtime = mt;
184- }
185- }
186- }
187-
188- if (newest == -1)
189- break;
190-
191- char *md5 = md5s[newest];
192-
193- /* advance the chosen timeline */
194- if (!xs_list_next(tls[newest], &md5s[newest], &c[newest]))
195- md5s[newest] = NULL;
196-
197- xs *post = NULL;
198-
199- if (!valid_status(object_get_by_md5(md5, &post)))
200- continue;
201-
202- if (!xs_match(xs_dict_get_def(post, "type", "-"), POSTLIKE_OBJECT_TYPE))
203- continue;
204-
205- char *content = xs_dict_get(post, "content");
206-
207- if (xs_is_null(content))
208- continue;
209-
210- /* strip HTML */
211- xs *c = xs_regex_replace(content, "<[^>]+>", " ");
212- c = xs_regex_replace_i(c, " {2,}", " ");
213- c = xs_tolower_i(c);
214-
215- /* apply regex */
216- if (xs_regex_match(c, i_regex)) {
217- if (xs_set_add(&seen, md5) == 1)
218- show--;
219- }
220- }
221-
222- xs_list *r = xs_set_result(&seen);
223-
224- if (skip) {
225- /* BAD */
226- while (skip--) {
227- r = xs_list_del(r, 0);
228- }
229- }
230-
231- xs_free(tls[0]);
232- xs_free(tls[1]);
233- xs_free(tls[2]);
234-
235- return r;
236-}
237-
238-
239 /** the queue **/
240
241 static xs_dict *_enqueue_put(const char *fn, xs_dict *msg)