ai/at
1
0
Files
at/install.zsh
2025-12-06 12:39:44 +09:00

364 lines
11 KiB
Bash
Executable File

#!/bin/zsh
# ./install.zsh $HOST
repos_v='{}'
function at-repos-env() {
host=$1
if [ -z "$1" ];then
host=syu.is
fi
did=did:plc:6qyecktefllvenje24fcxnie
icon=https://git.syui.ai/ai/at/raw/branch/main/icons/Logotype.tsx
repos=(
https://github.com/did-method-plc/did-method-plc
https://github.com/bluesky-social/indigo
https://github.com/bluesky-social/atproto
https://github.com/bluesky-social/social-app
https://github.com/bluesky-social/feed-generator
https://github.com/bluesky-social/ozone
https://github.com/bluesky-social/jetstream
)
services=( bsky plc pds jetstream bgs ozone social-app )
d=${0:a:h}
dh=${0:a:h:h}
name=${host%%.*}
domain=${host##*.}
dport=5000
}
function at-repos-json() {
f=~/.config/atproto/token.json
j="{ \"did\": \"did:plc:6qyecktefllvenje24fcxnie\", \"didDoc\": { \"service\": [ { \"serviceEndpoint\": \"https://syu.is\" } ] }, \"handle\": \"ai.syu.is\", \"accessJwt\": \"xxx\" }"
if [ ! -f "$f" ];then
mkdir -p ~/.config/atproto
echo $j >> $f
fi
echo $f
}
function at-repos-token() {
at-repos-json
if [ -z "$host" ] && [ -f $f ];then
host=`cat $f|jq -r ".didDoc.service.[].serviceEndpoint"`
handle=`cat $f|jq -r ".handle"`
did=`cat $f|jq -r ".did"`
token=`cat $f|jq -r ".token"`
host=${host##*/}
fi
name=${host%%.*}
domain=${host##*.}
}
function at-repos-clone() {
if [ ! -d $d/repos ];then
mkdir -p $d/repos
fi
cd $d/repos
for ((i=1; i<=${#repos}; i++)); do
repo=${repos[$i]}
echo $repo
if [ ! -d $d/repos/${repo##*/} ];then
git clone $repo
fi
done
if [ ! -f $d/repos/feed-generator/Dockerfile ] && [ -f $d/docker/feed/Dockerfile ];then
cp -rf $d/docker/feed/Dockerfile $d/repos/feed-generator/
fi
}
function at-repos-pull() {
cd $d/repos
for ((i=1; i<=${#repos}; i++)); do
repo=${repos[$i]}
echo $repo
if [ -d $d/repos/${repo##*/} ];then
cd $d/repos/${repo##*/}
git stash
if ! git pull;then
rm -rf $d/repos/${repo##*/}
at-repos-clone
fi
fi
rv=$(echo "$repos_v" | jq -r ".[\"${repo##*/}\"]")
if [ "$rv" != "null" ];then
cd $d/repos/${repo##*/}
git reset --hard $rv
cd ..
fi
done
cd $d
}
function at-repos-social-app-icon() {
curl -sL https://raw.githubusercontent.com/bluesky-social/social-app/main/src/view/icons/Logotype.tsx -o $d/repos/social-app/src/view/icons/Logotype.tsx
if [ -d $d/icons ];then
mkdir -p $d/icons
fi
cp -rf $d/repos/social-app/src/view/icons/Logotype.tsx $d/icons/
}
function at-repos-social-app-icon-origin() {
curl -sL $icon -o $d/icons/Logotype.tsx
}
function at-repos-social-app-avatar-write() {
did_admin=did:plc:6qyecktefllvenje24fcxnie
dt=$d/repos/social-app/src
cd $dt
grep -R syu.is .|cut -d : -f 1|sort -u|xargs sed -i "s/syu.is/${host}/g"
grep -R web.syu.is .|cut -d : -f 1|sort -u|xargs sed -i "s/web.syu.is/web.${host}/g"
f=$dt/lib/constants.ts
sed -i "s#export const BSKY_SERVICE = 'https://bsky.social'#export const BSKY_SERVICE = 'https://${host}'#g" $f
sed -i "s#export const BSKY_SERVICE_DID = 'did:web:bsky.social'#export const BSKY_SERVICE_DID = 'did:web:${host}'#g" $f
sed -i "s#export const PUBLIC_BSKY_SERVICE = 'https://public.api.bsky.app'#export const PUBLIC_BSKY_SERVICE = 'https://bsky.${host}'#g" $f
sed -i "s#export const PUBLIC_APPVIEW = 'https://api.bsky.app'#export const PUBLIC_APPVIEW = 'https://bsky.${host}'#g" $f
sed -i "s#export const PUBLIC_APPVIEW_DID = 'did:web:api.bsky.app'#export const PUBLIC_APPVIEW_DID = 'did:web:bsky.${host}'#g" $f
f=$dt/view/icons/Logotype.tsx
o=$d/icons/Logotype.tsx
cp -rf $o $f
f=$dt/view/com/util/UserAvatar.tsx
curl -sL https://raw.githubusercontent.com/bluesky-social/social-app/refs/heads/main/src/view/com/util/UserAvatar.tsx -o $f
sed -i "s#/img/avatar/plain/#https://cdn.web.syu.is/img/avatar/plain/#g" $f
sed -i "s#/img/avatar_thumbnail/plain/#https://bsky.${host}/img/avatar/plain/#g" $f
sed -i "s#source={{uri: avatar}}#source={{ uri: hackModifyThumbnailPath(avatar, 1 > 0), }}#g" $f
curl -sL https://raw.githubusercontent.com/bluesky-social/social-app/refs/heads/main/src/lib/strings/url-helpers.ts -o $dt/lib/strings/url-helpers.ts
sed -i "s#https://go.web.syu.is/redirect?u=\${encodeURIComponent(url)}#\${url}#g" $dt/lib/strings/url-helpers.ts
grep -R $did_admin .|cut -d : -f 1|sort -u|xargs sed -i "s/${did_admin}/${did}/g"
}
function at-repos-atproto-service-bsky-api-patch() {
# https://github.com/itaru2622/bluesky-selfhost-env/blob/master/patching/105-atproto-services-for-docker.diff
f=$d/repos/atproto/services/bsky/api.js
curl -sL https://raw.githubusercontent.com/bluesky-social/atproto/refs/heads/main/services/bsky/api.js -o $f
d_=$d/repos/atproto
p_=$d/patching/4367-atproto-services-bsky-api.diff
echo "applying patch: under ${f} for ${p_}"
pushd ${d_}
patch -p1 < ${p_}
popd
}
function at-repos-atproto-service-pds-index-patch() {
f=$d/repos/atproto/services/pds/index.js
curl -sL https://raw.githubusercontent.com/bluesky-social/atproto/refs/heads/main/services/pds/index.js -o $f
d_=$d/repos/atproto
p_=$d/patching/4367-atproto-services-pds-index.diff
echo "applying patch: under ${f} for ${p_}"
pushd ${d_}
patch -p1 < ${p_}
popd
}
function at-repos-atproto-oauth-same-site-patch() {
f=$d/repos/atproto/packages/oauth/oauth-provider/src/router/create-authorization-page-middleware.ts
d_=$d/repos/atproto
p_=$d/patching/170-pds-oauth-same-site-fix.patch
echo "applying patch: under ${f} for ${p_}"
pushd ${d_}
patch -p1 < ${p_}
popd
}
function at-repos-social-app-agent-patch() {
f=$d/repos/social-app/src/state/session/agent.ts
p_=$d/patching/8980-social-app-disable-proxy.diff
d_=$d/repos/social-app
echo "applying patch: under ${f} for ${p_}"
pushd ${d_}
patch -p1 < ${p_}
popd
}
function at-repos-social-app-disable-external-services-patch() {
f=$d/repos/social-app/src/state/geolocation/const.ts
p_=$d/patching/8980-social-app-disable-external-services.diff
d_=$d/repos/social-app
echo "applying patch: under ${f} for ${p_}"
pushd ${d_}
patch -p1 < ${p_}
popd
}
function at-repos-social-app-statsig-patch() {
f=$d/repos/social-app/src/lib/statsig/statsig.tsx
p_=$d/patching/disable-statsig-sdk.diff
d_=$d/repos/social-app
echo "applying patch: under ${f} for ${p_}"
pushd ${d_}
patch -p1 < ${p_}
popd
}
function at-repos-social-app-dockerfile-yarn-timeout-patch() {
f=$d/repos/social-app/Dockerfile
p_=$d/patching/140-social-app-yarn-network-timeout.patch
d_=$d/repos/social-app
echo "applying patch: under ${f} for ${p_}"
pushd ${d_}
patch -p1 < ${p_}
popd
}
function at-repos-atproto-service-ozone-api-patch() {
f=$d/repos/atproto/services/ozone/api.js
d_=$d/repos/atproto
p_=$d/patching/130-atproto-ozone-enable-daemon-v2.patch
echo "applying patch: under ${f} for ${p_}"
pushd ${d_}
patch -p1 < ${p_}
popd
}
function at-repos-ozone-patch() {
#DOMAIN=syu.is
cd $d/repos
d_=$d/repos/ozone
rm -rf ${d_}
p_=$d/patching/120-ozone-runtimeEnvVars.diff
git clone https://github.com/bluesky-social/ozone
cd ${d_}
pushd ${d_}
echo "applying patch: under ${d_} for ${p_}"
patch -p1 < ${p_}
popd
p_=$d/patching/122-ozone-enable-daemon.diff
echo "applying patch: under ${d_} for ${p_}"
pushd ${d_}
patch -p1 < ${p_}
popd
p_=$d/patching/130-ozone-skip-did-check.patch
echo "applying patch: under ${d_} for ${p_}"
pushd ${d_}
patch -p1 < ${p_}
popd
p_=$d/patching/150-ozone-plc-fix.patch
echo "applying patch: under ${d_} for ${p_}"
pushd ${d_}
patch -p1 < ${p_}
popd
p_=$d/patching/160-ozone-oauth-redirect-fix.patch
echo "applying patch: under ${d_} for ${p_}"
pushd ${d_}
patch -p1 < ${p_}
popd
p_=$d/patching/121-ozone-constants-fix.patch
echo "applying patch: under ${d_} for ${p_}"
pushd ${d_}
patch -p1 < ${p_} || true
# Replace process.env with env()
sed -i 's/process\.env\.\(NEXT_PUBLIC_[A-Z_]*\)/env('\''\1'\'')/g' lib/constants.ts
sed -i 's/process\.env\.NODE_ENV/env('\''NODE_ENV'\'')/g' lib/constants.ts
# Add missing SOCIAL_APP_DOMAIN constant after SOCIAL_APP_URL
sed -i '/^export const SOCIAL_APP_URL =/,/^$/{ /^$/a\
export const SOCIAL_APP_DOMAIN =\
env('\''NEXT_PUBLIC_SOCIAL_APP_DOMAIN'\'') || '\''bsky.app'\''\
}' lib/constants.ts
# Fix multiline process.env patterns
sed -i '/^export const NEW_ACCOUNT_MARKER_THRESHOLD_IN_DAYS = process\.env$/,/^ : 7$/ {
s/^export const NEW_ACCOUNT_MARKER_THRESHOLD_IN_DAYS = process\.env$/export const NEW_ACCOUNT_MARKER_THRESHOLD_IN_DAYS = env('\''NEXT_PUBLIC_NEW_ACCOUNT_MARKER_THRESHOLD_IN_DAYS'\'')/
/^ \.NEXT_PUBLIC_NEW_ACCOUNT_MARKER_THRESHOLD_IN_DAYS$/d
}' lib/constants.ts
sed -i '/^export const YOUNG_ACCOUNT_MARKER_THRESHOLD_IN_DAYS = process\.env$/,/^ : 30$/ {
s/^export const YOUNG_ACCOUNT_MARKER_THRESHOLD_IN_DAYS = process\.env$/export const YOUNG_ACCOUNT_MARKER_THRESHOLD_IN_DAYS = env('\''NEXT_PUBLIC_YOUNG_ACCOUNT_MARKER_THRESHOLD_IN_DAYS'\'')/
/^ \.NEXT_PUBLIC_YOUNG_ACCOUNT_MARKER_THRESHOLD_IN_DAYS$/d
}' lib/constants.ts
sed -i '/^export const HIGH_PROFILE_FOLLOWER_THRESHOLD = process\.env$/,/^ : Infinity$/ {
s/^export const HIGH_PROFILE_FOLLOWER_THRESHOLD = process\.env$/export const HIGH_PROFILE_FOLLOWER_THRESHOLD = env('\''NEXT_PUBLIC_HIGH_PROFILE_FOLLOWER_THRESHOLD'\'')/
/^ \.NEXT_PUBLIC_HIGH_PROFILE_FOLLOWER_THRESHOLD$/d
}' lib/constants.ts
# Fix parseInt() to handle undefined by adding || ''
sed -i "s/parseInt(env('\([^']*\)'))/parseInt(env('\1') || '0')/g" lib/constants.ts
popd
}
function at-repos-build-docker-atproto() {
cd $d
docker image prune -a
if [ -z "$1" ];then
for ((i=1; i<=${#services}; i++)); do
service=${services[$i]}
docker compose build --no-cache $service
done
else
docker compose build --no-cache $1
fi
}
function at-repos-push-reset() {
if [ -n "$(docker ps -q -f name=registry)" ]; then
echo "Registry is already running."
docker restart registry
docker stop registry
docker rm registry
docker volume rm registry-data 2>/dev/null || true
fi
docker run -d -p ${dport}:${dport} --name registry \
--restart=always \
-v registry-data:/var/lib/registry \
registry:2
}
function at-repos-push-docker() {
if [ -z "$1" ];then
for ((i=1; i<=${#services}; i++)); do
service=${services[$i]}
docker tag at-${service}:latest localhost:${dport}/${service}:latest
docker push localhost:${dport}/${service}:latest
done
else
docker tag at-${1}:latest localhost:${dport}/${1}:latest
docker push localhost:${dport}/${1}:latest
fi
}
function at-repos-pull-docker() {
cd $d
docker image prune -a
docker compose up -d --pull always
}
at-repos-env
case "`cat /etc/hostname`" in
at)
at-repos-pull-docker
exit
;;
*)
if [ "$1" = "r" ];then
at-repos-push-reset
exit
fi
at-repos-clone
at-repos-pull
at-repos-social-app-icon
at-repos-social-app-icon-origin
at-repos-social-app-avatar-write
at-repos-social-app-agent-patch
at-repos-social-app-disable-external-services-patch
at-repos-social-app-statsig-patch
at-repos-social-app-dockerfile-yarn-timeout-patch
at-repos-atproto-service-bsky-api-patch
at-repos-atproto-service-pds-index-patch
at-repos-atproto-oauth-same-site-patch
at-repos-atproto-service-ozone-api-patch
at-repos-ozone-patch
if [ -n "$1" ];then
at-repos-build-docker-atproto $1
at-repos-push-docker $1
exit
fi
at-repos-build-docker-atproto
at-repos-push-docker
cd $d; docker compose down
;;
esac