shithub: masto9

Download patch

ref: d7047b022e63c014469877be1faa54a977e51e89
parent: 25ce6ea9a2e96fc6c056ed752561475a90fc0a05
author: Julien Blanchard <jblanchard@makemusic.com>
date: Thu Mar 30 14:41:04 EDT 2023

Cleanup names, remove globals

--- a/http.c
+++ b/http.c
@@ -1,6 +1,7 @@
 #include <u.h>
 #include <libc.h>
 #include <stdio.h>
+#include <json.h>
 
 #include "masto9.h"
 
--- a/masto9.c
+++ b/masto9.c
@@ -7,10 +7,6 @@
 
 #include "masto9.h"
 
-char *URL = "https://fedi.9til.de/api/v1/timelines/home";
-char *POSTURL = "https://fedi.9til.de/api/v1/statuses";
-char *NOTIFICATIONSURL = "https://fedi.9til.de/api/v1/notifications";
-
 UserPasswd *
 getcredentials(char *host)
 {
@@ -18,13 +14,13 @@
 
 	p = auth_getuserpasswd(auth_getkey, "proto=pass service=mastodon server=%s", host);
 	if(p == nil)
-		sysfatal("mastofs: failed to retrieve token: %r");
+		sysfatal("masto9: failed to retrieve token: %r");
 
 	return p;
 }
 
 static JSON *
-get_json_key(JSON *obj, char *key)
+getjsonkey(JSON *obj, char *key)
 {
 	JSON *value = jsonbyname(obj, key);
 	if (value == nil)
@@ -33,37 +29,34 @@
 }
 
 void
-get_timeline(char *token, Toot toots[], char *after)
+gethome(char *token, char *host, Toot toots[], char *after)
 {
 	JSON *obj, *id, *content, *reblog_content, *account, *reblog_account, *handle, *reblog_handle, *display_name, *avatar, *reblog, *media_attachments, *type, *preview_url, *remote_url;
-	char *response, *tl_url;
+	char *endpoint;
 	int i = 0;
 
-  tl_url = emalloc(sizeof(char)*1024);
+  endpoint = emalloc(sizeof(char)*1024);
   if(after != nil) {
-    snprintf(tl_url, 1024, "%s?max_id=%s", URL, after);
+    snprintf(endpoint, 1024, "timelines/home?max_id=%s", after);
   } else {
-    tl_url = URL;
+    endpoint = "timelines/home";
   }
-	response = httpget(token, tl_url);
 
-	obj = jsonparse(response);
-	if (obj == nil)
-		sysfatal("jsonparse: not json");
-	if (obj->t != JSONArray)
+  obj = mastodonget(token, host, endpoint);
+  if (obj->t != JSONArray)
 		sysfatal("jsonparse: not an array");
 
 	for(JSONEl *p = obj->first; p != nil; p = p->next) {
 		JSON *toot_json = p->val;
 
-		id = get_json_key(toot_json, "id");
-		content = get_json_key(toot_json, "content");
-		account = get_json_key(toot_json, "account");
-		handle = get_json_key(account, "acct");
-		display_name = get_json_key(account, "display_name");
-		avatar = get_json_key(account, "avatar_static");
-		reblog = get_json_key(toot_json, "reblog");
-		media_attachments = get_json_key(toot_json, "media_attachments");
+		id = getjsonkey(toot_json, "id");
+		content = getjsonkey(toot_json, "content");
+		account = getjsonkey(toot_json, "account");
+		handle = getjsonkey(account, "acct");
+		display_name = getjsonkey(account, "display_name");
+		avatar = getjsonkey(account, "avatar_static");
+		reblog = getjsonkey(toot_json, "reblog");
+		media_attachments = getjsonkey(toot_json, "media_attachments");
 
 		Toot toot = emalloc(sizeof(Toot));
 		toot.id = strdup((char *)id->s);
@@ -72,15 +65,15 @@
 			toot.reblogged = 0;
 			toot.content = strdup((char *)content->s);
 		} else {
-			reblog_content = get_json_key(reblog, "content");
-			reblog_account = get_json_key(reblog, "account");
-			reblog_handle = get_json_key(reblog_account, "acct");
+			reblog_content = getjsonkey(reblog, "content");
+			reblog_account = getjsonkey(reblog, "account");
+			reblog_handle = getjsonkey(reblog_account, "acct");
 
 			toot.content = strdup((char *)reblog_content->s);
 			toot.reblogged_handle = strdup((char *)reblog_handle->s);
 			toot.reblogged = 1;
 
-			media_attachments = get_json_key(reblog, "media_attachments");
+			media_attachments = getjsonkey(reblog, "media_attachments");
 		};
 		toot.handle = strdup((char *)handle->s);
 		toot.display_name = strdup((char *)display_name->s);
@@ -92,9 +85,9 @@
 			for(JSONEl *at = media_attachments->first; at != nil; at = at->next) {
 				JSON *attachment_json = at->val;
 				Attachment attachment = emalloc(sizeof(Attachment));
-				type = get_json_key(attachment_json, "type");
-				preview_url = get_json_key(attachment_json, "preview_url");
-				remote_url = get_json_key(attachment_json, "remote_url");
+				type = getjsonkey(attachment_json, "type");
+				preview_url = getjsonkey(attachment_json, "preview_url");
+				remote_url = getjsonkey(attachment_json, "remote_url");
 				attachment.type = strdup((char *)type->s);
 
         if(strcmp(type->s, "image") == 0){
@@ -115,32 +108,30 @@
 }
 
 void
-get_notifications(char *token, Notification notifs[])
+notifications(char *token, char *host, Notification notifs[])
 {
 	JSON *obj, *id, *content, *display_name, *handle, *type, *account, *status;
-	char *response;
 	int i = 0;
 
-	response = httpget(token, NOTIFICATIONSURL);
+	obj = mastodonget(token, host, "notifications");
 
-  obj = jsonparse(response);
-	if (obj == nil)
-		sysfatal("jsonparse: not json");
-	if (obj->t != JSONArray)
+  if (obj->t != JSONArray)
 		sysfatal("jsonparse: not an array");
 
 	for(JSONEl *p = obj->first; p != nil; p = p->next) {
 		JSON *notif_json = p->val;
 
-		id = get_json_key(notif_json, "id");
-		type = get_json_key(notif_json, "type");
+		id = getjsonkey(notif_json, "id");
+		type = getjsonkey(notif_json, "type");
     if(strcmp(type->s, "follow") != 0) {
-      status = get_json_key(notif_json, "status");
-      content = get_json_key(status, "content");
+      status = getjsonkey(notif_json, "status");
+      content = getjsonkey(status, "content");
+    } else {
+      content = jsonparse("");
     }
-    account = get_json_key(notif_json, "account");
-    display_name = get_json_key(account, "display_name");
-    handle = get_json_key(account, "acct");
+    account = getjsonkey(notif_json, "account");
+    display_name = getjsonkey(account, "display_name");
+    handle = getjsonkey(account, "acct");
 
 		Notification notif = emalloc(sizeof(Notification));
 		notif.id = strdup((char *)id->s);
@@ -159,53 +150,76 @@
 }
 
 void
-post_toot(char *token, char *text)
+posttoot(char *token, char *host, char *text)
 {
-	httppost(token, POSTURL, concat("status=", text));
+  char url[MAXURL];
+  snprintf(url, MAXURL, "https://%s/api/v1/statuses", host);
+
+	httppost(token, url, concat("status=", text));
   print("Posted:\n %s\n", text);
 }
 
+char *
+tootauthor(char *token, char *host, char *id)
+{
+  JSON *obj, *account, *reblog;
+  char *endpoint;
+
+  endpoint = concat("statuses/", id);
+	obj = mastodonget(token, host, endpoint);
+
+  reblog = getjsonkey(obj, "reblog");
+  if(reblog != nil) {
+    account = getjsonkey(reblog, "account");
+  } else {
+    account = getjsonkey(obj, "account");
+  }
+
+  return getjsonkey(account, "acct")->s;
+}
+
 void
-action_toot(char *token, char *id, char *action)
+perform(char *token, char *host, char *id, char *action)
 {
-  char *response;
-  char url[1024];
-  snprintf(url, sizeof(url), "%s/%s/%s", POSTURL, id, action);
-  print("URL %s\n", url);
-  response = httppost(token, url, "");
-  print("Response:\n %s\n", response);
+  char url[MAXURL];
+  snprintf(url, sizeof(url), "%s/api/v1/statuses/%s/%s", host, id, action);
+  httppost(token, url, "");
 }
 
 void
-boost_toot(char *token, char *id)
+boost(char *token, char *host, char *id)
 {
-  action_toot(token, id, "reblog");
+  perform(token, host, id, "reblog");
+  print("Boosted toot.");
 }
 
 void
-unboost_toot(char *token, char *id)
+unboost(char *token, char *host, char *id)
 {
-  action_toot(token, id, "unreblog");
+  perform(token, host, id, "unreblog");
+  print("Unboosted toot.");
 }
 
 void
-fav_toot(char *token, char *id)
+fav(char *token, char *host, char *id)
 {
-  action_toot(token, id, "favourite");
+  perform(token, host, id, "favourite");
+  print("Favorited toot.");
 }
 
 void
-unfav_toot(char *token, char *id)
+unfav(char *token, char *host, char *id)
 {
-  action_toot(token, id, "unfavourite");
+  perform(token, host, id, "unfavourite");
+  print("Unfavorited toot.");
 }
 
 void
-reply_toot(char *token, char *id)
+reply(char *token, char *host, char *id)
 {
   char content[TOOTBUFSIZE];
   int fd, wait;
-  char *s, *t;
+  char *s, *t, *u, url[MAXURL];
   Biobuf body;
 
   wait = 0;
@@ -215,15 +229,18 @@
     close(open("/dev/text", OWRITE|OTRUNC|OCEXEC));
   if((fd = open("/dev/consctl", OWRITE|OCEXEC)) >= 0){
     write(fd, "holdon", 6);
-    print("Reply\n");
+    u = tootauthor(token, host, id);
+    print("Reply to %s\n", u);
     Binit(&body, 0, OREAD);
     if((s = Brdstr(&body, 0, 1)) != nil)
       t = smprint("%s", s);
     free(s);
     if(t != nil){
-      snprintf(content, TOOTBUFSIZE, "in_reply_to_id=%s&status=%s", id, t);
-      httppost(token, POSTURL, content);
-      print("\nReplied!\n");
+      snprintf(url, MAXURL, "%s/api/v1/statuses", host);
+      snprintf(content, TOOTBUFSIZE, "in_reply_to_id=%s&status=@%s %s", id, u, t);
+
+      httppost(token, url, content);
+      print("\nReply sent.\n");
       free(t);
     }else{
       fprint(2, "%r\n");
@@ -272,8 +289,8 @@
 char *
 cleanup(char *str)
 {
-	remove_tag(str, "<span");
-	remove_substring(str, "</span>");
+	removetag(str, "<span");
+	removesubstring(str, "</span>");
 
 	return str;
 }
@@ -282,16 +299,14 @@
 mastodonget(char *token, char *host, char *endpoint)
 {
 	JSON *obj;
-	char *response, url[MAX_URL];
+	char *response, url[MAXURL];
 
-	snprintf(url, MAX_URL, "https://%s/api/v1/%s", host, endpoint);
+	snprintf(url, MAXURL, "https://%s/api/v1/%s", host, endpoint);
 	response = httpget(token, url);
 
 	obj = jsonparse(response);
 	if (obj == nil)
 		sysfatal("jsonparse: not json");
-	if (obj->t != JSONArray)
-		sysfatal("jsonparse: not an array");
 
 	return(obj);
 }
@@ -303,12 +318,12 @@
 }
 
 void
-display_toots(Toot toots[], char *server)
+displaytoots(Toot toots[], char *server)
 {
   Biobuf out;
   Binit(&out, 1, OWRITE);
 
-  for (int i=0;i<TOOTS_COUNT;i++) {
+  for (int i=0;i<TOOTSCOUNT;i++) {
     Toot toot = toots[i];
     char *username;
 
@@ -337,12 +352,12 @@
 }
 
 void
-display_notifications(Notification notifs[])
+displaynotifications(Notification notifs[])
 {
   Biobuf out;
   Binit(&out, 1, OWRITE);
 
-  for (int i=0;i<NOTIFS_COUNT;i++) {
+  for (int i=0;i<NOTIFSCOUNT;i++) {
     Notification notif = notifs[i];
     char *username;
 
@@ -350,17 +365,18 @@
     snprintf(username, 256, "%s (%s)", notif.display_name, notif.handle);
 
     if (strcmp(notif.type, "reblog") == 0) {
-      Bprint(&out, "⊙ %s retooted\n %s\n", username, fmthtml(cleanup(notif.content)));
+      Bprint(&out, "\n⊙ %s retooted\n %s", username, fmthtml(cleanup(notif.content)));
     } else if (strcmp(notif.type, "favourite") == 0) {
-      Bprint(&out, "⊙ %s favorited\n %s\n", username, fmthtml(cleanup(notif.content)));
+      Bprint(&out, "\n⊙ %s favorited\n %s", username, fmthtml(cleanup(notif.content)));
     } else if (strcmp(notif.type, "mention") == 0) {
-      Bprint(&out, "⊙ %s mentioned you\n %s\n", username, fmthtml(cleanup(notif.content)));
+      Bprint(&out, "\n⊙ %s mentioned you\n %s", username, fmthtml(cleanup(notif.content)));
     } else if (strcmp(notif.type, "follow") == 0) {
-      Bprint(&out, "⊙ %s followed you\n\n", username);
+      Bprint(&out, "\n⊙ %s followed you\n", username);
     } else if (strcmp(notif.type, "poll") == 0) {
-      Bprint(&out, "⊙ %s poll ended\n %s\n", username, fmthtml(cleanup(notif.content)));
+      Bprint(&out, "\n⊙ %s poll ended\n %s", username, fmthtml(cleanup(notif.content)));
     }
   }
+  Bprint(&out, "\n");
   Bflush(&out);
 }
 
@@ -369,7 +385,7 @@
 main(int argc, char**argv)
 {
   UserPasswd *p;
-  char *token, *server, *command, *text, *id;
+  char *token, *host, *command, *text, *id;
 
   if(argc < 2)
 		usage();
@@ -376,41 +392,45 @@
 
   JSONfmtinstall();
 
-  server = argv[1];
+  host = argv[1];
   command = argv[2];
 
-  p = getcredentials(server);
+  p = getcredentials(host);
 	token = p->passwd;
 
   if(command == nil) {
-    get_timeline(token, toots, nil);
-    display_toots(toots, server);
+    Toot toots[TOOTSCOUNT];
+    gethome(token, host, toots, nil);
+    displaytoots(toots, host);
   } else if(strcmp(command, "toot") == 0) {
     text = argv[3];
-    post_toot(token, text);
+    posttoot(token, host, text);
   } else if(strcmp(command, "fav") == 0) {
     id = argv[3];
-    fav_toot(token, id);
+    fav(token, host, id);
   } else if(strcmp(command, "unfav") == 0) {
     id = argv[3];
-    unfav_toot(token, id);
+    unfav(token, host, id);
   } else if(strcmp(command, "boost") == 0) {
     id = argv[3];
-    boost_toot(token, id);
+    boost(token, host, id);
   } else if(strcmp(command, "unboost") == 0) {
     id = argv[3];
-    unboost_toot(token, id);
+    unboost(token, host, id);
   } else if(strcmp(command, "reply") == 0) {
     id = argv[3];
-    reply_toot(token, id);
+    reply(token, host, id);
   } else if(strcmp(command, "more") == 0) {
     id = argv[3];
-    get_timeline(token, toots, id);
-    display_toots(toots, server);
+    Toot toots[TOOTSCOUNT];
+    gethome(token, host, toots, id);
+    displaytoots(toots, host);
   } else if(strcmp(command, "notifications") == 0) {
-    get_notifications(token, notifs);
-    display_notifications(notifs);
+    Notification notifs[NOTIFSCOUNT];
+    notifications(token, host, notifs);
+    displaynotifications(notifs);
   }
 
+  free(p);
 	exits(nil);
 }
--- a/masto9.h
+++ b/masto9.h
@@ -36,13 +36,13 @@
 enum {
 	TOOTBUFSIZE = 8192,
 	TLBUFSIZE = 512000,
-	MAX_URL = 1024,
-	TOOTS_COUNT = 20,
-	NOTIFS_COUNT = 15
+	MAXURL = 1024,
+	TOOTSCOUNT = 20,
+	NOTIFSCOUNT = 40
 };
 
-Toot toots[TOOTS_COUNT];
-Notification notifs[40];
+JSON *mastodonget(char *token, char *host, char *endpoint);
+char *tootauthor(char *token, char *host, char *id);
 
 /* http */
 char *httpget(char *token, char *url);
@@ -57,5 +57,5 @@
 char *esmprint(char*, ...);
 char *fslurp(int, int*);
 u32int strhash(char *);
-void remove_substring(char *, char *);
-void remove_tag(char *, char *);
+void removesubstring(char *, char *);
+void removetag(char *, char *);
--- a/util.c
+++ b/util.c
@@ -3,6 +3,7 @@
 #include <bio.h>
 #include <thread.h>
 #include <regexp.h>
+#include <json.h>
 
 #include "masto9.h"
 
@@ -131,7 +132,7 @@
 }
 
 void
-remove_substring(char *str, char *sub)
+removesubstring(char *str, char *sub)
 {
   int len = strlen(sub);
 
@@ -141,7 +142,7 @@
 }
 
 void
-remove_tag(char *str, char *tag)
+removetag(char *str, char *tag)
 {
   char *start = strstr(str, tag);