test
This commit is contained in:
parent
53641fc8e7
commit
657d307485
28 changed files with 2045 additions and 161 deletions
|
|
@ -68,6 +68,32 @@ function parseTradeItem(r) {
|
|||
return { id, w, h, stashX, stashY, account };
|
||||
}
|
||||
|
||||
function parseTradeItemWithPrice(r) {
|
||||
const base = parseTradeItem(r);
|
||||
let name = "";
|
||||
let priceAmount = 0;
|
||||
let priceCurrency = "";
|
||||
|
||||
if (r.item?.icon) {
|
||||
try {
|
||||
const pathname = new URL(r.item.icon).pathname;
|
||||
const filename = pathname.split("/").pop() || "";
|
||||
name = filename.replace(".png", "");
|
||||
} catch {
|
||||
// fallback: regex on last path segment
|
||||
const match = r.item.icon.match(/\/([^/]+)\.png/);
|
||||
if (match) name = match[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (r.listing?.price) {
|
||||
if (r.listing.price.amount != null) priceAmount = r.listing.price.amount;
|
||||
if (r.listing.price.currency) priceCurrency = r.listing.price.currency;
|
||||
}
|
||||
|
||||
return { ...base, name, priceAmount, priceCurrency };
|
||||
}
|
||||
|
||||
async function waitForVisible(locator, timeoutMs) {
|
||||
try {
|
||||
await locator.waitFor({ state: "visible", timeout: timeoutMs });
|
||||
|
|
@ -97,19 +123,8 @@ function handleWebSocket(ws, searchId) {
|
|||
|
||||
ws.on("framereceived", (frame) => {
|
||||
if (pausedSearches.has(searchId)) return;
|
||||
try {
|
||||
const payload = typeof frame === "string" ? frame : frame.payload?.toString() ?? "";
|
||||
const doc = JSON.parse(payload);
|
||||
if (doc.new && Array.isArray(doc.new)) {
|
||||
const ids = doc.new.filter((s) => s != null);
|
||||
if (ids.length > 0) {
|
||||
log(`New listings: ${searchId} (${ids.length} items)`);
|
||||
sendEvent("newListings", { searchId, itemIds: ids });
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
/* Non-JSON WebSocket frame */
|
||||
}
|
||||
// Note: trade site now sends JWTs, not raw item IDs.
|
||||
// We rely on the fetch response interceptor instead.
|
||||
});
|
||||
|
||||
ws.on("close", () => {
|
||||
|
|
@ -160,14 +175,42 @@ async function cmdAddSearch(reqId, params) {
|
|||
const page = await context.newPage();
|
||||
searchPages.set(searchId, page);
|
||||
|
||||
// Register WebSocket handler BEFORE navigation so we catch connections during page load
|
||||
page.on("websocket", (ws) => handleWebSocket(ws, searchId));
|
||||
|
||||
// Track whether live search is active — don't emit items from initial page load
|
||||
let liveActive = false;
|
||||
const seenIds = new Set();
|
||||
|
||||
// Intercept fetch responses to get full item data (WebSocket now sends JWTs, not raw IDs)
|
||||
page.on("response", async (response) => {
|
||||
if (!liveActive) return;
|
||||
if (!response.url().includes("/api/trade2/fetch/")) return;
|
||||
try {
|
||||
const body = await response.text();
|
||||
const doc = JSON.parse(body);
|
||||
if (doc.result && Array.isArray(doc.result)) {
|
||||
const items = doc.result
|
||||
.map((r) => parseTradeItem(r))
|
||||
.filter((i) => i.id && !seenIds.has(i.id));
|
||||
items.forEach((i) => seenIds.add(i.id));
|
||||
if (items.length > 0) {
|
||||
log(`New listings (fetch): ${searchId} (${items.length} new items)`);
|
||||
sendEvent("newListings", { searchId, items });
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
/* Non-JSON trade response */
|
||||
}
|
||||
});
|
||||
|
||||
await page.goto(url, { waitUntil: "networkidle" });
|
||||
await new Promise((r) => setTimeout(r, 2000)); // PageLoad delay
|
||||
|
||||
page.on("websocket", (ws) => handleWebSocket(ws, searchId));
|
||||
|
||||
try {
|
||||
const liveBtn = page.locator(Selectors.LiveSearchButton).first();
|
||||
await liveBtn.click({ timeout: 5000 });
|
||||
liveActive = true;
|
||||
log(`Live search activated: ${searchId}`);
|
||||
} catch {
|
||||
log(`Could not click Activate Live Search: ${searchId}`);
|
||||
|
|
@ -222,6 +265,56 @@ async function cmdClickTravel(reqId, params) {
|
|||
}
|
||||
}
|
||||
|
||||
async function cmdAddDiamondSearch(reqId, params) {
|
||||
if (!context) throw new Error("Browser not started");
|
||||
const { url } = params;
|
||||
const searchId = extractSearchId(url);
|
||||
|
||||
if (searchPages.has(searchId)) {
|
||||
log(`Diamond search already open: ${searchId}`);
|
||||
sendResponse(reqId, { searchId });
|
||||
return;
|
||||
}
|
||||
|
||||
log(`Adding diamond search: ${url} (${searchId})`);
|
||||
const page = await context.newPage();
|
||||
searchPages.set(searchId, page);
|
||||
|
||||
// Intercept fetch responses for item data + prices
|
||||
page.on("response", async (response) => {
|
||||
if (!response.url().includes("/api/trade2/fetch/")) return;
|
||||
try {
|
||||
const body = await response.text();
|
||||
const doc = JSON.parse(body);
|
||||
if (doc.result && Array.isArray(doc.result)) {
|
||||
const items = doc.result.map((r) => parseTradeItemWithPrice(r));
|
||||
if (items.length > 0) {
|
||||
log(`Diamond listings: ${searchId} (${items.length} items)`);
|
||||
sendEvent("diamondListings", { searchId, items });
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
/* Non-JSON trade response */
|
||||
}
|
||||
});
|
||||
|
||||
// Hook WebSocket BEFORE navigation so we catch connections during page load
|
||||
page.on("websocket", (ws) => handleWebSocket(ws, searchId));
|
||||
|
||||
await page.goto(url, { waitUntil: "networkidle" });
|
||||
await new Promise((r) => setTimeout(r, 2000));
|
||||
|
||||
try {
|
||||
const liveBtn = page.locator(Selectors.LiveSearchButton).first();
|
||||
await liveBtn.click({ timeout: 5000 });
|
||||
log(`Diamond live search activated: ${searchId}`);
|
||||
} catch {
|
||||
log(`Could not click Activate Live Search: ${searchId}`);
|
||||
}
|
||||
|
||||
sendResponse(reqId, { searchId });
|
||||
}
|
||||
|
||||
async function cmdOpenScrapPage(reqId, params) {
|
||||
if (!context) throw new Error("Browser not started");
|
||||
const { url } = params;
|
||||
|
|
@ -339,6 +432,7 @@ async function cmdStop(reqId) {
|
|||
const handlers = {
|
||||
start: cmdStart,
|
||||
addSearch: cmdAddSearch,
|
||||
addDiamondSearch: cmdAddDiamondSearch,
|
||||
pauseSearch: cmdPauseSearch,
|
||||
clickTravel: cmdClickTravel,
|
||||
openScrapPage: cmdOpenScrapPage,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue