commit 979f2ad

default  ·  2024-05-08 14:43:02 +0000 UTC
parent 34c8968
Rewritten content_search() to read from both timelines.
3 files changed,  +65, -37
M data.c
M main.c
M snac.h
M data.c
+63, -14
  1@@ -2490,23 +2490,35 @@ void notify_clear(snac *snac)
  2 
  3 /** searches **/
  4 
  5-xs_list *content_search(snac *user, const xs_list *timeline,
  6-                        const char *regex, int max_secs, int *timeout)
  7+xs_list *content_search(snac *user, const char *regex, int priv, int max_secs, int *timeout)
  8 /* returns a list of posts which content matches the regex */
  9 {
 10-    xs_list *r = xs_list_new();
 11+    xs_set seen;
 12+
 13+    xs_set_init(&seen);
 14 
 15     if (max_secs == 0)
 16         max_secs = 3;
 17 
 18-    int c = 0;
 19-    char *v;
 20-
 21     time_t t = time(NULL) + max_secs;
 22     *timeout = 0;
 23 
 24-    while (xs_list_next(timeline, &v, &c)) {
 25-        xs *post = NULL;
 26+    /* iterate both timelines simultaneously */
 27+    xs *pub_tl    = timeline_simple_list(user, "public", 0, XS_ALL);
 28+    int pub_c     = 0;
 29+    char *pub_md5 = NULL;
 30+
 31+    xs *priv_tl    = priv ? timeline_simple_list(user, "private", 0, XS_ALL) : xs_list_new();
 32+    int priv_c     = 0;
 33+    char *priv_md5 = NULL;
 34+
 35+    /* first positioning */
 36+    xs_list_next(pub_tl,  &pub_md5,  &pub_c);
 37+    xs_list_next(priv_tl, &priv_md5, &priv_c);
 38+
 39+    for (;;) {
 40+        char *md5 = NULL;
 41+        enum { NONE, PUBLIC, PRIVATE } from = NONE;
 42 
 43         /* timeout? */
 44         if (time(NULL) > t) {
 45@@ -2514,11 +2526,48 @@ xs_list *content_search(snac *user, const xs_list *timeline,
 46             break;
 47         }
 48 
 49-        /* if from a user, must be in any timeline */
 50-        if (user && !timeline_here(user, v))
 51-            continue;
 52+        if (pub_md5 == NULL) {
 53+            /* out of both lists? done */
 54+            if (priv_md5 == NULL)
 55+                break;
 56 
 57-        if (!valid_status(object_get_by_md5(v, &post)))
 58+            /* out of public: take element from the private timeline and advance */
 59+            from = PRIVATE;
 60+        }
 61+        else
 62+        if (priv_md5 == NULL) {
 63+            /* out of private: take element from the public timeline and advance */
 64+            from = PUBLIC;
 65+        }
 66+        else {
 67+            /* candidates from both: choose one from the file dates */
 68+            xs *pub_fn  = xs_fmt("%s/public/%s.json",  user->basedir, pub_md5);
 69+            xs *priv_fn = xs_fmt("%s/private/%s.json", user->basedir, priv_md5);
 70+
 71+            if (mtime(pub_fn) < mtime(priv_fn))
 72+                from = PRIVATE;
 73+            else
 74+                from = PUBLIC;
 75+        }
 76+
 77+        if (from == PUBLIC) { /* public */
 78+            md5 = pub_md5;
 79+            if (!xs_list_next(pub_tl, &pub_md5, &pub_c))
 80+                pub_md5 = NULL;
 81+        }
 82+        else
 83+        if (from == PRIVATE) { /* private */
 84+            md5 = priv_md5;
 85+            if (!xs_list_next(priv_tl, &priv_md5, &priv_c))
 86+                priv_md5 = NULL;
 87+        }
 88+
 89+        if (md5 == NULL)
 90+            break;
 91+
 92+        xs *post = NULL;
 93+
 94+        if (!valid_status(timeline_get_by_md5(user, md5, &post)))
 95             continue;
 96 
 97         /* must be a Note */
 98@@ -2539,10 +2588,10 @@ xs_list *content_search(snac *user, const xs_list *timeline,
 99         xs *l = xs_regex_select_n(c, regex, 1);
100 
101         if (xs_list_len(l))
102-            r = xs_list_append(r, v);
103+            xs_set_add(&seen, md5);
104     }
105 
106-    return r;
107+    return xs_set_result(&seen);
108 }
109 
110 
M main.c
+1, -21
 1@@ -376,30 +376,10 @@ int main(int argc, char *argv[])
 2     }
 3 
 4     if (strcmp(cmd, "search") == 0) { /** **/
 5-        xs *tl = timeline_simple_list(&snac, "private", 0, XS_ALL);
 6         int to;
 7 
 8         /* 'url' contains the regex */
 9-        xs *r = content_search(&snac, tl, url, 10, &to);
10-
11-        int c = 0;
12-        char *v;
13-
14-        /* print results as standalone links */
15-        while (xs_list_next(r, &v, &c)) {
16-            printf("%s/admin/p/%s\n", snac.actor, v);
17-        }
18-
19-        return 0;
20-    }
21-
22-    if (strcmp(cmd, "search2") == 0) { /** **/
23-        /* undocumented (for testing only) */
24-        xs *tl = timeline_simple_list(&snac, "public", 0, XS_ALL);
25-        int to;
26-
27-        /* 'url' contains the regex */
28-        xs *r = content_search(&snac, tl, url, 10, &to);
29+        xs *r = content_search(&snac, url, 1, 10, &to);
30 
31         int c = 0;
32         char *v;
M snac.h
+1, -2
 1@@ -179,8 +179,7 @@ xs_list *list_timeline(snac *user, const char *list, int skip, int show);
 2 xs_val *list_content(snac *user, const char *list_id, const char *actor_md5, int op);
 3 void list_distribute(snac *user, const char *who, const xs_dict *post);
 4 
 5-xs_list *content_search(snac *user, const xs_list *timeline,
 6-                        const char *regex, int max_secs, int *timeout);
 7+xs_list *content_search(snac *user, const char *regex, int priv, int max_secs, int *timeout);
 8 
 9 int actor_add(const char *actor, xs_dict *msg);
10 int actor_get(const char *actor, xs_dict **data);