Update seller store experience
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* A deliberately narrow MAIN-world bridge for the mature 1688/Taobao/Tmall
|
||||
* structured collectors. It never exposes cookies, headers, arbitrary window
|
||||
* keys, or a generic fetch primitive; only public product-state projections.
|
||||
*/
|
||||
export default defineContentScript({
|
||||
matches: [
|
||||
'*://detail.1688.com/*',
|
||||
'*://item.taobao.com/*',
|
||||
'*://detail.tmall.com/*',
|
||||
],
|
||||
world: 'MAIN',
|
||||
runAt: 'document_idle',
|
||||
main() {
|
||||
window.addEventListener('message', (event) => {
|
||||
if (event.source !== window || !isRequest(event.data)) return;
|
||||
const data = event.data.platform === '1688'
|
||||
? project1688((window as unknown as Record<string, unknown>).context)
|
||||
: projectTaobao(window as unknown as Record<string, unknown>);
|
||||
window.postMessage({
|
||||
source: 'atlas-collector',
|
||||
type: 'source-page-state.response',
|
||||
requestId: event.data.requestId,
|
||||
data,
|
||||
}, location.origin);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
type Request = { source: 'atlas-collector'; type: 'source-page-state.request'; requestId: string; platform: '1688' | 'taobao' | 'tmall' };
|
||||
function isRequest(value: unknown): value is Request {
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
|
||||
const data = value as Record<string, unknown>;
|
||||
return data.source === 'atlas-collector' && data.type === 'source-page-state.request'
|
||||
&& typeof data.requestId === 'string' && /^[a-zA-Z0-9-]{16,120}$/.test(data.requestId)
|
||||
&& (data.platform === '1688' || data.platform === 'taobao' || data.platform === 'tmall');
|
||||
}
|
||||
|
||||
const safeClone = (value: unknown) => { try { return JSON.parse(JSON.stringify(value)); } catch { return undefined; } };
|
||||
function find(value: unknown, key: string): unknown {
|
||||
const pending: unknown[] = [value];
|
||||
const seen = new Set<object>();
|
||||
let visited = 0;
|
||||
while (pending.length && visited < 300_000) {
|
||||
const current = pending.shift();
|
||||
if (!current || typeof current !== 'object' || seen.has(current)) continue;
|
||||
seen.add(current);
|
||||
visited += 1;
|
||||
const record = current as Record<string, unknown>;
|
||||
if (key in record) return record[key];
|
||||
pending.push(...Object.values(record));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
function project1688(context: unknown) {
|
||||
const projected: Record<string, unknown> = {};
|
||||
for (const key of ['gallery', 'tempModel', 'skuModel', 'tradeModel', 'skuMapOriginal', 'pieceWeightScaleInfo', 'productAttributes']) {
|
||||
const value = find(context, key);
|
||||
if (value !== undefined) projected[key] = safeClone(value);
|
||||
}
|
||||
return projected;
|
||||
}
|
||||
function projectTaobao(windowState: Record<string, unknown>) {
|
||||
const ice = windowState.__ICE_APP_CONTEXT__ as Record<string, unknown> | undefined;
|
||||
const result = ice?.loaderData && typeof ice.loaderData === 'object'
|
||||
? (((ice.loaderData as Record<string, unknown>).home as Record<string, unknown> | undefined)?.data as Record<string, unknown> | undefined)?.res
|
||||
: undefined;
|
||||
return { product: safeClone(result) };
|
||||
}
|
||||
Reference in New Issue
Block a user