summaryrefslogtreecommitdiff
path: root/mastoapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'mastoapi.c')
-rw-r--r--mastoapi.c343
1 files changed, 177 insertions, 166 deletions
diff --git a/mastoapi.c b/mastoapi.c
index cd94528..791d3b8 100644
--- a/mastoapi.c
+++ b/mastoapi.c
@@ -403,7 +403,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path,
403xs_str *mastoapi_id(const xs_dict *msg) 403xs_str *mastoapi_id(const xs_dict *msg)
404/* returns a somewhat Mastodon-compatible status id */ 404/* returns a somewhat Mastodon-compatible status id */
405{ 405{
406 char tmp[256] = ""; 406 char tmp[15] = "";
407 int n = 0; 407 int n = 0;
408 const char *id = xs_dict_get(msg, "id"); 408 const char *id = xs_dict_get(msg, "id");
409 const char *published = xs_dict_get(msg, "published"); 409 const char *published = xs_dict_get(msg, "published");
@@ -424,6 +424,178 @@ xs_str *mastoapi_id(const xs_dict *msg)
424} 424}
425 425
426 426
427xs_dict *mastoapi_status(snac *snac, const xs_dict *msg)
428/* converts an ActivityPub note to a Mastodon status */
429{
430 xs *actor = NULL;
431 actor_get(snac, xs_dict_get(msg, "attributedTo"), &actor);
432
433 /* if the author is not here, discard */
434 if (actor == NULL)
435 return NULL;
436
437 /** shave the yak converting an ActivityPub Note to a Mastodon status **/
438
439 xs *acct = xs_dict_new();
440
441 const char *display_name = xs_dict_get(actor, "name");
442 if (xs_is_null(display_name) || *display_name == '\0')
443 display_name = xs_dict_get(actor, "preferredUsername");
444
445 const char *id = xs_dict_get(actor, "id");
446 const char *pub = xs_dict_get(actor, "published");
447 xs *acct_md5 = xs_md5_hex(id, strlen(id));
448 acct = xs_dict_append(acct, "id", acct_md5);
449 acct = xs_dict_append(acct, "username", xs_dict_get(actor, "preferredUsername"));
450 acct = xs_dict_append(acct, "acct", xs_dict_get(actor, "preferredUsername"));
451 acct = xs_dict_append(acct, "display_name", display_name);
452
453 if (pub)
454 acct = xs_dict_append(acct, "created_at", pub);
455
456 acct = xs_dict_append(acct, "note", xs_dict_get(actor, "summary"));
457 acct = xs_dict_append(acct, "url", id);
458
459 xs *avatar = NULL;
460 xs_dict *av = xs_dict_get(actor, "icon");
461
462 if (xs_type(av) == XSTYPE_DICT)
463 avatar = xs_dup(xs_dict_get(av, "url"));
464 else
465 avatar = xs_fmt("%s/susie.png", srv_baseurl);
466
467 acct = xs_dict_append(acct, "avatar", avatar);
468
469 xs *f = xs_val_new(XSTYPE_FALSE);
470 xs *t = xs_val_new(XSTYPE_TRUE);
471 xs *n = xs_val_new(XSTYPE_NULL);
472 xs *el = xs_list_new();
473 xs *idx = NULL;
474 xs *ixc = NULL;
475
476 char *tmp;
477 id = xs_dict_get(msg, "id");
478 xs *mid = mastoapi_id(msg);
479
480 xs_dict *st = xs_dict_new();
481
482 st = xs_dict_append(st, "id", mid);
483 st = xs_dict_append(st, "uri", id);
484 st = xs_dict_append(st, "url", id);
485 st = xs_dict_append(st, "created_at", xs_dict_get(msg, "published"));
486 st = xs_dict_append(st, "account", acct);
487 st = xs_dict_append(st, "content", xs_dict_get(msg, "content"));
488
489 st = xs_dict_append(st, "visibility",
490 is_msg_public(snac, msg) ? "public" : "private");
491
492 tmp = xs_dict_get(msg, "sensitive");
493 if (xs_is_null(tmp))
494 tmp = f;
495
496 st = xs_dict_append(st, "sensitive", tmp);
497
498 tmp = xs_dict_get(msg, "summary");
499 if (xs_is_null(tmp))
500 tmp = "";
501
502 st = xs_dict_append(st, "spoiler_text", tmp);
503
504 /* create the list of attachments */
505 xs *matt = xs_list_new();
506 xs_list *att = xs_dict_get(msg, "attachment");
507 xs_str *aobj;
508
509 while (xs_list_iter(&att, &aobj)) {
510 const char *mtype = xs_dict_get(aobj, "mediaType");
511
512 if (!xs_is_null(mtype) && xs_startswith(mtype, "image/")) {
513 xs *matteid = xs_fmt("%s_%d", id, xs_list_len(matt));
514 xs *matte = xs_dict_new();
515
516 matte = xs_dict_append(matte, "id", matteid);
517 matte = xs_dict_append(matte, "type", "image");
518 matte = xs_dict_append(matte, "url", xs_dict_get(aobj, "url"));
519 matte = xs_dict_append(matte, "preview_url", xs_dict_get(aobj, "url"));
520 matte = xs_dict_append(matte, "remote_url", xs_dict_get(aobj, "url"));
521 matte = xs_dict_append(matte, "description", xs_dict_get(aobj, "name"));
522
523 matt = xs_list_append(matt, matte);
524 }
525 }
526
527 st = xs_dict_append(st, "media_attachments", matt);
528
529 st = xs_dict_append(st, "mentions", el);
530 st = xs_dict_append(st, "tags", el);
531 st = xs_dict_append(st, "emojis", el);
532
533 xs_free(idx);
534 xs_free(ixc);
535 idx = object_likes(id);
536 ixc = xs_number_new(xs_list_len(idx));
537
538 st = xs_dict_append(st, "favourites_count", ixc);
539 st = xs_dict_append(st, "favourited",
540 xs_list_in(idx, snac->md5) != -1 ? t : f);
541
542 xs_free(idx);
543 xs_free(ixc);
544 idx = object_announces(id);
545 ixc = xs_number_new(xs_list_len(idx));
546
547 st = xs_dict_append(st, "reblogs_count", ixc);
548 st = xs_dict_append(st, "reblogged",
549 xs_list_in(idx, snac->md5) != -1 ? t : f);
550
551 xs_free(idx);
552 xs_free(ixc);
553 idx = object_children(id);
554 ixc = xs_number_new(xs_list_len(idx));
555
556 st = xs_dict_append(st, "replies_count", ixc);
557
558 /* default in_reply_to values */
559 st = xs_dict_append(st, "in_reply_to_id", n);
560 st = xs_dict_append(st, "in_reply_to_account_id", n);
561
562 tmp = xs_dict_get(msg, "inReplyTo");
563 if (!xs_is_null(tmp)) {
564 xs *irto = NULL;
565
566 if (valid_status(object_get(tmp, &irto))) {
567 xs *irt_mid = mastoapi_id(irto);
568 st = xs_dict_set(st, "in_reply_to_id", irt_mid);
569
570 char *at = NULL;
571 if (!xs_is_null(at = xs_dict_get(irto, "attributedTo"))) {
572 xs *at_md5 = xs_md5_hex(at, strlen(at));
573 st = xs_dict_set(st, "in_reply_to_account_id", at_md5);
574 }
575 }
576 }
577
578 st = xs_dict_append(st, "reblog", n);
579 st = xs_dict_append(st, "poll", n);
580 st = xs_dict_append(st, "card", n);
581 st = xs_dict_append(st, "language", n);
582
583 tmp = xs_dict_get(msg, "sourceContent");
584 if (xs_is_null(tmp))
585 tmp = "";
586
587 st = xs_dict_append(st, "text", tmp);
588
589 tmp = xs_dict_get(msg, "updated");
590 if (xs_is_null(tmp))
591 tmp = n;
592
593 st = xs_dict_append(st, "edited_at", tmp);
594
595 return st;
596}
597
598
427int mastoapi_get_handler(const xs_dict *req, const char *q_path, 599int mastoapi_get_handler(const xs_dict *req, const char *q_path,
428 char **body, int *b_size, char **ctype) 600 char **body, int *b_size, char **ctype)
429{ 601{
@@ -548,172 +720,11 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
548 if (strcmp(xs_dict_get(msg, "type"), "Note") != 0) 720 if (strcmp(xs_dict_get(msg, "type"), "Note") != 0)
549 continue; 721 continue;
550 722
551 xs *actor = NULL; 723 /* convert the Note into a Mastodon status */
552 actor_get(&snac, xs_dict_get(msg, "attributedTo"), &actor); 724 xs *st = mastoapi_status(&snac, msg);
553
554 /* if the author is not here, discard */
555 if (actor == NULL)
556 continue;
557
558 /** shave the yak converting an ActivityPub Note to a Mastodon status **/
559
560 xs *acct = xs_dict_new();
561
562 const char *display_name = xs_dict_get(actor, "name");
563 if (xs_is_null(display_name) || *display_name == '\0')
564 display_name = xs_dict_get(actor, "preferredUsername");
565
566 const char *id = xs_dict_get(actor, "id");
567 const char *pub = xs_dict_get(actor, "published");
568 xs *acct_md5 = xs_md5_hex(id, strlen(id));
569 acct = xs_dict_append(acct, "id", acct_md5);
570 acct = xs_dict_append(acct, "username", xs_dict_get(actor, "preferredUsername"));
571 acct = xs_dict_append(acct, "acct", xs_dict_get(actor, "preferredUsername"));
572 acct = xs_dict_append(acct, "display_name", display_name);
573
574 if (pub)
575 acct = xs_dict_append(acct, "created_at", pub);
576
577 acct = xs_dict_append(acct, "note", xs_dict_get(actor, "summary"));
578 acct = xs_dict_append(acct, "url", id);
579
580 xs *avatar = NULL;
581 xs_dict *av = xs_dict_get(actor, "icon");
582
583 if (xs_type(av) == XSTYPE_DICT)
584 avatar = xs_dup(xs_dict_get(av, "url"));
585 else
586 avatar = xs_fmt("%s/susie.png", srv_baseurl);
587
588 acct = xs_dict_append(acct, "avatar", avatar);
589
590 xs *f = xs_val_new(XSTYPE_FALSE);
591 xs *t = xs_val_new(XSTYPE_TRUE);
592 xs *n = xs_val_new(XSTYPE_NULL);
593 xs *el = xs_list_new();
594 xs *idx = NULL;
595 xs *ixc = NULL;
596
597 char *tmp;
598 id = xs_dict_get(msg, "id");
599 xs *mid = mastoapi_id(msg);
600
601 xs *st = xs_dict_new();
602
603 st = xs_dict_append(st, "id", mid);
604 st = xs_dict_append(st, "uri", id);
605 st = xs_dict_append(st, "url", id);
606 st = xs_dict_append(st, "created_at", xs_dict_get(msg, "published"));
607 st = xs_dict_append(st, "account", acct);
608 st = xs_dict_append(st, "content", xs_dict_get(msg, "content"));
609
610 st = xs_dict_append(st, "visibility",
611 is_msg_public(&snac, msg) ? "public" : "private");
612
613 tmp = xs_dict_get(msg, "sensitive");
614 if (xs_is_null(tmp))
615 tmp = f;
616
617 st = xs_dict_append(st, "sensitive", tmp);
618
619 tmp = xs_dict_get(msg, "summary");
620 if (xs_is_null(tmp))
621 tmp = "";
622
623 st = xs_dict_append(st, "spoiler_text", tmp);
624
625 /* create the list of attachments */
626 xs *matt = xs_list_new();
627 xs_list *att = xs_dict_get(msg, "attachment");
628 xs_str *aobj;
629
630 while (xs_list_iter(&att, &aobj)) {
631 const char *mtype = xs_dict_get(aobj, "mediaType");
632
633 if (!xs_is_null(mtype) && xs_startswith(mtype, "image/")) {
634 xs *matteid = xs_fmt("%s_%d", id, xs_list_len(matt));
635 xs *matte = xs_dict_new();
636
637 matte = xs_dict_append(matte, "id", matteid);
638 matte = xs_dict_append(matte, "type", "image");
639 matte = xs_dict_append(matte, "url", xs_dict_get(aobj, "url"));
640 matte = xs_dict_append(matte, "preview_url", xs_dict_get(aobj, "url"));
641 matte = xs_dict_append(matte, "remote_url", xs_dict_get(aobj, "url"));
642 matte = xs_dict_append(matte, "description", xs_dict_get(aobj, "name"));
643
644 matt = xs_list_append(matt, matte);
645 }
646 }
647
648 st = xs_dict_append(st, "media_attachments", matt);
649
650 st = xs_dict_append(st, "mentions", el);
651 st = xs_dict_append(st, "tags", el);
652 st = xs_dict_append(st, "emojis", el);
653
654 xs_free(idx);
655 xs_free(ixc);
656 idx = object_likes(id);
657 ixc = xs_number_new(xs_list_len(idx));
658
659 st = xs_dict_append(st, "favourites_count", ixc);
660 st = xs_dict_append(st, "favourited",
661 xs_list_in(idx, snac.md5) != -1 ? t : f);
662
663 xs_free(idx);
664 xs_free(ixc);
665 idx = object_announces(id);
666 ixc = xs_number_new(xs_list_len(idx));
667
668 st = xs_dict_append(st, "reblogs_count", ixc);
669 st = xs_dict_append(st, "reblogged",
670 xs_list_in(idx, snac.md5) != -1 ? t : f);
671
672 xs_free(idx);
673 xs_free(ixc);
674 idx = object_children(id);
675 ixc = xs_number_new(xs_list_len(idx));
676
677 st = xs_dict_append(st, "replies_count", ixc);
678
679 /* default in_reply_to values */
680 st = xs_dict_append(st, "in_reply_to_id", n);
681 st = xs_dict_append(st, "in_reply_to_account_id", n);
682
683 tmp = xs_dict_get(msg, "inReplyTo");
684 if (!xs_is_null(tmp)) {
685 xs *irto = NULL;
686
687 if (valid_status(object_get(tmp, &irto))) {
688 xs *irt_mid = mastoapi_id(irto);
689 st = xs_dict_set(st, "in_reply_to_id", irt_mid);
690
691 char *at = NULL;
692 if (!xs_is_null(at = xs_dict_get(irto, "attributedTo"))) {
693 xs *at_md5 = xs_md5_hex(at, strlen(at));
694 st = xs_dict_set(st, "in_reply_to_account_id", at_md5);
695 }
696 }
697 }
698
699 st = xs_dict_append(st, "reblog", n);
700 st = xs_dict_append(st, "poll", n);
701 st = xs_dict_append(st, "card", n);
702 st = xs_dict_append(st, "language", n);
703
704 tmp = xs_dict_get(msg, "sourceContent");
705 if (xs_is_null(tmp))
706 tmp = "";
707
708 st = xs_dict_append(st, "text", tmp);
709
710 tmp = xs_dict_get(msg, "updated");
711 if (xs_is_null(tmp))
712 tmp = n;
713
714 st = xs_dict_append(st, "edited_at", tmp);
715 725
716 out = xs_list_append(out, st); 726 if (st != NULL)
727 out = xs_list_append(out, st);
717 728
718 cnt++; 729 cnt++;
719 } 730 }