Bash と Caddy サーバで ActivityPub のインスタンス(10) 自分からフォロー・アンフォローする

## follow.json
例によって follow.json を作る。自分が承認したリクエストと大して変わらない。
```json:follow.json
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://{my_instance}/users/{myself}/statuses/{id}",
  "type": "Follow",
  "actor": "https://{my_instance}/users/{myself}",
  "object": "https://{to_instance}/users/{to}"
}
```

そしてこの json も json_templates ディレクトリに置く。

## follow.sh
script ディレクトリに置く follow.sh は、単にこの follow.json に自分とフォローしたい相手のインスタンスとアクター名を突っ込んで、相手の inbox へ投げるだけである。
```bash:follow.sh
#!/bin/bash


read -p "@myself@my_instance: " MY
MY_arry=(${MY//@/ })
myself=${MY_arry[0]}
my_instance=${MY_arry[1]}
echo

read -p "@to@to_instance: " TO
TO_arry=(${TO//@/ })
to=${TO_arry[0]}
to_instance=${TO_arry[1]}
echo

unixtime=$(date "+%s")
date_now=$(date -uR  | head -c -6 | sed -e 's/$/GMT/')

sed -e "s/{id}/$unixtime/g" ./json_templates/follow.json > live
sed -i "s/{myself}/$myself/g" live
sed -i "s/{my_instance}/$my_instance/g" live
sed -i "s/{to}/$to/g" live
sed -i "s/{to_instance}/$to_instance/g" live

body=$(cat live | jq -c .)
digest_val=$(echo -n "$body" | sha256sum | xxd -r -p | base64)

URL=$(curl https://$to_instance/.well-known/webfinger?resource=acct:$to@$to_instance | jq -r '.links[] | select (.rel == "self")'.href | tr -d "\"")
INBOX=$(curl -H "Accept: application/activity+json" $URL | jq .inbox | tr -d "\"")
REQUEST_TARGET=$(echo  "/"$(sed -E 's/^.*(https):\/\/([^/]+).([^/]+)/\3/g' <<< $INBOX))

signature_headers="(request-target): post ${REQUEST_TARGET}\ndate: ${date_now}\nhost: ${to_instance}\ndigest: SHA-256=${digest_val}"
echo -e "$signature_headers" > 4_sig_headers # 後に見返すためにファイルに
sig_val=$(echo -en $signature_headers | openssl dgst -binary -sign ./personal/private -sha256 | openssl enc -A -base64)
signature="Signature: keyId=\"https://${my_instance}/users/${myself}#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) date host digest\",signature=\"$sig_val\""

curl -v -H "Date: $date_now" -H "Digest: SHA-256=$digest_val" -H "$signature" $INBOX -d "$body"

echo $body > ./post/$unixtime
```

## unfollow してみる
次にこのフォローを外して(アンフォロー)みる。アンフォローするには、フォローした json を
```json:unfollow.json
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://{my_instance}/users/{myself}#follows/{id}/undo",
  "type": "Undo",
  "actor": "https://{my_instance}/users/{myself}",
  "object": {follow-json}
}
```
と、包んだ json をフォローしたアクターの inbox へ投げつけると出来る。{follow-json} の箇所にフォローした json を突っ込む。フォローした json が
```json
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://ホニャララ/users/aktor/statuses/1705589058",
  "type": "Follow",
  "actor": "https://ホニャララ/users/aktor",
  "object": "https://他のインスタンス/users/アクター"
}
```
ならば(見やすいように改行してある)、
```json
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://ホニャララ/users/aktor#follows/1705589555/undo",
  "type": "Undo",
  "actor": "https://ホニャララ/users/aktor",
  "object": {
	  "@context": "https://www.w3.org/ns/activitystreams",
	  "id": "https://ホニャララ/users/aktor/statuses/1705589058",
	  "type": "Follow",
	  "actor": "https://ホニャララ/users/aktor",
	  "object": "https://他のインスタンス/users/アクター"
	}
}
```

こうなる。なので unfollow.sh は以下のようにする。後から改善する(予定である)が、今はフォローした json ファイルを post ディレクトリからカレントディレクトリにコピーして置いておくこと。accept.sh とほぼ変わらない。
```bash:unfollow.sh
#!/bin/bash


read -p "@myself@my_instance: " MY
MY_arry=(${MY//@/ })
myself=${MY_arry[0]}
my_instance=${MY_arry[1]}
echo

read -p "@to@to_instance: " TO
TO_arry=(${TO//@/ })
to=${TO_arry[0]}
to_instance=${TO_arry[1]}
echo

unixtime=$(date "+%s")
date_now=$(date -uR  | head -c -6 | sed -e 's/$/GMT/')

sed -e "s/{id}/$unixtime/g" ./json_templates/follow.json > live
sed -i "s/{myself}/$myself/g" live
sed -i "s/{my_instance}/$my_instance/g" live
sed -i "s/{to}/$to/g" live
sed -i "s/{to_instance}/$to_instance/g" live

body=$(cat live | jq -c .)
digest_val=$(echo -n "$body" | sha256sum | xxd -r -p | base64)

URL=$(curl https://$to_instance/.well-known/webfinger?resource=acct:$to@$to_instance | jq -r '.links[] | select (.rel == "self")'.href | tr -d "\"")
INBOX=$(curl -H "Accept: application/activity+json" $URL | jq .inbox | tr -d "\"")
REQUEST_TARGET=$(echo  "/"$(sed -E 's/^.*(https):\/\/([^/]+).([^/]+)/\3/g' <<< $INBOX))

signature_headers="(request-target): post ${REQUEST_TARGET}\ndate: ${date_now}\nhost: ${to_instance}\ndigest: SHA-256=${digest_val}"
echo -e "$signature_headers" > 4_sig_headers # 後に見返すためにファイルに
sig_val=$(echo -en $signature_headers | openssl dgst -binary -sign ./personal/private -sha256 | openssl enc -A -base64)
signature="Signature: keyId=\"https://${my_instance}/users/${myself}#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) date host digest\",signature=\"$sig_val\""

curl -v -H "Date: $date_now" -H "Digest: SHA-256=$digest_val" -H "$signature" $INBOX -d "$body"

echo $body > ./post/$unixtime
```

post ディレクトリからコピーしたフォローリクエストのファイルの名前が 1705601087 だとすると
```
@myself@my_instance: @aktor@ホニャララ

@to@to_instance: @相手アクター@そのインスタンス

What request do you Undo?: 1705601087
```
でアンフォローできる。


## 参考記事
[ Fediverse入門―非中央集権型SNSサーバを作ろう！（1） ](https://gihyo.jp/dev/serial/01/perl-hackers-hub/005901)