598 lines
24 KiB
Markdown
598 lines
24 KiB
Markdown
+++
|
|
date = "2024-01-08"
|
|
tags = ["bluesky","pds"]
|
|
title = "blueskyをself-hostする"
|
|
slug = "bluesky"
|
|
+++
|
|
|
|
少し前にblueskyをself-host(セルフホスト)しました。
|
|
|
|
![](https://raw.githubusercontent.com/syui/img/master/other/bluesky_atproto_self_hosting_20240108_0001.png)
|
|
|
|
- https://web.syu.is
|
|
|
|
|server|url|src|
|
|
|---|---|---|
|
|
|pds|https://syu.is|[src](https://github.com/bluesky-social/atproto/tree/main/services/pds)|
|
|
|plc|https://plc.syu.is|[src](https://github.com/did-method-plc/did-method-plc/tree/main/packages/server)|
|
|
|mod|https://mod.syu.is|[src](https://github.com/bluesky-social/atproto/tree/main/services/ozone)|
|
|
|bgs|https://bgs.syu.is|[src](https://github.com/bluesky-social/indigo/tree/main/cmd/bigsky)|
|
|
|appview|https://api.syu.is|[src](https://github.com/bluesky-social/atproto/tree/main/services/bsky)|
|
|
|web|https://web.syu.is|[src](https://github.com/bluesky-social/social-app)|
|
|
|
|
以前はbluesky(pds+appview)を動かしていたのですが、一般的にblueskyと呼ばれるものは複数のserverに依存しています。例えば、plc, bgsです。今ではpdsにあったappviewも分離しています。
|
|
|
|
bsky.teamがそれぞれのsandboxを用意してくれていますが、全部をself-hostしないといつか動かなくなります。
|
|
|
|
|server|env|body|
|
|
|---|---|---|
|
|
|pds|PDS_DID_PLC_URL|`https://plc.${host}`|
|
|
|pds|PDS_BSKY_APP_VIEW_URL|`https://api.${host}`|
|
|
|pds|PDS_BSKY_APP_VIEW_DID|did:web:api.${host}|
|
|
|pds|PDS_MOD_SERVICE_URL|`https://mod.${host}`|
|
|
|pds|PDS_MOD_SERVICE_DID|did:web:mod.${host}|
|
|
|pds|PDS_CRAWLERS|`https://bgs.${host}`|
|
|
|
|
nostrで活動されているikuradonさんが全部のserverをセルフホストしているのを見て、どうやら他のserverも動作できる環境にあるようだと思ったので立ててみました。なお、ikuradonさんに結構助けてもらった。
|
|
|
|
今回、`syu.is`というdomainを取りました。なお、`.is`はあまりおすすめしません。これはアイスランドが独自方針で管理している感じで、メール認証などが必要です。その他、様々な制限があります。
|
|
|
|
|
|
```sh
|
|
git clone https://github.com/bluesky-social/atproto
|
|
cd atproto
|
|
git clone https://github.com/did-method-plc/did-method-plc ./repos/did-method-plc
|
|
git clone https://github.com/bluesky-social/indigo ./repos/indigo
|
|
git clone https://github.com/bluesky-social/social-app ./repos/social-app
|
|
touch .plc.env .bsky.env .bgs.env .pds.env .db.env .mod.env .web.env
|
|
```
|
|
|
|
```sh
|
|
mkdir -p ./postgres/init
|
|
echo '-- plc
|
|
CREATE DATABASE plc;
|
|
GRANT ALL PRIVILEGES ON DATABASE plc TO postgres;
|
|
|
|
-- bgs
|
|
CREATE DATABASE bgs;
|
|
CREATE DATABASE carstore;
|
|
GRANT ALL PRIVILEGES ON DATABASE bgs TO postgres;
|
|
GRANT ALL PRIVILEGES ON DATABASE carstore TO postgres;
|
|
|
|
-- bsky(appview)
|
|
CREATE DATABASE bsky;
|
|
GRANT ALL PRIVILEGES ON DATABASE bsky TO postgres;
|
|
|
|
-- ozone(moderation)
|
|
CREATE DATABASE mod;
|
|
GRANT ALL PRIVILEGES ON DATABASE mod TO postgres;
|
|
|
|
-- pds
|
|
CREATE DATABASE pds;
|
|
GRANT ALL PRIVILEGES ON DATABASE pds TO postgres;
|
|
' >> ./postgres/init/init.sql
|
|
```
|
|
|
|
### compose.yaml
|
|
|
|
docker composeで構築しました。大体は以下のような感じの構成です。
|
|
|
|
下記は最小構成なので、自分なりに読み替えてください。
|
|
|
|
```yml:compose.yaml
|
|
services:
|
|
plc:
|
|
ports:
|
|
- 2582:3000
|
|
build:
|
|
context: ./repos/did-method-plc/
|
|
dockerfile: packages/server/Dockerfile
|
|
env_file:
|
|
- ./.plc.env
|
|
depends_on:
|
|
- db
|
|
|
|
bgs:
|
|
ports:
|
|
- 2470:2470
|
|
build:
|
|
context: ./repos/indigo/
|
|
dockerfile: cmd/bigsky/Dockerfile
|
|
env_file:
|
|
- ./.bgs.env
|
|
volumes:
|
|
- ./data/bgs/:/data/
|
|
depends_on:
|
|
- db
|
|
|
|
bsky:
|
|
ports:
|
|
- 2584:3000
|
|
build:
|
|
context: ./
|
|
dockerfile: services/bsky/Dockerfile
|
|
env_file:
|
|
- ./.bsky.env
|
|
depends_on:
|
|
- db
|
|
- redis
|
|
|
|
bsky-daemon:
|
|
build:
|
|
context: ./
|
|
dockerfile: services/bsky/Dockerfile
|
|
command: node --enable-source-maps daemon.js
|
|
env_file:
|
|
- ./.bsky.env
|
|
depends_on:
|
|
- bsky
|
|
- db
|
|
- redis
|
|
|
|
bsky-indexer:
|
|
build:
|
|
context: ./
|
|
dockerfile: services/bsky/Dockerfile
|
|
command: node --enable-source-maps indexer.js
|
|
env_file:
|
|
- ./.bsky.env
|
|
volumes:
|
|
- ./data/bsky/cache/:/cache/
|
|
depends_on:
|
|
- bsky
|
|
- db
|
|
- redis
|
|
|
|
bsky-ingester:
|
|
build:
|
|
context: ./
|
|
dockerfile: services/bsky/Dockerfile
|
|
command: node --enable-source-maps ingester.js
|
|
env_file:
|
|
- ./.bsky.env
|
|
volumes:
|
|
- ./data/bsky/cache/:/cache/
|
|
depends_on:
|
|
- bsky
|
|
- db
|
|
- redis
|
|
|
|
mod:
|
|
ports:
|
|
- 2585:3000
|
|
build:
|
|
context: ./
|
|
dockerfile: services/ozone/Dockerfile
|
|
env_file:
|
|
- ./.mod.env
|
|
depends_on:
|
|
- db
|
|
|
|
mod-daemon:
|
|
build:
|
|
context: ./
|
|
dockerfile: services/ozone/Dockerfile
|
|
command: node --enable-source-maps daemon.js
|
|
env_file:
|
|
- ./.mod.env
|
|
depends_on:
|
|
- mod
|
|
- db
|
|
|
|
pds:
|
|
ports:
|
|
- 2583:3000
|
|
build:
|
|
context: ./
|
|
dockerfile: services/pds/Dockerfile
|
|
env_file:
|
|
- ./.pds.env
|
|
volumes:
|
|
- ./data/pds/:/data/
|
|
depends_on:
|
|
- db
|
|
|
|
social-app:
|
|
ports:
|
|
- 8100:8100
|
|
build:
|
|
context: ./repos/social-app/
|
|
dockerfile: Dockerfile
|
|
env_file:
|
|
- ./.web.env
|
|
command: "/usr/bin/bskyweb serve"
|
|
|
|
db:
|
|
image: postgres:latest
|
|
env_file:
|
|
- ./.db.env
|
|
volumes:
|
|
- ./postgres/init/:/docker-entrypoint-initdb.d/
|
|
- ./data/db/:/var/lib/postgresql/data/
|
|
|
|
redis:
|
|
image: redis
|
|
volumes:
|
|
- ./data/redis/:/data/
|
|
```
|
|
|
|
### hint
|
|
|
|
必要に応じて、以下の設定などを使用するとよいでしょう。
|
|
|
|
```yaml:compose.yaml
|
|
services:
|
|
plc:
|
|
depends_on:
|
|
db:
|
|
# 依存先のサービスが起動したら起動する
|
|
condition: service_started
|
|
```
|
|
|
|
```yaml:compose.yaml
|
|
services:
|
|
plc:
|
|
depends_on:
|
|
db:
|
|
# 依存先のサービスが起動して、なおかつ、 healthcheck が通ったら起動する
|
|
condition: service_healthy
|
|
|
|
db:
|
|
healthcheck:
|
|
# https://docs.docker.jp/compose/compose-file/compose-file-v3.html
|
|
test: ["CMD-SHELL", "pg_isready"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
```
|
|
|
|
```yaml:compose.yaml
|
|
services:
|
|
plc:
|
|
# https://docs.docker.jp/v19.03/config/container/start-containers-automatically.html
|
|
# コンテナが停止すると常に再起動します
|
|
restart: always
|
|
```
|
|
|
|
|
|
```yaml:compose.yaml
|
|
services:
|
|
db:
|
|
# https://hub.docker.com/_/postgres
|
|
# postgresのversionを固定
|
|
image: postgres:16
|
|
```
|
|
|
|
```yaml:compose.yaml
|
|
services:
|
|
db:
|
|
# localhostからのアクセスを可能にする
|
|
# postgresql://postgres:postgres@127.0.0.1:5432
|
|
ports:
|
|
- 5432:5432
|
|
```
|
|
|
|
```yaml:compose.yaml
|
|
services:
|
|
db:
|
|
# postgresql://user:password@127.0.0.1/test
|
|
environment:
|
|
POSTGRES_USER: user
|
|
POSTGRES_DB: test
|
|
POSTGRES_PASSWORD: password
|
|
```
|
|
|
|
### env
|
|
|
|
dbのurlになります。全部別々の`.env`に書いてください。
|
|
|
|
```sh:.*.env
|
|
# pds
|
|
PDS_DB_POSTGRES_URL=postgresql://postgres:postgres@db/pds
|
|
|
|
# bsky(appview)
|
|
DB_PRIMARY_POSTGRES_URL=postgres://postgres:postgres@db/bsky
|
|
DB_REPLICA_POSTGRES_URLS=postgres://postgres:postgres@db/bsky
|
|
|
|
# bgs
|
|
DATABASE_URL=postgres://postgres:postgres@db/bgs
|
|
CARSTORE_DATABASE_URL=postgres://postgres:postgres@db/carstore
|
|
|
|
# mod
|
|
OZONE_DB_POSTGRES_URL=postgres://postgres:postgres@db/mod
|
|
|
|
# plc
|
|
DATABASE_URL=postgres://postgres:postgres@db/plc
|
|
|
|
# email
|
|
PDS_EMAIL_SMTP_URL=smtps://$username:$password@smtp.gmail.com
|
|
```
|
|
|
|
環境変数をまとめます。
|
|
|
|
|server|env|body|
|
|
|---|---|---|
|
|
|bsky|DB_PRIMARY_POSTGRES_URL|postgres://postgres:postgres@db/bsky|
|
|
|bsky|DB_REPLICA_POSTGRES_URLS|postgres://postgres:postgres@db/bsky|
|
|
|bsky|DB_REPLICA_TAGS_ANY|0|
|
|
|bsky|PUBLIC_URL|`https://api.${host}`|
|
|
|bsky|SERVER_DID|did:web:api.${host}|
|
|
|bsky|DID_PLC_URL|`https://plc.${host}`|
|
|
|bsky|BLOB_CACHE_LOC|/cache/|
|
|
|bsky|SEARCH_ENDPOINT|`https://search.${host}`|
|
|
|bsky|REDIS_HOST|redis|
|
|
|bsky|INDEXER_PARTITION_IDS|0|
|
|
|bsky|INGESTER_PARTITION_COUNT|1|
|
|
|bsky|PUSH_NOTIFICATION_ENDPOINT|`https://push.bsky.${host}/api/push`|
|
|
|bsky|REPO_PROVIDER|wss://${host}|
|
|
|bsky|IMG_URI_ENDPOINT|`https://cdn.${host}/img`|
|
|
|bsky|ODERATION_SERVICE_DID|did:web:mod.${host}|
|
|
|bsky|MODERATION_PUSH_URL|`https://admin:${OZONE_ADMIN_PASSWORD}@mod.${host}`|
|
|
|bsky|ADMIN_PASSWORD|xxx|
|
|
|bsky|MODERATOR_PASSWORD|xxx|
|
|
|bsky|TRIAGE_PASSWORD|xxx|
|
|
|bsky|SERVICE_SIGNING_KEY|$ openssl ecparam --name secp256k1 --genkey ...|
|
|
|bsky|IMG_URI_SALT|xxx|
|
|
|bsky|IMG_URI_KEY|xxx|
|
|
|
|
|server|env|body|
|
|
|---|---|---|
|
|
|bgs|DATABASE_URL|postgres://postgres:postgres@db/bgs|
|
|
|bgs|CARSTORE_DATABASE_URL|postgres://postgres:postgres@db/carstore|
|
|
|bgs|DATA_DIR|/data|
|
|
|bgs|ATP_PLC_HOST|`https://plc.${host}`|
|
|
|bgs|BGS_ADMIN_KEY|xxx|
|
|
|
|
|server|env|body|
|
|
|---|---|---|
|
|
|mod|OZONE_PUBLIC_URL|`https://mod.${host}`|
|
|
|mod|OZONE_SERVER_DID|did:web:mod.${host}|
|
|
|mod|OZONE_APPVIEW_URL|`https://api.${host}`|
|
|
|mod|OZONE_APPVIEW_DID|did:web:api.${host}|
|
|
|mod|OZONE_PDS_URL|`https://${host}`|
|
|
|mod|OZONE_PDS_DID|did:web:${host}|
|
|
|mod|OZONE_DB_POSTGRES_URL|postgres://postgres:postgres@db/mod|
|
|
|mod|OZONE_DID_PLC_URL|`https://plc.${host}`|
|
|
|mod|MODERATION_PUSH_URL|`https://admin:${OZONE_ADMIN_PASSWORD}@mod.${host}`|
|
|
|mod|OZONE_ADMIN_PASSWORD|xxx|
|
|
|mod|OZONE_MODERATOR_PASSWORD|xxx|
|
|
|mod|OZONE_TRIAGE_PASSWORD|xxx|
|
|
|mod|OZONE_SIGNING_KEY_HEX|xxx|
|
|
|
|
|server|env|body|
|
|
|---|---|---|
|
|
|pds|PDS_HOSTNAME|${host}|
|
|
|pds|PDS_DATA_DIRECTORY|/data|
|
|
|pds|PDS_DB_POSTGRES_URL|postgresql://postgres:postgres@db/pds|
|
|
|pds|PDS_DID_PLC_URL|`https://plc.${host}`|
|
|
|pds|PDS_BSKY_APP_VIEW_URL|`https://api.${host}`|
|
|
|pds|PDS_BSKY_APP_VIEW_DID|did:web:api.${host}|
|
|
|pds|PDS_MOD_SERVICE_URL|`https://mod.${host}`|
|
|
|pds|PDS_MOD_SERVICE_DID|did:web:mod.${host}|
|
|
|pds|PDS_CRAWLERS|`https://bgs.${host}`|
|
|
|pds|PDS_EMAIL_SMTP_URL|smtps://$username:$password@smtp.gmail.com|
|
|
|pds|PDS_EMAIL_FROM_ADDRESS|no-reply@${host}|
|
|
|pds|PDS_INVITE_REQUIRED (招待コード)|false|
|
|
|pds|PDS_INVITE_INTERVAL|604800000|
|
|
|pds|PDS_BLOBSTORE_DISK_LOCATION|/data/img/static|
|
|
|pds|PDS_BLOBSTORE_DISK_TMP_LOCATION|/data/img/tmp|
|
|
|pds|PDS_JWT_SECRET|`$ openssl rand --hex 16`|
|
|
|pds|PDS_ADMIN_PASSWORD|xxx|
|
|
|pds|PDS_REPO_SIGNING_KEY_K256_PRIVATE_KEY_HEX|xxx|
|
|
|pds|PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX|xxx|
|
|
|
|
|server|env|body|
|
|
|---|---|---|
|
|
|plc|DATABASE_URL|postgres://postgres:postgres@db/plc|
|
|
|plc|DB_CREDS_JSON|'{"username":"postgres","password":"postgres","host":"db","port":"5432","database":"plc"}'|
|
|
|plc|ENABLE_MIGRATIONS|true|
|
|
|plc|DB_MIGRATE_CREDS_JSON|'{"username":"postgres","password":"postgres","host":"db","port":"5432","database":"plc"}'|
|
|
|
|
`xxx`は以下のコマンドなどで作成してもいいと思います。
|
|
|
|
```sh
|
|
$ openssl ecparam --name secp256k1 --genkey --noout --outform DER | tail --bytes=+8 | head --bytes=32 | xxd --plain --cols 32
|
|
```
|
|
|
|
### SERVER_DID / SERVICE_SIGNING_KEY
|
|
|
|
> `SERVICE_SIGNING_KEY`に入れる値は`SERVER_DID=did:web:xxx`の場合、ローカル環境で生成したもので構いません。しかし、`SERVER_DID=did:plc:xxx`を使用する場合はplcからkeyを登録します。
|
|
|
|
```sh
|
|
$ openssl ecparam --name secp256k1 --genkey --noout --outform DER | tail --bytes=+8 | head --bytes=32 | xxd --plain --cols 32
|
|
|
|
SERVICE_SIGNING_KEY=xxx
|
|
```
|
|
|
|
以下は現時点では必要ありません。
|
|
|
|
bsky(appview)の`SERVER_DID`は`did:web:xxx`という形式と`did:plc:xxx`という形式を使えます。後者はplcに登録して使うものと思われ、連合が開始する際に重要になるかもしれません。
|
|
|
|
`SERVICE_SIGNING_KEY`は`SERVER_DID`を取得したときのsign-keyだと思われます。
|
|
|
|
これはatprotoの`dev-env`でexampleが書かれています。
|
|
|
|
```ts:atproto/packages/dev-env/src/bsky.ts
|
|
static async create(cfg: BskyConfig): Promise<TestBsky> {
|
|
// packages/crypto/tests/keypairs.test.ts
|
|
const serviceKeypair = await Secp256k1Keypair.create({ exportable: true })
|
|
console.log(`ROTATION_KEY=${serviceKeypair.did()}`)
|
|
const exported = await serviceKeypair.export()
|
|
const plcClient = new PlcClient(cfg.plcUrl)
|
|
|
|
const port = cfg.port || (await getPort())
|
|
const url = `http://localhost:${port}`
|
|
const serverDid = await plcClient.createDid({
|
|
signingKey: serviceKeypair.did(),
|
|
rotationKeys: [serviceKeypair.did()],
|
|
handle: 'bsky.test',
|
|
pds: `http://localhost:${port}`,
|
|
signer: serviceKeypair,
|
|
})
|
|
console.log(`SERVER_DID=${serverDid}`)
|
|
|
|
const server = bsky.BskyAppView.create({
|
|
db,
|
|
redis: redisCache,
|
|
config,
|
|
algos: cfg.algos,
|
|
imgInvalidator: cfg.imgInvalidator,
|
|
signingKey: serviceKeypair,
|
|
})
|
|
```
|
|
|
|
```sh
|
|
$ make deps
|
|
$ make build
|
|
$ make test
|
|
|
|
$ make run-dev-env
|
|
```
|
|
|
|
appviewをcreateする際の`signingKey: serviceKeypair`の部分を見てください。objを使用しています。
|
|
|
|
つまり、signingKeyに`obj`を入れると動きますが、`services/bsky/api.ts`では以下のような処理がなされます。
|
|
|
|
```ts:atproto/services/bsky/api.js
|
|
const signingKey = await Secp256k1Keypair.import(env.serviceSigningKey)
|
|
```
|
|
|
|
didを作成したときに`Secp256k1Keypair`でimportできる値を`SERVICE_SIGNING_KEY`に入れてください。
|
|
|
|
あるいはコードを書き換えてobjをいれるのでもいけますが、現実的ではありません。
|
|
|
|
```ts:atproto/services/bsky/api.js
|
|
// const signingKey = await Secp256k1Keypair.import(env.serviceSigningKey)
|
|
const signingKey = process.env.SERVICE_SIGNING_OBJ
|
|
```
|
|
|
|
```ts:atproto/packages/crypto/tests/keypairs.test.ts
|
|
keypair = await Secp256k1Keypair.create({ exportable: true })
|
|
const exported = await keypair.export()
|
|
imported = await Secp256k1Keypair.import(exported, { exportable: true })
|
|
|
|
expect(keypair.did()).toBe(imported.did())
|
|
```
|
|
|
|
plcへの登録は以下のコマンドだと思われます。
|
|
|
|
```sh
|
|
# https://web.plc.directory/api/redoc#operation/ResolveDid
|
|
$ url=https://plc.$host/did:plc:pyc2ihzpelxtg4cdkfzbhcv4
|
|
$ json='{ "type": "create", "signingKey": "did:key:zQ3shP5TBe1sQfSttXty15FAEHV1DZgcxRZNxvEWnPfLFwLxJ", "recoveryKey": "did:key:zQ3shhCGUqDKjStzuDxPkTxN6ujddP4RkEKJJouJGRRkaLGbg", "handle": "first-post.bsky.social", "service": "https://bsky.social", "prev": null, "sig": "yvN4nQYWTZTDl9nKSSyC5EC3nsF5g4S56OmRg9G6_-pM6FCItV2U2u14riiMGyHiCD86l6O-1xC5MPwf8vVsRw" }'
|
|
|
|
$ curl -X POST -H "Content-Type: application/json" -d "$json" $url | jq .
|
|
```
|
|
|
|
### invite-code
|
|
|
|
```sh
|
|
$ host=example.com
|
|
$ admin_password="admin-pass"
|
|
$ url=https://$host/xrpc/com.atproto.server.createInviteCode
|
|
$ json="{\"useCount\":1}"
|
|
|
|
$ curl -X POST -u admin:${admin_password} -H "Content-Type: application/json" -d "$json" -sL $url | jq .
|
|
```
|
|
|
|
### social-app
|
|
|
|
svgを作りました。
|
|
|
|
<svg viewBox="0 0 2821.6379 794.29016" preserveAspectRatio="xMidYMid" xmlns:svg="http://www.w3.org/2000/svg"> <g transform="matrix(0.1,0,0,-0.1,-282.80153,1445)" fill="#000000" stroke="none" > <path d="m 24787,14443 c -4,-3 -7,-224 -7,-490 v -483 h 545 545 v 490 490 h -538 c -296,0 -542,-3 -545,-7 z" /> <path d="m 5190,13285 c -8,-3 -96,-12 -195,-20 -199,-16 -296,-32 -430,-70 -49,-14 -115,-32 -145,-40 -153,-39 -504,-198 -662,-301 -21,-13 -57,-36 -80,-51 -24,-16 -72,-50 -109,-78 -241,-182 -377,-315 -528,-517 -119,-158 -120,-160 -106,-188 23,-45 140,-140 560,-457 110,-84 319,-242 465,-353 146,-110 369,-279 495,-375 791,-600 723,-549 1049,-799 269,-207 398,-307 524,-403 l 114,-86 -49,-49 c -128,-131 -378,-258 -588,-299 -66,-13 -357,-13 -420,0 -115,23 -172,39 -202,54 -18,10 -37,17 -43,17 -24,0 -171,81 -255,141 -50,35 -146,121 -215,192 -69,70 -133,127 -142,127 -19,0 -153,-63 -177,-83 -9,-7 -54,-35 -101,-62 -47,-26 -110,-64 -140,-85 -30,-20 -97,-61 -148,-91 -51,-30 -107,-62 -124,-72 -18,-10 -57,-38 -87,-61 -70,-53 -252,-168 -446,-281 -82,-49 -158,-95 -168,-104 -16,-16 -14,-21 34,-106 165,-289 544,-666 867,-860 9,-6 35,-22 58,-37 36,-23 267,-138 349,-173 108,-47 160,-67 240,-93 150,-48 201,-62 228,-62 14,0 64,-9 109,-19 197,-46 302,-56 573,-56 197,1 281,5 345,17 47,9 110,19 141,22 31,3 75,13 99,21 23,8 56,15 72,15 17,0 51,7 77,15 25,8 80,24 121,36 41,12 125,41 185,66 61,25 124,50 140,56 17,7 89,42 160,78 113,58 177,98 395,246 82,56 273,232 403,371 127,136 237,271 237,291 0,12 -208,179 -425,342 -186,140 -1121,843 -1720,1294 -264,199 -589,444 -723,546 -134,101 -274,208 -312,237 -39,29 -70,58 -70,66 0,21 107,115 203,179 95,64 237,133 295,143 20,4 49,12 63,20 96,48 519,48 619,-1 14,-7 41,-16 60,-20 65,-13 262,-118 360,-191 99,-74 250,-230 372,-384 34,-44 70,-80 80,-80 9,0 39,15 67,33 28,17 70,44 94,58 23,15 121,76 217,136 96,60 254,156 350,213 96,56 272,160 390,230 118,70 230,135 248,144 41,21 41,45 -3,116 -18,30 -46,75 -61,100 -64,106 -252,348 -352,454 -106,112 -169,171 -293,274 -197,164 -310,235 -594,376 -215,106 -519,205 -735,240 -137,22 -574,51 -610,41 z" /> <path d="m 29095,12736 c -421,-44 -744,-157 -975,-342 -259,-207 -396,-446 -465,-809 -16,-84 -23,-301 -14,-425 36,-518 257,-859 694,-1070 166,-80 284,-116 716,-215 449,-103 514,-121 646,-186 218,-107 308,-253 306,-494 -2,-303 -188,-477 -588,-551 -140,-26 -640,-27 -825,-1 -275,38 -486,94 -776,203 -94,35 -174,64 -178,64 -3,0 -6,-175 -6,-389 v -388 l 88,-41 c 404,-187 905,-282 1486,-282 675,0 1154,150 1465,459 196,194 311,434 362,756 20,121 17,476 -5,600 -89,517 -358,800 -945,994 -130,43 -241,71 -616,156 -137,31 -299,73 -360,92 -331,106 -455,246 -455,511 1,249 127,412 387,501 272,92 801,76 1269,-39 116,-28 326,-96 432,-138 l 52,-22 -2,406 -3,406 -66,28 c -154,66 -413,140 -604,174 -279,49 -756,69 -1020,42 z" /> <path d="m 9630,12676 c 0,-2 403,-996 896,-2208 493,-1211 898,-2211 901,-2220 6,-21 -135,-386 -193,-499 -104,-202 -256,-324 -471,-380 -118,-30 -340,-43 -516,-29 -84,6 -185,17 -225,24 -40,7 -75,10 -77,7 -3,-2 -5,-163 -5,-357 v -353 l 63,-30 c 194,-93 493,-138 801,-120 414,23 683,115 937,319 174,140 357,402 474,680 26,62 1945,5159 1945,5167 0,2 -232,2 -516,1 l -517,-3 -556,-1550 c -485,-1350 -560,-1550 -578,-1553 -18,-3 -26,11 -62,105 -23,59 -295,758 -605,1553 l -562,1445 -567,3 c -312,1 -567,0 -567,-2 z" /> <path d="m 15690,10867 c 0,-1970 -1,-1936 56,-2153 128,-497 461,-787 1014,-885 147,-26 440,-36 605,-20 413,40 834,200 1181,447 35,25 73,44 88,44 14,0 26,-1 26,-3 0,-2 20,-94 45,-205 25,-111 45,-204 45,-207 0,-3 209,-5 465,-5 h 465 v 2400 2400 h -535 -535 l -2,-1866 -3,-1866 -115,-50 c -425,-185 -743,-252 -1088,-227 -302,21 -472,109 -562,293 -79,161 -74,11 -77,1969 l -3,1747 h -535 -535 z" /> <path d="m 24785,12668 c -3,-7 -4,-1086 -3,-2398 l 3,-2385 538,-3 537,-2 v 2400 2400 h -535 c -419,0 -537,-3 -540,-12 z" /> <path d="m 21660,8275 v -545 h 565 565 v 545 545 h -565 -565 z" /> </g> </svg>
|
|
|
|
```ts:social-app/src/view/icons/Logotype.tsx
|
|
import React from 'react'
|
|
import Svg, {Path, SvgProps, PathProps} from 'react-native-svg'
|
|
|
|
import {usePalette} from '#/lib/hooks/usePalette'
|
|
|
|
const ratio = 17 / 64
|
|
|
|
export function Logotype({
|
|
fill,
|
|
...rest
|
|
}: {fill?: PathProps['fill']} & SvgProps) {
|
|
const pal = usePalette('default')
|
|
// @ts-ignore it's fiiiiine
|
|
const size = parseInt(rest.width || 32)
|
|
|
|
return (
|
|
<Svg
|
|
fill="none"
|
|
viewBox="0 0 2821.6379 794.29016"
|
|
{...rest}
|
|
width={size}
|
|
height={Number(size) * ratio}>
|
|
<g
|
|
transform="matrix(0.1,0,0,-0.1,-282.80153,1445)"
|
|
fill="#000000"
|
|
stroke="none"
|
|
>
|
|
<path
|
|
d="m 24787,14443 c -4,-3 -7,-224 -7,-490 v -483 h 545 545 v 490 490 h -538 c -296,0 -542,-3 -545,-7 z"
|
|
/>
|
|
<path
|
|
d="m 5190,13285 c -8,-3 -96,-12 -195,-20 -199,-16 -296,-32 -430,-70 -49,-14 -115,-32 -145,-40 -153,-39 -504,-198 -662,-301 -21,-13 -57,-36 -80,-51 -24,-16 -72,-50 -109,-78 -241,-182 -377,-315 -528,-517 -119,-158 -120,-160 -106,-188 23,-45 140,-140 560,-457 110,-84 319,-242 465,-353 146,-110 369,-279 495,-375 791,-600 723,-549 1049,-799 269,-207 398,-307 524,-403 l 114,-86 -49,-49 c -128,-131 -378,-258 -588,-299 -66,-13 -357,-13 -420,0 -115,23 -172,39 -202,54 -18,10 -37,17 -43,17 -24,0 -171,81 -255,141 -50,35 -146,121 -215,192 -69,70 -133,127 -142,127 -19,0 -153,-63 -177,-83 -9,-7 -54,-35 -101,-62 -47,-26 -110,-64 -140,-85 -30,-20 -97,-61 -148,-91 -51,-30 -107,-62 -124,-72 -18,-10 -57,-38 -87,-61 -70,-53 -252,-168 -446,-281 -82,-49 -158,-95 -168,-104 -16,-16 -14,-21 34,-106 165,-289 544,-666 867,-860 9,-6 35,-22 58,-37 36,-23 267,-138 349,-173 108,-47 160,-67 240,-93 150,-48 201,-62 228,-62 14,0 64,-9 109,-19 197,-46 302,-56 573,-56 197,1 281,5 345,17 47,9 110,19 141,22 31,3 75,13 99,21 23,8 56,15 72,15 17,0 51,7 77,15 25,8 80,24 121,36 41,12 125,41 185,66 61,25 124,50 140,56 17,7 89,42 160,78 113,58 177,98 395,246 82,56 273,232 403,371 127,136 237,271 237,291 0,12 -208,179 -425,342 -186,140 -1121,843 -1720,1294 -264,199 -589,444 -723,546 -134,101 -274,208 -312,237 -39,29 -70,58 -70,66 0,21 107,115 203,179 95,64 237,133 295,143 20,4 49,12 63,20 96,48 519,48 619,-1 14,-7 41,-16 60,-20 65,-13 262,-118 360,-191 99,-74 250,-230 372,-384 34,-44 70,-80 80,-80 9,0 39,15 67,33 28,17 70,44 94,58 23,15 121,76 217,136 96,60 254,156 350,213 96,56 272,160 390,230 118,70 230,135 248,144 41,21 41,45 -3,116 -18,30 -46,75 -61,100 -64,106 -252,348 -352,454 -106,112 -169,171 -293,274 -197,164 -310,235 -594,376 -215,106 -519,205 -735,240 -137,22 -574,51 -610,41 z"
|
|
/>
|
|
<path
|
|
d="m 29095,12736 c -421,-44 -744,-157 -975,-342 -259,-207 -396,-446 -465,-809 -16,-84 -23,-301 -14,-425 36,-518 257,-859 694,-1070 166,-80 284,-116 716,-215 449,-103 514,-121 646,-186 218,-107 308,-253 306,-494 -2,-303 -188,-477 -588,-551 -140,-26 -640,-27 -825,-1 -275,38 -486,94 -776,203 -94,35 -174,64 -178,64 -3,0 -6,-175 -6,-389 v -388 l 88,-41 c 404,-187 905,-282 1486,-282 675,0 1154,150 1465,459 196,194 311,434 362,756 20,121 17,476 -5,600 -89,517 -358,800 -945,994 -130,43 -241,71 -616,156 -137,31 -299,73 -360,92 -331,106 -455,246 -455,511 1,249 127,412 387,501 272,92 801,76 1269,-39 116,-28 326,-96 432,-138 l 52,-22 -2,406 -3,406 -66,28 c -154,66 -413,140 -604,174 -279,49 -756,69 -1020,42 z"
|
|
/>
|
|
<path
|
|
d="m 9630,12676 c 0,-2 403,-996 896,-2208 493,-1211 898,-2211 901,-2220 6,-21 -135,-386 -193,-499 -104,-202 -256,-324 -471,-380 -118,-30 -340,-43 -516,-29 -84,6 -185,17 -225,24 -40,7 -75,10 -77,7 -3,-2 -5,-163 -5,-357 v -353 l 63,-30 c 194,-93 493,-138 801,-120 414,23 683,115 937,319 174,140 357,402 474,680 26,62 1945,5159 1945,5167 0,2 -232,2 -516,1 l -517,-3 -556,-1550 c -485,-1350 -560,-1550 -578,-1553 -18,-3 -26,11 -62,105 -23,59 -295,758 -605,1553 l -562,1445 -567,3 c -312,1 -567,0 -567,-2 z"
|
|
/>
|
|
<path
|
|
d="m 15690,10867 c 0,-1970 -1,-1936 56,-2153 128,-497 461,-787 1014,-885 147,-26 440,-36 605,-20 413,40 834,200 1181,447 35,25 73,44 88,44 14,0 26,-1 26,-3 0,-2 20,-94 45,-205 25,-111 45,-204 45,-207 0,-3 209,-5 465,-5 h 465 v 2400 2400 h -535 -535 l -2,-1866 -3,-1866 -115,-50 c -425,-185 -743,-252 -1088,-227 -302,21 -472,109 -562,293 -79,161 -74,11 -77,1969 l -3,1747 h -535 -535 z"
|
|
/>
|
|
<path
|
|
d="m 24785,12668 c -3,-7 -4,-1086 -3,-2398 l 3,-2385 538,-3 537,-2 v 2400 2400 h -535 c -419,0 -537,-3 -540,-12 z"
|
|
/>
|
|
<path
|
|
d="m 21660,8275 v -545 h 565 565 v 545 545 h -565 -565 z"
|
|
/>
|
|
</g>
|
|
</Svg>
|
|
)
|
|
}
|
|
```
|
|
|
|
その他、書き換えを行うscriptです。頻繁にupdateすると思うので、mergeはきつい。
|
|
|
|
```sh
|
|
host=syu.is
|
|
name=${host%%.*}
|
|
domain=${host##*.}
|
|
|
|
cd $d/repos/social-app/src
|
|
if [ -n "`grep -R bsky.social .`" ];then
|
|
for f (`grep -R bsky.social . |cut -d : -f 1`) sed -i -e "s/bsky\.social/${name}\.${domain}/g" $f
|
|
fi
|
|
if [ -n "`grep -R "isSandbox: false" .`" ];then
|
|
for f (`grep -R "isSandbox: false" . |cut -d : -f 1`) sed -i -e "s/isSandbox: false/isSandbox: true/g" $f
|
|
fi
|
|
if [ -n "`grep -R SANDBOX .`" ];then
|
|
for f (`grep -R SANDBOX . |cut -d : -f 1`) sed -i -e "s/SANDBOX/${name}\.${domain}/g" $f
|
|
fi
|
|
f=./view/com/modals/ServerInput.tsx
|
|
if [ -n "`grep -R Bluesky.Social $f`" ] && [ -f $f ];then
|
|
sed -i -e "s/Bluesky\.Social/${name}\.${domain}/g" $f
|
|
fi
|
|
f=./state/queries/preferences/moderation.ts
|
|
if [ -n "`grep -R 'Bluesky Social' $f`" ] && [ -f $f ];then
|
|
sed -i -e "s/Bluesky Social/${name}\.${domain}/g" $f
|
|
fi
|
|
f=./view/com/auth/create/Step1.tsx
|
|
if [ -n "`grep -R 'Bluesky' $f`" ] && [ -f $f ];then
|
|
sed -i -e "s/Bluesky/${name}\.${domain}/g" $f
|
|
fi
|
|
f=./lib/strings/url-helpers.ts
|
|
if [ -n "`grep -R 'Bluesky Social' $f`" ] && [ -f $f ];then
|
|
sed -i -e "s/Bluesky Social/${name}\.${domain}/g" $f
|
|
fi
|
|
f=./view/icons/Logotype.tsx
|
|
o=$d/icons/Logotype.tsx
|
|
if [ -n "`grep -R 'M8.478 6.252c1.503.538 2.3 1.7' $f`" ] && [ -f $f ] && [ -f $o ];then
|
|
cp -rf $o $f
|
|
fi
|
|
```
|