diff options
| author | 2025-07-16 20:21:20 +0200 | |
|---|---|---|
| committer | 2025-07-16 20:21:20 +0200 | |
| commit | 3554a73aa50526631961efcca78c6c8eb2a16911 (patch) | |
| tree | fc4c21a65337ab8ecb4fb00aa551ee21997faf6f /main.c | |
| parent | po/de_DE.po aktualisiert (diff) | |
| parent | Updated RELEASE_NOTES. (diff) | |
| download | snac2-3554a73aa50526631961efcca78c6c8eb2a16911.tar.gz snac2-3554a73aa50526631961efcca78c6c8eb2a16911.tar.xz snac2-3554a73aa50526631961efcca78c6c8eb2a16911.zip | |
Merge pull request 'master' (#9) from grunfink/snac2:master into master
Reviewed-on: https://codeberg.org/zen/snac2/pulls/9
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 166 |
1 files changed, 108 insertions, 58 deletions
| @@ -7,64 +7,90 @@ | |||
| 7 | #include "xs_time.h" | 7 | #include "xs_time.h" |
| 8 | #include "xs_openssl.h" | 8 | #include "xs_openssl.h" |
| 9 | #include "xs_match.h" | 9 | #include "xs_match.h" |
| 10 | #include "xs_random.h" | ||
| 10 | 11 | ||
| 11 | #include "snac.h" | 12 | #include "snac.h" |
| 12 | 13 | ||
| 13 | #include <sys/stat.h> | 14 | #include <sys/stat.h> |
| 14 | #include <sys/wait.h> | 15 | #include <sys/wait.h> |
| 15 | 16 | ||
| 16 | int usage(void) | 17 | int usage(const char *cmd) |
| 17 | { | 18 | { |
| 18 | printf("snac " VERSION " - A simple, minimalistic ActivityPub instance\n"); | 19 | printf("snac " VERSION " - A simple, minimalistic ActivityPub instance\n"); |
| 19 | printf("Copyright (c) 2022 - 2025 grunfink et al. / MIT license\n"); | 20 | printf("Copyright (c) 2022 - 2025 grunfink et al. / MIT license\n"); |
| 20 | printf("\n"); | 21 | printf("\n"); |
| 21 | printf("Commands:\n"); | 22 | |
| 22 | printf("\n"); | 23 | if (cmd == NULL) { |
| 23 | printf("init [{basedir}] Initializes the data storage\n"); | 24 | printf("Commands:\n"); |
| 24 | printf("upgrade {basedir} Upgrade to a new version\n"); | 25 | printf("\n"); |
| 25 | printf("adduser {basedir} [{uid}] Adds a new user\n"); | 26 | } |
| 26 | printf("deluser {basedir} {uid} Deletes a user\n"); | 27 | |
| 27 | printf("httpd {basedir} Starts the HTTPD daemon\n"); | 28 | const char *cmds = |
| 28 | printf("purge {basedir} Purges old data\n"); | 29 | "init [{basedir}] Initializes the data storage\n" |
| 29 | printf("state {basedir} Prints server state\n"); | 30 | "upgrade {basedir} Upgrade to a new version\n" |
| 30 | printf("webfinger {basedir} {account} Queries about an account (@user@host or actor url)\n"); | 31 | "adduser {basedir} [{uid}] Adds a new user\n" |
| 31 | printf("queue {basedir} {uid} Processes a user queue\n"); | 32 | "deluser {basedir} {uid} Deletes a user\n" |
| 32 | printf("follow {basedir} {uid} {actor} Follows an actor\n"); | 33 | "httpd {basedir} Starts the HTTPD daemon\n" |
| 33 | printf("unfollow {basedir} {uid} {actor} Unfollows an actor\n"); | 34 | "purge {basedir} Purges old data\n" |
| 34 | printf("request {basedir} {uid} {url} Requests an object\n"); | 35 | "state {basedir} Prints server state\n" |
| 35 | printf("insert {basedir} {uid} {url} Requests an object and inserts it into the timeline\n"); | 36 | "webfinger {basedir} {account} Queries about an account (@user@host or actor url)\n" |
| 36 | printf("actor {basedir} [{uid}] {url} Requests an actor\n"); | 37 | "queue {basedir} {uid} Processes a user queue\n" |
| 37 | printf("note {basedir} {uid} {text} [files...] Sends a note with optional attachments\n"); | 38 | "follow {basedir} {uid} {actor} Follows an actor\n" |
| 38 | printf("note_unlisted {basedir} {uid} {text} [files...] Sends an unlisted note with optional attachments\n"); | 39 | "unfollow {basedir} {uid} {actor} Unfollows an actor\n" |
| 39 | printf("note_mention {basedir} {uid} {text} [files...] Sends a note only to mentioned accounts\n"); | 40 | "request {basedir} {uid} {url} Requests an object\n" |
| 40 | printf("boost|announce {basedir} {uid} {url} Boosts (announces) a post\n"); | 41 | "insert {basedir} {uid} {url} Requests an object and inserts it into the timeline\n" |
| 41 | printf("unboost {basedir} {uid} {url} Unboosts a post\n"); | 42 | "actor {basedir} [{uid}] {url} Requests an actor\n" |
| 42 | printf("resetpwd {basedir} {uid} Resets the password of a user\n"); | 43 | "note {basedir} {uid} {text} [files...] Sends a note with optional attachments\n" |
| 43 | printf("ping {basedir} {uid} {actor} Pings an actor\n"); | 44 | "note_unlisted {basedir} {uid} {text} [files...] Sends an unlisted note with optional attachments\n" |
| 44 | printf("webfinger_s {basedir} {uid} {account} Queries about an account (@user@host or actor url)\n"); | 45 | "note_mention {basedir} {uid} {text} [files...] Sends a note only to mentioned accounts\n" |
| 45 | printf("pin {basedir} {uid} {msg_url} Pins a message\n"); | 46 | "boost|announce {basedir} {uid} {url} Boosts (announces) a post\n" |
| 46 | printf("unpin {basedir} {uid} {msg_url} Unpins a message\n"); | 47 | "unboost {basedir} {uid} {url} Unboosts a post\n" |
| 47 | printf("bookmark {basedir} {uid} {msg_url} Bookmarks a message\n"); | 48 | "resetpwd {basedir} {uid} Resets the password of a user\n" |
| 48 | printf("unbookmark {basedir} {uid} {msg_url} Unbookmarks a message\n"); | 49 | "ping {basedir} {uid} {actor} Pings an actor\n" |
| 49 | printf("block {basedir} {instance_url} Blocks a full instance\n"); | 50 | "webfinger_s {basedir} {uid} {account} Queries about an account (@user@host or actor url)\n" |
| 50 | printf("unblock {basedir} {instance_url} Unblocks a full instance\n"); | 51 | "pin {basedir} {uid} {msg_url} Pins a message\n" |
| 51 | printf("limit {basedir} {uid} {actor} Limits an actor (drops their announces)\n"); | 52 | "unpin {basedir} {uid} {msg_url} Unpins a message\n" |
| 52 | printf("unlimit {basedir} {uid} {actor} Unlimits an actor\n"); | 53 | "bookmark {basedir} {uid} {msg_url} Bookmarks a message\n" |
| 53 | printf("unmute {basedir} {uid} {actor} Unmutes a previously muted actor\n"); | 54 | "unbookmark {basedir} {uid} {msg_url} Unbookmarks a message\n" |
| 54 | printf("verify_links {basedir} {uid} Verifies a user's links (in the metadata)\n"); | 55 | "block {basedir} {instance_url} Blocks a full instance\n" |
| 55 | printf("search {basedir} {uid} {regex} Searches posts by content\n"); | 56 | "unblock {basedir} {instance_url} Unblocks a full instance\n" |
| 56 | printf("export_csv {basedir} {uid} Exports data as CSV files\n"); | 57 | "limit {basedir} {uid} {actor} Limits an actor (drops their announces)\n" |
| 57 | printf("alias {basedir} {uid} {account} Sets account (@user@host or actor url) as an alias\n"); | 58 | "unlimit {basedir} {uid} {actor} Unlimits an actor\n" |
| 58 | printf("migrate {basedir} {uid} Migrates to the account defined as the alias\n"); | 59 | "unmute {basedir} {uid} {actor} Unmutes a previously muted actor\n" |
| 59 | printf("import_csv {basedir} {uid} Imports data from CSV files\n"); | 60 | "verify_links {basedir} {uid} Verifies a user's links (in the metadata)\n" |
| 60 | printf("import_list {basedir} {uid} {file} Imports a Mastodon CSV list file\n"); | 61 | "search {basedir} {uid} {regex} Searches posts by content\n" |
| 61 | printf("import_block_list {basedir} {uid} {file} Imports a Mastodon CSV block list file\n"); | 62 | "export_csv {basedir} {uid} Exports followers, lists, MUTEd and bookmarks to CSV\n" |
| 62 | printf("lists {basedir} {uid} Returns the names of the lists created by the user\n"); | 63 | "export_posts {basedir} {iod} Exports all posts to outbox.json\n" |
| 63 | printf("list_members {basedir} {uid} {name} Returns the list of accounts inside a list\n"); | 64 | "alias {basedir} {uid} {account} Sets account (@user@host or actor url) as an alias\n" |
| 64 | printf("create_list {basedir} {uid} {name} Creates a new list\n"); | 65 | "migrate {basedir} {uid} Migrates to the account defined as the alias\n" |
| 65 | printf("delete_list {basedir} {uid} {name} Deletes an existing list\n"); | 66 | "import_csv {basedir} {uid} Imports data from CSV files\n" |
| 66 | printf("list_add {basedir} {uid} {name} {acct} Adds an account (@user@host or actor url) to a list\n"); | 67 | "import_list {basedir} {uid} {file} Imports a Mastodon CSV list file\n" |
| 67 | printf("list_del {basedir} {uid} {name} {actor} Deletes an actor URL from a list\n"); | 68 | "import_block_list {basedir} {uid} {file} Imports a Mastodon CSV block list file\n" |
| 69 | "lists {basedir} {uid} Returns the names of the lists created by the user\n" | ||
| 70 | "list_members {basedir} {uid} {name} Returns the list of accounts inside a list\n" | ||
| 71 | "list_create {basedir} {uid} {name} Creates a new list\n" | ||
| 72 | "list_remove {basedir} {uid} {name} Removes an existing list\n" | ||
| 73 | "list_add {basedir} {uid} {name} {acct} Adds an account (@user@host or actor url) to a list\n" | ||
| 74 | "list_del {basedir} {uid} {name} {actor} Deletes an actor URL from a list\n"; | ||
| 75 | |||
| 76 | if (cmd == NULL) | ||
| 77 | printf("%s", cmds); | ||
| 78 | else { | ||
| 79 | /* only show help for the entered command */ | ||
| 80 | xs *l = xs_split(cmds, "\n"); | ||
| 81 | const char *v; | ||
| 82 | int cnt = 0; | ||
| 83 | |||
| 84 | xs_list_foreach(l, v) { | ||
| 85 | if (xs_str_in(v, cmd) != -1) { | ||
| 86 | printf("%s\n", v); | ||
| 87 | cnt++; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | if (cnt == 0) | ||
| 92 | printf("%s", cmds); | ||
| 93 | } | ||
| 68 | 94 | ||
| 69 | return 1; | 95 | return 1; |
| 70 | } | 96 | } |
| @@ -94,7 +120,7 @@ int main(int argc, char *argv[]) | |||
| 94 | umask(0007); | 120 | umask(0007); |
| 95 | 121 | ||
| 96 | if ((cmd = GET_ARGV()) == NULL) | 122 | if ((cmd = GET_ARGV()) == NULL) |
| 97 | return usage(); | 123 | return usage(cmd); |
| 98 | 124 | ||
| 99 | if (strcmp(cmd, "init") == 0) { /** **/ | 125 | if (strcmp(cmd, "init") == 0) { /** **/ |
| 100 | /* initialize the data storage */ | 126 | /* initialize the data storage */ |
| @@ -106,7 +132,7 @@ int main(int argc, char *argv[]) | |||
| 106 | 132 | ||
| 107 | if ((basedir = getenv("SNAC_BASEDIR")) == NULL) { | 133 | if ((basedir = getenv("SNAC_BASEDIR")) == NULL) { |
| 108 | if ((basedir = GET_ARGV()) == NULL) | 134 | if ((basedir = GET_ARGV()) == NULL) |
| 109 | return usage(); | 135 | return usage(cmd); |
| 110 | } | 136 | } |
| 111 | 137 | ||
| 112 | if (strcmp(cmd, "upgrade") == 0) { /** **/ | 138 | if (strcmp(cmd, "upgrade") == 0) { /** **/ |
| @@ -143,6 +169,11 @@ int main(int argc, char *argv[]) | |||
| 143 | return 0; | 169 | return 0; |
| 144 | } | 170 | } |
| 145 | 171 | ||
| 172 | if (strcmp(cmd, "poll_hashtag_rss") == 0) { /** **/ | ||
| 173 | rss_poll_hashtags(); | ||
| 174 | return 0; | ||
| 175 | } | ||
| 176 | |||
| 146 | if (strcmp(cmd, "state") == 0) { /** **/ | 177 | if (strcmp(cmd, "state") == 0) { /** **/ |
| 147 | xs *shm_name = NULL; | 178 | xs *shm_name = NULL; |
| 148 | srv_state *p_state = srv_state_op(&shm_name, 1); | 179 | srv_state *p_state = srv_state_op(&shm_name, 1); |
| @@ -167,7 +198,7 @@ int main(int argc, char *argv[]) | |||
| 167 | } | 198 | } |
| 168 | 199 | ||
| 169 | if ((user = GET_ARGV()) == NULL) | 200 | if ((user = GET_ARGV()) == NULL) |
| 170 | return usage(); | 201 | return usage(cmd); |
| 171 | 202 | ||
| 172 | if (strcmp(cmd, "block") == 0) { /** **/ | 203 | if (strcmp(cmd, "block") == 0) { /** **/ |
| 173 | int ret = instance_block(user); | 204 | int ret = instance_block(user); |
| @@ -279,6 +310,11 @@ int main(int argc, char *argv[]) | |||
| 279 | return 0; | 310 | return 0; |
| 280 | } | 311 | } |
| 281 | 312 | ||
| 313 | if (strcmp(cmd, "export_posts") == 0) { /** **/ | ||
| 314 | export_posts(&snac); | ||
| 315 | return 0; | ||
| 316 | } | ||
| 317 | |||
| 282 | if (strcmp(cmd, "import_csv") == 0) { /** **/ | 318 | if (strcmp(cmd, "import_csv") == 0) { /** **/ |
| 283 | import_csv(&snac); | 319 | import_csv(&snac); |
| 284 | return 0; | 320 | return 0; |
| @@ -300,7 +336,7 @@ int main(int argc, char *argv[]) | |||
| 300 | } | 336 | } |
| 301 | 337 | ||
| 302 | if ((url = GET_ARGV()) == NULL) | 338 | if ((url = GET_ARGV()) == NULL) |
| 303 | return usage(); | 339 | return usage(cmd); |
| 304 | 340 | ||
| 305 | if (strcmp(cmd, "list_members") == 0) { /** **/ | 341 | if (strcmp(cmd, "list_members") == 0) { /** **/ |
| 306 | xs *lid = list_maint(&snac, url, 4); | 342 | xs *lid = list_maint(&snac, url, 4); |
| @@ -323,7 +359,7 @@ int main(int argc, char *argv[]) | |||
| 323 | return 0; | 359 | return 0; |
| 324 | } | 360 | } |
| 325 | 361 | ||
| 326 | if (strcmp(cmd, "create_list") == 0) { /** **/ | 362 | if (strcmp(cmd, "list_create") == 0) { /** **/ |
| 327 | xs *lid = list_maint(&snac, url, 4); | 363 | xs *lid = list_maint(&snac, url, 4); |
| 328 | 364 | ||
| 329 | if (lid == NULL) { | 365 | if (lid == NULL) { |
| @@ -336,7 +372,7 @@ int main(int argc, char *argv[]) | |||
| 336 | return 0; | 372 | return 0; |
| 337 | } | 373 | } |
| 338 | 374 | ||
| 339 | if (strcmp(cmd, "delete_list") == 0) { /** **/ | 375 | if (strcmp(cmd, "list_remove") == 0) { /** **/ |
| 340 | xs *lid = list_maint(&snac, url, 4); | 376 | xs *lid = list_maint(&snac, url, 4); |
| 341 | 377 | ||
| 342 | if (lid != NULL) { | 378 | if (lid != NULL) { |
| @@ -744,12 +780,24 @@ int main(int argc, char *argv[]) | |||
| 744 | xs *msg = NULL; | 780 | xs *msg = NULL; |
| 745 | xs *c_msg = NULL; | 781 | xs *c_msg = NULL; |
| 746 | xs *attl = xs_list_new(); | 782 | xs *attl = xs_list_new(); |
| 747 | char *fn = NULL; | 783 | const char *fn = NULL; |
| 784 | const char *in_reply_to = NULL; | ||
| 785 | const char **next = NULL; | ||
| 748 | 786 | ||
| 749 | /* iterate possible attachments */ | 787 | /* iterate possible attachments */ |
| 750 | while ((fn = GET_ARGV())) { | 788 | while ((fn = GET_ARGV())) { |
| 751 | FILE *f; | 789 | FILE *f; |
| 752 | 790 | ||
| 791 | if (next) { | ||
| 792 | *next = fn; | ||
| 793 | next = NULL; | ||
| 794 | } | ||
| 795 | else | ||
| 796 | if (strcmp(fn, "-r") == 0) { | ||
| 797 | /* next argument is an inReplyTo */ | ||
| 798 | next = &in_reply_to; | ||
| 799 | } | ||
| 800 | else | ||
| 753 | if ((f = fopen(fn, "rb")) != NULL) { | 801 | if ((f = fopen(fn, "rb")) != NULL) { |
| 754 | /* get the file size and content */ | 802 | /* get the file size and content */ |
| 755 | fseek(f, 0, SEEK_END); | 803 | fseek(f, 0, SEEK_END); |
| @@ -759,8 +807,10 @@ int main(int argc, char *argv[]) | |||
| 759 | fclose(f); | 807 | fclose(f); |
| 760 | 808 | ||
| 761 | char *ext = strrchr(fn, '.'); | 809 | char *ext = strrchr(fn, '.'); |
| 762 | xs *hash = xs_md5_hex(fn, strlen(fn)); | 810 | char rnd[32]; |
| 763 | xs *id = xs_fmt("%s%s", hash, ext); | 811 | xs_rnd_buf(rnd, sizeof(rnd)); |
| 812 | xs *hash = xs_md5_hex(rnd, sizeof(rnd)); | ||
| 813 | xs *id = xs_fmt("post-%s%s", hash, ext ? ext : ""); | ||
| 764 | xs *url = xs_fmt("%s/s/%s", snac.actor, id); | 814 | xs *url = xs_fmt("%s/s/%s", snac.actor, id); |
| 765 | 815 | ||
| 766 | /* store */ | 816 | /* store */ |
| @@ -821,7 +871,7 @@ int main(int argc, char *argv[]) | |||
| 821 | if (strcmp(cmd, "note_unlisted") == 0) | 871 | if (strcmp(cmd, "note_unlisted") == 0) |
| 822 | scope = 2; | 872 | scope = 2; |
| 823 | 873 | ||
| 824 | msg = msg_note(&snac, content, NULL, NULL, attl, scope, getenv("LANG"), NULL); | 874 | msg = msg_note(&snac, content, NULL, in_reply_to, attl, scope, getenv("LANG"), NULL); |
| 825 | 875 | ||
| 826 | c_msg = msg_create(&snac, msg); | 876 | c_msg = msg_create(&snac, msg); |
| 827 | 877 | ||