this repo has no description
32
fork

Configure Feed

Select the types of activity you want to include in your feed.

Prune dead adapter surface and tighten single mode

alice d061d58f bc633561

+22 -52
-1
package.json
··· 35 35 "./adapters/perlsky": "./src/adapters/perlsky.mjs", 36 36 "./adapters/tranquil-pds": "./src/adapters/tranquil-pds.mjs", 37 37 "./adapters/registry": "./src/adapters/registry.mjs", 38 - "./adapters/loader": "./src/adapters/loader.mjs", 39 38 "./lab/pdslab-targets": "./src/lab/pdslab-targets.mjs", 40 39 "./browser/run-single": "./src/browser/run-single.mjs", 41 40 "./browser/run-dual": "./src/browser/run-dual.mjs",
+2 -2
src/adapters/bring-your-own.mjs
··· 36 36 }; 37 37 }; 38 38 39 - export const createBringYourOwnSingleConfig = ({ 39 + const createBringYourOwnSingleConfig = ({ 40 40 account, 41 41 ...rest 42 42 } = {}) => { ··· 46 46 }); 47 47 }; 48 48 49 - export const createBringYourOwnDualConfig = ({ 49 + const createBringYourOwnDualConfig = ({ 50 50 primary, 51 51 secondary, 52 52 ...rest
-5
src/adapters/loader.mjs
··· 1 - export { 2 - getAdapter as loadAdapter, 3 - getAdapter, 4 - listAdapters, 5 - } from './registry.mjs';
-2
src/adapters/perlsky.mjs
··· 30 30 }; 31 31 32 32 const { 33 - createAccount: createPerlskyAccountConfig, 34 33 adapter: PERLSKY_ADAPTER, 35 34 } = createRoleBasedAdapter({ 36 35 name: 'perlsky', ··· 56 55 }, 57 56 }); 58 57 59 - export { createPerlskyAccountConfig }; 60 58 export { PERLSKY_ADAPTER };
-2
src/adapters/tranquil-pds.mjs
··· 27 27 }; 28 28 29 29 const { 30 - createAccount: createTranquilPdsAccountConfig, 31 30 adapter: TRANQUIL_PDS_ADAPTER, 32 31 } = createRoleBasedAdapter({ 33 32 name: 'tranquil-pds', ··· 49 48 secondaryCleanupPrefixes: TRANQUIL_PDS_SECONDARY_CLEANUP_PREFIXES, 50 49 }); 51 50 52 - export { createTranquilPdsAccountConfig }; 53 51 export { TRANQUIL_PDS_ADAPTER };
+6 -10
src/browser/lib/dual-actions/profile.mjs
··· 1 1 import { 2 + buttonText, 2 3 dismissBlockingOverlays, 3 4 loginToBlueskyApp, 5 + normalizeText, 4 6 pollJsonUntil, 5 7 } from '../runtime-utils.mjs'; 6 8 import { createPageAuthActions } from '../page-auth-actions.mjs'; ··· 17 19 fetchStatus, 18 20 avatarPngBase64, 19 21 }) => { 22 + const publicCheckTimeoutMs = config.publicCheckTimeoutMs ?? 180000; 20 23 const authActions = createPageAuthActions({ 21 24 appUrl: config.appUrl, 22 25 appBaseUrl, ··· 25 28 }); 26 29 const feedActions = createPageFeedActions({ 27 30 wait, 28 - normalizeText: (text) => (text || '').replace(/\s+/g, ' ').trim(), 29 - buttonText: async (locator) => { 30 - const label = await locator.getAttribute('aria-label'); 31 - if (label && label.trim()) { 32 - return label.trim(); 33 - } 34 - const text = await locator.innerText().catch(() => ''); 35 - return text.trim(); 36 - }, 31 + normalizeText, 32 + buttonText, 37 33 dismissBlockingOverlays, 38 34 }); 39 35 const profileEditActions = createPageProfileEditActions({ ··· 251 247 json?.description === account.profileNote && 252 248 typeof json?.avatar === 'string' && 253 249 json.avatar.length > 0, 254 - timeoutMs: config.publicCheckTimeoutMs ?? 180000, 250 + timeoutMs: publicCheckTimeoutMs, 255 251 fetchJson, 256 252 }); 257 253 const avatarResult = await fetchStatus(result.json.avatar);
-3
src/browser/lib/dual-api.mjs
··· 95 95 return (result.json?.records || []).map(normalizeRepoRecord); 96 96 }; 97 97 98 - const listOwnPosts = async (account, limit = 100) => 99 - listOwnRecords(account, 'app.bsky.feed.post', limit); 100 - 101 98 const recordRkey = (recordOrUri) => { 102 99 const uri = typeof recordOrUri === 'string' ? recordOrUri : recordOrUri?.uri; 103 100 return uri?.split('/').pop();
-5
src/browser/lib/dual-browser.mjs
··· 9 9 finalizeSummary, 10 10 launchBrowserWithFallback, 11 11 normalizeText, 12 - recordStep, 13 - sleep, 14 12 } from './runtime-utils.mjs'; 15 13 import { 16 14 isIgnoredConsoleEntry, ··· 73 71 }; 74 72 75 73 return { 76 - pageFor, 77 74 screenshot, 78 - recordStep, 79 75 normalizeText, 80 76 isIgnoredConsole: isIgnoredConsoleEntry, 81 77 isIgnoredRequestFailure: isIgnoredRequestFailureEntry, 82 78 isIgnoredHttpFailure: isIgnoredHttpFailureEntry, 83 79 step, 84 80 wait, 85 - sleep, 86 81 buttonText, 87 82 }; 88 83 };
-3
src/browser/lib/page-feed-actions.mjs
··· 322 322 findRowByPrimaryText, 323 323 maybeFindRowByPrimaryText, 324 324 findFirstFeedItem, 325 - clickLike, 326 - clickRepost, 327 325 clickQuote, 328 326 clickReply, 329 327 ensureLiked, ··· 333 331 ensureBookmarked, 334 332 ensureNotBookmarked, 335 333 openPostOptions, 336 - deletePostRow, 337 334 maybeDeleteOwnPostByText, 338 335 }; 339 336 };
+2 -1
src/browser/lib/single-actions/feed.mjs
··· 1 + import { dismissBlockingOverlays } from '../runtime-utils.mjs'; 1 2 import { createPageFeedActions } from '../page-feed-actions.mjs'; 2 3 3 4 export const createSingleFeedActions = ({ ··· 10 11 wait: (_page, ms) => wait(ms), 11 12 normalizeText, 12 13 buttonText, 13 - dismissBlockingOverlays: async () => undefined, 14 + dismissBlockingOverlays, 14 15 }); 15 16 16 17 return {
+5 -4
src/browser/lib/single-actions/profile.mjs
··· 12 12 pollJson, 13 13 avatarPngBase64, 14 14 }) => { 15 + const publicCheckTimeoutMs = config.publicCheckTimeoutMs ?? 180000; 15 16 const pageActions = createPageProfileEditActions({ 16 17 artifactsDir: config.artifactsDir, 17 18 wait: (_page, ms) => wait(ms), ··· 25 26 'public handle resolution', 26 27 () => `${config.publicApiUrl}/xrpc/com.atproto.identity.resolveHandle?handle=${encodeURIComponent(config.handle)}`, 27 28 ({ ok, json }) => ok && typeof json?.did === 'string' && json.did.length > 0, 28 - config.publicCheckTimeoutMs ?? 180000, 29 + publicCheckTimeoutMs, 29 30 ); 30 31 return { did: result.json.did }; 31 32 }; ··· 36 37 () => `${config.publicApiUrl}/xrpc/app.bsky.feed.getAuthorFeed?actor=${encodeURIComponent(config.handle)}&limit=20`, 37 38 ({ ok, json }) => 38 39 ok && Array.isArray(json?.feed) && json.feed.some((item) => item?.post?.record?.text === config.postText), 39 - config.publicCheckTimeoutMs ?? 180000, 40 + publicCheckTimeoutMs, 40 41 ); 41 42 const matching = result.json.feed.find((item) => item?.post?.record?.text === config.postText); 42 43 return { ··· 50 51 'public profile indexing', 51 52 () => `${config.publicApiUrl}/xrpc/app.bsky.actor.getProfile?actor=${encodeURIComponent(config.handle)}`, 52 53 ({ ok, json }) => ok && typeof json?.postsCount === 'number' && json.postsCount > 0, 53 - config.publicCheckTimeoutMs ?? 180000, 54 + publicCheckTimeoutMs, 54 55 ); 55 56 return { 56 57 postsCount: result.json.postsCount, ··· 70 71 json?.description === config.profileNote && 71 72 typeof json?.avatar === 'string' && 72 73 json.avatar.length > 0, 73 - config.publicCheckTimeoutMs ?? 180000, 74 + publicCheckTimeoutMs, 74 75 ); 75 76 const avatarResult = await fetchStatus(result.json.avatar); 76 77 if (!avatarResult.ok) {
+1 -1
src/browser/run-dual.mjs
··· 130 130 }); 131 131 await fs.writeFile( 132 132 path.join(config.artifactsDir, 'summary.json'), 133 - JSON.stringify(summary, null, 2) + '\n', 133 + `${JSON.stringify(summary, null, 2)}\n`, 134 134 'utf8', 135 135 ); 136 136 console.log(JSON.stringify(summary, null, 2));
+1 -1
src/browser/run-single.mjs
··· 124 124 await screenshot('final').catch(() => undefined); 125 125 await fs.writeFile( 126 126 path.join(config.artifactsDir, 'summary.json'), 127 - JSON.stringify(summary, null, 2) + '\n', 127 + `${JSON.stringify(summary, null, 2)}\n`, 128 128 'utf8', 129 129 ); 130 130 console.log(JSON.stringify(summary, null, 2));
+5 -3
src/config.mjs
··· 187 187 editProfile = false, 188 188 ...rest 189 189 } = {}) => { 190 + const suite = createSuiteConfig(rest); 191 + if (!suite.targetHandle) { 192 + throw new Error('targetHandle is required for single-mode runs'); 193 + } 190 194 return { 191 - ...createSuiteConfig(rest), 195 + ...suite, 192 196 ...createAccountConfig(account), 193 197 editProfile: !!editProfile, 194 198 }; ··· 213 217 214 218 return normalized; 215 219 }; 216 - 217 - export const suiteDefaults = Object.freeze({ ...DEFAULTS });
-1
src/index.mjs
··· 3 3 export * from './adapters/perlsky.mjs'; 4 4 export * from './adapters/tranquil-pds.mjs'; 5 5 export * from './adapters/registry.mjs'; 6 - export * from './adapters/loader.mjs'; 7 6 export * from './lab/pdslab-targets.mjs'; 8 7 export * from './browser/run-single.mjs'; 9 8 export * from './browser/run-dual.mjs';
-8
src/lab/pdslab-targets.mjs
··· 301 301 ], 302 302 }), 303 303 ]); 304 - 305 - export const getPdslabTarget = (id) => { 306 - return PDSLAB_TARGETS.find((target) => target.id === id); 307 - }; 308 - 309 - export const listPdslabTargets = () => { 310 - return PDSLAB_TARGETS.map((target) => structuredClone(target)); 311 - };