diff --git a/auto-listing-facebook-marketplace/auto-listing-facebook-marketplace/content.js b/auto-listing-facebook-marketplace/auto-listing-facebook-marketplace/content.js index ea71c74..270be5c 100644 --- a/auto-listing-facebook-marketplace/auto-listing-facebook-marketplace/content.js +++ b/auto-listing-facebook-marketplace/auto-listing-facebook-marketplace/content.js @@ -3,4 +3,4 @@ function S(e){return new Promise(t=>setTimeout(t,e))}function Ne(e,t){return fun `)}getSetCookie(){return this.get("set-cookie")||[]}get[Symbol.toStringTag](){return"AxiosHeaders"}static from(t){return t instanceof this?t:new this(t)}static concat(t,...n){const r=new this(t);return n.forEach(i=>r.set(i)),r}static accessor(t){const r=(this[Ee]=this[Ee]={accessors:{}}).accessors,i=this.prototype;function s(o){const c=q(o);r[c]||(ln(i,o),r[c]=!0)}return a.isArray(t)?t.forEach(s):s(t),this}};C.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]);a.reduceDescriptors(C.prototype,({value:e},t)=>{let n=t[0].toUpperCase()+t.slice(1);return{get:()=>e,set(r){this[n]=r}}});a.freezeMethods(C);function ie(e,t){const n=this||$,r=t||n,i=C.from(r.headers);let s=r.data;return a.forEach(e,function(c){s=c.call(n,s,i.normalize(),t?t.status:void 0)}),i.normalize(),s}function Ve(e){return!!(e&&e.__CANCEL__)}function I(e,t,n){m.call(this,e??"canceled",m.ERR_CANCELED,t,n),this.name="CanceledError"}a.inherits(I,m,{__CANCEL__:!0});function Ke(e,t,n){const r=n.config.validateStatus;!n.status||!r||r(n.status)?e(n):t(new m("Request failed with status code "+n.status,[m.ERR_BAD_REQUEST,m.ERR_BAD_RESPONSE][Math.floor(n.status/100)-4],n.config,n.request,n))}function dn(e){const t=/^([-+\w]{1,25})(:?\/\/|:)/.exec(e);return t&&t[1]||""}function un(e,t){e=e||10;const n=new Array(e),r=new Array(e);let i=0,s=0,o;return t=t!==void 0?t:1e3,function(u){const l=Date.now(),d=r[s];o||(o=l),n[i]=u,r[i]=l;let p=s,w=0;for(;p!==i;)w+=n[p++],p=p%e;if(i=(i+1)%e,i===s&&(s=(s+1)%e),l-o{n=d,i=null,s&&(clearTimeout(s),s=null),e.apply(null,l)};return[(...l)=>{const d=Date.now(),p=d-n;p>=r?o(l,d):(i=l,s||(s=setTimeout(()=>{s=null,o(i)},r-p)))},()=>i&&o(i)]}const W=(e,t,n=3)=>{let r=0;const i=un(50,250);return fn(s=>{const o=s.loaded,c=s.lengthComputable?s.total:void 0,u=o-r,l=i(u),d=o<=c;r=o;const p={loaded:o,total:c,progress:c?o/c:void 0,bytes:u,rate:l||void 0,estimated:l&&c&&d?(c-o)/l:void 0,event:s,lengthComputable:c!=null,[t?"download":"upload"]:!0};e(p)},n)},ge=(e,t)=>{const n=e!=null;return[r=>t[0]({lengthComputable:n,total:e,loaded:r}),t[1]]},Re=e=>(...t)=>a.asap(()=>e(...t)),pn=O.hasStandardBrowserEnv?((e,t)=>n=>(n=new URL(n,O.origin),e.protocol===n.protocol&&e.host===n.host&&(t||e.port===n.port)))(new URL(O.origin),O.navigator&&/(msie|trident)/i.test(O.navigator.userAgent)):()=>!0,hn=O.hasStandardBrowserEnv?{write(e,t,n,r,i,s){const o=[e+"="+encodeURIComponent(t)];a.isNumber(n)&&o.push("expires="+new Date(n).toGMTString()),a.isString(r)&&o.push("path="+r),a.isString(i)&&o.push("domain="+i),s===!0&&o.push("secure"),document.cookie=o.join("; ")},read(e){const t=document.cookie.match(new RegExp("(^|;\\s*)("+e+")=([^;]*)"));return t?decodeURIComponent(t[3]):null},remove(e){this.write(e,"",Date.now()-864e5)}}:{write(){},read(){return null},remove(){}};function mn(e){return/^([a-z][a-z\d+\-.]*:)?\/\//i.test(e)}function vn(e,t){return t?e.replace(/\/?\/$/,"")+"/"+t.replace(/^\/+/,""):e}function We(e,t,n){let r=!mn(t);return e&&(r||n==!1)?vn(e,t):t}const Se=e=>e instanceof C?{...e}:e;function D(e,t){t=t||{};const n={};function r(l,d,p,w){return a.isPlainObject(l)&&a.isPlainObject(d)?a.merge.call({caseless:w},l,d):a.isPlainObject(d)?a.merge({},d):a.isArray(d)?d.slice():d}function i(l,d,p,w){if(a.isUndefined(d)){if(!a.isUndefined(l))return r(void 0,l,p,w)}else return r(l,d,p,w)}function s(l,d){if(!a.isUndefined(d))return r(void 0,d)}function o(l,d){if(a.isUndefined(d)){if(!a.isUndefined(l))return r(void 0,l)}else return r(void 0,d)}function c(l,d,p){if(p in t)return r(l,d);if(p in e)return r(void 0,l)}const u={url:s,method:s,data:s,baseURL:o,transformRequest:o,transformResponse:o,paramsSerializer:o,timeout:o,timeoutMessage:o,withCredentials:o,withXSRFToken:o,adapter:o,responseType:o,xsrfCookieName:o,xsrfHeaderName:o,onUploadProgress:o,onDownloadProgress:o,decompress:o,maxContentLength:o,maxBodyLength:o,beforeRedirect:o,transport:o,httpAgent:o,httpsAgent:o,cancelToken:o,socketPath:o,responseEncoding:o,validateStatus:c,headers:(l,d,p)=>i(Se(l),Se(d),p,!0)};return a.forEach(Object.keys(Object.assign({},e,t)),function(d){const p=u[d]||i,w=p(e[d],t[d],d);a.isUndefined(w)&&p!==c||(n[d]=w)}),n}const Xe=e=>{const t=D({},e);let{data:n,withXSRFToken:r,xsrfHeaderName:i,xsrfCookieName:s,headers:o,auth:c}=t;t.headers=o=C.from(o),t.url=$e(We(t.baseURL,t.url,t.allowAbsoluteUrls),e.params,e.paramsSerializer),c&&o.set("Authorization","Basic "+btoa((c.username||"")+":"+(c.password?unescape(encodeURIComponent(c.password)):"")));let u;if(a.isFormData(n)){if(O.hasStandardBrowserEnv||O.hasStandardBrowserWebWorkerEnv)o.setContentType(void 0);else if((u=o.getContentType())!==!1){const[l,...d]=u?u.split(";").map(p=>p.trim()).filter(Boolean):[];o.setContentType([l||"multipart/form-data",...d].join("; "))}}if(O.hasStandardBrowserEnv&&(r&&a.isFunction(r)&&(r=r(t)),r||r!==!1&&pn(t.url))){const l=i&&s&&hn.read(s);l&&o.set(i,l)}return t},wn=typeof XMLHttpRequest<"u",yn=wn&&function(e){return new Promise(function(n,r){const i=Xe(e);let s=i.data;const o=C.from(i.headers).normalize();let{responseType:c,onUploadProgress:u,onDownloadProgress:l}=i,d,p,w,g,f;function v(){g&&g(),f&&f(),i.cancelToken&&i.cancelToken.unsubscribe(d),i.signal&&i.signal.removeEventListener("abort",d)}let h=new XMLHttpRequest;h.open(i.method.toUpperCase(),i.url,!0),h.timeout=i.timeout;function b(){if(!h)return;const T=C.from("getAllResponseHeaders"in h&&h.getAllResponseHeaders()),A={data:!c||c==="text"||c==="json"?h.responseText:h.response,status:h.status,statusText:h.statusText,headers:T,config:e,request:h};Ke(function(F){n(F),v()},function(F){r(F),v()},A),h=null}"onloadend"in h?h.onloadend=b:h.onreadystatechange=function(){!h||h.readyState!==4||h.status===0&&!(h.responseURL&&h.responseURL.indexOf("file:")===0)||setTimeout(b)},h.onabort=function(){h&&(r(new m("Request aborted",m.ECONNABORTED,e,h)),h=null)},h.onerror=function(){r(new m("Network Error",m.ERR_NETWORK,e,h)),h=null},h.ontimeout=function(){let L=i.timeout?"timeout of "+i.timeout+"ms exceeded":"timeout exceeded";const A=i.transitional||ze;i.timeoutErrorMessage&&(L=i.timeoutErrorMessage),r(new m(L,A.clarifyTimeoutError?m.ETIMEDOUT:m.ECONNABORTED,e,h)),h=null},s===void 0&&o.setContentType(null),"setRequestHeader"in h&&a.forEach(o.toJSON(),function(L,A){h.setRequestHeader(A,L)}),a.isUndefined(i.withCredentials)||(h.withCredentials=!!i.withCredentials),c&&c!=="json"&&(h.responseType=i.responseType),l&&([w,f]=W(l,!0),h.addEventListener("progress",w)),u&&h.upload&&([p,g]=W(u),h.upload.addEventListener("progress",p),h.upload.addEventListener("loadend",g)),(i.cancelToken||i.signal)&&(d=T=>{h&&(r(!T||T.type?new I(null,e,h):T),h.abort(),h=null)},i.cancelToken&&i.cancelToken.subscribe(d),i.signal&&(i.signal.aborted?d():i.signal.addEventListener("abort",d)));const R=dn(i.url);if(R&&O.protocols.indexOf(R)===-1){r(new m("Unsupported protocol "+R+":",m.ERR_BAD_REQUEST,e));return}h.send(s||null)})},bn=(e,t)=>{const{length:n}=e=e?e.filter(Boolean):[];if(t||n){let r=new AbortController,i;const s=function(l){if(!i){i=!0,c();const d=l instanceof Error?l:this.reason;r.abort(d instanceof m?d:new I(d instanceof Error?d.message:d))}};let o=t&&setTimeout(()=>{o=null,s(new m(`timeout ${t} of ms exceeded`,m.ETIMEDOUT))},t);const c=()=>{e&&(o&&clearTimeout(o),o=null,e.forEach(l=>{l.unsubscribe?l.unsubscribe(s):l.removeEventListener("abort",s)}),e=null)};e.forEach(l=>l.addEventListener("abort",s));const{signal:u}=r;return u.unsubscribe=()=>a.asap(c),u}},En=function*(e,t){let n=e.byteLength;if(n{const i=gn(e,t);let s=0,o,c=u=>{o||(o=!0,r&&r(u))};return new ReadableStream({async pull(u){try{const{done:l,value:d}=await i.next();if(l){c(),u.close();return}let p=d.byteLength;if(n){let w=s+=p;n(w)}u.enqueue(new Uint8Array(d))}catch(l){throw c(l),l}},cancel(u){return c(u),i.return()}},{highWaterMark:2})},te=typeof fetch=="function"&&typeof Request=="function"&&typeof Response=="function",Ge=te&&typeof ReadableStream=="function",Sn=te&&(typeof TextEncoder=="function"?(e=>t=>e.encode(t))(new TextEncoder):async e=>new Uint8Array(await new Response(e).arrayBuffer())),Ze=(e,...t)=>{try{return!!e(...t)}catch{return!1}},Tn=Ge&&Ze(()=>{let e=!1;const t=new Request(O.origin,{body:new ReadableStream,method:"POST",get duplex(){return e=!0,"half"}}).headers.has("Content-Type");return e&&!t}),Oe=64*1024,le=Ge&&Ze(()=>a.isReadableStream(new Response("").body)),X={stream:le&&(e=>e.body)};te&&(e=>{["text","arrayBuffer","blob","formData","stream"].forEach(t=>{!X[t]&&(X[t]=a.isFunction(e[t])?n=>n[t]():(n,r)=>{throw new m(`Response type '${t}' is not supported`,m.ERR_NOT_SUPPORT,r)})})})(new Response);const On=async e=>{if(e==null)return 0;if(a.isBlob(e))return e.size;if(a.isSpecCompliantForm(e))return(await new Request(O.origin,{method:"POST",body:e}).arrayBuffer()).byteLength;if(a.isArrayBufferView(e)||a.isArrayBuffer(e))return e.byteLength;if(a.isURLSearchParams(e)&&(e=e+""),a.isString(e))return(await Sn(e)).byteLength},An=async(e,t)=>{const n=a.toFiniteNumber(e.getContentLength());return n??On(t)},xn=te&&(async e=>{let{url:t,method:n,data:r,signal:i,cancelToken:s,timeout:o,onDownloadProgress:c,onUploadProgress:u,responseType:l,headers:d,withCredentials:p="same-origin",fetchOptions:w}=Xe(e);l=l?(l+"").toLowerCase():"text";let g=bn([i,s&&s.toAbortSignal()],o),f;const v=g&&g.unsubscribe&&(()=>{g.unsubscribe()});let h;try{if(u&&Tn&&n!=="get"&&n!=="head"&&(h=await An(d,r))!==0){let A=new Request(t,{method:"POST",body:r,duplex:"half"}),B;if(a.isFormData(r)&&(B=A.headers.get("content-type"))&&d.setContentType(B),A.body){const[F,z]=ge(h,W(Re(u)));r=Te(A.body,Oe,F,z)}}a.isString(p)||(p=p?"include":"omit");const b="credentials"in Request.prototype;f=new Request(t,{...w,signal:g,method:n.toUpperCase(),headers:d.normalize().toJSON(),body:r,duplex:"half",credentials:b?p:void 0});let R=await fetch(f,w);const T=le&&(l==="stream"||l==="response");if(le&&(c||T&&v)){const A={};["status","statusText","headers"].forEach(me=>{A[me]=R[me]});const B=a.toFiniteNumber(R.headers.get("content-length")),[F,z]=c&&ge(B,W(Re(c),!0))||[];R=new Response(Te(R.body,Oe,F,()=>{z&&z(),v&&v()}),A)}l=l||"text";let L=await X[a.findKey(X,l)||"text"](R,e);return!T&&v&&v(),await new Promise((A,B)=>{Ke(A,B,{data:L,headers:C.from(R.headers),status:R.status,statusText:R.statusText,config:e,request:f})})}catch(b){throw v&&v(),b&&b.name==="TypeError"&&/Load failed|fetch/i.test(b.message)?Object.assign(new m("Network Error",m.ERR_NETWORK,e,f),{cause:b.cause||b}):m.from(b,b&&b.code,e,f)}}),de={http:Mt,xhr:yn,fetch:xn};a.forEach(de,(e,t)=>{if(e){try{Object.defineProperty(e,"name",{value:t})}catch{}Object.defineProperty(e,"adapterName",{value:t})}});const Ae=e=>`- ${e}`,Cn=e=>a.isFunction(e)||e===null||e===!1,Qe={getAdapter:e=>{e=a.isArray(e)?e:[e];const{length:t}=e;let n,r;const i={};for(let s=0;s`adapter ${c} `+(u===!1?"is not supported by the environment":"is not available in the build"));let o=t?s.length>1?`since : `+s.map(Ae).join(` `):" "+Ae(s[0]):"as no adapter specified";throw new m("There is no suitable adapter to dispatch the request "+o,"ERR_NOT_SUPPORT")}return r},adapters:de};function se(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw new I(null,e)}function xe(e){return se(e),e.headers=C.from(e.headers),e.data=ie.call(e,e.transformRequest),["post","put","patch"].indexOf(e.method)!==-1&&e.headers.setContentType("application/x-www-form-urlencoded",!1),Qe.getAdapter(e.adapter||$.adapter)(e).then(function(r){return se(e),r.data=ie.call(e,e.transformResponse,r),r.headers=C.from(r.headers),r},function(r){return Ve(r)||(se(e),r&&r.response&&(r.response.data=ie.call(e,e.transformResponse,r.response),r.response.headers=C.from(r.response.headers))),Promise.reject(r)})}const Ye="1.10.0",ne={};["object","boolean","number","function","string","symbol"].forEach((e,t)=>{ne[e]=function(r){return typeof r===e||"a"+(t<1?"n ":" ")+e}});const Ce={};ne.transitional=function(t,n,r){function i(s,o){return"[Axios v"+Ye+"] Transitional option '"+s+"'"+o+(r?". "+r:"")}return(s,o,c)=>{if(t===!1)throw new m(i(o," has been removed"+(n?" in "+n:"")),m.ERR_DEPRECATED);return n&&!Ce[o]&&(Ce[o]=!0,console.warn(i(o," has been deprecated since v"+n+" and will be removed in the near future"))),t?t(s,o,c):!0}};ne.spelling=function(t){return(n,r)=>(console.warn(`${r} is likely a misspelling of ${t}`),!0)};function Pn(e,t,n){if(typeof e!="object")throw new m("options must be an object",m.ERR_BAD_OPTION_VALUE);const r=Object.keys(e);let i=r.length;for(;i-- >0;){const s=r[i],o=t[s];if(o){const c=e[s],u=c===void 0||o(c,s,e);if(u!==!0)throw new m("option "+s+" must be "+u,m.ERR_BAD_OPTION_VALUE);continue}if(n!==!0)throw new m("Unknown option "+s,m.ERR_BAD_OPTION)}}const K={assertOptions:Pn,validators:ne},N=K.validators;let U=class{constructor(t){this.defaults=t||{},this.interceptors={request:new be,response:new be}}async request(t,n){try{return await this._request(t,n)}catch(r){if(r instanceof Error){let i={};Error.captureStackTrace?Error.captureStackTrace(i):i=new Error;const s=i.stack?i.stack.replace(/^.+\n/,""):"";try{r.stack?s&&!String(r.stack).endsWith(s.replace(/^.+\n.+\n/,""))&&(r.stack+=` -`+s):r.stack=s}catch{}}throw r}}_request(t,n){typeof t=="string"?(n=n||{},n.url=t):n=t||{},n=D(this.defaults,n);const{transitional:r,paramsSerializer:i,headers:s}=n;r!==void 0&&K.assertOptions(r,{silentJSONParsing:N.transitional(N.boolean),forcedJSONParsing:N.transitional(N.boolean),clarifyTimeoutError:N.transitional(N.boolean)},!1),i!=null&&(a.isFunction(i)?n.paramsSerializer={serialize:i}:K.assertOptions(i,{encode:N.function,serialize:N.function},!0)),n.allowAbsoluteUrls!==void 0||(this.defaults.allowAbsoluteUrls!==void 0?n.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls:n.allowAbsoluteUrls=!0),K.assertOptions(n,{baseUrl:N.spelling("baseURL"),withXsrfToken:N.spelling("withXSRFToken")},!0),n.method=(n.method||this.defaults.method||"get").toLowerCase();let o=s&&a.merge(s.common,s[n.method]);s&&a.forEach(["delete","get","head","post","put","patch","common"],f=>{delete s[f]}),n.headers=C.concat(o,s);const c=[];let u=!0;this.interceptors.request.forEach(function(v){typeof v.runWhen=="function"&&v.runWhen(n)===!1||(u=u&&v.synchronous,c.unshift(v.fulfilled,v.rejected))});const l=[];this.interceptors.response.forEach(function(v){l.push(v.fulfilled,v.rejected)});let d,p=0,w;if(!u){const f=[xe.bind(this),void 0];for(f.unshift.apply(f,c),f.push.apply(f,l),w=f.length,d=Promise.resolve(n);p{if(!r._listeners)return;let s=r._listeners.length;for(;s-- >0;)r._listeners[s](i);r._listeners=null}),this.promise.then=i=>{let s;const o=new Promise(c=>{r.subscribe(c),s=c}).then(i);return o.cancel=function(){r.unsubscribe(s)},o},t(function(s,o,c){r.reason||(r.reason=new I(s,o,c),n(r.reason))})}throwIfRequested(){if(this.reason)throw this.reason}subscribe(t){if(this.reason){t(this.reason);return}this._listeners?this._listeners.push(t):this._listeners=[t]}unsubscribe(t){if(!this._listeners)return;const n=this._listeners.indexOf(t);n!==-1&&this._listeners.splice(n,1)}toAbortSignal(){const t=new AbortController,n=r=>{t.abort(r)};return this.subscribe(n),t.signal.unsubscribe=()=>this.unsubscribe(n),t.signal}static source(){let t;return{token:new et(function(i){t=i}),cancel:t}}};function Nn(e){return function(n){return e.apply(null,n)}}function Ln(e){return a.isObject(e)&&e.isAxiosError===!0}const ue={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511};Object.entries(ue).forEach(([e,t])=>{ue[t]=e});function tt(e){const t=new U(e),n=Ne(U.prototype.request,t);return a.extend(n,U.prototype,t,{allOwnKeys:!0}),a.extend(n,t,null,{allOwnKeys:!0}),n.create=function(i){return tt(D(e,i))},n}const E=tt($);E.Axios=U;E.CanceledError=I;E.CancelToken=_n;E.isCancel=Ve;E.VERSION=Ye;E.toFormData=ee;E.AxiosError=m;E.Cancel=E.CanceledError;E.all=function(t){return Promise.all(t)};E.spread=Nn;E.isAxiosError=Ln;E.mergeConfig=D;E.AxiosHeaders=C;E.formToJSON=e=>Je(a.isHTMLForm(e)?new FormData(e):e);E.getAdapter=Qe.getAdapter;E.HttpStatusCode=ue;E.default=E;const{Axios:zn,AxiosError:Jn,CanceledError:Vn,isCancel:Kn,CancelToken:Wn,VERSION:Xn,all:Gn,Cancel:Zn,isAxiosError:Qn,spread:Yn,toFormData:er,AxiosHeaders:tr,HttpStatusCode:nr,formToJSON:rr,getAdapter:ir,mergeConfig:sr}=E,Bn=E.create({baseURL:"http://localhost:4000/api/v1",headers:{"Content-Type":"application/json"}});class Fn{base64ToFile(t,n,r){const i=t.includes(",")?t.split(",")[1]:t,s=atob(i),o=new ArrayBuffer(s.length),c=new Uint8Array(o);for(let l=0;l{let s=0;const o=()=>{const c=document.evaluate(t,document,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;if(c instanceof HTMLElement){i(c);return}s++,s{const o=new FileReader;o.onloadend=()=>{typeof o.result=="string"?i(o.result.split(",")[1]):s("Không thể đọc dữ liệu ảnh")},o.onerror=s,o.readAsDataURL(r)})}getImageExtension(t){try{const r=new URL(t).pathname.match(/\.([a-zA-Z0-9]+)$/);return r?r[1].toLowerCase():null}catch{const i=t.split("?")[0].match(/\.([a-zA-Z0-9]+)$/);return i?i[1].toLowerCase():null}}imageLocalToBase64(t){return new Promise((n,r)=>{try{const i=chrome.runtime.getURL(`${t}`);fetch(i).then(s=>s.blob()).then(s=>{const o=new FileReader;o.onloadend=()=>n(o.result),o.onerror=r,o.readAsDataURL(s)}).catch(r)}catch(i){r(i)}})}scrollToElement(t,n="smooth"){t&&t.scrollIntoView({behavior:n,block:"center",inline:"nearest"})}getElementPointCoores(t){if(!t)return null;const n=t.getBoundingClientRect(),r=n.left+n.width/2,i=n.top+n.height/2;return{x:r,y:i}}setInputValue(t,n){t&&(t.value=n,t.dispatchEvent(new Event("input",{bubbles:!0})),t.dispatchEvent(new Event("change",{bubbles:!0})))}writeToInput=async(t,n)=>{const r=await this.getElementByXPath(n);if(!r)throw new Error("Xpath is not found");this.scrollToElement(r),this.clickByPoint(r),this.setInputValue(r,t)};pressEnter(t){if(!t)throw new Error("Textarea not found:",t);t.focus(),["keydown","keypress","keyup"].forEach(n=>{t.dispatchEvent(new KeyboardEvent(n,{key:"Enter",code:"Enter",keyCode:13,which:13,bubbles:!0,cancelable:!0}))})}}const y=new Fn,P={file__image_input:'input[type="file"]',title_input:"/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[5]/div/div/div/label/div/input",price_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[6]/div/div/div/label/div/input",brand_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/input",description_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[3]/div/div/div/label/div/div/textarea",sku_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[6]/div/div/div[1]/label/div/input",category_select:{wraper:"/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]/div/div/div/div",container:"/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[2]/div/div/div[1]/div[1]/div/div/div/div/div/span/div"},condition_select:{wraper:"/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[8]/div/div/div/div",container:"/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[2]/div/div/div[1]/div[1]/div/div/div/div/div[1]/div"},tags_input:{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/div[1]/label/div/div/div[2]/div/textarea"},location_select:{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[7]/div/div/div/div/div/div/div/div/label/div[2]/input",wraper:"/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[7]/div/div/div/div/div/div/div/div",container:"/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[2]/div/div/div[1]/div[1]/div/ul"},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"},kn=async e=>{const t=new DataTransfer;for(const r of e.images){console.log("Base64:",r.slice(0,50)+"...");const i=y.base64ToFile(r,e.sku,y.getImageExtension(r)||"jpg");t.items.add(i)}const n=document.querySelector(P.file__image_input);n?(n.files=t.files,n.dispatchEvent(new Event("change",{bubbles:!0}))):console.error("Không tìm thấy input[type='file']")},Pe=async(e,t)=>{const n=await y.getElementByXPath(t.wraper);if(!n)throw new Error("Wrapper xpath not found");y.scrollToElement(n),y.clickByPoint(n),await S(400);const r=await y.getElementByXPath(t.container);if(!r)throw new Error("Container xpath not found");const i=Array.from(r.children).find(s=>s.textContent?.trim().toLocaleLowerCase()===e.toLocaleLowerCase());if(!i)throw new Error(`No child found with text "${e}"`);y.scrollToElement(i),await S(200),y.clickByPoint(i)},Un=async(e,{input:t,...n})=>{await y.writeToInput(e,t),await S(400);const r=await y.getElementByXPath(n.container);if(!r)throw new Error("Container xpath not found");const i=Array.from(r.children).find(s=>s.textContent?.trim().toLocaleLowerCase().includes(e.toLocaleLowerCase()));if(!i)throw new Error(`No child found with text "${e}"`);y.scrollToElement(i),await S(200),y.clickByPoint(i)},Dn=async(e,t)=>{const n=await y.getElementByXPath(t.input);if(!n)throw new Error("Input is not found");y.scrollToElement(n),await S(200);for(const r of e)y.writeToInput(r,t.input),await S(200),y.pressEnter(n)},_e=async(e,t)=>{const{data:n}=await Bn({url:"products/publist-finish/"+e.id,method:"POST",data:t});return n},jn=async()=>{const e=await y.getElementByXPath(P.next_btn);if(!e)throw new Error("Next button is not found");y.clickByPoint(e)},In=async e=>(console.log({item:e}),await S(1e3),await kn(e),await S(200),y.writeToInput(e.title,P.title_input),await S(200),y.writeToInput(String(e.price),P.price_input),await S(200),await Pe(e.category,P.category_select),await S(200),await Pe(e.condition,P.condition_select),e.brand&&(await S(200),y.writeToInput(e.brand,P.brand_input)),await S(200),await y.writeToInput(e.description,P.description_input),await S(200),await Dn(e.tags,P.tags_input),await S(200),y.writeToInput(e.sku,P.sku_input),e?.location&&(await S(200),await Un(e.location,P.location_select)),await S(200),await jn(),!0),qn=async e=>{await S(2e3),chrome.runtime.sendMessage({type:"close-tab",payload:e})},Mn=chrome.runtime.connect();Mn.onMessage.addListener(async e=>{if(e.type==="publist-event"){const t=e.payload;if(!t)return;console.log("Received new product event:",t);try{await S(2e3),await In(t)}catch(n){await _e(t,{error:n.message,published:!1})}finally{await _e(t,{published:!0}),await qn(t)}}}); +`+s):r.stack=s}catch{}}throw r}}_request(t,n){typeof t=="string"?(n=n||{},n.url=t):n=t||{},n=D(this.defaults,n);const{transitional:r,paramsSerializer:i,headers:s}=n;r!==void 0&&K.assertOptions(r,{silentJSONParsing:N.transitional(N.boolean),forcedJSONParsing:N.transitional(N.boolean),clarifyTimeoutError:N.transitional(N.boolean)},!1),i!=null&&(a.isFunction(i)?n.paramsSerializer={serialize:i}:K.assertOptions(i,{encode:N.function,serialize:N.function},!0)),n.allowAbsoluteUrls!==void 0||(this.defaults.allowAbsoluteUrls!==void 0?n.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls:n.allowAbsoluteUrls=!0),K.assertOptions(n,{baseUrl:N.spelling("baseURL"),withXsrfToken:N.spelling("withXSRFToken")},!0),n.method=(n.method||this.defaults.method||"get").toLowerCase();let o=s&&a.merge(s.common,s[n.method]);s&&a.forEach(["delete","get","head","post","put","patch","common"],f=>{delete s[f]}),n.headers=C.concat(o,s);const c=[];let u=!0;this.interceptors.request.forEach(function(v){typeof v.runWhen=="function"&&v.runWhen(n)===!1||(u=u&&v.synchronous,c.unshift(v.fulfilled,v.rejected))});const l=[];this.interceptors.response.forEach(function(v){l.push(v.fulfilled,v.rejected)});let d,p=0,w;if(!u){const f=[xe.bind(this),void 0];for(f.unshift.apply(f,c),f.push.apply(f,l),w=f.length,d=Promise.resolve(n);p{if(!r._listeners)return;let s=r._listeners.length;for(;s-- >0;)r._listeners[s](i);r._listeners=null}),this.promise.then=i=>{let s;const o=new Promise(c=>{r.subscribe(c),s=c}).then(i);return o.cancel=function(){r.unsubscribe(s)},o},t(function(s,o,c){r.reason||(r.reason=new I(s,o,c),n(r.reason))})}throwIfRequested(){if(this.reason)throw this.reason}subscribe(t){if(this.reason){t(this.reason);return}this._listeners?this._listeners.push(t):this._listeners=[t]}unsubscribe(t){if(!this._listeners)return;const n=this._listeners.indexOf(t);n!==-1&&this._listeners.splice(n,1)}toAbortSignal(){const t=new AbortController,n=r=>{t.abort(r)};return this.subscribe(n),t.signal.unsubscribe=()=>this.unsubscribe(n),t.signal}static source(){let t;return{token:new et(function(i){t=i}),cancel:t}}};function Nn(e){return function(n){return e.apply(null,n)}}function Ln(e){return a.isObject(e)&&e.isAxiosError===!0}const ue={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511};Object.entries(ue).forEach(([e,t])=>{ue[t]=e});function tt(e){const t=new U(e),n=Ne(U.prototype.request,t);return a.extend(n,U.prototype,t,{allOwnKeys:!0}),a.extend(n,t,null,{allOwnKeys:!0}),n.create=function(i){return tt(D(e,i))},n}const E=tt($);E.Axios=U;E.CanceledError=I;E.CancelToken=_n;E.isCancel=Ve;E.VERSION=Ye;E.toFormData=ee;E.AxiosError=m;E.Cancel=E.CanceledError;E.all=function(t){return Promise.all(t)};E.spread=Nn;E.isAxiosError=Ln;E.mergeConfig=D;E.AxiosHeaders=C;E.formToJSON=e=>Je(a.isHTMLForm(e)?new FormData(e):e);E.getAdapter=Qe.getAdapter;E.HttpStatusCode=ue;E.default=E;const{Axios:zn,AxiosError:Jn,CanceledError:Vn,isCancel:Kn,CancelToken:Wn,VERSION:Xn,all:Gn,Cancel:Zn,isAxiosError:Qn,spread:Yn,toFormData:er,AxiosHeaders:tr,HttpStatusCode:nr,formToJSON:rr,getAdapter:ir,mergeConfig:sr}=E,Bn=E.create({baseURL:"http://localhost:4000/api/v1",headers:{"Content-Type":"application/json"}});class Fn{base64ToFile(t,n,r){const i=t.includes(",")?t.split(",")[1]:t,s=atob(i),o=new ArrayBuffer(s.length),c=new Uint8Array(o);for(let l=0;l{let s=0;const o=()=>{const c=document.evaluate(t,document,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;if(c instanceof HTMLElement){i(c);return}s++,s{const o=new FileReader;o.onloadend=()=>{typeof o.result=="string"?i(o.result.split(",")[1]):s("Không thể đọc dữ liệu ảnh")},o.onerror=s,o.readAsDataURL(r)})}getImageExtension(t){try{const r=new URL(t).pathname.match(/\.([a-zA-Z0-9]+)$/);return r?r[1].toLowerCase():null}catch{const i=t.split("?")[0].match(/\.([a-zA-Z0-9]+)$/);return i?i[1].toLowerCase():null}}imageLocalToBase64(t){return new Promise((n,r)=>{try{const i=chrome.runtime.getURL(`${t}`);fetch(i).then(s=>s.blob()).then(s=>{const o=new FileReader;o.onloadend=()=>n(o.result),o.onerror=r,o.readAsDataURL(s)}).catch(r)}catch(i){r(i)}})}scrollToElement(t,n="smooth"){t&&t.scrollIntoView({behavior:n,block:"center",inline:"nearest"})}getElementPointCoores(t){if(!t)return null;const n=t.getBoundingClientRect(),r=n.left+n.width/2,i=n.top+n.height/2;return{x:r,y:i}}setInputValue(t,n){t&&(t.value=n,t.dispatchEvent(new Event("input",{bubbles:!0})),t.dispatchEvent(new Event("change",{bubbles:!0})))}writeToInput=async(t,n)=>{const r=await this.getElementByXPath(n);if(!r)throw new Error("Xpath is not found with value: "+t);this.scrollToElement(r),this.clickByPoint(r),this.setInputValue(r,t)};pressEnter(t){if(!t)throw new Error("Textarea not found:",t);t.focus(),["keydown","keypress","keyup"].forEach(n=>{t.dispatchEvent(new KeyboardEvent(n,{key:"Enter",code:"Enter",keyCode:13,which:13,bubbles:!0,cancelable:!0}))})}}const y=new Fn,P={file__image_input:'input[type="file"]',title_input:"/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[5]/div/div/div/label/div/input",price_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[6]/div/div/div/label/div/input",brand_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/input",description_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[3]/div/div/div/label/div/div/textarea",sku_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[6]/div/div/div[1]/label/div/input",category_select:{wraper:"/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]/div/div/div/div",container:"/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[2]/div/div/div[1]/div[1]/div/div/div/div/div/span/div"},condition_select:{wraper:"/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[8]/div/div/div/div",container:"/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[2]/div/div/div[1]/div[1]/div/div/div/div/div[1]/div"},tags_input:{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/div[1]/label/div/div/div[2]/div/textarea"},location_select:{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[7]/div/div/div/div/div/div/div/div/label/div[2]/input",wraper:"/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[7]/div/div/div/div/div/div/div/div",container:"/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[2]/div/div/div[1]/div[1]/div/ul"},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"},kn=async e=>{const t=new DataTransfer;for(const r of e.images){console.log("Base64:",r.slice(0,50)+"...");const i=y.base64ToFile(r,e.sku,y.getImageExtension(r)||"jpg");t.items.add(i)}const n=document.querySelector(P.file__image_input);n?(n.files=t.files,n.dispatchEvent(new Event("change",{bubbles:!0}))):console.error("Không tìm thấy input[type='file']")},Pe=async(e,t)=>{const n=await y.getElementByXPath(t.wraper);if(!n)throw new Error("Wrapper xpath not found");y.scrollToElement(n),y.clickByPoint(n),await S(400);const r=await y.getElementByXPath(t.container);if(!r)throw new Error("Container xpath not found");const i=Array.from(r.children).find(s=>s.textContent?.trim().toLocaleLowerCase()===e.toLocaleLowerCase());if(!i)throw new Error(`No child found with text "${e}"`);y.scrollToElement(i),await S(200),y.clickByPoint(i)},Un=async(e,{input:t,...n})=>{await y.writeToInput(e,t),await S(400);const r=await y.getElementByXPath(n.container);if(!r)throw new Error("Container xpath not found");y.scrollToElement(r);const i=Array.from(r.children).find(s=>s.textContent?.trim().toLocaleLowerCase().includes(e.toLocaleLowerCase()));if(!i)throw new Error(`No child found with text "${e}"`);y.scrollToElement(i),await S(200),y.clickByPoint(i)},Dn=async(e,t)=>{const n=await y.getElementByXPath(t.input);if(!n)throw new Error("Input is not found");y.scrollToElement(n),await S(200);for(const r of e)y.writeToInput(r,t.input),await S(200),y.pressEnter(n)},_e=async(e,t)=>{const{data:n}=await Bn({url:"products/publist-finish/"+e.id,method:"POST",data:t});return n},jn=async()=>{const e=await y.getElementByXPath(P.next_btn);if(!e)throw new Error("Next button is not found");y.clickByPoint(e)},In=async e=>(console.log({item:e}),await S(1e3),await kn(e),await S(400),y.writeToInput(e.title,P.title_input),await S(400),y.writeToInput(String(e.price),P.price_input),await S(400),await Pe(e.category,P.category_select),await S(400),await Pe(e.condition,P.condition_select),e.brand&&(await S(400),y.writeToInput(e.brand,P.brand_input)),await S(400),await y.writeToInput(e.description,P.description_input),await S(400),await Dn(e.tags,P.tags_input),await S(400),y.writeToInput(e.sku,P.sku_input),e?.location&&(await S(400),await Un(e.location,P.location_select)),await S(400),await jn(),!0),qn=async e=>{await S(2e3),chrome.runtime.sendMessage({type:"close-tab",payload:e})},Mn=chrome.runtime.connect();Mn.onMessage.addListener(async e=>{if(e.type==="publist-event"){const t=e.payload;if(!t)return;console.log("Received new product event:",t);try{await S(2e3),await In(t)}catch(n){await _e(t,{error:n.message,published:!1})}finally{await _e(t,{published:!0}),await qn(t)}}}); diff --git a/auto-listing-facebook-marketplace/src/content.ts b/auto-listing-facebook-marketplace/src/content.ts index 290529b..2d1e663 100644 --- a/auto-listing-facebook-marketplace/src/content.ts +++ b/auto-listing-facebook-marketplace/src/content.ts @@ -136,6 +136,8 @@ const chooseLocation = async ( const container = await thiefService.getElementByXPath(xpaths.container); if (!container) throw new Error("Container xpath not found"); + thiefService.scrollToElement(container); + // Tìm phần tử con có nội dung giống value const matchingChild = Array.from(container.children).find((child) => child.textContent @@ -216,54 +218,54 @@ const handle = async (item: IItem) => { // B1. Upload images await uploadImages(item); - await delay(200); + await delay(400); // B2. Write title thiefService.writeToInput(item.title, selectors.title_input); - await delay(200); + await delay(400); // B3. Write price thiefService.writeToInput(String(item.price), selectors.price_input); - await delay(200); + await delay(400); // B4. Select category await chooseSelect(item.category, selectors.category_select); - await delay(200); + await delay(400); // B5. Select condition await chooseSelect(item.condition, selectors.condition_select); if (item.brand) { - await delay(200); + await delay(400); // B3. Write price thiefService.writeToInput(item.brand, selectors.brand_input); } - await delay(200); + await delay(400); // B3. Write price await thiefService.writeToInput( item.description, selectors.description_input ); - await delay(200); + await delay(400); await writeTags(item.tags, selectors.tags_input); - await delay(200); + await delay(400); // B3. Write price thiefService.writeToInput(item.sku, selectors.sku_input); if (item?.location) { - await delay(200); + await delay(400); await chooseLocation(item.location, selectors.location_select); } - await delay(200); + await delay(400); await clickNext(); - // await delay(200); + // await delay(400); return true; }; diff --git a/client/app/routes/products/list.tsx b/client/app/routes/products/list.tsx index 71cf801..07e46ab 100644 --- a/client/app/routes/products/list.tsx +++ b/client/app/routes/products/list.tsx @@ -107,7 +107,7 @@ export default function List() { displayType: "custom", render: (value, row) => { if (!row.tags.length) { - return Chưa có vai trò; + return No tags; } return ( diff --git a/server/public/medias/products/gwegwgwegewgew/product-1754988109416.png b/server/public/medias/products/gwegwgwegewgew/product-1754988109416.png new file mode 100644 index 0000000..6d59e9b Binary files /dev/null and b/server/public/medias/products/gwegwgwegewgew/product-1754988109416.png differ diff --git a/server/public/medias/products/wegwegwe/product-1754987864481.png b/server/public/medias/products/wegwegwe/product-1754987864481.png new file mode 100644 index 0000000..8772d49 Binary files /dev/null and b/server/public/medias/products/wegwegwe/product-1754987864481.png differ diff --git a/server/public/medias/products/wegwegwe/product-1754987864493.png b/server/public/medias/products/wegwegwe/product-1754987864493.png new file mode 100644 index 0000000..cd0fd11 Binary files /dev/null and b/server/public/medias/products/wegwegwe/product-1754987864493.png differ diff --git a/server/public/medias/products/wegwegwegw/product-1754988224001.png b/server/public/medias/products/wegwegwegw/product-1754988224001.png new file mode 100644 index 0000000..7b620cf Binary files /dev/null and b/server/public/medias/products/wegwegwegw/product-1754988224001.png differ diff --git a/server/src/entities/publist-history.entity.ts b/server/src/entities/publist-history.entity.ts index 0ad05b1..c16cc83 100644 --- a/server/src/entities/publist-history.entity.ts +++ b/server/src/entities/publist-history.entity.ts @@ -10,6 +10,8 @@ export class PublistHistory extends CoreEntity { @Column({ type: 'bool' }) published: boolean; - @ManyToOne(() => Product, (product) => product.histories) + @ManyToOne(() => Product, (product) => product.histories, { + onDelete: 'CASCADE', // hoặc 'SET NULL' tùy mục đích + }) product: Product; } diff --git a/server/src/modules/products/products.service.ts b/server/src/modules/products/products.service.ts index 17b2be5..9bc664a 100644 --- a/server/src/modules/products/products.service.ts +++ b/server/src/modules/products/products.service.ts @@ -122,7 +122,6 @@ export class ProductsService extends CoreService { // Đợi phản hồi từ client const publistResult = await this.waitForPublistResult(plainData); - console.log({ publistResult }); if (!publistResult.published) { throw new BadRequestException( AppResponse.toResponse(null, { @@ -169,7 +168,6 @@ export class ProductsService extends CoreService { const result = await this.historiesRepo.save({ ...data, product }); - console.log({ result }); this.eventService.sendEvent( `${ProductsService.EVENTS.PUBLIST_FINISH}_${plainData.id}`, plainToClass(PublistHistory, result),