ref: 963900f6a1fce690e901acad6265789d533a2fa0
parent: 5b0cf2e6a0ed85420a471a48c43a253e931237a4
author: Julien Blanchard <jblanchard@makemusic.com>
date: Fri Apr 14 09:10:25 EDT 2023
Extract display stuff
--- a/README.md
+++ b/README.md
@@ -8,6 +8,7 @@
Available commands:
+- `home` to view your notifications. Abbrev `h`
- `toot 'TEXT'` to post a new textual toot. Abbrev `t`
- `tootwithfile ['TEXT'] FILEPATH` to post a new toot with a file and optional text. . Abbrev `tf`
- `reply ID` to reply to a toot. Abbrev `r`
@@ -17,7 +18,7 @@
- `more ID` to view the timeline starting from a toot
- `debug ID` to view a toot JSON
-if no COMMAND is provided masto9 defaults to reading your timeline.
+if no COMMAND is provided masto9 defaults to `home`.
### Installation
--- /dev/null
+++ b/display.c
@@ -1,0 +1,116 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <json.h>
+
+#include "masto9.h"
+
+static char *
+cleanup(char *str)
+{
+ removetag(str, "<span");
+ removesubstring(str, "</span>");
+
+ return str;
+}
+
+static char *
+fmthtml(char *msg)
+{
+ int wr[2], rd[2], n;
+ char buf[TOOTBUFSIZE];
+
+ if(pipe(wr) == -1 || pipe(rd) == -1)
+ sysfatal("fmthtml: pipe: %r");
+ switch(fork()) {
+ case -1:
+ sysfatal("fmthtml: fork: %r");
+ break;
+ case 0:
+ close(wr[0]);
+ close(rd[1]);
+ dup(wr[1], 0);
+ dup(rd[0], 1);
+ execl("/bin/htmlfmt", "htmlfmt -cutf-8 -j", nil);
+ sysfatal("fmthtml: exec: %r");
+ break;
+ default:
+ close(wr[1]);
+ close(rd[0]);
+ write(wr[0], msg, strlen(msg));
+ close(wr[0]);
+ n = readn(rd[1], buf, sizeof(buf));
+ close(rd[1]);
+ if(n == -1)
+ sysfatal("fmthtml: read: %r\n");
+ buf[n] = 0;
+ return buf;
+ }
+ return buf;
+}
+
+void
+displaytoots(Toot toots[], char *server)
+{
+ Biobuf out;
+ Binit(&out, 1, OWRITE);
+
+ for(int i = 0; i < TOOTSCOUNT; i++) {
+ Toot toot = toots[i];
+ char *username;
+
+ username = esmprint("%s (%s)", toot.displayname, toot.handle);
+
+ Bprint(&out, "\n\n——————————\n");
+ if(toot.reblogged == 1) {
+ Bprint(&out, "⊙ %s retooted %s:\n", username, toot.rebloggedhandle);
+ } else {
+ Bprint(&out, "⊙ %s:\n", username);
+ }
+ Bprint(&out, "\n%s", fmthtml(cleanup(toot.content)));
+ if(toot.attachmentscount > 0) {
+ for(int j = 0; j < toot.attachmentscount; j++) {
+ Attachment *attachment = toot.mediaattachments[j];
+ Bprint(&out, "\n[%s] %s", attachment->type, attachment->url);
+ }
+ Bprint(&out, "\n");
+ }
+ Bprint(&out, "\nReply[%s] | Boost[%s] | Favorite[%s]", toot.id, toot.id,
+ toot.id);
+ }
+ Bprint(&out, "\n\n\n⇒ Send the next line to load more");
+ Bprint(&out, "\nmasto9 %s more %s\n\n", server, toots[TOOTSCOUNT - 1].id);
+ Bflush(&out);
+}
+
+void
+displaynotifications(Notification notifs[])
+{
+ Biobuf out;
+ Binit(&out, 1, OWRITE);
+
+ for(int i = 0; i < NOTIFSCOUNT; i++) {
+ Notification notif = notifs[i];
+ char *username;
+
+ username = esmprint("%s (%s)", notif.displayname, notif.handle);
+
+ if(strcmp(notif.type, "reblog") == 0) {
+ Bprint(&out, "\n⊙ %s retooted\n %s", username,
+ fmthtml(cleanup(notif.content)));
+ } else if(strcmp(notif.type, "favourite") == 0) {
+ Bprint(&out, "\n⊙ %s favorited\n %s", username,
+ fmthtml(cleanup(notif.content)));
+ } else if(strcmp(notif.type, "mention") == 0) {
+ Bprint(&out, "\n⊙ %s mentioned you\n %s", username,
+ fmthtml(cleanup(notif.content)));
+ } else if(strcmp(notif.type, "follow") == 0) {
+ Bprint(&out, "\n⊙ %s followed you\n", username);
+ } else if(strcmp(notif.type, "poll") == 0) {
+ Bprint(&out, "\n⊙ %s poll ended\n %s", username,
+ fmthtml(cleanup(notif.content)));
+ }
+ }
+ Bprint(&out, "\n");
+ Bflush(&out);
+}
--- a/masto9.c
+++ b/masto9.c
@@ -7,7 +7,7 @@
#include "masto9.h"
-UserPasswd *
+static UserPasswd *
getcredentials(char *host)
{
UserPasswd *p;
@@ -19,12 +19,27 @@
return p;
}
-void
+static JSON *
+mastodonget(char *token, char *host, char *endpoint)
+{
+ JSON *obj;
+ char *response, *url;
+
+ url = esmprint("https://%s/api/v1/%s", host, endpoint);
+ response = httpget(token, url);
+
+ if((obj = jsonparse(response)) == nil)
+ sysfatal("mastodonget: jsonparse: not json");
+
+ return (obj);
+}
+
+static void
gethome(char *token, char *host, Toot toots[], char *beforeid)
{
- JSON *obj, *id, *content, *reblogcontent, *account, *reblogaccount,
- *handle, *rebloghandle, *displayname, *avatar, *reblog,
- *mediaattachments, *type, *previewurl, *remoteurl;
+ JSON *obj, *id, *content, *reblogcontent, *account, *reblogaccount, *handle,
+ *rebloghandle, *displayname, *avatar, *reblog, *mediaattachments, *type,
+ *previewurl, *remoteurl;
char *endpoint;
int i = 0;
@@ -100,7 +115,7 @@
jsonfree(obj);
}
-void
+static void
getnotifications(char *token, char *host, Notification *notifs, char *filter)
{
JSON *obj, *id, *content, *displayname, *handle, *type, *account, *status;
@@ -148,7 +163,7 @@
jsonfree(obj);
}
-void
+static void
posttoot(char *token, char *host, char *text)
{
char *url;
@@ -158,7 +173,7 @@
print("Posted:\n %s\n", text);
}
-char *
+static char *
tootauthor(char *token, char *host, char *id)
{
JSON *obj, *account, *reblog;
@@ -183,7 +198,7 @@
return response;
}
-void
+static void
postattachment(char *token, char *host, char *text, char *filepath)
{
JSON *obj, *id;
@@ -208,7 +223,7 @@
print("Posted toot\n");
}
-void
+static void
perform(char *token, char *host, char *id, char *action)
{
char *url;
@@ -216,7 +231,7 @@
httppost(token, url, "");
}
-void
+static void
boost(char *token, char *host, char *id)
{
perform(token, host, id, "reblog");
@@ -223,7 +238,7 @@
print("Boosted toot.");
}
-void
+static void
unboost(char *token, char *host, char *id)
{
perform(token, host, id, "unreblog");
@@ -230,7 +245,7 @@
print("Unboosted toot.");
}
-void
+static void
fav(char *token, char *host, char *id)
{
perform(token, host, id, "favourite");
@@ -237,7 +252,7 @@
print("Favorited toot.");
}
-void
+static void
unfav(char *token, char *host, char *id)
{
perform(token, host, id, "unfavourite");
@@ -244,19 +259,16 @@
print("Unfavorited toot.");
}
-void
+static void
reply(char *token, char *host, char *id)
{
char *content;
- int fd, wait;
+ int fd;
char *s, *t, *u, *url;
Biobuf body;
- wait = 0;
t = nil;
- if(wait)
- close(open("/dev/text", OWRITE | OTRUNC | OCEXEC));
if((fd = open("/dev/consctl", OWRITE | OCEXEC)) >= 0) {
write(fd, "holdon", 6);
u = tootauthor(token, host, id);
@@ -266,7 +278,7 @@
t = esmprint("%s", s);
free(s);
if(t != nil) {
- url = esmprint("%s/api/v1/statuses", host);
+ url = esmprint("https://%s/api/v1/statuses", host);
content = esmprint("in_reply_to_id=%s&status=@%s %s", id, u, t);
httppost(token, url, content);
@@ -281,139 +293,13 @@
}
}
-char *
-fmthtml(char *msg)
-{
- int wr[2], rd[2], n;
- char buf[TOOTBUFSIZE];
-
- if(pipe(wr) == -1 || pipe(rd) == -1)
- sysfatal("fmthtml: pipe: %r");
- switch(fork()) {
- case -1:
- sysfatal("fmthtml: fork: %r");
- break;
- case 0:
- close(wr[0]);
- close(rd[1]);
- dup(wr[1], 0);
- dup(rd[0], 1);
- execl("/bin/htmlfmt", "htmlfmt -cutf-8 -j", nil);
- sysfatal("fmthtml: exec: %r");
- break;
- default:
- close(wr[1]);
- close(rd[0]);
- write(wr[0], msg, strlen(msg));
- close(wr[0]);
- n = readn(rd[1], buf, sizeof(buf));
- close(rd[1]);
- if(n == -1)
- sysfatal("fmthtml: read: %r\n");
- buf[n] = 0;
- return buf;
- }
- return buf;
-}
-
-char *
-cleanup(char *str)
-{
- removetag(str, "<span");
- removesubstring(str, "</span>");
-
- return str;
-}
-
-JSON *
-mastodonget(char *token, char *host, char *endpoint)
-{
- JSON *obj;
- char *response, *url;
-
- url = esmprint("https://%s/api/v1/%s", host, endpoint);
- response = httpget(token, url);
-
- if((obj = jsonparse(response)) == nil)
- sysfatal("mastodonget: jsonparse: not json");
-
- return (obj);
-}
-
-void
+static void
usage(void)
{
sysfatal("usage: masto9 DOMAIN [COMMAND] [DATA]");
}
-void
-displaytoots(Toot toots[], char *server)
-{
- Biobuf out;
- Binit(&out, 1, OWRITE);
-
- for(int i = 0; i < TOOTSCOUNT; i++) {
- Toot toot = toots[i];
- char *username;
-
- username = esmprint("%s (%s)", toot.displayname, toot.handle);
-
- Bprint(&out, "\n\n——————————\n");
- if(toot.reblogged == 1) {
- Bprint(&out, "⊙ %s retooted %s:\n", username,
- toot.rebloggedhandle);
- } else {
- Bprint(&out, "⊙ %s:\n", username);
- }
- Bprint(&out, "\n%s", fmthtml(cleanup(toot.content)));
- if(toot.attachmentscount > 0) {
- for(int j = 0; j < toot.attachmentscount; j++) {
- Attachment *attachment = toot.mediaattachments[j];
- Bprint(&out, "\n[%s] %s", attachment->type, attachment->url);
- }
- Bprint(&out, "\n");
- }
- Bprint(&out, "\nReply[%s] | Boost[%s] | Favorite[%s]", toot.id, toot.id,
- toot.id);
- }
- Bprint(&out, "\n\n\n⇒ Send the next line to load more");
- Bprint(&out, "\n6.out %s more %s\n\n", server, toots[19].id);
- Bflush(&out);
-}
-
-void
-displaynotifications(Notification notifs[])
-{
- Biobuf out;
- Binit(&out, 1, OWRITE);
-
- for(int i = 0; i < NOTIFSCOUNT; i++) {
- Notification notif = notifs[i];
- char *username;
-
- username = esmprint("%s (%s)", notif.displayname, notif.handle);
-
- if(strcmp(notif.type, "reblog") == 0) {
- Bprint(&out, "\n⊙ %s retooted\n %s", username,
- fmthtml(cleanup(notif.content)));
- } else if(strcmp(notif.type, "favourite") == 0) {
- Bprint(&out, "\n⊙ %s favorited\n %s", username,
- fmthtml(cleanup(notif.content)));
- } else if(strcmp(notif.type, "mention") == 0) {
- Bprint(&out, "\n⊙ %s mentioned you\n %s", username,
- fmthtml(cleanup(notif.content)));
- } else if(strcmp(notif.type, "follow") == 0) {
- Bprint(&out, "\n⊙ %s followed you\n", username);
- } else if(strcmp(notif.type, "poll") == 0) {
- Bprint(&out, "\n⊙ %s poll ended\n %s", username,
- fmthtml(cleanup(notif.content)));
- }
- }
- Bprint(&out, "\n");
- Bflush(&out);
-}
-
-void
+static void
debug(char *token, char *host, char *id)
{
JSON *obj;
@@ -429,7 +315,7 @@
main(int argc, char **argv)
{
UserPasswd *p;
- char *token, *host, *command, *text, *id, *filepath;
+ char *token, *host, *cmd, *text, *id, *filepath;
if(argc < 2)
usage();
@@ -437,20 +323,19 @@
JSONfmtinstall();
host = argv[1];
- command = argv[2];
+ cmd = argv[2];
p = getcredentials(host);
token = p->passwd;
- if(command == nil) {
+ if(cmd == nil || strcmp(cmd, "home") == 0 || strcmp(cmd, "h") == 0) {
Toot toots[TOOTSCOUNT];
gethome(token, host, toots, nil);
displaytoots(toots, host);
- } else if(strcmp(command, "toot") == 0 || strcmp(command, "t") == 0) {
+ } else if(strcmp(cmd, "toot") == 0 || strcmp(cmd, "t") == 0) {
text = argv[3];
posttoot(token, host, text);
- } else if(strcmp(command, "tootwithfile") == 0 ||
- strcmp(command, "tf") == 0) {
+ } else if(strcmp(cmd, "tootwithfile") == 0 || strcmp(cmd, "tf") == 0) {
if(argc > 4) {
text = argv[3];
filepath = argv[4];
@@ -459,40 +344,39 @@
filepath = argv[3];
}
postattachment(token, host, text, filepath);
- } else if(strcmp(command, "fav") == 0 || strcmp(command, "f") == 0) {
+ } else if(strcmp(cmd, "fav") == 0 || strcmp(cmd, "f") == 0) {
id = argv[3];
fav(token, host, id);
- } else if(strcmp(command, "unfav") == 0 || strcmp(command, "uf") == 0) {
+ } else if(strcmp(cmd, "unfav") == 0 || strcmp(cmd, "uf") == 0) {
id = argv[3];
unfav(token, host, id);
- } else if(strcmp(command, "boost") == 0 || strcmp(command, "b") == 0) {
+ } else if(strcmp(cmd, "boost") == 0 || strcmp(cmd, "b") == 0) {
id = argv[3];
boost(token, host, id);
- } else if(strcmp(command, "unboost") == 0 || strcmp(command, "ub") == 0) {
+ } else if(strcmp(cmd, "unboost") == 0 || strcmp(cmd, "ub") == 0) {
id = argv[3];
unboost(token, host, id);
- } else if(strcmp(command, "reply") == 0 || strcmp(command, "r") == 0) {
+ } else if(strcmp(cmd, "reply") == 0 || strcmp(cmd, "r") == 0) {
id = argv[3];
reply(token, host, id);
- } else if(strcmp(command, "debug") == 0) {
+ } else if(strcmp(cmd, "debug") == 0) {
id = argv[3];
debug(token, host, id);
- } else if(strcmp(command, "more") == 0) {
+ } else if(strcmp(cmd, "more") == 0) {
id = argv[3];
Toot toots[TOOTSCOUNT];
gethome(token, host, toots, id);
displaytoots(toots, host);
- } else if(strcmp(command, "notifications") == 0 ||
- strcmp(command, "n") == 0) {
+ } else if(strcmp(cmd, "notifications") == 0 || strcmp(cmd, "n") == 0) {
Notification notifs[NOTIFSCOUNT];
getnotifications(token, host, notifs, "");
displaynotifications(notifs);
- } else if(strcmp(command, "mentions") == 0 || strcmp(command, "m") == 0) {
+ } else if(strcmp(cmd, "mentions") == 0 || strcmp(cmd, "m") == 0) {
Notification notifs[NOTIFSCOUNT];
getnotifications(token, host, notifs, "mention");
displaynotifications(notifs);
} else {
- print("Unknown command %s.\n", command);
+ print("Unknown command %s.\n", cmd);
usage();
}
--- a/masto9.h
+++ b/masto9.h
@@ -38,8 +38,9 @@
NOTIFSCOUNT = 40
};
-JSON *mastodonget(char *token, char *host, char *endpoint);
-char *tootauthor(char *token, char *host, char *id);
+/* display */
+void displaytoots(Toot toots[], char *server);
+void displaynotifications(Notification notifs[]);
/* http */
char *httpget(char *token, char *url);
--- a/mkfile
+++ b/mkfile
@@ -5,6 +5,7 @@
BIN=/$objtype/bin
OFILES=\
+ display.$O\
http.$O\
masto9.$O\
util.$O\