mcp-scraper 0.89.0 → 0.89.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/README.md +3 -1
- package/dist/{analytics-repository-2BMT5JNE.js → analytics-repository-X6J7TWTL.js} +1 -1
- package/dist/bin/api-server.js +1 -1
- package/dist/bin/mcp-scraper-cli.js +1 -1
- package/dist/bin/mcp-scraper-core.js +1 -1
- package/dist/bin/mcp-scraper-install.js +1 -1
- package/dist/bin/mcp-stdio-server.js +1 -1
- package/dist/bin/paa-harvest.js +1 -1
- package/dist/{chunk-4AI7DOS7.js → chunk-2O3UYISB.js} +1 -1
- package/dist/{chunk-PUHFVA7P.js → chunk-3MUEBDWY.js} +1 -1
- package/dist/{chunk-MASR22K4.js → chunk-D4NOJAUN.js} +1 -1
- package/dist/{chunk-WSCGYRWA.js → chunk-DEPJ4ZZ6.js} +1 -1
- package/dist/{chunk-HDPYG3XV.js → chunk-DMCYIWB3.js} +1 -1
- package/dist/{chunk-XPZVJIZ2.js → chunk-EN66HBAW.js} +1 -1
- package/dist/{chunk-E2WRWV3A.js → chunk-HYQDXTS7.js} +1 -1
- package/dist/{chunk-7YGVI5J4.js → chunk-J7EVLE6H.js} +1 -1
- package/dist/{chunk-TXENITMS.js → chunk-K7KMLT33.js} +1 -1
- package/dist/{chunk-L4CGLFPU.js → chunk-MKEMCMRO.js} +1 -1
- package/dist/{chunk-X54CQLK2.js → chunk-S7RA23GR.js} +1 -1
- package/dist/chunk-TW46NKVH.js +1 -0
- package/dist/{chunk-CFI6CXIV.js → chunk-VEJQ4XPI.js} +1 -1
- package/dist/{chunk-M22MM4N4.js → chunk-Z27SYWYD.js} +1 -1
- package/dist/{chunk-GMWKPIYX.js → chunk-Z66Z2HV4.js} +182 -79
- package/dist/{chunk-CCYWSJNG.js → chunk-ZWZ6OWY6.js} +1 -1
- package/dist/db-NLGNTQC3.js +1 -0
- package/dist/{extract-bundle-SNUIHM3J.js → extract-bundle-TXH3VNXH.js} +1 -1
- package/dist/{gmail-service-BZ3H75XC.js → gmail-service-J2DWSQJX.js} +1 -1
- package/dist/index.cjs +143 -32
- package/dist/index.js +1 -1
- package/dist/{lead-list-enrichment-repository-S2H3U7T7.js → lead-list-enrichment-repository-G7Z5DQZR.js} +1 -1
- package/dist/{location-data-repository-OTWHWMV6.js → location-data-repository-TEXZ3I2N.js} +1 -1
- package/dist/{server-RFR2A5UJ.js → server-LBOFC2EE.js} +849 -816
- package/dist/{site-extract-repository-SE776XDC.js → site-extract-repository-MBSCAP4D.js} +1 -1
- package/dist/{worker-XUDSM3AL.js → worker-SUCJKWU2.js} +1 -1
- package/package.json +1 -1
- package/dist/chunk-Z2QGQJS2.js +0 -1
- package/dist/db-F2MX63GI.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{f as q}from"./chunk-QPWPR5XG.js";import{a as ye}from"./chunk-4FROKQJN.js";import{a as ke,b as pe,c as Nt,d as me,g as ve}from"./chunk-MASR22K4.js";import{a as ce,c as we,d as Ut,g as ge,l as Ne}from"./chunk-3GP5CYZX.js";import{a as Ce,i as Me,j as E,k as vt,m as _,n as ht,o as Kt}from"./chunk-GMWKPIYX.js";import{chromium as _t}from"playwright-extra";import fn from"puppeteer-extra-plugin-stealth";import{chromium as Pn}from"playwright";var H={container:".eJH8qe.adDDi",dataInitq:"[data-initq]",item:".related-question-pair",itemDataQ:"data-q",itemDataInitQ:"data-initq",itemQuestionEl:".JlqpRe",answerContainer:".bCOlv, .hgKElc, .wDYxhc, .LGOjhe, .fo7IQd, .fmW3u",aiAnswerBody:".pWvJNd",aiCitation:"a.PMDqCb[href]",aiSourceCard:"a.vIWmYe[href], a.Zbfntb[href]",sourceTitle:"h3",sourceSite:".VuuXrf",sourceCite:"cite",clickTarget:".JlqpRe",expandedClass:"aoRk1c",captchaMarker:'#captcha-form, #recaptcha, form[action*="/sorry/"], .g-recaptcha, [data-sitekey]'},Te={container:'div[jscontroller="HWk0Gf"]',sectionHeading:'.mgAbYb[role="heading"]',item:"a.rIRoqf"},Tt={udm:"39",item:"a.rIRoqf",durationPattern:/^\d+:\d+$/,platforms:["YouTube","TikTok","Instagram","Facebook","X"]},fe={section:".ULSxyf",item:"a.KYg7td.INpicf",title:".hyYc0c",source:".K4ETW"},Pe={sectionTag:"g-section-with-header",sectionHeadingText:"What people are saying",card:'.dRzkFf[role="listitem"]',cardLink:'a.WlydOe[jsname="YKoRaf"]',titleH1:"h1.WQWxe",titleDiv:".eAaXgc",popularCommentLabel:".qgdis",source:".sTl1Td",platformBadge:".appd0, .KrMNbf",ytChannel:".sjVJQd",ytDate:".PLq9Je",authorNote:".nDgy9d"},be={root:"[data-lhcontainer][data-streaming-container][eid]",legacyRoot:'[data-hveid="CBMQAA"]',wrapper:".Fgyi2e",controller:'[jscontroller="AkrxPe"]',contentSubtree:'[data-subtree="mfc"]',header:".heWuVc",heading:".Fzsovc.cwYVJe.RJPOee",showMoreButton:'[aria-label="Show more AI Overview"]',sourcesPanel:".OZ9ddf.WAUd4",disclaimer:".DuQANe.MSJHRb"},We={root:'[data-hveid="CAUQAA"]',wrapper:".Fgyi2e",citations:'.Fgyi2e [data-hveid] a[jsname="pxBnId"]'},Ie={result:".wHYlTd.tF2Cxc",title:"h3.LC20lb",siteName:".VuuXrf",cite:"cite.tjvcx",snippet:".VwiC3b",redditCite:"cite.qLRx3b",ratingWrap:".Y0A0hc",ratingValue:".yi40Hd",reviewCount:".RDApEe"},Ae={headingText:"Businesses",card:".w7Dbne",name:".OSrXXb",ratingValue:".yi40Hd",reviewCount:".RDApEe"};var _a={ratingAndCount:"div.F7nice",hoursTable:"table.eK4R0e",reviewScrollPane:'div.m6QErb[tabindex="-1"]',reviewScrollPaneFallback:'[role="main"] div[tabindex="-1"]',reviewCardAuthor:"div.d4r55, span.d4r55, span.RPZfBb",reviewCardDate:"span.rsqaWe",reviewCardText:"span.wiI7pd",reviewCardOwnerBlock:"div.CDe7pd",hoursTableAlt:'table[aria-label*="Hour"]',reviewCard:"[data-review-id]",reviewStars:'[role="img"][aria-label*="star"]',reviewTab:'button[role="tab"][aria-label*="Review"]',aboutTab:'button[role="tab"][aria-label*="About"]',expandReview:'[data-review-id] button[aria-label*="See more"], [data-review-id] button.w8nwRe'};async function ft(e,t,n,a){let s,i=!1,d,l=()=>{},U=()=>a?.reason instanceof DOMException&&a.reason.name==="TimeoutError"?a.reason:new _,u=()=>l(U()),S=new Promise((r,h)=>{l=h}),o=async r=>{let h;try{await Promise.race([r.close().catch(()=>{}),new Promise(c=>{h=setTimeout(c,2e3)})])}finally{h&&clearTimeout(h)}};if(a?.aborted)throw U();a?.addEventListener("abort",u,{once:!0}),d=setTimeout(()=>l(new DOMException("Optional pagination timed out","TimeoutError")),3e4);try{return await Promise.race([(async()=>{let r=await e.newPage();if(i)throw await o(r),new _;if(s=r,await t(r),i)throw new _;return n(r)})(),S])}finally{i=!0,d&&clearTimeout(d),a?.removeEventListener("abort",u),s&&await o(s)}}var Tn=/\b(?:HeadlessChrome|Chrome|Chromium|Firefox)\/\d+|\bVersion\/\d+.*\bSafari\//;async function Pt(e){try{let t=await e.evaluate(()=>navigator.userAgent);return typeof t=="string"&&Tn.test(t)?t:null}catch{return null}}async function bt(e){let t=null;try{let n=e.contexts().flatMap(a=>a.pages())[0];return n||(t=await e.newContext(),n=t.pages()[0]??await t.newPage()),await Pt(n)}catch{return null}finally{t&&await t.close().catch(()=>{})}}function ja(e,t){return t?{...e,userAgent:t}:e}_t.use(fn());var bn=180,Wn=3e3,In=5e3;function An(e,t){let n=process.env[e];if(!n)return t;let a=Number(n);return Number.isInteger(a)&&a>0?a:t}function Jt(e){return e?e.slice(-6):null}function Le(e,t){let n=(t??process.env.SERP_REDIRECT_BASE)?.trim().replace(/\/+$/,"");return n?`${n}/g/${Buffer.from(e,"utf8").toString("base64url")}`:e}function Ln(e){return e?/united states|u\.?s\.?a?\.?|^us$/i.test(e.trim()):!1}function ut(e){return e instanceof Error?e.message:String(e)}function On(e){return/\b409\b|conflict|already exists/i.test(ut(e))}async function xn(e,t){try{await e.profiles.create({name:t})}catch(n){if(!On(n))throw n}}function Wt(e,t){return{viewport:e.viewport,locale:e.locale,...t?{userAgent:t}:{},...e.deviceScaleFactor?{deviceScaleFactor:e.deviceScaleFactor}:{},...e.isMobile!==void 0?{isMobile:e.isMobile}:{},...e.hasTouch!==void 0?{hasTouch:e.hasTouch}:{}}}async function ot(e,t,n){let a;try{return await Promise.race([e,new Promise((s,i)=>{a=setTimeout(()=>i(new Error(`${n} timed out after ${t}ms`)),t)})])}finally{a&&clearTimeout(a)}}function Bn(e){let t=e.trim();if(!t)throw new Error("channelHandle is required");if(/^https?:\/\//i.test(t)||/^(www\.|m\.)?youtube\.com\//i.test(t)){let d=new URL(/^https?:\/\//i.test(t)?t:`https://${t}`);if(d.hostname.replace(/^www\./,"").replace(/^m\./,"").toLowerCase()!=="youtube.com")throw new Error("channel URL must be on youtube.com");let U=d.pathname.split("/").filter(Boolean),u=U[0]??"",S=U[1]??"";if(u.startsWith("@"))return`https://www.youtube.com/${u}/videos`;if(u==="channel"&&S)return`https://www.youtube.com/channel/${S}/videos`;if((u==="c"||u==="user")&&S)return`https://www.youtube.com/${u}/${S}/videos`;throw new Error("channel URL must be a YouTube handle, /channel/UC..., /c/..., or /user/... URL")}let s=t.replace(/^\/+/,"").replace(/\/+$/,"").replace(/\/videos$/i,"");if(/^UC[\w-]{20,}$/.test(s))return`https://www.youtube.com/channel/${s}/videos`;let i=s.startsWith("@")?s:`@${s}`;if(!/^@[\w.-]+$/.test(i))throw new Error("channelHandle must be an @handle, UC channel ID, or YouTube channel URL");return`https://www.youtube.com/${i}/videos`}var It=class{browser=null;context=null;page=null;\u006b\u0065\u0072\u006e\u0065\u006cClient=null;\u006b\u0065\u0072\u006e\u0065\u006cSessionId=null;\u006b\u0065\u0072\u006e\u0065\u006cOpenedAtMs=null;\u006b\u0065\u0072\u006e\u0065\u006cStealth=null;\u006b\u0065\u0072\u006e\u0065\u006cProxyUsed=null;\u006b\u0065\u0072\u006e\u0065\u006cProxySource=null;\u006b\u0065\u0072\u006e\u0065\u006cProxyType=null;\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent=null;debugEnabled=!1;debugSnapshot={\u006b\u0065\u0072\u006e\u0065\u006c:null,context:null,networkLocation:null,serpNavigation:null};async launch(t){this.debugEnabled=t.debug===!0;let n=t.proxyMode??(t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId?"configured":"none"),a=t.isMobile?"mobile":"desktop";if(this.debugSnapshot={\u006b\u0065\u0072\u006e\u0065\u006c:null,context:{viewport:t.viewport,locale:t.locale,device:a,userAgent:null,deviceScaleFactor:t.deviceScaleFactor??null,isMobile:t.isMobile===!0,hasTouch:t.hasTouch===!0},networkLocation:null,serpNavigation:null},t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey){this.\u006b\u0065\u0072\u006e\u0065\u006cClient=new q({apiKey:t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey});let i=Number.isInteger(t.\u006b\u0065\u0072\u006e\u0065\u006cTimeoutSeconds)&&Number(t.\u006b\u0065\u0072\u006e\u0065\u006cTimeoutSeconds)>0?Number(t.\u006b\u0065\u0072\u006e\u0065\u006cTimeoutSeconds):An("\u004b\u0045\u0052\u004e\u0045\u004c_BROWSER_TIMEOUT_SECONDS",bn);t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName&&t.\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges===!0&&await xn(this.\u006b\u0065\u0072\u006e\u0065\u006cClient,t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName);let d=Nt(),l;t.headlessMode==="headful"||d?.forceHeadful===!0?l=!1:t.headlessMode==="headless"?l=!0:l=d?.forceHeadless===!0||process.env.\u004b\u0045\u0052\u004e\u0045\u004c_HEADLESS_DISABLED!=="true"&&!!d?.op&&me.has(d.op),this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent=l?!0:null,d?.headlessSentOut&&(d.headlessSentOut.value=this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent);let U=await this.\u006b\u0065\u0072\u006e\u0065\u006cClient.browsers.create({stealth:t.\u006b\u0065\u0072\u006e\u0065\u006cStealth===!0,timeout_seconds:i,...l?{headless:!0}:{},...t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId?{proxy_id:t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId}:{},...t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName?{profile:{name:t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName,...typeof t.\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges=="boolean"?{save_changes:t.\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges}:{}}}:{}});this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId=U.session_id,this.\u006b\u0065\u0072\u006e\u0065\u006cOpenedAtMs=Date.now(),this.\u006b\u0065\u0072\u006e\u0065\u006cStealth=typeof U.stealth=="boolean"?U.stealth:null,this.\u006b\u0065\u0072\u006e\u0065\u006cProxyUsed=typeof U.proxy_id=="string"?!!U.proxy_id:!!t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,this.\u006b\u0065\u0072\u006e\u0065\u006cProxySource=t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution?.source??null,this.\u006b\u0065\u0072\u006e\u0065\u006cProxyType=t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution?.proxyType??null;let u=null,S=null;if(!t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId&&!t.keepDefaultProxy)try{await ot(this.\u006b\u0065\u0072\u006e\u0065\u006cClient.browsers.update(this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,{disable_default_proxy:!0}),5e3,`\u004b\u0065\u0072\u006e\u0065\u006c session ${this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId} disable default proxy`),u=!0}catch(r){u=!1,S=ut(r)}let o={sessionId:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,proxyMode:n,requestedProxyIdPresent:!!t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,requestedProxyIdSuffix:Jt(t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId),createdProxyIdPresent:typeof U.proxy_id=="string"?!!U.proxy_id:null,createdProxyIdSuffix:Jt(U.proxy_id),retrievedProxyIdPresent:null,retrievedProxyIdSuffix:null,retrievedProxyIdMatchesRequested:null,defaultProxyDisabled:u,defaultProxyDisableError:S,proxyResolution:t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution??null,timeoutSeconds:i,stealth:typeof U.stealth=="boolean"?U.stealth:null,profilePresent:null,poolPresent:null,retrieveError:null};if(this.debugSnapshot.\u006b\u0065\u0072\u006e\u0065\u006c=o,console.info(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_created",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,timeout_seconds:i,proxy_mode:n,proxy_id_present:!!t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,profile_name_present:!!t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName,proxy_resolution_source:t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution?.source})),this.debugEnabled&&await this.populate\u004b\u0065\u0072\u006e\u0065\u006cRetrieveDebug(o,t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId),this.browser=await Pn.connectOverCDP(U.cdp_ws_url),t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName||t.preserve\u004b\u0065\u0072\u006e\u0065\u006cContext)this.context=this.browser.contexts()[0]??await this.browser.newContext(Wt(t)),this.page=this.context.pages()[0]??await this.context.newPage(),this.debugSnapshot.context.userAgent=await Pt(this.page);else{let r=await bt(this.browser);this.debugSnapshot.context.userAgent=r,this.context=await this.browser.newContext(Wt(t,r)),this.page=await this.context.newPage()}if(await this.installEsbuildHelperShims(this.context),t.preserve\u004b\u0065\u0072\u006e\u0065\u006cContext||await this.page.setViewportSize(t.viewport),(this.debugEnabled||t.requireUsEgress)&&(this.debugSnapshot.networkLocation=await this.captureBrowserNetworkLocation()),t.requireUsEgress){let r=this.debugSnapshot.networkLocation?.country??null;if(!Ln(r))throw new E(`Non-US egress (${r??"unknown"}) \u2014 retrying with a fresh session`)}return}let s={headless:t.headless,proxy:t.proxy?{server:t.proxy}:void 0,...t.browserExecutablePath?{executablePath:t.browserExecutablePath}:{},...t.ignoreDefaultArgs?{ignoreDefaultArgs:t.ignoreDefaultArgs}:{}};if(t.profileDir)this.context=await _t.launchPersistentContext(t.profileDir,{...s,...Wt(t)}),await this.installEsbuildHelperShims(this.context),this.page=await this.context.newPage(),this.debugSnapshot.context.userAgent=await Pt(this.page);else{this.browser=await _t.launch(s);let i=await bt(this.browser);this.debugSnapshot.context.userAgent=i,this.context=await this.browser.newContext(Wt(t,i)),await this.installEsbuildHelperShims(this.context),this.page=await this.context.newPage()}this.debugEnabled&&(this.debugSnapshot.networkLocation=await this.captureBrowserNetworkLocation())}async populate\u004b\u0065\u0072\u006e\u0065\u006cRetrieveDebug(t,n){if(!(!this.\u006b\u0065\u0072\u006e\u0065\u006cClient||!this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId))try{let a=await ot(this.\u006b\u0065\u0072\u006e\u0065\u006cClient.browsers.retrieve(this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId),5e3,`\u004b\u0065\u0072\u006e\u0065\u006c session ${this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId} retrieve`);t.retrievedProxyIdPresent=typeof a.proxy_id=="string"?!!a.proxy_id:!1,t.retrievedProxyIdSuffix=Jt(a.proxy_id),t.retrievedProxyIdMatchesRequested=n?a.proxy_id===n:!a.proxy_id,t.timeoutSeconds=typeof a.timeout_seconds=="number"?a.timeout_seconds:t.timeoutSeconds,t.stealth=typeof a.stealth=="boolean"?a.stealth:t.stealth,t.profilePresent=!!a.profile,t.poolPresent=!!a.pool}catch(a){t.retrieveError=ut(a)}}async captureBrowserNetworkLocation(){let t=(a,s="ipapi.co")=>({source:s,ip:null,city:null,region:null,country:null,org:null,timezone:null,error:a});if(!this.context)return t("browser context is not available");let n=null;try{n=await this.context.newPage();let a=await this.loadJsonInDebugPage(n,"https://ipwho.is/");if(a){let l=typeof a.connection=="object"&&a.connection!==null?a.connection:{};return{source:"ipwho.is",ip:typeof a.ip=="string"?a.ip:null,city:typeof a.city=="string"?a.city:null,region:typeof a.region=="string"?a.region:null,country:typeof a.country=="string"?a.country:null,org:typeof l.org=="string"?l.org:null,timezone:typeof a.timezone=="object"&&a.timezone!==null&&typeof a.timezone.id=="string"?a.timezone.id:null,error:null}}let s=await this.loadJsonInDebugPage(n,"https://api64.ipify.org?format=json");if(s)return{source:"api64.ipify.org",ip:typeof s.ip=="string"?s.ip:null,city:null,region:null,country:null,org:null,timezone:null,error:null};await ot(n.goto("https://ipapi.co/json/",{waitUntil:"domcontentloaded",timeout:7e3}),8e3,"browser network location navigation");let i=await n.locator("body").innerText({timeout:2e3}),d=JSON.parse(i);return{source:"ipapi.co",ip:typeof d.ip=="string"?d.ip:null,city:typeof d.city=="string"?d.city:null,region:typeof d.region=="string"?d.region:null,country:typeof d.country_name=="string"?d.country_name:typeof d.country=="string"?d.country:null,org:typeof d.org=="string"?d.org:null,timezone:typeof d.timezone=="string"?d.timezone:null,error:null}}catch(a){return t(ut(a))}finally{await n?.close().catch(()=>{})}}async loadJsonInDebugPage(t,n){try{await ot(t.goto(n,{waitUntil:"domcontentloaded",timeout:7e3}),8e3,`browser network location navigation ${n}`);let a=await t.locator("body").innerText({timeout:2e3});return JSON.parse(a)}catch{return null}}async installEsbuildHelperShims(t){await t.addInitScript(()=>{let n=globalThis;typeof n.__name!="function"&&(n.__name=a=>a),typeof n.__publicField!="function"&&(n.__publicField=(a,s,i)=>(a[s]=i,i))})}async withTemporaryPage(t,n){if(!this.context)throw new Error("Browser context is not available");return ft(this.context,async()=>{},t,n)}async navigateToSERP(t,n,a,s,i){let d=new URLSearchParams({q:t,gl:a,hl:s,pws:"0"});i?.tbs&&d.set("tbs",i.tbs),n&&d.set("uule",n);let l="https://www.google.com/search?"+d.toString(),U=Le(l),u=i?.debug?{requestedUrl:l,finalUrl:null,title:null,bodySnippet:null,hasPaa:null,captchaDetected:null,googleSorryUrl:null,redirected:null}:null;u&&(this.debugSnapshot.serpNavigation=u);try{await this.page.goto(U,{waitUntil:"domcontentloaded",timeout:45e3})}catch(o){await this.updateSerpNavigationDebug(u,l,{hasPaa:null,captchaDetected:null});let r=await this.captureDiagnostics(l);throw new vt(`page.goto failed: ${o.message} | ${r}`)}if(await this.isSerpChallengeVisible())throw await this.updateSerpNavigationDebug(u,l,{hasPaa:!1,captchaDetected:!0}),new E(this.captchaMessage());if(await this.page.waitForSelector(H.item,{timeout:4e3}).catch(()=>null))return await this.updateSerpNavigationDebug(u,l,{hasPaa:!0,captchaDetected:!1}),{hasPaa:!0};if(await this.isSerpChallengeVisible())throw await this.updateSerpNavigationDebug(u,l,{hasPaa:!1,captchaDetected:!0}),new E(this.captchaMessage());for(let o=1;o<=6;o++)if(await this.page.evaluate(h=>{window.scrollTo(0,document.body.scrollHeight*h)},o/6),await this.page.waitForTimeout(600),await this.page.locator(H.item).count()>0)return await this.updateSerpNavigationDebug(u,l,{hasPaa:!0,captchaDetected:!1}),{hasPaa:!0};return await this.updateSerpNavigationDebug(u,l,{hasPaa:!1,captchaDetected:!1}),{hasPaa:!1}}async isSerpChallengeVisible(){if(!this.page)return!1;if(await this.page.locator(H.captchaMarker).count().catch(()=>0)>0)return!0;let n=this.page.url();if(/google\.[^/]+\/sorry\//i.test(n))return!0;let a=await this.page.evaluate(()=>(document.body?.innerText??"").replace(/\s+/g," ").trim().slice(0,1e3)).catch(()=>"");return/recaptcha|unusual traffic|are you a robot|about this page|detected unusual traffic/i.test(a)}async updateSerpNavigationDebug(t,n,a){if(!(!t||!this.page))try{let s=this.page.url(),i=await this.page.title().catch(()=>""),d=await this.page.evaluate(()=>(document.body?.innerText??"").replace(/\s+/g," ").trim().slice(0,500)).catch(()=>""),l=/recaptcha|unusual traffic|are you a robot/i.test(d);t.finalUrl=s,t.title=i,t.bodySnippet=d,t.hasPaa=a.hasPaa,t.captchaDetected=a.captchaDetected??l,t.googleSorryUrl=/google\.[^/]+\/sorry\//i.test(s),t.redirected=s!==n}catch(s){t.bodySnippet=`debug capture failed: ${ut(s)}`}}async captureDiagnostics(t){try{let n=this.page.url(),a=await this.page.title().catch(()=>""),s=await this.page.evaluate(()=>(document.body?.innerText??"").replace(/\s+/g," ").trim().slice(0,400)).catch(()=>""),i=/consent\.google\./.test(n)||/before you continue/i.test(s),d=/recaptcha|unusual traffic|are you a robot/i.test(s),l=[i?"CONSENT_WALL":"",d?"BOT_CHALLENGE":"",n!==t?"REDIRECTED":""].filter(Boolean).join(",");return`intended=${t} | final=${n} | title="${a}" | flags=[${l}] | body="${s}"`}catch(n){return`diagnostics-failed: ${n.message}`}}captchaMessage(){return this.\u006b\u0065\u0072\u006e\u0065\u006cClient?"Google returned a CAPTCHA on this session \u2014 retrying with a fresh session.":Ce}async navigateTo(t){let n=process.env.ADS_ARRIVAL_REDIRECT_BASE?.trim(),a=n?Le(t,n):t;try{if(await this.page.goto(a,{waitUntil:"domcontentloaded",timeout:45e3}),/google\.[^/]+\/search\?/i.test(t)&&await this.isSerpChallengeVisible())throw new E(this.captchaMessage())}catch(s){if(s instanceof E)throw s;let i=await this.captureDiagnostics(t);throw new vt(`page.goto failed: ${s.message} | ${i}`)}}async navigateToChannel(t){let n=Bn(t);try{await this.page.goto(n,{waitUntil:"networkidle",timeout:3e4})}catch(a){let s=await this.captureDiagnostics(n);throw new vt(`navigateToChannel failed: ${a.message} | ${s}`)}}async evaluate(t,n){return this.page.evaluate(t,n)}getPage(){return this.page}get\u004b\u0065\u0072\u006e\u0065\u006cSessionId(){return this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId}getProviderSessionMetadata(){return{provider:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId?"\u006b\u0065\u0072\u006e\u0065\u006c":"local",providerSessionId:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,disconnectObservation:null}}getDebugSnapshot(){return this.debugSnapshot}async close(){if(this.browser){let t=this.browser,n=this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,a=this.\u006b\u0065\u0072\u006e\u0065\u006cClient,s=this.\u006b\u0065\u0072\u006e\u0065\u006cOpenedAtMs,i=this.\u006b\u0065\u0072\u006e\u0065\u006cStealth,d=this.\u006b\u0065\u0072\u006e\u0065\u006cProxyUsed,l=this.\u006b\u0065\u0072\u006e\u0065\u006cProxySource,U=this.\u006b\u0065\u0072\u006e\u0065\u006cProxyType,u=this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent,S=this.getProviderSessionMetadata();if(this.browser=null,this.context=null,this.page=null,this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId=null,this.\u006b\u0065\u0072\u006e\u0065\u006cClient=null,this.\u006b\u0065\u0072\u006e\u0065\u006cOpenedAtMs=null,this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent=null,this.\u006b\u0065\u0072\u006e\u0065\u006cProxySource=null,this.\u006b\u0065\u0072\u006e\u0065\u006cProxyType=null,a&&n&&s!=null&&ve({\u006b\u0065\u0072\u006e\u0065\u006cSessionId:n,source:"browser_driver",stealth:i,headlessSent:u,proxyUsed:d,proxySource:l,proxyType:U,openedAtMs:s,closedAtMs:Date.now()}),a&&n){console.info(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_delete_started",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:n}));let o=ot(a.browsers.deleteByID(n),In,`\u004b\u0065\u0072\u006e\u0065\u006c session ${n} delete`),r=ot(t.close(),Wn,`\u004b\u0065\u0072\u006e\u0065\u006c browser ${n} close`),[h,c]=await Promise.allSettled([o,r]),C={\u006b\u0065\u0072\u006e\u0065\u006cSessionId:n,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!0,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:h.status==="fulfilled",\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:h.status==="rejected"?h.reason instanceof Error?h.reason.message:String(h.reason):null,browserCloseSucceeded:c.status==="fulfilled",browserCloseError:c.status==="rejected"?c.reason instanceof Error?c.reason.message:String(c.reason):null,provider:S.provider,providerSessionId:S.providerSessionId,providerDisconnectObserved:!1,providerDisconnectMessage:null};return h.status==="rejected"?(console.warn(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_delete_failed",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:n,message:C.\u006b\u0065\u0072\u006e\u0065\u006cDeleteError})),console.warn(`\u004b\u0065\u0072\u006e\u0065\u006c session cleanup failed for ${n}:`,h.reason)):console.info(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_delete_succeeded",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:n})),c.status==="rejected"&&(console.warn(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_close_failed",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:n,message:C.browserCloseError})),console.warn(`\u004b\u0065\u0072\u006e\u0065\u006c browser close failed for ${n}:`,c.reason)),C}return await t.close(),{\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!1,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:null,browserCloseSucceeded:!0,browserCloseError:null,provider:S.provider,providerSessionId:S.providerSessionId,providerDisconnectObserved:!1,providerDisconnectMessage:null}}else if(this.context){let t=this.context;return this.context=null,this.page=null,await t.close(),{\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!1,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:null,browserCloseSucceeded:!0,browserCloseError:null,provider:"local",providerSessionId:null,providerDisconnectObserved:!1,providerDisconnectMessage:null}}return{\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!1,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:null,browserCloseSucceeded:null,browserCloseError:null,provider:"local",providerSessionId:null,providerDisconnectObserved:!1,providerDisconnectMessage:null}}};import{chromium as Rn}from"playwright";function Hn(e,t){if(typeof e!="string")return null;let n=e.replace(/[\u0000-\u001f\u007f]+/g," ").replace(/\s+/g," ").trim();return n?n.slice(0,t):null}function Oe(e){let t=Hn(e,320);return t?t.replace(/\b(?:wss?|https?):\/\/\S+/gi,"[redacted endpoint]").replace(/\b(?:authorization|proxy-authorization):\s*\S+/gi,"$1: [redacted]").replace(/\bBearer\s+\S+/gi,"Bearer [redacted]").slice(0,320):null}function xe(e){return Oe(e)}function Be(e){if(typeof e!="string"||e.length===0||e.length>512||e.trim()!==e||/[\s\u0000-\u001f\u007f]/.test(e)||/:\/\//.test(e))throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 did not return a valid browser session ID");return e}function zt(e,t,n=new Date().toISOString()){let a=Oe(t);return{source:e,message:a??e.replaceAll("_"," "),observedAt:n}}function Fn(e){return{provider:e.provider,providerDisconnectObserved:e.disconnectObservation!==null,providerDisconnectMessage:e.disconnectObservation?.message??null}}function He(e){return{...Fn(e),providerSessionId:e.providerSessionId}}var Gn=new Set(["image","media","font","stylesheet","ping"]),Dn=["doubleclick.net","googleadservices.com","googlesyndication.com","google-analytics.com"];function Fe(){return process.env.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_BROWSER_WSS?.trim()||null}function Re(){return process.env.SERP_BROWSER_PROVIDER?.trim().toLowerCase()==="\u006b\u0065\u0072\u006e\u0065\u006c"?!1:!!Fe()}async function qt(e,t=!1){let n=e.request();try{let a=await n.allHeaders(),s=await fetch(n.url(),{method:n.method(),headers:{accept:a.accept??"*/*","accept-language":a["accept-language"]??"en-US,en;q=0.9","user-agent":a["user-agent"]??"Mozilla/5.0",...t?{cookie:a.cookie??"",referer:a.referer??"https://www.google.com/",...a["x-client-data"]?{"x-client-data":a["x-client-data"]}:{}}:{}},body:n.method()==="GET"||n.method()==="HEAD"?void 0:n.postData()});if(!s.ok)return!1;let i=Buffer.from(await s.arrayBuffer());return await e.fulfill({status:s.status,contentType:s.headers.get("content-type")??"application/octet-stream",headers:{"cache-control":"public, max-age=3600"},body:i}),!0}catch{return!1}}var At=class{browser=null;context=null;page=null;cdpSession=null;providerSessionId=null;disconnectObservation=null;closing=!1;observeDisconnect(t,n){this.closing||this.disconnectObservation||(this.disconnectObservation=zt(t,n))}async launch(t){if(this.page)return;this.closing=!1,this.providerSessionId=null,this.disconnectObservation=null;let n=Fe();if(!n)throw new Error("SERP browser service is not configured");this.browser=await Rn.connectOverCDP(n),this.context=this.browser.contexts()[0]??await this.browser.newContext(),await this.context.addInitScript(()=>{let i=globalThis;typeof i.__name!="function"&&(i.__name=d=>d),typeof i.__publicField!="function"&&(i.__publicField=(d,l,U)=>(d[l]=U,U))}),this.page=this.context.pages()[0]??await this.context.newPage(),this.browser.on("disconnected",()=>this.observeDisconnect("browser_disconnected")),this.context.on("close",()=>this.observeDisconnect("context_closed")),this.page.on("close",()=>this.observeDisconnect("page_closed")),this.page.on("crash",()=>this.observeDisconnect("page_crashed")),this.cdpSession=await this.context.newCDPSession(this.page);let s=await this.cdpSession.send("Browser.getSessionId");this.providerSessionId=Be(s?.sessionId),await this.setupPage(this.page)}async setupPage(t){await t.route("**/*",async n=>{let a=n.request(),s=a.resourceType(),i;try{i=new URL(a.url())}catch{await n.continue();return}let d=i.hostname.toLowerCase();if(!(i.pathname==="/sgasync"&&await qt(n,!0))&&!(i.pathname.includes("/shared_dict/")&&await qt(n))&&!(s==="script"&&(d==="www.google.com"||d==="www.gstatic.com")&&await qt(n))){if(Gn.has(s)){await n.abort("blockedbyclient");return}if(Dn.some(l=>d===l||d.endsWith(`.${l}`))){await n.abort("blockedbyclient");return}await n.continue()}})}async withTemporaryPage(t,n){if(!this.context||this.closing)throw new Error("Browser context is not available");return ft(this.context,a=>this.setupPage(a),t,n)}async navigateToSERP(t,n,a,s,i){if(!this.page)throw new Error("Browser page is not available");let d=new URLSearchParams({q:t,gl:a,hl:s,pws:"0"});return i?.tbs&&d.set("tbs",i.tbs),n&&d.set("uule",n),await this.page.goto(`https://www.google.com/search?${d}`,{waitUntil:"load",timeout:45e3}),{hasPaa:!!await this.page.waitForSelector(H.item,{timeout:8e3}).catch(()=>null)}}async navigateTo(t){if(!this.page)throw new Error("Browser page is not available");await this.page.goto(t,{waitUntil:"load",timeout:45e3})}async navigateToChannel(){throw new Error("YouTube navigation is not supported by the SERP browser driver")}async evaluate(t,n){if(!this.page)throw new Error("Browser page is not available");return this.page.evaluate(t,n)}getPage(){if(!this.page)throw new Error("Browser page is not available");return this.page}get\u004b\u0065\u0072\u006e\u0065\u006cSessionId(){return null}getProviderSessionMetadata(){return{provider:"\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api",providerSessionId:this.providerSessionId,disconnectObservation:this.disconnectObservation}}getDebugSnapshot(){return{\u006b\u0065\u0072\u006e\u0065\u006c:null,context:null,networkLocation:null,serpNavigation:null}}async close(){this.closing=!0;let t=null;try{await this.browser?.close()}catch(a){t=xe(a instanceof Error?a.message:String(a))??"\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 browser close failed",this.disconnectObservation??=zt("browser_close_error",t)}let n=He(this.getProviderSessionMetadata());return this.browser=null,this.context=null,this.page=null,this.cdpSession=null,{\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!1,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:null,browserCloseSucceeded:t===null,browserCloseError:t,...n}}};function Ge(e,t){let n=!!(e?.serpIdentity||e?.\u006b\u0065\u0072\u006e\u0065\u006cProfileName);return t?.forceManaged===!0||Re()&&!n?new At:new It}var tt={austin:"Austin,Texas,United States","new york":"New York,New York,United States","new york city":"New York,New York,United States",nyc:"New York,New York,United States","los angeles":"Los Angeles,California,United States",la:"Los Angeles,California,United States",chicago:"Chicago,Illinois,United States",houston:"Houston,Texas,United States",phoenix:"Phoenix,Arizona,United States",philadelphia:"Philadelphia,Pennsylvania,United States",philly:"Philadelphia,Pennsylvania,United States","san antonio":"San Antonio,Texas,United States",dallas:"Dallas,Texas,United States",miami:"Miami,Florida,United States",seattle:"Seattle,Washington,United States",denver:"Denver,Colorado,United States",loveland:"Loveland,Colorado,United States","loveland co":"Loveland,Colorado,United States","fort collins":"Fort Collins,Colorado,United States",boulder:"Boulder,Colorado,United States","colorado springs":"Colorado Springs,Colorado,United States",boston:"Boston,Massachusetts,United States",atlanta:"Atlanta,Georgia,United States","san francisco":"San Francisco,California,United States",sf:"San Francisco,California,United States",portland:"Portland,Oregon,United States","las vegas":"Las Vegas,Nevada,United States",minneapolis:"Minneapolis,Minnesota,United States",detroit:"Detroit,Michigan,United States",nashville:"Nashville,Tennessee,United States",charlotte:"Charlotte,North Carolina,United States",orlando:"Orlando,Florida,United States","san diego":"San Diego,California,United States",baltimore:"Baltimore,Maryland,United States",sacramento:"Sacramento,California,United States",columbus:"Columbus,Ohio,United States",indianapolis:"Indianapolis,Indiana,United States","san jose":"San Jose,California,United States","fort worth":"Fort Worth,Texas,United States",jacksonville:"Jacksonville,Florida,United States",memphis:"Memphis,Tennessee,United States",louisville:"Louisville,Kentucky,United States",raleigh:"Raleigh,North Carolina,United States",richmond:"Richmond,Virginia,United States","salt lake city":"Salt Lake City,Utah,United States",toronto:"Toronto,Ontario,Canada",vancouver:"Vancouver,British Columbia,Canada",montreal:"Montreal,Quebec,Canada",calgary:"Calgary,Alberta,Canada",ottawa:"Ottawa,Ontario,Canada",london:"London,England,United Kingdom",manchester:"Manchester,England,United Kingdom",birmingham:"Birmingham,England,United Kingdom",edinburgh:"Edinburgh,Scotland,United Kingdom",glasgow:"Glasgow,Scotland,United Kingdom",leeds:"Leeds,England,United Kingdom",sydney:"Sydney,New South Wales,Australia",melbourne:"Melbourne,Victoria,Australia",brisbane:"Brisbane,Queensland,Australia",perth:"Perth,Western Australia,Australia",adelaide:"Adelaide,South Australia,Australia",dublin:"Dublin,Leinster,Ireland"};var De=`3, Nanjemoy,Maryland,United States
|
|
1
|
+
import{f as q}from"./chunk-QPWPR5XG.js";import{a as ye}from"./chunk-4FROKQJN.js";import{a as ke,b as pe,c as Nt,d as me,g as ve}from"./chunk-D4NOJAUN.js";import{a as ce,c as we,d as Ut,g as ge,l as Ne}from"./chunk-3GP5CYZX.js";import{a as Ce,i as Me,j as E,k as vt,m as _,n as ht,o as Kt}from"./chunk-Z66Z2HV4.js";import{chromium as _t}from"playwright-extra";import fn from"puppeteer-extra-plugin-stealth";import{chromium as Pn}from"playwright";var H={container:".eJH8qe.adDDi",dataInitq:"[data-initq]",item:".related-question-pair",itemDataQ:"data-q",itemDataInitQ:"data-initq",itemQuestionEl:".JlqpRe",answerContainer:".bCOlv, .hgKElc, .wDYxhc, .LGOjhe, .fo7IQd, .fmW3u",aiAnswerBody:".pWvJNd",aiCitation:"a.PMDqCb[href]",aiSourceCard:"a.vIWmYe[href], a.Zbfntb[href]",sourceTitle:"h3",sourceSite:".VuuXrf",sourceCite:"cite",clickTarget:".JlqpRe",expandedClass:"aoRk1c",captchaMarker:'#captcha-form, #recaptcha, form[action*="/sorry/"], .g-recaptcha, [data-sitekey]'},Te={container:'div[jscontroller="HWk0Gf"]',sectionHeading:'.mgAbYb[role="heading"]',item:"a.rIRoqf"},Tt={udm:"39",item:"a.rIRoqf",durationPattern:/^\d+:\d+$/,platforms:["YouTube","TikTok","Instagram","Facebook","X"]},fe={section:".ULSxyf",item:"a.KYg7td.INpicf",title:".hyYc0c",source:".K4ETW"},Pe={sectionTag:"g-section-with-header",sectionHeadingText:"What people are saying",card:'.dRzkFf[role="listitem"]',cardLink:'a.WlydOe[jsname="YKoRaf"]',titleH1:"h1.WQWxe",titleDiv:".eAaXgc",popularCommentLabel:".qgdis",source:".sTl1Td",platformBadge:".appd0, .KrMNbf",ytChannel:".sjVJQd",ytDate:".PLq9Je",authorNote:".nDgy9d"},be={root:"[data-lhcontainer][data-streaming-container][eid]",legacyRoot:'[data-hveid="CBMQAA"]',wrapper:".Fgyi2e",controller:'[jscontroller="AkrxPe"]',contentSubtree:'[data-subtree="mfc"]',header:".heWuVc",heading:".Fzsovc.cwYVJe.RJPOee",showMoreButton:'[aria-label="Show more AI Overview"]',sourcesPanel:".OZ9ddf.WAUd4",disclaimer:".DuQANe.MSJHRb"},We={root:'[data-hveid="CAUQAA"]',wrapper:".Fgyi2e",citations:'.Fgyi2e [data-hveid] a[jsname="pxBnId"]'},Ie={result:".wHYlTd.tF2Cxc",title:"h3.LC20lb",siteName:".VuuXrf",cite:"cite.tjvcx",snippet:".VwiC3b",redditCite:"cite.qLRx3b",ratingWrap:".Y0A0hc",ratingValue:".yi40Hd",reviewCount:".RDApEe"},Ae={headingText:"Businesses",card:".w7Dbne",name:".OSrXXb",ratingValue:".yi40Hd",reviewCount:".RDApEe"};var _a={ratingAndCount:"div.F7nice",hoursTable:"table.eK4R0e",reviewScrollPane:'div.m6QErb[tabindex="-1"]',reviewScrollPaneFallback:'[role="main"] div[tabindex="-1"]',reviewCardAuthor:"div.d4r55, span.d4r55, span.RPZfBb",reviewCardDate:"span.rsqaWe",reviewCardText:"span.wiI7pd",reviewCardOwnerBlock:"div.CDe7pd",hoursTableAlt:'table[aria-label*="Hour"]',reviewCard:"[data-review-id]",reviewStars:'[role="img"][aria-label*="star"]',reviewTab:'button[role="tab"][aria-label*="Review"]',aboutTab:'button[role="tab"][aria-label*="About"]',expandReview:'[data-review-id] button[aria-label*="See more"], [data-review-id] button.w8nwRe'};async function ft(e,t,n,a){let s,i=!1,d,l=()=>{},U=()=>a?.reason instanceof DOMException&&a.reason.name==="TimeoutError"?a.reason:new _,u=()=>l(U()),S=new Promise((r,h)=>{l=h}),o=async r=>{let h;try{await Promise.race([r.close().catch(()=>{}),new Promise(c=>{h=setTimeout(c,2e3)})])}finally{h&&clearTimeout(h)}};if(a?.aborted)throw U();a?.addEventListener("abort",u,{once:!0}),d=setTimeout(()=>l(new DOMException("Optional pagination timed out","TimeoutError")),3e4);try{return await Promise.race([(async()=>{let r=await e.newPage();if(i)throw await o(r),new _;if(s=r,await t(r),i)throw new _;return n(r)})(),S])}finally{i=!0,d&&clearTimeout(d),a?.removeEventListener("abort",u),s&&await o(s)}}var Tn=/\b(?:HeadlessChrome|Chrome|Chromium|Firefox)\/\d+|\bVersion\/\d+.*\bSafari\//;async function Pt(e){try{let t=await e.evaluate(()=>navigator.userAgent);return typeof t=="string"&&Tn.test(t)?t:null}catch{return null}}async function bt(e){let t=null;try{let n=e.contexts().flatMap(a=>a.pages())[0];return n||(t=await e.newContext(),n=t.pages()[0]??await t.newPage()),await Pt(n)}catch{return null}finally{t&&await t.close().catch(()=>{})}}function ja(e,t){return t?{...e,userAgent:t}:e}_t.use(fn());var bn=180,Wn=3e3,In=5e3;function An(e,t){let n=process.env[e];if(!n)return t;let a=Number(n);return Number.isInteger(a)&&a>0?a:t}function Jt(e){return e?e.slice(-6):null}function Le(e,t){let n=(t??process.env.SERP_REDIRECT_BASE)?.trim().replace(/\/+$/,"");return n?`${n}/g/${Buffer.from(e,"utf8").toString("base64url")}`:e}function Ln(e){return e?/united states|u\.?s\.?a?\.?|^us$/i.test(e.trim()):!1}function ut(e){return e instanceof Error?e.message:String(e)}function On(e){return/\b409\b|conflict|already exists/i.test(ut(e))}async function xn(e,t){try{await e.profiles.create({name:t})}catch(n){if(!On(n))throw n}}function Wt(e,t){return{viewport:e.viewport,locale:e.locale,...t?{userAgent:t}:{},...e.deviceScaleFactor?{deviceScaleFactor:e.deviceScaleFactor}:{},...e.isMobile!==void 0?{isMobile:e.isMobile}:{},...e.hasTouch!==void 0?{hasTouch:e.hasTouch}:{}}}async function ot(e,t,n){let a;try{return await Promise.race([e,new Promise((s,i)=>{a=setTimeout(()=>i(new Error(`${n} timed out after ${t}ms`)),t)})])}finally{a&&clearTimeout(a)}}function Bn(e){let t=e.trim();if(!t)throw new Error("channelHandle is required");if(/^https?:\/\//i.test(t)||/^(www\.|m\.)?youtube\.com\//i.test(t)){let d=new URL(/^https?:\/\//i.test(t)?t:`https://${t}`);if(d.hostname.replace(/^www\./,"").replace(/^m\./,"").toLowerCase()!=="youtube.com")throw new Error("channel URL must be on youtube.com");let U=d.pathname.split("/").filter(Boolean),u=U[0]??"",S=U[1]??"";if(u.startsWith("@"))return`https://www.youtube.com/${u}/videos`;if(u==="channel"&&S)return`https://www.youtube.com/channel/${S}/videos`;if((u==="c"||u==="user")&&S)return`https://www.youtube.com/${u}/${S}/videos`;throw new Error("channel URL must be a YouTube handle, /channel/UC..., /c/..., or /user/... URL")}let s=t.replace(/^\/+/,"").replace(/\/+$/,"").replace(/\/videos$/i,"");if(/^UC[\w-]{20,}$/.test(s))return`https://www.youtube.com/channel/${s}/videos`;let i=s.startsWith("@")?s:`@${s}`;if(!/^@[\w.-]+$/.test(i))throw new Error("channelHandle must be an @handle, UC channel ID, or YouTube channel URL");return`https://www.youtube.com/${i}/videos`}var It=class{browser=null;context=null;page=null;\u006b\u0065\u0072\u006e\u0065\u006cClient=null;\u006b\u0065\u0072\u006e\u0065\u006cSessionId=null;\u006b\u0065\u0072\u006e\u0065\u006cOpenedAtMs=null;\u006b\u0065\u0072\u006e\u0065\u006cStealth=null;\u006b\u0065\u0072\u006e\u0065\u006cProxyUsed=null;\u006b\u0065\u0072\u006e\u0065\u006cProxySource=null;\u006b\u0065\u0072\u006e\u0065\u006cProxyType=null;\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent=null;debugEnabled=!1;debugSnapshot={\u006b\u0065\u0072\u006e\u0065\u006c:null,context:null,networkLocation:null,serpNavigation:null};async launch(t){this.debugEnabled=t.debug===!0;let n=t.proxyMode??(t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId?"configured":"none"),a=t.isMobile?"mobile":"desktop";if(this.debugSnapshot={\u006b\u0065\u0072\u006e\u0065\u006c:null,context:{viewport:t.viewport,locale:t.locale,device:a,userAgent:null,deviceScaleFactor:t.deviceScaleFactor??null,isMobile:t.isMobile===!0,hasTouch:t.hasTouch===!0},networkLocation:null,serpNavigation:null},t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey){this.\u006b\u0065\u0072\u006e\u0065\u006cClient=new q({apiKey:t.\u006b\u0065\u0072\u006e\u0065\u006cApiKey});let i=Number.isInteger(t.\u006b\u0065\u0072\u006e\u0065\u006cTimeoutSeconds)&&Number(t.\u006b\u0065\u0072\u006e\u0065\u006cTimeoutSeconds)>0?Number(t.\u006b\u0065\u0072\u006e\u0065\u006cTimeoutSeconds):An("\u004b\u0045\u0052\u004e\u0045\u004c_BROWSER_TIMEOUT_SECONDS",bn);t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName&&t.\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges===!0&&await xn(this.\u006b\u0065\u0072\u006e\u0065\u006cClient,t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName);let d=Nt(),l;t.headlessMode==="headful"||d?.forceHeadful===!0?l=!1:t.headlessMode==="headless"?l=!0:l=d?.forceHeadless===!0||process.env.\u004b\u0045\u0052\u004e\u0045\u004c_HEADLESS_DISABLED!=="true"&&!!d?.op&&me.has(d.op),this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent=l?!0:null,d?.headlessSentOut&&(d.headlessSentOut.value=this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent);let U=await this.\u006b\u0065\u0072\u006e\u0065\u006cClient.browsers.create({stealth:t.\u006b\u0065\u0072\u006e\u0065\u006cStealth===!0,timeout_seconds:i,...l?{headless:!0}:{},...t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId?{proxy_id:t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId}:{},...t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName?{profile:{name:t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName,...typeof t.\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges=="boolean"?{save_changes:t.\u006b\u0065\u0072\u006e\u0065\u006cProfileSaveChanges}:{}}}:{}});this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId=U.session_id,this.\u006b\u0065\u0072\u006e\u0065\u006cOpenedAtMs=Date.now(),this.\u006b\u0065\u0072\u006e\u0065\u006cStealth=typeof U.stealth=="boolean"?U.stealth:null,this.\u006b\u0065\u0072\u006e\u0065\u006cProxyUsed=typeof U.proxy_id=="string"?!!U.proxy_id:!!t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,this.\u006b\u0065\u0072\u006e\u0065\u006cProxySource=t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution?.source??null,this.\u006b\u0065\u0072\u006e\u0065\u006cProxyType=t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution?.proxyType??null;let u=null,S=null;if(!t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId&&!t.keepDefaultProxy)try{await ot(this.\u006b\u0065\u0072\u006e\u0065\u006cClient.browsers.update(this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,{disable_default_proxy:!0}),5e3,`\u004b\u0065\u0072\u006e\u0065\u006c session ${this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId} disable default proxy`),u=!0}catch(r){u=!1,S=ut(r)}let o={sessionId:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,proxyMode:n,requestedProxyIdPresent:!!t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,requestedProxyIdSuffix:Jt(t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId),createdProxyIdPresent:typeof U.proxy_id=="string"?!!U.proxy_id:null,createdProxyIdSuffix:Jt(U.proxy_id),retrievedProxyIdPresent:null,retrievedProxyIdSuffix:null,retrievedProxyIdMatchesRequested:null,defaultProxyDisabled:u,defaultProxyDisableError:S,proxyResolution:t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution??null,timeoutSeconds:i,stealth:typeof U.stealth=="boolean"?U.stealth:null,profilePresent:null,poolPresent:null,retrieveError:null};if(this.debugSnapshot.\u006b\u0065\u0072\u006e\u0065\u006c=o,console.info(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_created",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,timeout_seconds:i,proxy_mode:n,proxy_id_present:!!t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId,profile_name_present:!!t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName,proxy_resolution_source:t.\u006b\u0065\u0072\u006e\u0065\u006cProxyResolution?.source})),this.debugEnabled&&await this.populate\u004b\u0065\u0072\u006e\u0065\u006cRetrieveDebug(o,t.\u006b\u0065\u0072\u006e\u0065\u006cProxyId),this.browser=await Pn.connectOverCDP(U.cdp_ws_url),t.\u006b\u0065\u0072\u006e\u0065\u006cProfileName||t.preserve\u004b\u0065\u0072\u006e\u0065\u006cContext)this.context=this.browser.contexts()[0]??await this.browser.newContext(Wt(t)),this.page=this.context.pages()[0]??await this.context.newPage(),this.debugSnapshot.context.userAgent=await Pt(this.page);else{let r=await bt(this.browser);this.debugSnapshot.context.userAgent=r,this.context=await this.browser.newContext(Wt(t,r)),this.page=await this.context.newPage()}if(await this.installEsbuildHelperShims(this.context),t.preserve\u004b\u0065\u0072\u006e\u0065\u006cContext||await this.page.setViewportSize(t.viewport),(this.debugEnabled||t.requireUsEgress)&&(this.debugSnapshot.networkLocation=await this.captureBrowserNetworkLocation()),t.requireUsEgress){let r=this.debugSnapshot.networkLocation?.country??null;if(!Ln(r))throw new E(`Non-US egress (${r??"unknown"}) \u2014 retrying with a fresh session`)}return}let s={headless:t.headless,proxy:t.proxy?{server:t.proxy}:void 0,...t.browserExecutablePath?{executablePath:t.browserExecutablePath}:{},...t.ignoreDefaultArgs?{ignoreDefaultArgs:t.ignoreDefaultArgs}:{}};if(t.profileDir)this.context=await _t.launchPersistentContext(t.profileDir,{...s,...Wt(t)}),await this.installEsbuildHelperShims(this.context),this.page=await this.context.newPage(),this.debugSnapshot.context.userAgent=await Pt(this.page);else{this.browser=await _t.launch(s);let i=await bt(this.browser);this.debugSnapshot.context.userAgent=i,this.context=await this.browser.newContext(Wt(t,i)),await this.installEsbuildHelperShims(this.context),this.page=await this.context.newPage()}this.debugEnabled&&(this.debugSnapshot.networkLocation=await this.captureBrowserNetworkLocation())}async populate\u004b\u0065\u0072\u006e\u0065\u006cRetrieveDebug(t,n){if(!(!this.\u006b\u0065\u0072\u006e\u0065\u006cClient||!this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId))try{let a=await ot(this.\u006b\u0065\u0072\u006e\u0065\u006cClient.browsers.retrieve(this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId),5e3,`\u004b\u0065\u0072\u006e\u0065\u006c session ${this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId} retrieve`);t.retrievedProxyIdPresent=typeof a.proxy_id=="string"?!!a.proxy_id:!1,t.retrievedProxyIdSuffix=Jt(a.proxy_id),t.retrievedProxyIdMatchesRequested=n?a.proxy_id===n:!a.proxy_id,t.timeoutSeconds=typeof a.timeout_seconds=="number"?a.timeout_seconds:t.timeoutSeconds,t.stealth=typeof a.stealth=="boolean"?a.stealth:t.stealth,t.profilePresent=!!a.profile,t.poolPresent=!!a.pool}catch(a){t.retrieveError=ut(a)}}async captureBrowserNetworkLocation(){let t=(a,s="ipapi.co")=>({source:s,ip:null,city:null,region:null,country:null,org:null,timezone:null,error:a});if(!this.context)return t("browser context is not available");let n=null;try{n=await this.context.newPage();let a=await this.loadJsonInDebugPage(n,"https://ipwho.is/");if(a){let l=typeof a.connection=="object"&&a.connection!==null?a.connection:{};return{source:"ipwho.is",ip:typeof a.ip=="string"?a.ip:null,city:typeof a.city=="string"?a.city:null,region:typeof a.region=="string"?a.region:null,country:typeof a.country=="string"?a.country:null,org:typeof l.org=="string"?l.org:null,timezone:typeof a.timezone=="object"&&a.timezone!==null&&typeof a.timezone.id=="string"?a.timezone.id:null,error:null}}let s=await this.loadJsonInDebugPage(n,"https://api64.ipify.org?format=json");if(s)return{source:"api64.ipify.org",ip:typeof s.ip=="string"?s.ip:null,city:null,region:null,country:null,org:null,timezone:null,error:null};await ot(n.goto("https://ipapi.co/json/",{waitUntil:"domcontentloaded",timeout:7e3}),8e3,"browser network location navigation");let i=await n.locator("body").innerText({timeout:2e3}),d=JSON.parse(i);return{source:"ipapi.co",ip:typeof d.ip=="string"?d.ip:null,city:typeof d.city=="string"?d.city:null,region:typeof d.region=="string"?d.region:null,country:typeof d.country_name=="string"?d.country_name:typeof d.country=="string"?d.country:null,org:typeof d.org=="string"?d.org:null,timezone:typeof d.timezone=="string"?d.timezone:null,error:null}}catch(a){return t(ut(a))}finally{await n?.close().catch(()=>{})}}async loadJsonInDebugPage(t,n){try{await ot(t.goto(n,{waitUntil:"domcontentloaded",timeout:7e3}),8e3,`browser network location navigation ${n}`);let a=await t.locator("body").innerText({timeout:2e3});return JSON.parse(a)}catch{return null}}async installEsbuildHelperShims(t){await t.addInitScript(()=>{let n=globalThis;typeof n.__name!="function"&&(n.__name=a=>a),typeof n.__publicField!="function"&&(n.__publicField=(a,s,i)=>(a[s]=i,i))})}async withTemporaryPage(t,n){if(!this.context)throw new Error("Browser context is not available");return ft(this.context,async()=>{},t,n)}async navigateToSERP(t,n,a,s,i){let d=new URLSearchParams({q:t,gl:a,hl:s,pws:"0"});i?.tbs&&d.set("tbs",i.tbs),n&&d.set("uule",n);let l="https://www.google.com/search?"+d.toString(),U=Le(l),u=i?.debug?{requestedUrl:l,finalUrl:null,title:null,bodySnippet:null,hasPaa:null,captchaDetected:null,googleSorryUrl:null,redirected:null}:null;u&&(this.debugSnapshot.serpNavigation=u);try{await this.page.goto(U,{waitUntil:"domcontentloaded",timeout:45e3})}catch(o){await this.updateSerpNavigationDebug(u,l,{hasPaa:null,captchaDetected:null});let r=await this.captureDiagnostics(l);throw new vt(`page.goto failed: ${o.message} | ${r}`)}if(await this.isSerpChallengeVisible())throw await this.updateSerpNavigationDebug(u,l,{hasPaa:!1,captchaDetected:!0}),new E(this.captchaMessage());if(await this.page.waitForSelector(H.item,{timeout:4e3}).catch(()=>null))return await this.updateSerpNavigationDebug(u,l,{hasPaa:!0,captchaDetected:!1}),{hasPaa:!0};if(await this.isSerpChallengeVisible())throw await this.updateSerpNavigationDebug(u,l,{hasPaa:!1,captchaDetected:!0}),new E(this.captchaMessage());for(let o=1;o<=6;o++)if(await this.page.evaluate(h=>{window.scrollTo(0,document.body.scrollHeight*h)},o/6),await this.page.waitForTimeout(600),await this.page.locator(H.item).count()>0)return await this.updateSerpNavigationDebug(u,l,{hasPaa:!0,captchaDetected:!1}),{hasPaa:!0};return await this.updateSerpNavigationDebug(u,l,{hasPaa:!1,captchaDetected:!1}),{hasPaa:!1}}async isSerpChallengeVisible(){if(!this.page)return!1;if(await this.page.locator(H.captchaMarker).count().catch(()=>0)>0)return!0;let n=this.page.url();if(/google\.[^/]+\/sorry\//i.test(n))return!0;let a=await this.page.evaluate(()=>(document.body?.innerText??"").replace(/\s+/g," ").trim().slice(0,1e3)).catch(()=>"");return/recaptcha|unusual traffic|are you a robot|about this page|detected unusual traffic/i.test(a)}async updateSerpNavigationDebug(t,n,a){if(!(!t||!this.page))try{let s=this.page.url(),i=await this.page.title().catch(()=>""),d=await this.page.evaluate(()=>(document.body?.innerText??"").replace(/\s+/g," ").trim().slice(0,500)).catch(()=>""),l=/recaptcha|unusual traffic|are you a robot/i.test(d);t.finalUrl=s,t.title=i,t.bodySnippet=d,t.hasPaa=a.hasPaa,t.captchaDetected=a.captchaDetected??l,t.googleSorryUrl=/google\.[^/]+\/sorry\//i.test(s),t.redirected=s!==n}catch(s){t.bodySnippet=`debug capture failed: ${ut(s)}`}}async captureDiagnostics(t){try{let n=this.page.url(),a=await this.page.title().catch(()=>""),s=await this.page.evaluate(()=>(document.body?.innerText??"").replace(/\s+/g," ").trim().slice(0,400)).catch(()=>""),i=/consent\.google\./.test(n)||/before you continue/i.test(s),d=/recaptcha|unusual traffic|are you a robot/i.test(s),l=[i?"CONSENT_WALL":"",d?"BOT_CHALLENGE":"",n!==t?"REDIRECTED":""].filter(Boolean).join(",");return`intended=${t} | final=${n} | title="${a}" | flags=[${l}] | body="${s}"`}catch(n){return`diagnostics-failed: ${n.message}`}}captchaMessage(){return this.\u006b\u0065\u0072\u006e\u0065\u006cClient?"Google returned a CAPTCHA on this session \u2014 retrying with a fresh session.":Ce}async navigateTo(t){let n=process.env.ADS_ARRIVAL_REDIRECT_BASE?.trim(),a=n?Le(t,n):t;try{if(await this.page.goto(a,{waitUntil:"domcontentloaded",timeout:45e3}),/google\.[^/]+\/search\?/i.test(t)&&await this.isSerpChallengeVisible())throw new E(this.captchaMessage())}catch(s){if(s instanceof E)throw s;let i=await this.captureDiagnostics(t);throw new vt(`page.goto failed: ${s.message} | ${i}`)}}async navigateToChannel(t){let n=Bn(t);try{await this.page.goto(n,{waitUntil:"networkidle",timeout:3e4})}catch(a){let s=await this.captureDiagnostics(n);throw new vt(`navigateToChannel failed: ${a.message} | ${s}`)}}async evaluate(t,n){return this.page.evaluate(t,n)}getPage(){return this.page}get\u004b\u0065\u0072\u006e\u0065\u006cSessionId(){return this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId}getProviderSessionMetadata(){return{provider:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId?"\u006b\u0065\u0072\u006e\u0065\u006c":"local",providerSessionId:this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,disconnectObservation:null}}getDebugSnapshot(){return this.debugSnapshot}async close(){if(this.browser){let t=this.browser,n=this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,a=this.\u006b\u0065\u0072\u006e\u0065\u006cClient,s=this.\u006b\u0065\u0072\u006e\u0065\u006cOpenedAtMs,i=this.\u006b\u0065\u0072\u006e\u0065\u006cStealth,d=this.\u006b\u0065\u0072\u006e\u0065\u006cProxyUsed,l=this.\u006b\u0065\u0072\u006e\u0065\u006cProxySource,U=this.\u006b\u0065\u0072\u006e\u0065\u006cProxyType,u=this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent,S=this.getProviderSessionMetadata();if(this.browser=null,this.context=null,this.page=null,this.\u006b\u0065\u0072\u006e\u0065\u006cSessionId=null,this.\u006b\u0065\u0072\u006e\u0065\u006cClient=null,this.\u006b\u0065\u0072\u006e\u0065\u006cOpenedAtMs=null,this.\u006b\u0065\u0072\u006e\u0065\u006cHeadlessSent=null,this.\u006b\u0065\u0072\u006e\u0065\u006cProxySource=null,this.\u006b\u0065\u0072\u006e\u0065\u006cProxyType=null,a&&n&&s!=null&&ve({\u006b\u0065\u0072\u006e\u0065\u006cSessionId:n,source:"browser_driver",stealth:i,headlessSent:u,proxyUsed:d,proxySource:l,proxyType:U,openedAtMs:s,closedAtMs:Date.now()}),a&&n){console.info(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_delete_started",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:n}));let o=ot(a.browsers.deleteByID(n),In,`\u004b\u0065\u0072\u006e\u0065\u006c session ${n} delete`),r=ot(t.close(),Wn,`\u004b\u0065\u0072\u006e\u0065\u006c browser ${n} close`),[h,c]=await Promise.allSettled([o,r]),C={\u006b\u0065\u0072\u006e\u0065\u006cSessionId:n,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!0,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:h.status==="fulfilled",\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:h.status==="rejected"?h.reason instanceof Error?h.reason.message:String(h.reason):null,browserCloseSucceeded:c.status==="fulfilled",browserCloseError:c.status==="rejected"?c.reason instanceof Error?c.reason.message:String(c.reason):null,provider:S.provider,providerSessionId:S.providerSessionId,providerDisconnectObserved:!1,providerDisconnectMessage:null};return h.status==="rejected"?(console.warn(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_delete_failed",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:n,message:C.\u006b\u0065\u0072\u006e\u0065\u006cDeleteError})),console.warn(`\u004b\u0065\u0072\u006e\u0065\u006c session cleanup failed for ${n}:`,h.reason)):console.info(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_delete_succeeded",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:n})),c.status==="rejected"&&(console.warn(JSON.stringify({event:"\u006b\u0065\u0072\u006e\u0065\u006c_browser_close_failed",\u006b\u0065\u0072\u006e\u0065\u006c_session_id:n,message:C.browserCloseError})),console.warn(`\u004b\u0065\u0072\u006e\u0065\u006c browser close failed for ${n}:`,c.reason)),C}return await t.close(),{\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!1,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:null,browserCloseSucceeded:!0,browserCloseError:null,provider:S.provider,providerSessionId:S.providerSessionId,providerDisconnectObserved:!1,providerDisconnectMessage:null}}else if(this.context){let t=this.context;return this.context=null,this.page=null,await t.close(),{\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!1,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:null,browserCloseSucceeded:!0,browserCloseError:null,provider:"local",providerSessionId:null,providerDisconnectObserved:!1,providerDisconnectMessage:null}}return{\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!1,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:null,browserCloseSucceeded:null,browserCloseError:null,provider:"local",providerSessionId:null,providerDisconnectObserved:!1,providerDisconnectMessage:null}}};import{chromium as Rn}from"playwright";function Hn(e,t){if(typeof e!="string")return null;let n=e.replace(/[\u0000-\u001f\u007f]+/g," ").replace(/\s+/g," ").trim();return n?n.slice(0,t):null}function Oe(e){let t=Hn(e,320);return t?t.replace(/\b(?:wss?|https?):\/\/\S+/gi,"[redacted endpoint]").replace(/\b(?:authorization|proxy-authorization):\s*\S+/gi,"$1: [redacted]").replace(/\bBearer\s+\S+/gi,"Bearer [redacted]").slice(0,320):null}function xe(e){return Oe(e)}function Be(e){if(typeof e!="string"||e.length===0||e.length>512||e.trim()!==e||/[\s\u0000-\u001f\u007f]/.test(e)||/:\/\//.test(e))throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 did not return a valid browser session ID");return e}function zt(e,t,n=new Date().toISOString()){let a=Oe(t);return{source:e,message:a??e.replaceAll("_"," "),observedAt:n}}function Fn(e){return{provider:e.provider,providerDisconnectObserved:e.disconnectObservation!==null,providerDisconnectMessage:e.disconnectObservation?.message??null}}function He(e){return{...Fn(e),providerSessionId:e.providerSessionId}}var Gn=new Set(["image","media","font","stylesheet","ping"]),Dn=["doubleclick.net","googleadservices.com","googlesyndication.com","google-analytics.com"];function Fe(){return process.env.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_BROWSER_WSS?.trim()||null}function Re(){return process.env.SERP_BROWSER_PROVIDER?.trim().toLowerCase()==="\u006b\u0065\u0072\u006e\u0065\u006c"?!1:!!Fe()}async function qt(e,t=!1){let n=e.request();try{let a=await n.allHeaders(),s=await fetch(n.url(),{method:n.method(),headers:{accept:a.accept??"*/*","accept-language":a["accept-language"]??"en-US,en;q=0.9","user-agent":a["user-agent"]??"Mozilla/5.0",...t?{cookie:a.cookie??"",referer:a.referer??"https://www.google.com/",...a["x-client-data"]?{"x-client-data":a["x-client-data"]}:{}}:{}},body:n.method()==="GET"||n.method()==="HEAD"?void 0:n.postData()});if(!s.ok)return!1;let i=Buffer.from(await s.arrayBuffer());return await e.fulfill({status:s.status,contentType:s.headers.get("content-type")??"application/octet-stream",headers:{"cache-control":"public, max-age=3600"},body:i}),!0}catch{return!1}}var At=class{browser=null;context=null;page=null;cdpSession=null;providerSessionId=null;disconnectObservation=null;closing=!1;observeDisconnect(t,n){this.closing||this.disconnectObservation||(this.disconnectObservation=zt(t,n))}async launch(t){if(this.page)return;this.closing=!1,this.providerSessionId=null,this.disconnectObservation=null;let n=Fe();if(!n)throw new Error("SERP browser service is not configured");this.browser=await Rn.connectOverCDP(n),this.context=this.browser.contexts()[0]??await this.browser.newContext(),await this.context.addInitScript(()=>{let i=globalThis;typeof i.__name!="function"&&(i.__name=d=>d),typeof i.__publicField!="function"&&(i.__publicField=(d,l,U)=>(d[l]=U,U))}),this.page=this.context.pages()[0]??await this.context.newPage(),this.browser.on("disconnected",()=>this.observeDisconnect("browser_disconnected")),this.context.on("close",()=>this.observeDisconnect("context_closed")),this.page.on("close",()=>this.observeDisconnect("page_closed")),this.page.on("crash",()=>this.observeDisconnect("page_crashed")),this.cdpSession=await this.context.newCDPSession(this.page);let s=await this.cdpSession.send("Browser.getSessionId");this.providerSessionId=Be(s?.sessionId),await this.setupPage(this.page)}async setupPage(t){await t.route("**/*",async n=>{let a=n.request(),s=a.resourceType(),i;try{i=new URL(a.url())}catch{await n.continue();return}let d=i.hostname.toLowerCase();if(!(i.pathname==="/sgasync"&&await qt(n,!0))&&!(i.pathname.includes("/shared_dict/")&&await qt(n))&&!(s==="script"&&(d==="www.google.com"||d==="www.gstatic.com")&&await qt(n))){if(Gn.has(s)){await n.abort("blockedbyclient");return}if(Dn.some(l=>d===l||d.endsWith(`.${l}`))){await n.abort("blockedbyclient");return}await n.continue()}})}async withTemporaryPage(t,n){if(!this.context||this.closing)throw new Error("Browser context is not available");return ft(this.context,a=>this.setupPage(a),t,n)}async navigateToSERP(t,n,a,s,i){if(!this.page)throw new Error("Browser page is not available");let d=new URLSearchParams({q:t,gl:a,hl:s,pws:"0"});return i?.tbs&&d.set("tbs",i.tbs),n&&d.set("uule",n),await this.page.goto(`https://www.google.com/search?${d}`,{waitUntil:"load",timeout:45e3}),{hasPaa:!!await this.page.waitForSelector(H.item,{timeout:8e3}).catch(()=>null)}}async navigateTo(t){if(!this.page)throw new Error("Browser page is not available");await this.page.goto(t,{waitUntil:"load",timeout:45e3})}async navigateToChannel(){throw new Error("YouTube navigation is not supported by the SERP browser driver")}async evaluate(t,n){if(!this.page)throw new Error("Browser page is not available");return this.page.evaluate(t,n)}getPage(){if(!this.page)throw new Error("Browser page is not available");return this.page}get\u004b\u0065\u0072\u006e\u0065\u006cSessionId(){return null}getProviderSessionMetadata(){return{provider:"\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api",providerSessionId:this.providerSessionId,disconnectObservation:this.disconnectObservation}}getDebugSnapshot(){return{\u006b\u0065\u0072\u006e\u0065\u006c:null,context:null,networkLocation:null,serpNavigation:null}}async close(){this.closing=!0;let t=null;try{await this.browser?.close()}catch(a){t=xe(a instanceof Error?a.message:String(a))??"\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 browser close failed",this.disconnectObservation??=zt("browser_close_error",t)}let n=He(this.getProviderSessionMetadata());return this.browser=null,this.context=null,this.page=null,this.cdpSession=null,{\u006b\u0065\u0072\u006e\u0065\u006cSessionId:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:!1,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:null,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:null,browserCloseSucceeded:t===null,browserCloseError:t,...n}}};function Ge(e,t){let n=!!(e?.serpIdentity||e?.\u006b\u0065\u0072\u006e\u0065\u006cProfileName);return t?.forceManaged===!0||Re()&&!n?new At:new It}var tt={austin:"Austin,Texas,United States","new york":"New York,New York,United States","new york city":"New York,New York,United States",nyc:"New York,New York,United States","los angeles":"Los Angeles,California,United States",la:"Los Angeles,California,United States",chicago:"Chicago,Illinois,United States",houston:"Houston,Texas,United States",phoenix:"Phoenix,Arizona,United States",philadelphia:"Philadelphia,Pennsylvania,United States",philly:"Philadelphia,Pennsylvania,United States","san antonio":"San Antonio,Texas,United States",dallas:"Dallas,Texas,United States",miami:"Miami,Florida,United States",seattle:"Seattle,Washington,United States",denver:"Denver,Colorado,United States",loveland:"Loveland,Colorado,United States","loveland co":"Loveland,Colorado,United States","fort collins":"Fort Collins,Colorado,United States",boulder:"Boulder,Colorado,United States","colorado springs":"Colorado Springs,Colorado,United States",boston:"Boston,Massachusetts,United States",atlanta:"Atlanta,Georgia,United States","san francisco":"San Francisco,California,United States",sf:"San Francisco,California,United States",portland:"Portland,Oregon,United States","las vegas":"Las Vegas,Nevada,United States",minneapolis:"Minneapolis,Minnesota,United States",detroit:"Detroit,Michigan,United States",nashville:"Nashville,Tennessee,United States",charlotte:"Charlotte,North Carolina,United States",orlando:"Orlando,Florida,United States","san diego":"San Diego,California,United States",baltimore:"Baltimore,Maryland,United States",sacramento:"Sacramento,California,United States",columbus:"Columbus,Ohio,United States",indianapolis:"Indianapolis,Indiana,United States","san jose":"San Jose,California,United States","fort worth":"Fort Worth,Texas,United States",jacksonville:"Jacksonville,Florida,United States",memphis:"Memphis,Tennessee,United States",louisville:"Louisville,Kentucky,United States",raleigh:"Raleigh,North Carolina,United States",richmond:"Richmond,Virginia,United States","salt lake city":"Salt Lake City,Utah,United States",toronto:"Toronto,Ontario,Canada",vancouver:"Vancouver,British Columbia,Canada",montreal:"Montreal,Quebec,Canada",calgary:"Calgary,Alberta,Canada",ottawa:"Ottawa,Ontario,Canada",london:"London,England,United Kingdom",manchester:"Manchester,England,United Kingdom",birmingham:"Birmingham,England,United Kingdom",edinburgh:"Edinburgh,Scotland,United Kingdom",glasgow:"Glasgow,Scotland,United Kingdom",leeds:"Leeds,England,United Kingdom",sydney:"Sydney,New South Wales,Australia",melbourne:"Melbourne,Victoria,Australia",brisbane:"Brisbane,Queensland,Australia",perth:"Perth,Western Australia,Australia",adelaide:"Adelaide,South Australia,Australia",dublin:"Dublin,Leinster,Ireland"};var De=`3, Nanjemoy,Maryland,United States
|
|
2
2
|
Aaronsburg,Pennsylvania,United States
|
|
3
3
|
Abbeville,Alabama,United States
|
|
4
4
|
Abbeville,Georgia,United States
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as N}from"./chunk-YQZGZBB4.js";import{b as L,c as P}from"./chunk-HE45FFBU.js";import{h as $,s as x}from"./chunk-
|
|
1
|
+
import{a as N}from"./chunk-YQZGZBB4.js";import{b as L,c as P}from"./chunk-HE45FFBU.js";import{h as $,s as x}from"./chunk-Z66Z2HV4.js";import{createWriteStream as Z,mkdirSync as ee,rmSync as te}from"fs";import{homedir as re}from"os";import{join as I,extname as k,basename as B}from"path";import{pipeline as ne}from"stream/promises";import{Readable as oe,Transform as ie}from"stream";var se=["doubleclick.net","googlesyndication.com","googletagmanager.com","google-analytics.com","googletagservices.com","adservice.google","googletag.","pagead2.googlesyndication","facebook.net/tr","connect.facebook.net","fbcdn.net/rsrc","analytics.twitter.com","static.ads-twitter.com","ads.twitter.com","t.co/i/adsct","pixel.advertising.com","hotjar.com","clarity.ms","quantserve.com","scorecardresearch.com","newrelic.com","nr-data.net","segment.io","segment.com","amplitude.com","mixpanel.com","heap.io","fullstory.com","moatads.com","criteo.com","adsrvr.org","rubiconproject.com","pubmatic.com","openx.net","appnexus.com","amazon-adsystem.com","media.net","yieldmo.com","triplelift.com","sharethrough.com","prebid.","smaato.net","indexworm.com","casalemedia.com","outbrain.com","taboola.com","revcontent.com","mgid.com","tawk.to","intercom.io","drift.com","hs-scripts.com","zopim.com","livechatinc.com","userlike.com","onetrust.com","cookielaw.org","cookieinformation.com","trustarc.com","/ads/","/ad/","/banner/","/banners/","/pixel/","/beacon/","/tracking/","/tracker/","/remarketing/","/conversion/","1x1.gif","spacer.gif","blank.gif","transparent.gif"],ae=new Set([".jpg",".jpeg",".png",".webp",".gif",".avif",".svg",".tiff"]),de=new Set([".mp4",".webm",".mov",".avi",".m4v",".ogv",".mkv"]),ce=new Set([".mp3",".wav",".ogg",".aac",".m4a",".flac",".opus"]);function le(e){let t=e.toLowerCase();return se.some(r=>t.includes(r))}function ue(e){return e.startsWith("data:")}function F(e){try{let t=k(new URL(e).pathname).toLowerCase();if(ae.has(t))return"image";if(de.has(t))return"video";if(ce.has(t))return"audio"}catch{}return null}function q(e){let t=e.toLowerCase();return t.startsWith("image/")?"image":t.startsWith("video/")?"video":t.startsWith("audio/")?"audio":null}function me(e,t){if(!e||ue(e))return null;try{return new URL(e,t).href}catch{return null}}function U(e,t){try{let r=new URL(e);return B(r.pathname).replace(/[^a-zA-Z0-9._-]/g,"_").slice(0,80)||`asset-${t}`}catch{return`asset-${t}`}}function O(e,t){let r=e?.replace(/&(?:amp|#0?38|#x26);/gi,"&").replace(/\s+/g," ").trim();return r?r.slice(0,t):null}function ge(e){let t=e.match(/[-_/](\d{2,5})x(\d{2,5})(?=[._/?#-]|$)/i);return t?{width:Number(t[1]),height:Number(t[2])}:null}function pe(e){try{let t=new URL(e);t.hash="",t.pathname=t.pathname.replace(/-(?:\d{2,5}x\d{2,5}|scaled|e\d{6,})(?=\.[a-z0-9]{2,6}$)/i,"");for(let r of["w","width","h","height","resize"])t.searchParams.delete(r);return t.searchParams.sort(),t.href}catch{return e}}function S(e){let t=(e.width??0)*(e.height??0),r=e.discoveryMethods.some(g=>g.includes("lightbox"))?1e12:0,n=/-(?:\d{2,5}x\d{2,5}|scaled|e\d{6,})(?=\.[a-z0-9]{2,6}(?:[?#]|$))/i.test(e.url)?0:1e11;return r+n+t}function A(e,t){let r=e.get(t.url);if(!r){e.set(t.url,t);return}r.discoveryMethods=[...new Set([...r.discoveryMethods,...t.discoveryMethods])],r.altTexts=[...new Set([...r.altTexts,...t.altTexts])],r.contexts=[...new Set([...r.contexts,...t.contexts])],!r.type&&t.type&&(r.type=t.type),(t.width??0)*(t.height??0)>(r.width??0)*(r.height??0)&&(r.width=t.width,r.height=t.height)}function he(e,t){let r=new Map,n=(d,i,o=null,h,l,u)=>{let s=d?me(d.trim().replace(/&/g,"&"),t):null;if(!s||le(s))return;let m=u??ge(s);A(r,{url:s,type:o??F(s),discoveryMethods:[i],altTexts:h?[h]:[],contexts:l?[l]:[],width:m?.width??null,height:m?.height??null})},g=(d,i,o,h)=>{for(let l of(d??"").split(",")){let[u,s]=l.trim().split(/\s+/);if(!u)continue;let m=s?.match(/^(\d+)w$/)?.[1];n(u,i,o,h,null,m?{width:Number(m),height:0}:null)}},a=(d,i="")=>{let o=d.$;for(let l of d.images){let u=l.attributes,s=O(l.alt,500),m=l.width&&l.height?{width:l.width,height:l.height}:null;for(let p of["src","data-src","data-lazy-src","data-original","data-bg","data-background","data-bg-url","data-lazy-bg","data-echo"]){let y=u[p];n(y,`static-${p}${i}`,"image",s,null,m)}g(u.srcset,`static-srcset${i}`,"image",s),g(u["data-srcset"],`static-data-srcset${i}`,"image",s)}o("source").each((l,u)=>{let s=o(u),m=s.attr("type")??"",p=m.startsWith("video/")?"video":m.startsWith("audio/")?"audio":"image";n(s.attr("src"),`static-source${i}`,p),g(s.attr("srcset"),`static-source-srcset${i}`,p)}),o("video,audio").each((l,u)=>{let s=o(u),m=u.tagName.toLowerCase();n(s.attr("src"),`static-${m}${i}`,m),m==="video"&&n(s.attr("poster"),`static-video-poster${i}`,"image")}),o("meta").each((l,u)=>{let s=o(u),m=(s.attr("property")??s.attr("name")??"").toLowerCase();(m==="og:image"||m==="og:image:url"||m==="twitter:image"||m==="twitter:image:src")&&n(s.attr("content"),`static-${m}${i}`,"image")}),o("link[href]").each((l,u)=>{let s=o(u);(s.attr("rel")??"").toLowerCase().split(/\s+/).some(p=>p==="icon"||p==="apple-touch-icon")&&n(s.attr("href"),`static-icon${i}`,"image")}),o("svg image").each((l,u)=>{let s=o(u);n(s.attr("href")??s.attr("xlink:href"),`static-svg-image${i}`,"image")}),o("a[href]").has("img").each((l,u)=>{let s=o(u),m=s.attr("href");if(m&&(/lightbox|gallery|fancybox|glightbox|swipebox|elementor-open-lightbox/i.test(`${s.attr("class")??""} ${s.attr("data-elementor-open-lightbox")??""}`)||/\.(?:avif|gif|jpe?g|png|svg|webp)(?:[?#]|$)/i.test(m))){let p=O(s.find("img").first().attr("alt"),500);n(m,`static-lightbox-target${i}`,"image",p)}});let h=o("style").toArray().map(l=>o(l).text());o("[style]").each((l,u)=>{h.push(o(u).attr("style")??"")});for(let l of h.join(`
|
|
2
2
|
`).matchAll(/(?:background(?:-image)?\s*:\s*)?url\(\s*(?:["']|"|�?34;|'|�?39;)?([^"')&]+)(?:["']|"|�?34;|'|�?39;)?\s*\)/gi))n(l[1],`static-css-url${i}`,"image");for(let l of d.sourceHtml.matchAll(/["'](https?:\/\/[^"'\s<>]+\.(?:avif|gif|jpe?g|png|svg|webp|mp4|webm|mp3|ogg)(?:\?[^"'\s<>]*)?)["']/gi))n(l[1],`static-bare-url${i}`)},c=typeof e=="string"?P(e):e;return a(c),c.$("script").each((d,i)=>{let o=c.$(i).text(),h=o.replace(/\\u003[cC]/g,"<").replace(/\\u003[eE]/g,">").replace(/\\u0026/gi,"&").replace(/\\["']/g,l=>l.slice(1)).replace(/\\\//g,"/");h!==o&&/<(?:img|source|video|audio)\b/i.test(h)&&a(P(h),"-json-unescaped")}),[...r.values()]}function fe(e,t,r=100){let n=new Map;for(let a of e)A(n,a);for(let a of t?.assets??[])A(n,{...a,type:a.type});let g=new Map;for(let a of n.values()){let c=pe(a.url),d=g.get(c)??[];d.push(a),g.set(c,d)}return[...g.values()].map(a=>{let c=[...a].sort((i,o)=>S(o)-S(i)||i.url.localeCompare(o.url)),d={...c[0]};return d.discoveryMethods=[...new Set(a.flatMap(i=>i.discoveryMethods))],d.altTexts=[...new Set(a.flatMap(i=>i.altTexts))],d.contexts=[...new Set(a.flatMap(i=>i.contexts))],{...d,variants:c.slice(1).map(i=>i.url)}}).sort((a,c)=>S(c)-S(a)||a.url.localeCompare(c.url)).slice(0,Math.max(1,r))}async function ye(e,t,r,n={}){let g=Math.max(1,Math.min(n.maxBytes??52428800,104857600)),a=e,c=null;for(let p=0;p<=5;p++){let y=await L(a,{field:"media URL"});if(y.error||!y.parsed)throw new Error(y.error??"Media URL was rejected");if(c=await fetch(y.parsed.href,{signal:AbortSignal.timeout(15e3),redirect:"manual"}),c.status>=300&&c.status<400){let w=c.headers.get("location");if(!w)throw new Error(`HTTP ${c.status} redirect did not include Location`);a=new URL(w,y.parsed.href).href,c=null;continue}break}if(!c)throw new Error("Media download exceeded five redirects");if(!c.ok)throw new Error(`HTTP ${c.status}`);if(!c.body)throw new Error("Empty response body");let d=c.headers.get("content-type")?.split(";")[0].trim()??null;if(n.expectedType&&(!d||q(d)!==n.expectedType))throw new Error(`Expected ${n.expectedType} content but received ${d??"no content-type"}`);let i=Number(c.headers.get("content-length")??0);if(Number.isFinite(i)&&i>g)throw new Error(`Media asset exceeds ${g} byte limit`);let o=I(t,r);if(d&&!k(r)){let y={"image/jpeg":".jpg","image/png":".png","image/webp":".webp","image/gif":".gif","image/svg+xml":".svg","image/avif":".avif","video/mp4":".mp4","video/webm":".webm","audio/mpeg":".mp3","audio/ogg":".ogg","audio/wav":".wav"}[d];y&&(o=o+y)}let h=Z(o);await new Promise((p,y)=>{h.once("open",()=>p()),h.once("error",y)});let l=0,u=new ie({transform(p,y,w){let _=p.length;if(l+_>g){w(new Error(`Media asset exceeds ${g} byte limit`));return}if(n.consumeBytes&&!n.consumeBytes(_)){w(new Error("Media export total byte limit exceeded"));return}l+=_,w(null,p)}});try{await ne(oe.fromWeb(c.body),u,h)}catch(p){throw h.destroy(),te(o,{force:!0}),p}let{statSync:s}=await import("fs"),m=s(o).size;return{savedPath:o,sizeBytes:m,mimeType:d}}async function Le(e,t,r={}){let n=r.types??["image","video","audio"],g=new Set(n),a=he(e,t),c=Math.max(1,Math.min(r.maxAssets??100,250)),d=fe(a,r.rendered,2e3),i=d.slice(0,c),o=new Set([...a.map(f=>f.url),...(r.rendered?.assets??[]).map(f=>f.url)]).size,h=i.flatMap(f=>{let b=f.type??F(f.url);return b&&g.has(b)?[{...f,type:b}]:[]}),l=o-h.length,u=d.length>c,s=r.rendered?.exhausted===!0&&!u,m=u?"asset_limit":r.rendered?.stopReason??"render_unavailable",p=u?[`Media discovery found ${d.length} responsive families; only the requested ${c} records were retained.`]:r.rendered?r.rendered.exhausted?[]:[`Rendered media discovery stopped with ${r.rendered.stopReason}; the inventory may be incomplete.`]:["Rendered media discovery was unavailable; this manifest contains static-source evidence only."],y={pageUrl:t,staticFound:a.length,renderedFound:r.rendered?.assets.length??0,filteredCount:l,totalFound:o,completeness:s?"complete":"partial",exhausted:s,stopReason:m,scrollRounds:r.rendered?.scrollRounds??0,warnings:p,artifact:null};if(r.outputDir===null)return{...y,outputDir:null,assets:h.map((f,b)=>({...f,mimeType:null,filename:U(f.url,b),savedPath:null,sizeBytes:null,sha256:null,downloadStatus:"not_attempted",downloadError:null,inlinePreview:null}))};let w=(()=>{try{return new URL(t).hostname.replace(/^www\./,"")}catch{return"unknown"}})(),_=new Date().toISOString().replace(/[:.]/g,"-").slice(0,19),C=r.outputDir??I(re(),"Downloads","mcp-scraper","media",`${_}-${w}`);ee(C,{recursive:!0});let T=[];return await Promise.allSettled(h.map(async(f,b)=>{let R=U(f.url,b);try{let{savedPath:v,sizeBytes:Q,mimeType:D}=await ye(f.url,C,R),G=D?q(D)??f.type:f.type;T.push({...f,type:G,mimeType:D,filename:B(v),savedPath:v,sizeBytes:Q,sha256:null,downloadStatus:"downloaded",downloadError:null,inlinePreview:null})}catch(v){T.push({...f,mimeType:null,filename:R,savedPath:null,sizeBytes:null,sha256:null,downloadStatus:"failed",downloadError:v instanceof Error?v.message:"media_download_failed",inlinePreview:null})}})),T.sort((f,b)=>f.savedPath&&!b.savedPath?-1:!f.savedPath&&b.savedPath?1:f.url.localeCompare(b.url)),{...y,outputDir:C,assets:T}}var be=new Set(["browser_navigation_blocked","browser_navigation_failed","browser_timeout","browser_session_failed","browser_result_missing"]);function we(e){return e instanceof Error?e.code:void 0}function _e(e){return e instanceof Error?e.message:String(e)}function H(e){let t=e?.match(/^browser_http_(\d+)$/);return t?Number(t[1]):null}function ve(e){return e===404?"page_not_found":e===403?"page_forbidden":e===429?"page_rate_limited":e>=500&&e<=599?"page_server_error":"page_http_error"}function xe(e){let t=_e(e),r=we(e);if(N(e,t))return{errorCode:"vendor_unavailable",httpStatus:null,retryable:!0};let n=H(r)??H(t.match(/^(browser_http_\d+)/)?.[1]);return n!=null?{errorCode:ve(n),httpStatus:n,retryable:n===429||n>=500}:r==="browser_challenge_unresolved"||/^browser_challenge_unresolved/.test(t)?{errorCode:"bot_check_unresolved",httpStatus:null,retryable:!0}:r==="browser_response_too_large"||/exceeds \d+ byte limit/i.test(t)?{errorCode:"page_too_large",httpStatus:null,retryable:!1}:/browser (?:has been )?closed|context closed|target page, context or browser has been closed|session closed/i.test(t)?{errorCode:"browser_session_interrupted",httpStatus:null,retryable:!0}:be.has(r??"")||/timeout|navigation_failed|ERR_/i.test(t)?{errorCode:"page_unreachable",httpStatus:null,retryable:!0}:{errorCode:"extraction_failed",httpStatus:null,retryable:!1}}function j(e,t){switch(e){case"page_not_found":return`The page could not be found (HTTP ${t??404}). It may have been moved or deleted.`;case"page_forbidden":return`The site refused the request (HTTP ${t??403}).`;case"page_rate_limited":return"The site is rate-limiting requests right now (HTTP 429). Retrying after a short wait usually works.";case"page_server_error":return`The page's own server returned an error (HTTP ${t}). This is on the target site's side, not something a retry here can fix.`;case"page_http_error":return`The page returned an unexpected HTTP ${t} response.`;case"bot_check_unresolved":return"This site has automated-traffic protection (a bot/CAPTCHA check) that could not be resolved in time. Some sites are simply not extractable this way.";case"page_too_large":return"The page is larger than we can safely process.";case"page_unreachable":return"The page did not respond in time, or the connection could not be completed.";case"browser_session_interrupted":return"The browser session closed before extraction completed. A retry uses a fresh browser session.";case"vendor_unavailable":return"MCP Scraper's internal browser services require MCP Scraper team attention. Servers or IPs are down until this is fixed \u2014 this is not caused by your request. Please retry in a few minutes.";case"extraction_failed":return"The page could not be extracted. Please retry, or contact support if this persists for the same URL."}}function Ie(e,t={}){let r=j(e.errorCode,e.httpStatus);return{...$({errorCode:e.errorCode,retryable:e.retryable,chargeStatus:t.chargeStatus,details:{...t.details??{},...e.httpStatus!=null?{http_status:e.httpStatus}:{}}}),message:r,error:r}}function ke(e){return e.httpStatus===404?404:e.httpStatus===403?403:e.httpStatus===429?429:e.httpStatus!=null&&e.httpStatus>=500&&e.httpStatus<=599?500:e.httpStatus!=null?502:e.errorCode==="vendor_unavailable"?503:502}var Ee="wayback_capture_missing";function Be(e,t){if(e==null)return{failureCode:null,failureReason:null};if(e===Ee)return{failureCode:e,failureReason:t??null};let r=new Error(t??e);r.code=e;let n=xe(r);return{failureCode:n.errorCode,failureReason:j(n.errorCode,n.httpStatus)}}import{neon as Te}from"@neondatabase/serverless";var Se="jina",M=null,z=!1;function W(){return(process.env.JINA_EMBED_MODEL??"jina-embeddings-v5-omni-small").trim()}function Y(){return Number((process.env.JINA_EMBED_DIM??"1024").trim())}function J(){return!!(process.env.JINA_API_KEY?.trim()&&process.env.MEMORY_DATABASE_URL?.trim())}function E(){if(M)return M;let e=process.env.MEMORY_DATABASE_URL?.trim();if(!e)throw new Error("MEMORY_DATABASE_URL is not set; Commons semantic search needs the shared Postgres.");return M=Te(e),M}async function K(){if(z)return;let e=Y();await E().query("CREATE EXTENSION IF NOT EXISTS vector"),await E().query(`
|
|
3
3
|
CREATE TABLE IF NOT EXISTS commons_index_vectors (
|
|
4
4
|
document_id TEXT PRIMARY KEY,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{Ab as R,Bb as E,Db as v,Lb as T,Nb as h,Ob as w,Pb as _,Qb as y,Rb as C,Va as g,Xa as S,w as u,x as f}from"./chunk-
|
|
1
|
+
import{Ab as R,Bb as E,Db as v,Lb as T,Nb as h,Ob as w,Pb as _,Qb as y,Rb as C,Va as g,Xa as S,w as u,x as f}from"./chunk-3MUEBDWY.js";import{a as P}from"./chunk-ZWZ6OWY6.js";import{a as m}from"./chunk-TW46NKVH.js";import{readFileSync as N}from"fs";import{homedir as I}from"os";import{join as A}from"path";import{serveStdio as b}from"@modelcontextprotocol/server/stdio";import{McpServer as k}from"@modelcontextprotocol/server";var x=new Map(w.map(r=>[r.upstreamName,r.id]));function O(r){let s=r.split(`
|
|
2
2
|
`).filter(o=>o.startsWith("data:")).map(o=>o.slice(5).trim()).filter(Boolean);if(!s.length)return JSON.parse(r);for(let o of s){let e=JSON.parse(o);if(e.result||e.error)return e}throw new Error("hosted MCP returned no JSON-RPC result")}function a(r){return{content:[{type:"text",text:JSON.stringify({ok:!1,error:r})}],isError:!0}}var c=class{baseUrl;apiKey;constructor(s,o){this.baseUrl=s.replace(/\/$/,""),this.apiKey=o}async callMemoryTool(s,o){let e=x.get(s);if(!e)return a(`unknown memory tool: ${s}`);try{let n=await fetch(`${this.baseUrl}/mcp`,{method:"POST",headers:{"content-type":"application/json",accept:"application/json, text/event-stream","x-api-key":this.apiKey},body:JSON.stringify({jsonrpc:"2.0",id:`memory:${e}`,method:"tools/call",params:{name:e,arguments:o}})}),l=await n.text();if(!n.ok)return a(`hosted memory ${e} failed (HTTP ${n.status})`);let t=O(l);return t.error?a(t.error.message??`hosted memory ${e} failed`):t.result??a(`hosted memory ${e} returned no result`)}catch(n){return a(n instanceof Error?n.message:`hosted memory ${e} call failed`)}}};function M(r,s){if(s.length===0)throw new Error("Restricted MCP tool allowlist must contain at least one tool name");let o=new Set;for(let t of s){if(typeof t!="string"||t.trim()!==t||t.length===0)throw new Error("Restricted MCP tool allowlist contains a malformed tool name");if(o.has(t))throw new Error(`Restricted MCP tool allowlist contains duplicate tool name: ${t}`);o.add(t)}let e=new Set,n=r,l=n.registerTool.bind(r);return n.registerTool=(t,i,p)=>{if(o.has(t))return e.add(t),l(t,i,p)},{assertComplete(){let t=[...o].filter(i=>!e.has(i));if(t.length>0)throw new Error(`Restricted MCP tool allowlist contains unknown or unavailable tool names: ${t.join(", ")}`)},registeredToolNames(){return[...e]}}}var L=new Set(["paa","serp","browser-agent","scheduled-results","memory"]);function $(){let s=[process.env.MCP_SCRAPER_KEY_PATH?.trim(),A(I(),".mcp-scraper-key")].filter(Boolean);for(let o of s)try{let e=N(o,"utf8").trim();if(e)return e}catch{}}function Y(r,s={}){let o=s.toolsets??L,e=process.env.MCP_SCRAPER_BASE_URL?.trim()||process.env.MCP_BASE_URL?.trim()||"https://mcpscraper.dev",n=g(),l=S({deploymentProfile:n,transportProfile:"stdio",baseUrl:e,explicitlyEnabled:process.env.MCP_SCRAPER_ALLOW_PRIVATE_NETWORK==="1"}),t=process.env.BROWSER_AGENT_CONSOLE_URL?.trim()||e,i=new k({name:"mcp-scraper",version:m},{instructions:u,cacheHints:{"server/discover":{ttlMs:3e5,cacheScope:"private"},"tools/list":{ttlMs:3e5,cacheScope:"private"},"prompts/list":{ttlMs:3e5,cacheScope:"private"},"resources/list":{ttlMs:3e5,cacheScope:"private"},"resources/templates/list":{ttlMs:3e5,cacheScope:"private"},"resources/read":{ttlMs:6e4,cacheScope:"private"}}});f(i);let p=s.allowedToolNames?M(i,s.allowedToolNames):void 0,d=s.httpExecutor??new T(e,r,{localNetworkAccess:l});return o.has("paa")&&v(i,d,{ownerId:R(r),deploymentProfile:n,transportProfile:"stdio",baseUrl:e,localNetworkAccess:l,taskHandleSecret:r}),o.has("serp")&&E(i,d,{exposeDevelopmentDiagnostics:n==="development"||n==="test"}),o.has("browser-agent")&&h(i,{baseUrl:e,apiKey:r,consoleBaseUrl:t}),o.has("scheduled-results")&&C(i,new y(e,r)),o.has("memory")&&_(i,new c(e,r)),p?.assertComplete(),i}function se(r={}){let s=process.argv.includes("--stdio")||process.env.MCP_SCRAPER_FORCE_STDIO==="1",o=!!(process.stdin.isTTY&&process.stdout.isTTY),e=process.argv.includes("--help")||process.argv.includes("-h");if(!s&&(o||e)){let l=process.argv.includes("--no-color")||process.env.NO_COLOR!==void 0||process.env.FORCE_COLOR==="0"||!process.stdout.isTTY;process.stdout.write(P({version:m,color:!l,apiKeyConfigured:!!process.env.MCP_SCRAPER_API_KEY?.trim()})),process.exit(0)}let n=(process.env.MCP_SCRAPER_API_KEY??process.env.MCP_SCRAPER_KEY??process.env.MCP_API_KEY??$())?.trim();n||(process.stderr.write(`MCP_SCRAPER_API_KEY env var or ~/.mcp-scraper-key is required
|
|
3
3
|
`),process.exit(1)),b(()=>Y(n,r),{legacy:"serve",onerror(l){process.stderr.write(`${l.message}
|
|
4
4
|
`)}})}export{se as a};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as _,i as c}from"./chunk-
|
|
1
|
+
import{g as _,i as c}from"./chunk-Z66Z2HV4.js";var g={\u006b\u0065\u0072\u006e\u0065\u006c:"browserRuntime"},a=/error|message/i,w=(new RegExp("(?:spending|billing|organization|account).{0,80}(?:cap|limit|blocked|disabled)|(?:quota|capacity).{0,40}(?:reached|exceeded)|https?:\\/\\/\\S*(?:dashboard|on\u006b\u0065\u0072\u006e\u0065\u006c)", "i")),E=/\b(?:ENOENT|ENOTDIR|EACCES|EPERM|EISDIR|EMFILE|ENFILE)\b|\b(?:mkdir|open|stat|lstat|readFile|writeFile)\s+['"]?(?:\/|[A-Za-z]:\\)|(?:^|[\s'"])(?:\/Users|\/home|\/tmp|\/var|\/private|\/opt|\/srv|\/root)\//i,k=new Set(["\u006b\u0065\u0072\u006e\u0065\u006c_session_id","browser_session_id","\u006b\u0065\u0072\u006e\u0065\u006cSessionId","browserSessionId","sessionId","\u006b\u0065\u0072\u006e\u0065\u006c_delete_started","session_cleanup_started","\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted","sessionCleanupStarted","\u006b\u0065\u0072\u006e\u0065\u006c_delete_succeeded","session_cleanup_succeeded","\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded","sessionCleanupSucceeded","\u006b\u0065\u0072\u006e\u0065\u006c_delete_error","session_cleanup_error","\u006b\u0065\u0072\u006e\u0065\u006cDeleteError","sessionCleanupError","\u006b\u0065\u0072\u006e\u0065\u006cProxyId","proxyId","requestedProxyIdSuffix","retrievedProxyIdSuffix","provider","providerName","service","serviceName","vendor","vendorName","organization","organizationId","accountId","browser_provider","provider_session_id","provider_session_observed_at","provider_lookup_status","provider_status","provider_error_code","provider_error_message","provider_reason_source","provider_duration_ms","provider_bandwidth_bytes","provider_captcha","provider_checked_at","provider_detail","provider_detail_json","provider_disconnect_observed","provider_disconnect_message","browserProvider","providerSessionId","providerLookupStatus","providerStatus","providerErrorCode","providerErrorMessage","providerReasonSource","providerDurationMs","providerBandwidthBytes","providerCaptcha","providerCheckedAt","providerDetail","providerDisconnectObserved","providerDisconnectMessage"]),S=new Set(["hosted_url","hostedUrl","live_view_url","liveViewUrl","cdp_ws_url","cdpWsUrl","browser_live_view_url"]),f=(new RegExp("\\b(?:wss?|https?):\\/\\/[^\\s\"'<>]*\\bon\u006b\u0065\u0072\u006e\u0065\u006c\\.com[^\\s\"'<>]*", "gi"));function b(e){return e.replace(f,"[browser-service]")}var R=new Set(["\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api","\u006b\u0065\u0072\u006e\u0065\u006c","local"]),m=new Set(["pending","complete","not_found","unavailable_credentials","temporary_error","invalid_payload","not_applicable"]),h=new Set(["active","running","complete","completed","failed","closed","stopped","terminated","timed_out"]),I=new Set(["provider_session_api","client_runtime","extractor","unknown"]),y=new Set(["browser_disconnected","worker_disconnect","job_killed","cdp_cmd_timeout","network_inactivity_timeout","session_timeout","client_timeout","navigate_domains_limit","cdp_error","browser_session_interrupted","provider_detail_pending","provider_lookup_unavailable","provider_reported_no_error","provider_session_not_found","provider_invalid_json","provider_invalid_payload","provider_lookup_timeout","provider_lookup_network_error","unknown"]),T=new Set(["browser_provider","provider_session_id","provider_lookup_status","provider_status","provider_error_code","provider_error_message","provider_reason_source","provider_duration_ms","provider_bandwidth_bytes","provider_captcha","provider_checked_at","provider_detail","provider_detail_json","provider_disconnect_observed","provider_disconnect_message"]),P=512,A=320;function t(e,r){return typeof e=="string"&&r.has(e)?e:null}function O(e){return typeof e!="string"?null:y.has(e)||/^provider_http_(?:429|5\d\d)$/.test(e)?e:null}function D(e){return typeof e!="string"||e.length<1||e.length>P||/^(?:authorization|bearer|password|secret|token|api[_-]?key|account)/i.test(e)?null:/^[A-Za-z0-9._:-]+$/.test(e)&&!e.includes("://")?e:null}function p(e){return typeof e=="number"&&Number.isSafeInteger(e)&&e>=0?e:null}function l(e){if(typeof e!="string"||e.length>40)return null;let r=Date.parse(e);return Number.isFinite(r)&&new Date(r).toISOString()===e?e:null}function u(e){if(typeof e!="string")return null;let r=e.replace(/[\u0000-\u001f\u007f]+/g," ").replace(/\s+/g," ").trim();if(!r||r.startsWith("{")||r.startsWith("["))return null;let o=r.replace(/\b(?:wss?|https?):\/\/\S+/gi,"[redacted endpoint]").replace(/\b(?:authorization|proxy-authorization)\s*:\s*(?:Bearer\s+)?\S+/gi,"[redacted credential]").replace(/\bBearer\s+\S+/gi,"[redacted credential]").replace(/\b(?:api[_-]?key|password|secret|token|account[_-]?id)\s*[=:]\s*[^\s,;]+/gi,"[redacted credential]").replace(/\b(?:account|organization)\s+(?:id\s+)?[A-Za-z0-9_-]{4,}/gi,"[redacted account]");return b(o).slice(0,A)}function v(e){return typeof e=="boolean"?e:null}function N(e){return{browser_provider:t(e.browser_provider,R),provider_session_id:D(e.provider_session_id),provider_session_observed_at:l(e.provider_session_observed_at),provider_lookup_status:t(e.provider_lookup_status,m),provider_status:t(e.provider_status,h),provider_error_code:O(e.provider_error_code),provider_error_message:u(e.provider_error_message),provider_reason_source:t(e.provider_reason_source,I),provider_duration_ms:p(e.provider_duration_ms),provider_bandwidth_bytes:p(e.provider_bandwidth_bytes),provider_captcha:v(e.provider_captcha),provider_checked_at:l(e.provider_checked_at),provider_disconnect_observed:v(e.provider_disconnect_observed),provider_disconnect_message:u(e.provider_disconnect_message)}}function i(e,r=""){if(typeof e=="string"){let o=b(e);return a.test(r)&&(w.test(e)||E.test(e))?o=_("service_unavailable"):a.test(r)&&(o=c(o)),o}if(Array.isArray(e))return e.map(o=>i(o,r));if(e!==null&&typeof e=="object"){let o={};for(let[n,d]of Object.entries(e)){if(k.has(n))continue;let s=g[n]??n;if(S.has(n)){o[s]=null;continue}o[s]=i(d,n)}return o}return e}function L(e){return e.map(r=>{if(r===null||typeof r!="object"||Array.isArray(r))return i(r);let o=r,n=i(o);return Object.keys(o).some(s=>T.has(s))?{...n,...N(o)}:n})}function C(e){let r=e?.diagnostics;return r?.debug?{...e,diagnostics:{...r,debug:i(r.debug)}}:e}export{i as a,L as b,C as c};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var o="0.89.2";export{o as a};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as j,b as T,c as P,d as C,f as S}from"./chunk-TMB56NCA.js";import{W as w}from"./chunk-MZN4U5BL.js";import{
|
|
1
|
+
import{a as j,b as T,c as P,d as C,f as S}from"./chunk-TMB56NCA.js";import{W as w}from"./chunk-MZN4U5BL.js";import{Bb as N,Kb as D,d as m,e as I,i as u,s}from"./chunk-Z66Z2HV4.js";import{createHash as W}from"crypto";import{gunzipSync as $,gzipSync as q}from"zlib";var y="site-extracts/",L=10080*60*1e3,H=900*1e3;function U(){return process.env.SITE_EXTRACT_ARTIFACT_READ_WRITE_TOKEN?.trim()||process.env.PRIVATE_ARTIFACT_READ_WRITE_TOKEN?.trim()||process.env.CONNECTED_DATA_READ_WRITE_TOKEN?.trim()||process.env.CONNECTED_DATA_BLOB_READ_WRITE_TOKEN?.trim()||null}function v(){return process.env.VERCEL==="1"||process.env.NODE_ENV==="production"}function p(){return{prefix:y,artifactTtlMs:L,downloadTtlMs:H,token:U()}}function h(t){return j(t,y)}async function V(t){let e=await P({policy:p(),ownerId:t.ownerId,artifactKey:`${t.jobId}.zip`,createdAt:t.createdAt,filename:`${t.jobId}-site-export.zip`,contentType:"application/zip",content:t.content});return{key:e.artifactId,url:e.downloadUrl??"",bytes:e.bytes,contentType:e.contentType,filename:e.filename,sha256:e.sha256,expiresAt:e.expiresAt,downloadUrlExpiresAt:e.downloadUrlExpiresAt,kind:"bundle"}}async function G(t){let e=await T({policy:p(),ownerId:t.ownerId,scopeSegments:[t.jobId,"images"],artifactKey:`${t.imageId}.bin`,createdAt:new Date,filename:t.filename,contentType:t.contentType,content:t.content});return{key:e.artifactId,url:e.downloadUrl??"",bytes:e.bytes,contentType:e.contentType,filename:e.filename,sha256:e.sha256,expiresAt:e.expiresAt,downloadUrlExpiresAt:e.downloadUrlExpiresAt,kind:"image",imageId:t.imageId,sourceUrl:t.sourceUrl,sourcePage:t.sourcePage}}async function O(t){return T({policy:p(),ownerId:t.ownerId,scopeSegments:[t.jobId,"content"],artifactKey:`${t.chunkKey}.json.gz`,createdAt:t.createdAt,filename:`${t.chunkKey}.json.gz`,contentType:"application/gzip",content:t.content})}async function Q(t){return C({policy:p(),artifactId:t.artifactId,ownerId:t.ownerId})}async function J(t){return S({policy:p(),artifactId:t,maxBytes:50*1024*1024})}async function Z(t){return h(t.artifactId)!==t.ownerId?null:J(t.artifactId)}async function k(t){return h(t.artifactId)!==t.ownerId?null:S({policy:p(),artifactId:t.artifactId,maxBytes:25*1024*1024})}async function tt(t){return h(t.artifactId)!==t.ownerId?null:S({policy:p(),artifactId:t.artifactId,maxBytes:10*1024*1024})}async function et(t={}){let e=t.now??new Date,n=U();if(!n)return{deleted:0,store:v()?"none":"local"};if(!t.force&&!(e.getUTCHours()===3&&e.getUTCMinutes()===21))return{deleted:0,store:"private-vercel-blob",skipped:!0};let r=e.getTime()-L,{list:i,del:a}=await import("@vercel/blob"),o,c=0;for(let d=0;d<20;d+=1){let l=await i({prefix:y,token:n,limit:1e3,cursor:o}),f=l.blobs.filter(A=>new Date(A.uploadedAt).getTime()<=r);if(f.length>0&&(await a(f.map(A=>A.pathname),{token:n}),c+=f.length),!l.hasMore||!l.cursor)break;o=l.cursor}return{deleted:c,store:"private-vercel-blob"}}var F=10,b=20*1024*1024;function E(t){return W("sha256").update(t).digest("hex")}function B(t){return!t.acquiredHtml||t.extractionStatus==="failed"?null:{pageId:t.pageId??E(t.archivedUrl??t.url),url:t.archivedUrl??t.url,html:t.acquiredHtml,mainHtml:t.mainHtml??"",markdown:t.bodyMarkdown,htmlSha256:t.htmlSha256??E(t.acquiredHtml),markdownSha256:t.markdownSha256??E(t.bodyMarkdown)}}function R(t){return Buffer.from(JSON.stringify({version:"site-extract-content.v1",pages:t}))}async function M(t){let e=t.pages.flatMap(o=>{let c=B(o);return c?[c]:[]}),n=new Map,r=[],i=0,a=async()=>{if(!r.length)return;let o=R(r);if(o.length>b)throw new Error(`site export content chunk exceeds ${b} bytes`);let c=E(r.map(l=>l.pageId).join("\0")).slice(0,16),d=await O({ownerId:t.ownerId,jobId:t.jobId,createdAt:t.createdAt,chunkKey:`content-${String(i).padStart(4,"0")}-${c}`,content:q(o,{level:6})});for(let l of r)n.set(l.url,{artifactId:d.artifactId,artifactSha256:d.sha256,pageId:l.pageId,uncompressedBytes:o.length});i++,r=[]};for(let o of e){let c=[...r,o];if(r.length>0&&(c.length>F||R(c).length>b)&&await a(),r.push(o),R(r).length>b)throw new Error(`page ${o.pageId} exceeds the durable content chunk limit`)}return await a(),n}function it(t){let e=new Map;return async n=>{let r=e.get(n.artifactId);if(!r){let a=await k({artifactId:n.artifactId,ownerId:t});if(!a)throw new Error("site export content chunk is missing or unauthorized");if(E(a)!==n.artifactSha256)throw new Error("site export content chunk checksum mismatch");let o=$(a);if(o.length>b)throw new Error("site export content chunk exceeds its read limit");if(r=JSON.parse(o.toString("utf8")),r.version!=="site-extract-content.v1"||!Array.isArray(r.pages))throw new Error("site export content chunk has an unsupported contract");for(e.set(n.artifactId,r);e.size>2;)e.delete(e.keys().next().value)}let i=r.pages.find(a=>a.pageId===n.pageId);if(!i)throw new Error("site export page is missing from its content chunk");if(E(i.html)!==i.htmlSha256||E(i.markdown)!==i.markdownSha256)throw new Error("site export page checksum mismatch");return i}}var g="xray_entitlement";function pt(t){let e=Math.max(1,Number(t.options.effectiveMaxPages??t.options.maxPages??1)),n=Math.max(e,Number(t.options.requestedMaxPages??e)),r=n>e;return{requestedMaxPages:n,effectiveMaxPages:e,creditLimited:r,creditTruncated:r&&t.totalUrls>=e}}function Et(t,e=!1){return t.successfulUrls===0?"failed":t.failedUrls>0||t.remainingUrls>0||e?"partial":"complete"}function _(t){let e=Number(t.total_urls??0),n=t.attempted_urls==null,r=Number(n?t.done_urls??0:t.attempted_urls),i=Number(n?t.done_urls??0:t.successful_urls??0),a=Number(t.failed_urls??Math.max(0,r-i));return{id:String(t.id),userId:t.user_id!=null?Number(t.user_id):null,idempotencyKey:t.idempotency_key!=null?String(t.idempotency_key):null,requestFingerprint:t.request_fingerprint!=null?String(t.request_fingerprint):null,status:t.status!=null?String(t.status):"pending",startUrl:String(t.start_url??""),options:t.options?JSON.parse(String(t.options)):{},totalUrls:e,doneUrls:r,attemptedUrls:r,successfulUrls:i,failedUrls:a,remainingUrls:Math.max(0,e-r),artifacts:t.artifacts?JSON.parse(String(t.artifacts)):null,error:t.error!=null?String(t.error):null,publicError:I(t.public_error_json),billedMc:t.billed_mc!=null?Number(t.billed_mc):null,createdAt:String(t.created_at??""),updatedAt:String(t.updated_at??"")}}async function mt(t,e,n,r){await s().execute({sql:`INSERT INTO site_extract_jobs (id, user_id, status, start_url, options, created_at, updated_at)
|
|
2
2
|
VALUES (?, ?, 'pending', ?, ?, datetime('now'), datetime('now'))`,args:[t,e,n,JSON.stringify(r)]})}async function K(t,e){let r=await s().execute({sql:"SELECT * FROM site_extract_jobs WHERE user_id = ? AND idempotency_key = ? LIMIT 1",args:[t,e]});return r.rows[0]?_(r.rows[0]):null}async function gt(t){let n=await s().execute({sql:`INSERT OR IGNORE INTO site_extract_jobs
|
|
3
3
|
(id, user_id, status, start_url, options, idempotency_key, request_fingerprint, created_at, updated_at)
|
|
4
4
|
VALUES (?, ?, 'pending', ?, ?, ?, ?, datetime('now'), datetime('now'))`,args:[t.jobId,t.userId,t.startUrl,JSON.stringify(t.options),t.idempotencyKey,t.requestFingerprint]}),r=await K(t.userId,t.idempotencyKey);if(!r)throw new Error("idempotent extract job was not persisted");return{job:r,created:n.rowsAffected===1,conflict:r.requestFingerprint!==t.requestFingerprint}}async function x(t){let n=await s().execute({sql:"SELECT * FROM site_extract_jobs WHERE id = ?",args:[t]});return n.rows[0]?_(n.rows[0]):null}async function _t(t){return(await s().execute({sql:"SELECT * FROM site_extract_jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50",args:[t]})).rows.map(r=>_(r))}async function xt(t=25){return(await s().execute({sql:`SELECT * FROM site_extract_jobs
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{M as p,s as o}from"./chunk-Z66Z2HV4.js";import{createHmac as T,timingSafeEqual as y}from"crypto";var N=()=>process.env.NODE_ENV==="production"||process.env.VERCEL==="1";function S(){let e=process.env.SESSION_SECRET?.trim();if(e)return e;if(N())throw new Error("SESSION_SECRET is not set \u2014 add it to your Vercel env vars (see src/api/env.ts)");return"dev-secret-change-me"}var v=()=>S();function m(e,t){if(e.length!==t.length)return!1;try{return y(Buffer.from(e,"hex"),Buffer.from(t,"hex"))}catch{return!1}}function L(e){let t=String(e),n=T("sha256",v()).update(t).digest("hex");return`${t}.${n}`}function I(e){let t=e.lastIndexOf(".");if(t===-1)return null;let n=e.slice(0,t),r=e.slice(t+1),i=T("sha256",v()).update(n).digest("hex");if(!m(r,i))return null;let s=parseInt(n);return isNaN(s)?null:s}import{randomUUID as _}from"crypto";function x(e,t,n){return e.lifecycleStatus==="connected"&&e.actionsEnabled&&t.includes(e.providerConfigKey)&&e.actionTools.includes(n)}var a=null,u=null;function c(){let e=o();return a&&u===e||(u=e,a=(async()=>{let t=e;await t.execute(`
|
|
2
2
|
CREATE TABLE IF NOT EXISTS service_connections (
|
|
3
3
|
id TEXT PRIMARY KEY,
|
|
4
4
|
user_id INTEGER NOT NULL REFERENCES users(id),
|