2 lines
12 KiB
JavaScript
2 lines
12 KiB
JavaScript
import{a as s,d as v}from"./message.service-DcR3euAR.js";class f{base64ToFile(t,e,i){const n=t.includes(",")?t.split(",")[1]:t,o=atob(n),a=new ArrayBuffer(o.length),d=new Uint8Array(a);for(let l=0;l<o.length;l++)d[l]=o.charCodeAt(l);const c=new Blob([a],{type:i});return new File([c],e,{type:i})}clickByPoint(t){const e=t.getBoundingClientRect(),i=e.left+e.width/2,n=e.top+e.height/2,o=document.elementFromPoint(i,n);o&&o.dispatchEvent(new MouseEvent("click",{bubbles:!0,cancelable:!0,view:window}))}async getElementByXPath(t,{retryCount:e=2,delay:i=100,xpathFallback:n}={}){return new Promise(o=>{let a=0,d=!1;const c=()=>{const l=document.evaluate(d&&n?n:t,document,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;if(l instanceof HTMLElement){o(l);return}a++,a<e?setTimeout(c,i):!d&&n?(d=!0,a=0,setTimeout(c,i)):o(null)};c()})}async imageUrlToBase64(t){const i=await(await fetch(t)).blob();return new Promise((n,o)=>{const a=new FileReader;a.onloadend=()=>{typeof a.result=="string"?n(a.result.split(",")[1]):o("Không thể đọc dữ liệu ảnh")},a.onerror=o,a.readAsDataURL(i)})}getImageExtension(t){try{const i=new URL(t).pathname.match(/\.([a-zA-Z0-9]+)$/);return i?i[1].toLowerCase():null}catch{const n=t.split("?")[0].match(/\.([a-zA-Z0-9]+)$/);return n?n[1].toLowerCase():null}}imageLocalToBase64(t){return new Promise((e,i)=>{try{const n=chrome.runtime.getURL(`${t}`);fetch(n).then(o=>o.blob()).then(o=>{const a=new FileReader;a.onloadend=()=>e(a.result),a.onerror=i,a.readAsDataURL(o)}).catch(i)}catch(n){i(n)}})}scrollToElement(t,e="smooth"){t&&t.scrollIntoView({behavior:e,block:"center",inline:"nearest"})}getElementPointCoores(t){if(!t)return null;const e=t.getBoundingClientRect(),i=e.left+e.width/2,n=e.top+e.height/2;return{x:i,y:n}}setInputValue(t,e){t&&(t.value=e,t.dispatchEvent(new Event("input",{bubbles:!0})),t.dispatchEvent(new Event("change",{bubbles:!0})))}writeToInput=async(t,e)=>{let i;if(typeof e=="string"?i=await this.getElementByXPath(e):i=e,!i)throw new Error("Xpath is not found with value: "+t);this.scrollToElement(i),this.clickByPoint(i),this.setInputValue(i,t)};pressEnter(t){if(!t)throw new Error("Textarea not found:",t);t.focus(),["keydown","keypress","keyup"].forEach(e=>{t.dispatchEvent(new KeyboardEvent(e,{key:"Enter",code:"Enter",keyCode:13,which:13,bubbles:!0,cancelable:!0}))})}findNestedElement(t,e,i){const n=document.querySelector(t);if(!n)return null;const o=n.querySelectorAll(e);for(const a of o)if(a.innerText.trim().toLowerCase()===i.toLowerCase())return a;return null}findNestedIcElement(t,e,i){let n=null;if(typeof t=="string"){if(document.querySelector(t),!n)return null}else n=t;const o=n.querySelectorAll(e);for(const a of o)if(a.innerText.trim().toLowerCase().includes(i.toLowerCase()))return a;return null}findElInParent(t,e){return t&&t.parentElement?.querySelector(e)||null}waitForElement(t,e=100){return new Promise(i=>{const n=c=>c.offsetParent!==null&&(c.childElementCount>0||c.innerText.trim().length>0),o=()=>{const c=document.querySelector(t);c&&n(c)&&(a.disconnect(),clearInterval(d),i(c))},a=new MutationObserver(o);a.observe(document.body,{childList:!0,subtree:!0});const d=setInterval(o,e);o()})}}const r=new f;class m{sellingPath="https://www.facebook.com/marketplace/you/selling";marketPath="https://www.facebook.com/marketplace";createItem="https://www.facebook.com/marketplace/create/item";editItem="https://www.facebook.com/marketplace/edit";selectors={file__image_input:'input[type="file"]',next_btn:"/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[5]/div/div/div",update_btn:"/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[4]/div/div/div",publish_btn:"/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[4]/div[2]/div/div",products:"/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[2]/div/div/div[2]/div[1]/div/div[2]/div[2]/div",products_fallback:"/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[2]/div/div/div[2]/div[1]/div/div[3]/div/div/span/div[2]/div",option_btn:"/html/body/div[1]/div/div[1]/div/div[4]/div/div/div[1]/div/div[2]/div/div/div/div/div/div/div[3]/div/div/div/div/div[1]/div",option_btn_fallback:"/html/body/div[1]/div/div[1]/div/div[4]/div/div/div[1]/div/div[2]/div/div/div/div[3]/div[2]/div/div[2]/div[1]",close_btn_modal_feedback:"/html/body/div[1]/div/div[1]/div/div[4]/div/div/div[1]/div/div[2]/div/div/div/div[2]/div",images_container:"/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[2]/div[1]/div[2]/div/div/div[3]/div[2]/div",description_edit_input:"/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[9]/div/div/div[2]/div/div/div/label/div/div/textarea",sku_edit_input:"/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[9]/div/div/div[5]/div/div/div[1]/label/div/input",new_item_btn:"/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[7]/a/div",item_for_sell:"/html/body/div[1]/div/div[1]/div/div[5]/div/div/div[3]/div[2]/div[2]/div/div/div[2]/div[1]/div/span/div/div/div[1]/div/div",market_container:'[aria-label="Marketplace"]'};findInputByTitle(t,e="input"){const i=r.findNestedElement(this.selectors.market_container,"span",t);if(!i)throw new Error("Not found input by title: "+t);return r.findElInParent(i,e)}clearImages=async()=>{document.querySelectorAll('[aria-label="Remove"]').forEach(t=>t?.click())};uploadImages=async t=>{const e=new DataTransfer;for(const n of t.images){const o=await r.imageUrlToBase64(n);console.log("Base64:",n.slice(0,50)+"...");const a=r.base64ToFile(o,t.sku,r.getImageExtension(n)||"jpg");e.items.add(a)}const i=document.querySelector(this.selectors.file__image_input);i?(i.files=e.files,i.dispatchEvent(new Event("change",{bubbles:!0}))):console.error("Không tìm thấy input[type='file']")};chooseSelect=async(t,e,i='[aria-label="Dropdown menu"]')=>{const n=r.findNestedElement(this.selectors.market_container,"span",e);r.scrollToElement(n),await s(500,600),n?.click(),await s(500,600);const o=r.findNestedElement(i,"span",t);if(await s(500,600),!o)throw new Error(`No child found with text "${t}"`);r.scrollToElement(o),await s(500,600),o.click(),await s(500,600)};chooseLocation=async t=>{const e=this.findInputByTitle("location");await r.writeToInput(t,e),await v(600);const i=document.querySelector('[role="listbox"]')?.querySelectorAll("li")||[],n=Array.from(i).find(o=>o.innerHTML.trim().toLowerCase().includes(t.toLowerCase()));if(console.log(n),!n)throw new Error(`No child found with text "${t}"`);r.scrollToElement(n),await v(400),r.clickByPoint(n)};writeTags=async t=>{const e=this.findInputByTitle("product tags","textarea");if(!e)throw new Error("Input is not found");r.scrollToElement(e),await v(500);for(const i of t)await r.writeToInput(i,e),await v(300),r.pressEnter(e)};clickNext=async()=>{const t=await r.getElementByXPath(this.selectors.next_btn);if(!t)throw new Error("Next button is not found");r.clickByPoint(t)};clickUpdate=async()=>{const t=await r.getElementByXPath(this.selectors.update_btn);if(!t)throw new Error("Next button is not found");r.clickByPoint(t)};clickPublist=async()=>{const t=await r.getElementByXPath(this.selectors.publish_btn);if(!t)throw new Error("Publist button is not found");r.clickByPoint(t)};handlePublist=async t=>{console.log({item:t}),await s(600,1e3),await this.uploadImages(t),await s(600,1e3);const e=this.findInputByTitle("title");r.writeToInput(t.title,e),await s(600,1e3);const i=this.findInputByTitle("price");if(r.writeToInput(String(t.price),i),await s(600,1e3),await this.chooseSelect(t.category,"category"),await s(600,1e3),await this.chooseSelect(t.condition,"condition",'[aria-label="Select an option"]'),t.brand){await s(600,1e3);const a=this.findInputByTitle("brand");await r.writeToInput(t.brand,a)}await s(600,1e3);const n=this.findInputByTitle("description","textarea");await r.writeToInput(t.description,n),await s(600,1e3),await this.writeTags(t.tags),await s(600,1e3);const o=this.findInputByTitle("sku");return await r.writeToInput(t.sku,o),t?.location&&(await s(600,1e3),await this.chooseLocation(t.location)),await s(300,500),await this.clickNext(),!0};handleRePublist=async t=>{console.log({item:t}),await r.waitForElement('[aria-label="Collection of your Marketplace items"]');const e=await this.getOptionEls(t);console.log({items:e}),this.clickItemInList(e,"edit"),await v(1e3),await this.waitForPageReady(this.editItem,this.selectors.market_container),await s(1e3,2e3),await this.clearImages(),await s(600,1e3),await this.uploadImages(t),await s(600,1e3);const i=this.findInputByTitle("title");r.writeToInput(t.title,i),await s(600,1e3);const n=this.findInputByTitle("price");r.writeToInput(String(t.price),n),await s(600,1e3),await this.chooseSelect(t.category,"category"),await s(600,1e3),await this.chooseSelect(t.condition,"condition",'[aria-label="Select an option"]'),await s(600,1e3);const o=this.findInputByTitle("description","textarea");return await r.writeToInput(t.description,o),await s(600,1e3),await this.writeTags(t.tags),await s(600,1e3),t?.location&&(await s(600,1e3),await this.chooseLocation(t.location)),!0};getProducts=async()=>{const t=await r.getElementByXPath(this.selectors.products),e=await r.getElementByXPath(this.selectors.products_fallback);console.log({products1:t,products2:e});const i=[t,e].filter(Boolean);return i.length===0?[]:i.flatMap(n=>this.extractListings(n))};extractListings(t){return Array.from(t.children).map(i=>{const o=i.querySelector('span[dir="auto"], div[dir="auto"]')?.textContent?.trim()||"",a=document.querySelectorAll(`[aria-label="${o}"]`),d=Array.from(a).filter(p=>!p.querySelector("img"))[0],l=r.findNestedIcElement(d,"span","AU$")?.textContent?.match(/[\d,]+(?:\.\d+)?/),w=l?parseFloat(l[0].replace(/,/g,"")):0;return{title:o,price:w,el:t}})}closeTab=async t=>{chrome.runtime.sendMessage({type:"close-tab",payload:t})};clickOptionOfProduct(t){const e=document.querySelector(`[aria-label="More options for ${t.title}"]`);if(!e)throw new Error(`Not found option buttin in product ${`[aria-label="More options for ${t.title}"]`}, ID: ${t.id}`);r.scrollToElement(e),e.click?.()}async getOptionEls(t){return this.clickOptionOfProduct(t),await v(2e3),Array.from(document.querySelectorAll('[role="menuitem"]'))}clickItemInList(t,e){const i=t.find(n=>n.textContent.toLocaleLowerCase().includes(e));if(!i)throw new Error(`Not found item ${e} in options list`);i.click?.()}getItemInList(t,e){const i=t.find(n=>n.textContent.toLocaleLowerCase().includes(e));if(!i)throw new Error(`Not found item ${e} in options list`);return i}handleDelete=async t=>{const e=await this.getOptionEls(t);console.log({items:e}),this.clickItemInList(e,"delete"),await v(1e3);const i=await r.getElementByXPath(this.selectors.option_btn,{xpathFallback:this.selectors.option_btn_fallback});console.log({confirmBtn:i}),i?.click(),(await r.getElementByXPath(this.selectors.close_btn_modal_feedback))?.click(),chrome.runtime.sendMessage({type:"delete-done"})};waitForUrlContains(t,e=1e4){return new Promise((i,n)=>{const o=Date.now(),a=()=>{window.location.href.includes(t)?i():Date.now()-o>e?n(new Error("Timeout waiting for URL change")):setTimeout(a,500)};a()})}waitForPageReady(t,e,i=15e3){return new Promise((n,o)=>{const a=Date.now(),d=async()=>{window.location.href.includes(t)&&document.querySelector(e)?n():Date.now()-a>i?o(new Error("Timeout waiting for selling page ready")):setTimeout(d,500)};d()})}syncListing=async()=>{window.location.href.includes(this.sellingPath)||(document.querySelector('a[href="/marketplace/you/selling/"]')?.click?.(),await this.waitForPageReady(this.sellingPath,this.selectors.products)),await u.getProducts()};extractMarketplaceItemId(t){const e=t.match(/\/marketplace\/item\/(\d+)/);return e?e[1]:null}handleGetPublistID=async t=>{const e=await u.getProducts(),i=e.find(d=>d.title==t.title&&d.price==t.price);if(console.log({payload:t,product:i,products:e}),!i)return;i.el;const n=await this.getOptionEls(t),o=this.getItemInList(n,"view listing"),a=this.extractMarketplaceItemId(o.href);return this.clickOptionOfProduct(t),a};async gotoPublist(){(await r.getElementByXPath(this.selectors.new_item_btn))?.click(),await s(400,800),(await r.getElementByXPath(this.selectors.item_for_sell))?.click()}async gotoSell(){document.querySelector('[href="/marketplace/you/selling/"]')?.click()}}const u=new m;export{u as f,r as t};
|