add patch
This commit is contained in:
38
.github/workflows/generate-record.yml
vendored
Normal file
38
.github/workflows/generate-record.yml
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
name: Generate Record JSON
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch: # 手動トリガー
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- scpt/generate_record.py # スクリプトに変更があったとき
|
||||||
|
schedule:
|
||||||
|
- cron: '0 3 * * *' # 毎日03:00 UTCに自動生成(任意)
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.x'
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: |
|
||||||
|
pip install -r requirements.txt || true # 必要なら
|
||||||
|
|
||||||
|
- name: Run Record Generator Script
|
||||||
|
run: |
|
||||||
|
python scpt/generate_record.py
|
||||||
|
|
||||||
|
- name: Commit and Push Generated JSON
|
||||||
|
run: |
|
||||||
|
git config --global user.name "GitHub Actions Bot"
|
||||||
|
git config --global user.email "actions@github.com"
|
||||||
|
git add record.json
|
||||||
|
git commit -m "🧬 Auto-generate record.json" || echo "No changes to commit"
|
||||||
|
git push origin main
|
||||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
repos
|
||||||
|
.claude
|
||||||
96
README.md
96
README.md
@@ -1,11 +1,12 @@
|
|||||||
# at
|
# at
|
||||||
|
|
||||||
https://github.com/bluesky-social/atproto
|
- https://github.com/bluesky-social/atproto
|
||||||
|
- https://github.com/bluesky-social/atproto/discussions/2026
|
||||||
|
|
||||||
|word|name|example|
|
|word|name|example|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|at|uri|at://ai.syu.is|
|
|at|uri|at://example.com|
|
||||||
|@|user|@ai.syu.is|
|
|@|user|@example.com|
|
||||||
|[at]proto|repo|`git@github.com:bluesky-social/atproto`|
|
|[at]proto|repo|`git@github.com:bluesky-social/atproto`|
|
||||||
|[at]mosphere|system|pds, bsky(appview), ozone, bgs, plc|
|
|[at]mosphere|system|pds, bsky(appview), ozone, bgs, plc|
|
||||||
|[a]uthenticated [t]ransfer|protocol|[did](https://www.w3.org/TR/did-core/)|
|
|[a]uthenticated [t]ransfer|protocol|[did](https://www.w3.org/TR/did-core/)|
|
||||||
@@ -14,15 +15,13 @@ https://github.com/bluesky-social/atproto
|
|||||||
|
|
||||||
## account
|
## account
|
||||||
|
|
||||||
[@ai.syu.is](https://web.syu.is/profile/ai.syu.is)
|
- [ai@syu.is](https://syu.is/profile/did:plc:6qyecktefllvenje24fcxnie)
|
||||||
|
- [ai@bsky.app](https://bsky.app/profile/did:plc:6qyecktefllvenje24fcxnie)
|
||||||
- https://at.syu.is/at/yui.syui.ai
|
|
||||||
- https://plc.syu.is/did:plc:6qyecktefllvenje24fcxnie
|
- https://plc.syu.is/did:plc:6qyecktefllvenje24fcxnie
|
||||||
- https://plc.directory/did:plc:ytvoptig4ddshmwdsjmhtcym
|
- https://plc.directory/did:plc:6qyecktefllvenje24fcxnie
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ curl -sL syu.is/xrpc/_health
|
$ curl -sL syu.is/xrpc/_health
|
||||||
{"version":"0.4.65"}
|
|
||||||
|
|
||||||
# latest
|
# latest
|
||||||
# https://github.com/bluesky-social/atproto/blob/main/packages/pds/package.json
|
# https://github.com/bluesky-social/atproto/blob/main/packages/pds/package.json
|
||||||
@@ -30,10 +29,11 @@ $ curl -sL https://raw.githubusercontent.com/bluesky-social/atproto/refs/heads/m
|
|||||||
```
|
```
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ curl -sL "syu.is/xrpc/com.atproto.repo.describeRepo?repo=ai.syu.is" |jq -r .did
|
$ handle=ai.syui.ai
|
||||||
|
$ curl -sL "syu.is/xrpc/com.atproto.repo.describeRepo?repo=${handle}" |jq -r .did
|
||||||
did:plc:6qyecktefllvenje24fcxnie
|
did:plc:6qyecktefllvenje24fcxnie
|
||||||
|
|
||||||
$ curl -sL "syu.is/xrpc/com.atproto.repo.listRecords?repo=ai.syu.is&collection=app.bsky.feed.post&reverse=true&limit=1"
|
$ curl -sL "syu.is/xrpc/com.atproto.repo.listRecords?repo=${handle}&collection=app.bsky.feed.post&reverse=true&limit=1"
|
||||||
{"records":[{"uri":"at://did:plc:6qyecktefllvenje24fcxnie/app.bsky.feed.post/3l6s2riuouk2j","cid":"bafyreibjohl7va4upkibw5twaxdd4jg3l6rmfatu4dpjjfd5xkb2ijtlx4","value":{"text":"hello","$type":"app.bsky.feed.post","langs":["ja"],"createdAt":"2024-10-18T13:21:39.809Z"}}],"cursor":"3l6s2riuouk2j"}
|
{"records":[{"uri":"at://did:plc:6qyecktefllvenje24fcxnie/app.bsky.feed.post/3l6s2riuouk2j","cid":"bafyreibjohl7va4upkibw5twaxdd4jg3l6rmfatu4dpjjfd5xkb2ijtlx4","value":{"text":"hello","$type":"app.bsky.feed.post","langs":["ja"],"createdAt":"2024-10-18T13:21:39.809Z"}}],"cursor":"3l6s2riuouk2j"}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -45,80 +45,4 @@ $ curl -sL "syu.is/xrpc/com.atproto.repo.listRecords?repo=ai.syu.is&collection=a
|
|||||||
- https://feed.syu.is/xrpc/app.bsky.feed.getFeedSkeleton?feed=at://did:plc:4hqjfn7m6n5hno3doamuhgef/app.bsky.feed.generator/cmd
|
- https://feed.syu.is/xrpc/app.bsky.feed.getFeedSkeleton?feed=at://did:plc:4hqjfn7m6n5hno3doamuhgef/app.bsky.feed.generator/cmd
|
||||||
- https://desc.syu.is/xrpc/app.bsky.feed.getFeedSkeleton?feed=at://did:plc:6qyecktefllvenje24fcxnie/app.bsky.feed.generator/cmd
|
- https://desc.syu.is/xrpc/app.bsky.feed.getFeedSkeleton?feed=at://did:plc:6qyecktefllvenje24fcxnie/app.bsky.feed.generator/cmd
|
||||||
|
|
||||||
## link
|
|
||||||
|
|
||||||
- https://github.com/bluesky-social/atproto
|
|
||||||
- https://github.com/itaru2622/bluesky-selfhost-env
|
|
||||||
- https://github.com/bluesky-social/atproto/discussions/2026
|
|
||||||
|
|
||||||
## self-host
|
|
||||||
|
|
||||||
currently, bsky and bsync require patches to function properly. additionally, social-app is not displaying avatars. for components that are not working, it's recommended to use [itaru2622/bluesky-selfhost-env](https://github.com/itaru2622/bluesky-selfhost-env). this repository provides an environment for self-hosting bluesky.
|
|
||||||
|
|
||||||
- bsky = appview
|
|
||||||
- ozone = mod
|
|
||||||
|
|
||||||
|name|service|patch|
|
|
||||||
|---|---|---|
|
|
||||||
|pds|https://github.com/bluesky-social/atproto/blob/main/services/pds/Dockerfile||
|
|
||||||
|bsky|https://github.com/bluesky-social/atproto/blob/main/services/bsky/Dockerfile|[itaru2622/bluesky-atproto-bsky](https://hub.docker.com/r/itaru2622/bluesky-atproto-bsky)|
|
|
||||||
|bsync|https://github.com/bluesky-social/atproto/blob/main/services/bsync/Dockerfile||
|
|
||||||
|ozone|https://github.com/bluesky-social/atproto/blob/main/services/ozone/Dockerfile||
|
|
||||||
|plc|https://github.com/did-method-plc/did-method-plc/tree/main/packages/server||
|
|
||||||
|bgs|https://github.com/bluesky-social/indigo/tree/main/cmd/bigsky||
|
|
||||||
|feed|https://github.com/bluesky-social/feed-generator||
|
|
||||||
|web|https://github.com/bluesky-social/social-app|[bluesky-selfhost-env](https://github.com/itaru2622/bluesky-selfhost-env/blob/master/patching/160-social-app-disable-hackModifyThumbnailPath.diff)|
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# BSKY_IMG_URI_ENDPOINT, BSKY_BLOB_CACHE_LOC
|
|
||||||
# avatar link example
|
|
||||||
1. https://appview.${host}/img/avatar/plain/${did}/${cid}@jpeg
|
|
||||||
2. https://${host}/xrpc/com.atproto.sync.getBlob?did=${did}&cid=${cid}
|
|
||||||
```
|
|
||||||
|
|
||||||
docker compose will not be published unless you write ports. it is only valid internally. add ports only for what you want to publish.
|
|
||||||
|
|
||||||
## api
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# create account
|
|
||||||
url=https://${pds}/xrpc/com.atproto.server.createAccount
|
|
||||||
json="{\"email\": \"$email\", \"handle\": \"$handle\", \"password\": \"$password\"}"
|
|
||||||
curl -X POST -H "Content-Type: application/json" -d $json -sL $url
|
|
||||||
```
|
|
||||||
|
|
||||||
change `src/pds/handle` to use a name of 3 characters or less. also, you cannot create an account with a name of 3 characters or less from social-app (web client). please create it from api.
|
|
||||||
|
|
||||||
- [/atproto/packages/pds/src/handle/index.ts](https://github.com/bluesky-social/atproto/blame/d4d5a6edba972c0e9976289bde8bc0b42ff547ca/packages/pds/src/handle/index.ts#L86-L88)
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# invite code
|
|
||||||
admin_password=xxx
|
|
||||||
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
|
|
||||||
```
|
|
||||||
|
|
||||||
## oauth
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# https://github.com/bluesky-social/cookbook/tree/main/python-oauth-web-app
|
|
||||||
$ cd ./repos/cookbook/python-oauth-web-app
|
|
||||||
$ rye sync
|
|
||||||
$ rye run python3 -c 'import secrets; print(secrets.token_hex())'|xargs echo FLASK_SECRET_KEY|tr -d ' ' >> .env
|
|
||||||
$ rye run python3 generate_jwk.py |xargs echo FLASK_CLIENT_SECRET_JWK|tr -d ' ' >> .env
|
|
||||||
$ cat .env
|
|
||||||
$ rye run flask run
|
|
||||||
```
|
|
||||||
|
|
||||||
please access `127.0.0.1:5000`. it may not work if you use localhost.
|
|
||||||
|
|
||||||
also, oauth doesn't work on localhost. use [ngrok](https://ngrok.com/), [tailscale](https://tailscale.com/), [cloudflare](https://github.com/cloudflare/cloudflared).
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ ngrok http http://localhost:5000
|
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ cloudflared tunnel --url http://localhost:5000
|
|
||||||
```
|
|
||||||
|
|||||||
47
at.json
47
at.json
@@ -1,47 +0,0 @@
|
|||||||
{
|
|
||||||
"atmosphere": {
|
|
||||||
"name": "at",
|
|
||||||
"repo": "https://github.com/bluesky-social/atproto",
|
|
||||||
"uri": "https://atproto.com/ja/guides/glossary",
|
|
||||||
"exosphere": {
|
|
||||||
"km":[{ "min": 700, "max": 10000 }],
|
|
||||||
"tag": [ "universe" ]
|
|
||||||
},
|
|
||||||
"thermosphere": {
|
|
||||||
"km":[{ "min": 80, "max": 700 }],
|
|
||||||
"tag": [ "aurora" ]
|
|
||||||
},
|
|
||||||
"mesosphere": {
|
|
||||||
"km":[{ "min": 50, "max": 80 }],
|
|
||||||
"tag": [ "meteor" ]
|
|
||||||
},
|
|
||||||
"stratosphere": {
|
|
||||||
"km":[{ "min": 12, "max": 50 }],
|
|
||||||
"tag": [ "ozone", "bigsky" ],
|
|
||||||
"service":[
|
|
||||||
{ "name":"ozone", "repo":"https://github.com/bluesky-social/atproto/tree/main/services/ozone" },
|
|
||||||
{ "name":"bgs", "repo":"https://github.com/bluesky-social/indigo/tree/main/cmd/bigsky" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"troposphere": {
|
|
||||||
"km":[{ "min": 0, "max": 12 }],
|
|
||||||
"tag": [ "bluesky"],
|
|
||||||
"service":[
|
|
||||||
{ "name":"bsky", "repo":"https://github.com/bluesky-social/atproto/tree/main/services/bsky", "tag":[ "api", "appview" ] },
|
|
||||||
{ "name":"bsync","repo":"https://github.com/bluesky-social/atproto/tree/main/services/bsync" },
|
|
||||||
{ "name":"pds", "repo":"https://github.com/bluesky-social/atproto/tree/main/services/pds" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"other": {
|
|
||||||
"tag": [ "plc", "feed", "oauth", "social-app", "stream" ],
|
|
||||||
"service":[
|
|
||||||
{ "name":"plc", "repo":"https://github.com/did-method-plc/did-method-plc/tree/main/packages/server", "tag" : [ "did" ] },
|
|
||||||
{ "name":"social-app", "repo":"https://github.com/bluesky-social/social-app", "tag": [ "web" ] },
|
|
||||||
{ "name":"oauth", "repo":"https://github.com/bluesky-social/cookbook/tree/main/python-oauth-web-app" },
|
|
||||||
{ "name":"feed", "repo":"https://github.com/bluesky-social/feed-generator" },
|
|
||||||
{ "name":"stream", "repo":"https://github.com/bluesky-social/jetstream" }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ref": "https://en.wikipedia.org/wiki/Atmosphere_of_Earth"
|
|
||||||
}
|
|
||||||
128
compose.yml
128
compose.yml
@@ -48,71 +48,11 @@ services:
|
|||||||
- ./envs/pds
|
- ./envs/pds
|
||||||
volumes:
|
volumes:
|
||||||
- ./data/pds/:/data/
|
- ./data/pds/:/data/
|
||||||
|
command: node --enable-source-maps index.js
|
||||||
depends_on:
|
depends_on:
|
||||||
database:
|
database:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|
||||||
bgs:
|
|
||||||
ports:
|
|
||||||
- 2470:2470
|
|
||||||
build:
|
|
||||||
context: ./repos/indigo/
|
|
||||||
dockerfile: cmd/bigsky/Dockerfile
|
|
||||||
restart: always
|
|
||||||
env_file:
|
|
||||||
- ./envs/bgs
|
|
||||||
volumes:
|
|
||||||
- ./data/bgs/:/data/
|
|
||||||
depends_on:
|
|
||||||
database:
|
|
||||||
condition: service_healthy
|
|
||||||
|
|
||||||
ozone:
|
|
||||||
ports:
|
|
||||||
- 2585:3000
|
|
||||||
build:
|
|
||||||
context: ./repos/atproto/
|
|
||||||
dockerfile: services/ozone/Dockerfile
|
|
||||||
restart: always
|
|
||||||
command: node --enable-source-maps api.js
|
|
||||||
volumes:
|
|
||||||
- ./data/ozone/:/data/
|
|
||||||
- ./repos/ozone.js:/app/services/ozone/api.js:ro
|
|
||||||
env_file:
|
|
||||||
- ./envs/ozone
|
|
||||||
healthcheck:
|
|
||||||
test: "wget -q --spider http://localhost:3000/xrpc/_health"
|
|
||||||
interval: 5s
|
|
||||||
retries: 20
|
|
||||||
depends_on:
|
|
||||||
database:
|
|
||||||
condition: service_healthy
|
|
||||||
|
|
||||||
ozone-daemon:
|
|
||||||
build:
|
|
||||||
context: ./repos/atproto/
|
|
||||||
dockerfile: services/ozone/Dockerfile
|
|
||||||
restart: always
|
|
||||||
command: node --enable-source-maps daemon.js
|
|
||||||
env_file:
|
|
||||||
- ./envs/ozone
|
|
||||||
depends_on:
|
|
||||||
ozone:
|
|
||||||
condition: service_healthy
|
|
||||||
database:
|
|
||||||
condition: service_healthy
|
|
||||||
|
|
||||||
social-app:
|
|
||||||
ports:
|
|
||||||
- 8100:8100
|
|
||||||
build:
|
|
||||||
context: ./repos/social-app/
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
restart: always
|
|
||||||
env_file:
|
|
||||||
- ./envs/social-app
|
|
||||||
command: "/usr/bin/bskyweb serve"
|
|
||||||
|
|
||||||
bsky:
|
bsky:
|
||||||
ports:
|
ports:
|
||||||
- 2584:2584
|
- 2584:2584
|
||||||
@@ -131,3 +71,69 @@ services:
|
|||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
redis:
|
redis:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|
||||||
|
bgs:
|
||||||
|
ports:
|
||||||
|
- 2470:2470
|
||||||
|
build:
|
||||||
|
context: ./repos/indigo/
|
||||||
|
dockerfile: cmd/bigsky/Dockerfile
|
||||||
|
restart: always
|
||||||
|
env_file:
|
||||||
|
- ./envs/bgs
|
||||||
|
volumes:
|
||||||
|
- ./data/bgs/:/data/
|
||||||
|
depends_on:
|
||||||
|
database:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
social-app:
|
||||||
|
ports:
|
||||||
|
- 8100:8100
|
||||||
|
build:
|
||||||
|
context: ./repos/social-app/
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
restart: always
|
||||||
|
env_file:
|
||||||
|
- ./envs/social-app
|
||||||
|
command: "/usr/bin/bskyweb serve"
|
||||||
|
|
||||||
|
jetstream:
|
||||||
|
build:
|
||||||
|
context: ./repos/jetstream/
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
ports:
|
||||||
|
- 6008:6008
|
||||||
|
volumes:
|
||||||
|
- ./data/jetstream:/data
|
||||||
|
restart: always
|
||||||
|
env_file:
|
||||||
|
- ./envs/jetstream
|
||||||
|
|
||||||
|
ozone-web:
|
||||||
|
build:
|
||||||
|
context: ./repos/ozone/
|
||||||
|
ports:
|
||||||
|
- 2586:3000
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./data/ozone/:/data/
|
||||||
|
env_file:
|
||||||
|
- ./envs/ozone
|
||||||
|
depends_on:
|
||||||
|
database:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
ozone:
|
||||||
|
build:
|
||||||
|
context: ./repos/atproto/
|
||||||
|
dockerfile: services/ozone/Dockerfile
|
||||||
|
ports:
|
||||||
|
- 2585:3000
|
||||||
|
restart: always
|
||||||
|
command: node --enable-source-maps api.js
|
||||||
|
volumes:
|
||||||
|
- ./data/ozone/:/data/
|
||||||
|
env_file:
|
||||||
|
- ./envs/ozone
|
||||||
|
|
||||||
|
|||||||
4
envs/bgs
4
envs/bgs
@@ -2,5 +2,5 @@ DATABASE_URL=postgres://postgres:postgres@database/bgs
|
|||||||
CARSTORE_DATABASE_URL=postgres://postgres:postgres@database/carstore
|
CARSTORE_DATABASE_URL=postgres://postgres:postgres@database/carstore
|
||||||
DATA_DIR=/data
|
DATA_DIR=/data
|
||||||
ATP_PLC_HOST=https://plc.${host}
|
ATP_PLC_HOST=https://plc.${host}
|
||||||
|
BGS_NEW_PDS_PER_DAY_LIMIT=1000
|
||||||
BGS_ADMIN_KEY
|
BGS_ADMIN_KEY=
|
||||||
|
|||||||
5
envs/jetstream
Normal file
5
envs/jetstream
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
JETSTREAM_WS_URL=wss://bgs.${host}/xrpc/com.atproto.sync.subscribeRepos
|
||||||
|
JETSTREAM_DATA_DIR=/data
|
||||||
|
JETSTREAM_LISTEN_ADDR=:6008
|
||||||
|
JETSTREAM_METRICS_LISTEN_ADDR=:6009
|
||||||
|
JETSTREAM_LIVENESS_TTL=96h
|
||||||
@@ -19,3 +19,11 @@ OZONE_DB_MIGRATE=1
|
|||||||
|
|
||||||
OZONE_ADMIN_PASSWORD
|
OZONE_ADMIN_PASSWORD
|
||||||
OZONE_SIGNING_KEY_HEX
|
OZONE_SIGNING_KEY_HEX
|
||||||
|
OZONE_BLOB_DIVERT_ADMIN_PASSWORD
|
||||||
|
OZONE_VERIFIER_URL
|
||||||
|
OZONE_VERIFIER_DID
|
||||||
|
OZONE_VERIFIER_PASSWORD
|
||||||
|
OZONE_VERIFIER_ISSUERS_TO_INDEX
|
||||||
|
OZONE_VERIFIER_JETSTREAM_URL
|
||||||
|
|
||||||
|
OZONE_APPVIEW_PUSH_EVENTS=true
|
||||||
|
|||||||
2
envs/pds
2
envs/pds
@@ -6,6 +6,8 @@ PDS_BLOBSTORE_DISK_LOCATION=/data/img/static
|
|||||||
PDS_BSKY_APP_VIEW_DID=did:web:bsky.${host}
|
PDS_BSKY_APP_VIEW_DID=did:web:bsky.${host}
|
||||||
PDS_BSKY_APP_VIEW_URL=https://bsky.${host}
|
PDS_BSKY_APP_VIEW_URL=https://bsky.${host}
|
||||||
PDS_CRAWLERS=https://bgs.${host}
|
PDS_CRAWLERS=https://bgs.${host}
|
||||||
|
PDS_SEQUENCER_ENABLED=true
|
||||||
|
PDS_SEQUENCER_DB_LOCATION=/data/sequencer.sqlite
|
||||||
PDS_DEV_MODE=true
|
PDS_DEV_MODE=true
|
||||||
PDS_DID_PLC_URL=https://plc.${host}
|
PDS_DID_PLC_URL=https://plc.${host}
|
||||||
PDS_ENABLE_DID_DOC_WITH_SESSION=true
|
PDS_ENABLE_DID_DOC_WITH_SESSION=true
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
ATP_APPVIEW_HOST=https://bsky.${host}
|
ATP_APPVIEW_HOST=https://public.api.bsky.app
|
||||||
|
EXPO_PUBLIC_BLUESKY_PROXY_DID=did:web:api.bsky.app
|
||||||
|
EXPO_PUBLIC_ENV=production
|
||||||
|
|||||||
236
install.zsh
236
install.zsh
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/zsh
|
#!/bin/zsh
|
||||||
|
|
||||||
# ./install.zsh $HOST
|
# ./install.zsh $HOST
|
||||||
|
repos_v='{}'
|
||||||
function at-repos-env() {
|
function at-repos-env() {
|
||||||
host=$1
|
host=$1
|
||||||
if [ -z "$1" ];then
|
if [ -z "$1" ];then
|
||||||
@@ -15,11 +15,15 @@ function at-repos-env() {
|
|||||||
https://github.com/bluesky-social/atproto
|
https://github.com/bluesky-social/atproto
|
||||||
https://github.com/bluesky-social/social-app
|
https://github.com/bluesky-social/social-app
|
||||||
https://github.com/bluesky-social/feed-generator
|
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}
|
d=${0:a:h}
|
||||||
dh=${0:a:h:h}
|
dh=${0:a:h:h}
|
||||||
name=${host%%.*}
|
name=${host%%.*}
|
||||||
domain=${host##*.}
|
domain=${host##*.}
|
||||||
|
dport=5000
|
||||||
}
|
}
|
||||||
|
|
||||||
function at-repos-json() {
|
function at-repos-json() {
|
||||||
@@ -55,6 +59,7 @@ function at-repos-clone() {
|
|||||||
echo $repo
|
echo $repo
|
||||||
if [ ! -d $d/repos/${repo##*/} ];then
|
if [ ! -d $d/repos/${repo##*/} ];then
|
||||||
git clone $repo
|
git clone $repo
|
||||||
|
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
if [ ! -f $d/repos/feed-generator/Dockerfile ] && [ -f $d/docker/feed/Dockerfile ];then
|
if [ ! -f $d/repos/feed-generator/Dockerfile ] && [ -f $d/docker/feed/Dockerfile ];then
|
||||||
@@ -69,11 +74,18 @@ function at-repos-pull() {
|
|||||||
echo $repo
|
echo $repo
|
||||||
if [ -d $d/repos/${repo##*/} ];then
|
if [ -d $d/repos/${repo##*/} ];then
|
||||||
cd $d/repos/${repo##*/}
|
cd $d/repos/${repo##*/}
|
||||||
|
git stash
|
||||||
if ! git pull;then
|
if ! git pull;then
|
||||||
rm -rf $d/repos/${repo##*/}
|
rm -rf $d/repos/${repo##*/}
|
||||||
at-repos-clone
|
at-repos-clone
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
rv=$(echo "$repos_v" | jq -r ".[\"${repo##*/}\"]")
|
||||||
|
if [ "$rv" != "null" ];then
|
||||||
|
cd $d/repos/${repo##*/}
|
||||||
|
git reset --hard $rv
|
||||||
|
cd ..
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
cd $d
|
cd $d
|
||||||
}
|
}
|
||||||
@@ -90,58 +102,234 @@ function at-repos-social-app-icon-origin() {
|
|||||||
curl -sL $icon -o $d/icons/Logotype.tsx
|
curl -sL $icon -o $d/icons/Logotype.tsx
|
||||||
}
|
}
|
||||||
|
|
||||||
function at-repos-social-app-write() {
|
function at-repos-social-app-avatar-write() {
|
||||||
did_admin=did:plc:z72i7hdynmk6r22z27h6tvur
|
did_admin=did:plc:6qyecktefllvenje24fcxnie
|
||||||
|
|
||||||
dt=$d/repos/social-app/src
|
dt=$d/repos/social-app/src
|
||||||
cd $dt
|
cd $dt
|
||||||
grep -R bsky.social .|cut -d : -f 1|sort -u|xargs sed -i "s/bsky.social/${host}/g"
|
grep -R syu.is .|cut -d : -f 1|sort -u|xargs sed -i "s/syu.is/${host}/g"
|
||||||
grep -R bsky.app .|cut -d : -f 1|sort -u|xargs sed -i "s/bsky.app/web.${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
|
f=$dt/lib/constants.ts
|
||||||
sed -i "s/public.api.web/bsky/g" $f
|
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
|
||||||
|
|
||||||
|
# Disable external services (CORS fix)
|
||||||
|
f=$dt/state/geolocation/const.ts
|
||||||
|
curl -sL https://raw.githubusercontent.com/bluesky-social/social-app/refs/heads/main/src/state/geolocation/const.ts -o $f
|
||||||
|
cat > $f << 'GEOEOF'
|
||||||
|
import {type GeolocationStatus} from '#/state/geolocation/types'
|
||||||
|
import {BAPP_CONFIG_DEV_URL, IS_DEV} from '#/env'
|
||||||
|
import {type Device} from '#/storage'
|
||||||
|
|
||||||
|
export const IPCC_URL = `https://bsky.app/ipcc`
|
||||||
|
// Disabled for self-hosted environment to avoid CORS errors
|
||||||
|
export const BAPP_CONFIG_URL_PROD = null
|
||||||
|
export const BAPP_CONFIG_URL = null
|
||||||
|
export const GEOLOCATION_CONFIG_URL = BAPP_CONFIG_URL
|
||||||
|
|
||||||
|
export const DEFAULT_GEOLOCATION_CONFIG: Device['geolocation'] = {
|
||||||
|
countryCode: undefined,
|
||||||
|
regionCode: undefined,
|
||||||
|
ageRestrictedGeos: [],
|
||||||
|
ageBlockedGeos: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DEFAULT_GEOLOCATION_STATUS: GeolocationStatus = {
|
||||||
|
countryCode: undefined,
|
||||||
|
regionCode: undefined,
|
||||||
|
isAgeRestrictedGeo: false,
|
||||||
|
isAgeBlockedGeo: false,
|
||||||
|
}
|
||||||
|
GEOEOF
|
||||||
|
|
||||||
|
# Add null check to geolocation config.ts to prevent fetch(null) errors
|
||||||
|
f=$dt/state/geolocation/config.ts
|
||||||
|
curl -sL https://raw.githubusercontent.com/bluesky-social/social-app/refs/heads/main/src/state/geolocation/config.ts -o $f
|
||||||
|
# Add null check at the beginning of getGeolocationConfig function (after line with 'url: string,')
|
||||||
|
sed -i "s/): Promise<Device\['geolocation'\]> {/): Promise<Device['geolocation']> {\n if (!url) return undefined/" $f
|
||||||
|
|
||||||
|
# Disable Statsig (CORS fix)
|
||||||
|
f=$dt/lib/statsig/statsig.tsx
|
||||||
|
sed -i "s#api: 'https://events.bsky.app/v2'#api: '' // Disabled for self-hosted#g" $f
|
||||||
|
# Disable SDK initialization to prevent statsigapi.net connections
|
||||||
|
sed -i "s#const SDK_KEY = 'client-SXJakO39w9vIhl3D44u8UupyzFl4oZ2qPIkjwcvuPsV'#const SDK_KEY = '' // Disabled for self-hosted#g" $f
|
||||||
|
|
||||||
f=$dt/view/icons/Logotype.tsx
|
f=$dt/view/icons/Logotype.tsx
|
||||||
o=$d/icons/Logotype.tsx
|
o=$d/icons/Logotype.tsx
|
||||||
cp -rf $o $f
|
cp -rf $o $f
|
||||||
|
|
||||||
f=$dt/view/com/util/UserAvatar.tsx
|
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
|
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.bsky.app/img/avatar/plain/#g" $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#/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
|
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"
|
grep -R $did_admin .|cut -d : -f 1|sort -u|xargs sed -i "s/${did_admin}/${did}/g"
|
||||||
}
|
}
|
||||||
|
|
||||||
function at-repos-bsky-patch() {
|
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
|
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
|
curl -sL https://raw.githubusercontent.com/bluesky-social/atproto/refs/heads/main/services/bsky/api.js -o $f
|
||||||
d_=$d/repos/atproto
|
d_=$d/repos/atproto
|
||||||
p_=$d_/105-atproto-services-for-docker.diff
|
p_=$d/patching/4367-atproto-services-bsky-api.diff
|
||||||
cd $d_
|
echo "applying patch: under ${f} for ${p_}"
|
||||||
# https://github.com/itaru2622/bluesky-selfhost-env/blob/master/patching/105-atproto-services-for-docker.diff
|
|
||||||
curl -sLO https://raw.githubusercontent.com/itaru2622/bluesky-selfhost-env/refs/heads/master/patching/105-atproto-services-for-docker.diff
|
|
||||||
echo "applying patch: under ${d_} for ${p_}"
|
|
||||||
pushd ${d_}
|
pushd ${d_}
|
||||||
patch -p1 < ${p_}
|
patch -p1 < ${p_}
|
||||||
popd
|
popd
|
||||||
}
|
}
|
||||||
|
|
||||||
function at-repos-docker() {
|
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-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-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/121-ozone-constants-fix.patch
|
||||||
|
echo "applying patch: under ${d_} for ${p_}"
|
||||||
|
pushd ${d_}
|
||||||
|
patch -p1 < ${p_} || true
|
||||||
|
popd
|
||||||
|
#cp -rf $d/repos/atproto/service/ozone/* $d/ozone/service/
|
||||||
|
}
|
||||||
|
|
||||||
|
function at-repos-build-docker-atproto() {
|
||||||
cd $d
|
cd $d
|
||||||
sudo docker compose build && sudo docker compose up -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() {
|
||||||
|
docker restart registry
|
||||||
|
docker stop registry
|
||||||
|
docker rm registry
|
||||||
|
docker volume rm registry-data 2>/dev/null || true
|
||||||
|
docker run -d -p ${dport}:${dport} --name registry \
|
||||||
|
--restart=always \
|
||||||
|
-v registry-data:/var/lib/registry \
|
||||||
|
registry:2
|
||||||
|
sleep 3
|
||||||
|
docker run -d -p ${dport}:${dport} --name registry --restart=always 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
|
||||||
|
if [ "$service" = "ozone" ];then
|
||||||
|
docker tag at-${service}:latest localhost:${dport}/${service}-web:latest
|
||||||
|
docker push localhost:${dport}/${service}-web:latest
|
||||||
|
fi
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
function at-origin-social-app() {
|
||||||
|
cp -rf $d/social-app-custom $d/repos/social-app
|
||||||
}
|
}
|
||||||
|
|
||||||
at-repos-env
|
at-repos-env
|
||||||
|
case "`cat /etc/hostname`" in
|
||||||
|
at)
|
||||||
|
at-repos-pull-docker
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
at-repos-push-reset
|
||||||
at-repos-clone
|
at-repos-clone
|
||||||
at-repos-pull
|
at-repos-pull
|
||||||
at-repos-social-app-icon
|
at-repos-social-app-icon
|
||||||
at-repos-social-app-icon-origin
|
at-repos-social-app-icon-origin
|
||||||
at-repos-social-app-write
|
at-repos-social-app-avatar-write
|
||||||
at-repos-bsky-patch
|
at-repos-social-app-agent-patch
|
||||||
|
at-repos-social-app-disable-external-services-patch
|
||||||
echo "[y]docker compose build && up"
|
at-repos-atproto-service-bsky-api-patch
|
||||||
read key
|
at-repos-atproto-service-pds-index-patch
|
||||||
case $key in
|
at-repos-atproto-service-ozone-api-patch
|
||||||
[yY])
|
at-repos-ozone-patch
|
||||||
at-repos-docker
|
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
|
esac
|
||||||
|
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "ai.syui.card",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "record",
|
|
||||||
"description": "Record containing a cards box.",
|
|
||||||
"key": "tid",
|
|
||||||
"record": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["verify", "createdAt"],
|
|
||||||
"properties": {
|
|
||||||
"id":{
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 0,
|
|
||||||
"maximum": 14,
|
|
||||||
"default": 0
|
|
||||||
},
|
|
||||||
"cp":{
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 1,
|
|
||||||
"maximum": 5000,
|
|
||||||
"default": 1
|
|
||||||
},
|
|
||||||
"rank":{
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 0,
|
|
||||||
"maximum": 7,
|
|
||||||
"default": 0
|
|
||||||
},
|
|
||||||
"rare": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["normal", "super", "ultra", "yui", "ai"],
|
|
||||||
"default": "normal"
|
|
||||||
},
|
|
||||||
"author": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "uri",
|
|
||||||
"description": "https://verify...",
|
|
||||||
"default": "https://yui.syui.ai"
|
|
||||||
},
|
|
||||||
"verify": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "at-uri",
|
|
||||||
"description": "at://verify..."
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "datetime",
|
|
||||||
"description": "Client-declared timestamp when this post was originally created."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "ai.syui.card.verify",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "record",
|
|
||||||
"description": "Record containing a card verify.",
|
|
||||||
"key": "tid",
|
|
||||||
"record": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"handle",
|
|
||||||
"did",
|
|
||||||
"createdAt"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"id": {
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 0,
|
|
||||||
"maximum": 14,
|
|
||||||
"default": 0
|
|
||||||
},
|
|
||||||
"cp": {
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 1,
|
|
||||||
"maximum": 10000,
|
|
||||||
"default": 1
|
|
||||||
},
|
|
||||||
"rank": {
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 0,
|
|
||||||
"maximum": 7,
|
|
||||||
"default": 0
|
|
||||||
},
|
|
||||||
"rare": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"normal",
|
|
||||||
"super",
|
|
||||||
"ultra",
|
|
||||||
"yui",
|
|
||||||
"ai"
|
|
||||||
],
|
|
||||||
"default": "normal"
|
|
||||||
},
|
|
||||||
"handle": {
|
|
||||||
"type": "string",
|
|
||||||
"maxLength": 32,
|
|
||||||
"maxGraphemes": 32
|
|
||||||
},
|
|
||||||
"did": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"embed": {
|
|
||||||
"type": "union",
|
|
||||||
"refs": [
|
|
||||||
"app.bsky.embed.images",
|
|
||||||
"app.bsky.embed.external",
|
|
||||||
"app.bsky.embed.record",
|
|
||||||
"app.bsky.embed.recordWithMedia"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "datetime",
|
|
||||||
"description": "Client-declared timestamp when this post was originally created."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "ai.syui.game",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "record",
|
|
||||||
"description": "Record containing a game.",
|
|
||||||
"key": "literal:self",
|
|
||||||
"record": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["account", "createdAt"],
|
|
||||||
"properties": {
|
|
||||||
"account": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "at-uri",
|
|
||||||
"description": "at://verify..."
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "datetime",
|
|
||||||
"description": "Client-declared timestamp when this post was originally created."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "ai.syui.game.character",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "record",
|
|
||||||
"key": "string",
|
|
||||||
"description": "record containing a game character.",
|
|
||||||
"input": {
|
|
||||||
"encoding": "application/json",
|
|
||||||
"record": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"createdAt"
|
|
||||||
],
|
|
||||||
"charactor": {
|
|
||||||
"type": "object",
|
|
||||||
"enum": [
|
|
||||||
"ai",
|
|
||||||
"manny",
|
|
||||||
"quinn",
|
|
||||||
"chinese",
|
|
||||||
"phoenix",
|
|
||||||
"kirin",
|
|
||||||
"leviathan",
|
|
||||||
"wyvern",
|
|
||||||
"cerberus",
|
|
||||||
"dragon",
|
|
||||||
"kitsune",
|
|
||||||
"pegasus"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"season": {
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 0,
|
|
||||||
"maximum": 3,
|
|
||||||
"default": 1
|
|
||||||
},
|
|
||||||
"group": {
|
|
||||||
"type": "string",
|
|
||||||
"default": "fantasy",
|
|
||||||
"enum": [
|
|
||||||
"origin",
|
|
||||||
"fantasy",
|
|
||||||
"animal"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"gender": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"none",
|
|
||||||
"male",
|
|
||||||
"famale"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"fullname": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"nickname": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "datetime",
|
|
||||||
"description": "Client-declared timestamp when this post was originally created."
|
|
||||||
},
|
|
||||||
"updatedAt": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "datetime"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "ai.syui.game.user",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "record",
|
|
||||||
"key": "tid",
|
|
||||||
"description": "Record containing a game user.",
|
|
||||||
"input": {
|
|
||||||
"encoding": "application/json",
|
|
||||||
"record": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["did", "createdAt"],
|
|
||||||
"properties": {
|
|
||||||
"aiten":{
|
|
||||||
"type": "integer",
|
|
||||||
"default": 0
|
|
||||||
},
|
|
||||||
"did": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"login": {
|
|
||||||
"type": "bool"
|
|
||||||
},
|
|
||||||
"limit": {
|
|
||||||
"type": "bool"
|
|
||||||
},
|
|
||||||
"charactor": {
|
|
||||||
"type": "object",
|
|
||||||
"enum": ["ai","cerberus","chinesedragon","dragon","kirin","kitsune","leviathan","pegasus","phoenix"],
|
|
||||||
"properties": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"group":{
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"season":{
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"lv":{
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 1,
|
|
||||||
"maximum": 7,
|
|
||||||
"default": 1
|
|
||||||
},
|
|
||||||
"exp":{
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"rank":{
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 0,
|
|
||||||
"maximum": 7,
|
|
||||||
"default": 0
|
|
||||||
},
|
|
||||||
"mode":{
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 0,
|
|
||||||
"maximum": 7,
|
|
||||||
"default": 0
|
|
||||||
},
|
|
||||||
"hp":{
|
|
||||||
"type": "integer",
|
|
||||||
"maximum": 255,
|
|
||||||
"default": 0
|
|
||||||
},
|
|
||||||
"attach":{
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 1,
|
|
||||||
"maximum": 255,
|
|
||||||
"default": 1
|
|
||||||
},
|
|
||||||
"critical":{
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 0,
|
|
||||||
"maximum": 255,
|
|
||||||
"default": 0
|
|
||||||
},
|
|
||||||
"critical_d":{
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 0,
|
|
||||||
"maximum": 255,
|
|
||||||
"default": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "datetime",
|
|
||||||
"description": "Client-declared timestamp when this post was originally created."
|
|
||||||
},
|
|
||||||
"updatedAt": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "datetime"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "ai.syui.o.comment",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "record",
|
|
||||||
"description": "Record containing a Frontpage comment.",
|
|
||||||
"key": "tid",
|
|
||||||
"record": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["content", "createdAt", "post"],
|
|
||||||
"properties": {
|
|
||||||
"content": {
|
|
||||||
"type": "string",
|
|
||||||
"maxLength": 100000,
|
|
||||||
"maxGraphemes": 10000,
|
|
||||||
"description": "The content of the comment."
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "datetime",
|
|
||||||
"description": "Client-declared timestamp when this comment was originally created."
|
|
||||||
},
|
|
||||||
"parent": { "type": "ref", "ref": "com.atproto.repo.strongRef" },
|
|
||||||
"post": { "type": "ref", "ref": "com.atproto.repo.strongRef" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "ai.syui.o.post",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "record",
|
|
||||||
"description": "Record containing a Frontpage post.",
|
|
||||||
"key": "tid",
|
|
||||||
"record": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["title", "url", "createdAt"],
|
|
||||||
"properties": {
|
|
||||||
"title": {
|
|
||||||
"type": "string",
|
|
||||||
"maxLength": 3000,
|
|
||||||
"maxGraphemes": 300,
|
|
||||||
"description": "The title of the post."
|
|
||||||
},
|
|
||||||
"url": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "uri",
|
|
||||||
"description": "The URL of the post."
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "datetime",
|
|
||||||
"description": "Client-declared timestamp when this post was originally created."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "ai.syui.o.vote",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "record",
|
|
||||||
"description": "Record containing a Frontpage vote.",
|
|
||||||
"key": "tid",
|
|
||||||
"record": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["subject", "createdAt"],
|
|
||||||
"properties": {
|
|
||||||
"subject": { "type": "ref", "ref": "com.atproto.repo.strongRef" },
|
|
||||||
"createdAt": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "datetime",
|
|
||||||
"description": "Client-declared timestamp when this vote was originally created."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "com.atproto.repo.applyWrites",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "procedure",
|
|
||||||
"description": "Apply a batch transaction of repository creates, updates, and deletes. Requires auth, implemented by PDS.",
|
|
||||||
"input": {
|
|
||||||
"encoding": "application/json",
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["repo", "writes"],
|
|
||||||
"properties": {
|
|
||||||
"repo": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "at-identifier",
|
|
||||||
"description": "The handle or DID of the repo (aka, current account)."
|
|
||||||
},
|
|
||||||
"validate": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Can be set to 'false' to skip Lexicon schema validation of record data across all operations, 'true' to require it, or leave unset to validate only for known Lexicons."
|
|
||||||
},
|
|
||||||
"writes": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "union",
|
|
||||||
"refs": ["#create", "#update", "#delete"],
|
|
||||||
"closed": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"swapCommit": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "If provided, the entire operation will fail if the current repo commit CID does not match this value. Used to prevent conflicting repo mutations.",
|
|
||||||
"format": "cid"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"output": {
|
|
||||||
"encoding": "application/json",
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [],
|
|
||||||
"properties": {
|
|
||||||
"commit": {
|
|
||||||
"type": "ref",
|
|
||||||
"ref": "com.atproto.repo.defs#commitMeta"
|
|
||||||
},
|
|
||||||
"results": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "union",
|
|
||||||
"refs": ["#createResult", "#updateResult", "#deleteResult"],
|
|
||||||
"closed": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"errors": [
|
|
||||||
{
|
|
||||||
"name": "InvalidSwap",
|
|
||||||
"description": "Indicates that the 'swapCommit' parameter did not match current commit."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"create": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Operation which creates a new record.",
|
|
||||||
"required": ["collection", "value"],
|
|
||||||
"properties": {
|
|
||||||
"collection": { "type": "string", "format": "nsid" },
|
|
||||||
"rkey": { "type": "string", "maxLength": 15 },
|
|
||||||
"value": { "type": "unknown" }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"update": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Operation which updates an existing record.",
|
|
||||||
"required": ["collection", "rkey", "value"],
|
|
||||||
"properties": {
|
|
||||||
"collection": { "type": "string", "format": "nsid" },
|
|
||||||
"rkey": { "type": "string" },
|
|
||||||
"value": { "type": "unknown" }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"delete": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Operation which deletes an existing record.",
|
|
||||||
"required": ["collection", "rkey"],
|
|
||||||
"properties": {
|
|
||||||
"collection": { "type": "string", "format": "nsid" },
|
|
||||||
"rkey": { "type": "string" }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"createResult": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["uri", "cid"],
|
|
||||||
"properties": {
|
|
||||||
"uri": { "type": "string", "format": "at-uri" },
|
|
||||||
"cid": { "type": "string", "format": "cid" },
|
|
||||||
"validationStatus": {
|
|
||||||
"type": "string",
|
|
||||||
"knownValues": ["valid", "unknown"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"updateResult": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["uri", "cid"],
|
|
||||||
"properties": {
|
|
||||||
"uri": { "type": "string", "format": "at-uri" },
|
|
||||||
"cid": { "type": "string", "format": "cid" },
|
|
||||||
"validationStatus": {
|
|
||||||
"type": "string",
|
|
||||||
"knownValues": ["valid", "unknown"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"deleteResult": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [],
|
|
||||||
"properties": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "com.atproto.repo.createRecord",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "procedure",
|
|
||||||
"description": "Create a single new repository record. Requires auth, implemented by PDS.",
|
|
||||||
"input": {
|
|
||||||
"encoding": "application/json",
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["repo", "collection", "record"],
|
|
||||||
"properties": {
|
|
||||||
"repo": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "at-identifier",
|
|
||||||
"description": "The handle or DID of the repo (aka, current account)."
|
|
||||||
},
|
|
||||||
"collection": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "nsid",
|
|
||||||
"description": "The NSID of the record collection."
|
|
||||||
},
|
|
||||||
"rkey": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The Record Key.",
|
|
||||||
"maxLength": 15
|
|
||||||
},
|
|
||||||
"validate": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons."
|
|
||||||
},
|
|
||||||
"record": {
|
|
||||||
"type": "unknown",
|
|
||||||
"description": "The record itself. Must contain a $type field."
|
|
||||||
},
|
|
||||||
"swapCommit": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "cid",
|
|
||||||
"description": "Compare and swap with the previous commit by CID."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"output": {
|
|
||||||
"encoding": "application/json",
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["uri", "cid"],
|
|
||||||
"properties": {
|
|
||||||
"uri": { "type": "string", "format": "at-uri" },
|
|
||||||
"cid": { "type": "string", "format": "cid" },
|
|
||||||
"commit": {
|
|
||||||
"type": "ref",
|
|
||||||
"ref": "com.atproto.repo.defs#commitMeta"
|
|
||||||
},
|
|
||||||
"validationStatus": {
|
|
||||||
"type": "string",
|
|
||||||
"knownValues": ["valid", "unknown"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"errors": [
|
|
||||||
{
|
|
||||||
"name": "InvalidSwap",
|
|
||||||
"description": "Indicates that 'swapCommit' didn't match current repo commit."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "com.atproto.repo.defs",
|
|
||||||
"defs": {
|
|
||||||
"commitMeta": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["cid", "rev"],
|
|
||||||
"properties": {
|
|
||||||
"cid": { "type": "string", "format": "cid" },
|
|
||||||
"rev": { "type": "string" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "com.atproto.repo.deleteRecord",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "procedure",
|
|
||||||
"description": "Delete a repository record, or ensure it doesn't exist. Requires auth, implemented by PDS.",
|
|
||||||
"input": {
|
|
||||||
"encoding": "application/json",
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["repo", "collection", "rkey"],
|
|
||||||
"properties": {
|
|
||||||
"repo": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "at-identifier",
|
|
||||||
"description": "The handle or DID of the repo (aka, current account)."
|
|
||||||
},
|
|
||||||
"collection": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "nsid",
|
|
||||||
"description": "The NSID of the record collection."
|
|
||||||
},
|
|
||||||
"rkey": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The Record Key."
|
|
||||||
},
|
|
||||||
"swapRecord": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "cid",
|
|
||||||
"description": "Compare and swap with the previous record by CID."
|
|
||||||
},
|
|
||||||
"swapCommit": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "cid",
|
|
||||||
"description": "Compare and swap with the previous commit by CID."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"output": {
|
|
||||||
"encoding": "application/json",
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"commit": {
|
|
||||||
"type": "ref",
|
|
||||||
"ref": "com.atproto.repo.defs#commitMeta"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"errors": [{ "name": "InvalidSwap" }]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "com.atproto.repo.describeRepo",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "query",
|
|
||||||
"description": "Get information about an account and repository, including the list of collections. Does not require auth.",
|
|
||||||
"parameters": {
|
|
||||||
"type": "params",
|
|
||||||
"required": ["repo"],
|
|
||||||
"properties": {
|
|
||||||
"repo": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "at-identifier",
|
|
||||||
"description": "The handle or DID of the repo."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"output": {
|
|
||||||
"encoding": "application/json",
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"handle",
|
|
||||||
"did",
|
|
||||||
"didDoc",
|
|
||||||
"collections",
|
|
||||||
"handleIsCorrect"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"handle": { "type": "string", "format": "handle" },
|
|
||||||
"did": { "type": "string", "format": "did" },
|
|
||||||
"didDoc": {
|
|
||||||
"type": "unknown",
|
|
||||||
"description": "The complete DID document for this account."
|
|
||||||
},
|
|
||||||
"collections": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "List of all the collections (NSIDs) for which this repo contains at least one record.",
|
|
||||||
"items": { "type": "string", "format": "nsid" }
|
|
||||||
},
|
|
||||||
"handleIsCorrect": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Indicates if handle is currently valid (resolves bi-directionally)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "com.atproto.repo.getRecord",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "query",
|
|
||||||
"description": "Get a single record from a repository. Does not require auth.",
|
|
||||||
"parameters": {
|
|
||||||
"type": "params",
|
|
||||||
"required": ["repo", "collection", "rkey"],
|
|
||||||
"properties": {
|
|
||||||
"repo": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "at-identifier",
|
|
||||||
"description": "The handle or DID of the repo."
|
|
||||||
},
|
|
||||||
"collection": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "nsid",
|
|
||||||
"description": "The NSID of the record collection."
|
|
||||||
},
|
|
||||||
"rkey": { "type": "string", "description": "The Record Key." },
|
|
||||||
"cid": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "cid",
|
|
||||||
"description": "The CID of the version of the record. If not specified, then return the most recent version."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"output": {
|
|
||||||
"encoding": "application/json",
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["uri", "value"],
|
|
||||||
"properties": {
|
|
||||||
"uri": { "type": "string", "format": "at-uri" },
|
|
||||||
"cid": { "type": "string", "format": "cid" },
|
|
||||||
"value": { "type": "unknown" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"errors": [{ "name": "RecordNotFound" }]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "com.atproto.repo.importRepo",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "procedure",
|
|
||||||
"description": "Import a repo in the form of a CAR file. Requires Content-Length HTTP header to be set.",
|
|
||||||
"input": {
|
|
||||||
"encoding": "application/vnd.ipld.car"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "com.atproto.repo.listMissingBlobs",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "query",
|
|
||||||
"description": "Returns a list of missing blobs for the requesting account. Intended to be used in the account migration flow.",
|
|
||||||
"parameters": {
|
|
||||||
"type": "params",
|
|
||||||
"properties": {
|
|
||||||
"limit": {
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 1,
|
|
||||||
"maximum": 1000,
|
|
||||||
"default": 500
|
|
||||||
},
|
|
||||||
"cursor": { "type": "string" }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"output": {
|
|
||||||
"encoding": "application/json",
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["blobs"],
|
|
||||||
"properties": {
|
|
||||||
"cursor": { "type": "string" },
|
|
||||||
"blobs": {
|
|
||||||
"type": "array",
|
|
||||||
"items": { "type": "ref", "ref": "#recordBlob" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"recordBlob": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["cid", "recordUri"],
|
|
||||||
"properties": {
|
|
||||||
"cid": { "type": "string", "format": "cid" },
|
|
||||||
"recordUri": { "type": "string", "format": "at-uri" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "com.atproto.repo.listRecords",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "query",
|
|
||||||
"description": "List a range of records in a repository, matching a specific collection. Does not require auth.",
|
|
||||||
"parameters": {
|
|
||||||
"type": "params",
|
|
||||||
"required": ["repo", "collection"],
|
|
||||||
"properties": {
|
|
||||||
"repo": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "at-identifier",
|
|
||||||
"description": "The handle or DID of the repo."
|
|
||||||
},
|
|
||||||
"collection": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "nsid",
|
|
||||||
"description": "The NSID of the record type."
|
|
||||||
},
|
|
||||||
"limit": {
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 1,
|
|
||||||
"maximum": 100,
|
|
||||||
"default": 50,
|
|
||||||
"description": "The number of records to return."
|
|
||||||
},
|
|
||||||
"cursor": { "type": "string" },
|
|
||||||
"rkeyStart": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "DEPRECATED: The lowest sort-ordered rkey to start from (exclusive)"
|
|
||||||
},
|
|
||||||
"rkeyEnd": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "DEPRECATED: The highest sort-ordered rkey to stop at (exclusive)"
|
|
||||||
},
|
|
||||||
"reverse": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Flag to reverse the order of the returned records."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"output": {
|
|
||||||
"encoding": "application/json",
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["records"],
|
|
||||||
"properties": {
|
|
||||||
"cursor": { "type": "string" },
|
|
||||||
"records": {
|
|
||||||
"type": "array",
|
|
||||||
"items": { "type": "ref", "ref": "#record" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"record": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["uri", "cid", "value"],
|
|
||||||
"properties": {
|
|
||||||
"uri": { "type": "string", "format": "at-uri" },
|
|
||||||
"cid": { "type": "string", "format": "cid" },
|
|
||||||
"value": { "type": "unknown" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "com.atproto.repo.putRecord",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "procedure",
|
|
||||||
"description": "Write a repository record, creating or updating it as needed. Requires auth, implemented by PDS.",
|
|
||||||
"input": {
|
|
||||||
"encoding": "application/json",
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["repo", "collection", "rkey", "record"],
|
|
||||||
"nullable": ["swapRecord"],
|
|
||||||
"properties": {
|
|
||||||
"repo": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "at-identifier",
|
|
||||||
"description": "The handle or DID of the repo (aka, current account)."
|
|
||||||
},
|
|
||||||
"collection": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "nsid",
|
|
||||||
"description": "The NSID of the record collection."
|
|
||||||
},
|
|
||||||
"rkey": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The Record Key.",
|
|
||||||
"maxLength": 15
|
|
||||||
},
|
|
||||||
"validate": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons."
|
|
||||||
},
|
|
||||||
"record": {
|
|
||||||
"type": "unknown",
|
|
||||||
"description": "The record to write."
|
|
||||||
},
|
|
||||||
"swapRecord": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "cid",
|
|
||||||
"description": "Compare and swap with the previous record by CID. WARNING: nullable and optional field; may cause problems with golang implementation"
|
|
||||||
},
|
|
||||||
"swapCommit": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "cid",
|
|
||||||
"description": "Compare and swap with the previous commit by CID."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"output": {
|
|
||||||
"encoding": "application/json",
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["uri", "cid"],
|
|
||||||
"properties": {
|
|
||||||
"uri": { "type": "string", "format": "at-uri" },
|
|
||||||
"cid": { "type": "string", "format": "cid" },
|
|
||||||
"commit": {
|
|
||||||
"type": "ref",
|
|
||||||
"ref": "com.atproto.repo.defs#commitMeta"
|
|
||||||
},
|
|
||||||
"validationStatus": {
|
|
||||||
"type": "string",
|
|
||||||
"knownValues": ["valid", "unknown"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"errors": [{ "name": "InvalidSwap" }]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "com.atproto.repo.strongRef",
|
|
||||||
"description": "A URI with a content-hash fingerprint.",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["uri", "cid"],
|
|
||||||
"properties": {
|
|
||||||
"uri": { "type": "string", "format": "at-uri" },
|
|
||||||
"cid": { "type": "string", "format": "cid" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "com.atproto.repo.uploadBlob",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "procedure",
|
|
||||||
"description": "Upload a new blob, to be referenced from a repository record. The blob will be deleted if it is not referenced within a time window (eg, minutes). Blob restrictions (mimetype, size, etc) are enforced when the reference is created. Requires auth, implemented by PDS.",
|
|
||||||
"input": {
|
|
||||||
"encoding": "*/*"
|
|
||||||
},
|
|
||||||
"output": {
|
|
||||||
"encoding": "application/json",
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["blob"],
|
|
||||||
"properties": {
|
|
||||||
"blob": { "type": "blob" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
119
patching/120-ozone-runtimeEnvVars.diff
Normal file
119
patching/120-ozone-runtimeEnvVars.diff
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
diff --git a/app/layout.tsx b/app/layout.tsx
|
||||||
|
index bfc3470..9350629 100644
|
||||||
|
--- a/app/layout.tsx
|
||||||
|
+++ b/app/layout.tsx
|
||||||
|
@@ -5,6 +5,7 @@ import 'yet-another-react-lightbox/styles.css'
|
||||||
|
import 'yet-another-react-lightbox/plugins/thumbnails.css'
|
||||||
|
import 'yet-another-react-lightbox/plugins/captions.css'
|
||||||
|
import { ToastContainer } from 'react-toastify'
|
||||||
|
+import { PublicEnvScript } from 'next-runtime-env';
|
||||||
|
|
||||||
|
import { Shell } from '@/shell/Shell'
|
||||||
|
import { CommandPaletteRoot } from '@/shell/CommandPalette/Root'
|
||||||
|
@@ -36,6 +37,7 @@ export default function RootLayout({
|
||||||
|
isDarkModeEnabled() ? 'dark' : ''
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
+ <head>
|
||||||
|
<title>Ozone</title>
|
||||||
|
<link
|
||||||
|
rel="icon"
|
||||||
|
@@ -43,6 +45,8 @@ export default function RootLayout({
|
||||||
|
sizes="any"
|
||||||
|
/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
+ <PublicEnvScript />
|
||||||
|
+ </head>
|
||||||
|
<body className="h-full overflow-hidden">
|
||||||
|
<ToastContainer
|
||||||
|
position="bottom-right"
|
||||||
|
diff --git a/environment.d.ts b/environment.d.ts
|
||||||
|
index 7a47cc2..33ab29f 100644
|
||||||
|
--- a/environment.d.ts
|
||||||
|
+++ b/environment.d.ts
|
||||||
|
@@ -9,6 +9,8 @@ declare global {
|
||||||
|
NEXT_PUBLIC_OZONE_SERVICE_DID?: string // e.g. did:plc:xxx#atproto_labeler
|
||||||
|
NEXT_PUBLIC_OZONE_PUBLIC_URL?: string // e.g. https://ozone.example.com (falls back to window.location.origin)
|
||||||
|
NEXT_PUBLIC_SOCIAL_APP_URL?: string // e.g. https://bsky.app
|
||||||
|
+ NEXT_PUBLIC_SOCIAL_APP_DOMAIN?: string // e.g. bsky.app
|
||||||
|
+ NEXT_PUBLIC_HANDLE_RESOLVER_URL?: string // e.g. https://api.bsky.app
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/lib/constants.ts b/lib/constants.ts
|
||||||
|
index fe7c0e8..c286ac6 100644
|
||||||
|
--- a/lib/constants.ts
|
||||||
|
+++ b/lib/constants.ts
|
||||||
|
@@ -1,29 +1,32 @@
|
||||||
|
+import { env } from 'next-runtime-env';
|
||||||
|
+
|
||||||
|
export const OAUTH_SCOPE = 'atproto transition:generic'
|
||||||
|
|
||||||
|
export const OZONE_SERVICE_DID =
|
||||||
|
- process.env.NEXT_PUBLIC_OZONE_SERVICE_DID || undefined
|
||||||
|
+ env('NEXT_PUBLIC_OZONE_SERVICE_DID') || undefined
|
||||||
|
|
||||||
|
export const OZONE_PUBLIC_URL =
|
||||||
|
- process.env.NEXT_PUBLIC_OZONE_PUBLIC_URL || undefined
|
||||||
|
+ env('NEXT_PUBLIC_OZONE_PUBLIC_URL') || undefined
|
||||||
|
|
||||||
|
export const PLC_DIRECTORY_URL =
|
||||||
|
- process.env.NEXT_PUBLIC_PLC_DIRECTORY_URL ||
|
||||||
|
+ env('NEXT_PUBLIC_PLC_DIRECTORY_URL') ||
|
||||||
|
(process.env.NODE_ENV === 'development'
|
||||||
|
? 'http://localhost:2582'
|
||||||
|
: 'https://plc.directory')
|
||||||
|
|
||||||
|
-export const QUEUE_CONFIG = process.env.NEXT_PUBLIC_QUEUE_CONFIG || '{}'
|
||||||
|
+export const QUEUE_CONFIG = env('NEXT_PUBLIC_QUEUE_CONFIG') || '{}'
|
||||||
|
|
||||||
|
-export const QUEUE_SEED = process.env.NEXT_PUBLIC_QUEUE_SEED || ''
|
||||||
|
+export const QUEUE_SEED = env('NEXT_PUBLIC_QUEUE_SEED') || ''
|
||||||
|
|
||||||
|
+export const SOCIAL_APP_DOMAIN = env('NEXT_PUBLIC_SOCIAL_APP_DOMAIN') || 'bsky.app'
|
||||||
|
export const SOCIAL_APP_URL =
|
||||||
|
- process.env.NEXT_PUBLIC_SOCIAL_APP_URL ||
|
||||||
|
+ env('NEXT_PUBLIC_SOCIAL_APP_URL') ||
|
||||||
|
(process.env.NODE_ENV === 'development'
|
||||||
|
? 'http://localhost:2584'
|
||||||
|
- : 'https://bsky.app')
|
||||||
|
+ : `https://${SOCIAL_APP_DOMAIN}`)
|
||||||
|
|
||||||
|
export const HANDLE_RESOLVER_URL =
|
||||||
|
- process.env.NEXT_PUBLIC_HANDLE_RESOLVER_URL ||
|
||||||
|
+ env('NEXT_PUBLIC_HANDLE_RESOLVER_URL') ||
|
||||||
|
(process.env.NODE_ENV === 'development'
|
||||||
|
? 'http://localhost:2584'
|
||||||
|
: 'https://api.bsky.app')
|
||||||
|
diff --git a/lib/util.ts b/lib/util.ts
|
||||||
|
index 0aa4460..ecec7d1 100644
|
||||||
|
--- a/lib/util.ts
|
||||||
|
+++ b/lib/util.ts
|
||||||
|
@@ -1,5 +1,5 @@
|
||||||
|
import { CollectionId } from '@/reports/helpers/subject'
|
||||||
|
-import { SOCIAL_APP_URL } from './constants'
|
||||||
|
+import { SOCIAL_APP_URL, SOCIAL_APP_DOMAIN } from './constants'
|
||||||
|
import { AtUri } from '@atproto/api'
|
||||||
|
|
||||||
|
export function classNames(...classes: (string | undefined)[]) {
|
||||||
|
@@ -57,7 +57,7 @@ export function takesKeyboardEvt(el?: EventTarget | null) {
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
-const blueSkyUrlMatcher = new RegExp('(https?://)?.*bsky.app')
|
||||||
|
+const blueSkyUrlMatcher = new RegExp('(https?://)?.*'+ `${SOCIAL_APP_DOMAIN}`)
|
||||||
|
|
||||||
|
export const isBlueSkyAppUrl = (url: string) => blueSkyUrlMatcher.test(url)
|
||||||
|
|
||||||
|
diff --git a/package.json b/package.json
|
||||||
|
index 8919841..750dce9 100644
|
||||||
|
--- a/package.json
|
||||||
|
+++ b/package.json
|
||||||
|
@@ -37,6 +37,7 @@
|
||||||
|
"kbar": "^0.1.0-beta.45",
|
||||||
|
"lande": "^1.0.10",
|
||||||
|
"next": "15.2.4",
|
||||||
|
+ "next-runtime-env": "^3.2.1",
|
||||||
|
"react": "19.1.0",
|
||||||
|
"react-dom": "19.1.0",
|
||||||
|
"react-dropzone": "^14.3.5",
|
||||||
99
patching/121-ozone-constants-fix.patch
Normal file
99
patching/121-ozone-constants-fix.patch
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
--- a/lib/constants.ts
|
||||||
|
+++ b/lib/constants.ts
|
||||||
|
@@ -1,29 +1,32 @@
|
||||||
|
+import { env } from 'next-runtime-env';
|
||||||
|
+
|
||||||
|
export const OAUTH_SCOPE = 'atproto transition:generic transition:chat.bsky'
|
||||||
|
|
||||||
|
export const OZONE_SERVICE_DID =
|
||||||
|
- process.env.NEXT_PUBLIC_OZONE_SERVICE_DID || undefined
|
||||||
|
+ env('NEXT_PUBLIC_OZONE_SERVICE_DID') || undefined
|
||||||
|
|
||||||
|
export const OZONE_PUBLIC_URL =
|
||||||
|
- process.env.NEXT_PUBLIC_OZONE_PUBLIC_URL || undefined
|
||||||
|
+ env('NEXT_PUBLIC_OZONE_PUBLIC_URL') || undefined
|
||||||
|
|
||||||
|
export const PLC_DIRECTORY_URL =
|
||||||
|
- process.env.NEXT_PUBLIC_PLC_DIRECTORY_URL ||
|
||||||
|
+ env('NEXT_PUBLIC_PLC_DIRECTORY_URL') ||
|
||||||
|
(process.env.NODE_ENV === 'development'
|
||||||
|
? 'http://localhost:2582'
|
||||||
|
: 'https://plc.directory')
|
||||||
|
|
||||||
|
-export const QUEUE_CONFIG = process.env.NEXT_PUBLIC_QUEUE_CONFIG || '{}'
|
||||||
|
+export const QUEUE_CONFIG = env('NEXT_PUBLIC_QUEUE_CONFIG') || '{}'
|
||||||
|
|
||||||
|
-export const QUEUE_SEED = process.env.NEXT_PUBLIC_QUEUE_SEED || ''
|
||||||
|
+export const QUEUE_SEED = env('NEXT_PUBLIC_QUEUE_SEED') || ''
|
||||||
|
|
||||||
|
+export const SOCIAL_APP_DOMAIN = env('NEXT_PUBLIC_SOCIAL_APP_DOMAIN') || 'bsky.app'
|
||||||
|
export const SOCIAL_APP_URL =
|
||||||
|
- process.env.NEXT_PUBLIC_SOCIAL_APP_URL ||
|
||||||
|
+ env('NEXT_PUBLIC_SOCIAL_APP_URL') ||
|
||||||
|
(process.env.NODE_ENV === 'development'
|
||||||
|
? 'http://localhost:2584'
|
||||||
|
- : 'https://bsky.app')
|
||||||
|
+ : `https://${SOCIAL_APP_DOMAIN}`)
|
||||||
|
|
||||||
|
export const HANDLE_RESOLVER_URL =
|
||||||
|
- process.env.NEXT_PUBLIC_HANDLE_RESOLVER_URL ||
|
||||||
|
+ env('NEXT_PUBLIC_HANDLE_RESOLVER_URL') ||
|
||||||
|
(process.env.NODE_ENV === 'development'
|
||||||
|
? 'http://localhost:2584'
|
||||||
|
: 'https://api.bsky.app')
|
||||||
|
@@ -36,25 +39,25 @@
|
||||||
|
|
||||||
|
export const NEW_ACCOUNT_MARKER_THRESHOLD_IN_DAYS = process.env
|
||||||
|
.NEXT_PUBLIC_NEW_ACCOUNT_MARKER_THRESHOLD_IN_DAYS
|
||||||
|
- ? parseInt(process.env.NEXT_PUBLIC_NEW_ACCOUNT_MARKER_THRESHOLD_IN_DAYS)
|
||||||
|
+ ? parseInt(env('NEXT_PUBLIC_NEW_ACCOUNT_MARKER_THRESHOLD_IN_DAYS'))
|
||||||
|
: 7
|
||||||
|
|
||||||
|
export const YOUNG_ACCOUNT_MARKER_THRESHOLD_IN_DAYS = process.env
|
||||||
|
.NEXT_PUBLIC_YOUNG_ACCOUNT_MARKER_THRESHOLD_IN_DAYS
|
||||||
|
- ? parseInt(process.env.NEXT_PUBLIC_YOUNG_ACCOUNT_MARKER_THRESHOLD_IN_DAYS)
|
||||||
|
+ ? parseInt(env('NEXT_PUBLIC_YOUNG_ACCOUNT_MARKER_THRESHOLD_IN_DAYS'))
|
||||||
|
: 30
|
||||||
|
|
||||||
|
export const DOMAINS_ALLOWING_EMAIL_COMMUNICATION = (
|
||||||
|
- process.env.NEXT_PUBLIC_DOMAINS_ALLOWING_EMAIL_COMMUNICATION || ''
|
||||||
|
+ env('NEXT_PUBLIC_DOMAINS_ALLOWING_EMAIL_COMMUNICATION') || ''
|
||||||
|
).split(',')
|
||||||
|
|
||||||
|
export const HIGH_PROFILE_FOLLOWER_THRESHOLD = process.env
|
||||||
|
.NEXT_PUBLIC_HIGH_PROFILE_FOLLOWER_THRESHOLD
|
||||||
|
- ? parseInt(process.env.NEXT_PUBLIC_HIGH_PROFILE_FOLLOWER_THRESHOLD)
|
||||||
|
+ ? parseInt(env('NEXT_PUBLIC_HIGH_PROFILE_FOLLOWER_THRESHOLD'))
|
||||||
|
: Infinity
|
||||||
|
|
||||||
|
export const FALLBACK_VIDEO_URL = (
|
||||||
|
- process.env.NEXT_PUBLIC_FALLBACK_VIDEO_URL || ''
|
||||||
|
+ env('NEXT_PUBLIC_FALLBACK_VIDEO_URL') || ''
|
||||||
|
).split(':')
|
||||||
|
|
||||||
|
// strike to account suspension duration mapping (in hours)
|
||||||
|
@@ -87,18 +90,18 @@
|
||||||
|
|
||||||
|
export const STRIKE_TO_SUSPENSION_DURATION_IN_HOURS =
|
||||||
|
parseStrikeSuspensionConfig(
|
||||||
|
- process.env.NEXT_PUBLIC_STRIKE_SUSPENSION_CONFIG || '',
|
||||||
|
+ env('NEXT_PUBLIC_STRIKE_SUSPENSION_CONFIG') || '',
|
||||||
|
)
|
||||||
|
|
||||||
|
export const AUTOMATED_ACTION_EMAIL_IDS = {
|
||||||
|
warningWithTakedown:
|
||||||
|
- process.env.NEXT_PUBLIC_WARNING_WITH_TAKEDOWN_EMAIL_TEMPLATE_ID,
|
||||||
|
+ env('NEXT_PUBLIC_WARNING_WITH_TAKEDOWN_EMAIL_TEMPLATE_ID'),
|
||||||
|
suspensionWithTakedown:
|
||||||
|
- process.env.NEXT_PUBLIC_SUSPENSION_WITH_TAKEDOWN_EMAIL_TEMPLATE_ID,
|
||||||
|
+ env('NEXT_PUBLIC_SUSPENSION_WITH_TAKEDOWN_EMAIL_TEMPLATE_ID'),
|
||||||
|
suspensionWithoutTakedown:
|
||||||
|
- process.env.NEXT_PUBLIC_SUSPENSION_WITHOUT_TAKEDOWN_EMAIL_TEMPLATE_ID,
|
||||||
|
+ env('NEXT_PUBLIC_SUSPENSION_WITHOUT_TAKEDOWN_EMAIL_TEMPLATE_ID'),
|
||||||
|
permanentTakedown:
|
||||||
|
- process.env.NEXT_PUBLIC_PERMANENT_TAKEDOWN_EMAIL_TEMPLATE_ID,
|
||||||
|
+ env('NEXT_PUBLIC_PERMANENT_TAKEDOWN_EMAIL_TEMPLATE_ID'),
|
||||||
|
takedownWithoutStrike:
|
||||||
|
- process.env.NEXT_PUBLIC_TAKEDOWN_WITHOUT_STRIKE_EMAIL_TEMPLATE_ID,
|
||||||
|
+ env('NEXT_PUBLIC_TAKEDOWN_WITHOUT_STRIKE_EMAIL_TEMPLATE_ID'),
|
||||||
|
}
|
||||||
82
patching/122-ozone-enable-daemon.diff
Normal file
82
patching/122-ozone-enable-daemon.diff
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
diff --git a/service/index.js b/service/index.js
|
||||||
|
index 943c281..7721cd9 100644
|
||||||
|
--- a/service/index.js
|
||||||
|
+++ b/service/index.js
|
||||||
|
@@ -1,5 +1,7 @@
|
||||||
|
const next = require('next')
|
||||||
|
-const {
|
||||||
|
+const ozone = require('@atproto/ozone')
|
||||||
|
+/*
|
||||||
|
+{
|
||||||
|
readEnv,
|
||||||
|
httpLogger,
|
||||||
|
envToCfg,
|
||||||
|
@@ -7,6 +9,7 @@ const {
|
||||||
|
OzoneService,
|
||||||
|
Database,
|
||||||
|
} = require('@atproto/ozone')
|
||||||
|
+*/
|
||||||
|
const pkg = require('@atproto/ozone/package.json')
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
@@ -16,37 +19,48 @@ async function main() {
|
||||||
|
const frontendHandler = frontend.getRequestHandler()
|
||||||
|
await frontend.prepare()
|
||||||
|
// backend
|
||||||
|
- const env = readEnv()
|
||||||
|
+ const env = ozone.readEnv()
|
||||||
|
env.version ??= pkg.version
|
||||||
|
- const config = envToCfg(env)
|
||||||
|
- const secrets = envToSecrets(env)
|
||||||
|
+ const config = ozone.envToCfg(env)
|
||||||
|
+ const secrets = ozone.envToSecrets(env)
|
||||||
|
const migrate = process.env.OZONE_DB_MIGRATE === '1'
|
||||||
|
if (migrate) {
|
||||||
|
- const db = new Database({
|
||||||
|
+ const db = new ozone.Database({
|
||||||
|
url: config.db.postgresUrl,
|
||||||
|
schema: config.db.postgresSchema,
|
||||||
|
})
|
||||||
|
await db.migrateToLatestOrThrow()
|
||||||
|
await db.close()
|
||||||
|
}
|
||||||
|
- const ozone = await OzoneService.create(config, secrets)
|
||||||
|
+ const server = await ozone.OzoneService.create(config, secrets)
|
||||||
|
// setup handlers
|
||||||
|
- ozone.app.get('/.well-known/ozone-metadata.json', (_req, res) => {
|
||||||
|
+ server.app.get('/.well-known/ozone-metadata.json', (_req, res) => {
|
||||||
|
return res.json({
|
||||||
|
- did: ozone.ctx.cfg.service.did,
|
||||||
|
- url: ozone.ctx.cfg.service.publicUrl,
|
||||||
|
- publicKey: ozone.ctx.signingKey.did(),
|
||||||
|
+ did: server.ctx.cfg.service.did,
|
||||||
|
+ url: server.ctx.cfg.service.publicUrl,
|
||||||
|
+ publicKey: server.ctx.signingKey.did(),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
// Note: We must use `use()` here. This should be the last middleware.
|
||||||
|
- ozone.app.use((req, res) => {
|
||||||
|
+ server.app.use((req, res) => {
|
||||||
|
void frontendHandler(req, res, undefined)
|
||||||
|
})
|
||||||
|
// run
|
||||||
|
- const httpServer = await ozone.start()
|
||||||
|
+ const httpServer = await server.start()
|
||||||
|
+ // starts: involve ops from atproto/packages/dev-env/src/ozone.ts >>>
|
||||||
|
+ ozone.httpLogger.info('starts ozone daemon')
|
||||||
|
+ const daemon = await ozone.OzoneDaemon.create(config, secrets)
|
||||||
|
+ await daemon.start()
|
||||||
|
+ //if (process.env.OZONE_ENABLE_EVENT_REVERSER != 'true') // atproto/services/ozone/daemon.js doesn't stop eventReverser
|
||||||
|
+ //{
|
||||||
|
+ // ozone.httpLogger.info('disable ozone daemon eventReverser')
|
||||||
|
+ // await daemon.ctx.eventReverser.destroy()
|
||||||
|
+ //}
|
||||||
|
+ // ends: involve ops from atproto/packages/dev-env/src/ozone.ts <<<
|
||||||
|
+
|
||||||
|
/** @type {import('net').AddressInfo} */
|
||||||
|
const addr = httpServer.address()
|
||||||
|
- httpLogger.info(`Ozone is running at http://localhost:${addr.port}`)
|
||||||
|
+ ozone.httpLogger.info(`Ozone is running at http://localhost:${addr.port}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch(console.error)
|
||||||
28
patching/130-atproto-ozone-enable-daemon-v2.patch
Normal file
28
patching/130-atproto-ozone-enable-daemon-v2.patch
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
--- a/services/ozone/api.js
|
||||||
|
+++ b/services/ozone/api.js
|
||||||
|
@@ -23,6 +23,7 @@
|
||||||
|
Database,
|
||||||
|
OzoneService,
|
||||||
|
envToCfg,
|
||||||
|
+ OzoneDaemon,
|
||||||
|
envToSecrets,
|
||||||
|
httpLogger,
|
||||||
|
readEnv,
|
||||||
|
@@ -79,10 +80,17 @@
|
||||||
|
|
||||||
|
httpLogger.info('ozone is running')
|
||||||
|
|
||||||
|
+ // Start OzoneDaemon for label events
|
||||||
|
+ httpLogger.info('starting ozone daemon')
|
||||||
|
+ const daemon = await OzoneDaemon.create(cfg, secrets)
|
||||||
|
+ await daemon.start()
|
||||||
|
+ httpLogger.info('ozone daemon is running')
|
||||||
|
+
|
||||||
|
// Graceful shutdown (see also https://aws.amazon.com/blogs/containers/graceful-shutdowns-with-ecs/)
|
||||||
|
process.on('SIGTERM', async () => {
|
||||||
|
httpLogger.info('ozone is stopping')
|
||||||
|
|
||||||
|
+ await daemon.destroy()
|
||||||
|
await ozone.destroy()
|
||||||
|
|
||||||
|
httpLogger.info('ozone is stopped')
|
||||||
33
patching/130-atproto-ozone-enable-daemon.patch
Normal file
33
patching/130-atproto-ozone-enable-daemon.patch
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
--- a/services/ozone/api.js
|
||||||
|
+++ b/services/ozone/api.js
|
||||||
|
@@ -20,6 +20,7 @@ const {
|
||||||
|
MultiImageInvalidator,
|
||||||
|
} = require('@atproto/aws')
|
||||||
|
const {
|
||||||
|
Database,
|
||||||
|
OzoneService,
|
||||||
|
+ OzoneDaemon,
|
||||||
|
envToCfg,
|
||||||
|
envToSecrets,
|
||||||
|
httpLogger,
|
||||||
|
@@ -76,10 +77,17 @@ const main = async () => {
|
||||||
|
const ozone = await OzoneService.create(cfg, secrets, { imgInvalidator })
|
||||||
|
|
||||||
|
await ozone.start()
|
||||||
|
|
||||||
|
httpLogger.info('ozone is running')
|
||||||
|
|
||||||
|
+ // Start OzoneDaemon for label events
|
||||||
|
+ httpLogger.info('starting ozone daemon')
|
||||||
|
+ const daemon = await OzoneDaemon.create(cfg, secrets)
|
||||||
|
+ await daemon.start()
|
||||||
|
+ httpLogger.info('ozone daemon is running')
|
||||||
|
+
|
||||||
|
// Graceful shutdown (see also https://aws.amazon.com/blogs/containers/graceful-shutdowns-with-ecs/)
|
||||||
|
process.on('SIGTERM', async () => {
|
||||||
|
httpLogger.info('ozone is stopping')
|
||||||
|
|
||||||
|
+ await daemon.destroy()
|
||||||
|
await ozone.destroy()
|
||||||
|
|
||||||
|
httpLogger.info('ozone is stopped')
|
||||||
160
patching/4367-atproto-services-bsky-api.diff
Normal file
160
patching/4367-atproto-services-bsky-api.diff
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
--- a/services/bsky/api.js 2025-12-03 11:04:54
|
||||||
|
+++ b/services/bsky/api.js 2025-12-03 11:00:02
|
||||||
|
@@ -1,62 +1,105 @@
|
||||||
|
/* eslint-env node */
|
||||||
|
/* eslint-disable import/order */
|
||||||
|
-
|
||||||
|
+// https://github.com/bluesky-social/atproto/blob/main/services/bsky/api.js
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
-const dd = require('dd-trace')
|
||||||
|
+//const dd = require('dd-trace')
|
||||||
|
+//
|
||||||
|
+//dd.tracer
|
||||||
|
+// .init()
|
||||||
|
+// .use('http2', {
|
||||||
|
+// client: true, // calls into dataplane
|
||||||
|
+// server: false,
|
||||||
|
+// })
|
||||||
|
+// .use('express', {
|
||||||
|
+// hooks: {
|
||||||
|
+// request: (span, req) => {
|
||||||
|
+// maintainXrpcResource(span, req)
|
||||||
|
+// },
|
||||||
|
+// },
|
||||||
|
+// })
|
||||||
|
|
||||||
|
-dd.tracer
|
||||||
|
- .init()
|
||||||
|
- .use('http2', {
|
||||||
|
- client: true, // calls into dataplane
|
||||||
|
- server: false,
|
||||||
|
- })
|
||||||
|
- .use('express', {
|
||||||
|
- hooks: {
|
||||||
|
- request: (span, req) => {
|
||||||
|
- maintainXrpcResource(span, req)
|
||||||
|
- },
|
||||||
|
- },
|
||||||
|
- })
|
||||||
|
-
|
||||||
|
// modify tracer in order to track calls to dataplane as a service with proper resource names
|
||||||
|
const DATAPLANE_PREFIX = '/bsky.Service/'
|
||||||
|
-const origStartSpan = dd.tracer._tracer.startSpan
|
||||||
|
-dd.tracer._tracer.startSpan = function (name, options) {
|
||||||
|
- if (
|
||||||
|
- name !== 'http.request' ||
|
||||||
|
- options?.tags?.component !== 'http2' ||
|
||||||
|
- !options?.tags?.['http.url']
|
||||||
|
- ) {
|
||||||
|
- return origStartSpan.call(this, name, options)
|
||||||
|
- }
|
||||||
|
- const uri = new URL(options.tags['http.url'])
|
||||||
|
- if (!uri.pathname.startsWith(DATAPLANE_PREFIX)) {
|
||||||
|
- return origStartSpan.call(this, name, options)
|
||||||
|
- }
|
||||||
|
- options.tags['service.name'] = 'dataplane-bsky'
|
||||||
|
- options.tags['resource.name'] = uri.pathname.slice(DATAPLANE_PREFIX.length)
|
||||||
|
- return origStartSpan.call(this, name, options)
|
||||||
|
-}
|
||||||
|
+//const origStartSpan = dd.tracer._tracer.startSpan
|
||||||
|
+//dd.tracer._tracer.startSpan = function (name, options) {
|
||||||
|
+// if (
|
||||||
|
+// name !== 'http.request' ||
|
||||||
|
+// options?.tags?.component !== 'http2' ||
|
||||||
|
+// !options?.tags?.['http.url']
|
||||||
|
+// ) {
|
||||||
|
+// return origStartSpan.call(this, name, options)
|
||||||
|
+// }
|
||||||
|
+// const uri = new URL(options.tags['http.url'])
|
||||||
|
+// if (!uri.pathname.startsWith(DATAPLANE_PREFIX)) {
|
||||||
|
+// return origStartSpan.call(this, name, options)
|
||||||
|
+// }
|
||||||
|
+// options.tags['service.name'] = 'dataplane-bsky'
|
||||||
|
+// options.tags['resource.name'] = uri.pathname.slice(DATAPLANE_PREFIX.length)
|
||||||
|
+// return origStartSpan.call(this, name, options)
|
||||||
|
+//}
|
||||||
|
|
||||||
|
// Tracer code above must come before anything else
|
||||||
|
const assert = require('node:assert')
|
||||||
|
const cluster = require('node:cluster')
|
||||||
|
const path = require('node:path')
|
||||||
|
|
||||||
|
-const { BskyAppView, ServerConfig } = require('@atproto/bsky')
|
||||||
|
-const { Secp256k1Keypair } = require('@atproto/crypto')
|
||||||
|
+const bsky = require('/app/packages/bsky') // import all bsky features
|
||||||
|
+const { Secp256k1Keypair } = require('/app/packages/crypto')
|
||||||
|
|
||||||
|
const main = async () => {
|
||||||
|
const env = getEnv()
|
||||||
|
- const config = ServerConfig.readEnv()
|
||||||
|
+ const config = bsky.ServerConfig.readEnv()
|
||||||
|
assert(env.serviceSigningKey, 'must set BSKY_SERVICE_SIGNING_KEY')
|
||||||
|
const signingKey = await Secp256k1Keypair.import(env.serviceSigningKey)
|
||||||
|
- const bsky = BskyAppView.create({ config, signingKey })
|
||||||
|
- await bsky.start()
|
||||||
|
+
|
||||||
|
+// starts: involve logics in packages/dev-env/src/bsky.ts >>>>>>>>>>>>>
|
||||||
|
+// Separate migration db in case migration changes some connection state that we need in the tests, e.g. "alter database ... set ..."
|
||||||
|
+ const migrationDb = new bsky.Database({
|
||||||
|
+ url: env.dbPostgresUrl,
|
||||||
|
+ schema: env.dbPostgresSchema,
|
||||||
|
+ })
|
||||||
|
+ if (env.migration) {
|
||||||
|
+ await migrationDb.migrateToOrThrow(env.migration)
|
||||||
|
+ } else {
|
||||||
|
+ await migrationDb.migrateToLatestOrThrow()
|
||||||
|
+ }
|
||||||
|
+ await migrationDb.close()
|
||||||
|
+
|
||||||
|
+ const db = new bsky.Database({
|
||||||
|
+ url: env.dbPostgresUrl,
|
||||||
|
+ schema: env.dbPostgresSchema,
|
||||||
|
+ poolSize: 10,
|
||||||
|
+ })
|
||||||
|
+
|
||||||
|
+ const dataplane = await bsky.DataPlaneServer.create(
|
||||||
|
+ db,
|
||||||
|
+ env.dataplanePort,
|
||||||
|
+ config.didPlcUrl
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ const bsync = await bsky.MockBsync.create(db, env.bsyncPort)
|
||||||
|
+
|
||||||
|
+// ends: involve logics in packages/dev-env/src/bsky.ts <<<<<<<<<<<<<
|
||||||
|
+
|
||||||
|
+ const server = bsky.BskyAppView.create({ config, signingKey })
|
||||||
|
+// starts: involve logics in packages/dev-env/src/bsky.ts >>>>>>>>>>>>>
|
||||||
|
+ const sub = new bsky.RepoSubscription({
|
||||||
|
+ service: env.repoProvider,
|
||||||
|
+ db,
|
||||||
|
+ idResolver: dataplane.idResolver,
|
||||||
|
+ background: new bsky.BackgroundQueue(db),
|
||||||
|
+ })
|
||||||
|
+// ends: involve logics in packages/dev-env/src/bsky.ts <<<<<<<<<<<<<
|
||||||
|
+ await server.start()
|
||||||
|
+ sub.start() // involve logics in packages/dev-env/src/bsky.ts
|
||||||
|
// Graceful shutdown (see also https://aws.amazon.com/blogs/containers/graceful-shutdowns-with-ecs/)
|
||||||
|
const shutdown = async () => {
|
||||||
|
- await bsky.destroy()
|
||||||
|
+ await server.destroy()
|
||||||
|
+ await bsync.destroy()
|
||||||
|
+ await dataplane.destroy()
|
||||||
|
+ await sub.destroy()
|
||||||
|
+ await db.close()
|
||||||
|
}
|
||||||
|
process.on('SIGTERM', shutdown)
|
||||||
|
process.on('disconnect', shutdown) // when clustering
|
||||||
|
@@ -64,6 +107,12 @@
|
||||||
|
|
||||||
|
const getEnv = () => ({
|
||||||
|
serviceSigningKey: process.env.BSKY_SERVICE_SIGNING_KEY || undefined,
|
||||||
|
+ dbPostgresUrl: process.env.BSKY_DB_POSTGRES_URL || undefined,
|
||||||
|
+ dbPostgresSchema: process.env.BSKY_DB_POSTGRES_SCHEMA || undefined,
|
||||||
|
+ dataplanePort : maybeParseInt(process.env.BSKY_DATAPLANE_PORT) || undefined,
|
||||||
|
+ bsyncPort : maybeParseInt(process.env.BSKY_BSYNC_PORT) || undefined,
|
||||||
|
+ migration: process.env.ENABLE_MIGRATIONS === 'true' || undefined,
|
||||||
|
+ repoProvider: process.env.BSKY_REPO_PROVIDER || undefined
|
||||||
|
})
|
||||||
|
|
||||||
|
const maybeParseInt = (str) => {
|
||||||
20
patching/4367-atproto-services-pds-index.diff
Normal file
20
patching/4367-atproto-services-pds-index.diff
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
--- a/services/pds/index.js 2025-12-03 11:04:54
|
||||||
|
+++ b/services/pds/index.js 2025-12-02 22:11:39
|
||||||
|
@@ -1,5 +1,5 @@
|
||||||
|
/* eslint-env node */
|
||||||
|
-
|
||||||
|
+// https://github.com/bluesky-social/atproto/blob/main/services/pds/index.js
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const {
|
||||||
|
@@ -8,8 +8,8 @@
|
||||||
|
envToSecrets,
|
||||||
|
httpLogger,
|
||||||
|
readEnv,
|
||||||
|
-} = require('@atproto/pds')
|
||||||
|
-const pkg = require('@atproto/pds/package.json')
|
||||||
|
+} = require('/app/packages/pds')
|
||||||
|
+const pkg = require('/app/packages/pds/package.json')
|
||||||
|
|
||||||
|
const main = async () => {
|
||||||
|
const env = readEnv()
|
||||||
17
patching/8980-social-app-disable-external-services.diff
Normal file
17
patching/8980-social-app-disable-external-services.diff
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
--- a/src/state/geolocation/const.ts
|
||||||
|
+++ b/src/state/geolocation/const.ts
|
||||||
|
@@ -3,9 +3,10 @@ import {BAPP_CONFIG_DEV_URL, IS_DEV} from '#/env'
|
||||||
|
import {type Device} from '#/storage'
|
||||||
|
|
||||||
|
export const IPCC_URL = `https://bsky.app/ipcc`
|
||||||
|
-export const BAPP_CONFIG_URL_PROD = `https://ip.bsky.app/config`
|
||||||
|
-export const BAPP_CONFIG_URL = IS_DEV
|
||||||
|
- ? (BAPP_CONFIG_DEV_URL ?? BAPP_CONFIG_URL_PROD)
|
||||||
|
- : BAPP_CONFIG_URL_PROD
|
||||||
|
+// Disabled for self-hosted environment to avoid CORS errors
|
||||||
|
+// export const BAPP_CONFIG_URL_PROD = `https://ip.bsky.app/config`
|
||||||
|
+// export const BAPP_CONFIG_URL = IS_DEV
|
||||||
|
+// ? (BAPP_CONFIG_DEV_URL ?? BAPP_CONFIG_URL_PROD)
|
||||||
|
+// : BAPP_CONFIG_URL_PROD
|
||||||
|
+export const BAPP_CONFIG_URL = null
|
||||||
|
export const GEOLOCATION_CONFIG_URL = BAPP_CONFIG_URL
|
||||||
44
patching/8980-social-app-disable-proxy.diff
Normal file
44
patching/8980-social-app-disable-proxy.diff
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
@@ -1,499 +0,0 @@
|
|||||||
diff --git a/packages-rs/drainpipe/docker-compose.yml b/packages-rs/drainpipe/docker-compose.yml
|
|
||||||
index 0e1d2ca..d5e214a 100644
|
|
||||||
--- a/packages-rs/drainpipe/docker-compose.yml
|
|
||||||
+++ b/packages-rs/drainpipe/docker-compose.yml
|
|
||||||
@@ -1,4 +1,3 @@
|
|
||||||
-version: "3"
|
|
||||||
services:
|
|
||||||
drainpipe:
|
|
||||||
build:
|
|
||||||
diff --git a/packages-rs/drainpipe/src/main.rs b/packages-rs/drainpipe/src/main.rs
|
|
||||||
index 21278a5..0a05d06 100644
|
|
||||||
--- a/packages-rs/drainpipe/src/main.rs
|
|
||||||
+++ b/packages-rs/drainpipe/src/main.rs
|
|
||||||
@@ -76,7 +76,7 @@ async fn process(message: Vec<u8>, ctx: &mut Context) -> Result<i64, ProcessErro
|
|
||||||
let frontpage_ops = commit
|
|
||||||
.operations
|
|
||||||
.iter()
|
|
||||||
- .filter(|op| op.path.starts_with("fyi.unravel.frontpage."))
|
|
||||||
+ .filter(|op| op.path.starts_with("ai.syui.o."))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
if !frontpage_ops.is_empty() {
|
|
||||||
process_frontpage_ops(&frontpage_ops, &commit, &ctx)
|
|
||||||
diff --git a/packages/frontpage/app/(app)/_components/post-card.tsx b/packages/frontpage/app/(app)/_components/post-card.tsx
|
|
||||||
index c0720e5..e619a5f 100644
|
|
||||||
--- a/packages/frontpage/app/(app)/_components/post-card.tsx
|
|
||||||
+++ b/packages/frontpage/app/(app)/_components/post-card.tsx
|
|
||||||
@@ -83,7 +83,7 @@ export async function PostCard({
|
|
||||||
votes={votes}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
- <div className="w-full">
|
|
||||||
+ <div className="w-full overflow-hidden">
|
|
||||||
<h2 className="mb-1 text-xl">
|
|
||||||
<a
|
|
||||||
href={url}
|
|
||||||
diff --git a/packages/frontpage/app/(app)/layout.tsx b/packages/frontpage/app/(app)/layout.tsx
|
|
||||||
index 232502d..8340a9f 100644
|
|
||||||
--- a/packages/frontpage/app/(app)/layout.tsx
|
|
||||||
+++ b/packages/frontpage/app/(app)/layout.tsx
|
|
||||||
@@ -31,7 +31,8 @@ export default async function Layout({
|
|
||||||
}) {
|
|
||||||
const session = await getSession();
|
|
||||||
return (
|
|
||||||
- <div className="container mx-auto px-4 md:px-6 pt-4 pb-8 md:py-12 max-w-3xl">
|
|
||||||
+ <div className="container mx-auto px-4 md:px-6 pt-4 pb-8 md:py-12">
|
|
||||||
+ {/* <div className="container mx-auto px-4 md:px-6 pt-4 pb-8 md:py-12 max-w-3xl"> */}
|
|
||||||
<div className="flex place-content-between items-center mb-8">
|
|
||||||
<Link href="/">
|
|
||||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
||||||
@@ -52,6 +53,8 @@ export default async function Layout({
|
|
||||||
|
|
||||||
<main className="mb-6">{children}</main>
|
|
||||||
|
|
||||||
+ <footer> <span className="flex flex-row-reverse"><a href="https://github.com/likeandscribe/frontpage/" className="text-blue-600"><img src="https://raw.githubusercontent.com/likeandscribe/frontpage/refs/heads/main/packages/frontpage/public/frontpage-logo.svg" alt="Frontpage | MIT License | https://github.com/likeandscribe/frontpage/blob/main/LICENSE" className="h-10" /></a></span> <span className="flex justify-center items-center text-gray-500 dark:text-gray-400"> <a href={`https://bsky.app/profile/${FRONTPAGE_ATPROTO_HANDLE}`} className="font-medium text-indigo-600 hover:text-indigo-500 dark:text-indigo-400 dark:hover:text-indigo-300" > @syui.ai </a> </span> </footer>
|
|
||||||
+ {/*
|
|
||||||
<footer className="flex justify-between items-center text-gray-500 dark:text-gray-400">
|
|
||||||
<p>
|
|
||||||
Made by{" "}
|
|
||||||
@@ -59,10 +62,11 @@ export default async function Layout({
|
|
||||||
href={`https://bsky.app/profile/${FRONTPAGE_ATPROTO_HANDLE}`}
|
|
||||||
className="font-medium text-indigo-600 hover:text-indigo-500 dark:text-indigo-400 dark:hover:text-indigo-300"
|
|
||||||
>
|
|
||||||
- @frontpage.fyi <OpenInNewWindowIcon className="inline" />
|
|
||||||
+ @o.syui.ai <OpenInNewWindowIcon className="inline" />
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</footer>
|
|
||||||
+ */}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -141,8 +145,8 @@ async function LoginOrLogout() {
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
- <Button variant="outline" asChild>
|
|
||||||
- <Link href="/login">Login</Link>
|
|
||||||
+ <Button asChild>
|
|
||||||
+ <Link href="/login">@</Link>
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
diff --git a/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/[commentAuthor]/[commentRkey]/page.tsx b/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/[commentAuthor]/[commentRkey]/page.tsx
|
|
||||||
index c9a2883..c50b02f 100644
|
|
||||||
--- a/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/[commentAuthor]/[commentRkey]/page.tsx
|
|
||||||
+++ b/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/[commentAuthor]/[commentRkey]/page.tsx
|
|
||||||
@@ -30,7 +30,7 @@ export async function generateMetadata(props: {
|
|
||||||
description:
|
|
||||||
comment.status === "live" ? truncateText(comment.body, 47) : null,
|
|
||||||
alternates: {
|
|
||||||
- canonical: `https://frontpage.fyi${path}`,
|
|
||||||
+ canonical: `https://o.syui.ai${path}`,
|
|
||||||
},
|
|
||||||
openGraph:
|
|
||||||
comment.status === "live"
|
|
||||||
@@ -40,7 +40,7 @@ export async function generateMetadata(props: {
|
|
||||||
type: "article",
|
|
||||||
publishedTime: comment.createdAt.toISOString(),
|
|
||||||
authors: [`@${handle}`],
|
|
||||||
- url: `https://frontpage.fyi${path}`,
|
|
||||||
+ url: `https://o.syui.ai${path}`,
|
|
||||||
images: [
|
|
||||||
{
|
|
||||||
url: `${path}/og-image`,
|
|
||||||
diff --git a/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/_lib/comment-client.tsx b/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/_lib/comment-client.tsx
|
|
||||||
index 71dd664..954f499 100644
|
|
||||||
--- a/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/_lib/comment-client.tsx
|
|
||||||
+++ b/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/_lib/comment-client.tsx
|
|
||||||
@@ -283,16 +283,12 @@ export function NewComment({
|
|
||||||
ref={textAreaRef}
|
|
||||||
placeholder="Write a comment..."
|
|
||||||
disabled={isPending}
|
|
||||||
- className="resize-y flex-1"
|
|
||||||
+ className=""
|
|
||||||
/>
|
|
||||||
<div className="w-full flex justify-between">
|
|
||||||
- <InputLengthIndicator
|
|
||||||
- length={input.length}
|
|
||||||
- maxLength={MAX_COMMENT_LENGTH}
|
|
||||||
- />
|
|
||||||
- <div className="flex gap-2">
|
|
||||||
+ <div className="w-full">
|
|
||||||
{extraButton}
|
|
||||||
- <Button type="submit" disabled={isPending}>
|
|
||||||
+ <Button type="submit" disabled={isPending} className="w-full">
|
|
||||||
{isPending ? <Spinner /> : "Post"}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
diff --git a/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/layout.tsx b/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/layout.tsx
|
|
||||||
index 517c871..ef73ecb 100644
|
|
||||||
--- a/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/layout.tsx
|
|
||||||
+++ b/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/layout.tsx
|
|
||||||
@@ -29,7 +29,7 @@ export default async function Post(props: {
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
- <main className="mx-auto max-w-4xl space-y-6">
|
|
||||||
+ <main className="mx-auto space-y-1">
|
|
||||||
<PostCard
|
|
||||||
author={post.authorDid}
|
|
||||||
createdAt={post.createdAt}
|
|
||||||
diff --git a/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/page.tsx b/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/page.tsx
|
|
||||||
index a83f810..11003f9 100644
|
|
||||||
--- a/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/page.tsx
|
|
||||||
+++ b/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/page.tsx
|
|
||||||
@@ -20,7 +20,7 @@ export async function generateMetadata(props: {
|
|
||||||
title: post.title,
|
|
||||||
description: "Discuss this post on Frontpage.",
|
|
||||||
alternates: {
|
|
||||||
- canonical: `https://frontpage.fyi${path}`,
|
|
||||||
+ canonical: `https://o.syui.ai${path}`,
|
|
||||||
},
|
|
||||||
openGraph: {
|
|
||||||
title: post.title,
|
|
||||||
@@ -28,7 +28,7 @@ export async function generateMetadata(props: {
|
|
||||||
type: "article",
|
|
||||||
publishedTime: post.createdAt.toISOString(),
|
|
||||||
authors: [`@${handle}`],
|
|
||||||
- url: `https://frontpage.fyi${path}`,
|
|
||||||
+ url: `https://o.syui.ai${path}`,
|
|
||||||
images: [
|
|
||||||
{
|
|
||||||
url: `${path}/og-image`,
|
|
||||||
@@ -45,6 +45,8 @@ export default async function Post(props: { params: Promise<PostPageParams> }) {
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
+
|
|
||||||
+ {/*
|
|
||||||
<LinkAlternateAtUri
|
|
||||||
authority={authorDid}
|
|
||||||
collection={PostCollection}
|
|
||||||
@@ -65,6 +67,71 @@ export default async function Post(props: { params: Promise<PostPageParams> }) {
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
+ */}
|
|
||||||
+
|
|
||||||
+ {params.postAuthor === "syui.ai" && (post.title.includes("live") || post.title.includes("video")) && (
|
|
||||||
+ <div className="flex py-10 max-h-[720px] md:h-screen space-x-8">
|
|
||||||
+ <iframe className="w-full h-[300px] sm:h-[450px] md:h-[630px]
|
|
||||||
+ [&::-webkit-scrollbar]:w-2
|
|
||||||
+ [&::-webkit-scrollbar-track]:bg-gray-100
|
|
||||||
+ [&::-webkit-scrollbar-thumb]:bg-gray-300
|
|
||||||
+ dark:[&::-webkit-scrollbar-track]:bg-neutral-700
|
|
||||||
+ dark:[&::-webkit-scrollbar-thumb]:bg-neutral-500"
|
|
||||||
+ title="stream" src={post.url}>
|
|
||||||
+ </iframe>
|
|
||||||
+ <div className="hidden w-64 hidden-scrollbar md:block md:overflow-y-scroll
|
|
||||||
+ max-h-[600px]
|
|
||||||
+ [&::-webkit-scrollbar]:w-2
|
|
||||||
+ [&::-webkit-scrollbar-track]:bg-gray-100
|
|
||||||
+ [&::-webkit-scrollbar-thumb]:bg-gray-300
|
|
||||||
+ dark:[&::-webkit-scrollbar-track]:bg-neutral-700
|
|
||||||
+ dark:[&::-webkit-scrollbar-thumb]:bg-neutral-500">
|
|
||||||
+ <LinkAlternateAtUri
|
|
||||||
+ authority={authorDid}
|
|
||||||
+ collection={PostCollection}
|
|
||||||
+ rkey={post.rkey}
|
|
||||||
+ />
|
|
||||||
+ <NewComment postRkey={post.rkey} postAuthorDid={authorDid} />
|
|
||||||
+ {comments.map((comment) => (
|
|
||||||
+ <Comment
|
|
||||||
+ key={comment.id}
|
|
||||||
+ comment={comment}
|
|
||||||
+ level={0}
|
|
||||||
+ postAuthorParam={params.postAuthor}
|
|
||||||
+ postRkey={post.rkey}
|
|
||||||
+ />
|
|
||||||
+ ))}
|
|
||||||
+ </div>
|
|
||||||
+ </div>
|
|
||||||
+ )}
|
|
||||||
+ <LinkAlternateAtUri
|
|
||||||
+ authority={authorDid}
|
|
||||||
+ collection={PostCollection}
|
|
||||||
+ rkey={post.rkey}
|
|
||||||
+ />
|
|
||||||
+ {post.status === "live" ? (
|
|
||||||
+ <NewComment postRkey={post.rkey} postAuthorDid={authorDid} />
|
|
||||||
+ ) : (
|
|
||||||
+ <Alert>
|
|
||||||
+ <AlertTitle>This post has been deleted</AlertTitle>
|
|
||||||
+ <AlertDescription>
|
|
||||||
+ Deleted posts cannot receive new comments.
|
|
||||||
+ </AlertDescription>
|
|
||||||
+ </Alert>
|
|
||||||
+ )}
|
|
||||||
+ <div className="flex flex-col gap-6 bg-white">
|
|
||||||
+ {comments.map((comment) => (
|
|
||||||
+ <Comment
|
|
||||||
+ key={comment.id}
|
|
||||||
+ comment={comment}
|
|
||||||
+ level={0}
|
|
||||||
+ postAuthorParam={params.postAuthor}
|
|
||||||
+ postRkey={post.rkey}
|
|
||||||
+ />
|
|
||||||
+ ))}
|
|
||||||
+
|
|
||||||
+ </div>
|
|
||||||
+
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
diff --git a/packages/frontpage/app/(auth)/login/page.tsx b/packages/frontpage/app/(auth)/login/page.tsx
|
|
||||||
index e3165f9..4d661ce 100644
|
|
||||||
--- a/packages/frontpage/app/(auth)/login/page.tsx
|
|
||||||
+++ b/packages/frontpage/app/(auth)/login/page.tsx
|
|
||||||
@@ -14,17 +14,15 @@ export default async function LoginPage() {
|
|
||||||
<div className="w-full max-w-md space-y-6">
|
|
||||||
<div className="text-center">
|
|
||||||
<h2 className="text-3xl font-bold tracking-tight text-gray-900 dark:text-gray-100">
|
|
||||||
- Sign in to Frontpage
|
|
||||||
+ Login with <span className="text-blue-600">at</span>proto
|
|
||||||
</h2>
|
|
||||||
<p className="mt-2 text-sm text-gray-600 dark:text-gray-400">
|
|
||||||
- Don't have an account?{" "}
|
|
||||||
<a
|
|
||||||
href="https://bsky.app/"
|
|
||||||
className="font-medium text-indigo-600 hover:text-indigo-500 dark:text-indigo-400 dark:hover:text-indigo-300"
|
|
||||||
>
|
|
||||||
- Sign up on Bluesky
|
|
||||||
- </a>
|
|
||||||
- , then return here to login.
|
|
||||||
+ Bluesky
|
|
||||||
+ </a> oauth login
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<LoginForm />
|
|
||||||
diff --git a/packages/frontpage/app/api/receive_hook/route.ts b/packages/frontpage/app/api/receive_hook/route.ts
|
|
||||||
index 04bda27..9feb136 100644
|
|
||||||
--- a/packages/frontpage/app/api/receive_hook/route.ts
|
|
||||||
+++ b/packages/frontpage/app/api/receive_hook/route.ts
|
|
||||||
@@ -96,7 +96,7 @@ export async function POST(request: Request) {
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (collection === "fyi.unravel.frontpage.vote") {
|
|
||||||
+ if (collection === "ai.syui.o.vote") {
|
|
||||||
if (op.action === "create") {
|
|
||||||
const hydratedRecord = await atprotoGetRecord({
|
|
||||||
serviceEndpoint: service,
|
|
||||||
diff --git a/packages/frontpage/app/globals.css b/packages/frontpage/app/globals.css
|
|
||||||
index 9abc86b..e22dba5 100644
|
|
||||||
--- a/packages/frontpage/app/globals.css
|
|
||||||
+++ b/packages/frontpage/app/globals.css
|
|
||||||
@@ -13,8 +13,12 @@
|
|
||||||
--popover: 0 0% 100%;
|
|
||||||
--popover-foreground: 222.2 84% 4.9%;
|
|
||||||
|
|
||||||
+ /*
|
|
||||||
--primary: 222.2 47.4% 11.2%;
|
|
||||||
- --primary-foreground: 210 40% 98%;
|
|
||||||
+ --primary-foreground: 210 40% 98%; */
|
|
||||||
+
|
|
||||||
+ --primary: 210 100% 50%; /* HSLカラーで青色を定義 */
|
|
||||||
+ --primary-foreground: 0 0% 100%; /* 白色のテキスト */
|
|
||||||
|
|
||||||
--secondary: 210 40% 96.1%;
|
|
||||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
|
||||||
@@ -67,8 +71,12 @@
|
|
||||||
--popover: 222.2 84% 4.9%;
|
|
||||||
--popover-foreground: 210 40% 98%;
|
|
||||||
|
|
||||||
- --primary: 210 40% 98%;
|
|
||||||
- --primary-foreground: 222.2 47.4% 11.2%;
|
|
||||||
+ /*--primary: 210 40% 98%;
|
|
||||||
+ *--primary-foreground: 222.2 47.4% 11.2%;*/
|
|
||||||
+
|
|
||||||
+ /* ダークモード用に少し明るい青 */
|
|
||||||
+ --primary: 210 100% 60%;
|
|
||||||
+ --primary-foreground: 0 0% 100%;
|
|
||||||
|
|
||||||
--secondary: 217.2 32.6% 17.5%;
|
|
||||||
--secondary-foreground: 210 40% 98%;
|
|
||||||
diff --git a/packages/frontpage/app/layout.tsx b/packages/frontpage/app/layout.tsx
|
|
||||||
index e8b5a39..a9fa945 100644
|
|
||||||
--- a/packages/frontpage/app/layout.tsx
|
|
||||||
+++ b/packages/frontpage/app/layout.tsx
|
|
||||||
@@ -22,13 +22,13 @@ const sourceSans = Source_Sans_3({
|
|
||||||
});
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
- title: "Frontpage",
|
|
||||||
+ title: "o.syui.ai",
|
|
||||||
description: "A federated link aggregator. Your frontpage to the internet.",
|
|
||||||
openGraph: {
|
|
||||||
title: "Frontpage",
|
|
||||||
description: "Your frontpage to the internet.",
|
|
||||||
type: "website",
|
|
||||||
- siteName: "frontpage.fyi",
|
|
||||||
+ siteName: "o.syui.ai",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -53,11 +53,7 @@ export default function Layout({ children }: { children: React.ReactNode }) {
|
|
||||||
<SpeedInsights />
|
|
||||||
<Analytics />
|
|
||||||
</ThemeProvider>
|
|
||||||
- <script
|
|
||||||
- defer
|
|
||||||
- src="https://static.cloudflareinsights.com/beacon.min.js"
|
|
||||||
- data-cf-beacon='{"token": "5e64b32c70b34b1583d863032b03d9ad"}'
|
|
||||||
- />
|
|
||||||
+ {/* <script defer src="https://static.cloudflareinsights.com/beacon.min.js" data-cf-beacon='{"token": "5e64b32c70b34b1583d863032b03d9ad"}' /> */}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
);
|
|
||||||
diff --git a/packages/frontpage/lib/auth.ts b/packages/frontpage/lib/auth.ts
|
|
||||||
index ba161a0..cadfe54 100644
|
|
||||||
--- a/packages/frontpage/lib/auth.ts
|
|
||||||
+++ b/packages/frontpage/lib/auth.ts
|
|
||||||
@@ -33,7 +33,7 @@ import { eq } from "drizzle-orm";
|
|
||||||
import { getDidFromHandleOrDid } from "./data/atproto/identity";
|
|
||||||
import { startSpan } from "@sentry/nextjs";
|
|
||||||
|
|
||||||
-const USER_AGENT = "appview/@frontpage.fyi (@tom-sherman.com)";
|
|
||||||
+const USER_AGENT = "appview/@o.syui.ai (@tom-sherman.com)";
|
|
||||||
|
|
||||||
export const getPrivateJwk = cache(() =>
|
|
||||||
importJWK(JSON.parse(process.env.PRIVATE_JWK!), USER_SESSION_JWT_ALG),
|
|
||||||
diff --git a/packages/frontpage/lib/constants.ts b/packages/frontpage/lib/constants.ts
|
|
||||||
index 59b2de5..8fd68b5 100644
|
|
||||||
--- a/packages/frontpage/lib/constants.ts
|
|
||||||
+++ b/packages/frontpage/lib/constants.ts
|
|
||||||
@@ -1 +1 @@
|
|
||||||
-export const FRONTPAGE_ATPROTO_HANDLE = "frontpage.fyi";
|
|
||||||
+export const FRONTPAGE_ATPROTO_HANDLE = "syui.ai";
|
|
||||||
diff --git a/packages/frontpage/lib/data/atproto/comment.ts b/packages/frontpage/lib/data/atproto/comment.ts
|
|
||||||
index 42dfb3b..ed0d6df 100644
|
|
||||||
--- a/packages/frontpage/lib/data/atproto/comment.ts
|
|
||||||
+++ b/packages/frontpage/lib/data/atproto/comment.ts
|
|
||||||
@@ -11,7 +11,7 @@ import { PostCollection } from "./post";
|
|
||||||
import { DID, getPdsUrl } from "./did";
|
|
||||||
import { MAX_COMMENT_LENGTH } from "../db/constants";
|
|
||||||
|
|
||||||
-export const CommentCollection = "fyi.unravel.frontpage.comment";
|
|
||||||
+export const CommentCollection = "ai.syui.o.comment";
|
|
||||||
|
|
||||||
export const CommentRecord = z.object({
|
|
||||||
content: z.string().max(MAX_COMMENT_LENGTH),
|
|
||||||
diff --git a/packages/frontpage/lib/data/atproto/event.ts b/packages/frontpage/lib/data/atproto/event.ts
|
|
||||||
index 04fb4b0..80a9cb4 100644
|
|
||||||
--- a/packages/frontpage/lib/data/atproto/event.ts
|
|
||||||
+++ b/packages/frontpage/lib/data/atproto/event.ts
|
|
||||||
@@ -9,7 +9,7 @@ import { isDid } from "./did";
|
|
||||||
export const Collection = z.union([
|
|
||||||
z.literal(PostCollection),
|
|
||||||
z.literal(CommentCollection),
|
|
||||||
- z.literal("fyi.unravel.frontpage.vote"),
|
|
||||||
+ z.literal("ai.syui.o.vote"),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const Path = z.string().transform((p, ctx) => {
|
|
||||||
diff --git a/packages/frontpage/lib/data/atproto/post.ts b/packages/frontpage/lib/data/atproto/post.ts
|
|
||||||
index 8d8f930..eec4798 100644
|
|
||||||
--- a/packages/frontpage/lib/data/atproto/post.ts
|
|
||||||
+++ b/packages/frontpage/lib/data/atproto/post.ts
|
|
||||||
@@ -9,7 +9,7 @@ import { DataLayerError } from "../error";
|
|
||||||
import { DID, getPdsUrl } from "./did";
|
|
||||||
import { MAX_POST_TITLE_LENGTH, MAX_POST_URL_LENGTH } from "../db/constants";
|
|
||||||
|
|
||||||
-export const PostCollection = "fyi.unravel.frontpage.post";
|
|
||||||
+export const PostCollection = "ai.syui.o.post";
|
|
||||||
|
|
||||||
export const PostRecord = z.object({
|
|
||||||
title: z.string().max(MAX_POST_TITLE_LENGTH),
|
|
||||||
diff --git a/packages/frontpage/lib/data/atproto/vote.ts b/packages/frontpage/lib/data/atproto/vote.ts
|
|
||||||
index 93bdb78..91a57c0 100644
|
|
||||||
--- a/packages/frontpage/lib/data/atproto/vote.ts
|
|
||||||
+++ b/packages/frontpage/lib/data/atproto/vote.ts
|
|
||||||
@@ -49,7 +49,7 @@ export async function createVote({
|
|
||||||
VoteRecord.parse(record);
|
|
||||||
|
|
||||||
await atprotoCreateRecord({
|
|
||||||
- collection: "fyi.unravel.frontpage.vote",
|
|
||||||
+ collection: "ai.syui.o.vote",
|
|
||||||
record: record,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -58,7 +58,7 @@ export async function deleteVote(rkey: string) {
|
|
||||||
await ensureUser();
|
|
||||||
|
|
||||||
await atprotoDeleteRecord({
|
|
||||||
- collection: "fyi.unravel.frontpage.vote",
|
|
||||||
+ collection: "ai.syui.o.vote",
|
|
||||||
rkey,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
diff --git a/packages/frontpage/lib/data/db/post.ts b/packages/frontpage/lib/data/db/post.ts
|
|
||||||
index 082d8af..4ba3a3c 100644
|
|
||||||
--- a/packages/frontpage/lib/data/db/post.ts
|
|
||||||
+++ b/packages/frontpage/lib/data/db/post.ts
|
|
||||||
@@ -207,13 +207,13 @@ export async function unauthed_createPost({
|
|
||||||
{
|
|
||||||
title: "New post on Frontpage",
|
|
||||||
description: post.title,
|
|
||||||
- url: `https://frontpage.fyi/post/${authorDid}/${rkey}`,
|
|
||||||
+ url: `https://o.syui.ai/post/${authorDid}/${rkey}`,
|
|
||||||
color: 10181046,
|
|
||||||
author: bskyProfile
|
|
||||||
? {
|
|
||||||
name: `@${bskyProfile.handle}`,
|
|
||||||
icon_url: bskyProfile.avatar,
|
|
||||||
- url: `https://frontpage.fyi/profile/${bskyProfile.handle}`,
|
|
||||||
+ url: `https://o.syui.ai/profile/${bskyProfile.handle}`,
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
fields: [
|
|
||||||
diff --git a/packages/frontpage/public/frontpage-logo.svg b/packages/frontpage/public/frontpage-logo.svg
|
|
||||||
index 191ff3a..bd39143 100644
|
|
||||||
--- a/packages/frontpage/public/frontpage-logo.svg
|
|
||||||
+++ b/packages/frontpage/public/frontpage-logo.svg
|
|
||||||
@@ -1,30 +1,16 @@
|
|
||||||
-<svg width="334" height="334" viewBox="0 0 334 334" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
-<style>
|
|
||||||
- .stop-2 {
|
|
||||||
- stop-color: #040818;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- @media (prefers-color-scheme: dark) {
|
|
||||||
- .stop-2 {
|
|
||||||
- stop-color: #fff;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
-</style>
|
|
||||||
-<path d="M95 225.903V101L162 62.0968V32L69 86V241L95 225.903Z" fill="url(#paint0_linear_8_11)" style=""/>
|
|
||||||
-<path d="M147 256.903V132L214 93.0968V63L121 117V272L147 256.903Z" fill="url(#paint1_linear_8_11)" style=""/>
|
|
||||||
-<path d="M266 93V129L204 165V198L266 162V198L204 234V284L173 302V147L266 93Z" fill="url(#paint2_linear_8_11)" style=""/>
|
|
||||||
-<defs>
|
|
||||||
-<linearGradient id="paint0_linear_8_11" x1="69" y1="84.5" x2="205.5" y2="167" gradientUnits="userSpaceOnUse">
|
|
||||||
- <stop stop-color="#2E05FF"/>
|
|
||||||
- <stop class="stop-2" offset="1" />
|
|
||||||
-</linearGradient>
|
|
||||||
-<linearGradient id="paint1_linear_8_11" x1="69" y1="84.5" x2="205.5" y2="167" gradientUnits="userSpaceOnUse">
|
|
||||||
- <stop stop-color="#2E05FF"/>
|
|
||||||
- <stop class="stop-2" offset="1" />
|
|
||||||
-</linearGradient>
|
|
||||||
-<linearGradient id="paint2_linear_8_11" x1="69" y1="84.5" x2="205.5" y2="167" gradientUnits="userSpaceOnUse">
|
|
||||||
- <stop stop-color="#2E05FF"/>
|
|
||||||
- <stop class="stop-2" offset="1" />
|
|
||||||
-</linearGradient>
|
|
||||||
-</defs>
|
|
||||||
+<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
||||||
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1417px" height="1417px" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
||||||
+<g><path style="opacity:1" fill="#303030" d="M 717.5,182.5 C 716.773,186.224 718.106,188.891 721.5,190.5C 729.374,205.903 738.541,220.569 749,234.5C 750.399,237.363 751.399,240.363 752,243.5C 755.595,248.061 759.095,252.728 762.5,257.5C 763.792,259.667 764.625,262 765,264.5C 766.697,265.957 768.197,267.623 769.5,269.5C 773.055,277.685 777.722,285.018 783.5,291.5C 790.166,305.134 798.166,318.134 807.5,330.5C 814.742,342.185 821.742,353.852 828.5,365.5C 844.594,370.003 860.427,375.336 876,381.5C 877.169,382.009 878.002,382.842 878.5,384C 882.957,384.143 886.623,385.81 889.5,389C 891.715,390.044 894.048,390.71 896.5,391C 901.981,393.275 906.981,396.275 911.5,400C 913.518,400.505 915.518,401.005 917.5,401.5C 917.414,402.496 917.748,403.329 918.5,404C 923.387,405.947 928.054,408.114 932.5,410.5C 943.583,419.552 955.25,427.885 967.5,435.5C 979.922,445.75 991.922,456.583 1003.5,468C 1004.5,468.333 1005.5,468.667 1006.5,469C 1007.1,472.436 1009.1,474.269 1012.5,474.5C 1015.38,480.22 1019.55,484.887 1025,488.5C 1025.33,489.5 1025.67,490.5 1026,491.5C 1033.43,499.992 1040.6,508.658 1047.5,517.5C 1123.83,622.989 1147.5,739.989 1118.5,868.5C 1118.67,870.167 1118.83,871.833 1119,873.5C 1121.94,879.062 1125.11,884.395 1128.5,889.5C 1157.69,942.876 1187.19,996.21 1217,1049.5C 1218.4,1050.73 1219.57,1052.06 1220.5,1053.5C 1221.61,1056.18 1221.61,1058.84 1220.5,1061.5C 1147.34,1066.45 1074,1069.95 1000.5,1072C 988.536,1079.45 977.536,1088.28 967.5,1098.5C 956.996,1104.65 946.996,1111.65 937.5,1119.5C 930.045,1122.31 923.378,1126.31 917.5,1131.5C 911.537,1133.48 905.87,1135.98 900.5,1139C 898.015,1142.24 894.681,1143.91 890.5,1144C 889.833,1145.33 888.833,1146.33 887.5,1147C 855.91,1161.47 822.91,1171.64 788.5,1177.5C 782.486,1176.22 776.486,1176.39 770.5,1178C 772.5,1178.33 774.5,1178.67 776.5,1179C 774.618,1179.2 772.952,1179.7 771.5,1180.5C 674.89,1194.18 583.89,1177.51 498.5,1130.5C 493.758,1126.48 488.758,1122.98 483.5,1120C 479.247,1119.45 475.914,1117.45 473.5,1114C 461.022,1107.13 449.689,1098.8 439.5,1089C 438.5,1088.67 437.5,1088.33 436.5,1088C 432.5,1084.06 428.5,1080.06 424.5,1076C 421.495,1074.83 418.495,1073.66 415.5,1072.5C 360.479,1070.72 305.479,1068.22 250.5,1065C 236.756,1064.54 223.089,1063.38 209.5,1061.5C 197.677,1066.34 193.843,1063.01 198,1051.5C 201.275,1047.94 203.775,1043.94 205.5,1039.5C 210.672,1031.16 215.338,1022.49 219.5,1013.5C 238.656,980.53 257.323,947.196 275.5,913.5C 284.581,899.014 292.914,884.014 300.5,868.5C 299.933,866.018 299.266,863.684 298.5,861.5C 274.313,753.989 289.313,652.323 343.5,556.5C 347.461,550.306 351.628,544.306 356,538.5C 357.081,533.423 359.748,529.423 364,526.5C 365.839,522.827 368.006,519.494 370.5,516.5C 416.382,456.734 473.715,411.568 542.5,381C 557.672,374.288 573.339,368.955 589.5,365C 597.23,351.414 605.23,337.914 613.5,324.5C 617.425,319.2 621.258,313.867 625,308.5C 629.774,297.927 635.774,288.26 643,279.5C 644.407,276.137 645.907,272.803 647.5,269.5C 654.247,260.916 660.413,251.916 666,242.5C 666.311,240.444 666.811,238.444 667.5,236.5C 681.05,215.925 693.884,194.925 706,173.5C 707.494,172.253 708.994,172.253 710.5,173.5C 713.186,176.311 715.519,179.311 717.5,182.5 Z"/></g>
|
|
||||||
+<g><path style="opacity:0.057" fill="#ecdf18" d="M 717.5,182.5 C 715.519,179.311 713.186,176.311 710.5,173.5C 708.994,172.253 707.494,172.253 706,173.5C 693.884,194.925 681.05,215.925 667.5,236.5C 666.811,238.444 666.311,240.444 666,242.5C 660.413,251.916 654.247,260.916 647.5,269.5C 645.907,272.803 644.407,276.137 643,279.5C 635.774,288.26 629.774,297.927 625,308.5C 621.258,313.867 617.425,319.2 613.5,324.5C 605.23,337.914 597.23,351.414 589.5,365C 573.339,368.955 557.672,374.288 542.5,381C 473.715,411.568 416.382,456.734 370.5,516.5C 370.629,514.784 370.962,513.117 371.5,511.5C 411.77,458.386 461.77,417.219 521.5,388C 543.036,378.155 565.036,369.488 587.5,362C 626.95,299.212 665.95,236.046 704.5,172.5C 707.167,171.167 709.833,171.167 712.5,172.5C 715.081,175.404 716.748,178.737 717.5,182.5 Z"/></g>
|
|
||||||
+<g><path style="opacity:0.093" fill="#ece018" d="M 717.5,182.5 C 724.112,191.101 730.278,200.101 736,209.5C 766.572,260.563 797.738,311.23 829.5,361.5C 842.569,366.938 855.902,371.772 869.5,376C 886.41,383.122 902.744,391.289 918.5,400.5C 918.5,401.167 918.167,401.5 917.5,401.5C 915.518,401.005 913.518,400.505 911.5,400C 906.981,396.275 901.981,393.275 896.5,391C 894.048,390.71 891.715,390.044 889.5,389C 886.623,385.81 882.957,384.143 878.5,384C 878.002,382.842 877.169,382.009 876,381.5C 860.427,375.336 844.594,370.003 828.5,365.5C 821.742,353.852 814.742,342.185 807.5,330.5C 798.166,318.134 790.166,305.134 783.5,291.5C 777.722,285.018 773.055,277.685 769.5,269.5C 768.197,267.623 766.697,265.957 765,264.5C 764.625,262 763.792,259.667 762.5,257.5C 759.095,252.728 755.595,248.061 752,243.5C 751.399,240.363 750.399,237.363 749,234.5C 738.541,220.569 729.374,205.903 721.5,190.5C 718.106,188.891 716.773,186.224 717.5,182.5 Z"/></g>
|
|
||||||
+<g><path style="opacity:1" fill="#fdfd00" d="M 708.5,295.5 C 710.451,296.716 711.951,298.382 713,300.5C 742.151,349.467 771.818,398.134 802,446.5C 904.901,479.736 977.568,546.069 1020,645.5C 1044.44,709.71 1049.1,775.376 1034,842.5C 1033.33,845.5 1033.33,848.5 1034,851.5C 1061.47,900.436 1088.97,949.436 1116.5,998.5C 1116.02,999.478 1115.36,1000.31 1114.5,1001C 1055.46,1003.3 996.464,1006.3 937.5,1010C 842.928,1091.3 734.928,1116.3 613.5,1085C 563.341,1070.08 519.007,1045.08 480.5,1010C 421.531,1006.38 362.531,1003.38 303.5,1001C 301.022,999.062 300.855,996.895 303,994.5C 330.253,946.328 357.253,897.995 384,849.5C 358.519,733.144 384.852,630.477 463,541.5C 505.106,496.852 555.606,465.519 614.5,447.5C 646.288,397.06 677.621,346.394 708.5,295.5 Z"/></g>
|
|
||||||
+<g><path style="opacity:0.076" fill="#e2d51a" d="M 918.5,400.5 C 967.206,428.035 1009.04,463.701 1044,507.5C 1045.09,509.078 1045.93,510.745 1046.5,512.5C 1047.04,514.117 1047.37,515.784 1047.5,517.5C 1040.6,508.658 1033.43,499.992 1026,491.5C 1025.67,490.5 1025.33,489.5 1025,488.5C 1019.55,484.887 1015.38,480.22 1012.5,474.5C 1009.1,474.269 1007.1,472.436 1006.5,469C 1005.5,468.667 1004.5,468.333 1003.5,468C 991.922,456.583 979.922,445.75 967.5,435.5C 955.25,427.885 943.583,419.552 932.5,410.5C 928.054,408.114 923.387,405.947 918.5,404C 917.748,403.329 917.414,402.496 917.5,401.5C 918.167,401.5 918.5,401.167 918.5,400.5 Z"/></g>
|
|
||||||
+<g><path style="opacity:1" fill="#30302f" d="M 694.5,567.5 C 771.354,565.01 831.521,595.343 875,658.5C 913.837,725.131 915.503,792.798 880,861.5C 836.437,931.265 773.271,964.098 690.5,960C 617.969,951.138 564.802,914.305 531,849.5C 502.746,785.583 505.746,723.25 540,662.5C 576.413,606.246 627.913,574.579 694.5,567.5 Z"/></g>
|
|
||||||
+<g><path style="opacity:0.064" fill="#f6e716" d="M 1046.5,512.5 C 1055.58,523.094 1063.74,534.427 1071,546.5C 1129.23,644.638 1146.23,749.971 1122,862.5C 1121.5,863 1121,863.5 1120.5,864C 1129.42,878.329 1137.42,893.163 1144.5,908.5C 1143.18,908.67 1142.01,908.337 1141,907.5C 1140.49,905.122 1139.82,902.788 1139,900.5C 1136.15,896.81 1133.82,892.81 1132,888.5C 1130.99,889.337 1129.82,889.67 1128.5,889.5C 1125.11,884.395 1121.94,879.062 1119,873.5C 1118.83,871.833 1118.67,870.167 1118.5,868.5C 1147.5,739.989 1123.83,622.989 1047.5,517.5C 1047.37,515.784 1047.04,514.117 1046.5,512.5 Z"/></g>
|
|
||||||
+<g><path style="opacity:0.239" fill="#dccf1d" d="M 298.5,861.5 C 299.266,863.684 299.933,866.018 300.5,868.5C 292.914,884.014 284.581,899.014 275.5,913.5C 274.782,911.863 274.616,910.197 275,908.5C 276.732,906.717 278.232,904.717 279.5,902.5C 279.291,901.914 278.957,901.414 278.5,901C 281.22,896.324 283.72,891.491 286,886.5C 286.777,888.701 287.944,888.701 289.5,886.5C 288.691,884.929 288.357,883.262 288.5,881.5C 289.552,881.649 290.552,881.483 291.5,881C 292.104,878.532 293.438,876.532 295.5,875C 294.703,872.426 295.537,870.259 298,868.5C 298.497,866.19 298.663,863.857 298.5,861.5 Z"/></g>
|
|
||||||
+<g><path style="opacity:0.12" fill="#ecde19" d="M 1144.5,908.5 C 1167.91,948.307 1190.58,988.641 1212.5,1029.5C 1212.34,1032.55 1213.01,1035.38 1214.5,1038C 1214.17,1038.33 1213.83,1038.67 1213.5,1039C 1216.12,1039.58 1216.79,1040.91 1215.5,1043C 1217.86,1043.59 1218.86,1045.09 1218.5,1047.5C 1222.61,1048.49 1223.27,1050.49 1220.5,1053.5C 1219.57,1052.06 1218.4,1050.73 1217,1049.5C 1187.19,996.21 1157.69,942.876 1128.5,889.5C 1129.82,889.67 1130.99,889.337 1132,888.5C 1133.82,892.81 1136.15,896.81 1139,900.5C 1139.82,902.788 1140.49,905.122 1141,907.5C 1142.01,908.337 1143.18,908.67 1144.5,908.5 Z"/></g>
|
|
||||||
+<g><path style="opacity:0.282" fill="#d5c91e" d="M 219.5,1013.5 C 215.338,1022.49 210.672,1031.16 205.5,1039.5C 205.756,1037.21 205.423,1035.04 204.5,1033C 209.614,1028.62 213.114,1023.12 215,1016.5C 216.271,1015.12 217.771,1014.12 219.5,1013.5 Z"/></g>
|
|
||||||
+<g><path style="opacity:0.03" fill="#f3e517" d="M 371.5,511.5 C 370.962,513.117 370.629,514.784 370.5,516.5C 368.006,519.494 365.839,522.827 364,526.5C 359.748,529.423 357.081,533.423 356,538.5C 351.628,544.306 347.461,550.306 343.5,556.5C 289.313,652.323 274.313,753.989 298.5,861.5C 298.663,863.857 298.497,866.19 298,868.5C 295.537,870.259 294.703,872.426 295.5,875C 293.438,876.532 292.104,878.532 291.5,881C 290.552,881.483 289.552,881.649 288.5,881.5C 288.357,883.262 288.691,884.929 289.5,886.5C 287.944,888.701 286.777,888.701 286,886.5C 283.72,891.491 281.22,896.324 278.5,901C 278.957,901.414 279.291,901.914 279.5,902.5C 278.232,904.717 276.732,906.717 275,908.5C 274.616,910.197 274.782,911.863 275.5,913.5C 257.323,947.196 238.656,980.53 219.5,1013.5C 217.771,1014.12 216.271,1015.12 215,1016.5C 213.114,1023.12 209.614,1028.62 204.5,1033C 205.423,1035.04 205.756,1037.21 205.5,1039.5C 203.775,1043.94 201.275,1047.94 198,1051.5C 193.843,1063.01 197.677,1066.34 209.5,1061.5C 223.089,1063.38 236.756,1064.54 250.5,1065C 305.479,1068.22 360.479,1070.72 415.5,1072.5C 418.495,1073.66 421.495,1074.83 424.5,1076C 428.5,1080.06 432.5,1084.06 436.5,1088C 437.5,1088.33 438.5,1088.67 439.5,1089C 449.689,1098.8 461.022,1107.13 473.5,1114C 475.914,1117.45 479.247,1119.45 483.5,1120C 488.758,1122.98 493.758,1126.48 498.5,1130.5C 583.89,1177.51 674.89,1194.18 771.5,1180.5C 777.4,1180.12 783.067,1179.12 788.5,1177.5C 822.91,1171.64 855.91,1161.47 887.5,1147C 888.833,1146.33 889.833,1145.33 890.5,1144C 894.681,1143.91 898.015,1142.24 900.5,1139C 905.87,1135.98 911.537,1133.48 917.5,1131.5C 923.378,1126.31 930.045,1122.31 937.5,1119.5C 946.996,1111.65 956.996,1104.65 967.5,1098.5C 977.536,1088.28 988.536,1079.45 1000.5,1072C 1074,1069.95 1147.34,1066.45 1220.5,1061.5C 1221.61,1058.84 1221.61,1056.18 1220.5,1053.5C 1223.27,1050.49 1222.61,1048.49 1218.5,1047.5C 1218.86,1045.09 1217.86,1043.59 1215.5,1043C 1216.79,1040.91 1216.12,1039.58 1213.5,1039C 1213.83,1038.67 1214.17,1038.33 1214.5,1038C 1213.01,1035.38 1212.34,1032.55 1212.5,1029.5C 1218.28,1038.74 1223.78,1048.08 1229,1057.5C 1231.4,1062.49 1229.9,1065.99 1224.5,1068C 1221.44,1068.26 1218.44,1068.76 1215.5,1069.5C 1213.83,1068.83 1212.17,1068.17 1210.5,1067.5C 1180.44,1069.63 1150.44,1071.63 1120.5,1073.5C 1110.81,1073.47 1101.15,1073.47 1091.5,1073.5C 1059.05,1075.76 1026.71,1077.6 994.5,1079C 913.217,1150.34 818.05,1186.51 709,1187.5C 599.827,1186.84 504.661,1150.84 423.5,1079.5C 400.74,1077.32 377.74,1076.15 354.5,1076C 336.48,1074.62 318.647,1073.45 301,1072.5C 299.699,1072.96 298.366,1073.29 297,1073.5C 267.186,1071.67 237.353,1069.67 207.5,1067.5C 201.897,1069.4 196.231,1069.24 190.5,1067C 188.406,1065.74 187.406,1063.91 187.5,1061.5C 188.453,1057.6 189.953,1053.93 192,1050.5C 227.124,988.791 261.957,926.791 296.5,864.5C 271.3,753.389 287.133,648.723 344,550.5C 348.667,543.167 353.333,535.833 358,528.5C 362.418,522.603 366.918,516.936 371.5,511.5 Z"/></g>
|
|
||||||
+<g><path style="opacity:1" fill="#4a4730" d="M 788.5,1177.5 C 783.067,1179.12 777.4,1180.12 771.5,1180.5C 772.952,1179.7 774.618,1179.2 776.5,1179C 774.5,1178.67 772.5,1178.33 770.5,1178C 776.486,1176.39 782.486,1176.22 788.5,1177.5 Z"/></g>
|
|
||||||
</svg>
|
|
||||||
@@ -1,295 +0,0 @@
|
|||||||
diff --git a/packages/frontpage/app/(app)/layout.tsx b/packages/frontpage/app/(app)/layout.tsx
|
|
||||||
index 232502d..8340a9f 100644
|
|
||||||
--- a/packages/frontpage/app/(app)/layout.tsx
|
|
||||||
+++ b/packages/frontpage/app/(app)/layout.tsx
|
|
||||||
@@ -31,7 +31,8 @@ export default async function Layout({
|
|
||||||
}) {
|
|
||||||
const session = await getSession();
|
|
||||||
return (
|
|
||||||
- <div className="container mx-auto px-4 md:px-6 pt-4 pb-8 md:py-12 max-w-3xl">
|
|
||||||
+ <div className="container mx-auto px-4 md:px-6 pt-4 pb-8 md:py-12">
|
|
||||||
+ {/* <div className="container mx-auto px-4 md:px-6 pt-4 pb-8 md:py-12 max-w-3xl"> */}
|
|
||||||
<div className="flex place-content-between items-center mb-8">
|
|
||||||
<Link href="/">
|
|
||||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
||||||
@@ -52,6 +53,8 @@ export default async function Layout({
|
|
||||||
|
|
||||||
<main className="mb-6">{children}</main>
|
|
||||||
|
|
||||||
+ <footer> <span className="flex flex-row-reverse"><a href="https://github.com/likeandscribe/frontpage/" className="text-blue-600"><img src="https://raw.githubusercontent.com/likeandscribe/frontpage/refs/heads/main/packages/frontpage/public/frontpage-logo.svg" alt="Frontpage | MIT License | https://github.com/likeandscribe/frontpage/blob/main/LICENSE" className="h-10" /></a></span> <span className="flex justify-center items-center text-gray-500 dark:text-gray-400"> <a href={`https://bsky.app/profile/${FRONTPAGE_ATPROTO_HANDLE}`} className="font-medium text-indigo-600 hover:text-indigo-500 dark:text-indigo-400 dark:hover:text-indigo-300" > @syui.ai </a> </span> </footer>
|
|
||||||
+ {/*
|
|
||||||
<footer className="flex justify-between items-center text-gray-500 dark:text-gray-400">
|
|
||||||
<p>
|
|
||||||
Made by{" "}
|
|
||||||
@@ -59,10 +62,11 @@ export default async function Layout({
|
|
||||||
href={`https://bsky.app/profile/${FRONTPAGE_ATPROTO_HANDLE}`}
|
|
||||||
className="font-medium text-indigo-600 hover:text-indigo-500 dark:text-indigo-400 dark:hover:text-indigo-300"
|
|
||||||
>
|
|
||||||
- @frontpage.fyi <OpenInNewWindowIcon className="inline" />
|
|
||||||
+ @o.syui.ai <OpenInNewWindowIcon className="inline" />
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</footer>
|
|
||||||
+ */}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -141,8 +145,8 @@ async function LoginOrLogout() {
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
- <Button variant="outline" asChild>
|
|
||||||
- <Link href="/login">Login</Link>
|
|
||||||
+ <Button asChild>
|
|
||||||
+ <Link href="/login">@</Link>
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
diff --git a/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/_lib/comment-client.tsx b/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/_lib/comment-client.tsx
|
|
||||||
index 71dd664..46ab83a 100644
|
|
||||||
--- a/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/_lib/comment-client.tsx
|
|
||||||
+++ b/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/_lib/comment-client.tsx
|
|
||||||
@@ -283,16 +283,16 @@ export function NewComment({
|
|
||||||
ref={textAreaRef}
|
|
||||||
placeholder="Write a comment..."
|
|
||||||
disabled={isPending}
|
|
||||||
- className="resize-y flex-1"
|
|
||||||
+ className=""
|
|
||||||
/>
|
|
||||||
<div className="w-full flex justify-between">
|
|
||||||
<InputLengthIndicator
|
|
||||||
length={input.length}
|
|
||||||
maxLength={MAX_COMMENT_LENGTH}
|
|
||||||
/>
|
|
||||||
- <div className="flex gap-2">
|
|
||||||
+ <div className="w-full">
|
|
||||||
{extraButton}
|
|
||||||
- <Button type="submit" disabled={isPending}>
|
|
||||||
+ <Button type="submit" disabled={isPending} className="w-full">
|
|
||||||
{isPending ? <Spinner /> : "Post"}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
diff --git a/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/layout.tsx b/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/layout.tsx
|
|
||||||
index 517c871..ef73ecb 100644
|
|
||||||
--- a/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/layout.tsx
|
|
||||||
+++ b/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/layout.tsx
|
|
||||||
@@ -29,7 +29,7 @@ export default async function Post(props: {
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
- <main className="mx-auto max-w-4xl space-y-6">
|
|
||||||
+ <main className="mx-auto space-y-1">
|
|
||||||
<PostCard
|
|
||||||
author={post.authorDid}
|
|
||||||
createdAt={post.createdAt}
|
|
||||||
diff --git a/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/page.tsx b/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/page.tsx
|
|
||||||
index a83f810..11003f9 100644
|
|
||||||
--- a/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/page.tsx
|
|
||||||
+++ b/packages/frontpage/app/(app)/post/[postAuthor]/[postRkey]/page.tsx
|
|
||||||
@@ -20,7 +20,7 @@ export async function generateMetadata(props: {
|
|
||||||
title: post.title,
|
|
||||||
description: "Discuss this post on Frontpage.",
|
|
||||||
alternates: {
|
|
||||||
- canonical: `https://frontpage.fyi${path}`,
|
|
||||||
+ canonical: `https://o.syui.ai${path}`,
|
|
||||||
},
|
|
||||||
openGraph: {
|
|
||||||
title: post.title,
|
|
||||||
@@ -28,7 +28,7 @@ export async function generateMetadata(props: {
|
|
||||||
type: "article",
|
|
||||||
publishedTime: post.createdAt.toISOString(),
|
|
||||||
authors: [`@${handle}`],
|
|
||||||
- url: `https://frontpage.fyi${path}`,
|
|
||||||
+ url: `https://o.syui.ai${path}`,
|
|
||||||
images: [
|
|
||||||
{
|
|
||||||
url: `${path}/og-image`,
|
|
||||||
@@ -45,6 +45,8 @@ export default async function Post(props: { params: Promise<PostPageParams> }) {
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
+
|
|
||||||
+ {/*
|
|
||||||
<LinkAlternateAtUri
|
|
||||||
authority={authorDid}
|
|
||||||
collection={PostCollection}
|
|
||||||
@@ -65,6 +67,71 @@ export default async function Post(props: { params: Promise<PostPageParams> }) {
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
+ */}
|
|
||||||
+
|
|
||||||
+ {params.postAuthor === "syui.ai" && (post.title.includes("live") || post.title.includes("video")) && (
|
|
||||||
+ <div className="flex py-10 max-h-[720px] md:h-screen space-x-8">
|
|
||||||
+ <iframe className="w-full h-[300px] sm:h-[450px] md:h-[630px]
|
|
||||||
+ [&::-webkit-scrollbar]:w-2
|
|
||||||
+ [&::-webkit-scrollbar-track]:bg-gray-100
|
|
||||||
+ [&::-webkit-scrollbar-thumb]:bg-gray-300
|
|
||||||
+ dark:[&::-webkit-scrollbar-track]:bg-neutral-700
|
|
||||||
+ dark:[&::-webkit-scrollbar-thumb]:bg-neutral-500"
|
|
||||||
+ title="stream" src={post.url}>
|
|
||||||
+ </iframe>
|
|
||||||
+ <div className="hidden w-64 hidden-scrollbar md:block md:overflow-y-scroll
|
|
||||||
+ max-h-[600px]
|
|
||||||
+ [&::-webkit-scrollbar]:w-2
|
|
||||||
+ [&::-webkit-scrollbar-track]:bg-gray-100
|
|
||||||
+ [&::-webkit-scrollbar-thumb]:bg-gray-300
|
|
||||||
+ dark:[&::-webkit-scrollbar-track]:bg-neutral-700
|
|
||||||
+ dark:[&::-webkit-scrollbar-thumb]:bg-neutral-500">
|
|
||||||
+ <LinkAlternateAtUri
|
|
||||||
+ authority={authorDid}
|
|
||||||
+ collection={PostCollection}
|
|
||||||
+ rkey={post.rkey}
|
|
||||||
+ />
|
|
||||||
+ <NewComment postRkey={post.rkey} postAuthorDid={authorDid} />
|
|
||||||
+ {comments.map((comment) => (
|
|
||||||
+ <Comment
|
|
||||||
+ key={comment.id}
|
|
||||||
+ comment={comment}
|
|
||||||
+ level={0}
|
|
||||||
+ postAuthorParam={params.postAuthor}
|
|
||||||
+ postRkey={post.rkey}
|
|
||||||
+ />
|
|
||||||
+ ))}
|
|
||||||
+ </div>
|
|
||||||
+ </div>
|
|
||||||
+ )}
|
|
||||||
+ <LinkAlternateAtUri
|
|
||||||
+ authority={authorDid}
|
|
||||||
+ collection={PostCollection}
|
|
||||||
+ rkey={post.rkey}
|
|
||||||
+ />
|
|
||||||
+ {post.status === "live" ? (
|
|
||||||
+ <NewComment postRkey={post.rkey} postAuthorDid={authorDid} />
|
|
||||||
+ ) : (
|
|
||||||
+ <Alert>
|
|
||||||
+ <AlertTitle>This post has been deleted</AlertTitle>
|
|
||||||
+ <AlertDescription>
|
|
||||||
+ Deleted posts cannot receive new comments.
|
|
||||||
+ </AlertDescription>
|
|
||||||
+ </Alert>
|
|
||||||
+ )}
|
|
||||||
+ <div className="flex flex-col gap-6 bg-white">
|
|
||||||
+ {comments.map((comment) => (
|
|
||||||
+ <Comment
|
|
||||||
+ key={comment.id}
|
|
||||||
+ comment={comment}
|
|
||||||
+ level={0}
|
|
||||||
+ postAuthorParam={params.postAuthor}
|
|
||||||
+ postRkey={post.rkey}
|
|
||||||
+ />
|
|
||||||
+ ))}
|
|
||||||
+
|
|
||||||
+ </div>
|
|
||||||
+
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
diff --git a/packages/frontpage/app/(auth)/login/page.tsx b/packages/frontpage/app/(auth)/login/page.tsx
|
|
||||||
index e3165f9..4d661ce 100644
|
|
||||||
--- a/packages/frontpage/app/(auth)/login/page.tsx
|
|
||||||
+++ b/packages/frontpage/app/(auth)/login/page.tsx
|
|
||||||
@@ -14,17 +14,15 @@ export default async function LoginPage() {
|
|
||||||
<div className="w-full max-w-md space-y-6">
|
|
||||||
<div className="text-center">
|
|
||||||
<h2 className="text-3xl font-bold tracking-tight text-gray-900 dark:text-gray-100">
|
|
||||||
- Sign in to Frontpage
|
|
||||||
+ Login with <span className="text-blue-600">at</span>proto
|
|
||||||
</h2>
|
|
||||||
<p className="mt-2 text-sm text-gray-600 dark:text-gray-400">
|
|
||||||
- Don't have an account?{" "}
|
|
||||||
<a
|
|
||||||
href="https://bsky.app/"
|
|
||||||
className="font-medium text-indigo-600 hover:text-indigo-500 dark:text-indigo-400 dark:hover:text-indigo-300"
|
|
||||||
>
|
|
||||||
- Sign up on Bluesky
|
|
||||||
- </a>
|
|
||||||
- , then return here to login.
|
|
||||||
+ Bluesky
|
|
||||||
+ </a> oauth login
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<LoginForm />
|
|
||||||
diff --git a/packages/frontpage/app/globals.css b/packages/frontpage/app/globals.css
|
|
||||||
index 9abc86b..464377c 100644
|
|
||||||
--- a/packages/frontpage/app/globals.css
|
|
||||||
+++ b/packages/frontpage/app/globals.css
|
|
||||||
@@ -13,8 +13,12 @@
|
|
||||||
--popover: 0 0% 100%;
|
|
||||||
--popover-foreground: 222.2 84% 4.9%;
|
|
||||||
|
|
||||||
+ /*
|
|
||||||
--primary: 222.2 47.4% 11.2%;
|
|
||||||
- --primary-foreground: 210 40% 98%;
|
|
||||||
+ --primary-foreground: 210 40% 98%; */
|
|
||||||
+
|
|
||||||
+ --primary: 210 100% 50%; /* HSLカラーで青色を定義 */
|
|
||||||
+ --primary-foreground: 0 0% 100%; /* 白色のテキスト */
|
|
||||||
|
|
||||||
--secondary: 210 40% 96.1%;
|
|
||||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
|
||||||
@@ -67,8 +71,12 @@
|
|
||||||
--popover: 222.2 84% 4.9%;
|
|
||||||
--popover-foreground: 210 40% 98%;
|
|
||||||
|
|
||||||
- --primary: 210 40% 98%;
|
|
||||||
- --primary-foreground: 222.2 47.4% 11.2%;
|
|
||||||
+ /*--primary: 210 40% 98%;
|
|
||||||
+ *--primary-foreground: 222.2 47.4% 11.2%;*/
|
|
||||||
+
|
|
||||||
+ /* ダークモード用に少し明るい青 */
|
|
||||||
+ --primary: 210 100% 60%;
|
|
||||||
+ --primary-foreground: 0 0% 100%;
|
|
||||||
|
|
||||||
--secondary: 217.2 32.6% 17.5%;
|
|
||||||
--secondary-foreground: 210 40% 98%;
|
|
||||||
@@ -89,3 +97,7 @@
|
|
||||||
--input: 217.2 32.6% 17.5%;
|
|
||||||
--ring: 215.4 16.3% 46.9%;
|
|
||||||
}
|
|
||||||
diff --git a/packages/frontpage/app/layout.tsx b/packages/frontpage/app/layout.tsx
|
|
||||||
index e8b5a39..a9fa945 100644
|
|
||||||
--- a/packages/frontpage/app/layout.tsx
|
|
||||||
+++ b/packages/frontpage/app/layout.tsx
|
|
||||||
@@ -22,13 +22,13 @@ const sourceSans = Source_Sans_3({
|
|
||||||
});
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
- title: "Frontpage",
|
|
||||||
+ title: "o.syui.ai",
|
|
||||||
description: "A federated link aggregator. Your frontpage to the internet.",
|
|
||||||
openGraph: {
|
|
||||||
title: "Frontpage",
|
|
||||||
description: "Your frontpage to the internet.",
|
|
||||||
type: "website",
|
|
||||||
- siteName: "frontpage.fyi",
|
|
||||||
+ siteName: "o.syui.ai",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -53,11 +53,7 @@ export default function Layout({ children }: { children: React.ReactNode }) {
|
|
||||||
<SpeedInsights />
|
|
||||||
<Analytics />
|
|
||||||
</ThemeProvider>
|
|
||||||
- <script
|
|
||||||
- defer
|
|
||||||
- src="https://static.cloudflareinsights.com/beacon.min.js"
|
|
||||||
- data-cf-beacon='{"token": "5e64b32c70b34b1583d863032b03d9ad"}'
|
|
||||||
- />
|
|
||||||
+ {/* <script defer src="https://static.cloudflareinsights.com/beacon.min.js" data-cf-beacon='{"token": "5e64b32c70b34b1583d863032b03d9ad"}' /> */}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
);
|
|
||||||
diff --git a/packages/frontpage/app/(app)/_components/post-card.tsx b/packages/frontpage/app/(app)/_components/post-card.tsx
|
|
||||||
index c0720e5..e619a5f 100644
|
|
||||||
--- a/packages/frontpage/app/(app)/_components/post-card.tsx
|
|
||||||
+++ b/packages/frontpage/app/(app)/_components/post-card.tsx
|
|
||||||
@@ -83,7 +83,7 @@ export async function PostCard({
|
|
||||||
votes={votes}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
- <div className="w-full">
|
|
||||||
+ <div className="w-full overflow-hidden">
|
|
||||||
<h2 className="mb-1 text-xl">
|
|
||||||
<a
|
|
||||||
href={url}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "ai.syui.o.comment",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "record",
|
|
||||||
"description": "Record containing a Frontpage comment.",
|
|
||||||
"key": "tid",
|
|
||||||
"record": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["content", "createdAt", "post"],
|
|
||||||
"properties": {
|
|
||||||
"content": {
|
|
||||||
"type": "string",
|
|
||||||
"maxLength": 100000,
|
|
||||||
"maxGraphemes": 10000,
|
|
||||||
"description": "The content of the comment."
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "datetime",
|
|
||||||
"description": "Client-declared timestamp when this comment was originally created."
|
|
||||||
},
|
|
||||||
"parent": { "type": "ref", "ref": "com.atproto.repo.strongRef" },
|
|
||||||
"post": { "type": "ref", "ref": "com.atproto.repo.strongRef" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "ai.syui.o.post",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "record",
|
|
||||||
"description": "Record containing a Frontpage post.",
|
|
||||||
"key": "tid",
|
|
||||||
"record": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["title", "url", "createdAt"],
|
|
||||||
"properties": {
|
|
||||||
"title": {
|
|
||||||
"type": "string",
|
|
||||||
"maxLength": 3000,
|
|
||||||
"maxGraphemes": 300,
|
|
||||||
"description": "The title of the post."
|
|
||||||
},
|
|
||||||
"url": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "uri",
|
|
||||||
"description": "The URL of the post."
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "datetime",
|
|
||||||
"description": "Client-declared timestamp when this post was originally created."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
"lexicon": 1,
|
|
||||||
"id": "ai.syui.o.vote",
|
|
||||||
"defs": {
|
|
||||||
"main": {
|
|
||||||
"type": "record",
|
|
||||||
"description": "Record containing a Frontpage vote.",
|
|
||||||
"key": "tid",
|
|
||||||
"record": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["subject", "createdAt"],
|
|
||||||
"properties": {
|
|
||||||
"subject": { "type": "ref", "ref": "com.atproto.repo.strongRef" },
|
|
||||||
"createdAt": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "datetime",
|
|
||||||
"description": "Client-declared timestamp when this vote was originally created."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
DATABASE_URL="drainpipe.db"
|
|
||||||
FRONTPAGE_CONSUMER_URL="http://${cloudflared}/api/receive_hook"
|
|
||||||
FRONTPAGE_CONSUMER_SECRET=`openssl ecparam --name secp256k1 --genkey --noout --outform DER | tail --bytes=+8 | head --bytes=32 | xxd --plain --cols 32`
|
|
||||||
|
|
||||||
#RELAY_URL=wss://syu.is
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
FROM rust:1.78-alpine AS builder
|
|
||||||
|
|
||||||
RUN apk add libressl-dev musl-dev sqlite-dev
|
|
||||||
|
|
||||||
WORKDIR /usr/src/unravel
|
|
||||||
COPY . .
|
|
||||||
# TODO: Use cargo-chef to cache dependencies compilation independently of the binary
|
|
||||||
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
|
||||||
--mount=type=cache,target=/root/target \
|
|
||||||
cargo build --release --package drainpipe && \
|
|
||||||
# Move the release binary to a folder to be copied to the final image. It can't be copied directly from the target folder because it's in a cache mount
|
|
||||||
# See https://gist.github.com/noelbundick/6922d26667616e2ba5c3aff59f0824cd?permalink_comment_id=4379948#gistcomment-4379948
|
|
||||||
mv ./target/release /root
|
|
||||||
|
|
||||||
FROM alpine:3.14
|
|
||||||
COPY --from=builder /root/release/drainpipe /
|
|
||||||
|
|
||||||
ENV DATABASE_URL="/drainpipedata/drainpipe.db"
|
|
||||||
|
|
||||||
ENTRYPOINT ["/drainpipe"]
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
services:
|
|
||||||
drainpipe:
|
|
||||||
build:
|
|
||||||
dockerfile: ./packages-rs/drainpipe/Dockerfile
|
|
||||||
context: ../../
|
|
||||||
env_file:
|
|
||||||
- ./.env.local
|
|
||||||
volumes:
|
|
||||||
- ./drainpipedata:/drainpipedata
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
FROM node:20
|
|
||||||
|
|
||||||
RUN npm install -g pnpm
|
|
||||||
WORKDIR /app
|
|
||||||
RUN git clone https://github.com/likeandscribe/frontpage
|
|
||||||
WORKDIR /app/frontpage/packages/atproto-browser
|
|
||||||
RUN pnpm i
|
|
||||||
RUN pnpm build
|
|
||||||
|
|
||||||
CMD [ "pnpm", "start"]
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
services:
|
|
||||||
atbrowser:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
ports:
|
|
||||||
- "3000:3000"
|
|
||||||
environment:
|
|
||||||
- WATCHPACK_POLLING=true
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
PRIVATE_JWK=`pnpm exec tsx ./scripts/generate-jwk.mts`
|
|
||||||
PUBLIC_JWK=`pnpm exec tsx ./scripts/generate-jwk.mts`
|
|
||||||
|
|
||||||
TURSO_CONNECTION_URL=libsql://xxx.turso.io
|
|
||||||
#TURSO_CONNECTION_URL=`turso db shell xxx-xxx`
|
|
||||||
TURSO_AUTH_TOKEN=`turso db tokens create xxx-xxx`
|
|
||||||
|
|
||||||
DRAINPIPE_CONSUMER_SECRET=`openssl ecparam --name secp256k1 --genkey --noout --outform DER | tail --bytes=+8 | head --bytes=32 | xxd --plain --cols 32`
|
|
||||||
VERCEL_PROJECT_PRODUCTION_URL=example.com
|
|
||||||
VERCEL_BRANCH_URL=example.com
|
|
||||||
|
|
||||||
#DRAINPIPE_CONSUMER_SECRET=secret
|
|
||||||
#TURSO_CONNECTION_URL=libsql://turso.dev.unravel.fyi
|
|
||||||
#PLC_DIRECTORY_URL=https://plc.dev.unravel.fyi
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
FROM node:20
|
|
||||||
|
|
||||||
RUN npm install -g pnpm
|
|
||||||
WORKDIR /app
|
|
||||||
RUN git clone https://github.com/likeandscribe/frontpage
|
|
||||||
WORKDIR /app/frontpage
|
|
||||||
RUN pnpm i
|
|
||||||
RUN pnpm exec turbo run --affected type-check
|
|
||||||
|
|
||||||
WORKDIR /app/frontpage/packages/frontpage
|
|
||||||
COPY ./.env.local ./.env.local
|
|
||||||
COPY ./app ./app
|
|
||||||
COPY ./lib ./lib
|
|
||||||
RUN pnpm run db:generate
|
|
||||||
RUN pnpm run db:migrate
|
|
||||||
RUN pnpm run build
|
|
||||||
CMD [ "pnpm", "run", "start"]
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
<Button asChild>
|
|
||||||
<Link href="/post/game">Game</Link>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
"use server";
|
|
||||||
|
|
||||||
import { DID } from "@/lib/data/atproto/did";
|
|
||||||
import { getVerifiedHandle } from "@/lib/data/atproto/identity";
|
|
||||||
import { putPost } from "@/lib/data/atproto/game";
|
|
||||||
import { uncached_doesPostExist } from "@/lib/data/db/post";
|
|
||||||
import { DataLayerError } from "@/lib/data/error";
|
|
||||||
import { ensureUser } from "@/lib/data/user";
|
|
||||||
import { redirect } from "next/navigation";
|
|
||||||
|
|
||||||
export async function newPostAction(_prevState: unknown) {
|
|
||||||
"use server";
|
|
||||||
const user = await ensureUser();
|
|
||||||
const [handle] = await Promise.all([
|
|
||||||
getVerifiedHandle(user.did),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const account = `at://did:plc:4hqjfn7m6n5hno3doamuhgef/ai.syui.game.user/${handle}`;
|
|
||||||
try {
|
|
||||||
const { rkey } = await putPost({ account });
|
|
||||||
redirect(`https://at.syu.is/at/${user.did}/ai.syui.game/self`);
|
|
||||||
} catch (error) {
|
|
||||||
if (!(error instanceof DataLayerError)) throw error;
|
|
||||||
return { error: "Failed to create post" };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import { startTransition, useActionState, useId, useState } from "react";
|
|
||||||
import { newPostAction } from "./_action";
|
|
||||||
import { Label } from "@/lib/components/ui/label";
|
|
||||||
import { Input } from "@/lib/components/ui/input";
|
|
||||||
import { Button } from "@/lib/components/ui/button";
|
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/lib/components/ui/alert";
|
|
||||||
import { Spinner } from "@/lib/components/ui/spinner";
|
|
||||||
import { InputLengthIndicator } from "@/lib/components/input-length-indicator";
|
|
||||||
|
|
||||||
export function NewPostButton() {
|
|
||||||
const [state, action, isPending] = useActionState(newPostAction, null);
|
|
||||||
const [error, setError] = useState<string | null>(null);
|
|
||||||
|
|
||||||
const handleClick = async () => {
|
|
||||||
try {
|
|
||||||
const result = await action({});
|
|
||||||
if (result && 'error' in result) {
|
|
||||||
setError(result.error);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Error creating post:', e);
|
|
||||||
setError('予期しないエラーが発生しました');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<button onClick={handleClick} disabled={isPending}>
|
|
||||||
{isPending ? '投稿中...' : '新規投稿'}
|
|
||||||
</button>
|
|
||||||
{error && <p style={{ color: 'red' }}>{error}</p>}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
import { Metadata } from "next";
|
|
||||||
import { NewPostButton } from "./_client";
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
title: "New post | Frontpage",
|
|
||||||
robots: "noindex, nofollow",
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function NewPost() {
|
|
||||||
return (
|
|
||||||
<main className="flex flex-col gap-3">
|
|
||||||
<h2 className="text-3xl font-bold tracking-tight text-gray-900 dark:text-gray-100">
|
|
||||||
</h2>
|
|
||||||
<NewPostButton />
|
|
||||||
</main>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
services:
|
|
||||||
frontpage:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
ports:
|
|
||||||
- "3000:3000"
|
|
||||||
environment:
|
|
||||||
- WATCHPACK_POLLING=true
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
import "server-only";
|
|
||||||
import {
|
|
||||||
atprotoPutRecord,
|
|
||||||
atprotoCreateRecord,
|
|
||||||
atprotoDeleteRecord,
|
|
||||||
atprotoGetRecord,
|
|
||||||
} from "./record";
|
|
||||||
import { z } from "zod";
|
|
||||||
import { DataLayerError } from "../error";
|
|
||||||
import { DID, getPdsUrl } from "./did";
|
|
||||||
|
|
||||||
export const PostCollection = "ai.syui.game";
|
|
||||||
|
|
||||||
export const PostRecord = z.object({
|
|
||||||
account: z.string(),
|
|
||||||
createdAt: z.string(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export type Post = z.infer<typeof PostRecord>;
|
|
||||||
|
|
||||||
type PostInput = {
|
|
||||||
account: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export async function putPost({ account }: PostInput) {
|
|
||||||
const record = { account, createdAt: new Date().toISOString() };
|
|
||||||
PostRecord.parse(record);
|
|
||||||
|
|
||||||
const result = await atprotoPutRecord({
|
|
||||||
rkey: "self",
|
|
||||||
record,
|
|
||||||
collection: PostCollection,
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
rkey: "self",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function deletePost(rkey: string) {
|
|
||||||
await atprotoDeleteRecord({
|
|
||||||
rkey,
|
|
||||||
collection: PostCollection,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getPost({ rkey, repo }: { rkey: string; repo: DID }) {
|
|
||||||
const service = await getPdsUrl(repo);
|
|
||||||
|
|
||||||
if (!service) {
|
|
||||||
throw new DataLayerError("Failed to get service url");
|
|
||||||
}
|
|
||||||
|
|
||||||
const { value } = await atprotoGetRecord({
|
|
||||||
serviceEndpoint: service,
|
|
||||||
repo,
|
|
||||||
collection: PostCollection,
|
|
||||||
rkey,
|
|
||||||
});
|
|
||||||
|
|
||||||
return PostRecord.parse(value);
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
import "server-only";
|
|
||||||
import { z } from "zod";
|
|
||||||
import { ensureUser } from "../user";
|
|
||||||
import { DataLayerError } from "../error";
|
|
||||||
import { fetchAuthenticatedAtproto } from "@/lib/auth";
|
|
||||||
import { AtUri } from "./uri";
|
|
||||||
|
|
||||||
const PutRecordResponse = z.object({
|
|
||||||
uri: AtUri,
|
|
||||||
cid: z.string(),
|
|
||||||
});
|
|
||||||
|
|
||||||
type PutRecordInput = {
|
|
||||||
rkey?: string;
|
|
||||||
record: unknown;
|
|
||||||
collection: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export async function atprotoPutRecord({
|
|
||||||
rkey,
|
|
||||||
record,
|
|
||||||
collection,
|
|
||||||
}: PutRecordInput) {
|
|
||||||
const user = await ensureUser();
|
|
||||||
const pdsUrl = new URL(user.pdsUrl);
|
|
||||||
pdsUrl.pathname = "/xrpc/com.atproto.repo.putRecord";
|
|
||||||
|
|
||||||
const response = await fetchAuthenticatedAtproto(pdsUrl.toString(), {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
rkey: rkey || "self",
|
|
||||||
repo: user.did,
|
|
||||||
collection,
|
|
||||||
validate: false,
|
|
||||||
record: record,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new DataLayerError(`Failed to create record ${response.status}`, {
|
|
||||||
cause: response,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return PutRecordResponse.parse(await response.json());
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1417px" height="1417px" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
||||||
<g><path style="opacity:1" fill="#303030" d="M 717.5,182.5 C 716.773,186.224 718.106,188.891 721.5,190.5C 729.374,205.903 738.541,220.569 749,234.5C 750.399,237.363 751.399,240.363 752,243.5C 755.595,248.061 759.095,252.728 762.5,257.5C 763.792,259.667 764.625,262 765,264.5C 766.697,265.957 768.197,267.623 769.5,269.5C 773.055,277.685 777.722,285.018 783.5,291.5C 790.166,305.134 798.166,318.134 807.5,330.5C 814.742,342.185 821.742,353.852 828.5,365.5C 844.594,370.003 860.427,375.336 876,381.5C 877.169,382.009 878.002,382.842 878.5,384C 882.957,384.143 886.623,385.81 889.5,389C 891.715,390.044 894.048,390.71 896.5,391C 901.981,393.275 906.981,396.275 911.5,400C 913.518,400.505 915.518,401.005 917.5,401.5C 917.414,402.496 917.748,403.329 918.5,404C 923.387,405.947 928.054,408.114 932.5,410.5C 943.583,419.552 955.25,427.885 967.5,435.5C 979.922,445.75 991.922,456.583 1003.5,468C 1004.5,468.333 1005.5,468.667 1006.5,469C 1007.1,472.436 1009.1,474.269 1012.5,474.5C 1015.38,480.22 1019.55,484.887 1025,488.5C 1025.33,489.5 1025.67,490.5 1026,491.5C 1033.43,499.992 1040.6,508.658 1047.5,517.5C 1123.83,622.989 1147.5,739.989 1118.5,868.5C 1118.67,870.167 1118.83,871.833 1119,873.5C 1121.94,879.062 1125.11,884.395 1128.5,889.5C 1157.69,942.876 1187.19,996.21 1217,1049.5C 1218.4,1050.73 1219.57,1052.06 1220.5,1053.5C 1221.61,1056.18 1221.61,1058.84 1220.5,1061.5C 1147.34,1066.45 1074,1069.95 1000.5,1072C 988.536,1079.45 977.536,1088.28 967.5,1098.5C 956.996,1104.65 946.996,1111.65 937.5,1119.5C 930.045,1122.31 923.378,1126.31 917.5,1131.5C 911.537,1133.48 905.87,1135.98 900.5,1139C 898.015,1142.24 894.681,1143.91 890.5,1144C 889.833,1145.33 888.833,1146.33 887.5,1147C 855.91,1161.47 822.91,1171.64 788.5,1177.5C 782.486,1176.22 776.486,1176.39 770.5,1178C 772.5,1178.33 774.5,1178.67 776.5,1179C 774.618,1179.2 772.952,1179.7 771.5,1180.5C 674.89,1194.18 583.89,1177.51 498.5,1130.5C 493.758,1126.48 488.758,1122.98 483.5,1120C 479.247,1119.45 475.914,1117.45 473.5,1114C 461.022,1107.13 449.689,1098.8 439.5,1089C 438.5,1088.67 437.5,1088.33 436.5,1088C 432.5,1084.06 428.5,1080.06 424.5,1076C 421.495,1074.83 418.495,1073.66 415.5,1072.5C 360.479,1070.72 305.479,1068.22 250.5,1065C 236.756,1064.54 223.089,1063.38 209.5,1061.5C 197.677,1066.34 193.843,1063.01 198,1051.5C 201.275,1047.94 203.775,1043.94 205.5,1039.5C 210.672,1031.16 215.338,1022.49 219.5,1013.5C 238.656,980.53 257.323,947.196 275.5,913.5C 284.581,899.014 292.914,884.014 300.5,868.5C 299.933,866.018 299.266,863.684 298.5,861.5C 274.313,753.989 289.313,652.323 343.5,556.5C 347.461,550.306 351.628,544.306 356,538.5C 357.081,533.423 359.748,529.423 364,526.5C 365.839,522.827 368.006,519.494 370.5,516.5C 416.382,456.734 473.715,411.568 542.5,381C 557.672,374.288 573.339,368.955 589.5,365C 597.23,351.414 605.23,337.914 613.5,324.5C 617.425,319.2 621.258,313.867 625,308.5C 629.774,297.927 635.774,288.26 643,279.5C 644.407,276.137 645.907,272.803 647.5,269.5C 654.247,260.916 660.413,251.916 666,242.5C 666.311,240.444 666.811,238.444 667.5,236.5C 681.05,215.925 693.884,194.925 706,173.5C 707.494,172.253 708.994,172.253 710.5,173.5C 713.186,176.311 715.519,179.311 717.5,182.5 Z"/></g>
|
|
||||||
<g><path style="opacity:0.057" fill="#ecdf18" d="M 717.5,182.5 C 715.519,179.311 713.186,176.311 710.5,173.5C 708.994,172.253 707.494,172.253 706,173.5C 693.884,194.925 681.05,215.925 667.5,236.5C 666.811,238.444 666.311,240.444 666,242.5C 660.413,251.916 654.247,260.916 647.5,269.5C 645.907,272.803 644.407,276.137 643,279.5C 635.774,288.26 629.774,297.927 625,308.5C 621.258,313.867 617.425,319.2 613.5,324.5C 605.23,337.914 597.23,351.414 589.5,365C 573.339,368.955 557.672,374.288 542.5,381C 473.715,411.568 416.382,456.734 370.5,516.5C 370.629,514.784 370.962,513.117 371.5,511.5C 411.77,458.386 461.77,417.219 521.5,388C 543.036,378.155 565.036,369.488 587.5,362C 626.95,299.212 665.95,236.046 704.5,172.5C 707.167,171.167 709.833,171.167 712.5,172.5C 715.081,175.404 716.748,178.737 717.5,182.5 Z"/></g>
|
|
||||||
<g><path style="opacity:0.093" fill="#ece018" d="M 717.5,182.5 C 724.112,191.101 730.278,200.101 736,209.5C 766.572,260.563 797.738,311.23 829.5,361.5C 842.569,366.938 855.902,371.772 869.5,376C 886.41,383.122 902.744,391.289 918.5,400.5C 918.5,401.167 918.167,401.5 917.5,401.5C 915.518,401.005 913.518,400.505 911.5,400C 906.981,396.275 901.981,393.275 896.5,391C 894.048,390.71 891.715,390.044 889.5,389C 886.623,385.81 882.957,384.143 878.5,384C 878.002,382.842 877.169,382.009 876,381.5C 860.427,375.336 844.594,370.003 828.5,365.5C 821.742,353.852 814.742,342.185 807.5,330.5C 798.166,318.134 790.166,305.134 783.5,291.5C 777.722,285.018 773.055,277.685 769.5,269.5C 768.197,267.623 766.697,265.957 765,264.5C 764.625,262 763.792,259.667 762.5,257.5C 759.095,252.728 755.595,248.061 752,243.5C 751.399,240.363 750.399,237.363 749,234.5C 738.541,220.569 729.374,205.903 721.5,190.5C 718.106,188.891 716.773,186.224 717.5,182.5 Z"/></g>
|
|
||||||
<g><path style="opacity:1" fill="#fdfd00" d="M 708.5,295.5 C 710.451,296.716 711.951,298.382 713,300.5C 742.151,349.467 771.818,398.134 802,446.5C 904.901,479.736 977.568,546.069 1020,645.5C 1044.44,709.71 1049.1,775.376 1034,842.5C 1033.33,845.5 1033.33,848.5 1034,851.5C 1061.47,900.436 1088.97,949.436 1116.5,998.5C 1116.02,999.478 1115.36,1000.31 1114.5,1001C 1055.46,1003.3 996.464,1006.3 937.5,1010C 842.928,1091.3 734.928,1116.3 613.5,1085C 563.341,1070.08 519.007,1045.08 480.5,1010C 421.531,1006.38 362.531,1003.38 303.5,1001C 301.022,999.062 300.855,996.895 303,994.5C 330.253,946.328 357.253,897.995 384,849.5C 358.519,733.144 384.852,630.477 463,541.5C 505.106,496.852 555.606,465.519 614.5,447.5C 646.288,397.06 677.621,346.394 708.5,295.5 Z"/></g>
|
|
||||||
<g><path style="opacity:0.076" fill="#e2d51a" d="M 918.5,400.5 C 967.206,428.035 1009.04,463.701 1044,507.5C 1045.09,509.078 1045.93,510.745 1046.5,512.5C 1047.04,514.117 1047.37,515.784 1047.5,517.5C 1040.6,508.658 1033.43,499.992 1026,491.5C 1025.67,490.5 1025.33,489.5 1025,488.5C 1019.55,484.887 1015.38,480.22 1012.5,474.5C 1009.1,474.269 1007.1,472.436 1006.5,469C 1005.5,468.667 1004.5,468.333 1003.5,468C 991.922,456.583 979.922,445.75 967.5,435.5C 955.25,427.885 943.583,419.552 932.5,410.5C 928.054,408.114 923.387,405.947 918.5,404C 917.748,403.329 917.414,402.496 917.5,401.5C 918.167,401.5 918.5,401.167 918.5,400.5 Z"/></g>
|
|
||||||
<g><path style="opacity:1" fill="#30302f" d="M 694.5,567.5 C 771.354,565.01 831.521,595.343 875,658.5C 913.837,725.131 915.503,792.798 880,861.5C 836.437,931.265 773.271,964.098 690.5,960C 617.969,951.138 564.802,914.305 531,849.5C 502.746,785.583 505.746,723.25 540,662.5C 576.413,606.246 627.913,574.579 694.5,567.5 Z"/></g>
|
|
||||||
<g><path style="opacity:0.064" fill="#f6e716" d="M 1046.5,512.5 C 1055.58,523.094 1063.74,534.427 1071,546.5C 1129.23,644.638 1146.23,749.971 1122,862.5C 1121.5,863 1121,863.5 1120.5,864C 1129.42,878.329 1137.42,893.163 1144.5,908.5C 1143.18,908.67 1142.01,908.337 1141,907.5C 1140.49,905.122 1139.82,902.788 1139,900.5C 1136.15,896.81 1133.82,892.81 1132,888.5C 1130.99,889.337 1129.82,889.67 1128.5,889.5C 1125.11,884.395 1121.94,879.062 1119,873.5C 1118.83,871.833 1118.67,870.167 1118.5,868.5C 1147.5,739.989 1123.83,622.989 1047.5,517.5C 1047.37,515.784 1047.04,514.117 1046.5,512.5 Z"/></g>
|
|
||||||
<g><path style="opacity:0.239" fill="#dccf1d" d="M 298.5,861.5 C 299.266,863.684 299.933,866.018 300.5,868.5C 292.914,884.014 284.581,899.014 275.5,913.5C 274.782,911.863 274.616,910.197 275,908.5C 276.732,906.717 278.232,904.717 279.5,902.5C 279.291,901.914 278.957,901.414 278.5,901C 281.22,896.324 283.72,891.491 286,886.5C 286.777,888.701 287.944,888.701 289.5,886.5C 288.691,884.929 288.357,883.262 288.5,881.5C 289.552,881.649 290.552,881.483 291.5,881C 292.104,878.532 293.438,876.532 295.5,875C 294.703,872.426 295.537,870.259 298,868.5C 298.497,866.19 298.663,863.857 298.5,861.5 Z"/></g>
|
|
||||||
<g><path style="opacity:0.12" fill="#ecde19" d="M 1144.5,908.5 C 1167.91,948.307 1190.58,988.641 1212.5,1029.5C 1212.34,1032.55 1213.01,1035.38 1214.5,1038C 1214.17,1038.33 1213.83,1038.67 1213.5,1039C 1216.12,1039.58 1216.79,1040.91 1215.5,1043C 1217.86,1043.59 1218.86,1045.09 1218.5,1047.5C 1222.61,1048.49 1223.27,1050.49 1220.5,1053.5C 1219.57,1052.06 1218.4,1050.73 1217,1049.5C 1187.19,996.21 1157.69,942.876 1128.5,889.5C 1129.82,889.67 1130.99,889.337 1132,888.5C 1133.82,892.81 1136.15,896.81 1139,900.5C 1139.82,902.788 1140.49,905.122 1141,907.5C 1142.01,908.337 1143.18,908.67 1144.5,908.5 Z"/></g>
|
|
||||||
<g><path style="opacity:0.282" fill="#d5c91e" d="M 219.5,1013.5 C 215.338,1022.49 210.672,1031.16 205.5,1039.5C 205.756,1037.21 205.423,1035.04 204.5,1033C 209.614,1028.62 213.114,1023.12 215,1016.5C 216.271,1015.12 217.771,1014.12 219.5,1013.5 Z"/></g>
|
|
||||||
<g><path style="opacity:0.03" fill="#f3e517" d="M 371.5,511.5 C 370.962,513.117 370.629,514.784 370.5,516.5C 368.006,519.494 365.839,522.827 364,526.5C 359.748,529.423 357.081,533.423 356,538.5C 351.628,544.306 347.461,550.306 343.5,556.5C 289.313,652.323 274.313,753.989 298.5,861.5C 298.663,863.857 298.497,866.19 298,868.5C 295.537,870.259 294.703,872.426 295.5,875C 293.438,876.532 292.104,878.532 291.5,881C 290.552,881.483 289.552,881.649 288.5,881.5C 288.357,883.262 288.691,884.929 289.5,886.5C 287.944,888.701 286.777,888.701 286,886.5C 283.72,891.491 281.22,896.324 278.5,901C 278.957,901.414 279.291,901.914 279.5,902.5C 278.232,904.717 276.732,906.717 275,908.5C 274.616,910.197 274.782,911.863 275.5,913.5C 257.323,947.196 238.656,980.53 219.5,1013.5C 217.771,1014.12 216.271,1015.12 215,1016.5C 213.114,1023.12 209.614,1028.62 204.5,1033C 205.423,1035.04 205.756,1037.21 205.5,1039.5C 203.775,1043.94 201.275,1047.94 198,1051.5C 193.843,1063.01 197.677,1066.34 209.5,1061.5C 223.089,1063.38 236.756,1064.54 250.5,1065C 305.479,1068.22 360.479,1070.72 415.5,1072.5C 418.495,1073.66 421.495,1074.83 424.5,1076C 428.5,1080.06 432.5,1084.06 436.5,1088C 437.5,1088.33 438.5,1088.67 439.5,1089C 449.689,1098.8 461.022,1107.13 473.5,1114C 475.914,1117.45 479.247,1119.45 483.5,1120C 488.758,1122.98 493.758,1126.48 498.5,1130.5C 583.89,1177.51 674.89,1194.18 771.5,1180.5C 777.4,1180.12 783.067,1179.12 788.5,1177.5C 822.91,1171.64 855.91,1161.47 887.5,1147C 888.833,1146.33 889.833,1145.33 890.5,1144C 894.681,1143.91 898.015,1142.24 900.5,1139C 905.87,1135.98 911.537,1133.48 917.5,1131.5C 923.378,1126.31 930.045,1122.31 937.5,1119.5C 946.996,1111.65 956.996,1104.65 967.5,1098.5C 977.536,1088.28 988.536,1079.45 1000.5,1072C 1074,1069.95 1147.34,1066.45 1220.5,1061.5C 1221.61,1058.84 1221.61,1056.18 1220.5,1053.5C 1223.27,1050.49 1222.61,1048.49 1218.5,1047.5C 1218.86,1045.09 1217.86,1043.59 1215.5,1043C 1216.79,1040.91 1216.12,1039.58 1213.5,1039C 1213.83,1038.67 1214.17,1038.33 1214.5,1038C 1213.01,1035.38 1212.34,1032.55 1212.5,1029.5C 1218.28,1038.74 1223.78,1048.08 1229,1057.5C 1231.4,1062.49 1229.9,1065.99 1224.5,1068C 1221.44,1068.26 1218.44,1068.76 1215.5,1069.5C 1213.83,1068.83 1212.17,1068.17 1210.5,1067.5C 1180.44,1069.63 1150.44,1071.63 1120.5,1073.5C 1110.81,1073.47 1101.15,1073.47 1091.5,1073.5C 1059.05,1075.76 1026.71,1077.6 994.5,1079C 913.217,1150.34 818.05,1186.51 709,1187.5C 599.827,1186.84 504.661,1150.84 423.5,1079.5C 400.74,1077.32 377.74,1076.15 354.5,1076C 336.48,1074.62 318.647,1073.45 301,1072.5C 299.699,1072.96 298.366,1073.29 297,1073.5C 267.186,1071.67 237.353,1069.67 207.5,1067.5C 201.897,1069.4 196.231,1069.24 190.5,1067C 188.406,1065.74 187.406,1063.91 187.5,1061.5C 188.453,1057.6 189.953,1053.93 192,1050.5C 227.124,988.791 261.957,926.791 296.5,864.5C 271.3,753.389 287.133,648.723 344,550.5C 348.667,543.167 353.333,535.833 358,528.5C 362.418,522.603 366.918,516.936 371.5,511.5 Z"/></g>
|
|
||||||
<g><path style="opacity:1" fill="#4a4730" d="M 788.5,1177.5 C 783.067,1179.12 777.4,1180.12 771.5,1180.5C 772.952,1179.7 774.618,1179.2 776.5,1179C 774.5,1178.67 772.5,1178.33 770.5,1178C 776.486,1176.39 782.486,1176.22 788.5,1177.5 Z"/></g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 12 KiB |
@@ -1,245 +0,0 @@
|
|||||||
# frontpage
|
|
||||||
|
|
||||||
- https://frontpage.fyi
|
|
||||||
- https://bsky.app/profile/frontpage.fyi
|
|
||||||
- https://github.com/likeandscribe/frontpage
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ git clone https://github.com/likeandscribe/frontpage
|
|
||||||
$ dir=${0:a:h}/frontpage
|
|
||||||
$ cd $dir
|
|
||||||
```
|
|
||||||
|
|
||||||
## first setting
|
|
||||||
|
|
||||||
- https://o.syui.ai
|
|
||||||
- https://at.syu.is/at/syui.ai/ai.syui.o.post
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ cd $dir
|
|
||||||
$ nvm use 20
|
|
||||||
$ pnpm i
|
|
||||||
$ cat turbo.json
|
|
||||||
$ pnpm exec turbo run --affected type-check
|
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ cd $dir/packages/frontpage
|
|
||||||
$ pnpm exec tsx ./scripts/generate-jwk.mts
|
|
||||||
# pnpm run db:generate
|
|
||||||
# pnpm run db:migrate
|
|
||||||
$ cat .env.local
|
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# frontpage/.env.local
|
|
||||||
PRIVATE_JWK=`pnpm exec tsx ./scripts/generate-jwk.mts`
|
|
||||||
PUBLIC_JWK=`pnpm exec tsx ./scripts/generate-jwk.mts`
|
|
||||||
|
|
||||||
TURSO_CONNECTION_URL=`turso db create` #libsql://xxx.turso.io
|
|
||||||
#TURSO_CONNECTION_URL=`turso db shell xxx-xxx`
|
|
||||||
TURSO_AUTH_TOKEN=`turso db tokens create xxx-xxx`
|
|
||||||
|
|
||||||
DRAINPIPE_CONSUMER_SECRET=`openssl ecparam --name secp256k1 --genkey --noout --outform DER | tail --bytes=+8 | head --bytes=32 | xxd --plain --cols 32`
|
|
||||||
VERCEL_PROJECT_PRODUCTION_URL=example.com
|
|
||||||
VERCEL_BRANCH_URL=example.com
|
|
||||||
|
|
||||||
#DRAINPIPE_CONSUMER_SECRET=secret
|
|
||||||
#TURSO_CONNECTION_URL=libsql://turso.dev.unravel.fyi
|
|
||||||
#PLC_DIRECTORY_URL=https://plc.dev.unravel.fyi
|
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ cd $dir/packages-rs/drainpipe
|
|
||||||
$ cargo install diesel_cli --no-default-features --features sqlite
|
|
||||||
$ diesel setup
|
|
||||||
$ diesel migration run
|
|
||||||
$ ls drainpipe.db
|
|
||||||
$ cat .env.local
|
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# drainpipe/.env.local
|
|
||||||
DATABASE_URL="drainpipe.db"
|
|
||||||
FRONTPAGE_CONSUMER_URL="http://${cloudflared}/api/receive_hook"
|
|
||||||
FRONTPAGE_CONSUMER_SECRET=`openssl ecparam --name secp256k1 --genkey --noout --outform DER | tail --bytes=+8 | head --bytes=32 | xxd --plain --cols 32`
|
|
||||||
#RELAY_URL=wss://bsky.network
|
|
||||||
#FRONTPAGE_CONSUMER_SECRET=secret
|
|
||||||
```
|
|
||||||
|
|
||||||
## rewrite
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ cd $dir/packages/frontpage
|
|
||||||
$ PUBLIC_URL=example.com
|
|
||||||
$ grep -R frontpage.fyi ./app ./lib |cut -d : -f 1|xargs sed -i "s/frontpage.fyi/${PUBLIC_URL}/g"
|
|
||||||
|
|
||||||
$ HOST_REVERT=com.unravel.example
|
|
||||||
$ grep -R unravel.frontpage ./app ./lib |cut -d : -f 1|xargs sed -i "s/fyi.unravel.frontpage/${HOST_REVERT}/g"
|
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ cd $dir/packages-rs/drainpipe
|
|
||||||
$ HOST_REVERT=com.unravel.example
|
|
||||||
$ grep -R fyi.unravel.frontpage ./src |cut -d : -f 1|xargs sed -i "s/fyi.unravel.frontpage/${HOST_REVERT}/g"
|
|
||||||
```
|
|
||||||
|
|
||||||
## deploy
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ cd $dir/packages-rs/drainpipe
|
|
||||||
$ docker compose up
|
|
||||||
---
|
|
||||||
$ cd $dir/packages/frontpage
|
|
||||||
$ docker compose up
|
|
||||||
```
|
|
||||||
|
|
||||||
## explanation
|
|
||||||
|
|
||||||
### client-metadata.json
|
|
||||||
|
|
||||||
the `client_id` is different between `pnpm run start` and `pnpm run dev`. see `https://localhost:3000/oauth/client-metadata.json` for this.
|
|
||||||
|
|
||||||
### local-infra
|
|
||||||
|
|
||||||
i think this is the server configuration required for self-hosting.
|
|
||||||
|
|
||||||
https://github.com/likeandscribe/frontpage/tree/main/packages/frontpage/local-infra
|
|
||||||
|
|
||||||
since plc gives an error, do the following. probably a postgres database is required. there is no need to open ports.
|
|
||||||
|
|
||||||
```yml
|
|
||||||
plc:
|
|
||||||
image: ghcr.io/bluesky-social/did-method-plc:plc-f2ab7516bac5bc0f3f86842fa94e996bd1b3815b
|
|
||||||
container_name: plc
|
|
||||||
restart: unless-stopped
|
|
||||||
ports:
|
|
||||||
- '4000:8080'
|
|
||||||
depends_on:
|
|
||||||
- plc_db
|
|
||||||
env_file:
|
|
||||||
- ./plc.env
|
|
||||||
|
|
||||||
plc_db:
|
|
||||||
image: postgres:16-alpine
|
|
||||||
restart: always
|
|
||||||
env_file:
|
|
||||||
- ./postgres.env
|
|
||||||
volumes:
|
|
||||||
- ./configs/postgres/init/:/docker-entrypoint-initdb.d/
|
|
||||||
- ./data/postgres/:/var/lib/postgresql/data/
|
|
||||||
healthcheck:
|
|
||||||
test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
|
|
||||||
interval: 5s
|
|
||||||
retries: 20
|
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# plc.env
|
|
||||||
DEBUG_MODE=1
|
|
||||||
LOG_ENABLED=true
|
|
||||||
LOG_LEVEL=debug
|
|
||||||
LOG_DESTINATION=1
|
|
||||||
PORT=8080
|
|
||||||
DATABASE_URL=postgres://postgres:postgres@plc_db/plc
|
|
||||||
DB_CREDS_JSON='{"username":"postgres","password":"postgres","host":"plc_db","port":"5432","database":"plc"}'
|
|
||||||
ENABLE_MIGRATIONS=true
|
|
||||||
DB_MIGRATE_CREDS_JSON='{"username":"postgres","password":"postgres","host":"plc_db","port":"5432","database":"plc"}'
|
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# configs/postgres/init/init.sql
|
|
||||||
-- PLC
|
|
||||||
CREATE DATABASE plc;
|
|
||||||
GRANT ALL PRIVILEGES ON DATABASE plc TO postgres;
|
|
||||||
```
|
|
||||||
|
|
||||||
### pds
|
|
||||||
|
|
||||||
first, i think you need to get the pdsurl with oauth(session). if you have a session, you can perform operations such as posting.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ cd $dir/packages/frontpage
|
|
||||||
./lib/data/user.ts: const pdsUrl = await getPdsUrl(session.user.did);
|
|
||||||
```
|
|
||||||
|
|
||||||
it seems that drainpipe searches for `fyi.unravel.frontpage(collection)` in pds and commits it to firehose subscriberepos. if you change these two parts, it will not work with `frontpage.fyi`.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
// https://github.com/likeandscribe/frontpage/blob/e7444ec6c19f0ccef3776f04702c3bb033ed3bfc/packages-rs/drainpipe/src/main.rs#L66-L97
|
|
||||||
// RELAY_URL=wss://bsky.network
|
|
||||||
let mut ws_request = format!(
|
|
||||||
"{}/xrpc/com.atproto.sync.subscribeRepos{}",
|
|
||||||
relay_url, query_string
|
|
||||||
)
|
|
||||||
|
|
||||||
/// Process a message from the firehose. Returns the sequence number of the message or an error.
|
|
||||||
async fn process(message: Vec<u8>, ctx: &mut Context) -> Result<i64, ProcessError> {
|
|
||||||
let (_header, data) = firehose::read(&message).map_err(|e| ProcessError {
|
|
||||||
inner: e.into(),
|
|
||||||
seq: -1,
|
|
||||||
source: message.clone().into(),
|
|
||||||
kind: ProcessErrorKind::DecodeError,
|
|
||||||
})?;
|
|
||||||
let sequence = match data {
|
|
||||||
firehose::SubscribeRepos::Commit(commit) => {
|
|
||||||
let frontpage_ops = commit
|
|
||||||
.operations
|
|
||||||
.iter()
|
|
||||||
.filter(|op| op.path.starts_with("com.unravel.example."))
|
|
||||||
//.filter(|op| op.path.starts_with("fyi.unravel.frontpage."))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
if !frontpage_ops.is_empty() {
|
|
||||||
process_frontpage_ops(&frontpage_ops, &commit, &ctx)
|
|
||||||
.map_err(|e| ProcessError {
|
|
||||||
seq: commit.sequence,
|
|
||||||
inner: e,
|
|
||||||
source: message.clone().into(),
|
|
||||||
kind: ProcessErrorKind::ProcessError,
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
commit.sequence
|
|
||||||
}
|
|
||||||
msg => msg.sequence(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(sequence)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
色を変更するには`packages/frontpage/app/globals.css `を変更します。
|
|
||||||
|
|
||||||
```css
|
|
||||||
--primary: 210 100% 50%; /* HSLカラーで青色を定義 */
|
|
||||||
--primary-foreground: 0 0% 100%; /* 白色のテキスト */
|
|
||||||
```
|
|
||||||
|
|
||||||
## other
|
|
||||||
|
|
||||||
### delete record
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# at://did:plc:uqzpqmrjnptsxezjx4xuh2mn/ai.syui.o.post/3lafos6to6y2y
|
|
||||||
$ git clone https://git.syui.ai/ai/bot
|
|
||||||
$ cargo build
|
|
||||||
$ ./target/debug/ai delete 3lafos6to6y2y -c ai.syui.o.post
|
|
||||||
```
|
|
||||||
|
|
||||||
### license view
|
|
||||||
|
|
||||||
```html
|
|
||||||
// https://github.com/likeandscribe/frontpage/blob/de31aedf73c4e80e7376cf73c7c054437563f2ab/packages/frontpage/app/layout.tsx#L28-L52
|
|
||||||
+ <div dangerouslySetInnerHTML={{__html: '<!-- frontpage | MIT | https://github.com/likeandscribe/frontpage/blob/main/LICENSE -->'}} />
|
|
||||||
```
|
|
||||||
|
|
||||||
### admin view
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# https://github.com/likeandscribe/frontpage/blob/7fccf20fa800ba25fd57db279033ddf2cc92e9ce/packages/frontpage/lib/constants.ts
|
|
||||||
./lib/constants.ts:export const FRONTPAGE_ATPROTO_HANDLE = "admin.example.com";
|
|
||||||
|
|
||||||
# https://github.com/likeandscribe/frontpage/blob/cf8a4cb8bc7bab54407972964f8d39bf5e7c9182/packages/frontpage/app/(app)/layout.tsx#L55-L66
|
|
||||||
./app/\(app\)/layout.tsx:@admin.example.com <OpenInNewWindowIcon className="inline" />
|
|
||||||
```
|
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
FROM node:20
|
|
||||||
|
|
||||||
RUN npm install -g pnpm
|
|
||||||
WORKDIR /app
|
|
||||||
RUN git clone https://github.com/notjuliet/pdsls
|
|
||||||
WORKDIR /app/pdsls
|
|
||||||
COPY ./vite.config.ts ./vite.config.ts
|
|
||||||
RUN pnpm i
|
|
||||||
RUN pnpm build
|
|
||||||
|
|
||||||
CMD [ "pnpm", "start"]
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
services:
|
|
||||||
atbrowser:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
ports:
|
|
||||||
- 3000:13213
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
import { defineConfig } from "vite";
|
|
||||||
import solidPlugin from "vite-plugin-solid";
|
|
||||||
import UnoCSS from "unocss/vite";
|
|
||||||
|
|
||||||
const SERVER_HOST = "0.0.0.0";
|
|
||||||
const SERVER_PORT = 13213;
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [UnoCSS(), solidPlugin()],
|
|
||||||
server: {
|
|
||||||
host: SERVER_HOST,
|
|
||||||
port: SERVER_PORT,
|
|
||||||
},
|
|
||||||
build: {
|
|
||||||
target: "esnext",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
FROM syui/aios
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
COPY . .
|
|
||||||
RUN pacman -Syu rye --noconfirm
|
|
||||||
RUN rye sync
|
|
||||||
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
@app.route("/about")
|
|
||||||
def aboutpage():
|
|
||||||
return render_template("about.html")
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
services:
|
|
||||||
web:
|
|
||||||
build: .
|
|
||||||
env_file:
|
|
||||||
- ./.env
|
|
||||||
ports:
|
|
||||||
- "5000:5000"
|
|
||||||
volumes:
|
|
||||||
- ./demo.sqlite:/app/demo.sqlite
|
|
||||||
command: rye run flask run --host=0.0.0.0
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
{% extends 'base.html' %}
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<h2>service</h2>
|
|
||||||
<p>This service allows you to comment on live broadcasts using your atproto account.</p>
|
|
||||||
|
|
||||||
<h2>system</h2>
|
|
||||||
<p>Display posts to BBS using atproto oauth.</p>
|
|
||||||
<p>This service is generated using <a href="https://github.com/bluesky-social/cookbook">bluesky/cookbook</a>.</p>
|
|
||||||
<p>Authentication information will be deleted periodically.</p>
|
|
||||||
<hr/>
|
|
||||||
|
|
||||||
<h2>サービス</h2>
|
|
||||||
<p>このサービスはlive配信にatprotoアカウントを使ってコメントができます。</p>
|
|
||||||
<h2>システム</h2>
|
|
||||||
<p>atproto oauthを使用してbbsへの書き込みを許可します。</p>
|
|
||||||
<p>このサービスは<a href="https://github.com/bluesky-social/cookbook">bluesky/cookbook</a>を使用して生成されています。</p>
|
|
||||||
<p>認証情報は定期的に削除されます。</p>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="referrer" content="origin-when-cross-origin">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.classless.blue.min.css">
|
|
||||||
<link rel="stylesheet" href="https://syui.ai/bower_components/font-awesome/css/all.min.css" />
|
|
||||||
<link rel="icon" href="https://live.syui.ai/favicon.ico">
|
|
||||||
<title>o.syui.ai</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<header>
|
|
||||||
<hgroup>
|
|
||||||
{% if g.user %}
|
|
||||||
{% endif %}
|
|
||||||
</hgroup>
|
|
||||||
<nav>
|
|
||||||
<ul>
|
|
||||||
<li><a href="/"><button class="secondary">o</button></a></li>
|
|
||||||
<li>.syui.ai</li>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
{% if g.user %}
|
|
||||||
<li><a href="{{ url_for('bsky_post') }}">post</a>
|
|
||||||
<li><a href="{{ url_for('oauth_refresh') }}">refresh</a>
|
|
||||||
<li><a href="{{ url_for('oauth_logout') }}"><button class="secondary">logout</button></a>
|
|
||||||
{% else %}
|
|
||||||
<li><a href="/about"><i class="fa-solid fa-circle-question"></i></a></li>
|
|
||||||
{% endif %}
|
|
||||||
<!--
|
|
||||||
<li><a href="https://github.com/bluesky-social/cookbook">Code</a>
|
|
||||||
-->
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main class="container">
|
|
||||||
<section class="content">
|
|
||||||
{% for message in get_flashed_messages() %}
|
|
||||||
<article>{{ message }}</article>
|
|
||||||
{% endfor %}
|
|
||||||
{% block content %}{% endblock %}
|
|
||||||
</section>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
background-color: #f1f1f1;
|
|
||||||
}
|
|
||||||
button a {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
iframe#livechat {
|
|
||||||
width: 100%;
|
|
||||||
min-height: 500px;
|
|
||||||
}
|
|
||||||
iframe#livestream {
|
|
||||||
width: 100%;
|
|
||||||
min-height: 500px;
|
|
||||||
}
|
|
||||||
button.oauth-login {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
footer {
|
|
||||||
text-align:center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-1 {
|
|
||||||
display: flex;
|
|
||||||
.right-container {
|
|
||||||
background-color: #fff;
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
align-self: flex-start;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-end;
|
|
||||||
padding:10px;
|
|
||||||
margin-left:30px;
|
|
||||||
.content:first-of-type {
|
|
||||||
position: sticky;
|
|
||||||
bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.left-container {
|
|
||||||
padding:10px;
|
|
||||||
background-color: #fff;
|
|
||||||
width: 80%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 959px) {
|
|
||||||
.left-container {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
iframe#livestream {
|
|
||||||
width: 100%;
|
|
||||||
min-height:300px;
|
|
||||||
height:100%;
|
|
||||||
}
|
|
||||||
.container-1 {
|
|
||||||
display: block;
|
|
||||||
.right-container {
|
|
||||||
margin-left:0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<footer>©syui</footer>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{% extends 'base.html' %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<form method="post">
|
|
||||||
<textarea name="post_text" placeholder="What's up?" id="post_text" required></textarea>
|
|
||||||
<input type="submit" value="Poast!">
|
|
||||||
</form>
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
{% extends 'base.html' %}
|
|
||||||
|
|
||||||
{% block title %}Error{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<h2>⚠️ Error {{ status_code }} ⚠️</h2>
|
|
||||||
{% if err.description %}
|
|
||||||
<p><code>{{ err.description }}</code></p>
|
|
||||||
{% else %}
|
|
||||||
<p>Something went wrong!</p>
|
|
||||||
{% endif %}
|
|
||||||
<p><a href="/">Start Over</a></p>
|
|
||||||
{% endblock %}
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB |
@@ -1 +0,0 @@
|
|||||||
<?xml version="1.0" ?><svg height="512" viewBox="0 0 512 512" width="512" xmlns="http://www.w3.org/2000/svg"><title/><path d="M413.48,284.46c58.87,47.24,91.61,89,80.31,108.55-17.85,30.85-138.78-5.48-270.1-81.15S.37,149.84,18.21,119c11.16-19.28,62.58-12.32,131.64,14.09" style="fill:none;stroke:#000;stroke-miterlimit:10;stroke-width:32px"/><circle cx="256" cy="256" r="160" style="fill:none;stroke:#000;stroke-miterlimit:10;stroke-width:32px"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 450 B |
@@ -1,29 +0,0 @@
|
|||||||
{% extends 'base.html' %}
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<div class="container-1">
|
|
||||||
<div class="left-container">
|
|
||||||
<div class="livestream">
|
|
||||||
<iframe id="livestream" title="stream" src="https://live.syui.ai/b9ec42d4-8a4d-4343-99fc-1bd1cdbc5a6f.html"> </iframe>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="right-container">
|
|
||||||
{% if g.user %}
|
|
||||||
<span class="user-handle">@{{ g.user['handle'] }}</span>
|
|
||||||
<div class="livechat">
|
|
||||||
<iframe id="livechat" title="bskychat" src="https://bbs.syui.ai/?handle={{ session['user_handle'] }}"> </iframe>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<div class="livechat">
|
|
||||||
<a href="{{ url_for('oauth_login') }}"><button class="oauth-login">@</button></a>
|
|
||||||
<iframe id="livechat" title="bskychat" src="https://bbs.syui.ai"> </iframe>
|
|
||||||
</div>
|
|
||||||
<div class="right-container">
|
|
||||||
<p>write comment using oauth atproto.</p>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{% extends 'base.html' %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<article>
|
|
||||||
<h3>Login with atproto</h3>
|
|
||||||
<form method="post">
|
|
||||||
<p>Provide your handle or DID to authorize an existing account with PDS.
|
|
||||||
<br>You can also supply a PDS/entryway URL (eg, <code>https://pds.example.com</code>).</p>
|
|
||||||
<fieldset role="group">
|
|
||||||
<input name="username" id="username" placeholder="handle.example.com" style="font-family: monospace,monospace;" required>
|
|
||||||
<input type="submit" value="Login">
|
|
||||||
</fieldset>
|
|
||||||
</form>
|
|
||||||
</article>
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
https://github.com/notjuliet/pdsls
|
|
||||||
|
|
||||||
https://github.com/likeandscribe/frontpage
|
|
||||||
|
|
||||||
https://github.com/bluesky-social/cookbook/tree/main/python-oauth-web-app
|
|
||||||
31
scpt/at.zsh
31
scpt/at.zsh
@@ -4,6 +4,9 @@ d=${0:a:h}
|
|||||||
|
|
||||||
source $d/src/tag.zsh
|
source $d/src/tag.zsh
|
||||||
source $d/src/func.zsh
|
source $d/src/func.zsh
|
||||||
|
source $d/src/ue.zsh
|
||||||
|
source $d/src/ai/syui/game/character.zsh
|
||||||
|
source $d/src/is/syu/main.zsh
|
||||||
|
|
||||||
at-env
|
at-env
|
||||||
case $1 in
|
case $1 in
|
||||||
@@ -38,16 +41,34 @@ case $1 in
|
|||||||
at-profile
|
at-profile
|
||||||
;;
|
;;
|
||||||
download-character-icon)
|
download-character-icon)
|
||||||
source $d/ai/syui/game/character.zsh
|
|
||||||
download_character_icon
|
download_character_icon
|
||||||
;;
|
;;
|
||||||
create-game-character)
|
create-game-character)
|
||||||
source $d/ai/syui/game/character.zsh
|
|
||||||
create_game_character
|
create_game_character
|
||||||
;;
|
;;
|
||||||
ai-create-user)
|
create-game-user)
|
||||||
source $d/ai/syui/game/character.zsh
|
create_game_user $2
|
||||||
ai_create_user
|
;;
|
||||||
|
create-system)
|
||||||
|
create_system
|
||||||
|
;;
|
||||||
|
get-game-user)
|
||||||
|
get_game_user $2
|
||||||
|
;;
|
||||||
|
delete-game-user)
|
||||||
|
delete_game_user $2 $3
|
||||||
|
;;
|
||||||
|
verify-icon)
|
||||||
|
verify-icon
|
||||||
|
;;
|
||||||
|
self-col)
|
||||||
|
self-col $2
|
||||||
|
;;
|
||||||
|
ue-system)
|
||||||
|
ue-system
|
||||||
|
;;
|
||||||
|
ue-user)
|
||||||
|
ue-user $2
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "${help[@]}"
|
echo "${help[@]}"
|
||||||
|
|||||||
@@ -1,33 +1,3 @@
|
|||||||
character=(
|
|
||||||
ai
|
|
||||||
manny
|
|
||||||
quinn
|
|
||||||
chinese
|
|
||||||
kirin
|
|
||||||
leviathan
|
|
||||||
phoenix
|
|
||||||
wyvern
|
|
||||||
cerberus
|
|
||||||
dragon
|
|
||||||
kitsune
|
|
||||||
pegasus
|
|
||||||
)
|
|
||||||
|
|
||||||
img=(
|
|
||||||
bafkreie34pjuc6coenzcdwrgrh4fbacq7bkhsz263g5vpbsqxwaz37kkwy
|
|
||||||
bafkreie34pjuc6coenzcdwrgrh4fbacq7bkhsz263g5vpbsqxwaz37kkwy
|
|
||||||
bafkreie34pjuc6coenzcdwrgrh4fbacq7bkhsz263g5vpbsqxwaz37kkwy
|
|
||||||
bafkreidlealfybajqzwv5eoz4jshnsijc2vnktlhpw4ph47krwj6aigqby
|
|
||||||
bafkreiegpqedlrfa4ljhssdnkrr5hyd5huy2xhh2zszj5wq2wuuzejggmq
|
|
||||||
bafkreig6vszkx3c4dcortjwfsz6sa6zwqgj7zpxj4lxfrrkwql4xhiu5ou
|
|
||||||
bafkreich7fsumke2yvumvixkruonzrcevk3f6g2cntzfwdn4n2c2vox5dm
|
|
||||||
bafkreiacjvagsekhiiljz3j237b6klrt6pkptxljt7kltprgg5276gv25q
|
|
||||||
bafkreihpni4lp55jysalcntulzal5rbhidtbseanlucpyucagzxmv6xj24
|
|
||||||
bafkreia3huw2gdenqatoobx3hcft74chced46bw4znfgepo5aenegobkri
|
|
||||||
bafkreidy74aieb6ie646xhosginox5zbnbnrtd76cnt4pbn73hrxgfnple
|
|
||||||
bafkreifnbfj27fr6nv7qeqqmwdibf7qrw4lauvzoknw5hexbifmwqt6kmq
|
|
||||||
)
|
|
||||||
|
|
||||||
function download_character_icon(){
|
function download_character_icon(){
|
||||||
|
|
||||||
t=(
|
t=(
|
||||||
@@ -189,35 +159,85 @@ json="{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function ai_create_user() {
|
function get_game_user() {
|
||||||
|
rkey=$did.$pds
|
||||||
|
pds=bsky.social
|
||||||
|
if [ "$1" = "syui" ] || [ "$1" = "ai" ];then
|
||||||
|
rkey=$1
|
||||||
|
fi
|
||||||
|
req=com.atproto.repo.getRecord
|
||||||
|
url="https://$pds/xrpc/$req?rkey=$rkey&repo=$did_yui&collection=ai.syui.game"
|
||||||
|
curl -sL $url|jq .
|
||||||
|
}
|
||||||
|
|
||||||
col=ai.syui.game.user
|
delete_game_user() {
|
||||||
rkey=ai
|
rkey=$2
|
||||||
did=$did_yui
|
if [ -z "$1" ];then
|
||||||
handle=$handle_yui
|
col=ai.syui.game
|
||||||
|
else
|
||||||
|
col=$1
|
||||||
|
fi
|
||||||
|
req=com.atproto.repo.DeleteRecord
|
||||||
|
url=https://$pds/xrpc/$req
|
||||||
|
repo=$did
|
||||||
|
#repo=did:plc:6qyecktefllvenje24fcxnie
|
||||||
|
json="{\"collection\":\"$col\", \"rkey\":\"$rkey\", \"repo\":\"$repo\"}"
|
||||||
|
echo $json
|
||||||
|
curl -sL -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $token" -d $json $url
|
||||||
|
}
|
||||||
|
|
||||||
|
function create_game_user() {
|
||||||
|
col=ai.syui.game
|
||||||
|
rkey=$1
|
||||||
|
handle_yui=$handle
|
||||||
|
did_yui=$did
|
||||||
|
pds=`cat $f|jq -r ".didDoc.service.[].serviceEndpoint"|cut -d / -f 3`
|
||||||
|
if [ "$pds" != "syu.is" ];then
|
||||||
|
pds=bsky.social
|
||||||
|
fi
|
||||||
|
version=4
|
||||||
#rkey=syui
|
#rkey=syui
|
||||||
#img=https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:4hqjfn7m6n5hno3doamuhgef/bafkreie34pjuc6coenzcdwrgrh4fbacq7bkhsz263g5vpbsqxwaz37kkwy@jpeg
|
#img=https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:4hqjfn7m6n5hno3doamuhgef/bafkreie34pjuc6coenzcdwrgrh4fbacq7bkhsz263g5vpbsqxwaz37kkwy@jpeg
|
||||||
req=com.atproto.repo.putRecord
|
req=com.atproto.repo.putRecord
|
||||||
url=https://$host/xrpc/$req
|
url=https://$pds/xrpc/$req
|
||||||
|
|
||||||
for ((i=1; i<=${#character}; i++)); do
|
cname=dragon
|
||||||
|
cid=bafkreia3huw2gdenqatoobx3hcft74chced46bw4znfgepo5aenegobkri
|
||||||
|
|
||||||
cname=${character[$i]}
|
if [ "$rkey" = "ai" ];then
|
||||||
cid=${img[$i]}
|
cname=$rkey
|
||||||
|
cid=bafkreie34pjuc6coenzcdwrgrh4fbacq7bkhsz263g5vpbsqxwaz37kkwy
|
||||||
|
gender=none
|
||||||
|
fi
|
||||||
|
if [ "$rkey" = "syui" ];then
|
||||||
|
cname=chinese
|
||||||
|
did=$did_syui
|
||||||
|
handle=syui.ai
|
||||||
|
cid=bafkreidlealfybajqzwv5eoz4jshnsijc2vnktlhpw4ph47krwj6aigqby
|
||||||
|
gender=male
|
||||||
|
fi
|
||||||
|
if [ "$rkey" = "self" ];then
|
||||||
|
cname=manny
|
||||||
|
unset did handle gender
|
||||||
|
pds=bsky.social
|
||||||
|
plc=plc.directory
|
||||||
|
fi
|
||||||
imguri=https://cdn.bsky.app/img/feed_thumbnail/plain/$did_yui/${cid}@jpeg
|
imguri=https://cdn.bsky.app/img/feed_thumbnail/plain/$did_yui/${cid}@jpeg
|
||||||
echo $imguri
|
|
||||||
echo $i $character $cname
|
|
||||||
season=1
|
season=1
|
||||||
group=test
|
group=test
|
||||||
lv=1
|
lv=1
|
||||||
hp=100
|
hp=1
|
||||||
exp=0
|
exp=0
|
||||||
rank=0
|
rare=0
|
||||||
mode=0
|
mode=0
|
||||||
attack=0
|
attack=0
|
||||||
attack_post=0
|
attack_post=0
|
||||||
critical=0
|
critical=0
|
||||||
critical_d=0
|
critical_d=0
|
||||||
|
card=0
|
||||||
|
weapon=0
|
||||||
|
coin=0
|
||||||
|
count=0
|
||||||
|
|
||||||
case $cname in
|
case $cname in
|
||||||
ai)
|
ai)
|
||||||
@@ -233,16 +253,10 @@ function ai_create_user() {
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
jc="\"$cname\": { \"group\": \"$group\", \"season\": $season, \"img\": \"$imguri\", \"lv\": $lv, \"exp\": $exp, \"hp\": $hp, \"rank\": $rank, \"mode\": $mode, \"attack\": $attack, \"attack_post\": $attack_post, \"critical\": $critical, \"critical_d\": $critical_d }"
|
json="\"$cname\": { \"group\": \"$group\", \"season\": $season, \"lv\": $lv, \"exp\": $exp, \"hp\": $hp, \"mode\": $mode, \"attack\": $attack, \"critical\": $critical, \"critical_d\": $critical_d, \"card\": $card, \"coin\": $coin, \"weapon\": $weapon, \"count\": $count, \"rare\": $rare}"
|
||||||
|
#json="\"$cname\": { \"group\": \"$group\", \"season\": $season, \"img\": \"$imguri\", \"lv\": $lv, \"exp\": $exp, \"hp\": $hp, \"rank\": $rank, \"mode\": $mode, \"attack\": $attack, \"attack_post\": $attack_post, \"critical\": $critical, \"critical_d\": $critical_d }"
|
||||||
|
|
||||||
if [ $#character -ne $i ];then
|
v1_json="
|
||||||
jc=${jc},
|
|
||||||
fi
|
|
||||||
|
|
||||||
json=${json}${jc}
|
|
||||||
|
|
||||||
done
|
|
||||||
json="
|
|
||||||
{
|
{
|
||||||
\"repo\": \"$handle_yui\",
|
\"repo\": \"$handle_yui\",
|
||||||
\"did\": \"$did_yui\",
|
\"did\": \"$did_yui\",
|
||||||
@@ -254,7 +268,7 @@ function ai_create_user() {
|
|||||||
\"login\": false,
|
\"login\": false,
|
||||||
\"handle\": \"$handle\",
|
\"handle\": \"$handle\",
|
||||||
\"aiten\": 10,
|
\"aiten\": 10,
|
||||||
\"gender\": \"famale\",
|
\"gender\": \"$gender\",
|
||||||
\"character\": {
|
\"character\": {
|
||||||
$json
|
$json
|
||||||
},
|
},
|
||||||
@@ -263,19 +277,11 @@ function ai_create_user() {
|
|||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
|
|
||||||
|
json_item="
|
||||||
if echo $json|jq . ;then
|
\"coin\": [{\"id\": 0, \"cp\": 0, \"rare\": 0, \"count\": 0}],
|
||||||
echo $token_yui
|
\"card\": [{\"id\": 0, \"cp\": 0, \"rare\": 0, \"count\": 0}],
|
||||||
echo y
|
\"weapon\": [{\"id\": 0, \"cp\": 0, \"rare\": 0, \"count\": 0}]
|
||||||
read y
|
"
|
||||||
if [ "y" = "$y" ];then
|
|
||||||
curl -sL -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $token_yui" -d $json $url
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
col=ai.syui.game
|
|
||||||
rkey=self
|
|
||||||
at_uri=at://$did_yui/ai.syui.game.user/ai
|
|
||||||
|
|
||||||
json="
|
json="
|
||||||
{
|
{
|
||||||
@@ -284,9 +290,25 @@ json="
|
|||||||
\"collection\": \"$col\",
|
\"collection\": \"$col\",
|
||||||
\"rkey\": \"$rkey\",
|
\"rkey\": \"$rkey\",
|
||||||
\"record\": {
|
\"record\": {
|
||||||
\"account\": \"$at_uri\",
|
\"version\": $version,
|
||||||
\"username\": \"ai\",
|
\"did\": \"$did\",
|
||||||
\"createdAt\": \"$created\"
|
\"handle\": \"$handle\",
|
||||||
|
\"plc\": \"$plc\",
|
||||||
|
\"pds\": \"$pds\",
|
||||||
|
\"player\": {
|
||||||
|
\"limit\": false,
|
||||||
|
\"login\": false,
|
||||||
|
\"ten\": 0,
|
||||||
|
\"gender\": \"$gender\"
|
||||||
|
},
|
||||||
|
\"character\": {
|
||||||
|
$json
|
||||||
|
},
|
||||||
|
\"item\": {
|
||||||
|
$json_item
|
||||||
|
},
|
||||||
|
\"createdAt\": \"${created}\",
|
||||||
|
\"updatedAt\": \"${created}\"
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
|
|
||||||
@@ -294,9 +316,62 @@ if echo $json|jq . ;then
|
|||||||
echo y
|
echo y
|
||||||
read y
|
read y
|
||||||
if [ "y" = "$y" ];then
|
if [ "y" = "$y" ];then
|
||||||
curl -sL -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $token_yui" -d $json $url
|
t=`curl -sL -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $token" -d $json $url`
|
||||||
|
echo $t|jq .
|
||||||
|
#f=~/ai/ue/json/v${version}_${rkey}.json
|
||||||
|
#if [ -f $f ];then
|
||||||
|
# get_game_user $rkey >! $f
|
||||||
|
#fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function create_system() {
|
||||||
|
col=ai.syui.system
|
||||||
|
rkey=self
|
||||||
|
did=$did
|
||||||
|
handle=$handle
|
||||||
|
pds=`cat $f|jq -r ".didDoc.service.[].serviceEndpoint"|cut -d / -f 3`
|
||||||
|
if [ "$pds" != "syu.is" ];then
|
||||||
|
pds=bsky.social
|
||||||
|
fi
|
||||||
|
version=1
|
||||||
|
#rkey=syui
|
||||||
|
#img=https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:4hqjfn7m6n5hno3doamuhgef/bafkreie34pjuc6coenzcdwrgrh4fbacq7bkhsz263g5vpbsqxwaz37kkwy@jpeg
|
||||||
|
req=com.atproto.repo.putRecord
|
||||||
|
url=https://$pds/xrpc/$req
|
||||||
|
#cid=bafkreia3huw2gdenqatoobx3hcft74chced46bw4znfgepo5aenegobkri
|
||||||
|
#imguri=https://cdn.bsky.app/img/feed_thumbnail/plain/$did_yui/${cid}@jpeg
|
||||||
|
imgurl=https://git.syui.ai/ai/ai/raw/branch/main/img/item/card
|
||||||
|
json_card=" \"id\": $id, \"name\": \"$name\", \"img\": \"${imgurl}/${id}.webp\""
|
||||||
|
json_card=`curl -sL https://git.syui.ai/ai/ai/raw/branch/main/json/card.json|jq ".[]"`
|
||||||
|
json_weapon=`curl -sL https://git.syui.ai/ai/ai/raw/branch/main/json/weapon.json|jq ".[]"`
|
||||||
|
json_system=`curl -sL https://git.syui.ai/ai/ai/raw/branch/main/json/system.json|jq ".[]"`
|
||||||
|
json_character=`curl -sL https://git.syui.ai/ai/ai/raw/branch/main/json/character.json|jq ".[]"`
|
||||||
|
json_ability=`curl -sL https://git.syui.ai/ai/ai/raw/branch/main/json/ability.json|jq ".[]"`
|
||||||
|
json="
|
||||||
|
{
|
||||||
|
\"repo\": \"$handle\",
|
||||||
|
\"did\": \"$did\",
|
||||||
|
\"collection\": \"$col\",
|
||||||
|
\"rkey\": \"$rkey\",
|
||||||
|
\"record\": {
|
||||||
|
\"card\": ${json_card},
|
||||||
|
\"weapon\": ${json_weapon},
|
||||||
|
\"system\": ${json_system},
|
||||||
|
\"character\": ${json_character},
|
||||||
|
\"ability\": ${json_ability},
|
||||||
|
\"createdAt\": \"${created}\",
|
||||||
|
\"updatedAt\": \"${created}\"
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
|
||||||
|
if echo $json|jq . ;then
|
||||||
|
echo y
|
||||||
|
read y
|
||||||
|
if [ "y" = "$y" ];then
|
||||||
|
t=`curl -sL -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $token" -d $json $url`
|
||||||
|
echo $t|jq .
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
function at-env() {
|
function at-env() {
|
||||||
|
pds=bsky.social
|
||||||
|
plc=plc.directory
|
||||||
host=https://bsky.social
|
host=https://bsky.social
|
||||||
handle_syui=syui.ai
|
handle_syui=syui.ai
|
||||||
handle_yui=yui.syui.ai
|
handle_yui=yui.syui.ai
|
||||||
@@ -6,21 +8,25 @@ function at-env() {
|
|||||||
did_syui=did:plc:uqzpqmrjnptsxezjx4xuh2mn
|
did_syui=did:plc:uqzpqmrjnptsxezjx4xuh2mn
|
||||||
handle=$handle_yui
|
handle=$handle_yui
|
||||||
did=$did_yui
|
did=$did_yui
|
||||||
created=2020-01-01T00:00:00+09:00
|
created=2025-04-21T00:00:00.323Z
|
||||||
at_uri=at://$did_yui/ai.syui.game.user/syui
|
|
||||||
docs_uri=https://docs.bsky.app/docs/api
|
docs_uri=https://docs.bsky.app/docs/api
|
||||||
|
at_uri=at://$handle/ai.syui.game/ai
|
||||||
did=`echo $at_uri|cut -d / -f 3`
|
did=`echo $at_uri|cut -d / -f 3`
|
||||||
collection=`echo $at_uri|cut -d / -f 4`
|
collection=`echo $at_uri|cut -d / -f 4`
|
||||||
rkey=`echo $at_uri|cut -d / -f 5`
|
rkey=`echo $at_uri|cut -d / -f 5`
|
||||||
d=${0:a:h}
|
d=${0:a:h}
|
||||||
f=~/.config/.at-zsh.json
|
f=~/.config/ai/token.json
|
||||||
if [ -f $f ];then
|
if [ -f $f ];then
|
||||||
host=`cat $f|jq -r ".didDoc.service.[].serviceEndpoint"`
|
host=`cat $f|jq -r ".didDoc.service.[].serviceEndpoint"|cut -d / -f 3`
|
||||||
token=`cat $f|jq -r .accessJwt`
|
token=`cat $f|jq -r .accessJwt`
|
||||||
did=`cat $f|jq -r .did`
|
did=`cat $f|jq -r .did`
|
||||||
handle=`cat $f|jq -r .handle`
|
handle=`cat $f|jq -r .handle`
|
||||||
actor=$did
|
actor=$did
|
||||||
fi
|
fi
|
||||||
|
if [ "$host" = "syu.is" ];then
|
||||||
|
plc=plc.syu.is
|
||||||
|
pds=$host
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function at-unset() {
|
function at-unset() {
|
||||||
@@ -39,18 +45,17 @@ function at-version-env() {
|
|||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
tag=pds
|
tag=pds
|
||||||
list=( bsky.social syu.is boobee.blue socl.is )
|
list=( bsky.social syu.is socl.is )
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
title="atproto $tag version"
|
title="atproto $tag version"
|
||||||
latest=https://raw.githubusercontent.com/bluesky-social/atproto/refs/heads/main/packages/$tag/package.json
|
latest=https://raw.githubusercontent.com/bluesky-social/atproto/refs/heads/main/packages/$tag/package.json
|
||||||
|
latest=`curl -sL $latest |jq -r .version`
|
||||||
# bgs=( bsky.network bgs.syu.is )
|
# bgs=( bsky.network bgs.syu.is )
|
||||||
# plc=( plc.directory plc.syu.is )
|
# plc=( plc.directory plc.syu.is )
|
||||||
}
|
}
|
||||||
|
|
||||||
function at-version-json() {
|
function at-version-json() {
|
||||||
latest=`curl -sL $latest |jq -r .version`
|
|
||||||
echo "[{\"title\":\"$title\",\"latest\":\"$latest\"},["
|
echo "[{\"title\":\"$title\",\"latest\":\"$latest\"},["
|
||||||
e=${list[@]: -1}
|
e=${list[@]: -1}
|
||||||
for i in $list; do
|
for i in $list; do
|
||||||
@@ -64,7 +69,7 @@ function at-version-json() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function at-version() {
|
function at-version() {
|
||||||
at-version-env $1
|
at-version-env
|
||||||
at-version-json|jq .
|
at-version-json|jq .
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,3 +177,32 @@ function at-profile() {
|
|||||||
url="${host}${req}?actor=$did"
|
url="${host}${req}?actor=$did"
|
||||||
curl -sL -X GET -H "Content-Type: application/json" -H "Authorization: Bearer $token" $url|jq .
|
curl -sL -X GET -H "Content-Type: application/json" -H "Authorization: Bearer $token" $url|jq .
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function verify-icon() {
|
||||||
|
syuisadmin_handle=ai.syu.is
|
||||||
|
syuisadmin_did=did:plc:6qyecktefllvenje24fcxnie
|
||||||
|
#rkey=
|
||||||
|
col=app.bsky.graph.verification
|
||||||
|
handle=syui.syu.is
|
||||||
|
subject=did:plc:vzsvtbtbnwn22xjqhcu3vd6y
|
||||||
|
displayName=syui
|
||||||
|
req=/xrpc/com.atproto.repo.createRecord
|
||||||
|
url=${host}${req}
|
||||||
|
json="
|
||||||
|
{
|
||||||
|
\"repo\": \"$syuisadmin_handle\",
|
||||||
|
\"did\": \"$syuisadmin_did\",
|
||||||
|
\"collection\": \"$col\",
|
||||||
|
\"record\": {
|
||||||
|
\"subject\": \"$subject\",
|
||||||
|
\"handle\": \"$handle\",
|
||||||
|
\"displayName\": \"$displayName\",
|
||||||
|
\"createdAt\": \"${created}\"
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
|
||||||
|
if echo $json|jq . ;then
|
||||||
|
t=`curl -sL -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $token" -d $json $url`
|
||||||
|
echo $t
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|||||||
18
scpt/src/is/syu/main.zsh
Normal file
18
scpt/src/is/syu/main.zsh
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/zsh
|
||||||
|
|
||||||
|
function self-col(){
|
||||||
|
if [ -n "$1" ];then
|
||||||
|
t=`curl -sL "$pds/xrpc/com.atproto.repo.listRecords?repo=$handle&collection=$1"`
|
||||||
|
echo $t|jq .
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
col=(
|
||||||
|
ai.syui.game
|
||||||
|
ai.syui.system
|
||||||
|
)
|
||||||
|
e=${col[@]: -1}
|
||||||
|
for i in $col; do
|
||||||
|
t=`curl -sL "$pds/xrpc/com.atproto.repo.listRecords?repo=$handle&collection=$i"`
|
||||||
|
echo $t|jq .
|
||||||
|
done
|
||||||
|
}
|
||||||
@@ -38,3 +38,33 @@ github=(
|
|||||||
)
|
)
|
||||||
tag=( at bsky bsync pds bgs plc ozone feed jetstream social-app oauth )
|
tag=( at bsky bsync pds bgs plc ozone feed jetstream social-app oauth )
|
||||||
#pds_list=(bsky.social syu.is boobee.blue socl.is )
|
#pds_list=(bsky.social syu.is boobee.blue socl.is )
|
||||||
|
|
||||||
|
character=(
|
||||||
|
ai
|
||||||
|
manny
|
||||||
|
quinn
|
||||||
|
chinese
|
||||||
|
kirin
|
||||||
|
leviathan
|
||||||
|
phoenix
|
||||||
|
wyvern
|
||||||
|
cerberus
|
||||||
|
dragon
|
||||||
|
kitsune
|
||||||
|
pegasus
|
||||||
|
)
|
||||||
|
|
||||||
|
character_img=(
|
||||||
|
bafkreie34pjuc6coenzcdwrgrh4fbacq7bkhsz263g5vpbsqxwaz37kkwy
|
||||||
|
bafkreie34pjuc6coenzcdwrgrh4fbacq7bkhsz263g5vpbsqxwaz37kkwy
|
||||||
|
bafkreie34pjuc6coenzcdwrgrh4fbacq7bkhsz263g5vpbsqxwaz37kkwy
|
||||||
|
bafkreidlealfybajqzwv5eoz4jshnsijc2vnktlhpw4ph47krwj6aigqby
|
||||||
|
bafkreiegpqedlrfa4ljhssdnkrr5hyd5huy2xhh2zszj5wq2wuuzejggmq
|
||||||
|
bafkreig6vszkx3c4dcortjwfsz6sa6zwqgj7zpxj4lxfrrkwql4xhiu5ou
|
||||||
|
bafkreich7fsumke2yvumvixkruonzrcevk3f6g2cntzfwdn4n2c2vox5dm
|
||||||
|
bafkreiacjvagsekhiiljz3j237b6klrt6pkptxljt7kltprgg5276gv25q
|
||||||
|
bafkreihpni4lp55jysalcntulzal5rbhidtbseanlucpyucagzxmv6xj24
|
||||||
|
bafkreia3huw2gdenqatoobx3hcft74chced46bw4znfgepo5aenegobkri
|
||||||
|
bafkreidy74aieb6ie646xhosginox5zbnbnrtd76cnt4pbn73hrxgfnple
|
||||||
|
bafkreifnbfj27fr6nv7qeqqmwdibf7qrw4lauvzoknw5hexbifmwqt6kmq
|
||||||
|
)
|
||||||
|
|||||||
193
scpt/src/ue.zsh
Executable file
193
scpt/src/ue.zsh
Executable file
@@ -0,0 +1,193 @@
|
|||||||
|
case $OSTYPE in
|
||||||
|
darwin*)
|
||||||
|
day=`gdate --iso-8601=seconds`
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
day=`date --iso-8601=seconds`
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
function get_game_user() {
|
||||||
|
rkey=$did.$pds
|
||||||
|
pds=bsky.social
|
||||||
|
if [ "$1" = "syui" ] || [ "$1" = "ai" ];then
|
||||||
|
rkey=$1
|
||||||
|
fi
|
||||||
|
req=com.atproto.repo.getRecord
|
||||||
|
url="https://$pds/xrpc/$req?rkey=$rkey&repo=$did_yui&collection=ai.syui.game"
|
||||||
|
curl -sL $url|jq .
|
||||||
|
}
|
||||||
|
|
||||||
|
function delete_game_user() {
|
||||||
|
rkey=$2
|
||||||
|
if [ -z "$1" ];then
|
||||||
|
col=ai.syui.game
|
||||||
|
else
|
||||||
|
col=$1
|
||||||
|
fi
|
||||||
|
req=com.atproto.repo.DeleteRecord
|
||||||
|
url=https://$pds/xrpc/$req
|
||||||
|
repo=$did
|
||||||
|
#repo=did:plc:6qyecktefllvenje24fcxnie
|
||||||
|
json="{\"collection\":\"$col\", \"rkey\":\"$rkey\", \"repo\":\"$repo\"}"
|
||||||
|
echo $json
|
||||||
|
curl -sL -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $token" -d $json $url
|
||||||
|
}
|
||||||
|
|
||||||
|
function ue-user() {
|
||||||
|
col=ai.syui.game
|
||||||
|
rkey=$1
|
||||||
|
handle_yui=$handle
|
||||||
|
did_yui=$did
|
||||||
|
pds=`cat $f|jq -r ".didDoc.service.[].serviceEndpoint"|cut -d / -f 3`
|
||||||
|
if [ "$pds" != "syu.is" ];then
|
||||||
|
pds=bsky.social
|
||||||
|
fi
|
||||||
|
version=4
|
||||||
|
#rkey=syui
|
||||||
|
req=com.atproto.repo.putRecord
|
||||||
|
url=https://$pds/xrpc/$req
|
||||||
|
|
||||||
|
cname=dragon
|
||||||
|
|
||||||
|
if [ "$rkey" = "ai" ];then
|
||||||
|
cname=$rkey
|
||||||
|
gender=none
|
||||||
|
fi
|
||||||
|
if [ "$rkey" = "syui" ];then
|
||||||
|
cname=chinese
|
||||||
|
did=$did_syui
|
||||||
|
handle=syui.ai
|
||||||
|
gender=male
|
||||||
|
fi
|
||||||
|
if [ "$rkey" = "self" ];then
|
||||||
|
cname=manny
|
||||||
|
unset did handle gender
|
||||||
|
pds=bsky.social
|
||||||
|
plc=plc.directory
|
||||||
|
fi
|
||||||
|
season=1
|
||||||
|
group=test
|
||||||
|
lv=1
|
||||||
|
hp=1
|
||||||
|
exp=0
|
||||||
|
rare=0
|
||||||
|
mode=0
|
||||||
|
attack=0
|
||||||
|
attack_post=0
|
||||||
|
critical=0
|
||||||
|
critical_d=0
|
||||||
|
card=0
|
||||||
|
weapon=0
|
||||||
|
coin=0
|
||||||
|
count=0
|
||||||
|
|
||||||
|
case $cname in
|
||||||
|
ai)
|
||||||
|
group=origin
|
||||||
|
season=0
|
||||||
|
mode=2
|
||||||
|
;;
|
||||||
|
manny|quinn)
|
||||||
|
group=test
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
group=fantasy
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
json_item="
|
||||||
|
\"coin\": [{\"id\": 0, \"cp\": 0, \"rare\": 0, \"count\": 0}],
|
||||||
|
\"card\": [{\"id\": 0, \"cp\": 0, \"rare\": 0, \"count\": 0}],
|
||||||
|
\"weapon\": [{\"id\": 0, \"cp\": 0, \"rare\": 0, \"count\": 0}]
|
||||||
|
"
|
||||||
|
|
||||||
|
json="
|
||||||
|
{
|
||||||
|
\"repo\": \"$handle_yui\",
|
||||||
|
\"did\": \"$did_yui\",
|
||||||
|
\"collection\": \"$col\",
|
||||||
|
\"rkey\": \"$rkey\",
|
||||||
|
\"record\": {
|
||||||
|
\"version\": $version,
|
||||||
|
\"did\": \"$did\",
|
||||||
|
\"handle\": \"$handle\",
|
||||||
|
\"plc\": \"$plc\",
|
||||||
|
\"pds\": \"$pds\",
|
||||||
|
\"player\": {
|
||||||
|
\"limit\": false,
|
||||||
|
\"login\": false,
|
||||||
|
\"ten\": 0,
|
||||||
|
\"gender\": \"$gender\"
|
||||||
|
},
|
||||||
|
\"character\": {
|
||||||
|
$json
|
||||||
|
},
|
||||||
|
\"item\": {
|
||||||
|
$json_item
|
||||||
|
},
|
||||||
|
\"createdAt\": \"${created}\",
|
||||||
|
\"updatedAt\": \"${created}\"
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
|
||||||
|
if echo $json|jq . ;then
|
||||||
|
echo y
|
||||||
|
read y
|
||||||
|
if [ "y" = "$y" ];then
|
||||||
|
t=`curl -sL -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $token" -d $json $url`
|
||||||
|
echo $t|jq .
|
||||||
|
#f=~/ai/ue/json/v${version}_${rkey}.json
|
||||||
|
#if [ -f $f ];then
|
||||||
|
# get_game_user $rkey >! $f
|
||||||
|
#fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function ue-system() {
|
||||||
|
col=ai.syui.system
|
||||||
|
rkey=self
|
||||||
|
did=$did
|
||||||
|
handle=$handle
|
||||||
|
pds=`cat $f|jq -r ".didDoc.service.[].serviceEndpoint"|cut -d / -f 3`
|
||||||
|
if [ "$pds" != "syu.is" ];then
|
||||||
|
pds=bsky.social
|
||||||
|
fi
|
||||||
|
version=1
|
||||||
|
#rkey=syui
|
||||||
|
req=com.atproto.repo.putRecord
|
||||||
|
url=https://$pds/xrpc/$req
|
||||||
|
imgurl=https://git.syui.ai/ai/ai/raw/branch/main/img/item/card
|
||||||
|
json_card=" \"id\": $id, \"name\": \"$name\", \"img\": \"${imgurl}/${id}.webp\""
|
||||||
|
json_card=`curl -sL https://git.syui.ai/ai/ai/raw/branch/main/json/card.json|jq ".[]"`
|
||||||
|
json_weapon=`curl -sL https://git.syui.ai/ai/ai/raw/branch/main/json/weapon.json|jq ".[]"`
|
||||||
|
json_system=`curl -sL https://git.syui.ai/ai/ai/raw/branch/main/json/system.json|jq ".[]"`
|
||||||
|
json_character=`curl -sL https://git.syui.ai/ai/ai/raw/branch/main/json/character.json|jq ".[]"`
|
||||||
|
json_ability=`curl -sL https://git.syui.ai/ai/ai/raw/branch/main/json/ability.json|jq ".[]"`
|
||||||
|
json="
|
||||||
|
{
|
||||||
|
\"repo\": \"$handle\",
|
||||||
|
\"did\": \"$did\",
|
||||||
|
\"collection\": \"$col\",
|
||||||
|
\"rkey\": \"$rkey\",
|
||||||
|
\"record\": {
|
||||||
|
\"card\": ${json_card},
|
||||||
|
\"weapon\": ${json_weapon},
|
||||||
|
\"system\": ${json_system},
|
||||||
|
\"character\": ${json_character},
|
||||||
|
\"ability\": ${json_ability},
|
||||||
|
\"createdAt\": \"${created}\",
|
||||||
|
\"updatedAt\": \"${created}\"
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
|
||||||
|
if echo $json|jq . ;then
|
||||||
|
echo y
|
||||||
|
read y
|
||||||
|
if [ "y" = "$y" ];then
|
||||||
|
t=`curl -sL -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $token" -d $json $url`
|
||||||
|
echo $t|jq .
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
134
social-app-custom/AppInfo.tsx
Normal file
134
social-app-custom/AppInfo.tsx
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {View, Text, StyleSheet, Pressable, Linking} from 'react-native'
|
||||||
|
|
||||||
|
interface AppInfoProps {
|
||||||
|
onLinkPress?: (url: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AppInfo({onLinkPress}: AppInfoProps) {
|
||||||
|
const handleLinkPress = (url: string) => {
|
||||||
|
if (onLinkPress) {
|
||||||
|
onLinkPress(url)
|
||||||
|
} else {
|
||||||
|
Linking.openURL(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>About This App</Text>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
This is a customized AT Protocol social networking client. It allows you to
|
||||||
|
connect to any Personal Data Server (PDS) and participate in the decentralized
|
||||||
|
social network.
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>Key Features</Text>
|
||||||
|
<View style={styles.list}>
|
||||||
|
<Text style={styles.listItem}>• Connect to any AT Protocol PDS</Text>
|
||||||
|
<Text style={styles.listItem}>• Post text, images, and videos</Text>
|
||||||
|
<Text style={styles.listItem}>• Follow users and view timelines</Text>
|
||||||
|
<Text style={styles.listItem}>• Customize feeds and moderation settings</Text>
|
||||||
|
<Text style={styles.listItem}>• Direct messaging support</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>Open Source</Text>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
This application is based on the Bluesky social-app, licensed under the MIT
|
||||||
|
License. The original source code is available at:
|
||||||
|
</Text>
|
||||||
|
<Pressable
|
||||||
|
onPress={() =>
|
||||||
|
handleLinkPress('https://github.com/bluesky-social/social-app')
|
||||||
|
}>
|
||||||
|
<Text style={styles.link}>github.com/bluesky-social/social-app</Text>
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>AT Protocol</Text>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
This app uses the AT Protocol (Authenticated Transfer Protocol), an open and
|
||||||
|
decentralized standard for social applications.
|
||||||
|
</Text>
|
||||||
|
<Pressable onPress={() => handleLinkPress('https://atproto.com')}>
|
||||||
|
<Text style={styles.link}>atproto.com</Text>
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>License</Text>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
Copyright 2023–2025 Bluesky Social PBC
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software.
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>Contact</Text>
|
||||||
|
<Pressable onPress={() => handleLinkPress('https://syu.is')}>
|
||||||
|
<Text style={styles.link}>https://syu.is</Text>
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.versionText}>Version 1.0.0</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
section: {
|
||||||
|
marginBottom: 24,
|
||||||
|
},
|
||||||
|
sectionTitle: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: '600',
|
||||||
|
color: '#1d1d1f',
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
paragraph: {
|
||||||
|
fontSize: 15,
|
||||||
|
lineHeight: 22,
|
||||||
|
color: '#3a3a3c',
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
marginLeft: 8,
|
||||||
|
marginTop: 8,
|
||||||
|
},
|
||||||
|
listItem: {
|
||||||
|
fontSize: 15,
|
||||||
|
lineHeight: 24,
|
||||||
|
color: '#3a3a3c',
|
||||||
|
},
|
||||||
|
link: {
|
||||||
|
fontSize: 15,
|
||||||
|
color: '#007aff',
|
||||||
|
textDecorationLine: 'underline',
|
||||||
|
marginTop: 8,
|
||||||
|
},
|
||||||
|
versionText: {
|
||||||
|
fontSize: 13,
|
||||||
|
color: '#8e8e93',
|
||||||
|
fontStyle: 'italic',
|
||||||
|
},
|
||||||
|
})
|
||||||
95
social-app-custom/LicenseNotice.tsx
Normal file
95
social-app-custom/LicenseNotice.tsx
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {View, Text, StyleSheet, Pressable, Linking} from 'react-native'
|
||||||
|
|
||||||
|
export default function LicenseNotice() {
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<Text style={styles.title}>Open Source Licenses</Text>
|
||||||
|
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.projectName}>Bluesky Social App</Text>
|
||||||
|
<Text style={styles.license}>MIT License</Text>
|
||||||
|
<Text style={styles.copyright}>Copyright 2023–2025 Bluesky Social PBC</Text>
|
||||||
|
|
||||||
|
<Text style={styles.licenseText}>
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text style={styles.licenseText}>
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text style={styles.licenseText}>
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Pressable
|
||||||
|
onPress={() =>
|
||||||
|
Linking.openURL('https://github.com/bluesky-social/social-app')
|
||||||
|
}>
|
||||||
|
<Text style={styles.link}>View Source Code</Text>
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
padding: 16,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
marginBottom: 20,
|
||||||
|
color: '#1d1d1f',
|
||||||
|
},
|
||||||
|
section: {
|
||||||
|
marginBottom: 24,
|
||||||
|
padding: 16,
|
||||||
|
backgroundColor: '#f5f5f7',
|
||||||
|
borderRadius: 8,
|
||||||
|
},
|
||||||
|
projectName: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: '600',
|
||||||
|
marginBottom: 8,
|
||||||
|
color: '#1d1d1f',
|
||||||
|
},
|
||||||
|
license: {
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: '500',
|
||||||
|
color: '#007aff',
|
||||||
|
marginBottom: 4,
|
||||||
|
},
|
||||||
|
copyright: {
|
||||||
|
fontSize: 13,
|
||||||
|
color: '#3a3a3c',
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
licenseText: {
|
||||||
|
fontSize: 12,
|
||||||
|
lineHeight: 18,
|
||||||
|
color: '#3a3a3c',
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
link: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: '#007aff',
|
||||||
|
textDecorationLine: 'underline',
|
||||||
|
marginTop: 8,
|
||||||
|
},
|
||||||
|
})
|
||||||
163
social-app-custom/PrivacyContent.tsx
Normal file
163
social-app-custom/PrivacyContent.tsx
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {View, Text, StyleSheet, Pressable, Linking} from 'react-native'
|
||||||
|
|
||||||
|
interface PrivacyContentProps {
|
||||||
|
onLinkPress?: (url: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function PrivacyContent({onLinkPress}: PrivacyContentProps) {
|
||||||
|
const handleLinkPress = (url: string) => {
|
||||||
|
if (onLinkPress) {
|
||||||
|
onLinkPress(url)
|
||||||
|
} else {
|
||||||
|
Linking.openURL(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>Introduction</Text>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
This Privacy Policy explains how this AT Protocol client application
|
||||||
|
(hereinafter referred to as "the App") handles personal information.
|
||||||
|
Please read this policy carefully before using the App.
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>Information We Collect</Text>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
The App may collect and use the following information:
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text style={styles.subTitle}>1. Information Collected Automatically</Text>
|
||||||
|
<View style={styles.list}>
|
||||||
|
<Text style={styles.listItem}>• Device information (model, OS version)</Text>
|
||||||
|
<Text style={styles.listItem}>• App usage data (sessions, features used)</Text>
|
||||||
|
<Text style={styles.listItem}>• Crash logs and performance data</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Text style={styles.subTitle}>2. Information Provided by Users</Text>
|
||||||
|
<View style={styles.list}>
|
||||||
|
<Text style={styles.listItem}>
|
||||||
|
• DID (Decentralized Identifier) and handle for authentication
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.listItem}>• Posts, media, and social interactions</Text>
|
||||||
|
<Text style={styles.listItem}>• Profile information (avatar, display name, bio)</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.highlight}>
|
||||||
|
<Text style={styles.highlightText}>
|
||||||
|
Important: Your data is stored on your chosen PDS (Personal Data Server).
|
||||||
|
This app does not store your content on our servers.
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>How We Use Your Information</Text>
|
||||||
|
<View style={styles.list}>
|
||||||
|
<Text style={styles.listItem}>
|
||||||
|
• To provide AT Protocol social networking features
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.listItem}>• To improve app performance and user experience</Text>
|
||||||
|
<Text style={styles.listItem}>• To diagnose and fix technical issues</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>Data Sharing</Text>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
The App interacts with your chosen PDS and AppView services. Your posts and
|
||||||
|
profile information are shared according to the AT Protocol specification and
|
||||||
|
your privacy settings.
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>Your Rights</Text>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
You have the right to access, modify, or delete your data through your PDS.
|
||||||
|
You can also switch to a different PDS at any time while maintaining your
|
||||||
|
identity.
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>Contact</Text>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
For questions about this Privacy Policy, please contact:
|
||||||
|
</Text>
|
||||||
|
<Pressable onPress={() => handleLinkPress('https://syu.is')}>
|
||||||
|
<Text style={styles.link}>https://syu.is</Text>
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.lastUpdated}>Last Updated: December 3, 2025</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
section: {
|
||||||
|
marginBottom: 24,
|
||||||
|
},
|
||||||
|
sectionTitle: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: '600',
|
||||||
|
color: '#1d1d1f',
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
subTitle: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: '500',
|
||||||
|
color: '#1d1d1f',
|
||||||
|
marginTop: 12,
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
paragraph: {
|
||||||
|
fontSize: 15,
|
||||||
|
lineHeight: 22,
|
||||||
|
color: '#3a3a3c',
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
marginLeft: 8,
|
||||||
|
marginTop: 8,
|
||||||
|
},
|
||||||
|
listItem: {
|
||||||
|
fontSize: 15,
|
||||||
|
lineHeight: 24,
|
||||||
|
color: '#3a3a3c',
|
||||||
|
},
|
||||||
|
highlight: {
|
||||||
|
backgroundColor: '#fff3cd',
|
||||||
|
borderLeftWidth: 4,
|
||||||
|
borderLeftColor: '#ffc107',
|
||||||
|
padding: 12,
|
||||||
|
marginTop: 12,
|
||||||
|
borderRadius: 4,
|
||||||
|
},
|
||||||
|
highlightText: {
|
||||||
|
fontSize: 14,
|
||||||
|
lineHeight: 20,
|
||||||
|
color: '#856404',
|
||||||
|
},
|
||||||
|
link: {
|
||||||
|
fontSize: 15,
|
||||||
|
color: '#007aff',
|
||||||
|
textDecorationLine: 'underline',
|
||||||
|
marginTop: 8,
|
||||||
|
},
|
||||||
|
lastUpdated: {
|
||||||
|
fontSize: 13,
|
||||||
|
color: '#8e8e93',
|
||||||
|
fontStyle: 'italic',
|
||||||
|
},
|
||||||
|
})
|
||||||
42
social-app-custom/PrivacyPolicy.screen.tsx
Normal file
42
social-app-custom/PrivacyPolicy.screen.tsx
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {View} from 'react-native'
|
||||||
|
import {msg} from '@lingui/macro'
|
||||||
|
import {useLingui} from '@lingui/react'
|
||||||
|
import {useFocusEffect} from '@react-navigation/native'
|
||||||
|
|
||||||
|
import {usePalette} from '#/lib/hooks/usePalette'
|
||||||
|
import {
|
||||||
|
type CommonNavigatorParams,
|
||||||
|
type NativeStackScreenProps,
|
||||||
|
} from '#/lib/routes/types'
|
||||||
|
import {s} from '#/lib/styles'
|
||||||
|
import {useSetMinimalShellMode} from '#/state/shell'
|
||||||
|
import {ScrollView} from '#/view/com/util/Views'
|
||||||
|
import * as Layout from '#/components/Layout'
|
||||||
|
import {ViewHeader} from '../com/util/ViewHeader'
|
||||||
|
import PrivacyContent from '#/components/custom/PrivacyContent'
|
||||||
|
|
||||||
|
type Props = NativeStackScreenProps<CommonNavigatorParams, 'PrivacyPolicy'>
|
||||||
|
export const PrivacyPolicyScreen = (_props: Props) => {
|
||||||
|
const pal = usePalette('default')
|
||||||
|
const {_} = useLingui()
|
||||||
|
const setMinimalShellMode = useSetMinimalShellMode()
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
React.useCallback(() => {
|
||||||
|
setMinimalShellMode(false)
|
||||||
|
}, [setMinimalShellMode]),
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Layout.Screen>
|
||||||
|
<ViewHeader title={_(msg`Privacy Policy`)} />
|
||||||
|
<ScrollView style={[s.hContentRegion, pal.view]}>
|
||||||
|
<View style={[s.p20]}>
|
||||||
|
<PrivacyContent />
|
||||||
|
</View>
|
||||||
|
<View style={s.footerSpacer} />
|
||||||
|
</ScrollView>
|
||||||
|
</Layout.Screen>
|
||||||
|
)
|
||||||
|
}
|
||||||
38
social-app-custom/Support.screen.tsx
Normal file
38
social-app-custom/Support.screen.tsx
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {msg} from '@lingui/macro'
|
||||||
|
import {useLingui} from '@lingui/react'
|
||||||
|
import {useFocusEffect} from '@react-navigation/native'
|
||||||
|
|
||||||
|
import {usePalette} from '#/lib/hooks/usePalette'
|
||||||
|
import {
|
||||||
|
type CommonNavigatorParams,
|
||||||
|
type NativeStackScreenProps,
|
||||||
|
} from '#/lib/routes/types'
|
||||||
|
import {s} from '#/lib/styles'
|
||||||
|
import {useSetMinimalShellMode} from '#/state/shell'
|
||||||
|
import {ViewHeader} from '#/view/com/util/ViewHeader'
|
||||||
|
import {ScrollView} from '#/view/com/util/Views'
|
||||||
|
import * as Layout from '#/components/Layout'
|
||||||
|
import AppInfo from '#/components/custom/AppInfo'
|
||||||
|
|
||||||
|
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Support'>
|
||||||
|
export const SupportScreen = (_props: Props) => {
|
||||||
|
const pal = usePalette('default')
|
||||||
|
const setMinimalShellMode = useSetMinimalShellMode()
|
||||||
|
const {_} = useLingui()
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
React.useCallback(() => {
|
||||||
|
setMinimalShellMode(false)
|
||||||
|
}, [setMinimalShellMode]),
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Layout.Screen>
|
||||||
|
<ViewHeader title={_(msg`App Info`)} />
|
||||||
|
<ScrollView style={[s.hContentRegion, pal.view]}>
|
||||||
|
<AppInfo />
|
||||||
|
</ScrollView>
|
||||||
|
</Layout.Screen>
|
||||||
|
)
|
||||||
|
}
|
||||||
9
social-app-custom/app.config.patch.js
Normal file
9
social-app-custom/app.config.patch.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
// Aiat app configuration overrides
|
||||||
|
module.exports = {
|
||||||
|
name: 'Aiat',
|
||||||
|
slug: 'aiat',
|
||||||
|
scheme: 'aiat',
|
||||||
|
owner: 'syui', // Your Expo account
|
||||||
|
bundleIdentifier: 'ai.syui.at',
|
||||||
|
// Icon will be set separately
|
||||||
|
}
|
||||||
44
social-app-custom/bin/build.zsh
Executable file
44
social-app-custom/bin/build.zsh
Executable file
@@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/zsh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
d=~/ai/at/repos/social-app
|
||||||
|
APP_NAME=Aiat
|
||||||
|
PKG=aiat
|
||||||
|
TEAM_NAME=
|
||||||
|
TEAM_ID=
|
||||||
|
CERT="Apple Distribution: ${TEAM_NAME} (${TEAM_ID})"
|
||||||
|
MAIL=user@example.com
|
||||||
|
KEY_CHAIN=EXAMPLE
|
||||||
|
|
||||||
|
cd $d
|
||||||
|
# npx expo prebuild --clean
|
||||||
|
# cd ios && pod install && cd ..
|
||||||
|
|
||||||
|
## アーカイブ
|
||||||
|
xcodebuild -workspace ios/${PKG}.xcworkspace \
|
||||||
|
-scheme ${PKG} \
|
||||||
|
-configuration Release \
|
||||||
|
-archivePath build/${APP_NAME}.xcarchive \
|
||||||
|
-allowProvisioningUpdates \
|
||||||
|
archive
|
||||||
|
|
||||||
|
cd build
|
||||||
|
|
||||||
|
# IPA作成
|
||||||
|
rm -rf Payload ${APP_NAME}.ipa
|
||||||
|
mkdir -p Payload
|
||||||
|
cp -R ${APP_NAME}.xcarchive/Products/Applications/${PKG}.app Payload/
|
||||||
|
cp ../store.mobileprovision Payload/${PKG}.app/embedded.mobileprovision
|
||||||
|
|
||||||
|
# entitlements抽出
|
||||||
|
security cms -D -i Payload/${PKG}.app/embedded.mobileprovision > /tmp/profile.plist
|
||||||
|
/usr/libexec/PlistBuddy -x -c "Print :Entitlements" /tmp/profile.plist > /tmp/entitlements.plist
|
||||||
|
|
||||||
|
codesign -f -s "$CERT" Payload/${PKG}.app/Frameworks/*.framework 2>/dev/null || true
|
||||||
|
codesign -f -s "$CERT" --entitlements /tmp/entitlements.plist Payload/${PKG}.app
|
||||||
|
|
||||||
|
zip -r ${APP_NAME}.ipa Payload
|
||||||
|
|
||||||
|
xcrun altool --upload-app -f ${APP_NAME}.ipa -t ios -u "${MAIL}" -p "@keychain:${KEY_CHAIN}"
|
||||||
|
|
||||||
|
echo "Upload complete"
|
||||||
86
social-app-custom/bin/install.zsh
Normal file
86
social-app-custom/bin/install.zsh
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
#!/bin/zsh
|
||||||
|
|
||||||
|
if [ "$1" = "social-app-custom" ];then
|
||||||
|
at-social-app-custom-pages
|
||||||
|
at-social-app-custom-screens
|
||||||
|
at-social-app-aiat-config
|
||||||
|
at-social-app-aiat-logo
|
||||||
|
at-origin-social-app
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
function at-social-app-custom-pages() {
|
||||||
|
d_=$d/repos/social-app
|
||||||
|
custom=$d/social-app-custom
|
||||||
|
|
||||||
|
echo "copying custom components to social-app"
|
||||||
|
|
||||||
|
# Create components directory if not exists
|
||||||
|
mkdir -p ${d_}/src/components/custom
|
||||||
|
|
||||||
|
# Copy custom components
|
||||||
|
cp ${custom}/PrivacyContent.tsx ${d_}/src/components/custom/
|
||||||
|
cp ${custom}/AppInfo.tsx ${d_}/src/components/custom/
|
||||||
|
|
||||||
|
echo "custom components copied successfully"
|
||||||
|
}
|
||||||
|
|
||||||
|
function at-social-app-aiat-config() {
|
||||||
|
d_=$d/repos/social-app
|
||||||
|
custom=$d/social-app-custom
|
||||||
|
|
||||||
|
echo "applying Aiat configuration"
|
||||||
|
|
||||||
|
# Update app.config.js
|
||||||
|
cd ${d_}
|
||||||
|
|
||||||
|
# Backup original
|
||||||
|
cp app.config.js app.config.js.orig
|
||||||
|
|
||||||
|
# Apply changes using sed
|
||||||
|
sed -i "s/name: 'Bluesky'/name: 'Aiat'/g" app.config.js
|
||||||
|
sed -i "s/slug: 'bluesky'/slug: 'aiat'/g" app.config.js
|
||||||
|
sed -i "s/scheme: 'bluesky'/scheme: 'aiat'/g" app.config.js
|
||||||
|
sed -i "s/owner: 'blueskysocial'/owner: 'syui'/g" app.config.js
|
||||||
|
sed -i "s/bundleIdentifier: 'xyz.blueskyweb.app'/bundleIdentifier: 'ai.syui.at'/g" app.config.js
|
||||||
|
|
||||||
|
# Update package.json name
|
||||||
|
sed -i 's/"name": "bsky.app"/"name": "aiat"/g' package.json
|
||||||
|
|
||||||
|
echo "Aiat configuration applied"
|
||||||
|
}
|
||||||
|
|
||||||
|
function at-social-app-aiat-logo() {
|
||||||
|
d_=$d/repos/social-app
|
||||||
|
custom=$d/social-app-custom
|
||||||
|
|
||||||
|
echo "applying Aiat logo"
|
||||||
|
|
||||||
|
# Create logo directory if not exists
|
||||||
|
mkdir -p ${custom}/assets
|
||||||
|
|
||||||
|
# Copy logo if exists in custom folder
|
||||||
|
if [ -f ${custom}/assets/icon.png ]; then
|
||||||
|
cp ${custom}/assets/icon.png ${d_}/assets/app-icons/ios_icon_default_next.png
|
||||||
|
echo "Aiat logo applied"
|
||||||
|
else
|
||||||
|
echo "Warning: Logo file not found at ${custom}/assets/icon.png"
|
||||||
|
echo "Please add your logo file there"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function at-social-app-custom-screens() {
|
||||||
|
d_=$d/repos/social-app
|
||||||
|
custom=$d/social-app-custom
|
||||||
|
|
||||||
|
echo "applying custom screens"
|
||||||
|
|
||||||
|
# Copy custom screen files
|
||||||
|
cp ${custom}/PrivacyPolicy.screen.tsx ${d_}/src/view/screens/PrivacyPolicy.tsx
|
||||||
|
cp ${custom}/Support.screen.tsx ${d_}/src/view/screens/Support.tsx
|
||||||
|
cp ${custom}/LicenseNotice.tsx ${d_}/src/components/custom/
|
||||||
|
|
||||||
|
echo "custom screens applied"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user