]> gitweb.ps.run Git - chirp/commitdiff
likes, comments, write, read
authorPatrick <patrick.schoenberger@posteo.de>
Mon, 28 Aug 2023 01:40:51 +0000 (03:40 +0200)
committerPatrick <patrick.schoenberger@posteo.de>
Mon, 28 Aug 2023 01:40:51 +0000 (03:40 +0200)
src/main.c

index dff0d17a83bd554836810ac2472af7005e3de70e..4c994d9d216a7ac83181d9b6a5bbb651813fc6c9 100644 (file)
@@ -1,3 +1,4 @@
+#include <stdint.h>\r
 #include <mongoose.h>\r
 #define STB_DS_IMPLEMENTATION\r
 #include <stb_ds.h>\r
@@ -7,83 +8,99 @@
 #define CONTENT_LEN 1024\r
 #define HTML_LEN 1024*8\r
 \r
-typedef struct post Post;\r
-typedef struct user User;\r
+typedef struct Post Post;\r
+typedef struct User User;\r
 \r
 User * UsersFind(struct mg_str name);\r
 \r
-// Post\r
+// Post / User\r
 \r
-struct post {\r
+struct Post {\r
   time_t timestamp;\r
   User * user;\r
   char content[CONTENT_LEN];\r
+  int likes;\r
+  Post * comments;\r
+  Post * parent;\r
 };\r
 \r
-\r
-\r
-// User\r
-\r
-struct user {\r
+struct User {\r
   char name[NAME_LEN];\r
   Post * posts;\r
   User ** following;\r
 };\r
 \r
+Post\r
+PostNew() {\r
+  Post result;\r
+  memset(&result, 0, sizeof(result));\r
+  return result;\r
+}\r
+\r
+void\r
+PostWrite(Post * post, FILE * f) {\r
+  fwrite(&post->timestamp, 8, 1, f);\r
+  fwrite(post->user->name, 1, sizeof(post->user->name), f);\r
+  fwrite(post->content, 1, sizeof(post->content), f);\r
+}\r
+\r
+void\r
+PostRead(Post * post, FILE * f) {\r
+  fread(&post->timestamp, 8, 1, f);\r
+  char name[NAME_LEN];\r
+  fread(name, 1, sizeof(name), f);\r
+  post->user = UsersFind(mg_str(name));\r
+  fread(post->content, 1, sizeof(post->content), f);\r
+}\r
+\r
 User\r
 UserNew(const char * name) {\r
   User result;\r
+  memset(&result, 0, sizeof(result));\r
   strcpy(result.name, name);\r
-  result.posts = NULL;\r
-  result.following = NULL;\r
   return result;\r
 }\r
 \r
 void\r
-UserWrite(User * user) {\r
-  char filename[128];\r
-  snprintf(filename, 128, "data/users/%s", user->name);\r
-  FILE * f = fopen(filename, "w");\r
-\r
-  int numFollowing = arrlen(user->following);\r
-  int numPosts = arrlen(user->posts);\r
-  fwrite(&numFollowing, sizeof(int), 1, f);\r
-  fwrite(&numPosts, sizeof(int), 1, f);\r
+UserWrite(User * user, FILE * f) {\r
+  fwrite(user->name, 1, sizeof(user->name), f);\r
+\r
+  uint32_t numFollowing = arrlen(user->following);\r
+  uint32_t numPosts = arrlen(user->posts);\r
+  fwrite(&numFollowing, 4, 1, f);\r
+  fwrite(&numPosts, 4, 1, f);\r
+\r
   for (int i = 0; i < numFollowing; i++) {\r
     fwrite(user->following[i]->name, 1, sizeof(user->following[i]->name), f);\r
   }\r
+\r
   for (int i = 0; i < numPosts; i++) {\r
-    fwrite(&user->posts[i].timestamp, sizeof(user->posts[i].timestamp), 1, f);\r
-    fwrite(user->posts[i].user->name, 1, sizeof(user->posts[i].user->name), f);\r
-    fwrite(user->posts[i].content, 1, sizeof(user->posts[i].content), f);\r
+    PostWrite(&user->posts[i], f);\r
   }\r
-  fclose(f);\r
 }\r
 \r
 void\r
-UserRead(User * user) {\r
-  char filename[128];\r
-  snprintf(filename, 128, "data/users/%s", user->name);\r
-  FILE * f = fopen(filename, "r");\r
-\r
-  int numFollowing;\r
-  int numPosts;\r
-  fread(&numFollowing, sizeof(int), 1, f);\r
-  fread(&numPosts, sizeof(int), 1, f);\r
+UserRead(User * user, FILE * f) {\r
+  fread(user->name, 1, sizeof(user->name), f);\r
+\r
+  uint32_t numFollowing;\r
+  uint32_t numPosts;\r
+  fread(&numFollowing, 1, 4, f);\r
+  fread(&numPosts, 1, 4, f);\r
+\r
+  user->following = NULL;\r
   for (int i = 0; i < numFollowing; i++) {\r
     char name[NAME_LEN];\r
     fread(name, 1, sizeof(name), f);\r
     arrput(user->following, UsersFind(mg_str(name)));\r
   }\r
+\r
+  user->posts = NULL;\r
   for (int i = 0; i < numPosts; i++) {\r
-    char name[NAME_LEN];\r
-    Post post;\r
-    fread(&post.timestamp, sizeof(post.timestamp), 1, f);\r
-    fread(name, 1, sizeof(name), f);\r
-    post.user = UsersFind(mg_str(name));\r
-    fread(post.content, 1, sizeof(post.content), f);\r
+    Post post = PostNew();\r
+    PostRead(&post, f);\r
+    arrput(user->posts, post);\r
   }\r
-  fclose(f);\r
 }\r
 \r
 \r
@@ -99,10 +116,6 @@ UsersSetup() {
   yas = UserNew("yas");\r
   tof = UserNew("tof");\r
 \r
-  // UserRead(&pat);\r
-  // UserRead(&yas);\r
-  // UserRead(&tof);\r
-\r
   arrput(pat.following, &yas);\r
   arrput(yas.following, &pat);\r
   arrput(tof.following, &yas);\r
@@ -128,7 +141,7 @@ UsersFind(struct mg_str name) {
 // HTML\r
 \r
 void\r
-http_redirect_home(struct mg_connection * c, struct mg_http_message * hm, User * user) {\r
+http_redirect(struct mg_connection * c, struct mg_http_message * hm) {\r
   struct mg_str *referer = mg_http_get_header(hm, "Referer");\r
 \r
   static char redirectHeaders[128];\r
@@ -166,16 +179,55 @@ html_user_not_found()
   return html;\r
 }\r
 \r
-char *\r
-html_post(Post * post) {\r
-  static char html[2048];\r
-  snprintf(html, 2048,\r
-    "<p>[%s] <a href=\"/user/%s\">%s</a>: %s</p>",\r
+int\r
+html_post(Post * post, char * buffer, int bufferLen) {\r
+  int result = 0;\r
+  int printed = 0;\r
+\r
+  printed = snprintf(buffer, bufferLen,\r
+    "<div style=\"border: 2px solid black; margin: 2px; padding: 2px;\">[%s] <a href=\"/user/%s\">%s</a>: %s <br />",\r
       ctime(&post->timestamp),\r
       post->user->name,\r
       post->user->name,\r
       post->content);\r
-  return html;\r
+  buffer += printed; bufferLen -= printed; result += printed;\r
+\r
+  if (post->likes > 0) {\r
+    printed = snprintf(buffer, bufferLen,\r
+      "Likes: %d<br />", post->likes);\r
+    buffer += printed; bufferLen -= printed; result += printed;\r
+  }\r
+\r
+  printed = snprintf(buffer, bufferLen,\r
+    "<form action=\"/api/like/%s/%llu\" method=\"post\">"\r
+      "<input type=\"submit\" value=\"Like!\">"\r
+    "</form>",\r
+      post->user->name,\r
+      (size_t)post);\r
+  buffer += printed; bufferLen -= printed; result += printed;\r
+  \r
+  if (arrlen(post->comments) > 0) {\r
+    printed = snprintf(buffer, bufferLen,\r
+      "Comments:<br />");\r
+    buffer += printed; bufferLen -= printed; result += printed;\r
+\r
+    for (int i = 0; i < arrlen(post->comments); i++) {\r
+      printed = html_post(&post->comments[i], buffer, bufferLen);\r
+      buffer += printed; bufferLen -= printed; result += printed;\r
+    }\r
+  }\r
+\r
+  printed = snprintf(buffer, bufferLen,\r
+    "<form action=\"/api/comment/%s/%llu\" method=\"post\">"\r
+      "<input type=\"text\" name=\"content\" autofocus>"\r
+      "<input type=\"submit\" value=\"Comment!\">"\r
+    "</form>"\r
+    "</div>",\r
+      post->user->name,\r
+      (size_t)post);\r
+  buffer += printed; bufferLen -= printed; result += printed;\r
+\r
+  return result;\r
 }\r
 \r
 char *\r
@@ -205,17 +257,26 @@ html_home(User * user)
           "<html>"\r
           "<body>"\r
           "<form action=\"/api/post/%s\" method=\"post\">"\r
-            "<input type=\"text\" name=\"content\"><br>"\r
+            "<input type=\"text\" name=\"content\" autofocus><br>"\r
             "<input type=\"submit\" value=\"Chirp!\">"\r
           "</form>",\r
           user->name);\r
+  snprintf(html+strlen(html), HTML_LEN-strlen(html),\r
+          "<form action=\"/api/write/%s\" method=\"post\">"\r
+            "<input type=\"submit\" value=\"Write!\">"\r
+          "</form>"\r
+          "<form action=\"/api/read/%s\" method=\"post\">"\r
+            "<input type=\"submit\" value=\"Read!\">"\r
+          "</form>",\r
+          user->name,\r
+          user->name);\r
   for (int i = 0; i < arrlen(posts); i++) {\r
-    snprintf(html+strlen(html), HTML_LEN-strlen(html),\r
-            html_post(posts[i]));\r
+    html_post(posts[i], html+strlen(html), HTML_LEN-strlen(html));\r
   }\r
   snprintf(html+strlen(html), HTML_LEN-strlen(html),\r
           "</body>"\r
           "</html>");\r
+  arrfree(posts);\r
   return html;\r
 }\r
 \r
@@ -228,13 +289,21 @@ html_user(User * user)
           "<html>"\r
           "<body>"\r
           "<form action=\"/api/post/%s\" method=\"post\">"\r
-            "<input type=\"text\" name=\"content\"><br>"\r
+            "<input type=\"text\" name=\"content\" autofocus><br>"\r
             "<input type=\"submit\" value=\"Chirp!\">"\r
           "</form>",\r
           user->name);\r
+  snprintf(html+strlen(html), HTML_LEN-strlen(html),\r
+          "<form action=\"/api/write/%s\" method=\"post\">"\r
+            "<input type=\"submit\" value=\"Write!\">"\r
+          "</form>"\r
+          "<form action=\"/api/read/%s\" method=\"post\">"\r
+            "<input type=\"submit\" value=\"Read!\">"\r
+          "</form>",\r
+          user->name,\r
+          user->name);\r
   for (int i = arrlen(user->posts) - 1; i >= 0; i--) {\r
-    snprintf(html+strlen(html), HTML_LEN-strlen(html),\r
-            html_post(&user->posts[i]));\r
+    html_post(&user->posts[i], html+strlen(html), HTML_LEN-strlen(html));\r
   }\r
   snprintf(html+strlen(html), HTML_LEN-strlen(html),\r
           "</body>"\r
@@ -260,23 +329,69 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data)
       //   hm->message.len, hm->message.ptr);\r
       \r
 \r
-      struct mg_str caps[2];\r
+      // TODO: make sure this diesnt error. shhhhhh!\r
+      struct mg_str caps[10];\r
 \r
       if (mg_match(hm->uri, mg_str("/api/post/*"), caps)) {\r
         User * user = UsersFind(caps[0]);\r
         \r
         if (user != NULL) {\r
           Post newPost;\r
+          newPost.likes = 0;\r
+          newPost.comments = NULL;\r
+          newPost.parent = NULL;\r
           newPost.timestamp = time(NULL);\r
           newPost.user = user;\r
           mg_http_get_var(&hm->body, "content", newPost.content, sizeof(newPost.content)-1);\r
           arrput(user->posts, newPost);\r
-\r
-          // UserWrite(user);\r
-\r
-          http_redirect_home(c, hm, user);\r
         }\r
       }\r
+      else if (mg_match(hm->uri, mg_str("/api/comment/*/*"), caps)) {\r
+        User * user = UsersFind(caps[0]);\r
+        \r
+        if (user != NULL) {\r
+          Post * parent = (Post *)atoll(caps[1].ptr);\r
+          if (parent != NULL) {\r
+            Post newComment;\r
+            newComment.likes = 0;\r
+            newComment.comments = NULL;\r
+            newComment.parent = parent;\r
+            newComment.timestamp = time(NULL);\r
+            newComment.user = user;\r
+            mg_http_get_var(&hm->body, "content", newComment.content, sizeof(newComment.content)-1);\r
+            arrput(parent->comments, newComment);\r
+          }\r
+        }\r
+      }\r
+      else if (mg_match(hm->uri, mg_str("/api/like/*/*"), caps)) {\r
+        User * user = UsersFind(caps[0]);\r
+        if (user != NULL) {\r
+          Post * post = (Post *)atoll(caps[1].ptr);\r
+          if (post != NULL)\r
+            post->likes++;\r
+        }\r
+      }\r
+      else if (mg_match(hm->uri, mg_str("/api/write/*"), caps)) {\r
+        User * user = UsersFind(caps[0]);\r
+        if (user != NULL) {\r
+          char filename[128];\r
+          snprintf(filename, 128, "data/users/%s", user->name);\r
+          FILE * f = fopen(filename, "w");\r
+          UserWrite(user, f);\r
+          fclose(f);\r
+        }\r
+      }\r
+      else if (mg_match(hm->uri, mg_str("/api/read/*"), caps)) {\r
+        User * user = UsersFind(caps[0]);\r
+        if (user != NULL) {\r
+          char filename[128];\r
+          snprintf(filename, 128, "data/users/%s", user->name);\r
+          FILE * f = fopen(filename, "r");\r
+          UserRead(user, f);\r
+          fclose(f);\r
+        }\r
+      }\r
+      http_redirect(c, hm);\r
     }\r
     // GET\r
     else if (mg_strcmp(hm->method, mg_str("GET")) == 0)\r