ソースを参照

Merge remote-tracking branch 'upstream/master'

shtrophic 1 年間 前
コミット
6743113016
9 ファイル変更69 行追加18 行削除
  1. 10 4
      TODO.md
  2. 16 4
      activitypub.c
  3. 1 1
      data.c
  4. 2 0
      doc/snac.5
  5. 2 2
      html.c
  6. 14 0
      httpd.c
  7. 5 1
      main.c
  8. 18 6
      mastoapi.c
  9. 1 0
      snac.h

+ 10 - 4
TODO.md

@@ -16,10 +16,6 @@ Important: deleting a follower should do more that just delete the object, see h
 
 
 ## Wishlist
 ## Wishlist
 
 
-Implement Proxying for Media Links to Enhance User Privacy (see https://codeberg.org/grunfink/snac2/issues/219 for more information).
-
-Consider showing only posts by the account owner (not full trees) (see https://codeberg.org/grunfink/snac2/issues/217 for more information).
-
 Add support for subscribing and posting to relays (see https://codeberg.org/grunfink/snac2/issues/216 for more information).
 Add support for subscribing and posting to relays (see https://codeberg.org/grunfink/snac2/issues/216 for more information).
 
 
 The instance timeline should also show boosts from users.
 The instance timeline should also show boosts from users.
@@ -357,3 +353,13 @@ Fix a crash when posting from the links browser (2.63, 2024-11-08T15:57:25+0100)
 Fix some repeated images in Lemmy posts (2.63, 2024-11-08T15:57:25+0100).
 Fix some repeated images in Lemmy posts (2.63, 2024-11-08T15:57:25+0100).
 
 
 Fix a crash when posting an image from the tooot mobile app (2.63, 2024-11-11T19:42:11+0100).
 Fix a crash when posting an image from the tooot mobile app (2.63, 2024-11-11T19:42:11+0100).
+
+Fix some URL proxying (2.64, 2024-11-16T07:26:23+0100).
+
+Allow underscores in hashtags (2.64, 2024-11-16T07:26:23+0100).
+
+Add a pidfile (2.64, 2024-11-17T10:21:29+0100).
+
+Implement Proxying for Media Links to Enhance User Privacy (see https://codeberg.org/grunfink/snac2/issues/219 for more information) (2024-11-18T20:36:39+0100).
+
+Consider showing only posts by the account owner (not full trees) (see https://codeberg.org/grunfink/snac2/issues/217 for more information) (2024-11-18T20:36:39+0100).

+ 16 - 4
activitypub.c

@@ -183,6 +183,18 @@ const char *get_atto(const xs_dict *msg)
 }
 }
 
 
 
 
+const char *get_in_reply_to(const xs_dict *msg)
+/* gets the inReplyTo id */
+{
+    const xs_val *in_reply_to = xs_dict_get(msg, "inReplyTo");
+
+    if (xs_type(in_reply_to) == XSTYPE_DICT)
+        in_reply_to = xs_dict_get(in_reply_to, "id");
+
+    return in_reply_to;
+}
+
+
 xs_list *get_attachments(const xs_dict *msg)
 xs_list *get_attachments(const xs_dict *msg)
 /* unify the garbage fire that are the attachments */
 /* unify the garbage fire that are the attachments */
 {
 {
@@ -373,7 +385,7 @@ int timeline_request(snac *snac, const char **id, xs_str **wrk, int level)
                             }
                             }
 
 
                             /* does it have an ancestor? */
                             /* does it have an ancestor? */
-                            const char *in_reply_to = xs_dict_get(object, "inReplyTo");
+                            const char *in_reply_to = get_in_reply_to(object);
 
 
                             /* store */
                             /* store */
                             timeline_add(snac, nid, object);
                             timeline_add(snac, nid, object);
@@ -671,7 +683,7 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg)
         return 3;
         return 3;
 
 
     /* is this message a reply to another? */
     /* is this message a reply to another? */
-    const char *irt = xs_dict_get(msg, "inReplyTo");
+    const char *irt = get_in_reply_to(msg);
     if (!xs_is_null(irt)) {
     if (!xs_is_null(irt)) {
         xs *r_msg = NULL;
         xs *r_msg = NULL;
 
 
@@ -724,7 +736,7 @@ xs_str *process_tags(snac *snac, const char *content, xs_list **tag)
         /* use this same server */
         /* use this same server */
         def_srv = xs_dup(xs_dict_get(srv_config, "host"));
         def_srv = xs_dup(xs_dict_get(srv_config, "host"));
 
 
-    split = xs_regex_split(content, "(@[A-Za-z0-9_]+(@[A-Za-z0-9\\.-]+)?|&#[0-9]+;|#[^[:punct:][:space:]]+)");
+    split = xs_regex_split(content, "(@[A-Za-z0-9_]+(@[A-Za-z0-9\\.-]+)?|&#[0-9]+;|#(_|[^[:punct:][:space:]])+)");
 
 
     p = split;
     p = split;
     while (xs_list_iter(&p, &v)) {
     while (xs_list_iter(&p, &v)) {
@@ -1957,7 +1969,7 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req)
 
 
         if (xs_match(utype, "Note|Article")) { /** **/
         if (xs_match(utype, "Note|Article")) { /** **/
             const char *id          = xs_dict_get(object, "id");
             const char *id          = xs_dict_get(object, "id");
-            const char *in_reply_to = xs_dict_get(object, "inReplyTo");
+            const char *in_reply_to = get_in_reply_to(object);
             const char *atto        = get_atto(object);
             const char *atto        = get_atto(object);
             xs *wrk           = NULL;
             xs *wrk           = NULL;
 
 

+ 1 - 1
data.c

@@ -762,7 +762,7 @@ int _object_add(const char *id, const xs_dict *obj, int ow)
         fclose(f);
         fclose(f);
 
 
         /* does this object has a parent? */
         /* does this object has a parent? */
-        const char *in_reply_to = xs_dict_get(obj, "inReplyTo");
+        const char *in_reply_to = get_in_reply_to(obj);
 
 
         if (!xs_is_null(in_reply_to) && *in_reply_to) {
         if (!xs_is_null(in_reply_to) && *in_reply_to) {
             /* update the children index of the parent */
             /* update the children index of the parent */

+ 2 - 0
doc/snac.5

@@ -209,6 +209,8 @@ web interface.
 .It Pa history/
 .It Pa history/
 This directory contains generated HTML files. They may be snapshots of the
 This directory contains generated HTML files. They may be snapshots of the
 local timeline in previous months or other cached data.
 local timeline in previous months or other cached data.
+.It Pa server.pid
+This file stores the server PID in a single text line.
 .El
 .El
 .Sh SEE ALSO
 .Sh SEE ALSO
 .Xr snac 1 ,
 .Xr snac 1 ,

+ 2 - 2
html.c

@@ -1670,7 +1670,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
     if (strcmp(type, "Note") == 0) {
     if (strcmp(type, "Note") == 0) {
         if (level == 0) {
         if (level == 0) {
             /* is the parent not here? */
             /* is the parent not here? */
-            const char *parent = xs_dict_get(msg, "inReplyTo");
+            const char *parent = get_in_reply_to(msg);
 
 
             if (user && !xs_is_null(parent) && *parent && !timeline_here(user, parent)) {
             if (user && !xs_is_null(parent) && *parent && !timeline_here(user, parent)) {
                 xs_html_add(post_header,
                 xs_html_add(post_header,
@@ -2329,7 +2329,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only,
 
 
         /* is this message a non-public reply? */
         /* is this message a non-public reply? */
         if (user != NULL && !is_msg_public(msg)) {
         if (user != NULL && !is_msg_public(msg)) {
-            const char *irt = xs_dict_get(msg, "inReplyTo");
+            const char *irt = get_in_reply_to(msg);
 
 
             /* is it a reply to something not in the storage? */
             /* is it a reply to something not in the storage? */
             if (!xs_is_null(irt) && !object_here(irt)) {
             if (!xs_is_null(irt) && !object_here(irt)) {

+ 14 - 0
httpd.c

@@ -774,6 +774,7 @@ void httpd(void)
     xs *sem_name = NULL;
     xs *sem_name = NULL;
     xs *shm_name = NULL;
     xs *shm_name = NULL;
     sem_t anon_job_sem;
     sem_t anon_job_sem;
+    xs *pidfile = xs_fmt("%s/server.pid", srv_basedir);
 
 
     address = xs_dict_get(srv_config, "address");
     address = xs_dict_get(srv_config, "address");
 
 
@@ -809,6 +810,17 @@ void httpd(void)
     srv_log(xs_fmt("httpd%s start %s %s", p_state->use_fcgi ? " (FastCGI)" : "",
     srv_log(xs_fmt("httpd%s start %s %s", p_state->use_fcgi ? " (FastCGI)" : "",
                     full_address, USER_AGENT));
                     full_address, USER_AGENT));
 
 
+    {
+        FILE *f;
+
+        if ((f = fopen(pidfile, "w")) != NULL) {
+            fprintf(f, "%d\n", getpid());
+            fclose(f);
+        }
+        else
+            srv_log(xs_fmt("Cannot create %s: %s", pidfile, strerror(errno)));
+    }
+
     /* show the number of usable file descriptors */
     /* show the number of usable file descriptors */
     struct rlimit r;
     struct rlimit r;
     getrlimit(RLIMIT_NOFILE, &r);
     getrlimit(RLIMIT_NOFILE, &r);
@@ -894,4 +906,6 @@ void httpd(void)
     srv_log(xs_fmt("httpd%s stop %s (run time: %s)",
     srv_log(xs_fmt("httpd%s stop %s (run time: %s)",
                 p_state->use_fcgi ? " (FastCGI)" : "",
                 p_state->use_fcgi ? " (FastCGI)" : "",
                 full_address, uptime));
                 full_address, uptime));
+
+    unlink(pidfile);
 }
 }

+ 5 - 1
main.c

@@ -558,7 +558,11 @@ int main(int argc, char *argv[])
         if (data != NULL) {
         if (data != NULL) {
             xs_json_dump(data, 4, stdout);
             xs_json_dump(data, 4, stdout);
             enqueue_actor_refresh(&snac, xs_dict_get(data, "attributedTo"), 0);
             enqueue_actor_refresh(&snac, xs_dict_get(data, "attributedTo"), 0);
-            timeline_add(&snac, url, data);
+
+            if (!timeline_here(&snac, url))
+                timeline_add(&snac, url, data);
+            else
+                printf("Post %s already here\n", url);
         }
         }
 
 
         return 0;
         return 0;

+ 18 - 6
mastoapi.c

@@ -171,7 +171,7 @@ const char *login_page = ""
 "<body><h1>%s OAuth identify</h1>\n"
 "<body><h1>%s OAuth identify</h1>\n"
 "<div style=\"background-color: red; color: white\">%s</div>\n"
 "<div style=\"background-color: red; color: white\">%s</div>\n"
 "<form method=\"post\" action=\"%s:/" "/%s/%s\">\n"
 "<form method=\"post\" action=\"%s:/" "/%s/%s\">\n"
-"<p>Login: <input type=\"text\" name=\"login\"></p>\n"
+"<p>Login: <input type=\"text\" name=\"login\" autocapitalize=\"off\"></p>\n"
 "<p>Password: <input type=\"password\" name=\"passwd\"></p>\n"
 "<p>Password: <input type=\"password\" name=\"passwd\"></p>\n"
 "<input type=\"hidden\" name=\"redir\" value=\"%s\">\n"
 "<input type=\"hidden\" name=\"redir\" value=\"%s\">\n"
 "<input type=\"hidden\" name=\"cid\" value=\"%s\">\n"
 "<input type=\"hidden\" name=\"cid\" value=\"%s\">\n"
@@ -1024,7 +1024,7 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg)
     st = xs_dict_append(st, "in_reply_to_id",         xs_stock(XSTYPE_NULL));
     st = xs_dict_append(st, "in_reply_to_id",         xs_stock(XSTYPE_NULL));
     st = xs_dict_append(st, "in_reply_to_account_id", xs_stock(XSTYPE_NULL));
     st = xs_dict_append(st, "in_reply_to_account_id", xs_stock(XSTYPE_NULL));
 
 
-    tmp = xs_dict_get(msg, "inReplyTo");
+    tmp = get_in_reply_to(msg);
     if (!xs_is_null(tmp)) {
     if (!xs_is_null(tmp)) {
         xs *irto = NULL;
         xs *irto = NULL;
 
 
@@ -1727,11 +1727,11 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
         if (logged_in) {
         if (logged_in) {
             xs *l      = notify_list(&snac1, 0, 64);
             xs *l      = notify_list(&snac1, 0, 64);
             xs *out    = xs_list_new();
             xs *out    = xs_list_new();
-            xs_list *p = l;
             const xs_dict *v;
             const xs_dict *v;
             const xs_list *excl = xs_dict_get(args, "exclude_types[]");
             const xs_list *excl = xs_dict_get(args, "exclude_types[]");
+            const char *max_id = xs_dict_get(args, "max_id");
 
 
-            while (xs_list_iter(&p, &v)) {
+            xs_list_foreach(l, v) {
                 xs *noti = notify_get(&snac1, v);
                 xs *noti = notify_get(&snac1, v);
 
 
                 if (noti == NULL)
                 if (noti == NULL)
@@ -1740,6 +1740,8 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
                 const char *type  = xs_dict_get(noti, "type");
                 const char *type  = xs_dict_get(noti, "type");
                 const char *utype = xs_dict_get(noti, "utype");
                 const char *utype = xs_dict_get(noti, "utype");
                 const char *objid = xs_dict_get(noti, "objid");
                 const char *objid = xs_dict_get(noti, "objid");
+                const char *id    = xs_dict_get(noti, "id");
+                xs *fid = xs_replace(id, ".", "");
                 xs *actor = NULL;
                 xs *actor = NULL;
                 xs *entry = NULL;
                 xs *entry = NULL;
 
 
@@ -1752,6 +1754,13 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
                 if (is_hidden(&snac1, objid))
                 if (is_hidden(&snac1, objid))
                     continue;
                     continue;
 
 
+                if (max_id) {
+                    if (strcmp(fid, max_id) == 0)
+                        max_id = NULL;
+
+                    continue;
+                }
+
                 /* convert the type */
                 /* convert the type */
                 if (strcmp(type, "Like") == 0 || strcmp(type, "EmojiReact") == 0)
                 if (strcmp(type, "Like") == 0 || strcmp(type, "EmojiReact") == 0)
                     type = "favourite";
                     type = "favourite";
@@ -1778,12 +1787,15 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
 
 
                 mn = xs_dict_append(mn, "type", type);
                 mn = xs_dict_append(mn, "type", type);
 
 
-                xs *id = xs_replace(xs_dict_get(noti, "id"), ".", "");
-                mn = xs_dict_append(mn, "id", id);
+                mn = xs_dict_append(mn, "id", fid);
 
 
                 mn = xs_dict_append(mn, "created_at", xs_dict_get(noti, "date"));
                 mn = xs_dict_append(mn, "created_at", xs_dict_get(noti, "date"));
 
 
                 xs *acct = mastoapi_account(&snac1, actor);
                 xs *acct = mastoapi_account(&snac1, actor);
+
+                if (acct == NULL)
+                    continue;
+
                 mn = xs_dict_append(mn, "account", acct);
                 mn = xs_dict_append(mn, "account", acct);
 
 
                 if (strcmp(type, "follow") != 0 && !xs_is_null(objid)) {
                 if (strcmp(type, "follow") != 0 && !xs_is_null(objid)) {

+ 1 - 0
snac.h

@@ -298,6 +298,7 @@ const char *default_avatar_base64(void);
 xs_str *process_tags(snac *snac, const char *content, xs_list **tag);
 xs_str *process_tags(snac *snac, const char *content, xs_list **tag);
 
 
 const char *get_atto(const xs_dict *msg);
 const char *get_atto(const xs_dict *msg);
+const char *get_in_reply_to(const xs_dict *msg);
 xs_list *get_attachments(const xs_dict *msg);
 xs_list *get_attachments(const xs_dict *msg);
 
 
 xs_dict *msg_admiration(snac *snac, const char *object, const char *type);
 xs_dict *msg_admiration(snac *snac, const char *object, const char *type);