Expand seller store functionality
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Runs in Ozon's MAIN world so the request has exactly the same origin and
|
||||
* session context as the page. It accepts only Atlas' two fixed, numeric-SKU
|
||||
* routes and returns a small widget-state allowlist; it never exposes cookies,
|
||||
* request headers or arbitrary fetch capability to the isolated script.
|
||||
*/
|
||||
export default defineContentScript({
|
||||
matches: ['*://www.ozon.ru/*', '*://www.ozon.kz/*', '*://www.ozon.by/*'],
|
||||
world: 'MAIN',
|
||||
runAt: 'document_idle',
|
||||
main() {
|
||||
window.addEventListener('message', (event) => {
|
||||
if (event.source !== window || !isRequest(event.data)) return;
|
||||
void respond(event.data);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
type Request = {
|
||||
source: 'atlas-collector';
|
||||
type: 'ozon-page-json.request';
|
||||
requestId: string;
|
||||
kind: 'modal-aspects' | 'product' | 'product-detail';
|
||||
sku: string;
|
||||
};
|
||||
|
||||
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 === 'ozon-page-json.request' &&
|
||||
typeof data.requestId === 'string' &&
|
||||
/^[a-zA-Z0-9-]{16,120}$/.test(data.requestId) &&
|
||||
(data.kind === 'modal-aspects' ||
|
||||
data.kind === 'product' ||
|
||||
data.kind === 'product-detail') &&
|
||||
typeof data.sku === 'string' &&
|
||||
/^\d{4,}$/.test(data.sku)
|
||||
);
|
||||
}
|
||||
|
||||
async function respond(request: Request) {
|
||||
try {
|
||||
const pagePath =
|
||||
request.kind === 'modal-aspects'
|
||||
? `/modal/aspectsNew?product_id=${request.sku}`
|
||||
: request.kind === 'product-detail'
|
||||
? `/product/${request.sku}/?layout_container=pdpPage2column&layout_page_index=2`
|
||||
: `/product/${request.sku}/`;
|
||||
const response = await fetch(
|
||||
`/api/entrypoint-api.bx/page/json/v2?url=${encodeURIComponent(pagePath)}`,
|
||||
{ credentials: 'same-origin' },
|
||||
);
|
||||
if (!response.ok)
|
||||
throw new Error(`Ozon 页面状态请求失败(HTTP ${response.status})`);
|
||||
const value = await response.json();
|
||||
window.postMessage(
|
||||
{
|
||||
source: 'atlas-collector',
|
||||
type: 'ozon-page-json.response',
|
||||
requestId: request.requestId,
|
||||
ok: true,
|
||||
data: allowlistedPageState(value),
|
||||
},
|
||||
location.origin,
|
||||
);
|
||||
} catch (error) {
|
||||
window.postMessage(
|
||||
{
|
||||
source: 'atlas-collector',
|
||||
type: 'ozon-page-json.response',
|
||||
requestId: request.requestId,
|
||||
ok: false,
|
||||
error:
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: 'Ozon 页面状态请求失败',
|
||||
},
|
||||
location.origin,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function allowlistedPageState(value: unknown) {
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value))
|
||||
return { widgetStates: {} };
|
||||
const states = (value as { widgetStates?: unknown }).widgetStates;
|
||||
if (!states || typeof states !== 'object' || Array.isArray(states))
|
||||
return { widgetStates: {} };
|
||||
const widgetStates: Record<string, unknown> = {};
|
||||
for (const [name, state] of Object.entries(
|
||||
states as Record<string, unknown>,
|
||||
)) {
|
||||
if (
|
||||
/^web(Aspects|AspectsModal|ProductHeading|Price|Gallery|Description|RichContent|Features|ShortCharacteristics|DetailedCharacteristics|Characteristics)-/.test(
|
||||
name,
|
||||
)
|
||||
) {
|
||||
widgetStates[name] = state;
|
||||
}
|
||||
}
|
||||
return { widgetStates };
|
||||
}
|
||||
Reference in New Issue
Block a user