From 631e44a64a20741b5e4716bf75caf7fa743fef82 Mon Sep 17 00:00:00 2001 From: grunfink Date: Tue, 27 May 2025 21:08:57 +0200 Subject: Renamed timeline_here() to timeline_here_by_md5(), as it always should have been. --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'main.c') diff --git a/main.c b/main.c index 80df2d0..9cfbb0d 100644 --- a/main.c +++ b/main.c @@ -695,7 +695,7 @@ int main(int argc, char *argv[]) xs_json_dump(data, 4, stdout); enqueue_actor_refresh(&snac, xs_dict_get(data, "attributedTo"), 0); - if (!timeline_here(&snac, url)) + if (!timeline_here_by_md5(&snac, url)) timeline_add(&snac, url, data); else printf("Post %s already here\n", url); -- cgit From 5bc451159420d5d51a507fda82a623069cfae92b Mon Sep 17 00:00:00 2001 From: grunfink Date: Tue, 27 May 2025 21:14:23 +0200 Subject: New function timeline_here(). --- data.c | 8 ++++++++ html.c | 8 ++------ main.c | 2 +- mastoapi.c | 4 +--- snac.h | 1 + 5 files changed, 13 insertions(+), 10 deletions(-) (limited to 'main.c') diff --git a/data.c b/data.c index 9eada38..224976b 100644 --- a/data.c +++ b/data.c @@ -1400,6 +1400,14 @@ int timeline_here_by_md5(snac *snac, const char *md5) } +int timeline_here(snac *user, const char *id) +{ + xs *md5 = xs_md5_hex(id, strlen(id)); + + return timeline_here_by_md5(user, md5); +} + + int timeline_get_by_md5(snac *snac, const char *md5, xs_dict **msg) /* gets a message from the timeline */ { diff --git a/html.c b/html.c index 4aa0fa4..4c30355 100644 --- a/html.c +++ b/html.c @@ -2115,9 +2115,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, const char *parent = get_in_reply_to(msg); if (!xs_is_null(parent) && *parent) { - xs *md5 = xs_md5_hex(parent, strlen(parent)); - - if (!timeline_here_by_md5(user, md5)) { + if (!timeline_here(user, parent)) { xs_html_add(post_header, xs_html_tag("div", xs_html_attr("class", "snac-origin"), @@ -3773,9 +3771,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, q = url_acct; /* add the post to the timeline */ - xs *md5 = xs_md5_hex(q, strlen(q)); - - if (!timeline_here_by_md5(&snac, md5)) + if (!timeline_here(&snac, q)) timeline_add(&snac, q, object); } } diff --git a/main.c b/main.c index 9cfbb0d..80df2d0 100644 --- a/main.c +++ b/main.c @@ -695,7 +695,7 @@ int main(int argc, char *argv[]) xs_json_dump(data, 4, stdout); enqueue_actor_refresh(&snac, xs_dict_get(data, "attributedTo"), 0); - if (!timeline_here_by_md5(&snac, url)) + if (!timeline_here(&snac, url)) timeline_add(&snac, url, data); else printf("Post %s already here\n", url); diff --git a/mastoapi.c b/mastoapi.c index c88fd1b..df713a8 100644 --- a/mastoapi.c +++ b/mastoapi.c @@ -2508,9 +2508,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, /* reply something only for offset 0; otherwise, apps like Tusky keep asking again and again */ if (xs_startswith(q, "https://")) { - xs *md5 = xs_md5_hex(q, strlen(q)); - - if (!timeline_here_by_md5(&snac1, md5)) { + if (!timeline_here(&snac1, q)) { xs *object = NULL; int status; diff --git a/snac.h b/snac.h index 621ab8a..f32a90d 100644 --- a/snac.h +++ b/snac.h @@ -165,6 +165,7 @@ int pending_count(snac *user); double timeline_mtime(snac *snac); int timeline_touch(snac *snac); int timeline_here_by_md5(snac *snac, const char *md5); +int timeline_here(snac *snac, const char *id); int timeline_get_by_md5(snac *snac, const char *md5, xs_dict **msg); int timeline_del(snac *snac, const char *id); xs_str *user_index_fn(snac *user, const char *idx_name); -- cgit From 5ec55544e4d83503776f517d62262ae176ca15c6 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 29 May 2025 22:52:20 +0200 Subject: New command-line option 'poll_hashtag_rss'. --- main.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'main.c') diff --git a/main.c b/main.c index 80df2d0..c948b57 100644 --- a/main.c +++ b/main.c @@ -143,6 +143,11 @@ int main(int argc, char *argv[]) return 0; } + if (strcmp(cmd, "poll_hashtag_rss") == 0) { /** **/ + rss_poll_hashtags(); + return 0; + } + if (strcmp(cmd, "state") == 0) { /** **/ xs *shm_name = NULL; srv_state *p_state = srv_state_op(&shm_name, 1); -- cgit From 1ca5b346a556f2418c110b480ce1859ce7d5b36c Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 12 Jun 2025 12:11:34 +0200 Subject: The usage "screen" shows info only about the entered command. If there is no command or no command starts with that string, the full list is shown as before. --- main.c | 128 +++++++++++++++++++++++++++++++++++------------------------ xs_version.h | 2 +- 2 files changed, 77 insertions(+), 53 deletions(-) (limited to 'main.c') diff --git a/main.c b/main.c index c948b57..2995e3f 100644 --- a/main.c +++ b/main.c @@ -13,58 +13,82 @@ #include #include -int usage(void) +int usage(const char *cmd) { printf("snac " VERSION " - A simple, minimalistic ActivityPub instance\n"); printf("Copyright (c) 2022 - 2025 grunfink et al. / MIT license\n"); printf("\n"); - printf("Commands:\n"); - printf("\n"); - printf("init [{basedir}] Initializes the data storage\n"); - printf("upgrade {basedir} Upgrade to a new version\n"); - printf("adduser {basedir} [{uid}] Adds a new user\n"); - printf("deluser {basedir} {uid} Deletes a user\n"); - printf("httpd {basedir} Starts the HTTPD daemon\n"); - printf("purge {basedir} Purges old data\n"); - printf("state {basedir} Prints server state\n"); - printf("webfinger {basedir} {account} Queries about an account (@user@host or actor url)\n"); - printf("queue {basedir} {uid} Processes a user queue\n"); - printf("follow {basedir} {uid} {actor} Follows an actor\n"); - printf("unfollow {basedir} {uid} {actor} Unfollows an actor\n"); - printf("request {basedir} {uid} {url} Requests an object\n"); - printf("insert {basedir} {uid} {url} Requests an object and inserts it into the timeline\n"); - printf("actor {basedir} [{uid}] {url} Requests an actor\n"); - printf("note {basedir} {uid} {text} [files...] Sends a note with optional attachments\n"); - printf("note_unlisted {basedir} {uid} {text} [files...] Sends an unlisted note with optional attachments\n"); - printf("note_mention {basedir} {uid} {text} [files...] Sends a note only to mentioned accounts\n"); - printf("boost|announce {basedir} {uid} {url} Boosts (announces) a post\n"); - printf("unboost {basedir} {uid} {url} Unboosts a post\n"); - printf("resetpwd {basedir} {uid} Resets the password of a user\n"); - printf("ping {basedir} {uid} {actor} Pings an actor\n"); - printf("webfinger_s {basedir} {uid} {account} Queries about an account (@user@host or actor url)\n"); - printf("pin {basedir} {uid} {msg_url} Pins a message\n"); - printf("unpin {basedir} {uid} {msg_url} Unpins a message\n"); - printf("bookmark {basedir} {uid} {msg_url} Bookmarks a message\n"); - printf("unbookmark {basedir} {uid} {msg_url} Unbookmarks a message\n"); - printf("block {basedir} {instance_url} Blocks a full instance\n"); - printf("unblock {basedir} {instance_url} Unblocks a full instance\n"); - printf("limit {basedir} {uid} {actor} Limits an actor (drops their announces)\n"); - printf("unlimit {basedir} {uid} {actor} Unlimits an actor\n"); - printf("unmute {basedir} {uid} {actor} Unmutes a previously muted actor\n"); - printf("verify_links {basedir} {uid} Verifies a user's links (in the metadata)\n"); - printf("search {basedir} {uid} {regex} Searches posts by content\n"); - printf("export_csv {basedir} {uid} Exports data as CSV files\n"); - printf("alias {basedir} {uid} {account} Sets account (@user@host or actor url) as an alias\n"); - printf("migrate {basedir} {uid} Migrates to the account defined as the alias\n"); - printf("import_csv {basedir} {uid} Imports data from CSV files\n"); - printf("import_list {basedir} {uid} {file} Imports a Mastodon CSV list file\n"); - printf("import_block_list {basedir} {uid} {file} Imports a Mastodon CSV block list file\n"); - printf("lists {basedir} {uid} Returns the names of the lists created by the user\n"); - printf("list_members {basedir} {uid} {name} Returns the list of accounts inside a list\n"); - printf("create_list {basedir} {uid} {name} Creates a new list\n"); - printf("delete_list {basedir} {uid} {name} Deletes an existing list\n"); - printf("list_add {basedir} {uid} {name} {acct} Adds an account (@user@host or actor url) to a list\n"); - printf("list_del {basedir} {uid} {name} {actor} Deletes an actor URL from a list\n"); + + if (cmd == NULL) { + printf("Commands:\n"); + printf("\n"); + } + + const char *cmds = + "init [{basedir}] Initializes the data storage\n" + "upgrade {basedir} Upgrade to a new version\n" + "adduser {basedir} [{uid}] Adds a new user\n" + "deluser {basedir} {uid} Deletes a user\n" + "httpd {basedir} Starts the HTTPD daemon\n" + "purge {basedir} Purges old data\n" + "state {basedir} Prints server state\n" + "webfinger {basedir} {account} Queries about an account (@user@host or actor url)\n" + "queue {basedir} {uid} Processes a user queue\n" + "follow {basedir} {uid} {actor} Follows an actor\n" + "unfollow {basedir} {uid} {actor} Unfollows an actor\n" + "request {basedir} {uid} {url} Requests an object\n" + "insert {basedir} {uid} {url} Requests an object and inserts it into the timeline\n" + "actor {basedir} [{uid}] {url} Requests an actor\n" + "note {basedir} {uid} {text} [files...] Sends a note with optional attachments\n" + "note_unlisted {basedir} {uid} {text} [files...] Sends an unlisted note with optional attachments\n" + "note_mention {basedir} {uid} {text} [files...] Sends a note only to mentioned accounts\n" + "boost|announce {basedir} {uid} {url} Boosts (announces) a post\n" + "unboost {basedir} {uid} {url} Unboosts a post\n" + "resetpwd {basedir} {uid} Resets the password of a user\n" + "ping {basedir} {uid} {actor} Pings an actor\n" + "webfinger_s {basedir} {uid} {account} Queries about an account (@user@host or actor url)\n" + "pin {basedir} {uid} {msg_url} Pins a message\n" + "unpin {basedir} {uid} {msg_url} Unpins a message\n" + "bookmark {basedir} {uid} {msg_url} Bookmarks a message\n" + "unbookmark {basedir} {uid} {msg_url} Unbookmarks a message\n" + "block {basedir} {instance_url} Blocks a full instance\n" + "unblock {basedir} {instance_url} Unblocks a full instance\n" + "limit {basedir} {uid} {actor} Limits an actor (drops their announces)\n" + "unlimit {basedir} {uid} {actor} Unlimits an actor\n" + "unmute {basedir} {uid} {actor} Unmutes a previously muted actor\n" + "verify_links {basedir} {uid} Verifies a user's links (in the metadata)\n" + "search {basedir} {uid} {regex} Searches posts by content\n" + "export_csv {basedir} {uid} Exports data as CSV files\n" + "alias {basedir} {uid} {account} Sets account (@user@host or actor url) as an alias\n" + "migrate {basedir} {uid} Migrates to the account defined as the alias\n" + "import_csv {basedir} {uid} Imports data from CSV files\n" + "import_list {basedir} {uid} {file} Imports a Mastodon CSV list file\n" + "import_block_list {basedir} {uid} {file} Imports a Mastodon CSV block list file\n" + "lists {basedir} {uid} Returns the names of the lists created by the user\n" + "list_members {basedir} {uid} {name} Returns the list of accounts inside a list\n" + "create_list {basedir} {uid} {name} Creates a new list\n" + "delete_list {basedir} {uid} {name} Deletes an existing list\n" + "list_add {basedir} {uid} {name} {acct} Adds an account (@user@host or actor url) to a list\n" + "list_del {basedir} {uid} {name} {actor} Deletes an actor URL from a list\n"; + + if (cmd == NULL) + printf("%s", cmds); + else { + /* only show help for the entered command */ + xs *l = xs_split(cmds, "\n"); + const char *v; + int cnt = 0; + + xs_list_foreach(l, v) { + if (xs_startswith(v, cmd)) { + printf("%s\n", v); + cnt++; + } + } + + if (cnt == 0) + printf("%s", cmds); + } return 1; } @@ -94,7 +118,7 @@ int main(int argc, char *argv[]) umask(0007); if ((cmd = GET_ARGV()) == NULL) - return usage(); + return usage(cmd); if (strcmp(cmd, "init") == 0) { /** **/ /* initialize the data storage */ @@ -106,7 +130,7 @@ int main(int argc, char *argv[]) if ((basedir = getenv("SNAC_BASEDIR")) == NULL) { if ((basedir = GET_ARGV()) == NULL) - return usage(); + return usage(cmd); } if (strcmp(cmd, "upgrade") == 0) { /** **/ @@ -172,7 +196,7 @@ int main(int argc, char *argv[]) } if ((user = GET_ARGV()) == NULL) - return usage(); + return usage(cmd); if (strcmp(cmd, "block") == 0) { /** **/ int ret = instance_block(user); @@ -305,7 +329,7 @@ int main(int argc, char *argv[]) } if ((url = GET_ARGV()) == NULL) - return usage(); + return usage(cmd); if (strcmp(cmd, "list_members") == 0) { /** **/ xs *lid = list_maint(&snac, url, 4); diff --git a/xs_version.h b/xs_version.h index c7789a7..c9418a7 100644 --- a/xs_version.h +++ b/xs_version.h @@ -1 +1 @@ -/* 871d420cef893b6efe32869407294baf084ce3ab 2025-05-04T11:01:01+02:00 */ +/* 963b6129fca4fb5c009533db0ed602ab8ed5424d 2025-06-12T11:33:02+02:00 */ -- cgit From 7eecd4bb95116caef35d98f97e6e56f5dc910bd5 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 12 Jun 2025 12:14:18 +0200 Subject: Improved usage screen. --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'main.c') diff --git a/main.c b/main.c index 2995e3f..85576b6 100644 --- a/main.c +++ b/main.c @@ -80,7 +80,7 @@ int usage(const char *cmd) int cnt = 0; xs_list_foreach(l, v) { - if (xs_startswith(v, cmd)) { + if (xs_str_in(v, cmd) != -1) { printf("%s\n", v); cnt++; } -- cgit From e1fb414ffd4c46f51903f48ade7b399c0f5de9bb Mon Sep 17 00:00:00 2001 From: grunfink Date: Sun, 15 Jun 2025 09:43:42 +0200 Subject: Renamed some list command line options. create_list to list_create delete_list to list_delete. --- main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'main.c') diff --git a/main.c b/main.c index 85576b6..758e692 100644 --- a/main.c +++ b/main.c @@ -66,8 +66,8 @@ int usage(const char *cmd) "import_block_list {basedir} {uid} {file} Imports a Mastodon CSV block list file\n" "lists {basedir} {uid} Returns the names of the lists created by the user\n" "list_members {basedir} {uid} {name} Returns the list of accounts inside a list\n" - "create_list {basedir} {uid} {name} Creates a new list\n" - "delete_list {basedir} {uid} {name} Deletes an existing list\n" + "list_create {basedir} {uid} {name} Creates a new list\n" + "list_delete {basedir} {uid} {name} Deletes an existing list\n" "list_add {basedir} {uid} {name} {acct} Adds an account (@user@host or actor url) to a list\n" "list_del {basedir} {uid} {name} {actor} Deletes an actor URL from a list\n"; @@ -352,7 +352,7 @@ int main(int argc, char *argv[]) return 0; } - if (strcmp(cmd, "create_list") == 0) { /** **/ + if (strcmp(cmd, "list_create") == 0) { /** **/ xs *lid = list_maint(&snac, url, 4); if (lid == NULL) { @@ -365,7 +365,7 @@ int main(int argc, char *argv[]) return 0; } - if (strcmp(cmd, "delete_list") == 0) { /** **/ + if (strcmp(cmd, "list_delete") == 0) { /** **/ xs *lid = list_maint(&snac, url, 4); if (lid != NULL) { -- cgit From deb90ed0ac6dd5ccea4516b3988e16d95f9687b2 Mon Sep 17 00:00:00 2001 From: grunfink Date: Sun, 15 Jun 2025 09:44:56 +0200 Subject: Renamed cmd list_delete to list_remove. --- main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'main.c') diff --git a/main.c b/main.c index 758e692..5af3695 100644 --- a/main.c +++ b/main.c @@ -67,7 +67,7 @@ int usage(const char *cmd) "lists {basedir} {uid} Returns the names of the lists created by the user\n" "list_members {basedir} {uid} {name} Returns the list of accounts inside a list\n" "list_create {basedir} {uid} {name} Creates a new list\n" - "list_delete {basedir} {uid} {name} Deletes an existing list\n" + "list_remove {basedir} {uid} {name} Removes an existing list\n" "list_add {basedir} {uid} {name} {acct} Adds an account (@user@host or actor url) to a list\n" "list_del {basedir} {uid} {name} {actor} Deletes an actor URL from a list\n"; @@ -365,7 +365,7 @@ int main(int argc, char *argv[]) return 0; } - if (strcmp(cmd, "list_delete") == 0) { /** **/ + if (strcmp(cmd, "list_remove") == 0) { /** **/ xs *lid = list_maint(&snac, url, 4); if (lid != NULL) { -- cgit From 8c9eb18099370f34a577859d7fddea1d5f412612 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 19 Jun 2025 18:41:59 +0200 Subject: Minor tweak to usage screen. --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'main.c') diff --git a/main.c b/main.c index 5af3695..ddb02a8 100644 --- a/main.c +++ b/main.c @@ -58,7 +58,7 @@ int usage(const char *cmd) "unmute {basedir} {uid} {actor} Unmutes a previously muted actor\n" "verify_links {basedir} {uid} Verifies a user's links (in the metadata)\n" "search {basedir} {uid} {regex} Searches posts by content\n" - "export_csv {basedir} {uid} Exports data as CSV files\n" + "export_csv {basedir} {uid} Exports followers, lists, MUTEd and bookmarks to CSV\n" "alias {basedir} {uid} {account} Sets account (@user@host or actor url) as an alias\n" "migrate {basedir} {uid} Migrates to the account defined as the alias\n" "import_csv {basedir} {uid} Imports data from CSV files\n" -- cgit From a07458f408c304ae9d037c95bee77dbf4522f3f0 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 19 Jun 2025 19:19:08 +0200 Subject: New command-line option export_posts. --- main.c | 6 ++++++ snac.h | 2 ++ utils.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+) (limited to 'main.c') diff --git a/main.c b/main.c index ddb02a8..f271abc 100644 --- a/main.c +++ b/main.c @@ -59,6 +59,7 @@ int usage(const char *cmd) "verify_links {basedir} {uid} Verifies a user's links (in the metadata)\n" "search {basedir} {uid} {regex} Searches posts by content\n" "export_csv {basedir} {uid} Exports followers, lists, MUTEd and bookmarks to CSV\n" + "export_posts {basedir} {iod} Exports all posts to outbox.json\n" "alias {basedir} {uid} {account} Sets account (@user@host or actor url) as an alias\n" "migrate {basedir} {uid} Migrates to the account defined as the alias\n" "import_csv {basedir} {uid} Imports data from CSV files\n" @@ -308,6 +309,11 @@ int main(int argc, char *argv[]) return 0; } + if (strcmp(cmd, "export_posts") == 0) { /** **/ + export_posts(&snac); + return 0; + } + if (strcmp(cmd, "import_csv") == 0) { /** **/ import_csv(&snac); return 0; diff --git a/snac.h b/snac.h index 7f109e0..42fce87 100644 --- a/snac.h +++ b/snac.h @@ -434,6 +434,8 @@ void mastoapi_purge(void); void verify_links(snac *user); void export_csv(snac *user); +void export_posts(snac *user); + int migrate_account(snac *user); void import_blocked_accounts_csv(snac *user, const char *fn); diff --git a/utils.c b/utils.c index 7adbce2..5367f22 100644 --- a/utils.c +++ b/utils.c @@ -725,6 +725,58 @@ void export_csv(snac *user) } +void export_posts(snac *user) +/* exports all posts to an OrderedCollection */ +{ + xs *ifn = xs_fmt("%s/public.idx", user->basedir); + xs *index = index_list(ifn, XS_ALL); + xs *ofn = xs_fmt("%s/export/outbox.json", user->basedir); + FILE *f; + + if ((f = fopen(ofn, "w")) == NULL) { + snac_log(user, xs_fmt("Cannot create file %s", ofn)); + return; + } + + int cnt = 0; + + /* raw output */ + fprintf(f, "{\"@context\": \"https:/" "/www.w3.org/ns/activitystreams\","); + fprintf(f, "\"id\": \"outbox.json\","); + fprintf(f, "\"type\": \"OrderedCollection\","); + fprintf(f, "\"orderedItems\": ["); + + const char *md5; + + snac_log(user, xs_fmt("Creating %s...", ofn)); + + xs_list_foreach(index, md5) { + xs *obj = NULL; + + if (!valid_status(object_get_by_md5(md5, &obj))) + continue; + + const char *type = xs_dict_get(obj, "type"); + + if (!xs_is_string(type) || strcmp(type, "Note")) + continue; + + const char *atto = get_atto(obj); + + if (!xs_is_string(atto) || strcmp(atto, user->actor)) + continue; + + xs *c_msg = msg_create(user, obj); + xs_json_dump(c_msg, 0, f); + cnt++; + } + + fprintf(f, "], \"totalItems\": %d}", cnt); + + fclose(f); +} + + void import_blocked_accounts_csv(snac *user, const char *ifn) /* imports a Mastodon CSV file of blocked accounts */ { -- cgit From c976b9a334872e14aadc1f454680599468652231 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 26 Jun 2025 10:39:47 +0200 Subject: Sending notes from the cmdline allows setting an inReplyTo field. --- Makefile | 6 +++--- Makefile.NetBSD | 6 +++--- main.c | 23 +++++++++++++++++++---- 3 files changed, 25 insertions(+), 10 deletions(-) (limited to 'main.c') diff --git a/Makefile b/Makefile index 6059fef..5de2882 100644 --- a/Makefile +++ b/Makefile @@ -60,10 +60,10 @@ html.o: html.c xs.h xs_io.h xs_json.h xs_regex.h xs_set.h xs_openssl.h \ http.o: http.c xs.h xs_io.h xs_openssl.h xs_curl.h xs_time.h xs_json.h \ snac.h http_codes.h httpd.o: httpd.c xs.h xs_io.h xs_json.h xs_socket.h xs_unix_socket.h \ - xs_httpd.h xs_mime.h xs_time.h xs_openssl.h xs_fcgi.h xs_html.h snac.h \ - http_codes.h + xs_httpd.h xs_mime.h xs_time.h xs_openssl.h xs_fcgi.h xs_html.h \ + xs_webmention.h snac.h http_codes.h main.o: main.c xs.h xs_io.h xs_json.h xs_time.h xs_openssl.h xs_match.h \ - snac.h http_codes.h + xs_random.h snac.h http_codes.h mastoapi.o: mastoapi.c xs.h xs_hex.h xs_openssl.h xs_json.h xs_io.h \ xs_time.h xs_glob.h xs_set.h xs_random.h xs_url.h xs_mime.h xs_match.h \ xs_unicode.h snac.h http_codes.h diff --git a/Makefile.NetBSD b/Makefile.NetBSD index d19ab2d..ac5b052 100644 --- a/Makefile.NetBSD +++ b/Makefile.NetBSD @@ -49,10 +49,10 @@ html.o: html.c xs.h xs_io.h xs_json.h xs_regex.h xs_set.h xs_openssl.h \ http.o: http.c xs.h xs_io.h xs_openssl.h xs_curl.h xs_time.h xs_json.h \ snac.h http_codes.h httpd.o: httpd.c xs.h xs_io.h xs_json.h xs_socket.h xs_unix_socket.h \ - xs_httpd.h xs_mime.h xs_time.h xs_openssl.h xs_fcgi.h xs_html.h snac.h \ - http_codes.h + xs_httpd.h xs_mime.h xs_time.h xs_openssl.h xs_fcgi.h xs_html.h \ + xs_webmention.h snac.h http_codes.h main.o: main.c xs.h xs_io.h xs_json.h xs_time.h xs_openssl.h xs_match.h \ - snac.h http_codes.h + xs_random.h snac.h http_codes.h mastoapi.o: mastoapi.c xs.h xs_hex.h xs_openssl.h xs_json.h xs_io.h \ xs_time.h xs_glob.h xs_set.h xs_random.h xs_url.h xs_mime.h xs_match.h \ xs_unicode.h snac.h http_codes.h diff --git a/main.c b/main.c index f271abc..ce4e7ce 100644 --- a/main.c +++ b/main.c @@ -7,6 +7,7 @@ #include "xs_time.h" #include "xs_openssl.h" #include "xs_match.h" +#include "xs_random.h" #include "snac.h" @@ -779,12 +780,24 @@ int main(int argc, char *argv[]) xs *msg = NULL; xs *c_msg = NULL; xs *attl = xs_list_new(); - char *fn = NULL; + const char *fn = NULL; + const char *in_reply_to = NULL; + const char **next = NULL; /* iterate possible attachments */ while ((fn = GET_ARGV())) { FILE *f; + if (next) { + *next = fn; + next = NULL; + } + else + if (strcmp(fn, "-r") == 0) { + /* next argument is an inReplyTo */ + next = &in_reply_to; + } + else if ((f = fopen(fn, "rb")) != NULL) { /* get the file size and content */ fseek(f, 0, SEEK_END); @@ -794,8 +807,10 @@ int main(int argc, char *argv[]) fclose(f); char *ext = strrchr(fn, '.'); - xs *hash = xs_md5_hex(fn, strlen(fn)); - xs *id = xs_fmt("%s%s", hash, ext); + char rnd[32]; + xs_rnd_buf(rnd, sizeof(rnd)); + xs *hash = xs_md5_hex(rnd, sizeof(rnd)); + xs *id = xs_fmt("post-%s%s", hash, ext ? ext : ""); xs *url = xs_fmt("%s/s/%s", snac.actor, id); /* store */ @@ -856,7 +871,7 @@ int main(int argc, char *argv[]) if (strcmp(cmd, "note_unlisted") == 0) scope = 2; - msg = msg_note(&snac, content, NULL, NULL, attl, scope, getenv("LANG"), NULL); + msg = msg_note(&snac, content, NULL, in_reply_to, attl, scope, getenv("LANG"), NULL); c_msg = msg_create(&snac, msg); -- cgit