auto-post-marketplace-facebook/releases/auto-post-facebook-extensio.../assets/message.service-NYqpDB8M.js

2 lines
14 KiB
JavaScript

import{d as a,a as u}from"./app-C7VSS-q9.js";class f{base64ToFile(t,e,i){const n=t.includes(",")?t.split(",")[1]:t,o=atob(n),r=new ArrayBuffer(o.length),c=new Uint8Array(r);for(let d=0;d<o.length;d++)c[d]=o.charCodeAt(d);const l=new Blob([r],{type:i});return new File([l],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 r=0,c=!1;const l=()=>{const d=document.evaluate(c&&n?n:t,document,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;if(d instanceof HTMLElement){o(d);return}r++,r<e?setTimeout(l,i):!c&&n?(c=!0,r=0,setTimeout(l,i)):o(null)};l()})}async imageUrlToBase64(t){const i=await(await fetch(t)).blob();return new Promise((n,o)=>{const r=new FileReader;r.onloadend=()=>{typeof r.result=="string"?n(r.result.split(",")[1]):o("Không thể đọc dữ liệu ảnh")},r.onerror=o,r.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 r=new FileReader;r.onloadend=()=>e(r.result),r.onerror=i,r.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 r of o)if(r.innerText.trim().toLowerCase()===i.toLowerCase())return r;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 r of o)if(r.innerText.trim().toLowerCase().includes(i.toLowerCase()))return r;return null}findElInParent(t,e){return t&&t.parentElement?.querySelector(e)||null}waitForElement(t,e=100){return new Promise(i=>{const n=l=>l.offsetParent!==null&&(l.childElementCount>0||l.innerText.trim().length>0),o=()=>{const l=document.querySelector(t);l&&n(l)&&(r.disconnect(),clearInterval(c),i(l))},r=new MutationObserver(o);r.observe(document.body,{childList:!0,subtree:!0});const c=setInterval(o,e);o()})}}const s=new f;class g{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/div/span/div/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"]',collection_marketplace:'[aria-label="Collection of your Marketplace items"]'};findInputByTitle(t,e="input"){const i=s.findNestedElement(this.selectors.market_container,"span",t);if(!i)throw new Error("Not found input by title: "+t);return s.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 s.imageUrlToBase64(n);console.log("Base64:",n.slice(0,50)+"...");const r=s.base64ToFile(o,t.sku,s.getImageExtension(n)||"jpg");e.items.add(r)}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=s.findNestedElement(this.selectors.market_container,"span",e);s.scrollToElement(n),await a(500,600),n?.click(),await a(500,600);const o=s.findNestedElement(i,"span",t);if(await a(500,600),!o)throw new Error(`No child found with text "${t}"`);s.scrollToElement(o),await a(500,600),o.click(),await a(500,600)};chooseLocation=async t=>{const e=this.findInputByTitle("location");await s.writeToInput(t,e),await u(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}"`);s.scrollToElement(n),await u(400),s.clickByPoint(n)};writeTags=async t=>{const e=this.findInputByTitle("product tags","textarea");if(!e)throw new Error("Input is not found");s.scrollToElement(e),await u(500);for(const i of t)await s.writeToInput(i,e),await u(300),s.pressEnter(e)};clickNext=async()=>{const t=await s.getElementByXPath(this.selectors.next_btn);if(!t)throw new Error("Next button is not found");s.clickByPoint(t)};clickUpdate=async()=>{const t=await s.getElementByXPath(this.selectors.update_btn);if(!t)throw new Error("Next button is not found");s.clickByPoint(t)};clickPublist=async()=>{const t=await s.getElementByXPath(this.selectors.publish_btn);if(!t)throw new Error("Publist button is not found");s.clickByPoint(t)};handlePublist=async t=>{console.log({item:t}),await a(600,1e3),await this.uploadImages(t),await a(600,1e3);const e=this.findInputByTitle("title");s.writeToInput(t.title,e),await a(600,1e3);const i=this.findInputByTitle("price");if(s.writeToInput(String(t.price),i),await a(600,1e3),await this.chooseSelect(t.category,"category"),await a(600,1e3),await this.chooseSelect(t.condition,"condition",'[aria-label="Select an option"]'),t.brand){await a(600,1e3);const r=this.findInputByTitle("brand");await s.writeToInput(t.brand,r)}await a(600,1e3);const n=this.findInputByTitle("description","textarea");await s.writeToInput(t.description,n),await a(600,1e3),await this.writeTags(t.tags),await a(600,1e3);const o=this.findInputByTitle("sku");return await s.writeToInput(t.sku,o),t?.location&&(await a(600,1e3),await this.chooseLocation(t.location)),await a(300,500),await this.clickNext(),!0};handleRePublist=async t=>{console.log({item:t}),await s.waitForElement('[aria-label="Collection of your Marketplace items"]');const e=await this.getOptionEls(t);console.log({items:e}),this.clickItemInList(e,"edit"),await u(1e3),await this.waitForPageReady(this.editItem,this.selectors.market_container),await a(1e3,2e3),await this.clearImages(),await a(600,1e3),await this.uploadImages(t),await a(600,1e3);const i=this.findInputByTitle("title");s.writeToInput(t.title,i),await a(600,1e3);const n=this.findInputByTitle("price");s.writeToInput(String(t.price),n),await a(600,1e3),await this.chooseSelect(t.category,"category"),await a(600,1e3),await this.chooseSelect(t.condition,"condition",'[aria-label="Select an option"]'),await a(600,1e3);const o=this.findInputByTitle("description","textarea");return await s.writeToInput(t.description,o),await a(600,1e3),await this.writeTags(t.tags),await a(600,1e3),t?.location&&(await a(600,1e3),await this.chooseLocation(t.location)),!0};async getInfo(){try{const e=Date.now(),i=await new Promise(r=>{chrome.storage.local.get("meCache",c=>{r(c.meCache?JSON.parse(c.meCache):null)})});if(i&&e-i.timestamp<72e5)return i.data;const n=await fetch("/me",{credentials:"include"});if(!n.ok)throw new Error(`HTTP error! status: ${n.status}`);const o=await n.json();return chrome.storage.local.set({meCache:JSON.stringify({data:o,timestamp:e})}),o}catch(e){return console.error("Failed to get /me:",e),null}}getProducts=async()=>{const t=await s.getElementByXPath(this.selectors.products),e=await s.getElementByXPath(this.selectors.products_fallback);if(!t&&!e)throw new Error("List element has changed. Please connect to DEV");const i=[t,e].filter(Boolean);if(i.length===0)return[];const n=await this.getInfo();return console.log({info:n}),i.flatMap(o=>this.extractListings(o,n))};extractListings(t,e){return Array.from(t.children).map(n=>{const r=n.querySelector('span[dir="auto"], div[dir="auto"]')?.textContent?.trim()||"",c=document.querySelectorAll(`[aria-label="${r}"]`),l=Array.from(c).filter(p=>!p.querySelector("img"))[0],h=s.findNestedIcElement(l,"span","AU$")?.textContent?.match(/[\d,]+(?:\.\d+)?/),m=h?parseFloat(h[0].replace(/,/g,"")):0;return{title:r,price:m,el:t,url_info:e?.url}})}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}`);s.scrollToElement(e),e.click?.()}async getOptionEls(t){return this.clickOptionOfProduct(t),await u(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 u(1e3);const i=await s.getElementByXPath(this.selectors.option_btn,{xpathFallback:this.selectors.option_btn_fallback});console.log({confirmBtn:i}),i?.click(),(await s.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(),r=()=>{window.location.href.includes(t)?i():Date.now()-o>e?n(new Error("Timeout waiting for URL change")):setTimeout(r,500)};r()})}waitForPageReady(t,e,i=15e3){return new Promise((n,o)=>{const r=Date.now(),c=async()=>{window.location.href.includes(t)&&document.querySelector(e)?n():Date.now()-r>i?o(new Error("Timeout waiting for selling page ready")):setTimeout(c,500)};c()})}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 w.getProducts()};extractMarketplaceItemId(t){const e=t.match(/\/marketplace\/item\/(\d+)/);return e?e[1]:null}handleGetPublistID=async t=>{const e=await w.getProducts(),i=e.find(c=>c.title==t.title&&c.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"),r=this.extractMarketplaceItemId(o.href);return this.clickOptionOfProduct(t),r};async gotoPublist(){(await s.getElementByXPath(this.selectors.new_item_btn))?.click(),await a(400,800),(await s.getElementByXPath(this.selectors.item_for_sell))?.click()}async gotoSell(){document.querySelector('[href="/marketplace/you/selling/"]')?.click()}}const w=new g;class b{role;listeners;constructor(t){this.role=t,this.listeners=new Map,chrome.runtime.onMessage.addListener((e,i,n)=>{if(e?.type&&this.listeners.has(e.type))return this.listeners.get(e.type)(e.payload,i,n),!0})}on(t,e){this.listeners.set(t,e)}send(t,e,i){const n={from:this.role,to:t,type:e,payload:i};(this.role==="popup"||this.role==="content")&&chrome.runtime.sendMessage(n),this.role==="background"&&(t==="content"?chrome.tabs.query({active:!0,currentWindow:!0},o=>{o[0]?.id&&chrome.tabs.sendMessage(o[0].id,n,()=>{chrome.runtime.lastError&&console.warn("Không gửi được tới content script:",chrome.runtime.lastError.message)})}):t==="popup"&&chrome.runtime.sendMessage(n,()=>{chrome.runtime.lastError&&console.warn("Không gửi được tới popup:",chrome.runtime.lastError.message)}))}sendToTab(t,e,i){if(this.role!=="background")throw new Error("sendToTab chỉ được gọi từ background");const n={from:this.role,to:"content",type:e,payload:i};chrome.tabs.sendMessage(t,n,()=>{chrome.runtime.lastError&&console.warn(`Không gửi được tới content script ở tab ${t}:`,chrome.runtime.lastError.message)})}waitForMessage(t,e=3e4){return new Promise((i,n)=>{let o;const r=c=>{clearTimeout(o),this.off(t,r),i(c)};o=setTimeout(()=>{this.off(t,r),n(new Error(`Timeout khi chờ message: ${t}`))},e),this.on(t,r)})}off(t,e){this.listeners.get(t)===e&&this.listeners.delete(t)}}export{b as M,w as f,s as t};