-- 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: bfe113642c2695329559dd5c63dc8aa3d5ae5e8c:
path_to:
revision_to:

git.thebackupbox.net

actpub

git://git.thebackupbox.net/actpub

commit bfe113642c2695329559dd5c63dc8aa3d5ae5e8c
Author: epoch <epoch@thebackupbox.net>
Date:   Tue Mar 7 00:57:41 2023 -0600

    a whole lot of changes coming from the computer I use as client

diff --git a/Makefile b/Makefile

index d957a7dc36cefc1c9e31c330f6d060ac7b5f73b6..

index ..6398bd2439687a083bbdaef54ec355d12f95267d 100644

--- a/Makefile
+++ b/Makefile
@@ -4,20 +4,32 @@ all: csv

 install: all
 	install -t $(PREFIX)/bin webfinger
+	install -t $(PREFIX)/bin ap-iam
 	install -t $(PREFIX)/bin ap-like
+	install -t $(PREFIX)/bin ap-date
+	install -t $(PREFIX)/bin ap-accept
+	install -t $(PREFIX)/bin ap-create-note
 	install -t $(PREFIX)/bin ap-follow
-	install -t $(PREFIX)/bin ap-getattachmentlist
+	install -t $(PREFIX)/bin ap-whoami
 	install -t $(PREFIX)/bin ap-geticon
+	install -t $(PREFIX)/bin ap-announce
 	install -t $(PREFIX)/bin ap-getimage
-	install -t $(PREFIX)/bin ap-getinboxuri
 	install -t $(PREFIX)/bin ap-getactor
-	install -t $(PREFIX)/bin ap-getactoruri
 	install -t $(PREFIX)/bin ap-getpubkey
+	install -t $(PREFIX)/bin ap-cacheactor
 	install -t $(PREFIX)/bin ap-actor2acct
-	install -t $(PREFIX)/bin ap-activity2html
-	install -t $(PREFIX)/bin ap-verifysignature
+	install -t $(PREFIX)/bin ap-getactoruri
+	install -t $(PREFIX)/bin ap-getinboxuri
 	install -t $(PREFIX)/bin ap-cacheobject
 	install -t $(PREFIX)/bin ap-object2html
+	install -t $(PREFIX)/bin ap-getendpoint
+	install -t $(PREFIX)/bin ap-getoutboxuri
+	install -t $(PREFIX)/bin ap-getfollowers
+	install -t $(PREFIX)/bin ap-activity2html
+	install -t $(PREFIX)/bin ap-signed-request
+	install -t $(PREFIX)/bin ap-verifysignature
+	install -t $(PREFIX)/bin ap-upload-to-outbox
+	install -t $(PREFIX)/bin ap-getattachmentlist
 	install -t $(PREFIX)/bin csv
 	install ap-inbox.cgi /var/www/sites/hacking/inbox2/index.cgi
 	install ap-inbox.cgi /home/epoch/public_html/inbox2/index.cgi
diff --git a/README b/README

index 6930f5791f143d8a069576d57734931061b7cd30..

index ..9176518185447f9977c7efa6e3f293fc8de9a16e 100644

--- a/README
+++ b/README
@@ -1 +1,28 @@
-https://www.w3.org/TR/activitypub/
+###
+### A PILE OF SCRIPTS TO TRY TO BE MY OWN ACTIVITY PUB FEDIVERSE SERVER
+###
+
+
+so far these scripts will upload an activity to your outbox.
+
+ap-accept
+ap-announce
+ap-create-note
+ap-follow
+ap-like
+
+and then send the activity directly to who it is meant for.
+
+if this README gets out of date (likely) a good bet for finding the things
+that are actions you can take is to grep for "uuidgen"
+
+each separate target will need their individual POSTs signed.
+
+using the user's private key.
+
+so this is going to run client-side, then just get dropping into the outbox.
+like the rest of the things that add stuff to the outbox do.
+
+
+object types: https://www.w3.org/TR/activitystreams-vocabulary/#object-types
+ofc: https://www.w3.org/TR/activitypub/
diff --git a/ap-accept b/ap-accept
new file mode 100755
index 0000000000000000000000000000000000000000..6b3d5d7aeca1afcfff05917784f144db7d0f8200
--- /dev/null
+++ b/ap-accept
@@ -0,0 +1,85 @@
+#!/usr/bin/env bash
+
+date="$(rfc7231date)"
+
+## this is static
+context="https://www.w3.org/ns/activitystreams"
+
+## TODO: figure out if these have to mean anything
+uuid="$(uuidgen -t)"
+id="https://thebackupbox.net/~epoch/outbox/${uuid}"
+
+type="Accept"
+
+if [ ! "$1" ];then
+  printf "usage: ap-accept <uri-of-your-outbox-item-to-accept>\n" >&2
+  exit 1
+fi
+
+uri="$1"
+
+object_file="$(ap-cacheobject "${uri}")"
+object="$(cat "${object_file}")"
+
+target_actor="$(jq -r .actor < "${object_file}")"
+actor_file="$(ap-cacheactor "${target_actor}")"
+
+if [ ! "${target_actor}" ];then
+  printf "unable to find actor URI for user %s\n" "$user" >&2
+  exit 2
+fi
+
+target_inbox="$(jq -r .inbox < "${actor_file}")"
+
+if [ ! "$target_inbox" ];then
+  printf "unable to find inbox URI for user %s\n" "$user" >&2
+  exit 3
+fi
+
+## actor should be grabbed from a config file, or you know, static since only I'm going to use this.
+actor="https://thebackupbox.net/~epoch/"
+
+host="$(printf "%s\n" "$target_actor" | uricut -d)"
+
+#TODO: extact the inbox to use based on the object, not just hard-coding the target's user@host here
+target_inbox_path="$(printf "%s\n" "${target_inbox}" | uricut -p)"
+
+POST_DATA='{"@context":"'"$context"'","id":"'"$id"'","type":"'"$type"'","actor":"'"$actor"'","object":'"$object"'}'
+
+#printf '%s' "$POST_DATA"
+#exit 0
+
+mkdir -p ~/.cache/ap/outbox/
+
+cache_file=~/.cache/ap/outbox/"${uuid}"
+printf "%s" "${POST_DATA}" > "${cache_file}"
+ap-upload-to-outbox "${cache_file}"
+
+HTTP_DIGEST="SHA-256=$(printf "%s" "$POST_DATA" | openssl sha256 | cut '-d ' -f2- | xxd -r -p | base64)"
+
+printf "digest: %s\n" "${HTTP_DIGEST}"
+
+HTTPSIG_KEYID="https://thebackupbox.net/~epoch/#main-key"
+HTTPSIG_HEADERS="(request-target) host date digest content-type"
+HTTPSIG_ALGO="rsa-sha256"
+CONTENT_TYPE="application/activity+json"
+
+SIGNED_STRING="(request-target): post ${target_inbox_path}
+host: $host
+date: $date
+digest: $HTTP_DIGEST
+content-type: $CONTENT_TYPE"
+
+HTTPSIG_SIGNATURE="$(openssl dgst -sha256 -sign ~/.config/ap/private.pem <(printf "%s" "${SIGNED_STRING}") | base64 | tr -d '\n')"
+HTTP_SIGNATURE='keyId="'"${HTTPSIG_KEYID}"'",algorithm="'"${HTTPSIG_ALGO}"'",headers="'"${HTTPSIG_HEADERS}"'",signature="'"${HTTPSIG_SIGNATURE}"'"'
+
+echo -e "doing the curl:\n"
+
+curl -i \
+  --data-raw "${POST_DATA}" \
+  -H "Accept: application/activity+json" \
+  -H "Signature: $HTTP_SIGNATURE" \
+  -H "Date: $date" \
+  -H "Digest: $HTTP_DIGEST" \
+  -H "Content-Type: $CONTENT_TYPE" \
+  -g "$target_inbox"
diff --git a/ap-announce b/ap-announce
new file mode 100755
index 0000000000000000000000000000000000000000..4f527210b670bef5feacb75b400c88f00389234b
--- /dev/null
+++ b/ap-announce
@@ -0,0 +1,56 @@
+#!/usr/bin/env bash
+
+if [ ! "$1" ];then
+  printf "usage: ap-announce object-uri\n" >&2
+  exit 1
+fi
+
+object="$1"
+date="$(rfc7231date)"
+context="https://www.w3.org/ns/activitystreams"
+uuid="$(uuidgen -t)"
+id="https://thebackupbox.net/~epoch/outbox/${uuid}"
+type="Announce"
+actor="https://thebackupbox.net/~epoch/"
+
+for target_inbox in "$(ap-getfollowers epoch@thebackupbox.net | xargs -n1 ap-getendpoint | sort | uniq)"
+  host="$(uricut -d <<< "${target_inbox}")"
+  target_inbox_path="$(uricut -p <<< "${target_inbox}")"
+
+  POST_DATA='{"@context":"'"$context"'","id":"'"$id"'","type":"'"$type"'","actor":"'"$actor"'","object":"'"$object"'"}'
+
+  cache_file=~/.cache/ap/outbox/"${uuid}"
+  printf "%s" "$POST_DATA" > "${cache_file}"
+  ap-upload-to-outbox "${cache_file}"
+
+  HTTP_DIGEST="SHA-256=$(printf "%s" "$POST_DATA" | openssl sha256 | cut '-d ' -f2- | xxd -r -p | base64)"
+
+  printf "digest: %s\n" "${HTTP_DIGEST}"
+
+  HTTPSIG_KEYID="https://thebackupbox.net/~epoch/#main-key"
+  HTTPSIG_HEADERS="(request-target) host date digest content-type"
+  HTTPSIG_ALGO="rsa-sha256"
+  CONTENT_TYPE="application/activity+json"
+
+  SIGNED_STRING="(request-target): post ${target_inbox_path}
+host: $host
+date: $date
+digest: $HTTP_DIGEST
+content-type: $CONTENT_TYPE"
+
+  HTTPSIG_SIGNATURE="$(openssl dgst -sha256 -sign ~/.config/ap/private.pem <(printf "%s" "${SIGNED_STRING}") | base64 | tr -d '\n')"
+  HTTP_SIGNATURE='keyId="'"${HTTPSIG_KEYID}"'",algorithm="'"${HTTPSIG_ALGO}"'",headers="'"${HTTPSIG_HEADERS}"'",signature="'"${HTTPSIG_SIGNATURE}"'"'
+
+  printf "doing a curl to inbox: %s\n\n" "$target_inbox"
+  curl -i \
+    --data-raw "${POST_DATA}" \
+    -H "Accept: application/activity+json" \
+    -H "Signature: $HTTP_SIGNATURE" \
+    -H "Date: $date" \
+    -H "Digest: $HTTP_DIGEST" \
+    -H "Content-Type: $CONTENT_TYPE" \
+    -g "$target_inbox"
+  echo '[OK]'
+
+done
+
diff --git a/ap-cacheactor b/ap-cacheactor
new file mode 100755
index 0000000000000000000000000000000000000000..b72eb991aecf9ca4521e7314f367356031916da2
--- /dev/null
+++ b/ap-cacheactor
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+
+if [ ! "$1" ];then
+  printf 'Usage: ap-cacheactor <uri>\n' >&2
+  exit 1
+fi
+
+uri="$1"
+
+cache_file=~/.cache/ap/actor/"$(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-create-note b/ap-create-note
new file mode 100755
index 0000000000000000000000000000000000000000..1bb1d14f2435111aaafc3ac3fba97ffa37515d01
--- /dev/null
+++ b/ap-create-note
@@ -0,0 +1,76 @@
+#!/usr/bin/env bash
+
+if [ ! "$1" ];then
+  printf "usage: ap-create-note <note-data>\n" >&2
+  exit 1
+fi
+
+### come up with a way of getting an object to this script...
+### GET params from a webpage UI? heh.
+### "type" can be any from https://www.w3.org/TR/activitystreams-vocabulary/#object-types
+### but will probably get hardcoded to Note
+
+#    "id": "https://example.com/~mallory/note/72",
+#    "type": "Note",
+#    "attributedTo": "https://example.net/~mallory",
+#    "content": "This is a note",
+#    "published": "2015-02-10T15:04:55Z",
+#    "to": ["https://example.org/~john/"],
+#    "cc": ["https://example.com/~erik/followers",
+#           "https://www.w3.org/ns/activitystreams#Public"]
+
+timestamp="$(date +%s)"
+http_date="$(rfc7231date "${timestamp}")"
+ap_date="$(ap-date "--date=@${timestamp}")"
+context="https://www.w3.org/ns/activitystreams"
+uuid="$(uuidgen -t)"
+id="https://thebackupbox.net/~epoch/outbox/${uuid}" #need to get my own outbox URI
+type="Create"
+acct="$(ap-whoami)"
+actor="$(ap-getactoruri "${acct}")"
+to="https://www.w3.org/ns/activitystreams#Public"
+content="$1"
+
+object='{"id":"'"${id}"'#object","type":"Note","attributedTo":"'"${actor}"'","content":"'"${content}"'","published":"'"${ap_date}"'","to":"'"${to}"'"}'
+
+for target_inbox in $(ap-getfollowers "${acct}" | xargs -n1 ap-getendpoint | sort | uniq);do
+  host="$(uricut -d <<< "${target_inbox}")"
+  target_inbox_path="$(uricut -p <<< "${target_inbox}")"
+
+  POST_DATA='{"@context":"'"$context"'","id":"'"$id"'","type":"'"$type"'","actor":"'"$actor"'","object":'"$object"'}'
+
+  cache_file=~/.cache/ap/outbox/"${uuid}"
+  printf "%s" "$POST_DATA" > "${cache_file}"
+  printf "ap-create-note: local cache file of create activity: %s\n" "${cache_file}" >&2
+  ap-upload-to-outbox "${cache_file}"
+
+  HTTP_DIGEST="SHA-256=$(printf "%s" "$POST_DATA" | openssl sha256 | cut '-d ' -f2- | xxd -r -p | base64)"
+
+  printf "ap-create-note: digest: %s\n" "${HTTP_DIGEST}" >&2
+
+  HTTPSIG_KEYID="https://thebackupbox.net/~epoch/#main-key"
+  HTTPSIG_HEADERS="(request-target) host date digest content-type"
+  HTTPSIG_ALGO="rsa-sha256"
+  CONTENT_TYPE="application/activity+json"
+
+  SIGNED_STRING="(request-target): post ${target_inbox_path}
+host: $host
+date: $http_date
+digest: $HTTP_DIGEST
+content-type: $CONTENT_TYPE"
+
+  HTTPSIG_SIGNATURE="$(openssl dgst -sha256 -sign ~/.config/ap/private.pem <(printf "%s" "${SIGNED_STRING}") | base64 | tr -d '\n')"
+  HTTP_SIGNATURE='keyId="'"${HTTPSIG_KEYID}"'",algorithm="'"${HTTPSIG_ALGO}"'",headers="'"${HTTPSIG_HEADERS}"'",signature="'"${HTTPSIG_SIGNATURE}"'"'
+
+  printf "ap-create-note: doing a curl to inbox: %s\n" "$target_inbox" >&2
+  curl -i \
+    --data-raw "${POST_DATA}" \
+    -H "Accept: application/activity+json" \
+    -H "Signature: $HTTP_SIGNATURE" \
+    -H "Date: $http_date" \
+    -H "Digest: $HTTP_DIGEST" \
+    -H "Content-Type: $CONTENT_TYPE" \
+    -g "$target_inbox"
+  echo '[DONE]' >&2
+
+done
diff --git a/ap-date b/ap-date
new file mode 100755
index 0000000000000000000000000000000000000000..58727cba1c5bb4dc468d45b110f20a0bd4f8b1eb
--- /dev/null
+++ b/ap-date
@@ -0,0 +1,3 @@
+#!/usr/bin/env bash
+# lol. I don't want to write this more than once.
+TZ=UTC date --rfc-3339=seconds "$@" | tr ' ' 'T' | sed 's/+00:00/Z/'
diff --git a/ap-follow b/ap-follow

index f0b1ad0d064b8651919d5dc9ed7f1cc8fcf41860..

index ..95a9c2cab8aac5a7385211be8df734543fdc3701 100755

--- a/ap-follow
+++ b/ap-follow
@@ -6,7 +6,8 @@ date="$(rfc7231date)"
 context="https://www.w3.org/ns/activitystreams"

 ## TODO: figure out if these have to mean anything
-id="https://thebackupbox.net/$(uuidgen)"
+uuid="$(uuidgen -t)"
+id="https://thebackupbox.net/~epoch/outbox/${uuid}"

 type="Follow"

@@ -37,7 +38,13 @@ host="$(printf "%s\n" "$target_actor" | uricut -d)"
 #TODO: extact the inbox to use based on the object, not just hard-coding the target's user@host here
 target_inbox_path="$(printf "%s\n" "${target_inbox}" | uricut -p)"

-POST_DATA='{"@context":"'"$context"'","id":"'"$id"'","type":"'"$type"'","actor":"'"$actor"'","object":"'"$object"'"}'
+POST_DATA='{"@context":"'"$context"'","id":"'"$id"'","type":"'"$type"'","actor":"'"$actor"'","object":"'"$target_actor"'"}'
+
+mkdir -p ~/.cache/ap/outbox/
+
+cache_file=~/.cache/ap/outbox/"${uuid}"
+printf "%s" "${POST_DATA}" > "${cache_file}"
+ap-upload-to-outbox "${cache_file}"

 HTTP_DIGEST="SHA-256=$(printf "%s" "$POST_DATA" | openssl sha256 | cut '-d ' -f2- | xxd -r -p | base64)"

@@ -59,6 +66,8 @@ HTTP_SIGNATURE='keyId="'"${HTTPSIG_KEYID}"'",algorithm="'"${HTTPSIG_ALGO}"'",hea

 echo -e "doing the curl:\n"

+echo $target_inbox
+
 curl -i \
   --data-raw "${POST_DATA}" \
   -H "Accept: application/activity+json" \
@@ -67,3 +76,5 @@ curl -i \
   -H "Digest: $HTTP_DIGEST" \
   -H "Content-Type: $CONTENT_TYPE" \
   -g "$target_inbox"
+
+echo 'DONE'
diff --git a/ap-getactor b/ap-getactor

index c905db8de46b159a11c62ed939b2ed4cd19c07b9..

index ..8b4145f15c0be646ddb4829472d981f9f0838215 100755

--- a/ap-getactor
+++ b/ap-getactor
@@ -4,6 +4,11 @@ if [ "$1" == "--no-cache" ];then
   no_cache=1
   shift
 fi
+
+if [ ! "$1" ];then
+  printf "usage: ap-getactor <user@host>\n" >&2
+  exit 1
+fi
 user="$(printf "%s\n" "$1" | sed 's/^@//' | cut -d@ -f1)"
 domain="$(printf "%s\n" "$1" | sed 's/^@//' | cut -d@ -f2)"
 target="${user}@${domain}"
@@ -11,18 +16,21 @@ mkdir -p ~/.cache/ap/actor
 cache_file=~/.cache/ap/actor/${target}
 cache_file2=~/.cache/ap/actor/$(sha256sum <<< ${object} | cut '-d ' -f1)
 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.
+  printf "ap-getactor: 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")"
+
+  ###curl -s -o "${cache_file}" -H "Accept: application/activity+json, application/ld+json" -g "$(ap-getactoruri "$target")"
+  ### NOTICE: some servers require you to use signed GETs to get an actor file.
+  ap-signed-request "$(ap-getactoruri "$target")" > "${cache_file}"
   ln -s ${cache_file} ${cache_file2}
   #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
+  printf "ap-getactor: using cached actor file for %s@%s\n" "${user}" "${domain}" >&2
 fi
 cat "${cache_file}"
diff --git a/ap-getendpoint b/ap-getendpoint
new file mode 100755
index 0000000000000000000000000000000000000000..4c400e56ff5b2967a57dfe8db4e41c7ab8f14858
--- /dev/null
+++ b/ap-getendpoint
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+if [ ! "$1" ];then
+  printf "usage: ap-getendpoint <actor-uri>\n" >&2
+  exit 1
+fi
+jq -r '.endpoints.sharedInbox//.inbox//""' < "$(ap-cacheactor "$1")"
diff --git a/ap-getfollowers b/ap-getfollowers
new file mode 100755
index 0000000000000000000000000000000000000000..6d902609d5041cccca83e8a757758ca14b6f1c73
--- /dev/null
+++ b/ap-getfollowers
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+### use $1 for the acct of whose followers we want to grab...
+
+if [ ! "$1" ];then
+  printf "usage: ap-getfollowers <user@host>\n" 2>&1
+  exit 1
+fi
+
+acct="$1"
+url="$(ap-getactor "$acct" | jq -r '.followers')"
+
+### need to grab first page, then while loop until no next...
+next="$url"
+while [ "$next" ];do
+  echo "ap-getfollowers: getting $next" >&2
+  resp="$(curl -sg "$next")"
+  jq -r '.orderedItems//[]' <<< "$resp" | jq -r '.[]'
+  next="$(jq -r '.next//.first//""' <<< "$resp")"
+done
diff --git a/ap-getinboxuri b/ap-getinboxuri

index a78e1d31917682bfa88712ea14e65bf5573f4de5..

index ..d35c6452156b1202bdd4ba3de64c3c28411445ee 100755

--- a/ap-getinboxuri
+++ b/ap-getinboxuri
@@ -1,2 +1,2 @@
 #!/bin/sh
-ap-getactor "$1" | jq -r '.inbox'
+ap-getactor "$1" | jq -r '.inbox//""'
diff --git a/ap-getoutboxuri b/ap-getoutboxuri
new file mode 100755
index 0000000000000000000000000000000000000000..29a5bdf9c3ad5fccd0833c4034895e8943f721b7
--- /dev/null
+++ b/ap-getoutboxuri
@@ -0,0 +1,6 @@
+#!/bin/sh
+if [ ! "$1" ];then
+  printf "usage: ap-getoutboxuri <user@host>\n" >&2
+  exit 1
+fi
+ap-getactor "$1" | jq -r '.outbox//""'
diff --git a/ap-iam b/ap-iam
new file mode 100755
index 0000000000000000000000000000000000000000..503c21e78927ec0a803d232f9506e892d1510b27
--- /dev/null
+++ b/ap-iam
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+if [ ! "$1" ];then
+  printf "usage: ap-iam user@host\n" >&2
+  printf "identify yourself as user@host in the config file.\n" >&2
+  printf "read this script to see where it stores this.\n" >&2
+  exit 1
+fi
+iam="$1"
+
+printf "%s\n" "$1" > ~/.config/ap/iam
diff --git a/ap-like b/ap-like

index fed5bdaf1e9c5e4785b4da0a57e309805be19d92..

index ..ef1c2d9e0db067953975acb6513e5fa74129dd7c 100755

--- a/ap-like
+++ b/ap-like
@@ -6,7 +6,8 @@ date="$(rfc7231date)"
 context="https://www.w3.org/ns/activitystreams"

 ## TODO: figure out if these have to mean anything
-id="https://thebackupbox.net/$(uuidgen)"
+uuid="$(uuidgen -t)"
+id="https://thebackupbox.net/~epoch/outbox/${uuid}"

 type="Like"

@@ -45,6 +46,10 @@ target_inbox_path="$(printf "%s\n" "${target_inbox}" | uricut -p)"

 POST_DATA='{"@context":"'"$context"'","id":"'"$id"'","type":"'"$type"'","actor":"'"$actor"'","object":"'"$object"'"}'

+cache_file=~/.cache/ap/outbox/"${uuid}"
+printf "%s" "$POST_DATA" > "${cache_file}"
+ap-upload-to-outbox "${cache_file}"
+
 HTTP_DIGEST="SHA-256=$(printf "%s" "$POST_DATA" | openssl sha256 | cut '-d ' -f2- | xxd -r -p | base64)"

 printf "digest: %s\n" "${HTTP_DIGEST}"
diff --git a/ap-signed-request b/ap-signed-request
new file mode 100755
index 0000000000000000000000000000000000000000..a4c149257d0773ca499a20643c0f928d079b987e
--- /dev/null
+++ b/ap-signed-request
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+
+### this script is needed in some places instead of a plain curl...
+### tilde.zone requires you use a signed request when asking for
+### actor objects.
+
+privkey=~/.config/ap/private.pem
+keyid="$(head -n1 "${privkey}")"
+
+date="$(rfc7231date)"
+
+if [ ! "$1" ];then
+  printf "usage: ap-signed-request <uri>\n" >&2
+  exit 1
+fi
+
+uri="$1"
+host="$(printf "%s\n" "$uri" | uricut -d)"
+path="$(printf "%s\n" "$uri" | uricut -p)"
+
+### NOTE! the KEYID is stored on the first line of the private.pem
+HTTPSIG_KEYID="${keyid}"
+HTTPSIG_HEADERS="(request-target) host date"
+HTTPSIG_ALGO="rsa-sha256"
+CONTENT_TYPE="application/activity+json"
+
+SIGNED_STRING="(request-target): get ${path}
+host: ${host}
+date: ${date}"
+
+HTTPSIG_SIGNATURE="$(openssl dgst -sha256 -sign "${privkey}" <(printf "%s" "${SIGNED_STRING}") | base64 | tr -d '\n')"
+HTTP_SIGNATURE='keyId="'"${HTTPSIG_KEYID}"'",algorithm="'"${HTTPSIG_ALGO}"'",headers="'"${HTTPSIG_HEADERS}"'",signature="'"${HTTPSIG_SIGNATURE}"'"'
+
+curl -s \
+  -H "Accept: application/activity+json" \
+  -H "Signature: $HTTP_SIGNATURE" \
+  -H "Date: $date" \
+  -g "$uri"
+
diff --git a/ap-upload-to-outbox b/ap-upload-to-outbox
new file mode 100755
index 0000000000000000000000000000000000000000..e9a8c41d95d9fbcb053a51e5147fd0e6dfce0022
--- /dev/null
+++ b/ap-upload-to-outbox
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+#basename="$(basename "$1")"
+#shellsafe="$(printf "%s\n" "$basename" | sed 's/'\''/'\''\\'\'''\''/g')"
+#echo $1
+### we need "$1" to have its full path to prevent : problems
+
+fullpath="$(uriunescape "$(normalpath "$1")")"
+basename="$(basename "${fullpath}")"
+webbased="$(uriescape "${basename}")"
+#echo "uploading: $fullpath to..."
+host=21.41.41.5
+target="/home/epoch/public_html/outbox2/"
+target_uri="scp://${host}/${target}"
+#echo "$target scp://${host}/${target}"
+
+scp "${fullpath}" "${target_uri}" 2>&1 >/dev/null
+
+#echo $?
+uri="https://thebackupbox.net/~epoch/outbox/${webbased}"
+printf "%s" "$uri" | xclip -i
diff --git a/ap-whoami b/ap-whoami
new file mode 100755
index 0000000000000000000000000000000000000000..ea655580f3b2d4d99fe8b81e6a01b854b0815129
--- /dev/null
+++ b/ap-whoami
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+if [ ! -e ~/.config/ap/iam ];then
+  printf "ap-whoami: who you are is not set.\n" >&2
+  printf "figure out who you are and run ap-iam 'you@host'\n" >&2
+  exit 1
+fi
+cat ~/.config/ap/iam
diff --git a/webfinger b/webfinger

index ed22756a06b2399d0454f15c4e038cf1d03011ea..

index ..319d8888e9970fffb5a837e2dc88ee4054b046a5 100755

--- a/webfinger
+++ b/webfinger
@@ -17,10 +17,10 @@ domain="$(printf '%s\n' "$1" | sed 's/^@//' | cut -d@ -f2)"
 mkdir -p ~/.cache/webfinger
 cache_file=~/.cache/webfinger/${user}@${domain}
 if [ ! -s "${cache_file}" -o "${no_cache}" = 1 ];then
-  printf "downloading webfinger for %s@%s\n" "${user}" "${domain}" >&2
+  printf "webfinger: downloading webfinger for %s@%s\n" "${user}" "${domain}" >&2
   wget -qO "${cache_file}" "https://${domain}/.well-known/webfinger?resource=acct:${user}@${domain}"
 else
-  printf "using cached webfinger for %s@%s\n" "${user}" "${domain}" >&2
+  printf "webfinger: using cached webfinger for %s@%s\n" "${user}" "${domain}" >&2
 fi

 ### the response could be either xml or jq

-----END OF PAGE-----

-- Response ended

-- Page fetched on Sun Jun 2 16:51:04 2024