-- Leo's gemini proxy
-- Connecting to git.thebackupbox.net:1965...
-- Connected
-- Sending request
-- Meta line: 20 text/gemini
repo: actpub action: commit revision: path_from: revision_from: 530ca5a061b6219605380fee4abcf6c8675cb357: path_to: revision_to:
commit 530ca5a061b6219605380fee4abcf6c8675cb357 Author: epoch <epoch@thebackupbox.net> Date: Sat Feb 18 03:59:21 2023 +0000 changed a lot of things. mostly changed "object" to "actor" in all places. diff --git a/README b/README new file mode 100644 index 0000000000000000000000000000000000000000..6930f5791f143d8a069576d57734931061b7cd30 --- /dev/null +++ b/README @@ -0,0 +1 @@ +https://www.w3.org/TR/activitypub/ diff --git a/ap-activity2html b/ap-activity2html
--- a/ap-activity2html +++ b/ap-activity2html @@ -13,56 +13,54 @@ if [ "$type" = "Undo" ];then fi if [ "$(jq -r '.to | type' < "${activity_file}" )" = "array" ];then - if jq -r '.to[]' < "${activity_file}" | grep -vF 'https://www.w3.org/ns/activitystreams#Public' >/dev/null 2>&1;then - printf 'non-public post not shown. %s<br/>' "${activity_file}" - exit 0 - else + #if jq -r '.to[]' < "${activity_file}" | grep -vF 'https://www.w3.org/ns/activitystreams#Public' >/dev/null 2>&1;then + # printf 'non-public post not shown. %s<br/>' "${activity_file}" + # exit 0 + #else printf 'public post: <a href="%s">%s</a><br/>' "${activity_file}" "${activity_file}" - fi + #fi else printf "no to: found, guess public. *shrugs*\n" fi printf '<div class="actdiv">\n' -printf "Id: %s<br/>\n" "$(jq -r '.id' 2>/dev/null < "${activity_file}" | html_entities_encode)" +id="$(jq -r '.id' 2>/dev/null < "${activity_file}")" +printf "Id: <a href="%s">%s</a><br/>\n" "$(html_entities_encode <<< "$id")" "$(html_entities_encode <<< "$id")" actor="$(jq -r '.actor' 2>/dev/null < "${activity_file}" | html_entities_encode)" -acct="$(ap-object2acct "${actor}" 2>/dev/null | uricut -p 2>/dev/null)" +acct="$(ap-actor2acct "${actor}" 2>/dev/null | uricut -p 2>/dev/null)" printf 'Actor: <a href="%s">%s</a><br/>\n' "${actor}" "${actor}" printf 'Acct: <a href="acct:%s">%s</a><br/>\n' "${acct}" "${acct}" -icon="$(ap-getobject "${acct}" 2>/dev/null | jq -r .icon.url | html_entities_encode)" +icon="$(ap-getactor "${acct}" 2>/dev/null | jq -r .icon.url | html_entities_encode)" printf 'Icon: <img src="%s" width="128" height="128">' "${icon}" printf 'Type: %s<br/>\n' "$(html_entities_encode <<< "$type")" objType="$(jq -r '.object | type' < "${activity_file}")" +printf "Created: %s<br/>\n" "$(jq -r '.signature.created' 2>/dev/null < "${activity_file}" | html_entities_encode)" printf "ObjType: %s<br/>" "${objType}" -if [ "$objType" = "string" ];then - object="$(jq -r '.object' < "${activity_file}")" - printf "Object: <a href="%s">%s</a><br/>" "${object}" "${object}" -else - inReplyTo="$(jq -r '.object.inReplyTo//""' 2>/dev/null < "${activity_file}" | html_entities_encode)" - if [ "$inReplyTo" ];then - printf "inReplyTo: <a href="%s">%s</a><br/>\n" "${inReplyTo}" "${inReplyTo}" - fi - #printf "Content: %s<br/>\n" "$(jq -r '.object.content' 2>/dev/null < "${activity_file}" | html_entities_encode)" - printf "Content: %s<br/>\n" "$(jq -r '.object.content' 2>/dev/null < "${activity_file}")" - printf "Created: %s<br/>\n" "$(jq -r '.signature.created' 2>/dev/null < "${activity_file}" | html_entities_encode)" - if [ "$(jq -r '.object.attachement | type' < "${activity_file}")" == "array" ];then - jq -r '.object.attachment | .[] | .mediaType,.url' 2>/dev/null < "${activity_file}" | paste - - | html_entities_encode | while read type url;do - case "$type" in - image/*) - printf 'attachment: <img src="%s" /><br/>' "$url" - ;; - video/*) - printf 'attachment: <video loop autoplay><source src="%s" type="%s"></video><br/>' "$url" "$type" - ;; - *) - printf '<a href="%s">attachment</a><br/>' "$url" - ;; - esac - done - fi -fi + +case "$objType" in +string) + uri="$(jq -r '.object' < "${activity_file}")" + printf 'Object: <a href="%s">%s</a><br/>' "${uri}" "${uri}" + cache_file="$(ap-cacheobject "${uri}")" + printf 'Cache_File: %s\n' "${cache_file}" + ap-object2html "${cache_file}" 2>&1 + ;; +object) + uri="$(jq -r ".object.id" < "${activity_file}")" + cache_file=~/.cache/ap/object/"$(sha256sum <<< "$uri" | cut '-d ' -f1)" + jq -r .object < "${activity_file}" > "${cache_file}" + printf "Cache_File: %s\n" "${cache_file}" + ap-object2html "${cache_file}" 2>&1 + ;; +*) + printf "not sure how to handle this object." + printf "Object: " + jq -r '.object' < "${activity_file}" + ;; +esac + printf '</div>' diff --git a/ap-actor.cgi b/ap-actor.cgi new file mode 100755 index 0000000000000000000000000000000000000000..bf5a7c9b5cdd8283cfa2ca70f7461bc4cdf9eaf8 --- /dev/null +++ b/ap-actor.cgi @@ -0,0 +1,144 @@ +#!/usr/bin/env bash + +### we're going to use $USER for all this shit. +### and $SERVER_NAME + +### I dunno. I need to grab these values from somewhere. + +# HTTP_ACCEPT: application/activity+json, application/ld+json + +### TODO: make use of If-Modified-Since header. your/my fmrl code has useful examples. + printf "Status: 200 OK\r\n" + printf "Date: %s\r\n" "$(rfc7231date)" + printf "Content-Security-Policy: \r\n" + printf "Cache-Control: max-age=180\r\n" + printf "Server: epochttpd\r\n" + printf "Content-Type: application/activity+json; charset=utf-8\r\n\r\n" + #printf "Content-Type: application/ld+json\r\n\r\n" + PUBLIC_KEY="$(cat public.pem | jq --slurp -R)" +cat <<EOF +{ + "@context": [ + "https://www.w3.org/ns/activitystreams", + "https://w3id.org/security/v1" +EOF +### all of this stuff seems optional based on pleoroma response +cat <<EOF >/dev/null #long comment. lol + { + "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", + "toot": "http://joinmastodon.org/ns#", + "featured": { + "@id": "toot:featured", + "@type": "@id" + }, + "featuredTags": { + "@id": "toot:featuredTags", + "@type": "@id" + }, + "alsoKnownAs": { + "@id": "as:alsoKnownAs", + "@type": "@id" + }, + "movedTo": { + "@id": "as:movedTo", + "@type": "@id" + }, + "schema": "http://schema.org#", + "PropertyValue": "schema:PropertyValue", + "value": "schema:value", + "discoverable": "toot:discoverable", + "Device": "toot:Device", + "Ed25519Signature": "toot:Ed25519Signature", + "Ed25519Key": "toot:Ed25519Key", + "Curve25519Key": "toot:Curve25519Key", + "EncryptedMessage": "toot:EncryptedMessage", + "publicKeyBase64": "toot:publicKeyBase64", + "deviceId": "toot:deviceId", + "claim": { + "@type": "@id", + "@id": "toot:claim" + }, + "fingerprintKey": { + "@type": "@id", + "@id": "toot:fingerprintKey" + }, + "identityKey": { + "@type": "@id", + "@id": "toot:identityKey" + }, + "devices": { + "@type": "@id", + "@id": "toot:devices" + }, + "messageFranking": "toot:messageFranking", + "messageType": "toot:messageType", + "cipherText": "toot:cipherText", + "suspended": "toot:suspended", + "focalPoint": { + "@container": "@list", + "@id": "toot:focalPoint" + } + } +EOF +cat <<EOF + ], + + "id": "https://${SERVER_NAME}/~${USER}/", + "type": "Person", + "following": "https://${SERVER_NAME}/~${USER}/following/", + "followers": "https://${SERVER_NAME}/~${USER}/followers/", + "inbox": "https://${SERVER_NAME}/~${USER}/inbox/", + "outbox": "https://${SERVER_NAME}/~${USER}/outbox/", + "featured": "", + "featuredTags": "", + "name": "${USER}", + "preferredUsername": "${USER}", + "summary": "<p>hacks</p>", + "url": "https://${SERVER_NAME}/~${USER}/", + "manuallyApprovesFollowers": false, + "discoverable": true, + "published": "1970-01-01T03:13:37Z", + "devices": "https://${SERVER_NAME}/~${USER}/collections/devices/", + "publicKey": { + "id": "https://${SERVER_NAME}/~${USER}/#main-key", + "owner": "https://${SERVER_NAME}/~${USER}/", +EOF +printf ' "publicKeyPem": %s' "$PUBLIC_KEY" +cat <<EOF + }, + "tag": [], + "attachment": [ + { + "type": "PropertyValue", + "name": "h-card", + "value": "<a href=\"https://${SERVER_NAME}/~${USER}/\">https://${SERVER_NAME}/~${USER}/</a>" + }, + { + "type": "PropertyValue", + "name": "hobbies", + "value": "void staring" + } + ], + "endpoints": { + "sharedInbox": "https://${SERVER_NAME}/inbox/" + }, +EOF +### blocks go here for icon (pfp/avatar) and image (banner, whatever) +cat << EOF + "image": { + "type": "Image", + "mediaType": "image/jpeg", + "url": "https://${SERVER_NAME}/~${USER}/image.jpg" + }, +EOF +cat <<EOF + "icon": { + "type": "Image", + "mediaType": "image/png", + "url": "https://${SERVER_NAME}/~${USER}/icon.png" + } +EOF +# "url": "https://${SERVER_NAME}/cgi-bin/xface.cgi?IlrD8fxN=HlbdLwwiJkkn=qs4%3EtlW=8)AJX~vDBf8=,%7B4m5iD0Rt@uJMy%25c%5C%5Ez%3E0%25.N\$,QXXY)A@GPVl%3CtFo3A%605XDxcUh%7BtZj=]%3Co[%5EGH-Thr%7Cl+F)x~j%25Gb4U!XyXX;?a(hC6@yPNl5V%7B7[\$~P=M" +cat <<EOF +} +EOF diff --git a/ap-object2acct b/ap-actor2acct similarity index 81% rename from ap-object2acct rename to ap-actor2acct
--- a/ap-object2acct +++ b/ap-actor2acct @@ -1,7 +1,7 @@ #!/usr/bin/env bash if [ ! "$1" ];then - printf "arg1 needs to be the object URI of someone (aka actor uri)\n" >&2 + printf "usage: <actor URL>\n" >&2 exit 1 fi diff --git a/ap-cacheobject b/ap-cacheobject new file mode 100755 index 0000000000000000000000000000000000000000..0722c28c34c0daeb8de4d2da61e8cf762593d037 --- /dev/null +++ b/ap-cacheobject @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +if [ ! "$1" ];then + printf 'Usage: ap-cacheobject <uri>\n' >&2 + exit 1 +fi + +uri="$1" + +cache_file=~/.cache/ap/object/"$(sha256sum <<< "$uri" | cut '-d ' -f1)" + +if [ ! -s "$cache_file" ];then + curl -so "${cache_file}" -H "Accept: application/activity+json, application/ld+json" -g "$uri" +fi + +printf "%s\n" "${cache_file}" diff --git a/ap-getactor b/ap-getactor new file mode 100755 index 0000000000000000000000000000000000000000..a5db0d7129610687f383894890574f8da09b82e2 --- /dev/null +++ b/ap-getactor @@ -0,0 +1,26 @@ +#!/bin/bash +no_cache=0 +if [ "$1" == "--no-cache" ];then + no_cache=1 + shift +fi +user="$(printf "%s\n" "$1" | sed 's/^@//' | cut -d@ -f1)" +domain="$(printf "%s\n" "$1" | sed 's/^@//' | cut -d@ -f2)" +target="${user}@${domain}" +mkdir -p ~/.cache/ap/actor +cache_file=~/.cache/ap/actor/${target} +if [ ! -s ${cache_file} -o "${no_cache}" = 1 ];then + printf "downloading actor file for %s@%s\n" "${user}" "${domain}" >&2 + find ~/.cache/ap/actor -mtime 30 -rm # clear cache after 30 minutes. + ### I want to get the Cache-Control: max-age=180, derp header, + ### then get the max-age's value, + ### then set the mtime of the file that far into the future. + ### so I can find -mtime 0 . -rm on all of the object files. anything in the past gets deleted. + curl -s -o "${cache_file}" -H "Accept: application/activity+json, application/ld+json" -g "$(ap-getactoruri "$target")" + #id="$(date +%s)" + #touch -mt "/tmp/${id}" + #mv "/tmp/${id}" "${cache_file}" +else + printf "using cached actor file for %s@%s\n" "${user}" "${domain}" >&2 +fi +cat "${cache_file}" diff --git a/ap-getobjecturi b/ap-getactoruri similarity index 100% rename from ap-getobjecturi rename to ap-getactoruri diff --git a/ap-getattachmentlist b/ap-getattachmentlist
--- a/ap-getattachmentlist +++ b/ap-getattachmentlist @@ -1,5 +1,5 @@ #!/bin/sh -ap-getobject "$1" \ +ap-getactor "$1" \ | jq -r '.attachment[] | .name,.value' \ | sed 's/<\([^>]*\)>//g' \ | html_entities_decode \ diff --git a/ap-geticon b/ap-geticon
--- a/ap-geticon +++ b/ap-geticon @@ -1,5 +1,5 @@ #!/bin/sh -ap-getobject "$1" \ +ap-getactor "$1" \ | jq -r .icon.url \ | tr '\n' '\0' \ | xargs -0 curl -g \ diff --git a/ap-getimage b/ap-getimage
--- a/ap-getimage +++ b/ap-getimage @@ -1,5 +1,5 @@ #!/bin/sh -ap-getobject "$1" \ +ap-getactor "$1" \ | jq -r .image.url \ | xargs curl -g \ | img2sixel -w 100% - diff --git a/ap-getobject b/ap-getobject deleted file mode 100755 index 5022566ac0e42d59e24ac1f2737ba166999e33d2..0000000000000000000000000000000000000000 --- a/ap-getobject +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -no_cache=0 -if [ "$1" == "--no-cache" ];then - no_cache=1 - shift -fi -user="$(printf "%s\n" "$1" | sed 's/^@//' | cut -d@ -f1)" -domain="$(printf "%s\n" "$1" | sed 's/^@//' | cut -d@ -f2)" -target="${user}@${domain}" -mkdir -p ~/.cache/ap/object -cache_file=~/.cache/ap/object/${target} -if [ ! -s ${cache_file} -o "${no_cache}" = 1 ];then - printf "downloading object file for %s@%s\n" "${user}" "${domain}" >&2 - curl -s -o "${cache_file}" -H "Accept: application/activity+json, application/ld+json" -g "$(ap-getobjecturi "$target")" -else - printf "using cached object file for %s@%s\n" "${user}" "${domain}" >&2 -fi -cat "${cache_file}" diff --git a/ap-inbox.cgi b/ap-inbox.cgi
--- a/ap-inbox.cgi +++ b/ap-inbox.cgi @@ -1,6 +1,6 @@ #!/usr/bin/env bash -logger "ap-inbox at ${SCRIPT_NAME} requested! HTTP_ACCEPT: ${HTTP_ACCEPT}" +#logger "ap-inbox at ${SCRIPT_NAME} requested! HTTP_ACCEPT: ${HTTP_ACCEPT}" #if grep -E '' <<< "${HTTP_ACCEPT}";then @@ -17,42 +17,62 @@ if [ "$PATH_INFO" = "" ];then if [ "$REQUEST_METHOD" = "GET" ];then first="$(ls | sort -rn | grep '^[0-9]' | head -n1)" at="$(query_param "at")" + before="$(query_param "before" | tr -cd '0-9')" + reload="$(query_param "reload" | tr -cd '0-9')" + perpage="$(query_param "perpage" | tr -cd '0-9')" + if [ "${before}" ];then + printf 'Content-Type: text/html\r\n\r\n' + if [ "$reload" ];then + printf '<div hx-get="?before=%s&reload=%s" hx-trigger="every %ss" hx-swap="outerHTML">' "${first}" "${reload}" "${reload}" + printf 'last check %s<br/>' "$(date)" + printf 'next check in %s seconds<br/>' "${reload}" + fi + printf '<a href="?before=%s">click here for only the newer posts than currently displayed.</a><br/>' "${first}" + newer_posts="$(ls | sort -rn | grep '^[0-9]' | grep -B 1000 -F "${before}" | tac | tail -n+2 | tac)" + printf 'newer posts than %s: %s' "${before}" "$newer_posts" + printf '</div>' + ls | sort -rn | grep '^[0-9]' | grep -B 1000 -F "${before}" | tac | tail -n+2 | tac | while read next_file;do + ap-activity2html "${next_file}" + done + exit 0 + fi if [ "${at}" ] ;then + per_page=8 + total="$(ls | sort -rn | grep -c '^[0-9]')" + at="$(query_param at | tr -cd '0-9')" + if [ ! "$at" ];then + at="$(ls | sort -rn | head -n1)" + else + if [ ! -e "$at" ];then + printf "Status: 404 Not Found\r\n" + printf "Content-Type: text/plain\r\n\r\n" + printf "the note you are looking for can not be found." + fi + fi + next_at="$(ls | grep '^[0-9]' | sort -rn | grep -A "${per_page}" -F "${at}" | tail -n+$[${per_page}+1])" -per_page=8 -total="$(ls | sort -rn | grep -c '^[0-9]')" -at="$(query_param at | tr -cd '0-9')" -if [ ! "$at" ];then - at="$(ls | sort -rn | head -n1)" -else - if [ ! -e "$at" ];then - printf "Status: 404 Not Found\r\n" - printf "Content-Type: text/plain\r\n\r\n" - printf "the note you are looking for can not be found." - fi -fi -next_at="$(ls | grep '^[0-9]' | sort -rn | grep -A "${per_page}" -F "${at}" | tail -n+$[${per_page}+1])" - -printf "Content-Type: text/html\r\n\r\n" - -ls | grep '^[0-9]' | sort -rn | grep -A "$[${per_page}-1]" -F "${at}" | while read next_file;do - if [ "$next_file" ];then - ap-activity2html "$next_file" - else - printf "<div>not really infinite. you got to the end.</div>" - fi -done + printf "Content-Type: text/html\r\n\r\n" -if [ "${next_at}" ];then - printf '<div hx-get="?at=%s" hx-trigger="revealed" hx-swap="replace">loading loading loading... keep them notes a loading... RAW HIDE!</div>\n' "${next_at}" -else - printf "this is the end. total of %s things\n" "$total" -fi -exit 0 + ls | grep '^[0-9]' | sort -rn | grep -A "$[${per_page}-1]" -F "${at}" | while read next_file;do + if [ "$next_file" ];then + ap-activity2html "$next_file" + else + printf "<div>not really infinite. you got to the end.</div>" + fi + done + if [ "${next_at}" ];then + printf '<div hx-get="?at=%s" hx-trigger="revealed" hx-swap="replace">' "${next_at}" + printf 'loading loading loading... keep them notes a loading... RAW HIDE!' + printf '<a href="?at=%s">no javascript? load the next %s posts</a>' "${next_at}" "${per_page}" + printf '</div>\n' + else + printf "this is the end. total of %s things\n" "$total" + fi + exit 0 fi printf "Content-Type: text/html\r\n\r\n" cat <<EOF -<html> +<html id="top"> <head> <title>htmx fediverse inbox infinite scroll</title> <script src="/htmx.org.1.7.0.js"></script> @@ -63,11 +83,43 @@ cat <<EOF border-color: pink; max-width: 700px; margin: auto; +} +.objdiv { + border-style: solid; + border-width: 3px; + border-color blue; + max-width: 700px; + margin: auto; +} +.stick { + width: 100%; + text-align: right; + position: sticky; + top: 0px; +} +.stick span { + border-style: solid; + border-width: 3px; + border-color: black; } </style> </head> <body> - <div hx-get="?at=${first}" hx-trigger="revealed" hx-swap="afterend">INBOX</div> + <div class="stick"> + <span> + <a href="#top">top</a> + <a href="#center">center</a> + <a href="#bottom">bottom</a> + </span> + </div> + <div hx-get="?before=${first}&reload=10" hx-trigger="every 10s" hx-swap="outerHTML"> +<a href="?before=${first}">no javascript? load the newer posts than when the page loaded.</a> + </div> + <div id="center" hx-get="?at=${first}" hx-trigger="revealed" hx-swap="afterend"> +INBOX (page loaded here. newer posts above. older posts below) +<a href="?at=${first}">no javascript? load the next ${per_page} posts</a> + </div> + <a href="#top">top</a> <a id="bottom" href="#bottom">bottom</a> </body> </html> EOF diff --git a/ap-object2html b/ap-object2html new file mode 100755 index 0000000000000000000000000000000000000000..2bfba93c74718767abb767cc12723f2a36ec8cc4 --- /dev/null +++ b/ap-object2html @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +object_file="$1" + +recursion_count="${2:-0}" + +if [ "$recursion_count" -gt 10 ];then + printf "WHOOOOOOA THERE BUDDY. WE'RE RECURSING TOO DEEP.\n" + exit 1 +fi + +if [ ! "$object_file" ];then + printf "usage: ap-object2html <object file>\n" >&2 + exit 1 +fi + +printf '<div class="objdiv">\n' + +id="$(jq -r '.id' < "${object_file}")" +qs_id="$(uriescape "$id" | sed 's|\&|%26|g;s|;|%3b|g;s|#|%23|g')" +entitied_qs_id="$(html_entities_encode <<< "${qs_id}")" +entitied_id="$(html_entities_encode <<< "${id}")" +printf 'Id: <a href="%s">%s</a>\n' "$id" "$entitied_id" +printf '<a href="actpub:like?uri=%s">[like]</a>' "$entitied_qs_id" +printf '<br/>\n' + +attributed_to="$(jq -r .attributedTo < "${object_file}")" +printf 'Attributed To: <a href="%s">%s</a><br/>\n' "$attributed_to" "${attributed_to}" + +inReplyTo="$(jq -r '.inReplyTo//""' 2>/dev/null < "${object_file}" | html_entities_encode)" +if [ "$inReplyTo" ];then + printf "inReplyTo: <a href="%s">%s</a><br/>\n" "${inReplyTo}" "${inReplyTo}" + ## let's cache this fucker too and show it first :D + cache_file="$(ap-cacheobject "${inReplyTo}")" + ap-object2html "${cache_file}" $[$recursion_count + 1] +fi +#printf "Content: %s<br/>\n" "$(jq -r '.object.content' 2>/dev/null < "${object_file}" | html_entities_encode)" +printf "Content: %s<br/>\n" "$(jq -r '.content' 2>/dev/null < "${object_file}")" +if [ "$(jq -r '.attachment | type' < "${object_file}")" == "array" ];then + jq -r '.attachment | .[] | .mediaType,.url' 2>/dev/null < "${object_file}" | paste - - | html_entities_encode | while read type url;do + case "$type" in + image/*) + printf 'attachment: <a href="%s"><img src="%s" /></a><br/>' "$uri" "$url" + ;; + audio/*) + printf 'attachment: <audio controls><source src="%s" type="%s"></video><br/>' "$url" "$type" + ;; + video/*) + printf 'attachment: <video loop autoplay><source src="%s" type="%s"></video><br/>' "$url" "$type" + ;; + *) + printf '<a href="%s">attachment</a><br/>' "$url" + ;; + esac + done +fi + +printf '</div>\n'
-----END OF PAGE-----
-- Response ended
-- Page fetched on Sun Jun 2 14:56:16 2024