From 3526781af25d6c19438b611f5aa9b340b5a13ad0 Mon Sep 17 00:00:00 2001 From: syui Date: Thu, 8 Jan 2026 08:32:20 +0900 Subject: [PATCH] fix patch test --- install.zsh | 52 ++++++- ios/README.md | 6 +- ios/build.zsh | 24 +++- ios/patching/005-social-app-ios-screens.patch | 2 +- ios/preview.zsh | 2 - .../200-feed-generator-custom-existing.patch | 64 +++++++++ patching/210-pds-subscriberepos-no-auth.patch | 133 ++++++++++++++++++ 7 files changed, 268 insertions(+), 15 deletions(-) create mode 100644 patching/200-feed-generator-custom-existing.patch create mode 100644 patching/210-pds-subscriberepos-no-auth.patch diff --git a/install.zsh b/install.zsh index a4c331b..07a2275 100755 --- a/install.zsh +++ b/install.zsh @@ -77,7 +77,7 @@ PATCH_FILES=( "130-atproto-ozone-enable-daemon-v2.patch" "152-indigo-newpds-dayper-limit-pr707.diff" "190-bgs-disable-ratelimit.patch" - "200-feed-generator-custom.patch" + "200-feed-generator-custom-existing.patch" ) function at-repos-clone() { @@ -331,6 +331,54 @@ export const SOCIAL_APP_DOMAIN =\ popd > /dev/null } +function at-repos-feed-generator-newfiles() { + echo "" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "📝 Creating feed-generator new files..." + + # Create app.ts + cat > $d/repos/feed-generator/src/algos/app.ts <<'EOF' +import { QueryParams } from '../lexicon/types/app/bsky/feed/getFeedSkeleton' +import { AppContext } from '../config' + +// max 15 chars +export const shortname = 'app' + +export const handler = async (ctx: AppContext, params: QueryParams) => { + let builder = ctx.db + .selectFrom('post') + .selectAll() + .orderBy('indexedAt', 'desc') + .orderBy('cid', 'desc') + .limit(params.limit) + + if (params.cursor) { + const timeStr = new Date(parseInt(params.cursor, 10)).toISOString() + builder = builder.where('post.indexedAt', '<', timeStr) + } + const res = await builder.execute() + + const feed = res.map((row) => ({ + post: row.uri, + })) + + let cursor: string | undefined + const last = res.at(-1) + if (last) { + cursor = new Date(last.indexedAt).getTime().toString(10) + } + + return { + cursor, + feed, + } +} +EOF + + echo "✅ Created src/algos/app.ts" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +} + function at-repos-build-docker-atproto() { cd $d docker image prune -a @@ -533,6 +581,7 @@ case "$1" in at-repos-social-app-ios-patch at-repos-patch-apply-all at-repos-ozone-patch + at-repos-feed-generator-newfiles show-failed-patches exit ;; @@ -574,6 +623,7 @@ case "`cat /etc/hostname`" in at-repos-social-app-ios-patch at-repos-patch-apply-all at-repos-ozone-patch + at-repos-feed-generator-newfiles show-failed-patches at-repos-build-docker-atproto at-repos-push-docker diff --git a/ios/README.md b/ios/README.md index c08d5da..678c1b9 100644 --- a/ios/README.md +++ b/ios/README.md @@ -1,9 +1,7 @@ 今回の./ios (social-app)開発の要点をまとめます。 1. MITのライセンスを遵守すること、iosアプリとして出品しても問題ないようにすること -https://raw.githubusercontent.com/bluesky-social/social-app/refs/heads/main/LICENSE - 2. "Bluesky"という名称を使用しないこと。アイコンの変更。リンクの変更 +3. selfhostでも動くこと。 -3. selfhostでも動くこと。これはすでにpatchで実現しています。 - +https://raw.githubusercontent.com/bluesky-social/social-app/refs/heads/main/LICENSE diff --git a/ios/build.zsh b/ios/build.zsh index a379cff..cef231a 100755 --- a/ios/build.zsh +++ b/ios/build.zsh @@ -78,11 +78,11 @@ function cleanup_build { # 3. CocoaPods echo "3. Installing CocoaPods..." - # Ensure PATH includes Homebrew ruby gems if needed - export PATH="/opt/homebrew/lib/ruby/gems/3.4.0/bin:$PATH" - cd ios - pod install - cd .. + if [ -z "$1" ];then + cd ios + pod install + cd .. + fi # 4. Signing (Automated) echo "4. Configuring Xcode Signing..." @@ -132,6 +132,9 @@ EOF case $1 in i) + echo "Skipping cleanup_build..." + ;; + *) cleanup_build ;; esac @@ -167,8 +170,15 @@ cp -R ${APP_NAME}.xcarchive/Products/Applications/${APP_NAME}.app Payload/ # store.mobileprovisionの存在確認とコピー # https://developer.apple.com/account/resources/profiles/list if [ ! -f "$MOBILEPROVISION" ]; then - echo "Error: store.mobileprovision not found at $MOBILEPROVISION" - exit 1 + # 親ディレクトリからコピーを試みる + PARENT_MOBILEPROVISION="$SCRIPT_DIR/../embedded.mobileprovision" + if [ -f "$PARENT_MOBILEPROVISION" ]; then + echo "Copying mobileprovision from $PARENT_MOBILEPROVISION to $MOBILEPROVISION" + cp "$PARENT_MOBILEPROVISION" "$MOBILEPROVISION" + else + echo "Error: store.mobileprovision not found at $MOBILEPROVISION or $PARENT_MOBILEPROVISION" + exit 1 + fi fi cp "$MOBILEPROVISION" Payload/${APP_NAME}.app/embedded.mobileprovision diff --git a/ios/patching/005-social-app-ios-screens.patch b/ios/patching/005-social-app-ios-screens.patch index 492e263..f54c8b0 100644 --- a/ios/patching/005-social-app-ios-screens.patch +++ b/ios/patching/005-social-app-ios-screens.patch @@ -32,7 +32,7 @@ index 77f219e55..53f5e0cc0 100644 - to="https://bsky.social/about/support/tos" + label={_(msg`syu.is Terms of Service`)} + to="https://syu.is/about/support/tos" - style={[a.text_md, a.leading_normal]}> + style={[a.text_md, a.leading_snug]}> - Bluesky Social Terms of Service + syu.is Terms of Service diff --git a/ios/preview.zsh b/ios/preview.zsh index 3644670..96a412d 100755 --- a/ios/preview.zsh +++ b/ios/preview.zsh @@ -70,8 +70,6 @@ npx expo prebuild --platform ios --clean # 3. CocoaPods echo "3. Installing CocoaPods..." -# Ensure PATH includes Homebrew ruby gems if needed -export PATH="/opt/homebrew/lib/ruby/gems/3.4.0/bin:$PATH" cd ios pod install cd .. diff --git a/patching/200-feed-generator-custom-existing.patch b/patching/200-feed-generator-custom-existing.patch new file mode 100644 index 0000000..0925d08 --- /dev/null +++ b/patching/200-feed-generator-custom-existing.patch @@ -0,0 +1,64 @@ +diff --git a/src/algos/index.ts b/src/algos/index.ts +index b7ee48a..102cb93 100644 +--- a/src/algos/index.ts ++++ b/src/algos/index.ts +@@ -4,11 +4,13 @@ import { + OutputSchema as AlgoOutput, + } from '../lexicon/types/app/bsky/feed/getFeedSkeleton' + import * as whatsAlf from './whats-alf' ++import * as app from './app' + + type AlgoHandler = (ctx: AppContext, params: QueryParams) => Promise + + const algos: Record = { + [whatsAlf.shortname]: whatsAlf.handler, ++ [app.shortname]: app.handler, + } + + export default algos +diff --git a/src/index.ts b/src/index.ts +index 7128525..40d985c 100644 +--- a/src/index.ts ++++ b/src/index.ts +@@ -22,8 +22,10 @@ const run = async () => { + }) + await server.start() + console.log( +- `🤖 running feed generator at http://${server.cfg.listenhost}:${server.cfg.port}`, ++ `running feed generator at http://${server.cfg.listenhost}:${server.cfg.port}`, + ) ++ console.log('Supported algos:', Object.keys(require('./algos').default)) ++ console.log('Publisher DID:', server.cfg.publisherDid) + } + + const maybeStr = (val?: string) => { +diff --git a/src/methods/feed-generation.ts b/src/methods/feed-generation.ts +index 0f4989e..17be062 100644 +--- a/src/methods/feed-generation.ts ++++ b/src/methods/feed-generation.ts +@@ -10,7 +10,7 @@ export default function (server: Server, ctx: AppContext) { + const feedUri = new AtUri(params.feed) + const algo = algos[feedUri.rkey] + if ( +- feedUri.hostname !== ctx.cfg.publisherDid || ++ //feedUri.hostname !== ctx.cfg.publisherDid || + feedUri.collection !== 'app.bsky.feed.generator' || + !algo + ) { +diff --git a/package.json b/package.json +index 1431a9e..6a7c33c 100644 +--- a/package.json ++++ b/package.json +@@ -23,9 +23,11 @@ + "dotenv": "^16.0.3", + "express": "^4.18.2", + "kysely": "^0.27.4", +- "multiformats": "^9.9.0" ++ "multiformats": "^9.9.0", ++ "ws": "^8.14.2" + }, + "devDependencies": { ++ "@types/ws": "^8.5.10", + "@types/better-sqlite3": "^7.6.11", + "@types/express": "^4.17.17", + "@types/node": "^20.1.2", diff --git a/patching/210-pds-subscriberepos-no-auth.patch b/patching/210-pds-subscriberepos-no-auth.patch new file mode 100644 index 0000000..2783588 --- /dev/null +++ b/patching/210-pds-subscriberepos-no-auth.patch @@ -0,0 +1,133 @@ +diff --git a/packages/pds/src/api/com/atproto/sync/subscribeRepos.ts b/packages/pds/src/api/com/atproto/sync/subscribeRepos.ts +index c2418d343..f81789df0 100644 +--- a/packages/pds/src/api/com/atproto/sync/subscribeRepos.ts ++++ b/packages/pds/src/api/com/atproto/sync/subscribeRepos.ts +@@ -5,68 +5,71 @@ import { httpLogger } from '../../../../logger' + import { Outbox } from '../../../../sequencer/outbox' + + export default function (server: Server, ctx: AppContext) { +- server.com.atproto.sync.subscribeRepos(async function* ({ params, signal }) { +- const { cursor } = params +- const outbox = new Outbox(ctx.sequencer, { +- maxBufferSize: ctx.cfg.subscription.maxBuffer, +- }) +- httpLogger.info({ cursor }, 'request to com.atproto.sync.subscribeRepos') ++ server.com.atproto.sync.subscribeRepos({ ++ auth: undefined, ++ handler: async function* ({ params, signal }) { ++ const { cursor } = params ++ const outbox = new Outbox(ctx.sequencer, { ++ maxBufferSize: ctx.cfg.subscription.maxBuffer, ++ }) ++ httpLogger.info({ cursor }, 'request to com.atproto.sync.subscribeRepos') + +- const backfillTime = new Date( +- Date.now() - ctx.cfg.subscription.repoBackfillLimitMs, +- ).toISOString() +- let outboxCursor: number | undefined = undefined +- if (cursor !== undefined) { +- const [next, curr] = await Promise.all([ +- ctx.sequencer.next(cursor), +- ctx.sequencer.curr(), +- ]) +- if (cursor > (curr ?? 0)) { +- throw new InvalidRequestError('Cursor in the future.', 'FutureCursor') +- } else if (next && next.sequencedAt < backfillTime) { +- // if cursor is before backfill time, find earliest cursor from backfill window +- yield { +- $type: '#info', +- name: 'OutdatedCursor', +- message: 'Requested cursor exceeded limit. Possibly missing events', ++ const backfillTime = new Date( ++ Date.now() - ctx.cfg.subscription.repoBackfillLimitMs, ++ ).toISOString() ++ let outboxCursor: number | undefined = undefined ++ if (cursor !== undefined) { ++ const [next, curr] = await Promise.all([ ++ ctx.sequencer.next(cursor), ++ ctx.sequencer.curr(), ++ ]) ++ if (cursor > (curr ?? 0)) { ++ throw new InvalidRequestError('Cursor in the future.', 'FutureCursor') ++ } else if (next && next.sequencedAt < backfillTime) { ++ // if cursor is before backfill time, find earliest cursor from backfill window ++ yield { ++ $type: '#info', ++ name: 'OutdatedCursor', ++ message: 'Requested cursor exceeded limit. Possibly missing events', ++ } ++ const startEvt = await ctx.sequencer.earliestAfterTime(backfillTime) ++ outboxCursor = startEvt?.seq ? startEvt.seq - 1 : undefined ++ } else { ++ outboxCursor = cursor + } +- const startEvt = await ctx.sequencer.earliestAfterTime(backfillTime) +- outboxCursor = startEvt?.seq ? startEvt.seq - 1 : undefined +- } else { +- outboxCursor = cursor + } +- } + +- for await (const evt of outbox.events(outboxCursor, signal)) { +- if (evt.type === 'commit') { +- yield { +- $type: '#commit', +- seq: evt.seq, +- time: evt.time, +- ...evt.evt, +- } +- } else if (evt.type === 'sync') { +- yield { +- $type: '#sync', +- seq: evt.seq, +- time: evt.time, +- ...evt.evt, +- } +- } else if (evt.type === 'identity') { +- yield { +- $type: '#identity', +- seq: evt.seq, +- time: evt.time, +- ...evt.evt, +- } +- } else if (evt.type === 'account') { +- yield { +- $type: '#account', +- seq: evt.seq, +- time: evt.time, +- ...evt.evt, ++ for await (const evt of outbox.events(outboxCursor, signal)) { ++ if (evt.type === 'commit') { ++ yield { ++ $type: '#commit', ++ seq: evt.seq, ++ time: evt.time, ++ ...evt.evt, ++ } ++ } else if (evt.type === 'sync') { ++ yield { ++ $type: '#sync', ++ seq: evt.seq, ++ time: evt.time, ++ ...evt.evt, ++ } ++ } else if (evt.type === 'identity') { ++ yield { ++ $type: '#identity', ++ seq: evt.seq, ++ time: evt.time, ++ ...evt.evt, ++ } ++ } else if (evt.type === 'account') { ++ yield { ++ $type: '#account', ++ seq: evt.seq, ++ time: evt.time, ++ ...evt.evt, ++ } + } + } +- } ++ }, + }) + }