summaryrefslogtreecommitdiff
path: root/data.c
diff options
context:
space:
mode:
Diffstat (limited to 'data.c')
-rw-r--r--data.c107
1 files changed, 107 insertions, 0 deletions
diff --git a/data.c b/data.c
index 4e1682c..d9449d8 100644
--- a/data.c
+++ b/data.c
@@ -2488,6 +2488,113 @@ void notify_clear(snac *snac)
2488} 2488}
2489 2489
2490 2490
2491/** searches **/
2492
2493xs_list *content_search(snac *user, const char *regex, int priv, int max_secs, int *timeout)
2494/* returns a list of posts which content matches the regex */
2495{
2496 xs_set seen;
2497
2498 xs_set_init(&seen);
2499
2500 if (max_secs == 0)
2501 max_secs = 3;
2502
2503 time_t t = time(NULL) + max_secs;
2504 *timeout = 0;
2505
2506 /* iterate both timelines simultaneously */
2507 xs *pub_tl = timeline_simple_list(user, "public", 0, XS_ALL);
2508 int pub_c = 0;
2509 char *pub_md5 = NULL;
2510
2511 xs *priv_tl = priv ? timeline_simple_list(user, "private", 0, XS_ALL) : xs_list_new();
2512 int priv_c = 0;
2513 char *priv_md5 = NULL;
2514
2515 /* first positioning */
2516 xs_list_next(pub_tl, &pub_md5, &pub_c);
2517 xs_list_next(priv_tl, &priv_md5, &priv_c);
2518
2519 for (;;) {
2520 char *md5 = NULL;
2521 enum { NONE, PUBLIC, PRIVATE } from = NONE;
2522
2523 /* timeout? */
2524 if (time(NULL) > t) {
2525 *timeout = 1;
2526 break;
2527 }
2528
2529 if (pub_md5 == NULL) {
2530 /* out of both lists? done */
2531 if (priv_md5 == NULL)
2532 break;
2533
2534 /* out of public: take element from the private timeline and advance */
2535 from = PRIVATE;
2536 }
2537 else
2538 if (priv_md5 == NULL) {
2539 /* out of private: take element from the public timeline and advance */
2540 from = PUBLIC;
2541 }
2542 else {
2543 /* candidates from both: choose one from the file dates */
2544 xs *pub_fn = xs_fmt("%s/public/%s.json", user->basedir, pub_md5);
2545 xs *priv_fn = xs_fmt("%s/private/%s.json", user->basedir, priv_md5);
2546
2547 if (mtime(pub_fn) < mtime(priv_fn))
2548 from = PRIVATE;
2549 else
2550 from = PUBLIC;
2551 }
2552
2553 if (from == PUBLIC) { /* public */
2554 md5 = pub_md5;
2555 if (!xs_list_next(pub_tl, &pub_md5, &pub_c))
2556 pub_md5 = NULL;
2557 }
2558 else
2559 if (from == PRIVATE) { /* private */
2560 md5 = priv_md5;
2561 if (!xs_list_next(priv_tl, &priv_md5, &priv_c))
2562 priv_md5 = NULL;
2563 }
2564
2565 if (md5 == NULL)
2566 break;
2567
2568 xs *post = NULL;
2569
2570 if (!valid_status(timeline_get_by_md5(user, md5, &post)))
2571 continue;
2572
2573 /* must be a Note */
2574 if (strcmp(xs_dict_get_def(post, "type", ""), "Note"))
2575 continue;
2576
2577 char *content = xs_dict_get(post, "content");
2578
2579 if (xs_is_null(content))
2580 continue;
2581
2582 /* strip HTML */
2583 xs *c = xs_regex_replace(content, "<[^>]+>", " ");
2584 c = xs_regex_replace_i(c, " {2,}", " ");
2585 c = xs_tolower_i(c);
2586
2587 /* apply regex */
2588 xs *l = xs_regex_select_n(c, regex, 1);
2589
2590 if (xs_list_len(l))
2591 xs_set_add(&seen, md5);
2592 }
2593
2594 return xs_set_result(&seen);
2595}
2596
2597
2491/** the queue **/ 2598/** the queue **/
2492 2599
2493static xs_dict *_enqueue_put(const char *fn, xs_dict *msg) 2600static xs_dict *_enqueue_put(const char *fn, xs_dict *msg)