|
@@ -2270,7 +2270,7 @@ int instance_unblock(const char *instance)
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
+
|
|
|
|
|
|
int content_check(const char *file, const xs_dict *msg)
|
|
|
|
|
@@ -2307,6 +2307,114 @@ int content_check(const char *file, const xs_dict *msg)
|
|
|
}
|
|
|
|
|
|
|
|
|
+xs_list *content_search(snac *user, const char *regex,
|
|
|
+ int priv, int skip, int show, int max_secs, int *timeout)
|
|
|
+
|
|
|
+{
|
|
|
+ if (regex == NULL || *regex == '\0')
|
|
|
+ return xs_list_new();
|
|
|
+
|
|
|
+ xs *i_regex = xs_tolower_i(xs_dup(regex));
|
|
|
+
|
|
|
+ xs_set seen;
|
|
|
+
|
|
|
+ xs_set_init(&seen);
|
|
|
+
|
|
|
+ if (max_secs == 0)
|
|
|
+ max_secs = 3;
|
|
|
+
|
|
|
+ time_t t = time(NULL) + max_secs;
|
|
|
+ *timeout = 0;
|
|
|
+
|
|
|
+
|
|
|
+ xs_list *tls[3] = {0};
|
|
|
+ char *md5s[3] = {0};
|
|
|
+ int c[3] = {0};
|
|
|
+
|
|
|
+ tls[0] = timeline_simple_list(user, "public", 0, XS_ALL);
|
|
|
+ tls[1] = timeline_instance_list(0, XS_ALL);
|
|
|
+ tls[2] = priv ? timeline_simple_list(user, "private", 0, XS_ALL) : xs_list_new();
|
|
|
+
|
|
|
+
|
|
|
+ for (int n = 0; n < 3; n++)
|
|
|
+ xs_list_next(tls[n], &md5s[n], &c[n]);
|
|
|
+
|
|
|
+ show += skip;
|
|
|
+
|
|
|
+ while (show > 0) {
|
|
|
+
|
|
|
+ if (time(NULL) > t) {
|
|
|
+ *timeout = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ int newest = -1;
|
|
|
+ double mtime = 0.0;
|
|
|
+
|
|
|
+ for (int n = 0; n < 3; n++) {
|
|
|
+ if (md5s[n] != NULL) {
|
|
|
+ xs *fn = _object_fn_by_md5(md5s[n], "content_search");
|
|
|
+ double mt = mtime(fn);
|
|
|
+
|
|
|
+ if (mt > mtime) {
|
|
|
+ newest = n;
|
|
|
+ mtime = mt;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (newest == -1)
|
|
|
+ break;
|
|
|
+
|
|
|
+ char *md5 = md5s[newest];
|
|
|
+
|
|
|
+
|
|
|
+ if (!xs_list_next(tls[newest], &md5s[newest], &c[newest]))
|
|
|
+ md5s[newest] = NULL;
|
|
|
+
|
|
|
+ xs *post = NULL;
|
|
|
+
|
|
|
+ if (!valid_status(object_get_by_md5(md5, &post)))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (!xs_match(xs_dict_get_def(post, "type", "-"), POSTLIKE_OBJECT_TYPE))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ char *content = xs_dict_get(post, "content");
|
|
|
+
|
|
|
+ if (xs_is_null(content))
|
|
|
+ continue;
|
|
|
+
|
|
|
+
|
|
|
+ xs *c = xs_regex_replace(content, "<[^>]+>", " ");
|
|
|
+ c = xs_regex_replace_i(c, " {2,}", " ");
|
|
|
+ c = xs_tolower_i(c);
|
|
|
+
|
|
|
+
|
|
|
+ if (xs_regex_match(c, i_regex)) {
|
|
|
+ if (xs_set_add(&seen, md5) == 1)
|
|
|
+ show--;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ xs_list *r = xs_set_result(&seen);
|
|
|
+
|
|
|
+ if (skip) {
|
|
|
+
|
|
|
+ while (skip--) {
|
|
|
+ r = xs_list_del(r, 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ xs_free(tls[0]);
|
|
|
+ xs_free(tls[1]);
|
|
|
+ xs_free(tls[2]);
|
|
|
+
|
|
|
+ return r;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
|
|
|
|
|
|
xs_str *notify_check_time(snac *snac, int reset)
|
|
@@ -2485,116 +2593,6 @@ void notify_clear(snac *snac)
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-xs_list *content_search(snac *user, const char *regex,
|
|
|
- int priv, int skip, int show, int max_secs, int *timeout)
|
|
|
-
|
|
|
-{
|
|
|
- if (regex == NULL || *regex == '\0')
|
|
|
- return xs_list_new();
|
|
|
-
|
|
|
- xs *i_regex = xs_tolower_i(xs_dup(regex));
|
|
|
-
|
|
|
- xs_set seen;
|
|
|
-
|
|
|
- xs_set_init(&seen);
|
|
|
-
|
|
|
- if (max_secs == 0)
|
|
|
- max_secs = 3;
|
|
|
-
|
|
|
- time_t t = time(NULL) + max_secs;
|
|
|
- *timeout = 0;
|
|
|
-
|
|
|
-
|
|
|
- xs_list *tls[3] = {0};
|
|
|
- char *md5s[3] = {0};
|
|
|
- int c[3] = {0};
|
|
|
-
|
|
|
- tls[0] = timeline_simple_list(user, "public", 0, XS_ALL);
|
|
|
- tls[1] = timeline_instance_list(0, XS_ALL);
|
|
|
- tls[2] = priv ? timeline_simple_list(user, "private", 0, XS_ALL) : xs_list_new();
|
|
|
-
|
|
|
-
|
|
|
- for (int n = 0; n < 3; n++)
|
|
|
- xs_list_next(tls[n], &md5s[n], &c[n]);
|
|
|
-
|
|
|
- show += skip;
|
|
|
-
|
|
|
- while (show > 0) {
|
|
|
-
|
|
|
- if (time(NULL) > t) {
|
|
|
- *timeout = 1;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- int newest = -1;
|
|
|
- double mtime = 0.0;
|
|
|
-
|
|
|
- for (int n = 0; n < 3; n++) {
|
|
|
- if (md5s[n] != NULL) {
|
|
|
- xs *fn = _object_fn_by_md5(md5s[n], "content_search");
|
|
|
- double mt = mtime(fn);
|
|
|
-
|
|
|
- if (mt > mtime) {
|
|
|
- newest = n;
|
|
|
- mtime = mt;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (newest == -1)
|
|
|
- break;
|
|
|
-
|
|
|
- char *md5 = md5s[newest];
|
|
|
-
|
|
|
-
|
|
|
- if (!xs_list_next(tls[newest], &md5s[newest], &c[newest]))
|
|
|
- md5s[newest] = NULL;
|
|
|
-
|
|
|
- xs *post = NULL;
|
|
|
-
|
|
|
- if (!valid_status(object_get_by_md5(md5, &post)))
|
|
|
- continue;
|
|
|
-
|
|
|
- if (!xs_match(xs_dict_get_def(post, "type", "-"), POSTLIKE_OBJECT_TYPE))
|
|
|
- continue;
|
|
|
-
|
|
|
- char *content = xs_dict_get(post, "content");
|
|
|
-
|
|
|
- if (xs_is_null(content))
|
|
|
- continue;
|
|
|
-
|
|
|
-
|
|
|
- xs *c = xs_regex_replace(content, "<[^>]+>", " ");
|
|
|
- c = xs_regex_replace_i(c, " {2,}", " ");
|
|
|
- c = xs_tolower_i(c);
|
|
|
-
|
|
|
-
|
|
|
- if (xs_regex_match(c, i_regex)) {
|
|
|
- if (xs_set_add(&seen, md5) == 1)
|
|
|
- show--;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- xs_list *r = xs_set_result(&seen);
|
|
|
-
|
|
|
- if (skip) {
|
|
|
-
|
|
|
- while (skip--) {
|
|
|
- r = xs_list_del(r, 0);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- xs_free(tls[0]);
|
|
|
- xs_free(tls[1]);
|
|
|
- xs_free(tls[2]);
|
|
|
-
|
|
|
- return r;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
|
|
|
|
|
|
static xs_dict *_enqueue_put(const char *fn, xs_dict *msg)
|