ai/at
1
0
Clone
22
social-app
syui edited this page 2025-12-09 10:00:11 +00:00
PrivacyPolicy: 'https://syu.is/about/support/privacy-policy',
TermsOfService: 'https://syu.is/about/support/tos',
License: 'https://syu.is/about/support/license',
App: 'https://syu.is/about/support/app',
CommunityGuidelines: '/support/community-guidelines',
CopyrightPolicy: '/support/copyright',

logout状態では/profile/$didを閲覧できない

- ./lib/constants.ts:export const PUBLIC_BSKY_SERVICE = 'https://public.api.bsky.app'
+ ./lib/constants.ts:export const PUBLIC_BSKY_SERVICE = 'https://bsky.syu.is'

social-app(web)のtimelineではavatarが表示されない

基本的にavatarは以下のようなurlを使用し、timelineはavatar_thumbnailを使用します。

1. https://appview.${host}/img/avatar/plain/${did}/${cid}@jpeg
2. https://${host}/xrpc/com.atproto.sync.getBlob?did=${did}&cid=${cid}

例えば、BSKY_IMG_URI_ENDPOINT=https://cdn.bsky.app/imgを使用すると以下のようになります。

https://cdn.bsky.app/img/avatar_thumbnail/plain/${did}/${rkey}@jpeg

ですが、self-hostではBSKY_BLOB_CACHE_LOC=/dataを使用しますので、画像変換が行われず、表示されません。

これは問題でsocial-appを改造してもiosアプリでは表示されないということです。

webは以下の変更を行うと表示されます。

repos/social-app/src/view/com/util/UserAvatar.tsx

// https://raw.githubusercontent.com/bluesky-social/social-app/refs/heads/main/src/view/com/util/UserAvatar.tsx
function hackModifyThumbnailPath(uri: string, isEnabled: boolean): string {
  return isEnabled
//    ? uri.replace('/img/avatar/plain/', '/img/avatar_thumbnail/plain/')
    ? uri.replace('https://cdn.bsky.app/img/avatar/plain/', 'https://bsky.syu.is/img/avatar/plain/')
    : uri
}

source={{ uri: hackModifyThumbnailPath(avatar, 1 > 0), }}

cloudflareで解決する

しかし、上記の方法はwebだけで有効な方法です。iosではまた違った解決が必要になります。

まずprofileを見てください。

host=`cat ~/.config/atproto/token.json|jq -r ".didDoc.service.[].serviceEndpoint"`
token=`cat ~/.config/atproto/token.json|jq -r .accessJwt`
did=`cat ~/.config/atproto/token.json|jq -r .did`
req=/xrpc/app.bsky.actor.getProfile
url="${host}${req}?actor=$did"

curl -sL -X GET -H "Content-Type: application/json" -H "Authorization: Bearer $token" $url|jq .
{
  "did": "did:plc:vzsvtbtbnwn22xjqhcu3vd6y",
  "handle": "syui.syu.is",
  "displayName": "",
  "avatar": "https://bsky.syu.is/img/avatar/plain/did:plc:vzsvtbtbnwn22xjqhcu3vd6y/bafkreibj33gomcziy3rxx7hdnqlnpgjk4rwo3i564ooooooodsakrk6o7e@jpeg",
  "associated": {
    "lists": 0,
    "feedgens": 0,
    "starterPacks": 0,
    "labeler": false,
    "chat": {
      "allowIncoming": "following"
    }
  },
  "labels": [],
  "createdAt": "2024-08-11T14:04:57.419Z",
  "indexedAt": "2024-08-11T14:04:57.419Z",
  "followersCount": 1,
  "followsCount": 2,
  "postsCount": 51
}

上の例でいうとavatar_thumbnailをつけたlinkが有効でないとmin画像が表示されない。

+ https://bsky.syu.is/img/avatar/plain/did:plc:vzsvtbtbnwn22xjqhcu3vd6y/bafkreibj33gomcziy3rxx7hdnqlnpgjk4rwo3i564ooooooodsakrk6o7e@jpeg
- https://bsky.syu.is/img/avatar_thumbnail/plain/did:plc:vzsvtbtbnwn22xjqhcu3vd6y/bafkreibj33gomcziy3rxx7hdnqlnpgjk4rwo3i564ooooooodsakrk6o7e@jpeg

BSKY_IMG_URI_ENDPOINT - (recommended) the base url for resized images, e.g. https://cdn.bsky.app/img. When not set, sets-up an image resizing service directly on the appview.

BSKY_BLOB_CACHE_LOC - when BSKY_IMG_URI_ENDPOINT is not set, this determines where resized blobs are cached by the image resizing service.

基本的にBSKY_IMG_URI_ENDPOINTをコメントして、BSKY_BLOB_CACHE_LOCを設定します。すると、volumeに設定した場所、例えば、/data/bsky以下にこのようなファイルが作られます。

+ did:plc:vzsvtbtbnwn22xjqhcu3vd6y::bafkreibj33gomcziy3rxx7hdnqlnpgjk4rwo3i564ooooooodsakrk6o7e::avatar
+ did:plc:vzsvtbtbnwn22xjqhcu3vd6y::bafkreibj33gomcziy3rxx7hdnqlnpgjk4rwo3i564ooooooodsakrk6o7e::avatar_thumbnail

ファイルは作られているのですが、avatar_thumbnailにはなぜかアクセスできません。

そこで、cloudflareでurlの書き換えルールを設定します。これでiosから閲覧できるようになりました。

  1. rule(ルール) -> urlの書き換え
  2. req(リクエスト): https://bsky.syu.is/img/avatar_thumbnail/*
  3. path(パス): /img/avatar_thumbnail/* -> /img/avatar/${1}

script

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-write() {
	did_admin=did:plc:z72i7hdynmk6r22z27h6tvur

	dt=$d/repos/social-app/src
	cd $dt

	t=(bsky.social bsky.app)
	for tt in "${t[@]}"; do
		escaped_tt=$(echo "$tt" | sed 's/\./\\./g')
		grep -R "$escaped_tt" . | cut -d : -f 1 | sort -u | xargs -r sed -i "s/${tt}/${pds}/g"
	done

	t=(api public.api public.api.bsky public.bsky)
	for tt in "${t[@]}"; do
		grep -R "${tt}\.${pds}" . | cut -d : -f 1 | sort -u | xargs -r sed -i "s/${tt}\.${pds}/bsky.${pds}/g"
	done

	t=(cardyb events status)
	for tt in "${t[@]}"; do
		grep -R "${tt}\.${pds}" . | cut -d : -f 1 | sort -u | xargs -r sed -i "s/${tt}\.${pds}/${tt}.bsky.app/g"
	done

	f=$dt/lib/strings/url-helpers.ts
	sed -i 's#`https://go\.syu\.is/redirect\?u=\${encodeURIComponent(url)}`#url#g' $f

	#f=$dt/state/geolocation.tsx
	#sed -i 's#https://syu\.is/ipcc#https://bsky\.app/ipcc#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://bsky.${pds}/img/avatar/plain/#g" $f
	sed -i "s#/img/avatar_thumbnail/plain/#https://bsky.${pds}/img/avatar/plain/#g" $f
	sed -i "s#source={{uri: avatar}}#source={{ uri: hackModifyThumbnailPath(avatar, 1 > 0), }}#g" $f
	grep -R $did_admin .|cut -d : -f 1|sort -u|xargs sed -i "s/${did_admin}/${did}/g"
}

ipcc

自前のサービスにするか、あるいは、dockerで建てるかです。

// Cloudflare Workerのコード
export default {
  async fetch(request) {
    // IPアドレスから国を取得
    const country = request.cf?.country || 'JP';
    
    return new Response(JSON.stringify({ countryCode: country }), {
      status: 200,
      headers: {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'GET',
      },
    });
  },
};

dokcerの方法は以下。

./configs/ipcc/default.conf

server {
  location / {
    add_header Content-Type application/json;
    add_header Access-Control-Allow-Origin *;
    return 200 '{"countryCode":"JP"}';
  }
}

compose.yml

  ipcc:
    image: nginx:alpine
    restart: always
    volumes:
      - ./configs/ipcc/default.conf:/etc/nginx/conf.d/default.conf
    ports:
      - "8099:80"

web clientのloginが動作しない

  • 8980: social-app BLUESKY_PROXY_HEADER patch (2025-12-03)

https://github.com/bluesky-social/social-app/pull/8980

diff --git a/src/state/session/agent.ts b/src/state/session/agent.ts
index 36d19299b..ba095436a 100644
--- a/src/state/session/agent.ts
+++ b/src/state/session/agent.ts
@@ -39,7 +39,8 @@ export function createPublicAgent() {
   configureModerationForGuest() // Side effect but only relevant for tests
 
   const agent = new BskyAppAgent({service: PUBLIC_BSKY_SERVICE})
-  agent.configureProxy(BLUESKY_PROXY_HEADER.get())
+  // Disable proxy for self-hosted environments
+  // agent.configureProxy(BLUESKY_PROXY_HEADER.get())
   return agent
 }
 
@@ -77,7 +78,8 @@ export async function createAgentAndResume(
     }
   }
 
-  agent.configureProxy(BLUESKY_PROXY_HEADER.get())
+  // Disable proxy for self-hosted environments
+  // agent.configureProxy(BLUESKY_PROXY_HEADER.get())
 
   return agent.prepare(gates, moderation, onSessionChange)
 }
@@ -112,7 +114,8 @@ export async function createAgentAndLogin(
   const gates = tryFetchGates(account.did, 'prefer-fresh-gates')
   const moderation = configureModerationForAccount(agent, account)
 
-  agent.configureProxy(BLUESKY_PROXY_HEADER.get())
+  // Disable proxy for self-hosted environments
+  // agent.configureProxy(BLUESKY_PROXY_HEADER.get())
 
   return agent.prepare(gates, moderation, onSessionChange)
 }
@@ -201,7 +204,8 @@ export async function createAgentAndCreateAccount(
     logger.error(e, {message: `session: failed snoozeEmailConfirmationPrompt`})
   }
 
-  agent.configureProxy(BLUESKY_PROXY_HEADER.get())
+  // Disable proxy for self-hosted environments
+  // agent.configureProxy(BLUESKY_PROXY_HEADER.get())
 
   return agent.prepare(gates, moderation, onSessionChange)
 }

favicon

./src/bskyweb/static/, ./assets/app-iconsにあります。

# Copy new files that aren't in patches
function ios-copy-new-files() {
	echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
	echo "📁 Copying new files..."

	# Copy all assets from ios/assets/ to repos/social-app/assets/
	if [ -d "$d/ios/assets" ]; then
		cp -rf "$d/ios/assets/"* "$target_dir/assets/"
		echo "✅ Copied all assets (including logo.png, app-icons)"
	fi

	# Copy License.tsx
	if [ -f "$patching_dir/License.tsx" ]; then
		mkdir -p "$target_dir/src/view/screens"
		cp "$patching_dir/License.tsx" "$target_dir/src/view/screens/License.tsx"
		echo "✅ Copied License.tsx"
	fi

	# Copy pre-generated favicons for bskyweb
	local favicon_src="$d/ios/assets/favicons"
	local bskyweb_static="$target_dir/bskyweb/static"
	if [ -d "$favicon_src" ] && [ -d "$bskyweb_static" ]; then
		cp -f "$favicon_src/favicon.png" "$bskyweb_static/favicon.png"
		cp -f "$favicon_src/favicon-16x16.png" "$bskyweb_static/favicon-16x16.png"
		cp -f "$favicon_src/favicon-32x32.png" "$bskyweb_static/favicon-32x32.png"
		cp -f "$favicon_src/apple-touch-icon.png" "$bskyweb_static/apple-touch-icon.png"
		echo "✅ Copied favicons to bskyweb/static"
	fi

	echo ""
}