From: Patrick Date: Sat, 26 Aug 2023 20:34:01 +0000 (+0200) Subject: posts, following X-Git-Url: https://gitweb.ps.run/chirp/commitdiff_plain/46cdeacd5f0bb421055d628e21c71f4e2b7e36c4 posts, following --- diff --git a/src/main.c b/src/main.c index d26da8a..fb7ef33 100644 --- a/src/main.c +++ b/src/main.c @@ -1,59 +1,323 @@ -#include "mongoose.h" +#include +#define STB_DS_IMPLEMENTATION +#include + + +#define NAME_LEN 32 +#define CONTENT_LEN 1024 +#define HTML_LEN 1024*8 + +typedef struct post Post; +typedef struct user User; + +User * UsersFind(struct mg_str name); + +// Post + +struct post { + time_t timestamp; + User * user; + char content[CONTENT_LEN]; +}; + + + +// User + +struct user { + char name[NAME_LEN]; + Post * posts; + User ** following; +}; + +User +UserNew(const char * name) { + User result; + strcpy(result.name, name); + result.posts = NULL; + result.following = NULL; + return result; +} + +void +UserWrite(User * user) { + char filename[128]; + snprintf(filename, 128, "data/users/%s", user->name); + FILE * f = fopen(filename, "w"); + + int numFollowing = arrlen(user->following); + int numPosts = arrlen(user->posts); + fwrite(&numFollowing, sizeof(int), 1, f); + fwrite(&numPosts, sizeof(int), 1, f); + for (int i = 0; i < numFollowing; i++) { + fwrite(user->following[i]->name, 1, sizeof(user->following[i]->name), f); + } + for (int i = 0; i < numPosts; i++) { + fwrite(&user->posts[i].timestamp, sizeof(user->posts[i].timestamp), 1, f); + fwrite(user->posts[i].user->name, 1, sizeof(user->posts[i].user->name), f); + fwrite(user->posts[i].content, 1, sizeof(user->posts[i].content), f); + } + fclose(f); +} + +void +UserRead(User * user) { + char filename[128]; + snprintf(filename, 128, "data/users/%s", user->name); + FILE * f = fopen(filename, "r"); + + int numFollowing; + int numPosts; + fread(&numFollowing, sizeof(int), 1, f); + fread(&numPosts, sizeof(int), 1, f); + for (int i = 0; i < numFollowing; i++) { + char name[NAME_LEN]; + fread(name, 1, sizeof(name), f); + arrput(user->following, UsersFind(mg_str(name))); + } + for (int i = 0; i < numPosts; i++) { + char name[NAME_LEN]; + Post post; + fread(&post.timestamp, sizeof(post.timestamp), 1, f); + fread(name, 1, sizeof(name), f); + post.user = UsersFind(mg_str(name)); + fread(post.content, 1, sizeof(post.content), f); + } + fclose(f); +} + + + +// Users + +User ** g_users; +static User pat, yas, tof; + +void +UsersSetup() { + pat = UserNew("pat"); + yas = UserNew("yas"); + tof = UserNew("tof"); + + UserRead(&pat); + UserRead(&yas); + UserRead(&tof); + + arrput(pat.following, &yas); + arrput(yas.following, &pat); + arrput(tof.following, &yas); + arrput(tof.following, &pat); + + arrput(g_users, &pat); + arrput(g_users, &yas); + arrput(g_users, &tof); +} + +User * +UsersFind(struct mg_str name) { + for (int i = 0; i < arrlen(g_users); i++) { + User * user = g_users[i]; + if (strncmp(user->name, name.ptr, name.len) == 0) + return user; + } + return NULL; +} + // HTML +void +http_redirect_home(struct mg_connection * c, struct mg_http_message * hm, User * user) { + struct mg_str *referer = mg_http_get_header(hm, "Referer"); + + static char redirectHeaders[128]; + snprintf(redirectHeaders, 128, + "Location: %.*s\r\n", + referer->len, referer->ptr); + mg_http_reply(c, 303, redirectHeaders, ""); +} + char * -html_user_post(struct mg_str user) { - static char html[1024]; - snprintf(html, 1024, - "" - "" - "" - "
" - "
" - " " - "
" - "" - "", - user.len, user.ptr); - return html; +html_404() +{ + static char html[1024]; + snprintf(html, 1024, + "" + "" + "" + "

Eeeeeeh? The Website's Under Construction

" + "" + ""); + return html; } -// Post +char * +html_user_not_found() +{ + static char html[1024]; + snprintf(html, 1024, + "" + "" + "" + "

User was not found :/

" + "" + ""); + return html; +} + +char * +html_post(Post * post) { + static char html[2048]; + snprintf(html, 2048, + "

[%s] %s: %s

", + ctime(&post->timestamp), + post->user->name, + post->user->name, + post->content); + return html; +} +char * +html_home(User * user) +{ + Post ** posts = NULL; + for (int i = 0; i < arrlen(user->following); i++) { + User * userF = user->following[i]; + for (int j = 0; j < arrlen(userF->posts); j++) { + Post * post = &userF->posts[j]; + bool inserted = false; + for (int k = 0; k < arrlen(posts); k++) { + if (post->timestamp > posts[k]->timestamp) { + arrins(posts, k, post); + inserted = true; + break; + } + } + if (! inserted) + arrput(posts, post); + } + } + static char html[HTML_LEN]; + snprintf(html, HTML_LEN, + "" + "" + "" + "
" + "
" + "" + "
", + user->name); + for (int i = 0; i < arrlen(posts); i++) { + snprintf(html+strlen(html), HTML_LEN-strlen(html), + html_post(posts[i])); + } + snprintf(html+strlen(html), HTML_LEN-strlen(html), + "" + ""); + return html; +} +char * +html_user(User * user) +{ + static char html[HTML_LEN]; + snprintf(html, HTML_LEN, + "" + "" + "" + "
" + "
" + "" + "
", + user->name); + for (int i = arrlen(user->posts) - 1; i >= 0; i--) { + snprintf(html+strlen(html), HTML_LEN-strlen(html), + html_post(&user->posts[i])); + } + snprintf(html+strlen(html), HTML_LEN-strlen(html), + "" + ""); + return html; +} -// User +static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) +{ + if (ev == MG_EV_HTTP_MSG) + { + struct mg_http_message *hm = (struct mg_http_message *)ev_data; + + // POST + if (mg_strcmp(hm->method, mg_str("POST")) == 0) + { + // printf("POST: %.*s %.*s\n", + // hm->uri.len, hm->uri.ptr, + // hm->body.len, hm->body.ptr); + // printf("Message: %.*s\n", + // hm->message.len, hm->message.ptr); + + struct mg_str caps[2]; + if (mg_match(hm->uri, mg_str("/api/post/*"), caps)) { + User * user = UsersFind(caps[0]); + + if (user != NULL) { + Post newPost; + newPost.timestamp = time(NULL); + newPost.user = user; + mg_http_get_var(&hm->body, "content", newPost.content, sizeof(newPost.content)-1); + arrput(user->posts, newPost); -static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { - if (ev == MG_EV_HTTP_MSG) { - struct mg_http_message *hm = (struct mg_http_message *) ev_data; - if (mg_strcmp(hm->method, mg_str("post"))) { - printf("POST: %.*s\n", hm->body.len, hm->body.ptr); + UserWrite(user); + + http_redirect_home(c, hm, user); + } + } } - if (mg_http_match_uri(hm, "/user/*/post")) { - struct mg_str caps[2]; - printf("uri: %.*s\n", hm->uri.len, hm->uri.ptr); - mg_match(hm->uri, mg_str("/user/*/post"), caps); - mg_http_reply(c, 200, "", html_user_post(caps[0])); + // GET + else if (mg_strcmp(hm->method, mg_str("GET")) == 0) + { + struct mg_str caps[2]; + + if (mg_match(hm->uri, mg_str("/home/*"), caps)) { + User * user = UsersFind(caps[0]); + + if (user == NULL) + mg_http_reply(c, 200, "", html_user_not_found()); + else + mg_http_reply(c, 200, "", html_home(user)); + } + else if (mg_match(hm->uri, mg_str("/user/*"), caps)) { + User * user = UsersFind(caps[0]); + + if (user == NULL) + mg_http_reply(c, 200, "", html_user_not_found()); + else + mg_http_reply(c, 200, "", html_user(user)); + } + else { + mg_http_reply(c, 404, "", html_404()); + } } else { - mg_http_reply(c, 404, "", "Not found :/"); + mg_http_reply(c, 404, "", "Unknown"); } } } -int main(int argc, char *argv[]) { +int main(int argc, char *argv[]) +{ + UsersSetup(); + struct mg_mgr mgr; - mg_mgr_init(&mgr); // Init manager - mg_http_listen(&mgr, "http://0.0.0.0:8000", fn, &mgr); // Setup listener - for (;;) mg_mgr_poll(&mgr, 1000); // Event loop - mg_mgr_free(&mgr); // Cleanup + mg_mgr_init(&mgr); + mg_http_listen(&mgr, "http://0.0.0.0:8000", fn, &mgr); + while (1) + mg_mgr_poll(&mgr, 1000); + mg_mgr_free(&mgr); return 0; }