ref: 416e913d695eea696560b129c98cd3038efa103a
parent: 49ba85bf6b67c33707cd56111d9868e610c429ae
author: Julien Blanchard <[email protected]>
date: Sun Mar 26 11:51:23 EDT 2023
Split files, add boost and fav
--- /dev/null
+++ b/http.c
@@ -1,0 +1,108 @@
+#include <u.h>
+#include <libc.h>
+#include <stdio.h>
+
+#include "masto9.h"
+
+char *
+httpget(char *token, char *url)
+{
+ int ctlfd, bodyfd, conn, n;
+ char buf[1024];
+ char *body;
+ char *bearer_token;
+
+ ctlfd = open("/mnt/web/clone", ORDWR);
+ if (ctlfd < 0)
+ sysfatal("open: %r");
+ n = read(ctlfd, buf, sizeof(buf));
+ if (n < 0)
+ sysfatal("read: %r");
+ buf[n] = 0;
+ conn = atoi(buf);
+
+ /* the write(2) syscall (used by fprint) is considered
+ * failed if it returns -1 or N != Nwritten. to check for
+ * error here you'd have to snprint the url to a temporary
+ * buffer, get its length, then write it out and check the
+ * amount written against the length */
+ if (fprint(ctlfd, "url %s", url) <= 0)
+ sysfatal("write ctl failed 'url %s': %r", url);
+
+ bearer_token = concat("Authorization: Bearer ", token);
+
+ if (fprint(ctlfd, "headers %s", bearer_token) <= 0)
+ sysfatal("write ctl failed 'headers'");
+
+ snprint(buf, sizeof(buf), "/mnt/web/%d/body", conn);
+
+ bodyfd = open(buf, OREAD);
+ if (bodyfd < 0)
+ sysfatal("open %s: %r", buf);
+
+ body = emalloc(TLBUFSIZE * sizeof(char));
+ if (readn(bodyfd, body, TLBUFSIZE) <= 0)
+ sysfatal("readn: %r");
+
+ close(bodyfd);
+ close(ctlfd);
+ print("BODY %d", strlen(body));
+ return body;
+}
+
+char *
+httppost(char *token, char *url, char *text)
+{
+ int ctlfd, bodyfd, conn, n;
+ char *buf;
+ char *bearer_token;
+
+ buf = emalloc(TOOTBUFSIZE * sizeof(char));
+
+ ctlfd = open("/mnt/web/clone", ORDWR);
+ if (ctlfd < 0)
+ sysfatal("open ctlfd: %r");
+ /* n = write(ctlfd, Contenttype, sizeof(Contenttype)); */
+ /* if (n < 0) */
+ /* sysfatal("write: %r"); */
+ /* buf[n] = 0; */
+ conn = atoi(buf);
+
+ /* the write(2) syscall (used by fprint) is considered
+ * failed if it returns -1 or N != Nwritten. to check for
+ * error here you'd have to snprint the url to a temporary
+ * buffer, get its length, then write it out and check the
+ * amount written against the length */
+ if (fprint(ctlfd, "url %s", url) <= 0)
+ sysfatal("write ctl failed 'url %s': %r", url);
+
+ bearer_token = concat("Authorization: Bearer ", token);
+
+ if (fprint(ctlfd, "headers %s", bearer_token) <= 0)
+ sysfatal("write ctl failed 'headers'");
+
+ snprint(buf, TOOTBUFSIZE, "/mnt/web/%d/postbody", conn);
+ bodyfd = open(buf, OWRITE);
+ if (bodyfd < 0)
+ sysfatal("open bodyfd %s: %r", buf);
+
+ if (write(bodyfd, text, strlen(text)) < 0)
+ sysfatal("write: %r");
+
+ close(bodyfd);
+ snprint(buf, TOOTBUFSIZE, "/mnt/web/%d/body", conn);
+
+ bodyfd = open(buf, OREAD);
+ if (bodyfd < 0)
+ sysfatal("open %s: %r", buf);
+
+ if (readn(bodyfd, buf, TOOTBUFSIZE) <= 0)
+ sysfatal("readn: %r");
+
+ /* print("BUF %s", buf); */
+
+ close(bodyfd);
+ close(ctlfd);
+
+ return buf;
+}
--- a/masto9.c
+++ b/masto9.c
@@ -4,47 +4,12 @@
#include <json.h>
#include <auth.h>
-#define Contenttype "contenttype application/json"
+#include "masto9.h"
-typedef struct Attachment {
- char *type;
- char *url;
-} Attachment;
-
-typedef struct Notification {
- char *id;
- char *type;
- char *username;
- char *content;
-} Notification;
-
-typedef struct Toot {
- char *id;
- char *content;
- char *username;
- char *display_name;
- char *avatar_url;
- char *in_reply_to_account_id;
- int reblogged;
- char *reblogged_username;
- Attachment media_attachments[10];
- int attachments_count;
-} Toot;
-
-enum {
- BUFSIZE = 8182,
- MAX_URL = 1024,
- TOOTS_COUNT = 20,
- NOTIFS_COUNT = 15
-};
-
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";
-Toot toots[TOOTS_COUNT];
-Notification notifs[TOOTS_COUNT];
-
UserPasswd *
getcredentials(char *host)
{
@@ -58,115 +23,7 @@
return p;
}
-char *
-concat(char *s1, char *s2)
-{
- char *result;
- result = malloc(strlen(s1) + strlen(s2) + 1); // +1 for the null-terminator
- if (result == nil)
- sysfatal("malloc: %r");
- strcpy(result, s1);
- strcat(result, s2);
- return result;
-}
-
-static void
-httpget(char *token, char *url, char *body, int bufsize)
-{
- int ctlfd, bodyfd, conn, n;
- char buf[1024];
- char *bearer_token;
-
- ctlfd = open("/mnt/web/clone", ORDWR);
- if (ctlfd < 0)
- sysfatal("open: %r");
- n = read(ctlfd, buf, sizeof(buf));
- if (n < 0)
- sysfatal("read: %r");
- buf[n] = 0;
- conn = atoi(buf);
-
- /* the write(2) syscall (used by fprint) is considered
- * failed if it returns -1 or N != Nwritten. to check for
- * error here you'd have to snprint the url to a temporary
- * buffer, get its length, then write it out and check the
- * amount written against the length */
- if (fprint(ctlfd, "url %s", url) <= 0)
- sysfatal("write ctl failed 'url %s': %r", url);
-
- bearer_token = concat("Authorization: Bearer ", token);
-
- if (fprint(ctlfd, "headers %s", bearer_token) <= 0)
- sysfatal("write ctl failed 'headers'");
-
- snprint(buf, sizeof(buf), "/mnt/web/%d/body", conn);
-
- bodyfd = open(buf, OREAD);
- if (bodyfd < 0)
- sysfatal("open %s: %r", buf);
-
- if (readn(bodyfd, body, bufsize) <= 0)
- sysfatal("readn: %r");
-
- close(bodyfd);
- close(ctlfd);
-}
-
-static void
-httppost(char *token, char *url, char *response, int bufsize, char *text)
-{
- int ctlfd, bodyfd, conn, n;
- char buf[1024];
- char *bearer_token;
-
- ctlfd = open("/mnt/web/clone", ORDWR);
- if (ctlfd < 0)
- sysfatal("open: %r");
- /* n = write(ctlfd, Contenttype, sizeof(Contenttype)); */
- /* if (n < 0) */
- /* sysfatal("write: %r"); */
- buf[n] = 0;
- conn = atoi(buf);
-
-
- /* the write(2) syscall (used by fprint) is considered
- * failed if it returns -1 or N != Nwritten. to check for
- * error here you'd have to snprint the url to a temporary
- * buffer, get its length, then write it out and check the
- * amount written against the length */
- if (fprint(ctlfd, "url %s", url) <= 0)
- sysfatal("write ctl failed 'url %s': %r", url);
-
- bearer_token = concat("Authorization: Bearer ", token);
-
- if (fprint(ctlfd, "headers %s", bearer_token) <= 0)
- sysfatal("write ctl failed 'headers'");
-
- snprint(buf, sizeof(buf), "/mnt/web/%d/postbody", conn);
- bodyfd = open(buf, OWRITE);
- if (bodyfd < 0)
- sysfatal("open %s: %r", buf);
-
- if (write(bodyfd, text, strlen(text)) < 0)
- sysfatal("write: %r");
-
- close(bodyfd);
- snprint(buf, sizeof(buf), "/mnt/web/%d/body", conn);
-
- bodyfd = open(buf, OREAD);
- if (bodyfd < 0)
- sysfatal("open %s: %r", buf);
-
- if (readn(bodyfd, buf, sizeof(buf)) <= 0)
- sysfatal("readn: %r");
-
- /* print("BUF %s", buf); */
-
- close(bodyfd);
- close(ctlfd);
-}
-
static JSON *
get_json_key(JSON *obj, char *key)
{
@@ -180,14 +37,12 @@
get_timeline(char *token, Toot toots[])
{
JSON *obj, *id, *content, *reblog_content, *account, *reblog_account, *username, *reblog_username, *display_name, *avatar, *reblog, *media_attachments, *type, *url;
- char buf[BUFSIZE * 32];
+ char *response;
int i = 0;
- httpget(token, URL, buf, sizeof(buf));
+ response = httpget(token, URL);
- obj = jsonparse(buf);
- //print("%J", obj);
-
+ obj = jsonparse(response);
if (obj == nil)
sysfatal("jsonparse: not json");
if (obj->t != JSONArray)
@@ -205,7 +60,7 @@
reblog = get_json_key(toot_json, "reblog");
media_attachments = get_json_key(toot_json, "media_attachments");
- Toot toot = malloc(sizeof(Toot));
+ Toot toot = emalloc(sizeof(Toot));
toot.id = strdup((char *)id->s);
if(reblog->s == nil) {
@@ -233,7 +88,7 @@
for(JSONEl *at = media_attachments->first; at != nil; at = at->next) {
JSON *attachment_json = at->val;
//print("att: %J", attachment_json);
- Attachment attachment = malloc(sizeof(Attachment));
+ Attachment attachment = emalloc(sizeof(Attachment));
type = get_json_key(attachment_json, "type");
url = get_json_key(attachment_json, "preview_url");
attachment.type = strdup((char *)type->s);
@@ -254,14 +109,12 @@
get_notifications(char *token, Notification toots[])
{
JSON *obj, *id, *content, *username, *type, *account, *status;
- char buf[BUFSIZE * 32];
+ char *response;
int i = 0;
- httpget(token, NOTIFICATIONSURL, buf, sizeof(buf));
+ response = httpget(token, NOTIFICATIONSURL);
- obj = jsonparse(buf);
- //print("%J", obj);
-
+ obj = jsonparse(response);
if (obj == nil)
sysfatal("jsonparse: not json");
if (obj->t != JSONArray)
@@ -269,6 +122,7 @@
for(JSONEl *p = obj->first; p != nil; p = p->next) {
JSON *toot_json = p->val;
+ content = emalloc(JSONNull);
id = get_json_key(toot_json, "id");
type = get_json_key(toot_json, "type");
@@ -279,7 +133,7 @@
account = get_json_key(toot_json, "account");
username = get_json_key(account, "username");
- Notification toot = malloc(sizeof(Notification));
+ Notification toot = emalloc(sizeof(Notification));
toot.id = strdup((char *)id->s);
toot.type = strdup((char *)type->s);
@@ -295,29 +149,59 @@
void
post_toot(char *token, char *text)
{
- char buf[BUFSIZE * 32];
- httppost(token, POSTURL, buf, sizeof(buf), text);
+ char buf[TOOTBUFSIZE];
+ httppost(token, POSTURL, text);
print("RESPONSE %s", buf);
}
void
+action_toot(char *token, 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);
+}
+
+void
+boost_toot(char *token, char *id)
+{
+ action_toot(token, id, "reblog");
+}
+
+void
+unboost_toot(char *token, char *id)
+{
+ action_toot(token, id, "unreblog");
+}
+
+void
fav_toot(char *token, char *id)
{
- char buf[BUFSIZE * 32];
- char * url = concat(POSTURL, "/");
- url = concat(url, id);
- url = concat(url, "/favourite");
+ action_toot(token, id, "favourite");
+}
- print("URL %s", url);
- httppost(token, url, buf, sizeof(buf), "");
- print("RESPONSE %s", buf);
+void
+unfav_toot(char *token, char *id)
+{
+ action_toot(token, id, "unfavourite");
}
+void
+reply_toot(char *token, char *id, char *text)
+{
+ char content[TOOTBUFSIZE];
+ snprintf(content, TOOTBUFSIZE, "in_reply_to_id=%s&status=%s", id, text);
+ httppost(token, POSTURL, content);
+}
+
char *
fmthtml(char *msg)
{
int wr[2], rd[2], n;
- char buf[BUFSIZE];
+ char buf[TOOTBUFSIZE];
if(pipe(wr) == -1 || pipe(rd) == -1)
sysfatal("pipe: %r");
@@ -506,14 +390,12 @@
mastodonget(char *token, char *host, char *endpoint)
{
JSON *obj;
- char buf[BUFSIZE], url[MAX_URL];
+ char *response, url[MAX_URL];
snprintf(url, MAX_URL, "https://%s/api/v1/%s", host, endpoint);
- httpget(token, url, buf, sizeof(buf));
+ response = httpget(token, url);
- obj = jsonparse(buf);
- //print("%J", obj);
-
+ obj = jsonparse(response);
if (obj == nil)
sysfatal("jsonparse: not json");
if (obj->t != JSONArray)
@@ -571,9 +453,21 @@
} else if(strcmp(command, "toot") == 0) {
text = argv[3];
post_toot(token, text);
- } else if(strcmp(command, "favorite") == 0) {
+ } else if(strcmp(command, "fav") == 0) {
id = argv[3];
fav_toot(token, id);
+ } else if(strcmp(command, "unfav") == 0) {
+ id = argv[3];
+ unfav_toot(token, id);
+ } else if(strcmp(command, "boost") == 0) {
+ id = argv[3];
+ boost_toot(token, id);
+ } else if(strcmp(command, "unboost") == 0) {
+ id = argv[3];
+ unboost_toot(token, id);
+ } else if(strcmp(command, "reply") == 0) {
+ id = argv[3];
+ reply_toot(token, id, "@[email protected] now this should be a proper reply");
} else if(strcmp(command, "notifications") == 0) {
get_notifications(token, notifs);
@@ -584,6 +478,8 @@
print("⊙ %s retooted\n %s\n", notif.username, fmthtml(cleanup(notif.content)));
} else if (strcmp(notif.type, "favourite") == 0) {
print("⊙ %s favorited\n %s\n", notif.username, fmthtml(cleanup(notif.content)));
+ } else if (strcmp(notif.type, "mention") == 0) {
+ print("⊙ %s mentioned you\n %s\n", notif.username, fmthtml(cleanup(notif.content)));
} else if (strcmp(notif.type, "follow") == 0) {
print("⊙ %s followed you\n", notif.username);
} else if (strcmp(notif.type, "poll") == 0) {
--- /dev/null
+++ b/masto9.h
@@ -1,0 +1,51 @@
+#define Contenttype "contenttype application/json"
+
+typedef struct Attachment {
+ char *type;
+ char *url;
+} Attachment;
+
+typedef struct Notification {
+ char *id;
+ char *type;
+ char *username;
+ char *content;
+} Notification;
+
+typedef struct Toot {
+ char *id;
+ char *content;
+ char *username;
+ char *display_name;
+ char *avatar_url;
+ char *in_reply_to_account_id;
+ int reblogged;
+ char *reblogged_username;
+ Attachment media_attachments[10];
+ int attachments_count;
+} Toot;
+
+enum {
+ TOOTBUFSIZE = 8192,
+ TLBUFSIZE = 512000,
+ MAX_URL = 1024,
+ TOOTS_COUNT = 20,
+ NOTIFS_COUNT = 15
+};
+
+Toot toots[TOOTS_COUNT];
+Notification notifs[TOOTS_COUNT];
+
+/* http */
+char *httpget(char *token, char *url);
+char *httppost(char *token, char *url, char *text);
+
+/* utils */
+char *concat(char *s1, char *s2);
+void *emalloc(ulong);
+void *erealloc(void*, ulong);
+char *estrdup(char*);
+char *estrjoin(char **strings, char *sep);
+char *esmprint(char*, ...);
+char *fslurp(int, int*);
+u32int strhash(char*);
--- a/mkfile
+++ b/mkfile
@@ -5,7 +5,12 @@
BIN=/$objtype/bin
OFILES=\
+ http.$O\
masto9.$O\
+ util.$O\
+
+HFILES=masto9.h
+MAN=/sys/man/1/
UPDATE=\
$HFILES\
--- /dev/null
+++ b/util.c
@@ -1,0 +1,131 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <thread.h>
+#include <regexp.h>
+
+#include "masto9.h"
+
+void *
+emalloc(ulong n)
+{
+ void *v;
+
+ v = mallocz(n, 1);
+ if(v == nil)
+ sysfatal("malloc: %r");
+ setmalloctag(v, getcallerpc(&n));
+ return v;
+}
+
+void *
+erealloc(void *p, ulong n)
+{
+ void *v;
+
+ v = realloc(p, n);
+ if(v == nil)
+ sysfatal("realloc: %r");
+ setmalloctag(v, getcallerpc(&p));
+ return v;
+}
+
+char*
+estrdup(char *s)
+{
+ s = strdup(s);
+ if(s == nil)
+ sysfatal("strdup: %r");
+ setmalloctag(s, getcallerpc(&s));
+ return s;
+}
+
+/* char* */
+/* estrjoin(char *s, ...) */
+/* { */
+/* va_list ap; */
+/* char *r, *t, *p, *e; */
+/* int n; */
+
+/* va_start(ap, s); */
+/* n = strlen(s) + 1; */
+/* while((p = va_arg(ap, char*)) != nil) */
+/* n += strlen(p); */
+/* va_end(ap); */
+
+/* r = emalloc(n); */
+/* e = r + n; */
+/* va_start(ap, s); */
+/* t = strecpy(r, e, s); */
+/* while((p = va_arg(ap, char*)) != nil) */
+/* t = strecpy(t, e, p); */
+/* va_end(ap); */
+/* return r; */
+/* } */
+
+char *
+concat(char *s1, char *s2)
+{
+ char *result;
+ result = emalloc(strlen(s1) + strlen(s2) + 1); // +1 for the null-terminator
+
+ strcpy(result, s1);
+ strcat(result, s2);
+ return result;
+}
+
+char*
+esmprint(char *fmt, ...)
+{
+ char *s;
+ va_list ap;
+
+ va_start(ap, fmt);
+ s = vsmprint(fmt, ap);
+ va_end(ap);
+ if(s == nil)
+ sysfatal("smprint: %r");
+ setmalloctag(s, getcallerpc(&fmt));
+ return s;
+}
+
+char*
+fslurp(int fd, int *nbuf)
+{
+ int n, sz, r;
+ char *buf;
+
+ n = 0;
+ sz = 128;
+ buf = emalloc(sz);
+ while(1){
+ r = read(fd, buf + n, sz - n);
+ if(r == 0)
+ break;
+ if(r == -1)
+ goto error;
+ n += r;
+ if(n == sz){
+ sz += sz/2;
+ buf = erealloc(buf, sz);
+ }
+ }
+ buf[n] = 0;
+ if(nbuf)
+ *nbuf = n;
+ return buf;
+error:
+ free(buf);
+ return nil;
+}
+
+u32int
+strhash(char *s)
+{
+ u32int h, c;
+
+ h = 5381;
+ while(c = *s++ & 0xff)
+ h = ((h << 5) + h) + c;
+ return h;
+}