@softtynet/zplus-worker 1.0.51 → 1.0.52

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.
Files changed (2) hide show
  1. package/dist/cli.js +2 -2
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -54,7 +54,7 @@ Content-Type: ${a.type||"application/octet-stream"}\r
54
54
  `)).replace(/\n/g,"%0A").replace(/\r/g,"%0D").replace(/"/g,"%22"),aa=(e,t,r)=>{if(t.length<r)throw new TypeError(`Failed to execute '${e}' on 'FormData': ${r} arguments required, but only ${t.length} present.`)},oa=class{#e=[];constructor(...t){if(t.length)throw new TypeError("Failed to construct 'FormData': parameter 1 is not of type 'HTMLFormElement'.")}get[js](){return"FormData"}[QM](){return this.entries()}static[eq](t){return t&&typeof t=="object"&&t[js]==="FormData"&&!tq.some(r=>typeof t[r]!="function")}append(...t){aa("append",arguments,2),this.#e.push(QR(...t))}delete(t){aa("delete",arguments,1),t+="",this.#e=this.#e.filter(([r])=>r!==t)}get(t){aa("get",arguments,1),t+="";for(var r=this.#e,n=r.length,i=0;i<n;i++)if(r[i][0]===t)return r[i][1];return null}getAll(t,r){return aa("getAll",arguments,1),r=[],t+="",this.#e.forEach(n=>n[0]===t&&r.push(n[1])),r}has(t){return aa("has",arguments,1),t+="",this.#e.some(r=>r[0]===t)}forEach(t,r){aa("forEach",arguments,1);for(var[n,i]of this)t.call(r,i,n,this)}set(...t){aa("set",arguments,2);var r=[],n=!0;t=QR(...t),this.#e.forEach(i=>{i[0]===t[0]?n&&(n=!r.push(t)):r.push(i)}),n&&r.push(t),this.#e=r}*entries(){yield*this.#e}*keys(){for(var[t]of this)yield t}*values(){for(var[,t]of this)yield t}}});var Gn,gp=L(()=>{Gn=class extends Error{constructor(t,r){super(t),Error.captureStackTrace(this,this.constructor),this.type=r}get name(){return this.constructor.name}get[Symbol.toStringTag](){return this.constructor.name}}});var rr,h0=L(()=>{gp();rr=class extends Gn{constructor(t,r,n){super(t,r),n&&(this.code=this.errno=n.code,this.erroredSysCall=n.syscall)}}});var yp,m0,Ms,tP,rP,nP,xp=L(()=>{yp=Symbol.toStringTag,m0=e=>typeof e=="object"&&typeof e.append=="function"&&typeof e.delete=="function"&&typeof e.get=="function"&&typeof e.getAll=="function"&&typeof e.has=="function"&&typeof e.set=="function"&&typeof e.sort=="function"&&e[yp]==="URLSearchParams",Ms=e=>e&&typeof e=="object"&&typeof e.arrayBuffer=="function"&&typeof e.type=="string"&&typeof e.stream=="function"&&typeof e.constructor=="function"&&/^(Blob|File)$/.test(e[yp]),tP=e=>typeof e=="object"&&(e[yp]==="AbortSignal"||e[yp]==="EventTarget"),rP=(e,t)=>{let r=new URL(t).hostname,n=new URL(e).hostname;return r===n||r.endsWith(`.${n}`)},nP=(e,t)=>{let r=new URL(t).protocol,n=new URL(e).protocol;return r===n}});var aP=N((Jie,iP)=>{if(!globalThis.DOMException)try{let{MessageChannel:e}=require("worker_threads"),t=new e().port1,r=new ArrayBuffer;t.postMessage(r,[r,r])}catch(e){e.constructor.name==="DOMException"&&(globalThis.DOMException=e.constructor)}iP.exports=globalThis.DOMException});var bp,rq,Yie,g0=L(()=>{bp=require("node:fs"),rq=le(aP(),1);d0();zs();({stat:Yie}=bp.promises)});var sP={};Og(sP,{toFormData:()=>lq});function cq(e){let t=e.match(/\bfilename=("(.*?)"|([^()<>@,;:\\"/[\]?={}\s\t]+))($|;\s)/i);if(!t)return;let r=t[2]||t[3]||"",n=r.slice(r.lastIndexOf("\\")+1);return n=n.replace(/%22/g,'"'),n=n.replace(/&#(\d{4});/g,(i,a)=>String.fromCharCode(a)),n}async function lq(e,t){if(!/multipart/i.test(t))throw new TypeError("Failed to fetch");let r=t.match(/boundary=(?:"([^"]+)"|([^;]+))/i);if(!r)throw new TypeError("no or bad content-type header, no multipart boundary");let n=new y0(r[1]||r[2]),i,a,o,s,c,l,u=[],f=new oa,d=m=>{o+=k.decode(m,{stream:!0})},h=m=>{u.push(m)},v=()=>{let m=new xo(u,l,{type:c});f.append(s,m)},w=()=>{f.append(s,o)},k=new TextDecoder("utf-8");k.decode(),n.onPartBegin=function(){n.onPartData=d,n.onPartEnd=w,i="",a="",o="",s="",c="",l=null,u.length=0},n.onHeaderField=function(m){i+=k.decode(m,{stream:!0})},n.onHeaderValue=function(m){a+=k.decode(m,{stream:!0})},n.onHeaderEnd=function(){if(a+=k.decode(),i=i.toLowerCase(),i==="content-disposition"){let m=a.match(/\bname=("([^"]*)"|([^()<>@,;:\\"/[\]?={}\s\t]+))/i);m&&(s=m[2]||m[3]||""),l=cq(a),l&&(n.onPartData=h,n.onPartEnd=v)}else i==="content-type"&&(c=a);a="",i=""};for await(let m of e)n.write(m);return n.end(),f}var wn,ot,oP,_i,vp,wp,nq,qs,iq,aq,oq,sq,sa,y0,cP=L(()=>{g0();mp();wn=0,ot={START_BOUNDARY:wn++,HEADER_FIELD_START:wn++,HEADER_FIELD:wn++,HEADER_VALUE_START:wn++,HEADER_VALUE:wn++,HEADER_VALUE_ALMOST_DONE:wn++,HEADERS_ALMOST_DONE:wn++,PART_DATA_START:wn++,PART_DATA:wn++,END:wn++},oP=1,_i={PART_BOUNDARY:oP,LAST_BOUNDARY:oP*=2},vp=10,wp=13,nq=32,qs=45,iq=58,aq=97,oq=122,sq=e=>e|32,sa=()=>{},y0=class{constructor(t){this.index=0,this.flags=0,this.onHeaderEnd=sa,this.onHeaderField=sa,this.onHeadersEnd=sa,this.onHeaderValue=sa,this.onPartBegin=sa,this.onPartData=sa,this.onPartEnd=sa,this.boundaryChars={},t=`\r
55
55
  --`+t;let r=new Uint8Array(t.length);for(let n=0;n<t.length;n++)r[n]=t.charCodeAt(n),this.boundaryChars[r[n]]=!0;this.boundary=r,this.lookbehind=new Uint8Array(this.boundary.length+8),this.state=ot.START_BOUNDARY}write(t){let r=0,n=t.length,i=this.index,{lookbehind:a,boundary:o,boundaryChars:s,index:c,state:l,flags:u}=this,f=this.boundary.length,d=f-1,h=t.length,v,w,k=y=>{this[y+"Mark"]=r},m=y=>{delete this[y+"Mark"]},x=(y,_,S,R)=>{(_===void 0||_!==S)&&this[y](R&&R.subarray(_,S))},b=(y,_)=>{let S=y+"Mark";S in this&&(_?(x(y,this[S],r,t),delete this[S]):(x(y,this[S],t.length,t),this[S]=0))};for(r=0;r<n;r++)switch(v=t[r],l){case ot.START_BOUNDARY:if(c===o.length-2){if(v===qs)u|=_i.LAST_BOUNDARY;else if(v!==wp)return;c++;break}else if(c-1===o.length-2){if(u&_i.LAST_BOUNDARY&&v===qs)l=ot.END,u=0;else if(!(u&_i.LAST_BOUNDARY)&&v===vp)c=0,x("onPartBegin"),l=ot.HEADER_FIELD_START;else return;break}v!==o[c+2]&&(c=-2),v===o[c+2]&&c++;break;case ot.HEADER_FIELD_START:l=ot.HEADER_FIELD,k("onHeaderField"),c=0;case ot.HEADER_FIELD:if(v===wp){m("onHeaderField"),l=ot.HEADERS_ALMOST_DONE;break}if(c++,v===qs)break;if(v===iq){if(c===1)return;b("onHeaderField",!0),l=ot.HEADER_VALUE_START;break}if(w=sq(v),w<aq||w>oq)return;break;case ot.HEADER_VALUE_START:if(v===nq)break;k("onHeaderValue"),l=ot.HEADER_VALUE;case ot.HEADER_VALUE:v===wp&&(b("onHeaderValue",!0),x("onHeaderEnd"),l=ot.HEADER_VALUE_ALMOST_DONE);break;case ot.HEADER_VALUE_ALMOST_DONE:if(v!==vp)return;l=ot.HEADER_FIELD_START;break;case ot.HEADERS_ALMOST_DONE:if(v!==vp)return;x("onHeadersEnd"),l=ot.PART_DATA_START;break;case ot.PART_DATA_START:l=ot.PART_DATA,k("onPartData");case ot.PART_DATA:if(i=c,c===0){for(r+=d;r<h&&!(t[r]in s);)r+=f;r-=d,v=t[r]}if(c<o.length)o[c]===v?(c===0&&b("onPartData",!0),c++):c=0;else if(c===o.length)c++,v===wp?u|=_i.PART_BOUNDARY:v===qs?u|=_i.LAST_BOUNDARY:c=0;else if(c-1===o.length)if(u&_i.PART_BOUNDARY){if(c=0,v===vp){u&=~_i.PART_BOUNDARY,x("onPartEnd"),x("onPartBegin"),l=ot.HEADER_FIELD_START;break}}else u&_i.LAST_BOUNDARY&&v===qs?(x("onPartEnd"),l=ot.END,u=0):c=0;if(c>0)a[c-1]=v;else if(i>0){let y=new Uint8Array(a.buffer,a.byteOffset,a.byteLength);x("onPartData",0,i,y),i=0,k("onPartData"),r--}break;case ot.END:break;default:throw new Error(`Unexpected state entered: ${l}`)}b("onHeaderField"),b("onHeaderValue"),b("onPartData"),this.index=c,this.state=l,this.flags=u}end(){if(this.state===ot.HEADER_FIELD_START&&this.index===0||this.state===ot.PART_DATA&&this.index===this.boundary.length)this.onPartEnd();else if(this.state!==ot.END)throw new Error("MultipartParser.end(): stream ended unexpectedly")}}});async function x0(e){if(e[nr].disturbed)throw new TypeError(`body used already for: ${e.url}`);if(e[nr].disturbed=!0,e[nr].error)throw e[nr].error;let{body:t}=e;if(t===null)return fr.Buffer.alloc(0);if(!(t instanceof Nr.default))return fr.Buffer.alloc(0);let r=[],n=0;try{for await(let i of t){if(e.size>0&&n+i.length>e.size){let a=new rr(`content size at ${e.url} over limit: ${e.size}`,"max-size");throw t.destroy(a),a}n+=i.length,r.push(i)}}catch(i){throw i instanceof Gn?i:new rr(`Invalid response body while trying to fetch ${e.url}: ${i.message}`,"system",i)}if(t.readableEnded===!0||t._readableState.ended===!0)try{return r.every(i=>typeof i=="string")?fr.Buffer.from(r.join("")):fr.Buffer.concat(r,n)}catch(i){throw new rr(`Could not create Buffer from response body for ${e.url}: ${i.message}`,"system",i)}else throw new rr(`Premature close of server response while trying to fetch ${e.url}`)}var Nr,Vn,fr,uq,nr,_n,bo,pq,_p,lP,uP,kp=L(()=>{Nr=le(require("node:stream"),1),Vn=require("node:util"),fr=require("node:buffer");zs();mp();h0();gp();xp();uq=(0,Vn.promisify)(Nr.default.pipeline),nr=Symbol("Body internals"),_n=class{constructor(t,{size:r=0}={}){let n=null;t===null?t=null:m0(t)?t=fr.Buffer.from(t.toString()):Ms(t)||fr.Buffer.isBuffer(t)||(Vn.types.isAnyArrayBuffer(t)?t=fr.Buffer.from(t):ArrayBuffer.isView(t)?t=fr.Buffer.from(t.buffer,t.byteOffset,t.byteLength):t instanceof Nr.default||(t instanceof oa?(t=eP(t),n=t.type.split("=")[1]):t=fr.Buffer.from(String(t))));let i=t;fr.Buffer.isBuffer(t)?i=Nr.default.Readable.from(t):Ms(t)&&(i=Nr.default.Readable.from(t.stream())),this[nr]={body:t,stream:i,boundary:n,disturbed:!1,error:null},this.size=r,t instanceof Nr.default&&t.on("error",a=>{let o=a instanceof Gn?a:new rr(`Invalid response body while trying to fetch ${this.url}: ${a.message}`,"system",a);this[nr].error=o})}get body(){return this[nr].stream}get bodyUsed(){return this[nr].disturbed}async arrayBuffer(){let{buffer:t,byteOffset:r,byteLength:n}=await x0(this);return t.slice(r,r+n)}async formData(){let t=this.headers.get("content-type");if(t.startsWith("application/x-www-form-urlencoded")){let n=new oa,i=new URLSearchParams(await this.text());for(let[a,o]of i)n.append(a,o);return n}let{toFormData:r}=await Promise.resolve().then(()=>(cP(),sP));return r(this.body,t)}async blob(){let t=this.headers&&this.headers.get("content-type")||this[nr].body&&this[nr].body.type||"",r=await this.arrayBuffer();return new Wn([r],{type:t})}async json(){let t=await this.text();return JSON.parse(t)}async text(){let t=await x0(this);return new TextDecoder().decode(t)}buffer(){return x0(this)}};_n.prototype.buffer=(0,Vn.deprecate)(_n.prototype.buffer,"Please use 'response.arrayBuffer()' instead of 'response.buffer()'","node-fetch#buffer");Object.defineProperties(_n.prototype,{body:{enumerable:!0},bodyUsed:{enumerable:!0},arrayBuffer:{enumerable:!0},blob:{enumerable:!0},json:{enumerable:!0},text:{enumerable:!0},data:{get:(0,Vn.deprecate)(()=>{},"data doesn't exist, use json(), text(), arrayBuffer(), or body instead","https://github.com/node-fetch/node-fetch/issues/1000 (response)")}});bo=(e,t)=>{let r,n,{body:i}=e[nr];if(e.bodyUsed)throw new Error("cannot clone body after it is used");return i instanceof Nr.default&&typeof i.getBoundary!="function"&&(r=new Nr.PassThrough({highWaterMark:t}),n=new Nr.PassThrough({highWaterMark:t}),i.pipe(r),i.pipe(n),e[nr].stream=r,i=n),i},pq=(0,Vn.deprecate)(e=>e.getBoundary(),"form-data doesn't follow the spec and requires special treatment. Use alternative package","https://github.com/node-fetch/node-fetch/issues/1167"),_p=(e,t)=>e===null?null:typeof e=="string"?"text/plain;charset=UTF-8":m0(e)?"application/x-www-form-urlencoded;charset=UTF-8":Ms(e)?e.type||null:fr.Buffer.isBuffer(e)||Vn.types.isAnyArrayBuffer(e)||ArrayBuffer.isView(e)?null:e instanceof oa?`multipart/form-data; boundary=${t[nr].boundary}`:e&&typeof e.getBoundary=="function"?`multipart/form-data;boundary=${pq(e)}`:e instanceof Nr.default?null:"text/plain;charset=UTF-8",lP=e=>{let{body:t}=e[nr];return t===null?0:Ms(t)?t.size:fr.Buffer.isBuffer(t)?t.length:t&&typeof t.getLengthSync=="function"&&t.hasKnownLength&&t.hasKnownLength()?t.getLengthSync():null},uP=async(e,{body:t})=>{t===null?e.end():await uq(t,e)}});function pP(e=[]){return new hr(e.reduce((t,r,n,i)=>(n%2===0&&t.push(i.slice(n,n+2)),t),[]).filter(([t,r])=>{try{return Sp(t),v0(t,String(r)),!0}catch{return!1}}))}var b0,Hs,Sp,v0,hr,Ep=L(()=>{b0=require("node:util"),Hs=le(require("node:http"),1),Sp=typeof Hs.default.validateHeaderName=="function"?Hs.default.validateHeaderName:e=>{if(!/^[\^`\-\w!#$%&'*+.|~]+$/.test(e)){let t=new TypeError(`Header name must be a valid HTTP token [${e}]`);throw Object.defineProperty(t,"code",{value:"ERR_INVALID_HTTP_TOKEN"}),t}},v0=typeof Hs.default.validateHeaderValue=="function"?Hs.default.validateHeaderValue:(e,t)=>{if(/[^\t\u0020-\u007E\u0080-\u00FF]/.test(t)){let r=new TypeError(`Invalid character in header content ["${e}"]`);throw Object.defineProperty(r,"code",{value:"ERR_INVALID_CHAR"}),r}},hr=class e extends URLSearchParams{constructor(t){let r=[];if(t instanceof e){let n=t.raw();for(let[i,a]of Object.entries(n))r.push(...a.map(o=>[i,o]))}else if(t!=null)if(typeof t=="object"&&!b0.types.isBoxedPrimitive(t)){let n=t[Symbol.iterator];if(n==null)r.push(...Object.entries(t));else{if(typeof n!="function")throw new TypeError("Header pairs must be iterable");r=[...t].map(i=>{if(typeof i!="object"||b0.types.isBoxedPrimitive(i))throw new TypeError("Each header pair must be an iterable object");return[...i]}).map(i=>{if(i.length!==2)throw new TypeError("Each header pair must be a name/value tuple");return[...i]})}}else throw new TypeError("Failed to construct 'Headers': The provided value is not of type '(sequence<sequence<ByteString>> or record<ByteString, ByteString>)");return r=r.length>0?r.map(([n,i])=>(Sp(n),v0(n,String(i)),[String(n).toLowerCase(),String(i)])):void 0,super(r),new Proxy(this,{get(n,i,a){switch(i){case"append":case"set":return(o,s)=>(Sp(o),v0(o,String(s)),URLSearchParams.prototype[i].call(n,String(o).toLowerCase(),String(s)));case"delete":case"has":case"getAll":return o=>(Sp(o),URLSearchParams.prototype[i].call(n,String(o).toLowerCase()));case"keys":return()=>(n.sort(),new Set(URLSearchParams.prototype.keys.call(n)).keys());default:return Reflect.get(n,i,a)}}})}get[Symbol.toStringTag](){return this.constructor.name}toString(){return Object.prototype.toString.call(this)}get(t){let r=this.getAll(t);if(r.length===0)return null;let n=r.join(", ");return/^content-encoding$/i.test(t)&&(n=n.toLowerCase()),n}forEach(t,r=void 0){for(let n of this.keys())Reflect.apply(t,r,[this.get(n),n,this])}*values(){for(let t of this.keys())yield this.get(t)}*entries(){for(let t of this.keys())yield[t,this.get(t)]}[Symbol.iterator](){return this.entries()}raw(){return[...this.keys()].reduce((t,r)=>(t[r]=this.getAll(r),t),{})}[Symbol.for("nodejs.util.inspect.custom")](){return[...this.keys()].reduce((t,r)=>{let n=this.getAll(r);return r==="host"?t[r]=n[0]:t[r]=n.length>1?n:n[0],t},{})}};Object.defineProperties(hr.prototype,["get","entries","forEach","values"].reduce((e,t)=>(e[t]={enumerable:!0},e),{}))});var dq,Ap,w0=L(()=>{dq=new Set([301,302,303,307,308]),Ap=e=>dq.has(e)});var Vr,Lr,dP=L(()=>{Ep();kp();w0();Vr=Symbol("Response internals"),Lr=class e extends _n{constructor(t=null,r={}){super(t,r);let n=r.status!=null?r.status:200,i=new hr(r.headers);if(t!==null&&!i.has("Content-Type")){let a=_p(t,this);a&&i.append("Content-Type",a)}this[Vr]={type:"default",url:r.url,status:n,statusText:r.statusText||"",headers:i,counter:r.counter,highWaterMark:r.highWaterMark}}get type(){return this[Vr].type}get url(){return this[Vr].url||""}get status(){return this[Vr].status}get ok(){return this[Vr].status>=200&&this[Vr].status<300}get redirected(){return this[Vr].counter>0}get statusText(){return this[Vr].statusText}get headers(){return this[Vr].headers}get highWaterMark(){return this[Vr].highWaterMark}clone(){return new e(bo(this,this.highWaterMark),{type:this.type,url:this.url,status:this.status,statusText:this.statusText,headers:this.headers,ok:this.ok,redirected:this.redirected,size:this.size,highWaterMark:this.highWaterMark})}static redirect(t,r=302){if(!Ap(r))throw new RangeError('Failed to execute "redirect" on "response": Invalid status code');return new e(null,{headers:{location:new URL(t).toString()},status:r})}static error(){let t=new e(null,{status:0,statusText:""});return t[Vr].type="error",t}static json(t=void 0,r={}){let n=JSON.stringify(t);if(n===void 0)throw new TypeError("data is not JSON serializable");let i=new hr(r&&r.headers);return i.has("content-type")||i.set("content-type","application/json"),new e(n,{...r,headers:i})}get[Symbol.toStringTag](){return"Response"}};Object.defineProperties(Lr.prototype,{type:{enumerable:!0},url:{enumerable:!0},status:{enumerable:!0},ok:{enumerable:!0},redirected:{enumerable:!0},statusText:{enumerable:!0},headers:{enumerable:!0},clone:{enumerable:!0}})});var fP,hP=L(()=>{fP=e=>{if(e.search)return e.search;let t=e.href.length-1,r=e.hash||(e.href[t]==="#"?"#":"");return e.href[t-r.length]==="?"?"?":""}});function mP(e,t=!1){return e==null||(e=new URL(e),/^(about|blob|data):$/.test(e.protocol))?"no-referrer":(e.username="",e.password="",e.hash="",t&&(e.pathname="",e.search=""),e)}function bP(e){if(!yP.has(e))throw new TypeError(`Invalid referrerPolicy: ${e}`);return e}function fq(e){if(/^(http|ws)s:$/.test(e.protocol))return!0;let t=e.host.replace(/(^\[)|(]$)/g,""),r=(0,gP.isIP)(t);return r===4&&/^127\./.test(t)||r===6&&/^(((0+:){7})|(::(0+:){0,6}))0*1$/.test(t)?!0:e.host==="localhost"||e.host.endsWith(".localhost")?!1:e.protocol==="file:"}function vo(e){return/^about:(blank|srcdoc)$/.test(e)||e.protocol==="data:"||/^(blob|filesystem):$/.test(e.protocol)?!0:fq(e)}function vP(e,{referrerURLCallback:t,referrerOriginCallback:r}={}){if(e.referrer==="no-referrer"||e.referrerPolicy==="")return null;let n=e.referrerPolicy;if(e.referrer==="about:client")return"no-referrer";let i=e.referrer,a=mP(i),o=mP(i,!0);a.toString().length>4096&&(a=o),t&&(a=t(a)),r&&(o=r(o));let s=new URL(e.url);switch(n){case"no-referrer":return"no-referrer";case"origin":return o;case"unsafe-url":return a;case"strict-origin":return vo(a)&&!vo(s)?"no-referrer":o.toString();case"strict-origin-when-cross-origin":return a.origin===s.origin?a:vo(a)&&!vo(s)?"no-referrer":o;case"same-origin":return a.origin===s.origin?a:"no-referrer";case"origin-when-cross-origin":return a.origin===s.origin?a:o;case"no-referrer-when-downgrade":return vo(a)&&!vo(s)?"no-referrer":a;default:throw new TypeError(`Invalid referrerPolicy: ${n}`)}}function wP(e){let t=(e.get("referrer-policy")||"").split(/[,\s]+/),r="";for(let n of t)n&&yP.has(n)&&(r=n);return r}var gP,yP,xP,_0=L(()=>{gP=require("node:net");yP=new Set(["","no-referrer","no-referrer-when-downgrade","same-origin","origin","strict-origin","origin-when-cross-origin","strict-origin-when-cross-origin","unsafe-url"]),xP="strict-origin-when-cross-origin"});var _P,kP,At,Ws,hq,ca,SP,EP=L(()=>{_P=require("node:url"),kP=require("node:util");Ep();kp();xp();hP();_0();At=Symbol("Request internals"),Ws=e=>typeof e=="object"&&typeof e[At]=="object",hq=(0,kP.deprecate)(()=>{},".data is not a valid RequestInit property, use .body instead","https://github.com/node-fetch/node-fetch/issues/1000 (request)"),ca=class e extends _n{constructor(t,r={}){let n;if(Ws(t)?n=new URL(t.url):(n=new URL(t),t={}),n.username!==""||n.password!=="")throw new TypeError(`${n} is an url with embedded credentials.`);let i=r.method||t.method||"GET";if(/^(delete|get|head|options|post|put)$/i.test(i)&&(i=i.toUpperCase()),!Ws(r)&&"data"in r&&hq(),(r.body!=null||Ws(t)&&t.body!==null)&&(i==="GET"||i==="HEAD"))throw new TypeError("Request with GET/HEAD method cannot have body");let a=r.body?r.body:Ws(t)&&t.body!==null?bo(t):null;super(a,{size:r.size||t.size||0});let o=new hr(r.headers||t.headers||{});if(a!==null&&!o.has("Content-Type")){let l=_p(a,this);l&&o.set("Content-Type",l)}let s=Ws(t)?t.signal:null;if("signal"in r&&(s=r.signal),s!=null&&!tP(s))throw new TypeError("Expected signal to be an instanceof AbortSignal or EventTarget");let c=r.referrer==null?t.referrer:r.referrer;if(c==="")c="no-referrer";else if(c){let l=new URL(c);c=/^about:(\/\/)?client$/.test(l)?"client":l}else c=void 0;this[At]={method:i,redirect:r.redirect||t.redirect||"follow",headers:o,parsedURL:n,signal:s,referrer:c},this.follow=r.follow===void 0?t.follow===void 0?20:t.follow:r.follow,this.compress=r.compress===void 0?t.compress===void 0?!0:t.compress:r.compress,this.counter=r.counter||t.counter||0,this.agent=r.agent||t.agent,this.highWaterMark=r.highWaterMark||t.highWaterMark||16384,this.insecureHTTPParser=r.insecureHTTPParser||t.insecureHTTPParser||!1,this.referrerPolicy=r.referrerPolicy||t.referrerPolicy||""}get method(){return this[At].method}get url(){return(0,_P.format)(this[At].parsedURL)}get headers(){return this[At].headers}get redirect(){return this[At].redirect}get signal(){return this[At].signal}get referrer(){if(this[At].referrer==="no-referrer")return"";if(this[At].referrer==="client")return"about:client";if(this[At].referrer)return this[At].referrer.toString()}get referrerPolicy(){return this[At].referrerPolicy}set referrerPolicy(t){this[At].referrerPolicy=bP(t)}clone(){return new e(this)}get[Symbol.toStringTag](){return"Request"}};Object.defineProperties(ca.prototype,{method:{enumerable:!0},url:{enumerable:!0},headers:{enumerable:!0},redirect:{enumerable:!0},clone:{enumerable:!0},signal:{enumerable:!0},referrer:{enumerable:!0},referrerPolicy:{enumerable:!0}});SP=e=>{let{parsedURL:t}=e[At],r=new hr(e[At].headers);r.has("Accept")||r.set("Accept","*/*");let n=null;if(e.body===null&&/^(post|put)$/i.test(e.method)&&(n="0"),e.body!==null){let s=lP(e);typeof s=="number"&&!Number.isNaN(s)&&(n=String(s))}n&&r.set("Content-Length",n),e.referrerPolicy===""&&(e.referrerPolicy=xP),e.referrer&&e.referrer!=="no-referrer"?e[At].referrer=vP(e):e[At].referrer="no-referrer",e[At].referrer instanceof URL&&r.set("Referer",e.referrer),r.has("User-Agent")||r.set("User-Agent","node-fetch"),e.compress&&!r.has("Accept-Encoding")&&r.set("Accept-Encoding","gzip, deflate, br");let{agent:i}=e;typeof i=="function"&&(i=i(t));let a=fP(t),o={path:t.pathname+a,method:e.method,headers:r[Symbol.for("nodejs.util.inspect.custom")](),insecureHTTPParser:e.insecureHTTPParser,agent:i};return{parsedURL:t,options:o}}});var Cp,AP=L(()=>{gp();Cp=class extends Gn{constructor(t,r="aborted"){super(t,r)}}});async function Vs(e,t){return new Promise((r,n)=>{let i=new ca(e,t),{parsedURL:a,options:o}=SP(i);if(!mq.has(a.protocol))throw new TypeError(`node-fetch cannot load ${e}. URL scheme "${a.protocol.replace(/:$/,"")}" is not supported.`);if(a.protocol==="data:"){let v=WR(i.url),w=new Lr(v,{headers:{"Content-Type":v.typeFull}});r(w);return}let s=(a.protocol==="https:"?IP.default:CP.default).request,{signal:c}=i,l=null,u=()=>{let v=new Cp("The operation was aborted.");n(v),i.body&&i.body instanceof mr.default.Readable&&i.body.destroy(v),!(!l||!l.body)&&l.body.emit("error",v)};if(c&&c.aborted){u();return}let f=()=>{u(),h()},d=s(a.toString(),o);c&&c.addEventListener("abort",f);let h=()=>{d.abort(),c&&c.removeEventListener("abort",f)};d.on("error",v=>{n(new rr(`request to ${i.url} failed, reason: ${v.message}`,"system",v)),h()}),gq(d,v=>{l&&l.body&&l.body.destroy(v)}),process.version<"v14"&&d.on("socket",v=>{let w;v.prependListener("end",()=>{w=v._eventsCount}),v.prependListener("close",k=>{if(l&&w<v._eventsCount&&!k){let m=new Error("Premature close");m.code="ERR_STREAM_PREMATURE_CLOSE",l.body.emit("error",m)}})}),d.on("response",v=>{d.setTimeout(0);let w=pP(v.rawHeaders);if(Ap(v.statusCode)){let y=w.get("Location"),_=null;try{_=y===null?null:new URL(y,i.url)}catch{if(i.redirect!=="manual"){n(new rr(`uri requested responds with an invalid redirect URL: ${y}`,"invalid-redirect")),h();return}}switch(i.redirect){case"error":n(new rr(`uri requested responds with a redirect, redirect mode is set to error: ${i.url}`,"no-redirect")),h();return;case"manual":break;case"follow":{if(_===null)break;if(i.counter>=i.follow){n(new rr(`maximum redirect reached at: ${i.url}`,"max-redirect")),h();return}let S={headers:new hr(i.headers),follow:i.follow,counter:i.counter+1,agent:i.agent,compress:i.compress,method:i.method,body:bo(i),signal:i.signal,size:i.size,referrer:i.referrer,referrerPolicy:i.referrerPolicy};if(!rP(i.url,_)||!nP(i.url,_))for(let B of["authorization","www-authenticate","cookie","cookie2"])S.headers.delete(B);if(v.statusCode!==303&&i.body&&t.body instanceof mr.default.Readable){n(new rr("Cannot follow redirect with body being a readable stream","unsupported-redirect")),h();return}(v.statusCode===303||(v.statusCode===301||v.statusCode===302)&&i.method==="POST")&&(S.method="GET",S.body=void 0,S.headers.delete("content-length"));let R=wP(w);R&&(S.referrerPolicy=R),r(Vs(new ca(_,S))),h();return}default:return n(new TypeError(`Redirect option '${i.redirect}' is not a valid value of RequestRedirect`))}}c&&v.once("end",()=>{c.removeEventListener("abort",f)});let k=(0,mr.pipeline)(v,new mr.PassThrough,y=>{y&&n(y)});process.version<"v12.10"&&v.on("aborted",f);let m={url:i.url,status:v.statusCode,statusText:v.statusMessage,headers:w,size:i.size,counter:i.counter,highWaterMark:i.highWaterMark},x=w.get("Content-Encoding");if(!i.compress||i.method==="HEAD"||x===null||v.statusCode===204||v.statusCode===304){l=new Lr(k,m),r(l);return}let b={flush:la.default.Z_SYNC_FLUSH,finishFlush:la.default.Z_SYNC_FLUSH};if(x==="gzip"||x==="x-gzip"){k=(0,mr.pipeline)(k,la.default.createGunzip(b),y=>{y&&n(y)}),l=new Lr(k,m),r(l);return}if(x==="deflate"||x==="x-deflate"){let y=(0,mr.pipeline)(v,new mr.PassThrough,_=>{_&&n(_)});y.once("data",_=>{(_[0]&15)===8?k=(0,mr.pipeline)(k,la.default.createInflate(),S=>{S&&n(S)}):k=(0,mr.pipeline)(k,la.default.createInflateRaw(),S=>{S&&n(S)}),l=new Lr(k,m),r(l)}),y.once("end",()=>{l||(l=new Lr(k,m),r(l))});return}if(x==="br"){k=(0,mr.pipeline)(k,la.default.createBrotliDecompress(),y=>{y&&n(y)}),l=new Lr(k,m),r(l);return}l=new Lr(k,m),r(l)}),uP(d,i).catch(n)})}function gq(e,t){let r=Gs.Buffer.from(`0\r
56
56
  \r
57
- `),n=!1,i=!1,a;e.on("response",o=>{let{headers:s}=o;n=s["transfer-encoding"]==="chunked"&&!s["content-length"]}),e.on("socket",o=>{let s=()=>{if(n&&!i){let l=new Error("Premature close");l.code="ERR_STREAM_PREMATURE_CLOSE",t(l)}},c=l=>{i=Gs.Buffer.compare(l.slice(-5),r)===0,!i&&a&&(i=Gs.Buffer.compare(a.slice(-3),r.slice(0,3))===0&&Gs.Buffer.compare(l.slice(-2),r.slice(3))===0),a=l};o.prependListener("close",s),o.on("data",c),e.on("close",()=>{o.removeListener("close",s),o.removeListener("data",c)})})}var CP,IP,la,mr,Gs,mq,TP=L(()=>{CP=le(require("node:http"),1),IP=le(require("node:https"),1),la=le(require("node:zlib"),1),mr=le(require("node:stream"),1),Gs=require("node:buffer");GR();kp();dP();Ep();EP();h0();AP();w0();mp();xp();_0();g0();mq=new Set(["data:","http:","https:"])});var PP=N((zae,k0)=>{"use strict";var yq=Object.prototype.hasOwnProperty,Wt="~";function Js(){}Object.create&&(Js.prototype=Object.create(null),new Js().__proto__||(Wt=!1));function xq(e,t,r){this.fn=e,this.context=t,this.once=r||!1}function RP(e,t,r,n,i){if(typeof r!="function")throw new TypeError("The listener must be a function");var a=new xq(r,n||e,i),o=Wt?Wt+t:t;return e._events[o]?e._events[o].fn?e._events[o]=[e._events[o],a]:e._events[o].push(a):(e._events[o]=a,e._eventsCount++),e}function Ip(e,t){--e._eventsCount===0?e._events=new Js:delete e._events[t]}function Ut(){this._events=new Js,this._eventsCount=0}Ut.prototype.eventNames=function(){var t=[],r,n;if(this._eventsCount===0)return t;for(n in r=this._events)yq.call(r,n)&&t.push(Wt?n.slice(1):n);return Object.getOwnPropertySymbols?t.concat(Object.getOwnPropertySymbols(r)):t};Ut.prototype.listeners=function(t){var r=Wt?Wt+t:t,n=this._events[r];if(!n)return[];if(n.fn)return[n.fn];for(var i=0,a=n.length,o=new Array(a);i<a;i++)o[i]=n[i].fn;return o};Ut.prototype.listenerCount=function(t){var r=Wt?Wt+t:t,n=this._events[r];return n?n.fn?1:n.length:0};Ut.prototype.emit=function(t,r,n,i,a,o){var s=Wt?Wt+t:t;if(!this._events[s])return!1;var c=this._events[s],l=arguments.length,u,f;if(c.fn){switch(c.once&&this.removeListener(t,c.fn,void 0,!0),l){case 1:return c.fn.call(c.context),!0;case 2:return c.fn.call(c.context,r),!0;case 3:return c.fn.call(c.context,r,n),!0;case 4:return c.fn.call(c.context,r,n,i),!0;case 5:return c.fn.call(c.context,r,n,i,a),!0;case 6:return c.fn.call(c.context,r,n,i,a,o),!0}for(f=1,u=new Array(l-1);f<l;f++)u[f-1]=arguments[f];c.fn.apply(c.context,u)}else{var d=c.length,h;for(f=0;f<d;f++)switch(c[f].once&&this.removeListener(t,c[f].fn,void 0,!0),l){case 1:c[f].fn.call(c[f].context);break;case 2:c[f].fn.call(c[f].context,r);break;case 3:c[f].fn.call(c[f].context,r,n);break;case 4:c[f].fn.call(c[f].context,r,n,i);break;default:if(!u)for(h=1,u=new Array(l-1);h<l;h++)u[h-1]=arguments[h];c[f].fn.apply(c[f].context,u)}}return!0};Ut.prototype.on=function(t,r,n){return RP(this,t,r,n,!1)};Ut.prototype.once=function(t,r,n){return RP(this,t,r,n,!0)};Ut.prototype.removeListener=function(t,r,n,i){var a=Wt?Wt+t:t;if(!this._events[a])return this;if(!r)return Ip(this,a),this;var o=this._events[a];if(o.fn)o.fn===r&&(!i||o.once)&&(!n||o.context===n)&&Ip(this,a);else{for(var s=0,c=[],l=o.length;s<l;s++)(o[s].fn!==r||i&&!o[s].once||n&&o[s].context!==n)&&c.push(o[s]);c.length?this._events[a]=c.length===1?c[0]:c:Ip(this,a)}return this};Ut.prototype.removeAllListeners=function(t){var r;return t?(r=Wt?Wt+t:t,this._events[r]&&Ip(this,r)):(this._events=new Js,this._eventsCount=0),this};Ut.prototype.off=Ut.prototype.removeListener;Ut.prototype.addListener=Ut.prototype.on;Ut.prefixed=Wt;Ut.EventEmitter=Ut;typeof k0<"u"&&(k0.exports=Ut)});var OP,FP,DP=L(()=>{OP=le(PP(),1),FP=OP.default});var Tp,BP=L(()=>{"use strict";DP();Tp=class extends FP{}});function Rp(e,t){let r=e.data||e,n=String(r.fromId||r.uidFrom||r.idFrom||r.uid||r.fromUid||""),i=!!e.isSelf||!!r.isSelf||n==="0"||r.uidFrom==="0"||r.fromId==="0"||!!n&&n===t,a=i?n&&n!=="0"?n:t:n,o=r.dName||r.displayName||r.senderName||void 0,s="text",c="";typeof r.msg=="string"?c=r.msg:typeof r.message=="string"?c=r.message:typeof r.content=="string"&&(c=r.content);let l=r.mediaUrl||(typeof r.content=="object"&&r.content!==null?r.content.href||r.content.thumb||r.content.url||"":typeof r.content=="string"&&(r.content.startsWith("http://")||r.content.startsWith("https://"))?r.content:r.href||r.url||"");r.msgType==="chat.image"||r.msgType==="chat.photo"?s="image":r.msgType==="chat.video"?s="video":r.msgType==="chat.voice"||r.msgType==="chat.audio"?s="audio":r.msgType==="chat.file"||r.msgType==="chat.document"?s="file":r.msgType==="chat.sticker"?s="sticker":(r.msgType==="system"||r.msgType==="chat.system")&&(s="system");let u=String(e.threadId||r.threadId||r.groupId||"");if(!u){let v=String(r.toId||r.idTo||"");u=v===t?a:v}let f=!!(Number(e.type)===1||Number(r.type)===1||r.groupId||e.groupId||r.msgType?.includes("group")||String(u).startsWith("g")||String(u).includes("|")),d=r.groupName||r.gName||r.groupTitle||e.groupName||void 0,h=r.groupAvatar||r.gAvatar||r.avt||e.groupAvatar||void 0;return{id:String(r.msgId||r.id||r.cliMsgId||""),conversationId:u,threadId:u,accountId:t,senderId:a,senderName:o,text:c,content:c,type:s,messageType:s,mediaUrl:l,timestamp:Number(r.ts||r.timestamp||Date.now()),platform:"zalo",isFromMe:i,isSelf:i,isGroup:f,groupName:d,groupAvatar:h,metadata:{rawMsgType:r.msgType,reactions:r.reactions||r.reaction||null,sticker:r.sticker||null,rawPayload:bq(e)}}}function bq(e){if(!e||typeof e!="object")return e;let t={},r=["threadId","type","isGroup","serverTime","act"];for(let n of r)e[n]!==void 0&&(t[n]=e[n]);if(e.data&&typeof e.data=="object")t.data=NP(e.data);else{let n=NP(e);Object.assign(t,n)}return t}function NP(e){if(!e||typeof e!="object")return e;let t={},r=["msgId","id","cliMsgId","globalMsgId","actionId","msgType","msg","message","content","mediaUrl","ts","timestamp","time","fromId","uidFrom","idFrom","uid","fromUid","userId","toId","idTo","toUid","uidTo","dName","displayName","fromDisplayName","avatar","avt","fullAvt","fromAvatar","oaAvatar","groupName","gName","groupTitle","groupAvatar","gAvt","isTyping","seenTime","action","paramsExt","params"];for(let n of r)e[n]!==void 0&&(n==="paramsExt"&&typeof e[n]=="object"&&e[n]!==null?t[n]=JSON.parse(JSON.stringify(e[n])):t[n]=e[n]);return e.attachments!==void 0&&(t.attachments=Array.isArray(e.attachments)?e.attachments.map(n=>JSON.parse(JSON.stringify(n))):e.attachments),e.quote!==void 0&&(t.quote=vq(e.quote)),e.reactions!==void 0&&(t.reactions=e.reactions),e.reaction!==void 0&&(t.reaction=e.reaction),e.sticker!==void 0&&(t.sticker=e.sticker),e.mentions!==void 0&&(t.mentions=e.mentions),t}function vq(e){if(!e||typeof e!="object")return e;let t=["msgId","cliMsgId","globalMsgId","msg","content","attach","fromD","msgType","ownerId","senderId","senderName","ts","timestamp","url","href","thumb","localPath","fileName","fileSize","cloud_file_id"],r={};for(let n of t)e[n]!==void 0&&(r[n]=e[n]);return r}var S0=L(()=>{"use strict"});function E0(e){if(!e)return{id:"",name:"Zalo User",avatarUrl:"",platform:"zalo"};let t=e;if(typeof t=="string")try{t=JSON.parse(t)}catch{}t&&t.data&&!t.changed_profiles&&(t=t.data),t&&t.changed_profiles&&(t=Object.values(t.changed_profiles)[0]||t),t&&t.profile&&(t=t.profile);let r=t||{},n=String(r.userId||r.id||r.uid||r.uidFrom||""),i=String(r.displayName||r.name||r.zaloName||r.zName||(typeof r.username=="string"&&r.username?r.username:"")||"Zalo User"),a=String(r.avatar||r.avt||r.fullAvt||r.picture||""),o=r.phoneNumber||r.phone||r.phone_number||void 0;return{id:n,name:i,avatarUrl:a,phoneNumber:o,platform:"zalo",rawContact:r}}function LP(e){let t=e.data||e,r=String(t.threadId||t.id||t.groupId||""),n=String(t.name||t.displayName||t.threadName||"Zalo Chat"),i=String(t.avatar||t.avt||t.avatarUrl||""),a="direct";return(r.startsWith("g")||r.includes("|")||t.isGroup||t.type===1)&&(a="group"),{id:r,name:n,avatarUrl:i,type:a,unreadCount:Number(t.unreadCount||0),platform:"zalo",rawConversation:t}}var A0=L(()=>{"use strict"});function wq(e){if(!e||e.length<16)return null;if(e[0]===137&&e[1]===80&&e[2]===78&&e[3]===71){let t=e.readUInt32BE(16),r=e.readUInt32BE(20);return{width:t,height:r,format:"png"}}if(e[0]===71&&e[1]===73&&e[2]===70){let t=e.readUInt16LE(6),r=e.readUInt16LE(8);return{width:t,height:r,format:"gif"}}if(e[0]===255&&e[1]===216){let t=2;for(;t<e.length-8;){if(e[t]!==255){t++;continue}let r=e[t+1];if(r>=192&&r<=195||r>=197&&r<=199||r>=201&&r<=203||r>=205&&r<=207){let i=e.readUInt16BE(t+5);return{width:e.readUInt16BE(t+7),height:i,format:"jpeg"}}let n=e.readUInt16BE(t+2);t+=2+n}}if(e.length>=30&&e.toString("ascii",0,4)==="RIFF"&&e.toString("ascii",8,12)==="WEBP"){let t=e.toString("ascii",12,16);if(t==="VP8 "){let r=e.readUInt16LE(26)&16383,n=e.readUInt16LE(28)&16383;return{width:r,height:n,format:"webp"}}else if(t==="VP8L"&&e[20]===47){let r=e[21],n=e[22],i=e[23],a=e[24],o=1+((n&63)<<8|r),s=1+((a&15)<<10|i<<2|(n&192)>>6);return{width:o,height:s,format:"webp"}}else if(t==="VP8X"){let r=1+(e[24]|e[25]<<8|e[26]<<16),n=1+(e[27]|e[28]<<8|e[29]<<16);return{width:r,height:n,format:"webp"}}}return null}var UP,$P,zP,jP,C0,Pp,Op,MP=L(()=>{"use strict";zm();UP=le(DR()),$P=le(LR()),zP=le(HR());TP();jP=le(Vo()),C0=le(require("fs/promises")),Pp=le(require("path"));BP();S0();A0();S0();A0();zm();Op=class e{accountId;platform="zalo";eventBus=new Tp;status="disconnected";zaloInstance=null;api=null;session=null;constructor(t){this.accountId=t}async getImageMetadata(t){try{let r=await C0.default.readFile(t),n=wq(r);return n?{width:n.width,height:n.height,size:r.length,extension:n.format||Pp.default.extname(t).slice(1)}:{width:0,height:0,size:(await C0.default.stat(t)).size,extension:Pp.default.extname(t).slice(1)||"jpg"}}catch{return{width:0,height:0,size:0,extension:Pp.default.extname(t).slice(1)||"jpg"}}}async initialize(t){this.session=t;let r={selfListen:!0,checkUpdate:!1,logging:!0,userAgent:t.authData.userAgent,imei:t.authData.imei,imageMetadataGetter:i=>this.getImageMetadata(i)};if(t.proxy)try{let i;t.proxy.startsWith("socks")?i=UP.SocksProxyAgent:t.proxy.startsWith("https")?i=zP.HttpsProxyAgent:i=$P.HttpProxyAgent,r.agent=new i(t.proxy)}catch{}r.polyfill=Vs.default||Vs,this.zaloInstance=new Ns(r);let n=this.zaloInstance;if(n.ctx&&n.ctx.cookie){let i=n.ctx.cookie.setCookie.bind(n.ctx.cookie);n.ctx.cookie.setCookie=async(a,o,s)=>{try{let c;return typeof a=="string"?c=jP.Cookie.parse(a):c=a,c&&c.value==="EXPIRED"?Promise.resolve(c):i(a,o,s)}catch{return i(a,o,s)}}}t.authData.cookie&&(t.authData.cookie=e.patchCookieDomain(t.authData.cookie));try{this.status="connecting",this.eventBus.emit("session:status_changed","connecting");let i=this.zaloInstance.login(t.authData);i.then(s=>{this.status==="disconnected"&&s&&s.listener&&typeof s.listener.stop=="function"&&s.listener.stop()}).catch(()=>{});let a=new Promise((s,c)=>setTimeout(()=>c(new Error("Zalo login timeout after 30s")),3e4));this.api=await Promise.race([i,a]),this.setupListeners(),t.authData?.autoStartListener!==!1&&(this.api?.listener&&typeof this.api.listener.start=="function"&&this.api.listener.start({retryOnClose:!0}),this.requestCatchUp()),this.status="connected",this.eventBus.emit("session:status_changed","connected")}catch(i){throw this.status="disconnected",this.eventBus.emit("session:status_changed","disconnected",i.message),i}}async disconnect(){if(this.zaloInstance){try{if(this.api&&this.api.listener){let t=this.api.listener;typeof t.stop=="function"&&t.stop()}}catch{}this.zaloInstance=null,this.api=null,this.status="disconnected",this.eventBus.emit("session:status_changed","disconnected")}}async sendMessage(t,r){if(!this.api)throw new Error("Adapter not initialized or logged in");let i=r.isGroup??(t.startsWith("g")||t.includes("|"))?Z.Group:Z.User,a;if(r.type==="text"){let c={msg:r.text};r.mentions&&r.mentions.length>0&&(c.mentions=r.mentions),r.quote&&(c.quote=r.quote),a=await this.api.sendMessage(c,t,i)}else if(r.type==="image"){let c=r.filePath||r.url;if(!c)throw new Error("Image path or url is required for image payload");if(typeof this.api.sendImage=="function"){let l={url:c,caption:r.caption};r.quote&&(l.quote=r.quote),a=await this.api.sendImage(l,t,i)}else{let l={msg:r.caption||"",attachments:[c]};r.quote&&(l.quote=r.quote),a=await this.api.sendMessage(l,t,i)}}else if(r.type==="sticker")if(typeof this.api.sendSticker=="function")a=await this.api.sendSticker({stickerId:r.stickerId,stickerPackId:r.stickerPackId},t,i);else throw new Error("sendSticker method is not supported on this version of underlying client");else if(r.type==="file"){let c=r.filePath||r.url;if(!c)throw new Error("File path or url is required for file payload");a=await this.api.sendMessage({msg:"",attachments:[c]},t,i)}else throw new Error(`Unsupported message payload type: ${r.type}`);let o=a?.message?a.message:a,s=Rp(o,this.accountId);return s.conversationId||(s.conversationId=t),s.senderId||(s.senderId=this.accountId),!s.text&&r.type==="text"&&r.text&&(s.text=r.text),s}async getConversations(t=20){if(!this.api)throw new Error("Adapter not initialized");return(await this.api.getConversations(t)).map(LP)}async getMessageHistory(t,r=50){if(!this.api)throw new Error("Adapter not initialized");return[]}async getCurrentUser(){if(!this.api)return null;let t=await this.api.fetchAccountInfo();return E0(t)}async getContactInfo(t){if(!this.api)throw new Error("Adapter not initialized");try{let r=await this.api.getUserInfo(t);return E0(r)}catch{return null}}async markAsRead(t){if(!this.api)throw new Error("Adapter not initialized");try{typeof this.api.markAsRead=="function"&&await this.api.markAsRead(t)}catch{}}async sendTyping(t,r){if(!this.api)throw new Error("Adapter not initialized");try{typeof this.api.sendTyping=="function"&&await this.api.sendTyping(t,r)}catch{}}getUnderlyingClient(){return this.api}setupListeners(){if(!this.api||!this.api.listener)return;let t=this.api.listener;t.on("message",r=>{try{let n=Rp(r,this.accountId);this.eventBus.emit("message:received",n)}catch(n){console.error(`[ZaloAdapter:${this.accountId}] Failed to map incoming message:`,n?.message||n)}}),t.on("connected",()=>{this.status="connected",this.eventBus.emit("session:status_changed","connected")}),t.on("error",r=>{console.error(`[ZaloAdapter:${this.accountId}] WebSocket listener error:`,r?.message||r)}),t.on("typing",r=>{try{this.eventBus.emit("chat:typing",{conversationId:String(r.threadId||r.groupId||""),senderId:String(r.senderId||r.fromUid||""),isTyping:!!(r.isTyping||r.type==="start")})}catch{}}),t.on("undo",r=>{try{this.eventBus.emit("message:recalled",{conversationId:String(r.threadId||""),messageId:String(r.msgId||""),recalledAt:Date.now()})}catch{}}),t.on("read",r=>{try{this.eventBus.emit("chat:read",{conversationId:String(r.threadId||""),readerId:String(r.senderId||r.uid||""),timestamp:Date.now()})}catch{}}),t.on("old_messages",r=>{if(!(!r||!Array.isArray(r))){for(let n of r)if(n)try{let i=Rp(n,this.accountId);this.eventBus.emit("message:received",i)}catch{}}})}requestCatchUp(){if(!this.api||!this.api.listener)return;let t=this.api.listener;try{typeof t.requestOldMessages=="function"&&(t.requestOldMessages(0),t.requestOldMessages(1))}catch{}}async getGroupInfo(t){if(!this.api||typeof this.api.getGroupInfo!="function")return null;try{return await this.api.getGroupInfo(t)}catch{return null}}async getAllGroups(){if(!this.api||typeof this.api.getAllGroups!="function")return null;try{return await this.api.getAllGroups()}catch{return null}}static patchCookieDomain(t){if(!t)return t;let r=[],n=!1;if(Array.isArray(t))r=t;else if(t&&Array.isArray(t.cookies))r=t.cookies,n=!0;else return t;let i=r.map(a=>a&&(a.domain==="id.zalo.me"||a.domain==="zaloapp.com")?{...a,domain:".zalo.me"}:a);return n?{...t,cookies:i}:i}}});var qP={};Og(qP,{ZaloChannelRunner:()=>I0});var Zs,I0,HP=L(()=>{"use strict";Zs=le(it());MP();I0=class{constructor(t,r,n,i){this.accountId=t;this.sessionData=r;this.proxyData=n;this.logger=i||(0,Zs.createLogger)(`ZaloRunner:${t}`)}platform="zalo";status="offline";logger;messageHandler;adapter;groupNameCache=new Map;onMessage(t){this.messageHandler=t}async start(){let t=this.proxyData?` via resident proxy ${this.proxyData.host||this.proxyData.ip||"configured"}`:" (direct)";this.logger.info(`Starting 24/7 headless Zalo runner for account ${this.accountId}${t}...`);let r=this.sessionData;this.sessionData?.encryptedSession?r=Zs.CloudCrypto.parseCloudSession(this.sessionData.encryptedSession):typeof this.sessionData=="string"&&(r=Zs.CloudCrypto.parseCloudSession(this.sessionData));let n=r?.cookie||r?.cookies;if(n&&r?.imei)try{this.adapter=new Op(this.accountId),this.adapter.eventBus.on("message:received",a=>{this.receiveIncomingMessage(a)});let i;if(this.proxyData?.host&&this.proxyData?.port){let a=this.proxyData.username&&this.proxyData.password?`${this.proxyData.username}:${this.proxyData.password}@`:"";i=`${this.proxyData.protocol||"http"}://${a}${this.proxyData.host}:${this.proxyData.port}`}await this.adapter.initialize({accountId:this.accountId,platform:"zalo",status:"connecting",authData:{cookie:n,imei:r.imei,userAgent:r.userAgent},proxy:i}),this.status="active",this.logger.info(`Headless Zalo socket WSS connected & listening for ${this.accountId}`),this.prewarmGroupCache().catch(()=>{})}catch(i){this.status="expired",this.logger.warn(`Could not initialize live Zalo socket for ${this.accountId}: ${i.message}. Phi\xEAn \u0111\u0103ng nh\u1EADp Zalo \u0111\xE3 h\u1EBFt h\u1EA1n ho\u1EB7c kh\xF4ng h\u1EE3p l\u1EC7.`)}else this.status="active",this.logger.debug(`No direct Zalo session credentials provided for ${this.accountId}. Running in standby mode.`)}async stop(){if(this.logger.info(`Stopping headless Zalo runner for account ${this.accountId}...`),this.adapter){try{await this.adapter.disconnect()}catch(t){this.logger.debug(`Error disconnecting adapter during teardown for ${this.accountId}:`,t?.message)}this.adapter=void 0}this.status="offline"}getStatus(){return this.status}pause(){this.status==="active"&&(this.status="standby",this.logger.info(`\u23F8\uFE0F [StateGuard] Paused Zalo runner for account ${this.accountId} (standby)`))}resume(){this.status==="standby"&&(this.status="active",this.logger.info(`\u25B6\uFE0F [StateGuard] Resumed Zalo runner for account ${this.accountId} (active)`))}async sendMessage(t){if(this.logger.info(`Headless Zalo runner sending message ${t.id} to thread ${t.threadId}`),this.adapter&&this.adapter.status==="connected")try{let r=t.threadId||t.conversationId,n=Array.isArray(t.attachments)&&t.attachments.length>0?t.attachments[0]?.url:void 0;return t.messageType==="image"&&n?await this.adapter.sendMessage(r,{type:"image",url:n,caption:t.content||void 0}):await this.adapter.sendMessage(r,{type:"text",text:t.content||""}),!0}catch(r){return this.logger.error(`Failed to send message via Zalo socket: ${r.message}`),!1}return!0}async resolveGroupMetadata(t){if(!t)return null;let r=this.groupNameCache.get(t);if(r)return r;if(!this.adapter)return null;try{let n=await this.adapter.getGroupInfo(t),i=n?.data||n,a=i?.gridInfoMap?.[t]||i;if(a?.name){let o={name:String(a.name).trim(),avatar:a.avt||a.fullAvt||a.avatar||void 0};return this.groupNameCache.set(t,o),o}}catch(n){this.logger.debug(`Could not resolve group info for ${t}: ${n?.message}`)}return null}async prewarmGroupCache(){if(this.adapter)try{let t=await this.adapter.getAllGroups(),r=t?.gridVerMap||t?.data?.gridVerMap;if(r){let n=Object.keys(r);if(n.length>0){for(let a=0;a<Math.min(n.length,100);a+=25){let o=n.slice(a,a+25),s=await this.adapter.getGroupInfo(o),c=s?.gridInfoMap||s?.data?.gridInfoMap;if(c)for(let l of Object.keys(c)){let u=c[l];u?.name&&this.groupNameCache.set(l,{name:String(u.name).trim(),avatar:u.avt||u.fullAvt||u.avatar||void 0})}}this.logger.info(`[ZaloRunner:${this.accountId}] \u2705 Pre-warmed ${this.groupNameCache.size} group metadata entries.`)}}}catch(t){this.logger.debug(`[ZaloRunner:${this.accountId}] Note prewarming groups: ${t?.message}`)}}async receiveIncomingMessage(t){if(this.status!=="active")return;let r=String(t.content||t.text||""),n=String(t.threadId||t.conversationId||""),i=String(t.conversationId||t.threadId||""),a=!!(t.isSelf||t.isFromMe||t.senderId==="0"||this.accountId&&String(t.senderId)===String(this.accountId)),o=t.metadata?.rawPayload||t.rawPayload||t,s=!!(t.isGroup||o?.isGroup||Number(o?.type)===1||Number(o?.data?.type)===1||o?.groupId||o?.data?.groupId||n.startsWith("g")),c=t.groupName||o?.groupName||o?.data?.groupName,l=t.groupAvatar||o?.groupAvatar||o?.data?.groupAvatar;if(s&&(!c||c==="Nh\xF3m Zalo")){let f=this.groupNameCache.get(n);if(f?.name)c=f.name,l=f.avatar||l;else{let d=await Promise.race([this.resolveGroupMetadata(n),new Promise(h=>setTimeout(()=>h(null),1e3))]);d?.name&&(c=d.name,l=d.avatar||l)}}let u={...t,content:r,text:r,threadId:n,conversationId:i,accountId:t.accountId||this.accountId,senderId:a&&(t.senderId==="0"||!t.senderId)?this.accountId:t.senderId,isSelf:a,isGroup:s,groupName:c||(s?"Nh\xF3m Zalo":void 0),groupAvatar:l};this.logger.info(`\u{1F4E9} [ZaloRunner:${this.accountId}] Received message ${u.id} from sender ${u.senderName||u.senderId}${s?` in group [${u.groupName}]`:""}: "${r.slice(0,60)}"`),this.messageHandler?.(u)}requestCatchUp(){this.adapter&&typeof this.adapter.requestCatchUp=="function"&&this.adapter.requestCatchUp()}}});var tt=le(require("fs")),$t=le(require("path")),rt=le(require("os")),h4=le(require("readline")),Ze=require("child_process");var Rn=le(require("os")),ni=le(require("fs")),Lo=le(require("path")),Fg=le(require("crypto"));function KO(){return"1.0.51"}var Vt=KO();function Ac(){return{totalMemMb:Math.round(Rn.default.totalmem()/(1024*1024)),freeMemMb:Math.round(Rn.default.freemem()/(1024*1024)),cpuCount:Rn.default.cpus()?.length||1,platform:Rn.default.platform()}}function YO(e){try{let t=Lo.default.join(Rn.default.homedir(),".zplus");ni.default.existsSync(t)||ni.default.mkdirSync(t,{recursive:!0});let r=e?`_slot_${e.replace(/[^a-zA-Z0-9_-]/g,"")}`:"",n=Lo.default.join(t,`worker_identity${r}.json`);if(ni.default.existsSync(n)){let f=JSON.parse(ni.default.readFileSync(n,"utf-8"));if(f&&f.workerId)return{workerId:f.workerId,workerName:f.workerName||f.workerId}}let a=(Rn.default.hostname()||"node").replace(/[^a-zA-Z0-9_-]/g,"_").toLowerCase().slice(0,14),o=Fg.default.randomBytes(2).toString("hex"),s=`worker_${a}${r}_${o}`,c=e?` #${e}`:"",l=`Worker ${a.toUpperCase()}${c}`,u={workerId:s,workerName:l,slot:e||"default",createdAt:new Date().toISOString()};return ni.default.writeFileSync(n,JSON.stringify(u,null,2),"utf-8"),u}catch{let t=e?`_slot_${e}`:"",r=`worker_${Rn.default.hostname().replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,14)||"node"}${t}`;return{workerId:r,workerName:r}}}var Ec=class{static loadFromEnv(t=process.argv.slice(2)){let r=B=>{for(let T of t){if(T.startsWith(`--${B}=`))return T.split("=").slice(1).join("=");if(T===`--${B}`&&t[t.indexOf(T)+1])return t[t.indexOf(T)+1]}},n=r("cloud-provider")||process.env.CLOUD_PROVIDER||"appwrite",i=r("token")||process.env.CLOUD_AUTH_TOKEN||process.env.APPWRITE_SESSION_TOKEN||process.env.WORKER_TOKEN||process.env.SESSION_TOKEN,a=r("jwt")||process.env.CLOUD_JWT||process.env.APPWRITE_JWT||process.env.JWT,o=r("secret")||process.env.DESKTOP_SECRET,s=r("team-id")||process.env.TEAM_ID||"default",c=t.includes("--enable-http")||r("enable-http")==="true"||process.env.ENABLE_HTTP==="true"||!1,l=r("port")||process.env.PORT,u=l?Number(l):c?8080:void 0,f=r("endpoint")||process.env.CLOUD_ENDPOINT||process.env.CLOUD_API_ENDPOINT||process.env.APPWRITE_ENDPOINT||process.env.VITE_APPWRITE_ENDPOINT||"https://api.softty.net/v1",d=r("project-id")||process.env.CLOUD_PROJECT_ID||process.env.CLOUD_TENANT_ID||process.env.APPWRITE_PROJECT_ID||process.env.VITE_APPWRITE_PROJECT_ID||"699cfc3100136099c1c1",h=r("database-id")||process.env.CLOUD_DATABASE_ID||process.env.APPWRITE_DATABASE_ID||process.env.VITE_APPWRITE_DATABASE_ID||"zplus_app",v=r("storage-bucket-id")||process.env.STORAGE_BUCKET_ID||process.env.APPWRITE_STORAGE_BUCKET_ID||process.env.VITE_APPWRITE_STORAGE_BUCKET_ID||"zplus-media-vault",w=Math.max(1,Math.round(Rn.default.totalmem()/(1024*1024*1024))),k=Math.min(200,Math.max(20,w*25)),m=r("max-capacity")||process.env.MAX_CAPACITY,x=Number(m||k),b=r("slot")||process.env.WORKER_SLOT||process.env.pm_id||process.env.NODE_APP_INSTANCE,y=YO(b),_=r("worker-id")||process.env.WORKER_ID||y.workerId,S=r("worker-name")||process.env.WORKER_NAME||process.env.HOSTNAME||y.workerName,R=r("user-id")||process.env.USER_ID||process.env.SOFTTY_USER_ID;return{workerId:_,version:Vt,enableHttp:c,port:u,userId:R,teamId:s,workerName:S,maxCapacity:x,recommendedCapacity:k,clusterPollIntervalMs:Number(r("poll-interval")||process.env.CLUSTER_POLL_INTERVAL_MS||5e3),cloudProvider:n,cloudEndpoint:f,cloudProjectId:d,cloudSessionToken:i,cloudJwt:a,cloudDatabaseId:h,appwriteEndpoint:f,appwriteProjectId:d,appwriteSessionToken:i,appwriteJwt:a,storageBucketId:v,desktopSecret:o,databaseId:h,heartbeatIntervalMs:Number(r("heartbeat-interval")||process.env.HEARTBEAT_INTERVAL_MS||3e4),geminiApiKey:r("gemini-api-key")||process.env.GEMINI_API_KEY||process.env.GOOGLE_API_KEY,openaiApiKey:r("openai-api-key")||process.env.OPENAI_API_KEY,deepseekApiKey:r("deepseek-api-key")||process.env.DEEPSEEK_API_KEY,anthropicApiKey:r("anthropic-api-key")||process.env.ANTHROPIC_API_KEY,customAiApiKey:r("custom-ai-api-key")||process.env.CUSTOM_AI_API_KEY,aiBaseUrl:r("ai-base-url")||process.env.AI_BASE_URL,aiProvider:r("ai-provider")||process.env.AI_PROVIDER,aiModel:r("ai-model")||process.env.AI_MODEL,nightSystemPrompt:r("night-system-prompt")||process.env.NIGHT_SYSTEM_PROMPT,nightFallbackReply:r("night-fallback-reply")||process.env.NIGHT_FALLBACK_REPLY,logLevel:r("log-level")||process.env.LOG_LEVEL||"info"}}};var Si=le(require("fs")),Zp=le(require("os")),da=le(require("path")),d4=le(require("crypto")),Yp=le(it());var qg=le(it()),Oc=class{runners=new Map;logger;constructor(t){this.logger=t||(0,qg.createLogger)("ChannelRunnerRegistry")}register(t){let r=`${t.platform}:${t.accountId}`;this.runners.has(r)&&this.logger.warn(`Overwriting existing runner for ${r}`),this.runners.set(r,t),this.logger.info(`Registered runner for ${r}`)}unregister(t,r){let n=`${t}:${r}`,i=this.runners.get(n);return i?(i.stop().catch(a=>{this.logger.error(`Error stopping runner ${n} during unregister`,a)}),this.runners.delete(n),this.logger.info(`Unregistered runner for ${n}`),!0):!1}get(t,r){return this.runners.get(`${t}:${r}`)}getAll(){return Array.from(this.runners.values())}getCount(){return this.runners.size}async startAll(){this.logger.info(`Starting all ${this.runners.size} registered channel runners...`);for(let[t,r]of this.runners.entries())try{await r.start()}catch(n){this.logger.error(`Failed to start runner ${t}:`,n)}}async stopAll(){this.logger.info(`Stopping all ${this.runners.size} channel runners...`);for(let[t,r]of this.runners.entries())try{await r.stop()}catch(n){this.logger.error(`Failed to stop runner ${t}:`,n)}this.runners.clear()}async pauseAll(){this.logger.info(`Pausing all ${this.runners.size} channel runners due to worker auth/standby status...`);for(let[t,r]of this.runners.entries())try{typeof r.pause=="function"&&await r.pause()}catch(n){this.logger.error(`Failed to pause runner ${t}:`,n)}}async resumeAll(){this.logger.info(`Resuming all ${this.runners.size} channel runners...`);for(let[t,r]of this.runners.entries())try{typeof r.resume=="function"&&await r.resume()}catch(n){this.logger.error(`Failed to resume runner ${t}:`,n)}}};var Hg=le(it()),Fc=class{constructor(t=6e4,r,n){this.defaultTtlMs=t;this.logger=r||(0,Hg.createLogger)("DistributedLockManager"),this.storageProvider=n}logger;locks=new Map;preemptCallbacks=[];storageProvider;setStorageProvider(t){this.storageProvider=t}getStorageProvider(){return this.storageProvider}onPreempt(t){this.preemptCallbacks.push(t)}async acquireLockRemote(t,r,n=this.defaultTtlMs){return this.storageProvider&&!await this.storageProvider.acquireLock(t,r,n)?!1:this.acquireLock(t,r,n)}async releaseLockRemote(t,r){return this.storageProvider&&await this.storageProvider.releaseLock(t,r),this.releaseLock(t,r)}async renewLockRemote(t,r,n=this.defaultTtlMs){return this.storageProvider&&await this.storageProvider.renewLock(t,r,n),this.acquireLock(t,r,n)}acquireLock(t,r,n=this.defaultTtlMs){let i=Date.now(),a=this.locks.get(t);return a&&a.expiresAt>i&&a.ownerId!==r?(this.logger.warn(`Lock denied for account ${t}: currently held by ${a.ownerId} (expires in ${a.expiresAt-i}ms)`),!1):(this.locks.set(t,{accountId:t,ownerId:r,acquiredAt:i,expiresAt:i+n}),this.logger.info(`\u2705 Lock granted: account=${t}, owner=${r}, ttl=${n}ms`),!0)}async preemptLock(t,r){let n=this.locks.get(t);this.logger.info(`\u26A1 Preemption triggered for account ${t} by master ${r} (previous owner: ${n?.ownerId||"none"})`);let i=this.preemptCallbacks.map(o=>{try{return Promise.resolve(o(t,r))}catch(s){return this.logger.error(`Error in preempt callback for ${t}:`,s),Promise.resolve()}});await Promise.race([Promise.all(i),new Promise(o=>setTimeout(o,1e3))]);let a=Date.now();return this.locks.set(t,{accountId:t,ownerId:r,acquiredAt:a,expiresAt:a+this.defaultTtlMs}),this.logger.info(`\u2705 Account ${t} preempted successfully by ${r}.`),!0}releaseLock(t,r){let n=this.locks.get(t);return n?r&&n.ownerId!==r?(this.logger.warn(`Attempted unauthorized lock release for ${t} by ${r} (real owner: ${n.ownerId})`),!1):(this.locks.delete(t),this.logger.info(`\u{1F513} Lock released for account ${t}.`),!0):!0}releaseAllForOwner(t){let r=0;for(let[n,i]of this.locks.entries())i.ownerId===t&&(this.locks.delete(n),r++);return r}isLocked(t){let r=this.locks.get(t);return r?r.expiresAt>Date.now():!1}getLockOwner(t){let r=this.locks.get(t);return!r||r.expiresAt<=Date.now()?null:r.ownerId}};var Ta=le(require("fs")),Wg=le(require("path")),Gg=le(it()),Dc=class{logger;queue=[];maxCapacity;persistenceFilePath;constructor(t=1e4,r,n){this.maxCapacity=t,this.logger=r||(0,Gg.createLogger)("CloudPendingMessageQueue"),this.persistenceFilePath=n,this.loadFromDisk()}loadFromDisk(){if(this.persistenceFilePath)try{if(Ta.default.existsSync(this.persistenceFilePath)){let t=Ta.default.readFileSync(this.persistenceFilePath,"utf8");if(t&&t.trim()){let r=JSON.parse(t);Array.isArray(r)&&(this.queue.push(...r),this.logger.info(`\u{1F4E6} Restored ${r.length} pending delta messages from disk: ${this.persistenceFilePath}`))}}}catch(t){this.logger.warn(`Failed to restore pending messages from disk (${this.persistenceFilePath}): ${t?.message}`)}}saveToDisk(){if(this.persistenceFilePath)try{let t=Wg.default.dirname(this.persistenceFilePath);Ta.default.existsSync(t)||Ta.default.mkdirSync(t,{recursive:!0}),Ta.default.writeFileSync(this.persistenceFilePath,JSON.stringify(this.queue),"utf8")}catch(t){this.logger.warn(`Failed to save pending messages to disk (${this.persistenceFilePath}): ${t?.message}`)}}enqueue(t){if(this.queue.length>=this.maxCapacity){let r=this.queue.shift();this.logger.warn(`Queue capacity reached (${this.maxCapacity}). Dropped oldest message: ${r?.id}`)}this.queue.push(t),this.saveToDisk(),this.logger.debug(`Enqueued pending message ${t.id} for account ${t.accountId} (Total pending: ${this.queue.length})`)}getDeltas(t,r=0){return this.queue.filter(n=>{let i=!t||n.accountId===t,a=n.timestamp>=r;return i&&a})}purgeSynced(t,r){let n=this.queue.length,i=[];for(let o=0;o<this.queue.length;o++){let s=this.queue[o];s.timestamp<=t&&(!r||s.accountId===r)&&i.push(o)}for(let o=i.length-1;o>=0;o--)this.queue.splice(i[o],1);let a=n-this.queue.length;return a>0&&(this.saveToDisk(),this.logger.info(`Purged ${a} synced delta messages from queue.`)),a}getCount(){return this.queue.length}getAll(){return[...this.queue]}remove(t){let r=this.queue.findIndex(n=>n.id===t);return r!==-1?(this.queue.splice(r,1),this.saveToDisk(),!0):!1}clear(){this.queue.length=0,this.saveToDisk()}};var Vg=le(it()),Bc=class{logger;campaigns=new Map;rules=new Map;threadHistory=new Map;lastReplyTimes=new Map;aiConfig={enabled:!1};constructor(t,r){this.logger=t||(0,Vg.createLogger)("HeadlessAutomationEngine"),r&&this.configure(r)}configure(t){this.aiConfig={...this.aiConfig,...t},this.logger.info(`[HeadlessAutomation] Configured AI provider: ${this.aiConfig.provider||"none"} (model: ${this.aiConfig.model||"none"}, enabled: ${this.aiConfig.enabled===!0})`)}getAiConfig(){return{...this.aiConfig}}registerCampaign(t){this.campaigns.set(t.id,t),this.logger.info(`Loaded campaign ${t.id} (${t.name})`)}registerRule(t){this.rules.set(t.id,t),this.logger.info(`Loaded automation rule ${t.id} (${t.name})`)}async evaluateIncomingMessage(t){if(t.isSelf||t.senderType&&t.senderType!=="customer"||!t.content||typeof t.content!="string"||!t.content.trim())return null;let r=t.threadId||t.conversationId||t.senderId,n=Date.now(),i=this.lastReplyTimes.get(r)||0;if(n-i<3e3)return this.logger.debug(`[HeadlessAutomation] Rate limit hit for thread ${r}. Skipping reply.`),null;let a=t.content.trim(),o=this.getThreadHistory(r);if(o.push({role:"user",content:a,timestamp:n}),o.length>6&&o.splice(0,o.length-6),!this.aiConfig||this.aiConfig.enabled!==!0||!this.aiConfig.provider)return this.logger.debug(`[HeadlessAutomation] Bot AI is disabled or unconfigured. Message saved, no auto-reply sent for thread ${r}.`),null;let s=t.accountId,c=this.aiConfig.accountBotConfigs,l=s&&c?c[s]:void 0;if(!l||!l.isBotEnabled)return this.logger.debug(`[HeadlessAutomation] Account [${s||"unknown"}] has not been configured or enabled for Bot AI by user in Chatbot settings. Message saved, no auto-reply sent.`),null;let u=t,f=!!u.isGroup||!!u.groupId||typeof t.threadId=="string"&&t.threadId.startsWith("g")||typeof t.conversationId=="string"&&t.conversationId.startsWith("g"),d=l.replyTarget||"all";if(d==="individual"&&f)return this.logger.debug(`[HeadlessAutomation] Account [${s}] configured for individual chat only. Skipping group message ${r}.`),null;if(d==="group"&&!f)return this.logger.debug(`[HeadlessAutomation] Account [${s}] configured for group chat only. Skipping direct message ${r}.`),null;let h=l.scheduleType||"always";if(h!=="always"){let _=new Date().getHours(),S=l.scheduleStartHour??8,R=l.scheduleEndHour??18;if(h==="working_hours"){if(_<S||_>=R)return this.logger.debug(`[HeadlessAutomation] Outside working hours (${_}h, allowed: ${S}h-${R}h). Skipping reply.`),null}else if(h==="outside_hours"&&_>=S&&_<R)return this.logger.debug(`[HeadlessAutomation] Inside working hours (${_}h, allowed outside: ${S}h-${R}h). Skipping reply.`),null}let v=l.excludeContactIds||[];if(!f&&v.length>0){let _=String(t.senderId||"");if(v.includes(_))return this.logger.debug(`[HeadlessAutomation] Sender ${_} is in contact blacklist. Skipping reply.`),null}if(f){let _=String(u.groupId||u.threadId||r||""),S=l.excludeGroupIds||[],R=l.includeGroupIds||[];if(S.length>0&&S.includes(_))return this.logger.debug(`[HeadlessAutomation] Group ${_} is in group blacklist. Skipping reply.`),null;if(R.length>0&&!R.includes(_))return this.logger.debug(`[HeadlessAutomation] Group ${_} is not in group whitelist. Skipping reply.`),null}let w=l.excludeKeywords||[],k=l.includeKeywords||[],m=a.toLowerCase();if(w.length>0&&w.some(S=>{let R=S.trim().toLowerCase();return R.length>0&&m.includes(R)}))return this.logger.debug("[HeadlessAutomation] Message contains blacklisted keyword. Skipping reply."),null;if(k.length>0&&!k.some(S=>{let R=S.trim().toLowerCase();return R.length>0&&m.includes(R)}))return this.logger.debug("[HeadlessAutomation] Message does not match any whitelist keyword. Skipping reply."),null;let x=l.systemPrompt&&l.systemPrompt.trim()?l.systemPrompt:this.aiConfig.systemPrompt;if(this.aiConfig.provider==="rule_based")return this.aiConfig.fallbackMessage&&this.aiConfig.fallbackMessage.trim().length>0?(this.lastReplyTimes.set(r,n),this.aiConfig.fallbackMessage.trim()):null;let b=this.aiConfig.provider,y=this.aiConfig.apiKey;if(y||(b==="openai"?y=process.env.OPENAI_API_KEY:b==="deepseek"?y=process.env.DEEPSEEK_API_KEY:b==="anthropic"?y=process.env.ANTHROPIC_API_KEY:b==="custom"?y=process.env.CUSTOM_AI_API_KEY:b==="gemini"&&(y=process.env.GEMINI_API_KEY||process.env.GOOGLE_API_KEY)),!y&&b!=="custom")return this.logger.debug(`[HeadlessAutomation] No API key found for provider [${b}]. No auto-reply sent.`),null;try{let _=null;if(b==="openai"||b==="custom"||b==="deepseek")_=await this.callOpenAiCompatible(a,o,y||"",x);else if(b==="anthropic")_=await this.callAnthropic(a,o,y||"",x);else if(b==="gemini")_=await this.callGemini(a,o,y||"",x);else return this.logger.warn(`[HeadlessAutomation] Unsupported AI provider [${b}]. No reply generated.`),null;if(_&&_.trim().length>0){let S=_.trim();return o.push({role:"model",content:S,timestamp:Date.now()}),this.lastReplyTimes.set(r,Date.now()),S}}catch(_){this.logger.warn(`[HeadlessAutomation] AI generation error with provider [${b}] (${_?.message}).`)}return this.aiConfig.fallbackMessage&&this.aiConfig.fallbackMessage.trim().length>0?(this.lastReplyTimes.set(r,Date.now()),this.aiConfig.fallbackMessage.trim()):null}getThreadHistory(t){let r=this.threadHistory.get(t);return r||(r=[],this.threadHistory.set(t,r)),r}async callGemini(t,r,n,i){let o=`https://generativelanguage.googleapis.com/v1beta/models/${this.aiConfig.model||"gemini-2.0-flash"}:generateContent?key=${n}`,s=r.map(d=>({role:d.role==="model"?"model":"user",parts:[{text:d.content}]}));(s.length===0||s[s.length-1].parts[0]?.text!==t)&&s.push({role:"user",parts:[{text:t}]});let c={contents:s,generationConfig:{temperature:this.aiConfig.temperature??.7,maxOutputTokens:this.aiConfig.maxTokens??300}},l=i||this.aiConfig.systemPrompt;l&&l.trim()&&(c.systemInstruction={parts:[{text:l.trim()}]});let u=new AbortController,f=setTimeout(()=>u.abort(),7e3);try{let d=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(c),signal:u.signal});if(!d.ok){let w=await d.text();return this.logger.warn(`[HeadlessAutomation] Gemini API returned status ${d.status}: ${w.slice(0,200)}`),null}return(await d.json())?.candidates?.[0]?.content?.parts?.[0]?.text||null}finally{clearTimeout(f)}}async callOpenAiCompatible(t,r,n,i){let a=(this.aiConfig.baseUrl||(this.aiConfig.provider==="deepseek"?"https://api.deepseek.com/v1":"https://api.openai.com/v1")).replace(/\/+$/,"");a.includes("api.deepseek.com")&&!a.endsWith("/v1")?a+="/v1":(a.includes("11434")||a.includes("ollama"))&&(a=a.replace(/\/api$/,"").replace(/\/+$/,""),a.endsWith("/v1")||(a+="/v1"));let o=`${a}/chat/completions`,s=this.aiConfig.model||(this.aiConfig.provider==="deepseek"?"deepseek-chat":this.aiConfig.provider==="openai"?"gpt-4o-mini":"deepseek-chat"),c=i||this.aiConfig.systemPrompt,l=[...c&&c.trim()?[{role:"system",content:c.trim()}]:[],...r.map(h=>({role:h.role==="model"?"assistant":"user",content:h.content}))],u={"Content-Type":"application/json"};n&&(u.Authorization=`Bearer ${n}`);let f=new AbortController,d=setTimeout(()=>f.abort(),8e3);try{let h=await fetch(o,{method:"POST",headers:u,body:JSON.stringify({model:s,messages:l,temperature:this.aiConfig.temperature??.7,max_tokens:this.aiConfig.maxTokens??300}),signal:f.signal});if(!h.ok){let w=await h.text();return this.logger.warn(`[HeadlessAutomation] OpenAI-compatible API returned status ${h.status}: ${w.slice(0,200)}`),null}return(await h.json())?.choices?.[0]?.message?.content||null}finally{clearTimeout(d)}}async callAnthropic(t,r,n,i){let a="https://api.anthropic.com/v1/messages",o=this.aiConfig.model||"claude-3-5-haiku-20241022",s=r.map(u=>({role:u.role==="model"?"assistant":"user",content:u.content}));(s.length===0||s[s.length-1].content!==t)&&s.push({role:"user",content:t});let c=new AbortController,l=setTimeout(()=>c.abort(),8e3);try{let u=i||this.aiConfig.systemPrompt,f={model:o,messages:s,max_tokens:this.aiConfig.maxTokens??300,temperature:this.aiConfig.temperature??.7};u&&u.trim()&&(f.system=u.trim());let d=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":n,"anthropic-version":"2023-06-01"},body:JSON.stringify(f),signal:c.signal});if(!d.ok){let v=await d.text();return this.logger.warn(`[HeadlessAutomation] Anthropic API returned status ${d.status}: ${v.slice(0,200)}`),null}return(await d.json())?.content?.[0]?.text||null}finally{clearTimeout(l)}}clear(){this.campaigns.clear(),this.rules.clear(),this.threadHistory.clear(),this.lastReplyTimes.clear()}};var Jg=le(it()),Nc=class{logger;endpoint;projectId;apiKey;constructor(t,r){this.logger=t||(0,Jg.createLogger)("PushNotificationDispatcher"),this.endpoint=r?.endpoint||process.env.APPWRITE_ENDPOINT||"https://api.softty.net/v1",this.projectId=r?.projectId||process.env.APPWRITE_PROJECT_ID||"699cfc3100136099c1c1",this.apiKey=r?.apiKey||process.env.APPWRITE_API_KEY}formatMessagePreview(t){if(t.isRecall)return"[Tin nh\u1EAFn \u0111\xE3 \u0111\u01B0\u1EE3c thu h\u1ED3i]";let r=t.content,n=String(t.messageType||"").toLowerCase(),i=null;if(typeof r=="string"&&r.trim().startsWith("{")&&r.trim().endsWith("}"))try{i=JSON.parse(r)}catch{}else typeof r=="object"&&r!==null&&(i=r);let a=c=>!!(c&&(/\.(png|jpg|jpeg|gif|webp)(\?|#|$)/i.test(c)||c.includes("photo-stal")||c.includes("zdn.vn"))),o=c=>!!(c&&/\.(mp3|m4a|wav|aac|ogg|opus)(\?|#|$)/i.test(c)),s=c=>!!(c&&/\.(mp4|avi|mov|mkv|wmv|flv)(\?|#|$)/i.test(c));if(i){let c=String(i.msgType||i.type||n).toLowerCase(),l=String(i.title||i.fileName||i.filename||i.name||"").trim(),u=String(i.href||i.url||i.rawUrl||"");if(i.id&&(i.cateId!==void 0||i.type==="sticker")||c.includes("sticker"))return"[Nh\xE3n d\xE1n]";if(c.includes("photo")||c.includes("image")||a(u)||a(l))return l&&!l.startsWith("http")&&!a(l)?`[H\xECnh \u1EA3nh] ${l}`:"[H\xECnh \u1EA3nh]";if(c.includes("video")||s(l)||s(u))return l&&!l.startsWith("http")?`[Video] ${l}`:"[Video]";if(c.includes("voice")||c.includes("audio")||o(l)||o(u))return"[Tin nh\u1EAFn tho\u1EA1i]";if(c.includes("file")||i.fileSize!==void 0)return o(l)?"[Tin nh\u1EAFn tho\u1EA1i]":s(l)?`[Video] ${l}`:a(l)?`[H\xECnh \u1EA3nh] ${l}`:l?`[T\u1EADp tin] ${l}`:"[T\u1EADp tin]";if(c.includes("contact")||String(i.action||"").includes("recommended.user"))return l?`[Danh thi\u1EBFp] ${l}`:"[Danh thi\u1EBFp]";if(c.includes("location")||i.lat!==void 0)return i.address||l?`[V\u1ECB tr\xED] ${i.address||l}`:"[V\u1ECB tr\xED]";if(c.includes("poll"))return i.question||i.topic?`[B\xECnh ch\u1ECDn] ${i.question||i.topic}`:"[B\xECnh ch\u1ECDn]";if(c.includes("bank"))return"[Th\xF4ng tin chuy\u1EC3n kho\u1EA3n]";if(c.includes("link"))return l&&!l.startsWith("http")?`[Li\xEAn k\u1EBFt] ${l}`:"[Li\xEAn k\u1EBFt]";if(i.text||i.msg||i.message)return String(i.text||i.msg||i.message)}if(n==="image"||n.includes("photo"))return"[H\xECnh \u1EA3nh]";if(n==="video")return"[Video]";if(n==="audio"||n.includes("voice"))return"[Tin nh\u1EAFn tho\u1EA1i]";if(n==="file")return"[T\u1EADp tin]";if(n==="sticker")return"[Nh\xE3n d\xE1n]";if(n==="location")return"[V\u1ECB tr\xED]";if(n==="contact")return"[Danh thi\u1EBFp]";if(typeof r=="string"){let c=r.trim();return c?a(c)?"[H\xECnh \u1EA3nh]":c.startsWith("{")&&c.endsWith("}")?c.includes("photo-stal")?"[H\xECnh \u1EA3nh]":"[\u0110\xEDnh k\xE8m ph\u01B0\u01A1ng ti\u1EC7n]":c.length>120?`${c.slice(0,117)}...`:c:"\u0110\xE3 g\u1EEDi m\u1ED9t tin nh\u1EAFn m\u1EDBi"}return"\u0110\xE3 g\u1EEDi m\u1ED9t tin nh\u1EAFn m\u1EDBi"}async dispatchMessageAlert(t,r,n,i){if(r.isRecall||r.deleted_at)return!1;let a=r.timestamp??r.time,o=Number(a||0);if(o>0){let h=o<1e11?o*1e3:o,v=Date.now()-h;if(v>12e4||v<-6e4)return this.logger.debug(`Suppressed stale push alert for message ${r.id} (age: ${Math.round(v/1e3)}s)`),!1}let s=r.metadata?.rawPayload||r.rawPayload||r,c=!!(r.isGroup||s?.isGroup||Number(s?.type)===1||Number(s?.data?.type)===1||s?.groupId||s?.data?.groupId||r.type==="group"||r.threadType===1||r.threadType==="group"||String(r.threadId||"").startsWith("g")),l=r.groupName||r.threadName||s?.groupName||s?.data?.groupName||"Nh\xF3m Zalo",u=this.formatMessagePreview(r),f=c?l:r.senderName||"Kh\xE1ch h\xE0ng",d=c?`${r.senderName||"Th\xE0nh vi\xEAn"}: ${u}`:u;return d.length>130&&(d=`${d.slice(0,127)}...`),this.sendNotification({recipientToken:t,title:f,body:d,platform:n,userId:i,data:{messageId:r.id,threadId:r.threadId,platform:r.platform,accountId:r.accountId}})}async enqueueNotification(t,r,n){if(t.isSelf||t.isRecall||t.deleted_at)return!1;let i=t.timestamp??t.time,a=Number(i||0);if(a>0){let v=a<1e11?a*1e3:a,w=Date.now()-v;if(w>12e4||w<-6e4)return this.logger.debug(`Suppressed stale push alert for message ${t.id} (age: ${Math.round(w/1e3)}s)`),!1}let o=t.metadata?.rawPayload||t.rawPayload||t,s=!!(t.isGroup||o?.isGroup||Number(o?.type)===1||Number(o?.data?.type)===1||o?.groupId||o?.data?.groupId||t.type==="group"||t.threadType===1||t.threadType==="group"||String(t.threadId||"").startsWith("g")),c=t.groupName||t.threadName||o?.groupName||o?.data?.groupName||"Nh\xF3m Zalo",l=this.formatMessagePreview(t),u=s?c:t.senderName||"Kh\xE1ch h\xE0ng",f=s?`${t.senderName||"Th\xE0nh vi\xEAn"}: ${l}`:l;f.length>130&&(f=`${f.slice(0,127)}...`);let d=`pn_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,h=(s?t.groupAvatar||o?.groupAvatar||o?.data?.groupAvatar:void 0)||t.avatar||t.senderAvatar||t.groupAvatar||"";try{return await r.createDocument("push_notification_queue",d,{teamId:n.teamId||"",userId:n.userId||"",channelAccountId:n.channelAccountId||t.accountId||"",title:u,body:f,avatarUrl:h,threadId:t.threadId||t.conversationId||"",platform:t.platform||"zalo",msgId:t.id||d}),this.logger.debug(`Enqueued push notification ${d} for message ${t.id}`),!0}catch(v){return this.logger.warn(`Failed to enqueue push notification: ${v?.message}`),!1}}async sendNotification(t){if(this.logger.debug(`Dispatching push notification to device token: ${t.recipientToken.slice(0,8)}...`),t.recipientToken.startsWith("ExponentPushToken")||t.recipientToken.startsWith("ExpoPushToken"))try{return(await fetch("https://exp.host/--/api/v2/push/send",{method:"POST",headers:{Accept:"application/json","Accept-encoding":"gzip, deflate","Content-Type":"application/json"},body:JSON.stringify({to:t.recipientToken,title:t.title,body:t.body,data:t.data,sound:"default",priority:"high",channelId:"default"})})).ok}catch(r){this.logger.warn(`Expo push send error: ${r?.message}`)}if(this.apiKey)try{let r=t.platform==="ios"||t.recipientToken.length===64,n=t.recipientToken.replace(/[^a-zA-Z0-9]/g,""),i=`${r?"apns":"fcm"}_${n.slice(0,31)}`,a=`${this.endpoint}/messaging/messages/push`;if((await fetch(a,{method:"POST",headers:{"Content-Type":"application/json","X-Appwrite-Project":this.projectId,"X-Appwrite-Key":this.apiKey},body:JSON.stringify({messageId:`push_${Date.now()}_${Math.random().toString(36).slice(2,7)}`,title:t.title,body:t.body,data:t.data||{},targets:[i],draft:!1})})).ok)return!0}catch(r){this.logger.warn(`Appwrite push send error: ${r?.message}`)}return!0}};var GP=le(require("http")),VP=require("url"),JP=le(it());var WP=le(it()),wo=class{static logger=(0,WP.createLogger)("ChannelRunnerFactory");static async createRunner(t,r,n,i){let a=(t||"zalo").toLowerCase(),o=a==="web"||a.includes("zalo")?"zalo":a;try{if(o==="zalo"){let{ZaloChannelRunner:s}=await Promise.resolve().then(()=>(HP(),qP));return new s(r,n,i)}return this.logger.warn(`Unsupported platform for ChannelRunner: ${t}`),null}catch(s){return this.logger.error(`Failed to dynamically initialize runner for ${o}:${r}:`,s?.message||s),null}}};var Fp=class{constructor(t,r,n,i,a){this.port=t;this.engine=r;this.lockManager=n;this.deltaQueue=i;this.logger=a||(0,JP.createLogger)("WorkerHttpServer")}logger;server=null;async start(){if(!this.server)return new Promise((t,r)=>{this.server=GP.default.createServer((n,i)=>{this.handleRequest(n,i).catch(a=>{this.logger.error("Unhandled HTTP error:",a),i.headersSent||(i.writeHead(500,{"Content-Type":"application/json"}),i.end(JSON.stringify({error:"Internal Server Error"})))})}),this.server.listen(this.port,()=>{this.logger.info(`\u{1F680} Worker HTTP Server listening on port ${this.port}`),t()}),this.server.on("error",n=>{this.logger.error(`Worker HTTP Server error on port ${this.port}:`,n),r(n)})})}async stop(){if(this.server)return new Promise(t=>{this.server?.close(()=>{this.logger.info("Worker HTTP Server closed."),this.server=null,t()})})}async handleRequest(t,r){let n=new VP.URL(t.url||"/",`http://${t.headers.host||"localhost"}`),i=n.pathname,a=(t.method||"GET").toUpperCase();if(r.setHeader("Access-Control-Allow-Origin","*"),r.setHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS"),r.setHeader("Access-Control-Allow-Headers","Content-Type, X-Softty-User-Id, X-Desktop-Secret, Authorization"),a==="OPTIONS"){r.writeHead(204),r.end();return}if(a==="GET"&&i==="/health"){let o=this.engine.getMetrics();r.writeHead(200,{"Content-Type":"application/json"}),r.end(JSON.stringify({status:"healthy",timestamp:Date.now(),pendingDeltaMessages:this.deltaQueue.getCount(),metrics:o}));return}if(i.startsWith("/api/v1/")){let o=this.engine.config.desktopSecret;if(o){let s=t.headers["x-desktop-secret"]||t.headers.authorization;if((typeof s=="string"&&s.startsWith("Bearer ")?s.slice(7):s)!==o){r.writeHead(401,{"Content-Type":"application/json"}),r.end(JSON.stringify({error:"Unauthorized: Invalid or missing X-Desktop-Secret"}));return}}}if(a==="POST"&&i==="/api/v1/sentinel/handover"){let o=await this.readJsonBody(t),{deviceId:s,sessions:c,aiConfig:l}=o||{};if(l&&(this.engine.automationEngine.configure(l),this.logger.info(`[Handover] Configured 24/7 AI automation engine with provider: ${l.provider||"gemini"}, model: ${l.model||"default"}`)),!Array.isArray(c)){r.writeHead(400,{"Content-Type":"application/json"}),r.end(JSON.stringify({error:"Invalid sessions array payload"}));return}this.logger.info(`[Handover] Received handover request from device ${s||"unknown"} with ${c.length} sessions.`);let u=0;for(let f of c){if(!f.id||!f.nightWorkerEnabled)continue;if(!this.lockManager.acquireLock(f.id,`worker_${f.id}`)){this.logger.warn(`Skipping account ${f.id} because lock was not acquired.`);continue}let h=(f.platform||"zalo").toLowerCase(),v=h==="web"||h.includes("zalo")?"zalo":h,w=await wo.createRunner(v,f.id,f.sessionData);w&&(this.engine.registerRunner(w),await w.start(),this.engine.registerAccount({id:f.id,platform:v,accountName:f.accountName||f.id,status:"active",nightWorkerEnabled:!0}),u++)}r.writeHead(200,{"Content-Type":"application/json"}),r.end(JSON.stringify({success:!0,message:"Sessions handed over successfully",activatedCount:u,timestamp:Date.now()}));return}if(a==="POST"&&i==="/api/v1/sentinel/reclaim"){let o=await this.readJsonBody(t),{deviceId:s}=o||{};this.logger.info(`[Reclaim] Master device ${s||"desktop"} reclaiming all active sessions. Stopping cloud runners...`);let c=this.engine.channelRunnerRegistry.getCount();await this.engine.channelRunnerRegistry.stopAll(),this.lockManager.releaseAllForOwner("worker"),r.writeHead(200,{"Content-Type":"application/json"}),r.end(JSON.stringify({success:!0,reclaimedCount:c,timestamp:Date.now()}));return}if(i==="/api/v1/sentinel/night-config"){if(a==="POST"){let o=await this.readJsonBody(t);o&&(this.engine.automationEngine.configure(o),this.logger.info(`[NightConfig] Updated 24/7 AI config dynamically: provider=${o.provider||"gemini"}, model=${o.model||"default"}`)),r.writeHead(200,{"Content-Type":"application/json"}),r.end(JSON.stringify({success:!0,config:this.engine.automationEngine.getAiConfig()}));return}else if(a==="GET"){r.writeHead(200,{"Content-Type":"application/json"}),r.end(JSON.stringify({success:!0,config:this.engine.automationEngine.getAiConfig()}));return}}if(a==="GET"&&i==="/api/v1/sync/delta"){let o=n.searchParams.get("accountId")||void 0,s=parseInt(n.searchParams.get("since")||"0",10),c=this.deltaQueue.getDeltas(o,s);this.logger.info(`[DeltaSync] Serving ${c.length} night messages (since: ${s}, account: ${o||"all"})`),r.writeHead(200,{"Content-Type":"application/json"}),r.end(JSON.stringify({success:!0,messages:c,count:c.length,syncedTimestamp:Date.now()}));return}r.writeHead(404,{"Content-Type":"application/json"}),r.end(JSON.stringify({error:"Endpoint not found"}))}readJsonBody(t){return new Promise(r=>{let n="";t.on("data",i=>{n+=i}),t.on("end",()=>{try{r(JSON.parse(n))}catch{r({})}})})}};var pa=le(it());var Dp=le(require("fs")),P0=le(require("path")),_o=require("child_process"),QP=le(it());var yt=le(require("fs")),ZP=le(require("os")),ua=le(require("path")),KP=le(require("zlib")),R0=le(require("crypto")),YP=le(require("module")),XP=le(it()),T0="__ZPLUS_RUNTIME_BOOTSTRAPPED__",ki=class{static PACKAGE_NAME="@softtynet/zplus-worker";static getRuntimeDir(){let t=process.env.ZPLUS_HOME||process.env.DATA_DIR||ua.default.join(ZP.default.homedir(),".zplus");return ua.default.join(t,"runtime")}static getRuntimeCliPath(){return ua.default.join(this.getRuntimeDir(),"cli.js")}static getRuntimeVersionPath(){return ua.default.join(this.getRuntimeDir(),"version.json")}static isNewerVersion(t,r){let n=u=>u.replace(/^v/,"").trim().split("-")[0].split(".").map(f=>parseInt(f,10)||0),[i=0,a=0,o=0]=n(t),[s=0,c=0,l=0]=n(r);return i!==s?i>s:a!==c?a>c:o>l}static getInstalledRuntimeVersion(){try{let t=this.getRuntimeVersionPath(),r=this.getRuntimeCliPath();if(!yt.default.existsSync(t)||!yt.default.existsSync(r)||yt.default.statSync(r).size<1024)return null;let n=JSON.parse(yt.default.readFileSync(t,"utf-8"));return n?.version?String(n.version).trim():null}catch{return null}}static extractFileFromTarGz(t,r="package/dist/cli.js"){let n=KP.default.gunzipSync(t),i=0;for(;i+512<=n.length;){let a=n.subarray(i,i+512);if(a.every(w=>w===0))break;let o=(w,k)=>a.subarray(w,k).toString("utf-8").replace(/\0.*$/,"").trim(),s=o(0,100),c=o(345,500),l=c?`${c}/${s}`:s,u=parseInt(o(124,136),8)||0,f=a[156],d=f===0||f===48,h=i+512,v=h+u;if(d&&u>0&&v<=n.length&&(l===r||l.endsWith("/dist/cli.js")))return Buffer.from(n.subarray(h,v));i=h+Math.ceil(u/512)*512}return null}static async downloadAndInstallRuntimeBundle(t="latest",r=(0,XP.createLogger)("RuntimeBundleManager")){try{let n=t.replace(/^v/,"").trim()||"latest",i=await fetch(`https://registry.npmjs.org/${this.PACKAGE_NAME}/${n}`,{headers:{Accept:"application/json"},signal:AbortSignal.timeout(1e4)});if(!i.ok)throw new Error(`NPM Registry metadata HTTP ${i.status}`);let a=await i.json(),o=String(a?.version||"").trim(),s=String(a?.dist?.tarball||"").trim(),c=String(a?.dist?.shasum||"").trim(),l=String(a?.dist?.integrity||"").trim();if(!o||!s)throw new Error("Thi\u1EBFu th\xF4ng tin version ho\u1EB7c tarball t\u1EEB NPM Registry");let u=await fetch(s,{signal:AbortSignal.timeout(6e4)});if(!u.ok)throw new Error(`T\u1EA3i tarball th\u1EA5t b\u1EA1i: HTTP ${u.status}`);let f=Buffer.from(await u.arrayBuffer());if(l.startsWith("sha512-")){let b=l.slice(7);if(R0.default.createHash("sha512").update(f).digest("base64")!==b)throw new Error("M\xE3 ki\u1EC3m tra to\xE0n v\u1EB9n SHA-512 kh\xF4ng kh\u1EDBp!")}else if(c&&R0.default.createHash("sha1").update(f).digest("hex")!==c)throw new Error("M\xE3 ki\u1EC3m tra to\xE0n v\u1EB9n SHA-1 (shasum) kh\xF4ng kh\u1EDBp!");let d=this.extractFileFromTarGz(f,"package/dist/cli.js");if(!d||d.length<1024)throw new Error("Kh\xF4ng t\xECm th\u1EA5y ho\u1EB7c t\u1EC7p dist/cli.js trong g\xF3i kh\xF4ng h\u1EE3p l\u1EC7");let h=this.getRuntimeDir();yt.default.existsSync(h)||yt.default.mkdirSync(h,{recursive:!0});let v=this.getRuntimeCliPath(),w=`${v}.${process.pid}.tmp`;yt.default.writeFileSync(w,d,{mode:493}),yt.default.renameSync(w,v);let k={version:o,updatedAt:new Date().toISOString(),integrity:l||c},m=`${this.getRuntimeVersionPath()}.${process.pid}.tmp`;yt.default.writeFileSync(m,JSON.stringify(k,null,2)),yt.default.renameSync(m,this.getRuntimeVersionPath());let x="/app/cli.js";if(yt.default.existsSync(x))try{yt.default.accessSync(x,yt.default.constants.W_OK);try{let b=`${x}.${process.pid}.tmp`;yt.default.writeFileSync(b,d,{mode:493}),yt.default.renameSync(b,x)}catch{yt.default.writeFileSync(x,d,{mode:493})}}catch{}return r.info(`\u{1F4E6} [RuntimeBundle] \u0110\xE3 t\u1EA3i v\xE0 x\xE1c th\u1EF1c g\xF3i v${o} v\xE0o b\u1ED9 nh\u1EDB b\u1EC1n v\u1EEFng (${v})`),{success:!0,version:o,cliPath:v}}catch(n){return r.warn(`\u26A0\uFE0F [RuntimeBundle] Kh\xF4ng th\u1EC3 t\u1EA3i tr\u1EF1c ti\u1EBFp bundle t\u1EEB Registry: ${n?.message||n}`),{success:!1}}}static tryBootstrapNewerRuntime(t){if(globalThis[T0])return!1;try{let r=this.getInstalledRuntimeVersion();if(!r||!this.isNewerVersion(r,t))return!1;let n=this.getRuntimeCliPath();return ua.default.resolve(process.argv[1]||"")===ua.default.resolve(n)?!1:(globalThis[T0]=r,YP.default.createRequire(n)(n),!0)}catch{globalThis[T0]=void 0;try{yt.default.existsSync(this.getRuntimeVersionPath())&&yt.default.unlinkSync(this.getRuntimeVersionPath())}catch{}return!1}}};var Bp=class e{logger;timer;isUpdating=!1;constructor(t){this.logger=t||(0,QP.createLogger)("WorkerAutoUpdater")}static getNpmExecutionInfo(){let t=P0.default.dirname(process.execPath),r=P0.default.join(t,process.platform==="win32"?"npm.cmd":"npm"),n=Dp.default.existsSync(r)?`"${r}"`:"npm",i={...process.env,PATH:`${t}:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:${process.env.PATH||""}`};return{npmBin:n,env:i}}static isDocker(){return Dp.default.existsSync("/.dockerenv")||Dp.default.existsSync("/run/.containerenv")||!!process.env.DOCKER_CONTAINER}static isNewerVersion(t,r){return ki.isNewerVersion(t,r)}async fetchLatestVersion(){let t="@softtynet/zplus-worker";try{let r=new AbortController,n=setTimeout(()=>r.abort(),5e3),i=await fetch(`https://registry.npmjs.org/${t}/latest`,{signal:r.signal,headers:{Accept:"application/json"}});if(clearTimeout(n),i.ok){let a=await i.json();if(a?.version)return String(a.version).trim()}}catch{}try{let{npmBin:r,env:n}=e.getNpmExecutionInfo();return(0,_o.execSync)(`${r} view ${t} version`,{encoding:"utf-8",timeout:8e3,stdio:["ignore","pipe","ignore"],env:n}).trim()}catch{return null}}async checkUpdate(t){let r=await this.fetchLatestVersion();return r?{hasUpdate:e.isNewerVersion(r,t),latestVersion:r}:{hasUpdate:!1,latestVersion:t}}async performUpdateAndRestart(t){if(this.isUpdating)return this.logger.warn("C\u1EADp nh\u1EADt \u0111ang di\u1EC5n ra, b\u1ECF qua y\xEAu c\u1EA7u tr\xF9ng l\u1EB7p."),!1;this.isUpdating=!0;let r=t||"latest",n=`@softtynet/zplus-worker@${r}`,i=e.isDocker();this.logger.info(`\u{1F680} [AutoUpdater] B\u1EAFt \u0111\u1EA7u t\u1EF1 \u0111\u1ED9ng n\xE2ng c\u1EA5p Worker l\xEAn ${n} (M\xF4i tr\u01B0\u1EDDng: ${i?"Docker Container":"Host NPM"})...`);let a=!1,o=!1;try{if(a=(await ki.downloadAndInstallRuntimeBundle(r,this.logger)).success,!i)try{let{npmBin:c,env:l}=e.getNpmExecutionInfo();(0,_o.execSync)(`${c} install -g ${n}`,{stdio:"inherit",timeout:12e4,env:l}),o=!0,this.logger.info(`\u2705 [AutoUpdater] \u0110\xE3 c\u1EADp nh\u1EADt g\xF3i NPM to\xE0n c\u1EE5c: ${n}!`)}catch(c){if(a)this.logger.info("\u2139\uFE0F [AutoUpdater] B\u1ECF qua c\u1EADp nh\u1EADt global npm (thi\u1EBFu quy\u1EC1n root), \u0111\xE3 s\u1EED d\u1EE5ng Runtime Bundle t\u1EA1i ~/.zplus/runtime/cli.js.");else throw c}if(!a&&!o)throw new Error("Kh\xF4ng th\u1EC3 c\u1EADp nh\u1EADt qua c\u1EA3 Runtime Bundle l\u1EABn NPM Global.");return this.logger.info(`\u2705 [AutoUpdater] \u0110\xE3 ho\xE0n t\u1EA5t n\xE2ng c\u1EA5p l\xEAn ${n}! \u0110ang kh\u1EDFi \u0111\u1ED9ng l\u1EA1i d\u1ECBch v\u1EE5...`),this.triggerRestart(),!0}catch(s){return this.isUpdating=!1,this.logger.error(`\u274C [AutoUpdater] N\xE2ng c\u1EA5p th\u1EA5t b\u1EA1i: ${s?.message||s}`),!1}}triggerRestart(){if(!e.isDocker()){try{if((0,_o.execSync)("pm2 jlist",{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:5e3}).includes("zplus-worker")){this.logger.info("\u{1F504} [AutoUpdater] \u0110ang ph\xE1t l\u1EC7nh kh\u1EDFi \u0111\u1ED9ng l\u1EA1i PM2 ti\u1EBFn tr\xECnh 'zplus-worker'...");let n=(0,_o.spawn)("pm2",["restart","zplus-worker"],{detached:!0,stdio:"ignore"});n.on("error",()=>{}),n.unref(),setTimeout(()=>process.exit(0),1e3);return}}catch{}if(!!process.stdout.isTTY&&!process.env.PM2_HOME&&!process.env.pm_id&&!process.env.INVOCATION_ID){this.logger.warn("\u26A0\uFE0F [AutoUpdater] \u0110\xE3 t\u1EA3i phi\xEAn b\u1EA3n m\u1EDBi. V\xEC \u0111ang ch\u1EA1y Worker tr\u1EF1c ti\u1EBFp tr\xEAn Terminal (kh\xF4ng qua PM2/Daemon), vui l\xF2ng nh\u1EA5n Ctrl+C v\xE0 ch\u1EA1y l\u1EA1i \u0111\u1EC3 n\u1EA1p m\xE3 m\u1EDBi."),this.isUpdating=!1;return}}this.logger.info("\u{1F504} [AutoUpdater] Ti\u1EBFn tr\xECnh s\u1EBD tho\xE1t an to\xE0n (exit 0) \u0111\u1EC3 h\u1EC7 th\u1ED1ng (Docker / OS Service) t\u1EF1 kh\u1EDFi \u0111\u1ED9ng l\u1EA1i v\u1EDBi b\u1EA3n m\u1EDBi..."),setTimeout(()=>process.exit(0),1500)}startPeriodicAutoUpdate(t,r=3600*1e3){this.timer&&clearInterval(this.timer),setTimeout(()=>this.runCheckCycle(t).catch(()=>{}),6e4),this.timer=setInterval(()=>this.runCheckCycle(t).catch(()=>{}),r),this.logger.info(`\u23F0 [AutoUpdater] \u0110\xE3 k\xEDch ho\u1EA1t c\u01A1 ch\u1EBF t\u1EF1 \u0111\u1ED9ng c\u1EADp nh\u1EADt ng\u1EA7m cho c\u1EA3 NPM & Docker (chu k\u1EF3: ${Math.round(r/6e4)} ph\xFAt).`)}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0)}async runCheckCycle(t){try{let{hasUpdate:r,latestVersion:n}=await this.checkUpdate(t);r&&(this.logger.info(`\u{1F514} [AutoUpdater] Ph\xE1t hi\u1EC7n phi\xEAn b\u1EA3n m\u1EDBi tr\xEAn NPM Registry: v${n} (hi\u1EC7n t\u1EA1i: v${t}). \u0110ang t\u1EF1 \u0111\u1ED9ng n\xE2ng c\u1EA5p...`),await this.performUpdateAndRestart(n))}catch(r){this.logger.debug("Auto-update check cycle error:",r?.message)}}};var Jn=le(require("fs")),Np=le(require("path")),Lp=le(require("os")),e4=le(require("readline")),kn=le(it()),ko=class{logger;lastReconciledToken="";lastReconciledAt=0;constructor(t){this.logger=t||(0,kn.createLogger)("WorkerAuthManager")}getWorkerDeviceKey(){let r=(process.env.WORKER_ID||process.env.HOSTNAME||Lp.default.hostname()||"default").replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,48);return r.startsWith("worker_")?r:`worker_${r}`}async reconcileWorkerSession(t,r=process.env.APPWRITE_ENDPOINT||"https://api.softty.net/v1",n=process.env.APPWRITE_PROJECT_ID||"699cfc3100136099c1c1",i=!1){if(!t)return;let a=Date.now();if(!(!i&&this.lastReconciledToken===t&&a-this.lastReconciledAt<1800*1e3))try{let o=this.getWorkerDeviceKey();(await kn.AppwriteSessionJanitor.reconcileDeviceSession({endpoint:r,projectId:n,sessionSecret:t,deviceKey:o,deviceType:"worker",deviceName:`ZPlus Worker (${Lp.default.hostname()})`,pinned:!0})).currentSessionId&&(this.lastReconciledToken=t,this.lastReconciledAt=a)}catch(o){this.logger.debug("reconcileWorkerSession warning:",o?.message)}}extractSessionTokenFromResponse(t,r){let n=r?.secret||"";if(!n&&t?.headers?.get&&(n=t.headers.get("x-appwrite-session")||""),!n&&t?.headers){let i=typeof t.headers.getSetCookie=="function"?t.headers.getSetCookie():[t.headers.get&&t.headers.get("set-cookie")||""];for(let a of i){let o=a.match(/a_session_[^=]+=([^;]+)/);if(o&&o[1]){n=decodeURIComponent(o[1]);break}}}if(!n&&t?.headers?.get)try{let i=t.headers.get("x-fallback-cookies");if(i){let a=JSON.parse(i);for(let o of Object.keys(a))if(o.startsWith("a_session_")){n=a[o];break}}}catch{}return n}syncRecoveryTokenFromCloud(t){if(!t||typeof t!="string")return;let r=this.loadStoredAuth();if(r){if(r.authType==="cluster_session"||r.authType==="credentials"){r.refreshToken&&(delete r.refreshToken,this.saveAuth(r));return}r.refreshToken!==t&&(r.refreshToken=t,this.saveAuth(r),this.logger.info("\u{1F504} [AuthManager] \u0110\xE3 \u0111\u1ED3ng b\u1ED9 ch\xECa kh\xF3a ph\u1EE5c h\u1ED3i phi\xEAn 24/7 m\u1EDBi nh\u1EA5t t\u1EEB Cloud."))}}getAuthFilePath(){let t=process.env.DATA_DIR||Np.default.join(Lp.default.homedir(),".zplus");return Np.default.join(t,"worker_auth.json")}loadStoredAuth(){try{let t=this.getAuthFilePath();if(!Jn.default.existsSync(t))return null;let r=Jn.default.readFileSync(t,"utf-8"),n=JSON.parse(r);return!n||!n.sessionToken?null:n}catch(t){return this.logger.debug("Failed to read worker_auth.json:",t?.message),null}}saveAuth(t){try{let r=this.getAuthFilePath(),n=Np.default.dirname(r);Jn.default.existsSync(n)||Jn.default.mkdirSync(n,{recursive:!0,mode:448}),Jn.default.writeFileSync(r,JSON.stringify(t,null,2),{encoding:"utf-8",mode:384});try{Jn.default.chmodSync(r,384)}catch{}this.logger.info(`\u2705 Phi\xEAn x\xE1c th\u1EF1c \u0111\xE3 \u0111\u01B0\u1EE3c l\u01B0u an to\xE0n t\u1EA1i: ${r} (Quy\u1EC1n 0600 - Ch\u1EC9 Owner)`)}catch(r){this.logger.error("Could not save worker_auth.json:",r)}}clearAuth(t=process.env.APPWRITE_ENDPOINT||"https://api.softty.net/v1",r=process.env.APPWRITE_PROJECT_ID||"699cfc3100136099c1c1"){try{let n=this.loadStoredAuth();n?.sessionToken&&kn.AppwriteSessionJanitor.revokeCurrentDeviceSession({endpoint:t,projectId:r,sessionSecret:n.sessionToken,deviceKey:this.getWorkerDeviceKey()}).catch(()=>{});let i=this.getAuthFilePath();Jn.default.existsSync(i)&&Jn.default.unlinkSync(i),this.logger.info("\u0110\xE3 x\xF3a phi\xEAn \u0111\u0103ng nh\u1EADp c\u1EE7a Worker.")}catch(n){this.logger.debug("clearAuth error:",n?.message)}}async verifyEntitlements(t,r=process.env.APPWRITE_ENDPOINT||"https://api.softty.net/v1",n=process.env.APPWRITE_PROJECT_ID||"699cfc3100136099c1c1",i="default"){try{let a=`${r}/account`,o=t.includes(".")&&t.split(".").length===3,s={"Content-Type":"application/json","X-Appwrite-Project":n};o?s["X-Appwrite-JWT"]=t:(s["X-Appwrite-Session"]=t,s.Cookie=`a_session_${n}=${t}; a_session_${n}_legacy=${t}`,t.startsWith("eyJ")&&(s["X-Fallback-Cookies"]=JSON.stringify({[`a_session_${n}`]:t,[`a_session_${n}_legacy`]:t})));let c=await fetch(a,{method:"GET",headers:s});if(!c.ok)return{allowed:!1,userId:"",userName:"Unknown",email:"",teamId:i,isOwner:!1,isPremium:!1,reason:`Phi\xEAn \u0111\u0103ng nh\u1EADp kh\xF4ng h\u1EE3p l\u1EC7 ho\u1EB7c \u0111\xE3 h\u1EBFt h\u1EA1n (HTTP ${c.status}).`};let l=await c.json(),u=l.$id||l.id||"",f=l.name||"Ng\u01B0\u1EDDi d\xF9ng ZPlus",d=l.email||"",h=Array.isArray(l.labels)?l.labels:[],v=l.prefs||{},w=kn.AppwriteSessionJanitor.parseRegistry(v),k=this.getWorkerDeviceKey();(!w[k]?.sessionId||!w[k]?.pinned)&&(this.lastReconciledAt=0);let m=null;if(v.entitlements)try{m=typeof v.entitlements=="string"?JSON.parse(v.entitlements):v.entitlements}catch{}if(!m&&l.entitlements)try{m=typeof l.entitlements=="string"?JSON.parse(l.entitlements):l.entitlements}catch{}let x=!1;for(let[G,ee]of Object.entries(v))if(G.endsWith("_entitlements")&&typeof ee=="string")try{let X=JSON.parse(ee);if(Array.isArray(X.features))for(let pe of X.features){let ue=String(pe).toUpperCase();if(ue.includes("PREMIUM")||ue.includes("ENTERPRISE")){x=!0;break}}}catch{}let y=!h.some(G=>G.toLowerCase()==="member")&&v.isOwner!==!1,S=!(h.some(G=>G.toLowerCase()==="free")||v.tier==="free"||m?.tier==="FREE"||m?.isPremium===!1)&&!!(x||(m?.isPremium??v.isPremium??h.some(G=>G.toLowerCase()==="premium"||G.toLowerCase()==="enterprise"))),R=!S,B=S?-1:Number(m?.cloudTtlDays||v.cloudTtlDays||7),T=S?!0:m?.allowedCloudSync!==!1&&v.allowedCloudSync!==!1,z=v.teamId||v.storage?.teamId||m?.storage?.teamId||l.teamId||i;(!z||z==="default")&&m?.storage?.teamId&&(z=m.storage.teamId);let F=v.teamName||m?.teamName||"";try{let G=await fetch(`${r}/teams`,{method:"GET",headers:s});if(G.ok){let ee=await G.json().catch(()=>({})),X=Array.isArray(ee.teams)?ee.teams:[];if(X.length>0){let pe=z&&z!=="default"&&X.find(ue=>ue.$id===z)||X[0];pe&&((!z||z==="default")&&(z=pe.$id),F=pe.name||F)}}}catch{}return(!z||z==="default")&&(z=u||i),R?{allowed:T,userId:u,userName:f,email:d,teamId:z,teamName:F||void 0,isOwner:y,isPremium:!1,cloudTtlDays:B,reason:T?`\u2705 X\xE1c th\u1EF1c th\xE0nh c\xF4ng: T\xE0i kho\u1EA3n Mi\u1EC5n Ph\xED [${f}] (${d}) - Ch\u1EBF \u0111\u1ED9 \u0110\u1EC7m Cloud ${B} ng\xE0y (T\u1ED1i \u0111a 5 t\xE0i kho\u1EA3n).`:"\u26A0\uFE0F Ch\u1EBF \u0111\u1ED9 \u0111\u1EC7m Cloud t\u1EA1m th\u1EDDi b\u1ECB t\u1EAFt b\u1EDFi Qu\u1EA3n tr\u1ECB vi\xEAn Softty."}:y?{allowed:!0,userId:u,userName:f,email:d,teamId:z,teamName:F||void 0,isOwner:!0,isPremium:!0,cloudTtlDays:-1,reason:`\u2705 X\xE1c th\u1EF1c th\xE0nh c\xF4ng: Tr\u01B0\u1EDFng nh\xF3m [${f}] (${d}) - G\xF3i Doanh Nghi\u1EC7p Active.`}:{allowed:!1,userId:u,userName:f,email:d,teamId:z,teamName:F||void 0,isOwner:!1,isPremium:S,cloudTtlDays:-1,reason:`\u26A0\uFE0F T\xE0i kho\u1EA3n [${d}] l\xE0 Th\xE0nh vi\xEAn (Member). \u0110\u1EC3 b\u1EA3o v\u1EC7 d\u1EEF li\u1EC7u c\xF4ng ty, ch\u1EC9 Tr\u01B0\u1EDFng nh\xF3m (Team Owner) m\u1EDBi c\xF3 quy\u1EC1n k\xEDch ho\u1EA1t c\u1EE5m Worker cho Team.`}}catch(a){return{allowed:!1,userId:"",userName:"Unknown",email:"",teamId:i,isOwner:!1,isPremium:!1,reason:`L\u1ED7i k\u1EBFt n\u1ED1i ki\u1EC3m tra quy\u1EC1n h\u1EA1n: ${a?.message}`}}}async loginWithCredentials(t,r,n=process.env.APPWRITE_ENDPOINT||"https://api.softty.net/v1",i=process.env.APPWRITE_PROJECT_ID||"699cfc3100136099c1c1"){let a=t?.trim(),o=r;if(!a||!o){console.log(`
57
+ `),n=!1,i=!1,a;e.on("response",o=>{let{headers:s}=o;n=s["transfer-encoding"]==="chunked"&&!s["content-length"]}),e.on("socket",o=>{let s=()=>{if(n&&!i){let l=new Error("Premature close");l.code="ERR_STREAM_PREMATURE_CLOSE",t(l)}},c=l=>{i=Gs.Buffer.compare(l.slice(-5),r)===0,!i&&a&&(i=Gs.Buffer.compare(a.slice(-3),r.slice(0,3))===0&&Gs.Buffer.compare(l.slice(-2),r.slice(3))===0),a=l};o.prependListener("close",s),o.on("data",c),e.on("close",()=>{o.removeListener("close",s),o.removeListener("data",c)})})}var CP,IP,la,mr,Gs,mq,TP=L(()=>{CP=le(require("node:http"),1),IP=le(require("node:https"),1),la=le(require("node:zlib"),1),mr=le(require("node:stream"),1),Gs=require("node:buffer");GR();kp();dP();Ep();EP();h0();AP();w0();mp();xp();_0();g0();mq=new Set(["data:","http:","https:"])});var PP=N((zae,k0)=>{"use strict";var yq=Object.prototype.hasOwnProperty,Wt="~";function Js(){}Object.create&&(Js.prototype=Object.create(null),new Js().__proto__||(Wt=!1));function xq(e,t,r){this.fn=e,this.context=t,this.once=r||!1}function RP(e,t,r,n,i){if(typeof r!="function")throw new TypeError("The listener must be a function");var a=new xq(r,n||e,i),o=Wt?Wt+t:t;return e._events[o]?e._events[o].fn?e._events[o]=[e._events[o],a]:e._events[o].push(a):(e._events[o]=a,e._eventsCount++),e}function Ip(e,t){--e._eventsCount===0?e._events=new Js:delete e._events[t]}function Ut(){this._events=new Js,this._eventsCount=0}Ut.prototype.eventNames=function(){var t=[],r,n;if(this._eventsCount===0)return t;for(n in r=this._events)yq.call(r,n)&&t.push(Wt?n.slice(1):n);return Object.getOwnPropertySymbols?t.concat(Object.getOwnPropertySymbols(r)):t};Ut.prototype.listeners=function(t){var r=Wt?Wt+t:t,n=this._events[r];if(!n)return[];if(n.fn)return[n.fn];for(var i=0,a=n.length,o=new Array(a);i<a;i++)o[i]=n[i].fn;return o};Ut.prototype.listenerCount=function(t){var r=Wt?Wt+t:t,n=this._events[r];return n?n.fn?1:n.length:0};Ut.prototype.emit=function(t,r,n,i,a,o){var s=Wt?Wt+t:t;if(!this._events[s])return!1;var c=this._events[s],l=arguments.length,u,f;if(c.fn){switch(c.once&&this.removeListener(t,c.fn,void 0,!0),l){case 1:return c.fn.call(c.context),!0;case 2:return c.fn.call(c.context,r),!0;case 3:return c.fn.call(c.context,r,n),!0;case 4:return c.fn.call(c.context,r,n,i),!0;case 5:return c.fn.call(c.context,r,n,i,a),!0;case 6:return c.fn.call(c.context,r,n,i,a,o),!0}for(f=1,u=new Array(l-1);f<l;f++)u[f-1]=arguments[f];c.fn.apply(c.context,u)}else{var d=c.length,h;for(f=0;f<d;f++)switch(c[f].once&&this.removeListener(t,c[f].fn,void 0,!0),l){case 1:c[f].fn.call(c[f].context);break;case 2:c[f].fn.call(c[f].context,r);break;case 3:c[f].fn.call(c[f].context,r,n);break;case 4:c[f].fn.call(c[f].context,r,n,i);break;default:if(!u)for(h=1,u=new Array(l-1);h<l;h++)u[h-1]=arguments[h];c[f].fn.apply(c[f].context,u)}}return!0};Ut.prototype.on=function(t,r,n){return RP(this,t,r,n,!1)};Ut.prototype.once=function(t,r,n){return RP(this,t,r,n,!0)};Ut.prototype.removeListener=function(t,r,n,i){var a=Wt?Wt+t:t;if(!this._events[a])return this;if(!r)return Ip(this,a),this;var o=this._events[a];if(o.fn)o.fn===r&&(!i||o.once)&&(!n||o.context===n)&&Ip(this,a);else{for(var s=0,c=[],l=o.length;s<l;s++)(o[s].fn!==r||i&&!o[s].once||n&&o[s].context!==n)&&c.push(o[s]);c.length?this._events[a]=c.length===1?c[0]:c:Ip(this,a)}return this};Ut.prototype.removeAllListeners=function(t){var r;return t?(r=Wt?Wt+t:t,this._events[r]&&Ip(this,r)):(this._events=new Js,this._eventsCount=0),this};Ut.prototype.off=Ut.prototype.removeListener;Ut.prototype.addListener=Ut.prototype.on;Ut.prefixed=Wt;Ut.EventEmitter=Ut;typeof k0<"u"&&(k0.exports=Ut)});var OP,FP,DP=L(()=>{OP=le(PP(),1),FP=OP.default});var Tp,BP=L(()=>{"use strict";DP();Tp=class extends FP{}});function Rp(e,t){let r=e.data||e,n=String(r.fromId||r.uidFrom||r.idFrom||r.uid||r.fromUid||""),i=!!e.isSelf||!!r.isSelf||n==="0"||r.uidFrom==="0"||r.fromId==="0"||!!n&&n===t,a=i?n&&n!=="0"?n:t:n,o=r.dName||r.displayName||r.senderName||void 0,s="text",c="";typeof r.msg=="string"?c=r.msg:typeof r.message=="string"?c=r.message:typeof r.content=="string"&&(c=r.content);let l=r.mediaUrl||(typeof r.content=="object"&&r.content!==null?r.content.href||r.content.thumb||r.content.url||"":typeof r.content=="string"&&(r.content.startsWith("http://")||r.content.startsWith("https://"))?r.content:r.href||r.url||"");r.msgType==="chat.image"||r.msgType==="chat.photo"?s="image":r.msgType==="chat.video"?s="video":r.msgType==="chat.voice"||r.msgType==="chat.audio"?s="audio":r.msgType==="chat.file"||r.msgType==="chat.document"?s="file":r.msgType==="chat.sticker"?s="sticker":(r.msgType==="system"||r.msgType==="chat.system")&&(s="system");let u=String(e.threadId||r.threadId||r.groupId||"");if(!u){let v=String(r.toId||r.idTo||"");u=v===t?a:v}let f=!!(Number(e.type)===1||Number(r.type)===1||r.groupId||e.groupId||r.msgType?.includes("group")||String(u).startsWith("g")||String(u).includes("|")),d=r.groupName||r.gName||r.groupTitle||e.groupName||void 0,h=r.groupAvatar||r.gAvatar||r.avt||e.groupAvatar||void 0;return{id:String(r.msgId||r.id||r.cliMsgId||""),conversationId:u,threadId:u,accountId:t,senderId:a,senderName:o,text:c,content:c,type:s,messageType:s,mediaUrl:l,timestamp:Number(r.ts||r.timestamp||Date.now()),platform:"zalo",isFromMe:i,isSelf:i,isGroup:f,groupName:d,groupAvatar:h,metadata:{rawMsgType:r.msgType,reactions:r.reactions||r.reaction||null,sticker:r.sticker||null,rawPayload:bq(e)}}}function bq(e){if(!e||typeof e!="object")return e;let t={},r=["threadId","type","isGroup","serverTime","act"];for(let n of r)e[n]!==void 0&&(t[n]=e[n]);if(e.data&&typeof e.data=="object")t.data=NP(e.data);else{let n=NP(e);Object.assign(t,n)}return t}function NP(e){if(!e||typeof e!="object")return e;let t={},r=["msgId","id","cliMsgId","globalMsgId","actionId","msgType","msg","message","content","mediaUrl","ts","timestamp","time","fromId","uidFrom","idFrom","uid","fromUid","userId","toId","idTo","toUid","uidTo","dName","displayName","fromDisplayName","avatar","avt","fullAvt","fromAvatar","oaAvatar","groupName","gName","groupTitle","groupAvatar","gAvt","isTyping","seenTime","action","paramsExt","params"];for(let n of r)e[n]!==void 0&&(n==="paramsExt"&&typeof e[n]=="object"&&e[n]!==null?t[n]=JSON.parse(JSON.stringify(e[n])):t[n]=e[n]);return e.attachments!==void 0&&(t.attachments=Array.isArray(e.attachments)?e.attachments.map(n=>JSON.parse(JSON.stringify(n))):e.attachments),e.quote!==void 0&&(t.quote=vq(e.quote)),e.reactions!==void 0&&(t.reactions=e.reactions),e.reaction!==void 0&&(t.reaction=e.reaction),e.sticker!==void 0&&(t.sticker=e.sticker),e.mentions!==void 0&&(t.mentions=e.mentions),t}function vq(e){if(!e||typeof e!="object")return e;let t=["msgId","cliMsgId","globalMsgId","msg","content","attach","fromD","msgType","ownerId","senderId","senderName","ts","timestamp","url","href","thumb","localPath","fileName","fileSize","cloud_file_id"],r={};for(let n of t)e[n]!==void 0&&(r[n]=e[n]);return r}var S0=L(()=>{"use strict"});function E0(e){if(!e)return{id:"",name:"Zalo User",avatarUrl:"",platform:"zalo"};let t=e;if(typeof t=="string")try{t=JSON.parse(t)}catch{}t&&t.data&&!t.changed_profiles&&(t=t.data),t&&t.changed_profiles&&(t=Object.values(t.changed_profiles)[0]||t),t&&t.profile&&(t=t.profile);let r=t||{},n=String(r.userId||r.id||r.uid||r.uidFrom||""),i=String(r.displayName||r.name||r.zaloName||r.zName||(typeof r.username=="string"&&r.username?r.username:"")||"Zalo User"),a=String(r.avatar||r.avt||r.fullAvt||r.picture||""),o=r.phoneNumber||r.phone||r.phone_number||void 0;return{id:n,name:i,avatarUrl:a,phoneNumber:o,platform:"zalo",rawContact:r}}function LP(e){let t=e.data||e,r=String(t.threadId||t.id||t.groupId||""),n=String(t.name||t.displayName||t.threadName||"Zalo Chat"),i=String(t.avatar||t.avt||t.avatarUrl||""),a="direct";return(r.startsWith("g")||r.includes("|")||t.isGroup||t.type===1)&&(a="group"),{id:r,name:n,avatarUrl:i,type:a,unreadCount:Number(t.unreadCount||0),platform:"zalo",rawConversation:t}}var A0=L(()=>{"use strict"});function wq(e){if(!e||e.length<16)return null;if(e[0]===137&&e[1]===80&&e[2]===78&&e[3]===71){let t=e.readUInt32BE(16),r=e.readUInt32BE(20);return{width:t,height:r,format:"png"}}if(e[0]===71&&e[1]===73&&e[2]===70){let t=e.readUInt16LE(6),r=e.readUInt16LE(8);return{width:t,height:r,format:"gif"}}if(e[0]===255&&e[1]===216){let t=2;for(;t<e.length-8;){if(e[t]!==255){t++;continue}let r=e[t+1];if(r>=192&&r<=195||r>=197&&r<=199||r>=201&&r<=203||r>=205&&r<=207){let i=e.readUInt16BE(t+5);return{width:e.readUInt16BE(t+7),height:i,format:"jpeg"}}let n=e.readUInt16BE(t+2);t+=2+n}}if(e.length>=30&&e.toString("ascii",0,4)==="RIFF"&&e.toString("ascii",8,12)==="WEBP"){let t=e.toString("ascii",12,16);if(t==="VP8 "){let r=e.readUInt16LE(26)&16383,n=e.readUInt16LE(28)&16383;return{width:r,height:n,format:"webp"}}else if(t==="VP8L"&&e[20]===47){let r=e[21],n=e[22],i=e[23],a=e[24],o=1+((n&63)<<8|r),s=1+((a&15)<<10|i<<2|(n&192)>>6);return{width:o,height:s,format:"webp"}}else if(t==="VP8X"){let r=1+(e[24]|e[25]<<8|e[26]<<16),n=1+(e[27]|e[28]<<8|e[29]<<16);return{width:r,height:n,format:"webp"}}}return null}var UP,$P,zP,jP,C0,Pp,Op,MP=L(()=>{"use strict";zm();UP=le(DR()),$P=le(LR()),zP=le(HR());TP();jP=le(Vo()),C0=le(require("fs/promises")),Pp=le(require("path"));BP();S0();A0();S0();A0();zm();Op=class e{accountId;platform="zalo";eventBus=new Tp;status="disconnected";zaloInstance=null;api=null;session=null;constructor(t){this.accountId=t}async getImageMetadata(t){try{let r=await C0.default.readFile(t),n=wq(r);return n?{width:n.width,height:n.height,size:r.length,extension:n.format||Pp.default.extname(t).slice(1)}:{width:0,height:0,size:(await C0.default.stat(t)).size,extension:Pp.default.extname(t).slice(1)||"jpg"}}catch{return{width:0,height:0,size:0,extension:Pp.default.extname(t).slice(1)||"jpg"}}}async initialize(t){this.session=t;let r={selfListen:!0,checkUpdate:!1,logging:!0,userAgent:t.authData.userAgent,imei:t.authData.imei,imageMetadataGetter:i=>this.getImageMetadata(i)};if(t.proxy)try{let i;t.proxy.startsWith("socks")?i=UP.SocksProxyAgent:t.proxy.startsWith("https")?i=zP.HttpsProxyAgent:i=$P.HttpProxyAgent,r.agent=new i(t.proxy)}catch{}r.polyfill=Vs.default||Vs,this.zaloInstance=new Ns(r);let n=this.zaloInstance;if(n.ctx&&n.ctx.cookie){let i=n.ctx.cookie.setCookie.bind(n.ctx.cookie);n.ctx.cookie.setCookie=async(a,o,s)=>{try{let c;return typeof a=="string"?c=jP.Cookie.parse(a):c=a,c&&c.value==="EXPIRED"?Promise.resolve(c):i(a,o,s)}catch{return i(a,o,s)}}}t.authData.cookie&&(t.authData.cookie=e.patchCookieDomain(t.authData.cookie));try{this.status="connecting",this.eventBus.emit("session:status_changed","connecting");let i=this.zaloInstance.login(t.authData);i.then(s=>{this.status==="disconnected"&&s&&s.listener&&typeof s.listener.stop=="function"&&s.listener.stop()}).catch(()=>{});let a=new Promise((s,c)=>setTimeout(()=>c(new Error("Zalo login timeout after 30s")),3e4));this.api=await Promise.race([i,a]),this.setupListeners(),t.authData?.autoStartListener!==!1&&(this.api?.listener&&typeof this.api.listener.start=="function"&&this.api.listener.start({retryOnClose:!0}),this.requestCatchUp()),this.status="connected",this.eventBus.emit("session:status_changed","connected")}catch(i){throw this.status="disconnected",this.eventBus.emit("session:status_changed","disconnected",i.message),i}}async disconnect(){if(this.zaloInstance){try{if(this.api&&this.api.listener){let t=this.api.listener;typeof t.stop=="function"&&t.stop()}}catch{}this.zaloInstance=null,this.api=null,this.status="disconnected",this.eventBus.emit("session:status_changed","disconnected")}}async sendMessage(t,r){if(!this.api)throw new Error("Adapter not initialized or logged in");let i=r.isGroup??(t.startsWith("g")||t.includes("|"))?Z.Group:Z.User,a;if(r.type==="text"){let c={msg:r.text};r.mentions&&r.mentions.length>0&&(c.mentions=r.mentions),r.quote&&(c.quote=r.quote),a=await this.api.sendMessage(c,t,i)}else if(r.type==="image"){let c=r.filePath||r.url;if(!c)throw new Error("Image path or url is required for image payload");if(typeof this.api.sendImage=="function"){let l={url:c,caption:r.caption};r.quote&&(l.quote=r.quote),a=await this.api.sendImage(l,t,i)}else{let l={msg:r.caption||"",attachments:[c]};r.quote&&(l.quote=r.quote),a=await this.api.sendMessage(l,t,i)}}else if(r.type==="sticker")if(typeof this.api.sendSticker=="function")a=await this.api.sendSticker({stickerId:r.stickerId,stickerPackId:r.stickerPackId},t,i);else throw new Error("sendSticker method is not supported on this version of underlying client");else if(r.type==="file"){let c=r.filePath||r.url;if(!c)throw new Error("File path or url is required for file payload");a=await this.api.sendMessage({msg:"",attachments:[c]},t,i)}else throw new Error(`Unsupported message payload type: ${r.type}`);let o=a?.message?a.message:a,s=Rp(o,this.accountId);return s.conversationId||(s.conversationId=t),s.senderId||(s.senderId=this.accountId),!s.text&&r.type==="text"&&r.text&&(s.text=r.text),s}async getConversations(t=20){if(!this.api)throw new Error("Adapter not initialized");return(await this.api.getConversations(t)).map(LP)}async getMessageHistory(t,r=50){if(!this.api)throw new Error("Adapter not initialized");return[]}async getCurrentUser(){if(!this.api)return null;let t=await this.api.fetchAccountInfo();return E0(t)}async getContactInfo(t){if(!this.api)throw new Error("Adapter not initialized");try{let r=await this.api.getUserInfo(t);return E0(r)}catch{return null}}async markAsRead(t){if(!this.api)throw new Error("Adapter not initialized");try{typeof this.api.markAsRead=="function"&&await this.api.markAsRead(t)}catch{}}async sendTyping(t,r){if(!this.api)throw new Error("Adapter not initialized");try{typeof this.api.sendTyping=="function"&&await this.api.sendTyping(t,r)}catch{}}getUnderlyingClient(){return this.api}setupListeners(){if(!this.api||!this.api.listener)return;let t=this.api.listener;t.on("message",r=>{try{let n=Rp(r,this.accountId);this.eventBus.emit("message:received",n)}catch(n){console.error(`[ZaloAdapter:${this.accountId}] Failed to map incoming message:`,n?.message||n)}}),t.on("connected",()=>{this.status="connected",this.eventBus.emit("session:status_changed","connected")}),t.on("error",r=>{console.error(`[ZaloAdapter:${this.accountId}] WebSocket listener error:`,r?.message||r)}),t.on("typing",r=>{try{this.eventBus.emit("chat:typing",{conversationId:String(r.threadId||r.groupId||""),senderId:String(r.senderId||r.fromUid||""),isTyping:!!(r.isTyping||r.type==="start")})}catch{}}),t.on("undo",r=>{try{this.eventBus.emit("message:recalled",{conversationId:String(r.threadId||""),messageId:String(r.msgId||""),recalledAt:Date.now()})}catch{}}),t.on("read",r=>{try{this.eventBus.emit("chat:read",{conversationId:String(r.threadId||""),readerId:String(r.senderId||r.uid||""),timestamp:Date.now()})}catch{}}),t.on("old_messages",r=>{if(!(!r||!Array.isArray(r))){for(let n of r)if(n)try{let i=Rp(n,this.accountId);this.eventBus.emit("message:received",i)}catch{}}})}requestCatchUp(){if(!this.api||!this.api.listener)return;let t=this.api.listener;try{typeof t.requestOldMessages=="function"&&(t.requestOldMessages(0),t.requestOldMessages(1))}catch{}}async getGroupInfo(t){if(!this.api||typeof this.api.getGroupInfo!="function")return null;try{return await this.api.getGroupInfo(t)}catch{return null}}async getAllGroups(){if(!this.api||typeof this.api.getAllGroups!="function")return null;try{return await this.api.getAllGroups()}catch{return null}}static patchCookieDomain(t){if(!t)return t;let r=[],n=!1;if(Array.isArray(t))r=t;else if(t&&Array.isArray(t.cookies))r=t.cookies,n=!0;else return t;let i=r.map(a=>a&&(a.domain==="id.zalo.me"||a.domain==="zaloapp.com")?{...a,domain:".zalo.me"}:a);return n?{...t,cookies:i}:i}}});var qP={};Og(qP,{ZaloChannelRunner:()=>I0});var Zs,I0,HP=L(()=>{"use strict";Zs=le(it());MP();I0=class{constructor(t,r,n,i){this.accountId=t;this.sessionData=r;this.proxyData=n;this.logger=i||(0,Zs.createLogger)(`ZaloRunner:${t}`)}platform="zalo";status="offline";logger;messageHandler;adapter;groupNameCache=new Map;onMessage(t){this.messageHandler=t}async start(){let t=this.proxyData?` via resident proxy ${this.proxyData.host||this.proxyData.ip||"configured"}`:" (direct)";this.logger.info(`Starting 24/7 headless Zalo runner for account ${this.accountId}${t}...`);let r=this.sessionData;this.sessionData?.encryptedSession?r=Zs.CloudCrypto.parseCloudSession(this.sessionData.encryptedSession):typeof this.sessionData=="string"&&(r=Zs.CloudCrypto.parseCloudSession(this.sessionData));let n=r?.cookie||r?.cookies;if(n&&r?.imei)try{this.adapter=new Op(this.accountId),this.adapter.eventBus.on("message:received",a=>{this.receiveIncomingMessage(a)});let i;if(this.proxyData?.host&&this.proxyData?.port){let a=this.proxyData.username&&this.proxyData.password?`${this.proxyData.username}:${this.proxyData.password}@`:"";i=`${this.proxyData.protocol||"http"}://${a}${this.proxyData.host}:${this.proxyData.port}`}await this.adapter.initialize({accountId:this.accountId,platform:"zalo",status:"connecting",authData:{cookie:n,imei:r.imei,userAgent:r.userAgent},proxy:i}),this.status="active",this.logger.info(`Headless Zalo socket WSS connected & listening for ${this.accountId}`),this.prewarmGroupCache().catch(()=>{})}catch(i){this.status="expired",this.logger.warn(`Could not initialize live Zalo socket for ${this.accountId}: ${i.message}. Phi\xEAn \u0111\u0103ng nh\u1EADp Zalo \u0111\xE3 h\u1EBFt h\u1EA1n ho\u1EB7c kh\xF4ng h\u1EE3p l\u1EC7.`)}else this.status="active",this.logger.debug(`No direct Zalo session credentials provided for ${this.accountId}. Running in standby mode.`)}async stop(){if(this.logger.info(`Stopping headless Zalo runner for account ${this.accountId}...`),this.adapter){try{await this.adapter.disconnect()}catch(t){this.logger.debug(`Error disconnecting adapter during teardown for ${this.accountId}:`,t?.message)}this.adapter=void 0}this.status="offline"}getStatus(){return this.status}pause(){this.status==="active"&&(this.status="standby",this.logger.info(`\u23F8\uFE0F [StateGuard] Paused Zalo runner for account ${this.accountId} (standby)`))}resume(){this.status==="standby"&&(this.status="active",this.logger.info(`\u25B6\uFE0F [StateGuard] Resumed Zalo runner for account ${this.accountId} (active)`))}async sendMessage(t){if(this.logger.info(`Headless Zalo runner sending message ${t.id} to thread ${t.threadId}`),this.adapter&&this.adapter.status==="connected")try{let r=t.threadId||t.conversationId,n=Array.isArray(t.attachments)&&t.attachments.length>0?t.attachments[0]?.url:void 0;return t.messageType==="image"&&n?await this.adapter.sendMessage(r,{type:"image",url:n,caption:t.content||void 0}):await this.adapter.sendMessage(r,{type:"text",text:t.content||""}),!0}catch(r){return this.logger.error(`Failed to send message via Zalo socket: ${r.message}`),!1}return!0}async resolveGroupMetadata(t){if(!t)return null;let r=this.groupNameCache.get(t);if(r)return r;if(!this.adapter)return null;try{let n=await this.adapter.getGroupInfo(t),i=n?.data||n,a=i?.gridInfoMap?.[t]||i;if(a?.name){let o={name:String(a.name).trim(),avatar:a.avt||a.fullAvt||a.avatar||void 0};return this.groupNameCache.set(t,o),o}}catch(n){this.logger.debug(`Could not resolve group info for ${t}: ${n?.message}`)}return null}async prewarmGroupCache(){if(this.adapter)try{let t=await this.adapter.getAllGroups(),r=t?.gridVerMap||t?.data?.gridVerMap;if(r){let n=Object.keys(r);if(n.length>0){for(let a=0;a<Math.min(n.length,100);a+=25){let o=n.slice(a,a+25),s=await this.adapter.getGroupInfo(o),c=s?.gridInfoMap||s?.data?.gridInfoMap;if(c)for(let l of Object.keys(c)){let u=c[l];u?.name&&this.groupNameCache.set(l,{name:String(u.name).trim(),avatar:u.avt||u.fullAvt||u.avatar||void 0})}}this.logger.info(`[ZaloRunner:${this.accountId}] \u2705 Pre-warmed ${this.groupNameCache.size} group metadata entries.`)}}}catch(t){this.logger.debug(`[ZaloRunner:${this.accountId}] Note prewarming groups: ${t?.message}`)}}async receiveIncomingMessage(t){if(this.status!=="active")return;let r=String(t.content||t.text||""),n=String(t.threadId||t.conversationId||""),i=String(t.conversationId||t.threadId||""),a=!!(t.isSelf||t.isFromMe||t.senderId==="0"||this.accountId&&String(t.senderId)===String(this.accountId)),o=t.metadata?.rawPayload||t.rawPayload||t,s=!!(t.isGroup||o?.isGroup||Number(o?.type)===1||Number(o?.data?.type)===1||o?.groupId||o?.data?.groupId||n.startsWith("g")),c=t.groupName||o?.groupName||o?.data?.groupName,l=t.groupAvatar||o?.groupAvatar||o?.data?.groupAvatar;if(s&&(!c||c==="Nh\xF3m Zalo")){let f=this.groupNameCache.get(n);if(f?.name)c=f.name,l=f.avatar||l;else{let d=await Promise.race([this.resolveGroupMetadata(n),new Promise(h=>setTimeout(()=>h(null),1e3))]);d?.name&&(c=d.name,l=d.avatar||l)}}let u={...t,content:r,text:r,threadId:n,conversationId:i,accountId:t.accountId||this.accountId,senderId:a&&(t.senderId==="0"||!t.senderId)?this.accountId:t.senderId,isSelf:a,isGroup:s,groupName:c||(s?"Nh\xF3m Zalo":void 0),groupAvatar:l};this.logger.info(`\u{1F4E9} [ZaloRunner:${this.accountId}] Received message ${u.id} from sender ${u.senderName||u.senderId}${s?` in group [${u.groupName}]`:""}: "${r.slice(0,60)}"`),this.messageHandler?.(u)}requestCatchUp(){this.adapter&&typeof this.adapter.requestCatchUp=="function"&&this.adapter.requestCatchUp()}}});var tt=le(require("fs")),$t=le(require("path")),rt=le(require("os")),h4=le(require("readline")),Ze=require("child_process");var Rn=le(require("os")),ni=le(require("fs")),Lo=le(require("path")),Fg=le(require("crypto"));function KO(){return"1.0.52"}var Vt=KO();function Ac(){return{totalMemMb:Math.round(Rn.default.totalmem()/(1024*1024)),freeMemMb:Math.round(Rn.default.freemem()/(1024*1024)),cpuCount:Rn.default.cpus()?.length||1,platform:Rn.default.platform()}}function YO(e){try{let t=Lo.default.join(Rn.default.homedir(),".zplus");ni.default.existsSync(t)||ni.default.mkdirSync(t,{recursive:!0});let r=e?`_slot_${e.replace(/[^a-zA-Z0-9_-]/g,"")}`:"",n=Lo.default.join(t,`worker_identity${r}.json`);if(ni.default.existsSync(n)){let f=JSON.parse(ni.default.readFileSync(n,"utf-8"));if(f&&f.workerId)return{workerId:f.workerId,workerName:f.workerName||f.workerId}}let a=(Rn.default.hostname()||"node").replace(/[^a-zA-Z0-9_-]/g,"_").toLowerCase().slice(0,14),o=Fg.default.randomBytes(2).toString("hex"),s=`worker_${a}${r}_${o}`,c=e?` #${e}`:"",l=`Worker ${a.toUpperCase()}${c}`,u={workerId:s,workerName:l,slot:e||"default",createdAt:new Date().toISOString()};return ni.default.writeFileSync(n,JSON.stringify(u,null,2),"utf-8"),u}catch{let t=e?`_slot_${e}`:"",r=`worker_${Rn.default.hostname().replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,14)||"node"}${t}`;return{workerId:r,workerName:r}}}var Ec=class{static loadFromEnv(t=process.argv.slice(2)){let r=B=>{for(let T of t){if(T.startsWith(`--${B}=`))return T.split("=").slice(1).join("=");if(T===`--${B}`&&t[t.indexOf(T)+1])return t[t.indexOf(T)+1]}},n=r("cloud-provider")||process.env.CLOUD_PROVIDER||"appwrite",i=r("token")||process.env.CLOUD_AUTH_TOKEN||process.env.APPWRITE_SESSION_TOKEN||process.env.WORKER_TOKEN||process.env.SESSION_TOKEN,a=r("jwt")||process.env.CLOUD_JWT||process.env.APPWRITE_JWT||process.env.JWT,o=r("secret")||process.env.DESKTOP_SECRET,s=r("team-id")||process.env.TEAM_ID||"default",c=t.includes("--enable-http")||r("enable-http")==="true"||process.env.ENABLE_HTTP==="true"||!1,l=r("port")||process.env.PORT,u=l?Number(l):c?8080:void 0,f=r("endpoint")||process.env.CLOUD_ENDPOINT||process.env.CLOUD_API_ENDPOINT||process.env.APPWRITE_ENDPOINT||process.env.VITE_APPWRITE_ENDPOINT||"https://api.softty.net/v1",d=r("project-id")||process.env.CLOUD_PROJECT_ID||process.env.CLOUD_TENANT_ID||process.env.APPWRITE_PROJECT_ID||process.env.VITE_APPWRITE_PROJECT_ID||"699cfc3100136099c1c1",h=r("database-id")||process.env.CLOUD_DATABASE_ID||process.env.APPWRITE_DATABASE_ID||process.env.VITE_APPWRITE_DATABASE_ID||"zplus_app",v=r("storage-bucket-id")||process.env.STORAGE_BUCKET_ID||process.env.APPWRITE_STORAGE_BUCKET_ID||process.env.VITE_APPWRITE_STORAGE_BUCKET_ID||"zplus-media-vault",w=Math.max(1,Math.round(Rn.default.totalmem()/(1024*1024*1024))),k=Math.min(200,Math.max(20,w*25)),m=r("max-capacity")||process.env.MAX_CAPACITY,x=Number(m||k),b=r("slot")||process.env.WORKER_SLOT||process.env.pm_id||process.env.NODE_APP_INSTANCE,y=YO(b),_=r("worker-id")||process.env.WORKER_ID||y.workerId,S=r("worker-name")||process.env.WORKER_NAME||process.env.HOSTNAME||y.workerName,R=r("user-id")||process.env.USER_ID||process.env.SOFTTY_USER_ID;return{workerId:_,version:Vt,enableHttp:c,port:u,userId:R,teamId:s,workerName:S,maxCapacity:x,recommendedCapacity:k,clusterPollIntervalMs:Number(r("poll-interval")||process.env.CLUSTER_POLL_INTERVAL_MS||5e3),cloudProvider:n,cloudEndpoint:f,cloudProjectId:d,cloudSessionToken:i,cloudJwt:a,cloudDatabaseId:h,appwriteEndpoint:f,appwriteProjectId:d,appwriteSessionToken:i,appwriteJwt:a,storageBucketId:v,desktopSecret:o,databaseId:h,heartbeatIntervalMs:Number(r("heartbeat-interval")||process.env.HEARTBEAT_INTERVAL_MS||3e4),geminiApiKey:r("gemini-api-key")||process.env.GEMINI_API_KEY||process.env.GOOGLE_API_KEY,openaiApiKey:r("openai-api-key")||process.env.OPENAI_API_KEY,deepseekApiKey:r("deepseek-api-key")||process.env.DEEPSEEK_API_KEY,anthropicApiKey:r("anthropic-api-key")||process.env.ANTHROPIC_API_KEY,customAiApiKey:r("custom-ai-api-key")||process.env.CUSTOM_AI_API_KEY,aiBaseUrl:r("ai-base-url")||process.env.AI_BASE_URL,aiProvider:r("ai-provider")||process.env.AI_PROVIDER,aiModel:r("ai-model")||process.env.AI_MODEL,nightSystemPrompt:r("night-system-prompt")||process.env.NIGHT_SYSTEM_PROMPT,nightFallbackReply:r("night-fallback-reply")||process.env.NIGHT_FALLBACK_REPLY,logLevel:r("log-level")||process.env.LOG_LEVEL||"info"}}};var Si=le(require("fs")),Zp=le(require("os")),da=le(require("path")),d4=le(require("crypto")),Yp=le(it());var qg=le(it()),Oc=class{runners=new Map;logger;constructor(t){this.logger=t||(0,qg.createLogger)("ChannelRunnerRegistry")}register(t){let r=`${t.platform}:${t.accountId}`;this.runners.has(r)&&this.logger.warn(`Overwriting existing runner for ${r}`),this.runners.set(r,t),this.logger.info(`Registered runner for ${r}`)}unregister(t,r){let n=`${t}:${r}`,i=this.runners.get(n);return i?(i.stop().catch(a=>{this.logger.error(`Error stopping runner ${n} during unregister`,a)}),this.runners.delete(n),this.logger.info(`Unregistered runner for ${n}`),!0):!1}get(t,r){return this.runners.get(`${t}:${r}`)}getAll(){return Array.from(this.runners.values())}getCount(){return this.runners.size}async startAll(){this.logger.info(`Starting all ${this.runners.size} registered channel runners...`);for(let[t,r]of this.runners.entries())try{await r.start()}catch(n){this.logger.error(`Failed to start runner ${t}:`,n)}}async stopAll(){this.logger.info(`Stopping all ${this.runners.size} channel runners...`);for(let[t,r]of this.runners.entries())try{await r.stop()}catch(n){this.logger.error(`Failed to stop runner ${t}:`,n)}this.runners.clear()}async pauseAll(){this.logger.info(`Pausing all ${this.runners.size} channel runners due to worker auth/standby status...`);for(let[t,r]of this.runners.entries())try{typeof r.pause=="function"&&await r.pause()}catch(n){this.logger.error(`Failed to pause runner ${t}:`,n)}}async resumeAll(){this.logger.info(`Resuming all ${this.runners.size} channel runners...`);for(let[t,r]of this.runners.entries())try{typeof r.resume=="function"&&await r.resume()}catch(n){this.logger.error(`Failed to resume runner ${t}:`,n)}}};var Hg=le(it()),Fc=class{constructor(t=6e4,r,n){this.defaultTtlMs=t;this.logger=r||(0,Hg.createLogger)("DistributedLockManager"),this.storageProvider=n}logger;locks=new Map;preemptCallbacks=[];storageProvider;setStorageProvider(t){this.storageProvider=t}getStorageProvider(){return this.storageProvider}onPreempt(t){this.preemptCallbacks.push(t)}async acquireLockRemote(t,r,n=this.defaultTtlMs){return this.storageProvider&&!await this.storageProvider.acquireLock(t,r,n)?!1:this.acquireLock(t,r,n)}async releaseLockRemote(t,r){return this.storageProvider&&await this.storageProvider.releaseLock(t,r),this.releaseLock(t,r)}async renewLockRemote(t,r,n=this.defaultTtlMs){return this.storageProvider&&await this.storageProvider.renewLock(t,r,n),this.acquireLock(t,r,n)}acquireLock(t,r,n=this.defaultTtlMs){let i=Date.now(),a=this.locks.get(t);return a&&a.expiresAt>i&&a.ownerId!==r?(this.logger.warn(`Lock denied for account ${t}: currently held by ${a.ownerId} (expires in ${a.expiresAt-i}ms)`),!1):(this.locks.set(t,{accountId:t,ownerId:r,acquiredAt:i,expiresAt:i+n}),this.logger.info(`\u2705 Lock granted: account=${t}, owner=${r}, ttl=${n}ms`),!0)}async preemptLock(t,r){let n=this.locks.get(t);this.logger.info(`\u26A1 Preemption triggered for account ${t} by master ${r} (previous owner: ${n?.ownerId||"none"})`);let i=this.preemptCallbacks.map(o=>{try{return Promise.resolve(o(t,r))}catch(s){return this.logger.error(`Error in preempt callback for ${t}:`,s),Promise.resolve()}});await Promise.race([Promise.all(i),new Promise(o=>setTimeout(o,1e3))]);let a=Date.now();return this.locks.set(t,{accountId:t,ownerId:r,acquiredAt:a,expiresAt:a+this.defaultTtlMs}),this.logger.info(`\u2705 Account ${t} preempted successfully by ${r}.`),!0}releaseLock(t,r){let n=this.locks.get(t);return n?r&&n.ownerId!==r?(this.logger.warn(`Attempted unauthorized lock release for ${t} by ${r} (real owner: ${n.ownerId})`),!1):(this.locks.delete(t),this.logger.info(`\u{1F513} Lock released for account ${t}.`),!0):!0}releaseAllForOwner(t){let r=0;for(let[n,i]of this.locks.entries())i.ownerId===t&&(this.locks.delete(n),r++);return r}isLocked(t){let r=this.locks.get(t);return r?r.expiresAt>Date.now():!1}getLockOwner(t){let r=this.locks.get(t);return!r||r.expiresAt<=Date.now()?null:r.ownerId}};var Ta=le(require("fs")),Wg=le(require("path")),Gg=le(it()),Dc=class{logger;queue=[];maxCapacity;persistenceFilePath;constructor(t=1e4,r,n){this.maxCapacity=t,this.logger=r||(0,Gg.createLogger)("CloudPendingMessageQueue"),this.persistenceFilePath=n,this.loadFromDisk()}loadFromDisk(){if(this.persistenceFilePath)try{if(Ta.default.existsSync(this.persistenceFilePath)){let t=Ta.default.readFileSync(this.persistenceFilePath,"utf8");if(t&&t.trim()){let r=JSON.parse(t);Array.isArray(r)&&(this.queue.push(...r),this.logger.info(`\u{1F4E6} Restored ${r.length} pending delta messages from disk: ${this.persistenceFilePath}`))}}}catch(t){this.logger.warn(`Failed to restore pending messages from disk (${this.persistenceFilePath}): ${t?.message}`)}}saveToDisk(){if(this.persistenceFilePath)try{let t=Wg.default.dirname(this.persistenceFilePath);Ta.default.existsSync(t)||Ta.default.mkdirSync(t,{recursive:!0}),Ta.default.writeFileSync(this.persistenceFilePath,JSON.stringify(this.queue),"utf8")}catch(t){this.logger.warn(`Failed to save pending messages to disk (${this.persistenceFilePath}): ${t?.message}`)}}enqueue(t){if(this.queue.length>=this.maxCapacity){let r=this.queue.shift();this.logger.warn(`Queue capacity reached (${this.maxCapacity}). Dropped oldest message: ${r?.id}`)}this.queue.push(t),this.saveToDisk(),this.logger.debug(`Enqueued pending message ${t.id} for account ${t.accountId} (Total pending: ${this.queue.length})`)}getDeltas(t,r=0){return this.queue.filter(n=>{let i=!t||n.accountId===t,a=n.timestamp>=r;return i&&a})}purgeSynced(t,r){let n=this.queue.length,i=[];for(let o=0;o<this.queue.length;o++){let s=this.queue[o];s.timestamp<=t&&(!r||s.accountId===r)&&i.push(o)}for(let o=i.length-1;o>=0;o--)this.queue.splice(i[o],1);let a=n-this.queue.length;return a>0&&(this.saveToDisk(),this.logger.info(`Purged ${a} synced delta messages from queue.`)),a}getCount(){return this.queue.length}getAll(){return[...this.queue]}remove(t){let r=this.queue.findIndex(n=>n.id===t);return r!==-1?(this.queue.splice(r,1),this.saveToDisk(),!0):!1}clear(){this.queue.length=0,this.saveToDisk()}};var Vg=le(it()),Bc=class{logger;campaigns=new Map;rules=new Map;threadHistory=new Map;lastReplyTimes=new Map;aiConfig={enabled:!1};constructor(t,r){this.logger=t||(0,Vg.createLogger)("HeadlessAutomationEngine"),r&&this.configure(r)}configure(t){this.aiConfig={...this.aiConfig,...t},this.logger.info(`[HeadlessAutomation] Configured AI provider: ${this.aiConfig.provider||"none"} (model: ${this.aiConfig.model||"none"}, enabled: ${this.aiConfig.enabled===!0})`)}getAiConfig(){return{...this.aiConfig}}registerCampaign(t){this.campaigns.set(t.id,t),this.logger.info(`Loaded campaign ${t.id} (${t.name})`)}registerRule(t){this.rules.set(t.id,t),this.logger.info(`Loaded automation rule ${t.id} (${t.name})`)}async evaluateIncomingMessage(t){if(t.isSelf||t.senderType&&t.senderType!=="customer"||!t.content||typeof t.content!="string"||!t.content.trim())return null;let r=t.threadId||t.conversationId||t.senderId,n=Date.now(),i=this.lastReplyTimes.get(r)||0;if(n-i<3e3)return this.logger.debug(`[HeadlessAutomation] Rate limit hit for thread ${r}. Skipping reply.`),null;let a=t.content.trim(),o=this.getThreadHistory(r);if(o.push({role:"user",content:a,timestamp:n}),o.length>6&&o.splice(0,o.length-6),!this.aiConfig||this.aiConfig.enabled!==!0||!this.aiConfig.provider)return this.logger.debug(`[HeadlessAutomation] Bot AI is disabled or unconfigured. Message saved, no auto-reply sent for thread ${r}.`),null;let s=t.accountId,c=this.aiConfig.accountBotConfigs,l=s&&c?c[s]:void 0;if(!l||!l.isBotEnabled)return this.logger.debug(`[HeadlessAutomation] Account [${s||"unknown"}] has not been configured or enabled for Bot AI by user in Chatbot settings. Message saved, no auto-reply sent.`),null;let u=t,f=!!u.isGroup||!!u.groupId||typeof t.threadId=="string"&&t.threadId.startsWith("g")||typeof t.conversationId=="string"&&t.conversationId.startsWith("g"),d=l.replyTarget||"all";if(d==="individual"&&f)return this.logger.debug(`[HeadlessAutomation] Account [${s}] configured for individual chat only. Skipping group message ${r}.`),null;if(d==="group"&&!f)return this.logger.debug(`[HeadlessAutomation] Account [${s}] configured for group chat only. Skipping direct message ${r}.`),null;let h=l.scheduleType||"always";if(h!=="always"){let _=new Date().getHours(),S=l.scheduleStartHour??8,R=l.scheduleEndHour??18;if(h==="working_hours"){if(_<S||_>=R)return this.logger.debug(`[HeadlessAutomation] Outside working hours (${_}h, allowed: ${S}h-${R}h). Skipping reply.`),null}else if(h==="outside_hours"&&_>=S&&_<R)return this.logger.debug(`[HeadlessAutomation] Inside working hours (${_}h, allowed outside: ${S}h-${R}h). Skipping reply.`),null}let v=l.excludeContactIds||[];if(!f&&v.length>0){let _=String(t.senderId||"");if(v.includes(_))return this.logger.debug(`[HeadlessAutomation] Sender ${_} is in contact blacklist. Skipping reply.`),null}if(f){let _=String(u.groupId||u.threadId||r||""),S=l.excludeGroupIds||[],R=l.includeGroupIds||[];if(S.length>0&&S.includes(_))return this.logger.debug(`[HeadlessAutomation] Group ${_} is in group blacklist. Skipping reply.`),null;if(R.length>0&&!R.includes(_))return this.logger.debug(`[HeadlessAutomation] Group ${_} is not in group whitelist. Skipping reply.`),null}let w=l.excludeKeywords||[],k=l.includeKeywords||[],m=a.toLowerCase();if(w.length>0&&w.some(S=>{let R=S.trim().toLowerCase();return R.length>0&&m.includes(R)}))return this.logger.debug("[HeadlessAutomation] Message contains blacklisted keyword. Skipping reply."),null;if(k.length>0&&!k.some(S=>{let R=S.trim().toLowerCase();return R.length>0&&m.includes(R)}))return this.logger.debug("[HeadlessAutomation] Message does not match any whitelist keyword. Skipping reply."),null;let x=l.systemPrompt&&l.systemPrompt.trim()?l.systemPrompt:this.aiConfig.systemPrompt;if(this.aiConfig.provider==="rule_based")return this.aiConfig.fallbackMessage&&this.aiConfig.fallbackMessage.trim().length>0?(this.lastReplyTimes.set(r,n),this.aiConfig.fallbackMessage.trim()):null;let b=this.aiConfig.provider,y=this.aiConfig.apiKey;if(y||(b==="openai"?y=process.env.OPENAI_API_KEY:b==="deepseek"?y=process.env.DEEPSEEK_API_KEY:b==="anthropic"?y=process.env.ANTHROPIC_API_KEY:b==="custom"?y=process.env.CUSTOM_AI_API_KEY:b==="gemini"&&(y=process.env.GEMINI_API_KEY||process.env.GOOGLE_API_KEY)),!y&&b!=="custom")return this.logger.debug(`[HeadlessAutomation] No API key found for provider [${b}]. No auto-reply sent.`),null;try{let _=null;if(b==="openai"||b==="custom"||b==="deepseek")_=await this.callOpenAiCompatible(a,o,y||"",x);else if(b==="anthropic")_=await this.callAnthropic(a,o,y||"",x);else if(b==="gemini")_=await this.callGemini(a,o,y||"",x);else return this.logger.warn(`[HeadlessAutomation] Unsupported AI provider [${b}]. No reply generated.`),null;if(_&&_.trim().length>0){let S=_.trim();return o.push({role:"model",content:S,timestamp:Date.now()}),this.lastReplyTimes.set(r,Date.now()),S}}catch(_){this.logger.warn(`[HeadlessAutomation] AI generation error with provider [${b}] (${_?.message}).`)}return this.aiConfig.fallbackMessage&&this.aiConfig.fallbackMessage.trim().length>0?(this.lastReplyTimes.set(r,Date.now()),this.aiConfig.fallbackMessage.trim()):null}getThreadHistory(t){let r=this.threadHistory.get(t);return r||(r=[],this.threadHistory.set(t,r)),r}async callGemini(t,r,n,i){let o=`https://generativelanguage.googleapis.com/v1beta/models/${this.aiConfig.model||"gemini-2.0-flash"}:generateContent?key=${n}`,s=r.map(d=>({role:d.role==="model"?"model":"user",parts:[{text:d.content}]}));(s.length===0||s[s.length-1].parts[0]?.text!==t)&&s.push({role:"user",parts:[{text:t}]});let c={contents:s,generationConfig:{temperature:this.aiConfig.temperature??.7,maxOutputTokens:this.aiConfig.maxTokens??300}},l=i||this.aiConfig.systemPrompt;l&&l.trim()&&(c.systemInstruction={parts:[{text:l.trim()}]});let u=new AbortController,f=setTimeout(()=>u.abort(),7e3);try{let d=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(c),signal:u.signal});if(!d.ok){let w=await d.text();return this.logger.warn(`[HeadlessAutomation] Gemini API returned status ${d.status}: ${w.slice(0,200)}`),null}return(await d.json())?.candidates?.[0]?.content?.parts?.[0]?.text||null}finally{clearTimeout(f)}}async callOpenAiCompatible(t,r,n,i){let a=(this.aiConfig.baseUrl||(this.aiConfig.provider==="deepseek"?"https://api.deepseek.com/v1":"https://api.openai.com/v1")).replace(/\/+$/,"");a.includes("api.deepseek.com")&&!a.endsWith("/v1")?a+="/v1":(a.includes("11434")||a.includes("ollama"))&&(a=a.replace(/\/api$/,"").replace(/\/+$/,""),a.endsWith("/v1")||(a+="/v1"));let o=`${a}/chat/completions`,s=this.aiConfig.model||(this.aiConfig.provider==="deepseek"?"deepseek-chat":this.aiConfig.provider==="openai"?"gpt-4o-mini":"deepseek-chat"),c=i||this.aiConfig.systemPrompt,l=[...c&&c.trim()?[{role:"system",content:c.trim()}]:[],...r.map(h=>({role:h.role==="model"?"assistant":"user",content:h.content}))],u={"Content-Type":"application/json"};n&&(u.Authorization=`Bearer ${n}`);let f=new AbortController,d=setTimeout(()=>f.abort(),8e3);try{let h=await fetch(o,{method:"POST",headers:u,body:JSON.stringify({model:s,messages:l,temperature:this.aiConfig.temperature??.7,max_tokens:this.aiConfig.maxTokens??300}),signal:f.signal});if(!h.ok){let w=await h.text();return this.logger.warn(`[HeadlessAutomation] OpenAI-compatible API returned status ${h.status}: ${w.slice(0,200)}`),null}return(await h.json())?.choices?.[0]?.message?.content||null}finally{clearTimeout(d)}}async callAnthropic(t,r,n,i){let a="https://api.anthropic.com/v1/messages",o=this.aiConfig.model||"claude-3-5-haiku-20241022",s=r.map(u=>({role:u.role==="model"?"assistant":"user",content:u.content}));(s.length===0||s[s.length-1].content!==t)&&s.push({role:"user",content:t});let c=new AbortController,l=setTimeout(()=>c.abort(),8e3);try{let u=i||this.aiConfig.systemPrompt,f={model:o,messages:s,max_tokens:this.aiConfig.maxTokens??300,temperature:this.aiConfig.temperature??.7};u&&u.trim()&&(f.system=u.trim());let d=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":n,"anthropic-version":"2023-06-01"},body:JSON.stringify(f),signal:c.signal});if(!d.ok){let v=await d.text();return this.logger.warn(`[HeadlessAutomation] Anthropic API returned status ${d.status}: ${v.slice(0,200)}`),null}return(await d.json())?.content?.[0]?.text||null}finally{clearTimeout(l)}}clear(){this.campaigns.clear(),this.rules.clear(),this.threadHistory.clear(),this.lastReplyTimes.clear()}};var Jg=le(it()),Nc=class{logger;endpoint;projectId;apiKey;constructor(t,r){this.logger=t||(0,Jg.createLogger)("PushNotificationDispatcher"),this.endpoint=r?.endpoint||process.env.APPWRITE_ENDPOINT||"https://api.softty.net/v1",this.projectId=r?.projectId||process.env.APPWRITE_PROJECT_ID||"699cfc3100136099c1c1",this.apiKey=r?.apiKey||process.env.APPWRITE_API_KEY}formatMessagePreview(t){if(t.isRecall)return"[Tin nh\u1EAFn \u0111\xE3 \u0111\u01B0\u1EE3c thu h\u1ED3i]";let r=t.content,n=String(t.messageType||"").toLowerCase(),i=null;if(typeof r=="string"&&r.trim().startsWith("{")&&r.trim().endsWith("}"))try{i=JSON.parse(r)}catch{}else typeof r=="object"&&r!==null&&(i=r);let a=c=>!!(c&&(/\.(png|jpg|jpeg|gif|webp)(\?|#|$)/i.test(c)||c.includes("photo-stal")||c.includes("zdn.vn"))),o=c=>!!(c&&/\.(mp3|m4a|wav|aac|ogg|opus)(\?|#|$)/i.test(c)),s=c=>!!(c&&/\.(mp4|avi|mov|mkv|wmv|flv)(\?|#|$)/i.test(c));if(i){let c=String(i.msgType||i.type||n).toLowerCase(),l=String(i.title||i.fileName||i.filename||i.name||"").trim(),u=String(i.href||i.url||i.rawUrl||"");if(i.id&&(i.cateId!==void 0||i.type==="sticker")||c.includes("sticker"))return"[Nh\xE3n d\xE1n]";if(c.includes("photo")||c.includes("image")||a(u)||a(l))return l&&!l.startsWith("http")&&!a(l)?`[H\xECnh \u1EA3nh] ${l}`:"[H\xECnh \u1EA3nh]";if(c.includes("video")||s(l)||s(u))return l&&!l.startsWith("http")?`[Video] ${l}`:"[Video]";if(c.includes("voice")||c.includes("audio")||o(l)||o(u))return"[Tin nh\u1EAFn tho\u1EA1i]";if(c.includes("file")||i.fileSize!==void 0)return o(l)?"[Tin nh\u1EAFn tho\u1EA1i]":s(l)?`[Video] ${l}`:a(l)?`[H\xECnh \u1EA3nh] ${l}`:l?`[T\u1EADp tin] ${l}`:"[T\u1EADp tin]";if(c.includes("contact")||String(i.action||"").includes("recommended.user"))return l?`[Danh thi\u1EBFp] ${l}`:"[Danh thi\u1EBFp]";if(c.includes("location")||i.lat!==void 0)return i.address||l?`[V\u1ECB tr\xED] ${i.address||l}`:"[V\u1ECB tr\xED]";if(c.includes("poll"))return i.question||i.topic?`[B\xECnh ch\u1ECDn] ${i.question||i.topic}`:"[B\xECnh ch\u1ECDn]";if(c.includes("bank"))return"[Th\xF4ng tin chuy\u1EC3n kho\u1EA3n]";if(c.includes("link"))return l&&!l.startsWith("http")?`[Li\xEAn k\u1EBFt] ${l}`:"[Li\xEAn k\u1EBFt]";if(i.text||i.msg||i.message)return String(i.text||i.msg||i.message)}if(n==="image"||n.includes("photo"))return"[H\xECnh \u1EA3nh]";if(n==="video")return"[Video]";if(n==="audio"||n.includes("voice"))return"[Tin nh\u1EAFn tho\u1EA1i]";if(n==="file")return"[T\u1EADp tin]";if(n==="sticker")return"[Nh\xE3n d\xE1n]";if(n==="location")return"[V\u1ECB tr\xED]";if(n==="contact")return"[Danh thi\u1EBFp]";if(typeof r=="string"){let c=r.trim();return c?a(c)?"[H\xECnh \u1EA3nh]":c.startsWith("{")&&c.endsWith("}")?c.includes("photo-stal")?"[H\xECnh \u1EA3nh]":"[\u0110\xEDnh k\xE8m ph\u01B0\u01A1ng ti\u1EC7n]":c.length>120?`${c.slice(0,117)}...`:c:"\u0110\xE3 g\u1EEDi m\u1ED9t tin nh\u1EAFn m\u1EDBi"}return"\u0110\xE3 g\u1EEDi m\u1ED9t tin nh\u1EAFn m\u1EDBi"}async dispatchMessageAlert(t,r,n,i){if(r.isRecall||r.deleted_at)return!1;let a=r.timestamp??r.time,o=Number(a||0);if(o>0){let h=o<1e11?o*1e3:o,v=Date.now()-h;if(v>12e4||v<-6e4)return this.logger.debug(`Suppressed stale push alert for message ${r.id} (age: ${Math.round(v/1e3)}s)`),!1}let s=r.metadata?.rawPayload||r.rawPayload||r,c=!!(r.isGroup||s?.isGroup||Number(s?.type)===1||Number(s?.data?.type)===1||s?.groupId||s?.data?.groupId||r.type==="group"||r.threadType===1||r.threadType==="group"||String(r.threadId||"").startsWith("g")),l=r.groupName||r.threadName||s?.groupName||s?.data?.groupName||"Nh\xF3m Zalo",u=this.formatMessagePreview(r),f=c?l:r.senderName||"Kh\xE1ch h\xE0ng",d=c?`${r.senderName||"Th\xE0nh vi\xEAn"}: ${u}`:u;return d.length>130&&(d=`${d.slice(0,127)}...`),this.sendNotification({recipientToken:t,title:f,body:d,platform:n,userId:i,data:{messageId:r.id,threadId:r.threadId,platform:r.platform,accountId:r.accountId}})}async enqueueNotification(t,r,n){if(t.isSelf||t.isRecall||t.deleted_at)return!1;let i=t.timestamp??t.time,a=Number(i||0);if(a>0){let v=a<1e11?a*1e3:a,w=Date.now()-v;if(w>12e4||w<-6e4)return this.logger.debug(`Suppressed stale push alert for message ${t.id} (age: ${Math.round(w/1e3)}s)`),!1}let o=t.metadata?.rawPayload||t.rawPayload||t,s=!!(t.isGroup||o?.isGroup||Number(o?.type)===1||Number(o?.data?.type)===1||o?.groupId||o?.data?.groupId||t.type==="group"||t.threadType===1||t.threadType==="group"||String(t.threadId||"").startsWith("g")),c=t.groupName||t.threadName||o?.groupName||o?.data?.groupName||"Nh\xF3m Zalo",l=this.formatMessagePreview(t),u=s?c:t.senderName||"Kh\xE1ch h\xE0ng",f=s?`${t.senderName||"Th\xE0nh vi\xEAn"}: ${l}`:l;f.length>130&&(f=`${f.slice(0,127)}...`);let d=`pn_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,h=(s?t.groupAvatar||o?.groupAvatar||o?.data?.groupAvatar:void 0)||t.avatar||t.senderAvatar||t.groupAvatar||"";try{return await r.createDocument("push_notification_queue",d,{teamId:n.teamId||"",userId:n.userId||"",channelAccountId:n.channelAccountId||t.accountId||"",title:u,body:f,avatarUrl:h,threadId:t.threadId||t.conversationId||"",platform:t.platform||"zalo",msgId:t.id||d}),this.logger.debug(`Enqueued push notification ${d} for message ${t.id}`),!0}catch(v){return this.logger.warn(`Failed to enqueue push notification: ${v?.message}`),!1}}async sendNotification(t){if(this.logger.debug(`Dispatching push notification to device token: ${t.recipientToken.slice(0,8)}...`),t.recipientToken.startsWith("ExponentPushToken")||t.recipientToken.startsWith("ExpoPushToken"))try{return(await fetch("https://exp.host/--/api/v2/push/send",{method:"POST",headers:{Accept:"application/json","Accept-encoding":"gzip, deflate","Content-Type":"application/json"},body:JSON.stringify({to:t.recipientToken,title:t.title,body:t.body,data:t.data,sound:"default",priority:"high",channelId:"default"})})).ok}catch(r){this.logger.warn(`Expo push send error: ${r?.message}`)}if(this.apiKey)try{let r=t.platform==="ios"||t.recipientToken.length===64,n=t.recipientToken.replace(/[^a-zA-Z0-9]/g,""),i=`${r?"apns":"fcm"}_${n.slice(0,31)}`,a=`${this.endpoint}/messaging/messages/push`;if((await fetch(a,{method:"POST",headers:{"Content-Type":"application/json","X-Appwrite-Project":this.projectId,"X-Appwrite-Key":this.apiKey},body:JSON.stringify({messageId:`push_${Date.now()}_${Math.random().toString(36).slice(2,7)}`,title:t.title,body:t.body,data:t.data||{},targets:[i],draft:!1})})).ok)return!0}catch(r){this.logger.warn(`Appwrite push send error: ${r?.message}`)}return!0}};var GP=le(require("http")),VP=require("url"),JP=le(it());var WP=le(it()),wo=class{static logger=(0,WP.createLogger)("ChannelRunnerFactory");static async createRunner(t,r,n,i){let a=(t||"zalo").toLowerCase(),o=a==="web"||a.includes("zalo")?"zalo":a;try{if(o==="zalo"){let{ZaloChannelRunner:s}=await Promise.resolve().then(()=>(HP(),qP));return new s(r,n,i)}return this.logger.warn(`Unsupported platform for ChannelRunner: ${t}`),null}catch(s){return this.logger.error(`Failed to dynamically initialize runner for ${o}:${r}:`,s?.message||s),null}}};var Fp=class{constructor(t,r,n,i,a){this.port=t;this.engine=r;this.lockManager=n;this.deltaQueue=i;this.logger=a||(0,JP.createLogger)("WorkerHttpServer")}logger;server=null;async start(){if(!this.server)return new Promise((t,r)=>{this.server=GP.default.createServer((n,i)=>{this.handleRequest(n,i).catch(a=>{this.logger.error("Unhandled HTTP error:",a),i.headersSent||(i.writeHead(500,{"Content-Type":"application/json"}),i.end(JSON.stringify({error:"Internal Server Error"})))})}),this.server.listen(this.port,()=>{this.logger.info(`\u{1F680} Worker HTTP Server listening on port ${this.port}`),t()}),this.server.on("error",n=>{this.logger.error(`Worker HTTP Server error on port ${this.port}:`,n),r(n)})})}async stop(){if(this.server)return new Promise(t=>{this.server?.close(()=>{this.logger.info("Worker HTTP Server closed."),this.server=null,t()})})}async handleRequest(t,r){let n=new VP.URL(t.url||"/",`http://${t.headers.host||"localhost"}`),i=n.pathname,a=(t.method||"GET").toUpperCase();if(r.setHeader("Access-Control-Allow-Origin","*"),r.setHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS"),r.setHeader("Access-Control-Allow-Headers","Content-Type, X-Softty-User-Id, X-Desktop-Secret, Authorization"),a==="OPTIONS"){r.writeHead(204),r.end();return}if(a==="GET"&&i==="/health"){let o=this.engine.getMetrics();r.writeHead(200,{"Content-Type":"application/json"}),r.end(JSON.stringify({status:"healthy",timestamp:Date.now(),pendingDeltaMessages:this.deltaQueue.getCount(),metrics:o}));return}if(i.startsWith("/api/v1/")){let o=this.engine.config.desktopSecret;if(o){let s=t.headers["x-desktop-secret"]||t.headers.authorization;if((typeof s=="string"&&s.startsWith("Bearer ")?s.slice(7):s)!==o){r.writeHead(401,{"Content-Type":"application/json"}),r.end(JSON.stringify({error:"Unauthorized: Invalid or missing X-Desktop-Secret"}));return}}}if(a==="POST"&&i==="/api/v1/sentinel/handover"){let o=await this.readJsonBody(t),{deviceId:s,sessions:c,aiConfig:l}=o||{};if(l&&(this.engine.automationEngine.configure(l),this.logger.info(`[Handover] Configured 24/7 AI automation engine with provider: ${l.provider||"gemini"}, model: ${l.model||"default"}`)),!Array.isArray(c)){r.writeHead(400,{"Content-Type":"application/json"}),r.end(JSON.stringify({error:"Invalid sessions array payload"}));return}this.logger.info(`[Handover] Received handover request from device ${s||"unknown"} with ${c.length} sessions.`);let u=0;for(let f of c){if(!f.id||!f.nightWorkerEnabled)continue;if(!this.lockManager.acquireLock(f.id,`worker_${f.id}`)){this.logger.warn(`Skipping account ${f.id} because lock was not acquired.`);continue}let h=(f.platform||"zalo").toLowerCase(),v=h==="web"||h.includes("zalo")?"zalo":h,w=await wo.createRunner(v,f.id,f.sessionData);w&&(this.engine.registerRunner(w),await w.start(),this.engine.registerAccount({id:f.id,platform:v,accountName:f.accountName||f.id,status:"active",nightWorkerEnabled:!0}),u++)}r.writeHead(200,{"Content-Type":"application/json"}),r.end(JSON.stringify({success:!0,message:"Sessions handed over successfully",activatedCount:u,timestamp:Date.now()}));return}if(a==="POST"&&i==="/api/v1/sentinel/reclaim"){let o=await this.readJsonBody(t),{deviceId:s}=o||{};this.logger.info(`[Reclaim] Master device ${s||"desktop"} reclaiming all active sessions. Stopping cloud runners...`);let c=this.engine.channelRunnerRegistry.getCount();await this.engine.channelRunnerRegistry.stopAll(),this.lockManager.releaseAllForOwner("worker"),r.writeHead(200,{"Content-Type":"application/json"}),r.end(JSON.stringify({success:!0,reclaimedCount:c,timestamp:Date.now()}));return}if(i==="/api/v1/sentinel/night-config"){if(a==="POST"){let o=await this.readJsonBody(t);o&&(this.engine.automationEngine.configure(o),this.logger.info(`[NightConfig] Updated 24/7 AI config dynamically: provider=${o.provider||"gemini"}, model=${o.model||"default"}`)),r.writeHead(200,{"Content-Type":"application/json"}),r.end(JSON.stringify({success:!0,config:this.engine.automationEngine.getAiConfig()}));return}else if(a==="GET"){r.writeHead(200,{"Content-Type":"application/json"}),r.end(JSON.stringify({success:!0,config:this.engine.automationEngine.getAiConfig()}));return}}if(a==="GET"&&i==="/api/v1/sync/delta"){let o=n.searchParams.get("accountId")||void 0,s=parseInt(n.searchParams.get("since")||"0",10),c=this.deltaQueue.getDeltas(o,s);this.logger.info(`[DeltaSync] Serving ${c.length} night messages (since: ${s}, account: ${o||"all"})`),r.writeHead(200,{"Content-Type":"application/json"}),r.end(JSON.stringify({success:!0,messages:c,count:c.length,syncedTimestamp:Date.now()}));return}r.writeHead(404,{"Content-Type":"application/json"}),r.end(JSON.stringify({error:"Endpoint not found"}))}readJsonBody(t){return new Promise(r=>{let n="";t.on("data",i=>{n+=i}),t.on("end",()=>{try{r(JSON.parse(n))}catch{r({})}})})}};var pa=le(it());var Dp=le(require("fs")),P0=le(require("path")),_o=require("child_process"),QP=le(it());var yt=le(require("fs")),ZP=le(require("os")),ua=le(require("path")),KP=le(require("zlib")),R0=le(require("crypto")),YP=le(require("module")),XP=le(it()),T0="__ZPLUS_RUNTIME_BOOTSTRAPPED__",ki=class{static PACKAGE_NAME="@softtynet/zplus-worker";static getRuntimeDir(){let t=process.env.ZPLUS_HOME||process.env.DATA_DIR||ua.default.join(ZP.default.homedir(),".zplus");return ua.default.join(t,"runtime")}static getRuntimeCliPath(){return ua.default.join(this.getRuntimeDir(),"cli.js")}static getRuntimeVersionPath(){return ua.default.join(this.getRuntimeDir(),"version.json")}static isNewerVersion(t,r){let n=u=>u.replace(/^v/,"").trim().split("-")[0].split(".").map(f=>parseInt(f,10)||0),[i=0,a=0,o=0]=n(t),[s=0,c=0,l=0]=n(r);return i!==s?i>s:a!==c?a>c:o>l}static getInstalledRuntimeVersion(){try{let t=this.getRuntimeVersionPath(),r=this.getRuntimeCliPath();if(!yt.default.existsSync(t)||!yt.default.existsSync(r)||yt.default.statSync(r).size<1024)return null;let n=JSON.parse(yt.default.readFileSync(t,"utf-8"));return n?.version?String(n.version).trim():null}catch{return null}}static extractFileFromTarGz(t,r="package/dist/cli.js"){let n=KP.default.gunzipSync(t),i=0;for(;i+512<=n.length;){let a=n.subarray(i,i+512);if(a.every(w=>w===0))break;let o=(w,k)=>a.subarray(w,k).toString("utf-8").replace(/\0.*$/,"").trim(),s=o(0,100),c=o(345,500),l=c?`${c}/${s}`:s,u=parseInt(o(124,136),8)||0,f=a[156],d=f===0||f===48,h=i+512,v=h+u;if(d&&u>0&&v<=n.length&&(l===r||l.endsWith("/dist/cli.js")))return Buffer.from(n.subarray(h,v));i=h+Math.ceil(u/512)*512}return null}static async downloadAndInstallRuntimeBundle(t="latest",r=(0,XP.createLogger)("RuntimeBundleManager")){try{let n=t.replace(/^v/,"").trim()||"latest",i=await fetch(`https://registry.npmjs.org/${this.PACKAGE_NAME}/${n}`,{headers:{Accept:"application/json"},signal:AbortSignal.timeout(1e4)});if(!i.ok)throw new Error(`NPM Registry metadata HTTP ${i.status}`);let a=await i.json(),o=String(a?.version||"").trim(),s=String(a?.dist?.tarball||"").trim(),c=String(a?.dist?.shasum||"").trim(),l=String(a?.dist?.integrity||"").trim();if(!o||!s)throw new Error("Thi\u1EBFu th\xF4ng tin version ho\u1EB7c tarball t\u1EEB NPM Registry");let u=await fetch(s,{signal:AbortSignal.timeout(6e4)});if(!u.ok)throw new Error(`T\u1EA3i tarball th\u1EA5t b\u1EA1i: HTTP ${u.status}`);let f=Buffer.from(await u.arrayBuffer());if(l.startsWith("sha512-")){let b=l.slice(7);if(R0.default.createHash("sha512").update(f).digest("base64")!==b)throw new Error("M\xE3 ki\u1EC3m tra to\xE0n v\u1EB9n SHA-512 kh\xF4ng kh\u1EDBp!")}else if(c&&R0.default.createHash("sha1").update(f).digest("hex")!==c)throw new Error("M\xE3 ki\u1EC3m tra to\xE0n v\u1EB9n SHA-1 (shasum) kh\xF4ng kh\u1EDBp!");let d=this.extractFileFromTarGz(f,"package/dist/cli.js");if(!d||d.length<1024)throw new Error("Kh\xF4ng t\xECm th\u1EA5y ho\u1EB7c t\u1EC7p dist/cli.js trong g\xF3i kh\xF4ng h\u1EE3p l\u1EC7");let h=this.getRuntimeDir();yt.default.existsSync(h)||yt.default.mkdirSync(h,{recursive:!0});let v=this.getRuntimeCliPath(),w=`${v}.${process.pid}.tmp`;yt.default.writeFileSync(w,d,{mode:493}),yt.default.renameSync(w,v);let k={version:o,updatedAt:new Date().toISOString(),integrity:l||c},m=`${this.getRuntimeVersionPath()}.${process.pid}.tmp`;yt.default.writeFileSync(m,JSON.stringify(k,null,2)),yt.default.renameSync(m,this.getRuntimeVersionPath());let x="/app/cli.js";if(yt.default.existsSync(x))try{yt.default.accessSync(x,yt.default.constants.W_OK);try{let b=`${x}.${process.pid}.tmp`;yt.default.writeFileSync(b,d,{mode:493}),yt.default.renameSync(b,x)}catch{yt.default.writeFileSync(x,d,{mode:493})}}catch{}return r.info(`\u{1F4E6} [RuntimeBundle] \u0110\xE3 t\u1EA3i v\xE0 x\xE1c th\u1EF1c g\xF3i v${o} v\xE0o b\u1ED9 nh\u1EDB b\u1EC1n v\u1EEFng (${v})`),{success:!0,version:o,cliPath:v}}catch(n){return r.warn(`\u26A0\uFE0F [RuntimeBundle] Kh\xF4ng th\u1EC3 t\u1EA3i tr\u1EF1c ti\u1EBFp bundle t\u1EEB Registry: ${n?.message||n}`),{success:!1}}}static tryBootstrapNewerRuntime(t){if(globalThis[T0])return!1;try{let r=this.getInstalledRuntimeVersion();if(!r||!this.isNewerVersion(r,t))return!1;let n=this.getRuntimeCliPath();return ua.default.resolve(process.argv[1]||"")===ua.default.resolve(n)?!1:(globalThis[T0]=r,YP.default.createRequire(n)(n),!0)}catch{globalThis[T0]=void 0;try{yt.default.existsSync(this.getRuntimeVersionPath())&&yt.default.unlinkSync(this.getRuntimeVersionPath())}catch{}return!1}}};var Bp=class e{logger;timer;isUpdating=!1;constructor(t){this.logger=t||(0,QP.createLogger)("WorkerAutoUpdater")}static getNpmExecutionInfo(){let t=P0.default.dirname(process.execPath),r=P0.default.join(t,process.platform==="win32"?"npm.cmd":"npm"),n=Dp.default.existsSync(r)?`"${r}"`:"npm",i={...process.env,PATH:`${t}:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:${process.env.PATH||""}`};return{npmBin:n,env:i}}static isDocker(){return Dp.default.existsSync("/.dockerenv")||Dp.default.existsSync("/run/.containerenv")||!!process.env.DOCKER_CONTAINER}static isNewerVersion(t,r){return ki.isNewerVersion(t,r)}async fetchLatestVersion(){let t="@softtynet/zplus-worker";try{let r=new AbortController,n=setTimeout(()=>r.abort(),5e3),i=await fetch(`https://registry.npmjs.org/${t}/latest`,{signal:r.signal,headers:{Accept:"application/json"}});if(clearTimeout(n),i.ok){let a=await i.json();if(a?.version)return String(a.version).trim()}}catch{}try{let{npmBin:r,env:n}=e.getNpmExecutionInfo();return(0,_o.execSync)(`${r} view ${t} version`,{encoding:"utf-8",timeout:8e3,stdio:["ignore","pipe","ignore"],env:n}).trim()}catch{return null}}async checkUpdate(t){let r=await this.fetchLatestVersion();return r?{hasUpdate:e.isNewerVersion(r,t),latestVersion:r}:{hasUpdate:!1,latestVersion:t}}async performUpdateAndRestart(t){if(this.isUpdating)return this.logger.warn("C\u1EADp nh\u1EADt \u0111ang di\u1EC5n ra, b\u1ECF qua y\xEAu c\u1EA7u tr\xF9ng l\u1EB7p."),!1;this.isUpdating=!0;let r=t||"latest",n=`@softtynet/zplus-worker@${r}`,i=e.isDocker();this.logger.info(`\u{1F680} [AutoUpdater] B\u1EAFt \u0111\u1EA7u t\u1EF1 \u0111\u1ED9ng n\xE2ng c\u1EA5p Worker l\xEAn ${n} (M\xF4i tr\u01B0\u1EDDng: ${i?"Docker Container":"Host NPM"})...`);let a=!1,o=!1;try{if(a=(await ki.downloadAndInstallRuntimeBundle(r,this.logger)).success,!i)try{let{npmBin:c,env:l}=e.getNpmExecutionInfo();(0,_o.execSync)(`${c} install -g ${n}`,{stdio:"inherit",timeout:12e4,env:l}),o=!0,this.logger.info(`\u2705 [AutoUpdater] \u0110\xE3 c\u1EADp nh\u1EADt g\xF3i NPM to\xE0n c\u1EE5c: ${n}!`)}catch(c){if(a)this.logger.info("\u2139\uFE0F [AutoUpdater] B\u1ECF qua c\u1EADp nh\u1EADt global npm (thi\u1EBFu quy\u1EC1n root), \u0111\xE3 s\u1EED d\u1EE5ng Runtime Bundle t\u1EA1i ~/.zplus/runtime/cli.js.");else throw c}if(!a&&!o)throw new Error("Kh\xF4ng th\u1EC3 c\u1EADp nh\u1EADt qua c\u1EA3 Runtime Bundle l\u1EABn NPM Global.");return this.logger.info(`\u2705 [AutoUpdater] \u0110\xE3 ho\xE0n t\u1EA5t n\xE2ng c\u1EA5p l\xEAn ${n}! \u0110ang kh\u1EDFi \u0111\u1ED9ng l\u1EA1i d\u1ECBch v\u1EE5...`),this.triggerRestart(),!0}catch(s){return this.isUpdating=!1,this.logger.error(`\u274C [AutoUpdater] N\xE2ng c\u1EA5p th\u1EA5t b\u1EA1i: ${s?.message||s}`),!1}}triggerRestart(){if(!e.isDocker()){try{if((0,_o.execSync)("pm2 jlist",{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:5e3}).includes("zplus-worker")){this.logger.info("\u{1F504} [AutoUpdater] \u0110ang ph\xE1t l\u1EC7nh kh\u1EDFi \u0111\u1ED9ng l\u1EA1i PM2 ti\u1EBFn tr\xECnh 'zplus-worker'...");let n=(0,_o.spawn)("pm2",["restart","zplus-worker"],{detached:!0,stdio:"ignore"});n.on("error",()=>{}),n.unref(),setTimeout(()=>process.exit(0),1e3);return}}catch{}if(!!process.stdout.isTTY&&!process.env.PM2_HOME&&!process.env.pm_id&&!process.env.INVOCATION_ID){this.logger.warn("\u26A0\uFE0F [AutoUpdater] \u0110\xE3 t\u1EA3i phi\xEAn b\u1EA3n m\u1EDBi. V\xEC \u0111ang ch\u1EA1y Worker tr\u1EF1c ti\u1EBFp tr\xEAn Terminal (kh\xF4ng qua PM2/Daemon), vui l\xF2ng nh\u1EA5n Ctrl+C v\xE0 ch\u1EA1y l\u1EA1i \u0111\u1EC3 n\u1EA1p m\xE3 m\u1EDBi."),this.isUpdating=!1;return}}this.logger.info("\u{1F504} [AutoUpdater] Ti\u1EBFn tr\xECnh s\u1EBD tho\xE1t an to\xE0n (exit 0) \u0111\u1EC3 h\u1EC7 th\u1ED1ng (Docker / OS Service) t\u1EF1 kh\u1EDFi \u0111\u1ED9ng l\u1EA1i v\u1EDBi b\u1EA3n m\u1EDBi..."),setTimeout(()=>process.exit(0),1500)}startPeriodicAutoUpdate(t,r=3600*1e3){this.timer&&clearInterval(this.timer),setTimeout(()=>this.runCheckCycle(t).catch(()=>{}),6e4),this.timer=setInterval(()=>this.runCheckCycle(t).catch(()=>{}),r),this.logger.info(`\u23F0 [AutoUpdater] \u0110\xE3 k\xEDch ho\u1EA1t c\u01A1 ch\u1EBF t\u1EF1 \u0111\u1ED9ng c\u1EADp nh\u1EADt ng\u1EA7m cho c\u1EA3 NPM & Docker (chu k\u1EF3: ${Math.round(r/6e4)} ph\xFAt).`)}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0)}async runCheckCycle(t){try{let{hasUpdate:r,latestVersion:n}=await this.checkUpdate(t);r&&(this.logger.info(`\u{1F514} [AutoUpdater] Ph\xE1t hi\u1EC7n phi\xEAn b\u1EA3n m\u1EDBi tr\xEAn NPM Registry: v${n} (hi\u1EC7n t\u1EA1i: v${t}). \u0110ang t\u1EF1 \u0111\u1ED9ng n\xE2ng c\u1EA5p...`),await this.performUpdateAndRestart(n))}catch(r){this.logger.debug("Auto-update check cycle error:",r?.message)}}};var Jn=le(require("fs")),Np=le(require("path")),Lp=le(require("os")),e4=le(require("readline")),kn=le(it()),ko=class{logger;lastReconciledToken="";lastReconciledAt=0;constructor(t){this.logger=t||(0,kn.createLogger)("WorkerAuthManager")}getWorkerDeviceKey(){let r=(process.env.WORKER_ID||process.env.HOSTNAME||Lp.default.hostname()||"default").replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,48);return r.startsWith("worker_")?r:`worker_${r}`}async reconcileWorkerSession(t,r=process.env.APPWRITE_ENDPOINT||"https://api.softty.net/v1",n=process.env.APPWRITE_PROJECT_ID||"699cfc3100136099c1c1",i=!1){if(!t)return;let a=Date.now();if(!(!i&&this.lastReconciledToken===t&&a-this.lastReconciledAt<1800*1e3))try{let o=this.getWorkerDeviceKey();(await kn.AppwriteSessionJanitor.reconcileDeviceSession({endpoint:r,projectId:n,sessionSecret:t,deviceKey:o,deviceType:"worker",deviceName:`ZPlus Worker (${Lp.default.hostname()})`,pinned:!0})).currentSessionId&&(this.lastReconciledToken=t,this.lastReconciledAt=a)}catch(o){this.logger.debug("reconcileWorkerSession warning:",o?.message)}}extractSessionTokenFromResponse(t,r){let n=r?.secret||"";if(!n&&t?.headers?.get&&(n=t.headers.get("x-appwrite-session")||""),!n&&t?.headers){let i=typeof t.headers.getSetCookie=="function"?t.headers.getSetCookie():[t.headers.get&&t.headers.get("set-cookie")||""];for(let a of i){let o=a.match(/a_session_[^=]+=([^;]+)/);if(o&&o[1]){n=decodeURIComponent(o[1]);break}}}if(!n&&t?.headers?.get)try{let i=t.headers.get("x-fallback-cookies");if(i){let a=JSON.parse(i);for(let o of Object.keys(a))if(o.startsWith("a_session_")){n=a[o];break}}}catch{}return n}syncRecoveryTokenFromCloud(t){if(!t||typeof t!="string")return;let r=this.loadStoredAuth();if(r){if(r.authType==="cluster_session"||r.authType==="credentials"){r.refreshToken&&(delete r.refreshToken,this.saveAuth(r));return}r.refreshToken!==t&&(r.refreshToken=t,this.saveAuth(r),this.logger.info("\u{1F504} [AuthManager] \u0110\xE3 \u0111\u1ED3ng b\u1ED9 ch\xECa kh\xF3a ph\u1EE5c h\u1ED3i phi\xEAn 24/7 m\u1EDBi nh\u1EA5t t\u1EEB Cloud."))}}getAuthFilePath(){let t=process.env.DATA_DIR||Np.default.join(Lp.default.homedir(),".zplus");return Np.default.join(t,"worker_auth.json")}loadStoredAuth(){try{let t=this.getAuthFilePath();if(!Jn.default.existsSync(t))return null;let r=Jn.default.readFileSync(t,"utf-8"),n=JSON.parse(r);return!n||!n.sessionToken?null:n}catch(t){return this.logger.debug("Failed to read worker_auth.json:",t?.message),null}}saveAuth(t){try{let r=this.getAuthFilePath(),n=Np.default.dirname(r);Jn.default.existsSync(n)||Jn.default.mkdirSync(n,{recursive:!0,mode:448}),Jn.default.writeFileSync(r,JSON.stringify(t,null,2),{encoding:"utf-8",mode:384});try{Jn.default.chmodSync(r,384)}catch{}this.logger.info(`\u2705 Phi\xEAn x\xE1c th\u1EF1c \u0111\xE3 \u0111\u01B0\u1EE3c l\u01B0u an to\xE0n t\u1EA1i: ${r} (Quy\u1EC1n 0600 - Ch\u1EC9 Owner)`)}catch(r){this.logger.error("Could not save worker_auth.json:",r)}}clearAuth(t=process.env.APPWRITE_ENDPOINT||"https://api.softty.net/v1",r=process.env.APPWRITE_PROJECT_ID||"699cfc3100136099c1c1"){try{let n=this.loadStoredAuth();n?.sessionToken&&kn.AppwriteSessionJanitor.revokeCurrentDeviceSession({endpoint:t,projectId:r,sessionSecret:n.sessionToken,deviceKey:this.getWorkerDeviceKey()}).catch(()=>{});let i=this.getAuthFilePath();Jn.default.existsSync(i)&&Jn.default.unlinkSync(i),this.logger.info("\u0110\xE3 x\xF3a phi\xEAn \u0111\u0103ng nh\u1EADp c\u1EE7a Worker.")}catch(n){this.logger.debug("clearAuth error:",n?.message)}}async verifyEntitlements(t,r=process.env.APPWRITE_ENDPOINT||"https://api.softty.net/v1",n=process.env.APPWRITE_PROJECT_ID||"699cfc3100136099c1c1",i="default"){try{let a=`${r}/account`,o=t.includes(".")&&t.split(".").length===3,s={"Content-Type":"application/json","X-Appwrite-Project":n};o?s["X-Appwrite-JWT"]=t:(s["X-Appwrite-Session"]=t,s.Cookie=`a_session_${n}=${t}; a_session_${n}_legacy=${t}`,t.startsWith("eyJ")&&(s["X-Fallback-Cookies"]=JSON.stringify({[`a_session_${n}`]:t,[`a_session_${n}_legacy`]:t})));let c=await fetch(a,{method:"GET",headers:s});if(!c.ok)return{allowed:!1,userId:"",userName:"Unknown",email:"",teamId:i,isOwner:!1,isPremium:!1,reason:`Phi\xEAn \u0111\u0103ng nh\u1EADp kh\xF4ng h\u1EE3p l\u1EC7 ho\u1EB7c \u0111\xE3 h\u1EBFt h\u1EA1n (HTTP ${c.status}).`};let l=await c.json(),u=l.$id||l.id||"",f=l.name||"Ng\u01B0\u1EDDi d\xF9ng ZPlus",d=l.email||"",h=Array.isArray(l.labels)?l.labels:[],v=l.prefs||{},w=kn.AppwriteSessionJanitor.parseRegistry(v),k=this.getWorkerDeviceKey();(!w[k]?.sessionId||!w[k]?.pinned)&&(this.lastReconciledAt=0);let m=null;if(v.entitlements)try{m=typeof v.entitlements=="string"?JSON.parse(v.entitlements):v.entitlements}catch{}if(!m&&l.entitlements)try{m=typeof l.entitlements=="string"?JSON.parse(l.entitlements):l.entitlements}catch{}let x=!1;for(let[G,ee]of Object.entries(v))if(G.endsWith("_entitlements")&&typeof ee=="string")try{let X=JSON.parse(ee);if(Array.isArray(X.features))for(let pe of X.features){let ue=String(pe).toUpperCase();if(ue.includes("PREMIUM")||ue.includes("ENTERPRISE")){x=!0;break}}}catch{}let y=!h.some(G=>G.toLowerCase()==="member")&&v.isOwner!==!1,S=!(h.some(G=>G.toLowerCase()==="free")||v.tier==="free"||m?.tier==="FREE"||m?.isPremium===!1)&&!!(x||(m?.isPremium??v.isPremium??h.some(G=>G.toLowerCase()==="premium"||G.toLowerCase()==="enterprise"))),R=!S,B=S?-1:Number(m?.cloudTtlDays||v.cloudTtlDays||7),T=S?!0:m?.allowedCloudSync!==!1&&v.allowedCloudSync!==!1,z=v.teamId||v.storage?.teamId||m?.storage?.teamId||l.teamId||i;(!z||z==="default")&&m?.storage?.teamId&&(z=m.storage.teamId);let F=v.teamName||m?.teamName||"";try{let G=await fetch(`${r}/teams`,{method:"GET",headers:s});if(G.ok){let ee=await G.json().catch(()=>({})),X=Array.isArray(ee.teams)?ee.teams:[];if(X.length>0){let pe=z&&z!=="default"&&X.find(ue=>ue.$id===z)||X[0];pe&&((!z||z==="default")&&(z=pe.$id),F=pe.name||F)}}}catch{}return(!z||z==="default")&&(z=u||i),R?{allowed:T,userId:u,userName:f,email:d,teamId:z,teamName:F||void 0,isOwner:y,isPremium:!1,cloudTtlDays:B,reason:T?`\u2705 X\xE1c th\u1EF1c th\xE0nh c\xF4ng: T\xE0i kho\u1EA3n Mi\u1EC5n Ph\xED [${f}] (${d}) - Ch\u1EBF \u0111\u1ED9 \u0110\u1EC7m Cloud ${B} ng\xE0y (T\u1ED1i \u0111a 5 t\xE0i kho\u1EA3n).`:"\u26A0\uFE0F Ch\u1EBF \u0111\u1ED9 \u0111\u1EC7m Cloud t\u1EA1m th\u1EDDi b\u1ECB t\u1EAFt b\u1EDFi Qu\u1EA3n tr\u1ECB vi\xEAn Softty."}:y?{allowed:!0,userId:u,userName:f,email:d,teamId:z,teamName:F||void 0,isOwner:!0,isPremium:!0,cloudTtlDays:-1,reason:`\u2705 X\xE1c th\u1EF1c th\xE0nh c\xF4ng: Tr\u01B0\u1EDFng nh\xF3m [${f}] (${d}) - G\xF3i Doanh Nghi\u1EC7p Active.`}:{allowed:!1,userId:u,userName:f,email:d,teamId:z,teamName:F||void 0,isOwner:!1,isPremium:S,cloudTtlDays:-1,reason:`\u26A0\uFE0F T\xE0i kho\u1EA3n [${d}] l\xE0 Th\xE0nh vi\xEAn (Member). \u0110\u1EC3 b\u1EA3o v\u1EC7 d\u1EEF li\u1EC7u c\xF4ng ty, ch\u1EC9 Tr\u01B0\u1EDFng nh\xF3m (Team Owner) m\u1EDBi c\xF3 quy\u1EC1n k\xEDch ho\u1EA1t c\u1EE5m Worker cho Team.`}}catch(a){return{allowed:!1,userId:"",userName:"Unknown",email:"",teamId:i,isOwner:!1,isPremium:!1,reason:`L\u1ED7i k\u1EBFt n\u1ED1i ki\u1EC3m tra quy\u1EC1n h\u1EA1n: ${a?.message}`}}}async loginWithCredentials(t,r,n=process.env.APPWRITE_ENDPOINT||"https://api.softty.net/v1",i=process.env.APPWRITE_PROJECT_ID||"699cfc3100136099c1c1"){let a=t?.trim(),o=r;if(!a||!o){console.log(`
58
58
  ==================================================================`),console.log("\u{1F510} ZPLUS WORKER TERMINAL LOGIN (HEADLESS LINUX / VPS)"),console.log("=================================================================="),console.log("\u2139\uFE0F \u0110\u0103ng nh\u1EADp b\u1EB1ng t\xE0i kho\u1EA3n Tr\u01B0\u1EDFng nh\xF3m (Softty ID) \u0111\u1EC3 c\u1EA5p quy\u1EC1n Worker."),console.log("------------------------------------------------------------------");let s=e4.default.createInterface({input:process.stdin,output:process.stdout}),c=l=>new Promise(u=>s.question(l,u));a||(a=(await c("? Nh\u1EADp Email Tr\u01B0\u1EDFng nh\xF3m (Softty ID): ")).trim()),o||(o=await c("? Nh\u1EADp M\u1EADt kh\u1EA9u: ")),s.close()}if(!a||!o)return console.error("\u274C L\u1ED7i: Email v\xE0 m\u1EADt kh\u1EA9u kh\xF4ng \u0111\u01B0\u1EE3c \u0111\u1EC3 tr\u1ED1ng."),null;try{console.log(`
59
59
  \u23F3 \u0110ang x\xE1c th\u1EF1c v\u1EDBi m\xE1y ch\u1EE7 Softty Cloud...`);let s=`${n}/account/sessions/email`,c=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json","X-Appwrite-Project":i},body:JSON.stringify({email:a,password:o})});if(!c.ok){let v=await c.json().catch(()=>({}));return console.error(`\u274C \u0110\u0103ng nh\u1EADp th\u1EA5t b\u1EA1i: ${v?.message||"Email ho\u1EB7c m\u1EADt kh\u1EA9u kh\xF4ng ch\xEDnh x\xE1c."}`),null}let l=await c.json().catch(()=>({})),u=this.extractSessionTokenFromResponse(c,l);if(!u)return console.error("\u274C L\u1ED7i: M\xE1y ch\u1EE7 Appwrite kh\xF4ng tr\u1EA3 v\u1EC1 m\xE3 phi\xEAn x\xE1c th\u1EF1c (Session Secret)."),null;let f=await this.verifyEntitlements(u,n,i);if(console.log(`
60
60
  `+f.reason),!f.allowed&&!f.userId)return console.warn(`
@@ -66,7 +66,7 @@ Content-Type: ${a.type||"application/octet-stream"}\r
66
66
  `+w.reason),!w.allowed&&(!w.userId||w.reason.includes("401")||w.reason.includes("h\u1EBFt h\u1EA1n")))return console.warn(`
67
67
  \u274C M\xE3 gh\xE9p n\u1ED1i kh\xF4ng h\u1EE3p l\u1EC7, b\u1ECB c\u1EAFt ng\u1EAFn ho\u1EB7c \u0111\xE3 h\u1EBFt h\u1EA1n. Vui l\xF2ng l\u1EA5y m\xE3 m\u1EDBi t\u1EEB ZPlus Desktop.`),null;let k={userId:w.userId||l||"",userName:w.userName,email:w.email,teamId:w.teamId||u,teamName:w.teamName,sessionToken:d,refreshToken:h,tokenExpiresAt:v,authType:f?"cluster_session":h?"oauth_pair":"token",isOwner:w.isOwner,isPremium:w.isPremium,isAllowed:w.allowed,cloudTtlDays:w.cloudTtlDays,statusMessage:w.reason,savedAt:Date.now()};return this.saveAuth(k),await this.reconcileWorkerSession(d,r,n,!0),w.allowed?console.log(`
68
68
  \u{1F680} Gh\xE9p n\u1ED1i th\xE0nh c\xF4ng! C\u1EE5m Worker 24/7 \u0111\xE3 s\u1EB5n s\xE0ng ho\u1EA1t \u0111\u1ED9ng (T\u1EF1 duy tr\xEC phi\xEAn li\xEAn t\u1EE5c)!`):console.warn(`
69
- \u23F8\uFE0F Worker chuy\u1EC3n sang ch\u1EBF \u0111\u1ED9 STANDBY (Kh\xF4ng nh\u1EADn vi\u1EC7c, kh\xF4ng ti\xEAu t\u1ED1n t\xE0i nguy\xEAn).`),k}};var Up=class{constructor(t,r,n){this.config=t;this.engine=r;this.logger=n||(0,pa.createLogger)(`ClusterSentinel:${t.workerId}`),this.autoUpdater=new Bp(this.logger),this.authManager=new ko(this.logger)}logger;autoUpdater;authManager;refreshPromise=null;isRunning=!1;pollTimer;heartbeatTimer;cachedPeerWorkers=[];lastPeerCheckTime=0;lastNightConfigUpdatedAt=0;lastNightConfigCheck=0;lastAuthFailureTime=0;lastAuthErrorLogTime=0;isSyncingAccounts=!1;getHeaders(){let t=this.config.appwriteProjectId||"",r={"Content-Type":"application/json","X-Appwrite-Project":t};if(this.config.appwriteSessionToken){let n=this.config.appwriteSessionToken;n.includes(".")&&n.split(".").length===3?r["X-Appwrite-JWT"]=n:(r["X-Appwrite-Session"]=n,r.Cookie=`a_session_${t}=${n}; a_session_${t}_legacy=${n}`,n.startsWith("eyJ")&&(r["X-Fallback-Cookies"]=JSON.stringify({[`a_session_${t}`]:n,[`a_session_${t}_legacy`]:n})))}else this.config.appwriteJwt&&(r["X-Appwrite-JWT"]=this.config.appwriteJwt);return r}getWorkerPermissions(){let t=[],r=this.config.userId,n=this.config.teamId;return r&&t.push(`read("user:${r}")`,`update("user:${r}")`,`delete("user:${r}")`),n&&n!==r&&n!=="default"&&t.push(`read("team:${n}")`,`update("team:${n}")`,`delete("team:${n}")`),t.length===0&&t.push('read("users")','update("users")','delete("users")'),t}async handleAuthExpired(){return this.refreshPromise?await this.refreshPromise:(this.refreshPromise=(async()=>{try{let t=this.authManager.loadStoredAuth();if(t?.sessionToken&&t.sessionToken!==this.config.appwriteSessionToken){let i=await this.authManager.verifyEntitlements(t.sessionToken,this.config.appwriteEndpoint,this.config.appwriteProjectId,this.config.teamId);if(i.allowed)return this.config.appwriteSessionToken=t.sessionToken,this.config.cloudSessionToken=t.sessionToken,i.teamId&&i.teamId!=="default"&&(this.config.teamId=i.teamId),this.lastAuthFailureTime=0,this.engine.setStatus("running"),this.logger.info(`\u2705 [ClusterSentinel] \u0110\xE3 t\u1EF1 \u0111\u1ED9ng n\u1EA1p phi\xEAn \u0111\u0103ng nh\u1EADp m\u1EDBi t\u1EEB worker_auth.json! (${i.userName})`),!0}let r=Date.now();if(this.lastAuthFailureTime>0&&r-this.lastAuthFailureTime<6e4)return!1;this.logger.warn("\u26A0\uFE0F [ClusterSentinel] Phi\xEAn x\xE1c th\u1EF1c Cloud \u0111\xE3 h\u1EBFt h\u1EA1n (HTTP 401). \u0110ang k\xEDch ho\u1EA1t Silent Refresh Token 24/7...");let n=await this.authManager.ensureValidSession(this.config.appwriteEndpoint,this.config.appwriteProjectId,!0);return n?.sessionToken?(this.config.appwriteSessionToken=n.sessionToken,this.config.cloudSessionToken=n.sessionToken,n.teamId&&n.teamId!=="default"&&(this.config.teamId=n.teamId),this.lastAuthFailureTime=0,this.engine.setStatus("running"),this.logger.info(`\u2705 [ClusterSentinel] \u0110\xE3 t\u1EF1 \u0111\u1ED9ng kh\xF4i ph\u1EE5c quy\u1EC1n h\u1EA1n 24/7 th\xE0nh c\xF4ng! (${n.userName})`),!0):(this.lastAuthFailureTime=Date.now(),Date.now()-this.lastAuthErrorLogTime>300*1e3&&(this.lastAuthErrorLogTime=Date.now(),this.logger.error("\u274C [ClusterSentinel] Kh\xF4ng th\u1EC3 t\u1EF1 \u0111\u1ED9ng l\xE0m m\u1EDBi phi\xEAn. Vui l\xF2ng \u0111\u0103ng nh\u1EADp l\u1EA1i Worker qua l\u1EC7nh: zplus-worker login")),this.engine.setStatus("auth_error","M\xE1y ch\u1EE7 tr\u1EF1c ban 24/7 b\u1ECB h\u1EBFt h\u1EA1n phi\xEAn. Vui l\xF2ng ch\u1EA1y l\u1EC7nh 'zplus-worker login' \u0111\u1EC3 c\u1EA5p l\u1EA1i phi\xEAn l\xE0m vi\u1EC7c."),!1)}catch(t){return this.lastAuthFailureTime=Date.now(),this.logger.error("\u274C [ClusterSentinel] L\u1ED7i ngo\u1EA1i l\u1EC7 trong Silent Refresh Token:",t?.message),this.engine.setStatus("auth_error",`L\u1ED7i ngo\u1EA1i l\u1EC7 x\xE1c th\u1EF1c: ${t?.message||"Kh\xF4ng x\xE1c \u0111\u1ECBnh"}`),!1}finally{this.refreshPromise=null}})(),await this.refreshPromise)}isCloudConfigured(){return!!(this.config.appwriteEndpoint&&this.config.appwriteProjectId&&(this.config.appwriteSessionToken||this.config.appwriteJwt))}startAutoUpdaterOnly(){this.autoUpdater.startPeriodicAutoUpdate(this.config.version||Vt)}async start(){if(this.isRunning)return;if(this.isRunning=!0,this.startAutoUpdaterOnly(),!this.isCloudConfigured()){this.logger.info("Appwrite Cloud credentials not fully configured. Running in standalone local mode.");return}this.logger.info(`\u{1F680} Initializing Team Cluster Sentinel for Team [${this.config.teamId}] (Worker: ${this.config.workerId}, Capacity: ${this.config.maxCapacity})`),this.config.appwriteSessionToken&&this.authManager.reconcileWorkerSession(this.config.appwriteSessionToken,this.config.appwriteEndpoint,this.config.appwriteProjectId,!1).catch(()=>{}),await this.registerWorkerInstance(),this.heartbeatTimer=setInterval(()=>{this.pingWorkerHeartbeat().catch(r=>{this.logger.debug("Worker heartbeat ping error:",r?.message)})},15e3);let t=this.config.clusterPollIntervalMs||3e3;this.pollTimer=setInterval(()=>{this.syncTeamAccounts().catch(n=>{this.logger.debug("Cluster account sync error:",n?.message)});let r=Date.now();r-this.lastNightConfigCheck>3e4&&(this.lastNightConfigCheck=r,this.syncNightShiftConfig().catch(()=>{}))},t),this.syncTeamAccounts().catch(()=>{}),this.syncNightShiftConfig().catch(()=>{})}async stop(){this.isRunning=!1,this.autoUpdater.stop(),this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=void 0),this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=void 0),this.isCloudConfigured()&&await this.markWorkerOffline(),this.logger.info("Cluster Sentinel stopped.")}async syncNightShiftConfig(){if(!(!this.isRunning||!this.isCloudConfigured()||!this.config.teamId))try{let t=this.config.appwriteEndpoint,r=this.config.databaseId||"zplus_app",n=`night_cfg_${this.config.teamId}`.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),i=`${t}/databases/${r}/collections/cluster_settings/documents/${n}`,a=await fetch(i,{method:"GET",headers:this.getHeaders()});if(!a.ok)return;let o=await a.json(),s=Number(o.updated_at||0);if(s>this.lastNightConfigUpdatedAt&&o.config_json)try{let c=JSON.parse(o.config_json);if(c.encryptedWorkerRecovery)try{let l=pa.CloudCrypto.decryptFromCloud(c.encryptedWorkerRecovery,this.config.teamId,[this.config.userId||"default","default"]),u=JSON.parse(l);u?.refreshToken&&this.authManager.syncRecoveryTokenFromCloud(u.refreshToken)}catch{}this.engine.automationEngine.configure(c),this.lastNightConfigUpdatedAt=s,this.logger.info(`\u{1F319} [ClusterSentinel] Synchronized latest Night AI config from Cloud DB (Provider: ${c.provider||"default"}, Enabled: ${c.enabled})`)}catch(c){this.logger.debug("Failed to parse night config JSON from Cloud DB:",c?.message)}}catch{}}async getActivePeerWorkers(){let t=Date.now();if(t-this.lastPeerCheckTime<15e3&&this.cachedPeerWorkers.length>0)return this.cachedPeerWorkers;try{let r=this.config.appwriteEndpoint,n=this.config.databaseId||"zplus_app",i=JSON.stringify({method:"equal",attribute:"team_id",values:[this.config.teamId]}),a=JSON.stringify({method:"limit",values:[25]}),o=`${r}/databases/${n}/collections/team_workers/documents?queries[]=${encodeURIComponent(i)}&queries[]=${encodeURIComponent(a)}`,s=await fetch(o,{method:"GET",headers:this.getHeaders()});if(s.ok){let c=await s.json(),l=Array.isArray(c?.documents)?c.documents:[];this.cachedPeerWorkers=l.filter(u=>u.worker_id!==this.config.workerId&&u.status==="online"&&t-Number(u.last_ping||0)<45e3).map(u=>({workerId:u.worker_id,currentLoad:Number(u.current_load||0),maxCapacity:Number(u.max_capacity||50),lastPing:Number(u.last_ping||0)})),this.lastPeerCheckTime=t}}catch{}return this.cachedPeerWorkers}async registerWorkerInstance(){try{let t=this.config.appwriteEndpoint,r=this.config.databaseId||"zplus_app",n=this.config.workerId.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),i=Ac(),a=this.engine.channelRunnerRegistry.getCount(),o=a>this.config.maxCapacity,s=`${t}/databases/${r}/collections/team_workers/documents/${n}`,c={data:{worker_id:this.config.workerId,team_id:this.config.teamId,worker_name:this.config.workerName,max_capacity:this.config.maxCapacity,recommended_capacity:this.config.recommendedCapacity||this.config.maxCapacity,current_load:a,is_overloaded:o,system_specs:JSON.stringify({...i,version:this.config.version||Vt}),status:"online",last_ping:Date.now()}},l=await fetch(s,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify(c)});if(l.status===401&&await this.handleAuthExpired()&&(l=await fetch(s,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify(c)})),l.ok){this.logger.info(`\u2705 Worker registered in Team Cluster: ${this.config.workerId}`);return}if(l.status===404){let u=`${t}/databases/${r}/collections/team_workers/documents`,f=this.getWorkerPermissions(),d=await fetch(u,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({documentId:n,permissions:f,...c})});if(d.status===401&&await this.handleAuthExpired()&&(d=await fetch(u,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({documentId:n,permissions:f,...c})})),!d.ok&&d.status===400){let h=this.config.userId?[`read("user:${this.config.userId}")`,`update("user:${this.config.userId}")`,`delete("user:${this.config.userId}")`]:['read("users")','update("users")','delete("users")'],v={data:{worker_id:this.config.workerId,team_id:this.config.teamId,worker_name:this.config.workerName,max_capacity:this.config.maxCapacity,current_load:a,status:"online",last_ping:Date.now()}};d=await fetch(u,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({documentId:n,permissions:h,...v})})}d.ok?this.logger.info(`\u2705 Worker registered in Team Cluster: ${this.config.workerId}`):this.logger.warn(`\u26A0\uFE0F Could not register in team_workers: HTTP ${d.status}`)}else this.logger.warn(`\u26A0\uFE0F Could not patch team_workers: HTTP ${l.status}`)}catch(t){this.logger.warn("Could not register in team_workers:",t?.message)}}async pingWorkerHeartbeat(){if(!(!this.isRunning||!this.isCloudConfigured()))try{let t=this.config.appwriteEndpoint,r=this.config.databaseId||"zplus_app",n=this.config.workerId.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),i=`${t}/databases/${r}/collections/team_workers/documents/${n}`,a=Ac(),o=this.engine.channelRunnerRegistry.getCount(),s=o>this.config.maxCapacity,c={current_load:o,is_overloaded:s,system_specs:JSON.stringify({...a,version:this.config.version||Vt}),last_ping:Date.now(),status:"online"},l=await fetch(i,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify({data:c})});if(l.status===401){await this.handleAuthExpired();return}if(l.ok)try{let d=await l.json()||{};d?.command==="UPGRADE"&&(this.logger.info("\u{1F4E1} [ClusterSentinel] Nh\u1EADn l\u1EC7nh UPGRADE t\u1EEB xa!"),this.autoUpdater.performUpdateAndRestart().catch(()=>{})),d?.max_capacity&&Number(d.max_capacity)!==this.config.maxCapacity&&(this.config.maxCapacity=Number(d.max_capacity),this.logger.info(`\u2699\uFE0F [ClusterSentinel] \u0110\xE3 c\u1EADp nh\u1EADt gi\u1EDBi h\u1EA1n t\u1EA3i t\u1EEB xa: ${this.config.maxCapacity}`))}catch{}else l.status===404?await this.registerWorkerInstance():l.status===400&&await fetch(i,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify({data:{current_load:o,last_ping:Date.now(),status:"online"}})}).catch(()=>{});let u=this.config.workerId.startsWith("worker_")?this.config.workerId:`worker_${this.config.workerId}`,f=this.engine.channelRunnerRegistry.getAll();for(let d of f)try{await this.engine.lockManager.renewLockRemote(d.accountId,u,6e4)}catch{}}catch{}}async markWorkerOffline(){try{let t=this.config.appwriteEndpoint,r=this.config.databaseId||"zplus_app",n=this.config.workerId.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),i=`${t}/databases/${r}/collections/team_workers/documents/${n}`;await fetch(i,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify({data:{status:"offline",last_ping:Date.now()}})})}catch{}}async syncTeamAccounts(){if(!(!this.isRunning||!this.isCloudConfigured()||this.isSyncingAccounts)){this.isSyncingAccounts=!0;try{let t=this.config.appwriteEndpoint,r=this.config.databaseId||"zplus_app",n=Date.now(),i=this.config.maxCapacity,a=0,o=100,s=!0,c=new Set,l=!1;for(;s&&this.isRunning;){let d=!!this.config.teamId&&this.config.teamId!=="default"?[this.config.teamId]:["default"],h=JSON.stringify({method:"equal",attribute:"team_id",values:d}),v=JSON.stringify({method:"limit",values:[o]}),w=JSON.stringify({method:"offset",values:[a]}),k=`${t}/databases/${r}/collections/channel_accounts/documents?queries[]=${encodeURIComponent(h)}&queries[]=${encodeURIComponent(v)}&queries[]=${encodeURIComponent(w)}`,m=await fetch(k,{method:"GET",headers:this.getHeaders()});if(!m.ok){if(m.status===401){if(await this.handleAuthExpired()&&!l){l=!0;continue}break}let y=await m.text().catch(()=>""),_=`HTTP ${m.status}`;try{let S=JSON.parse(y);S?.message&&(_+=`: ${S.message}`)}catch{if(y.includes("<title>")){let S=y.match(/<title>([^<]+)<\/title>/i);S&&(_+=`: ${S[1].trim()}`)}else y&&y.length<150&&(_+=`: ${y.trim()}`)}this.logger.warn((0,pa.formatActionableError)({context:"ClusterSentinel",action:"\u0110\u1ED3ng b\u1ED9 t\xE0i kho\u1EA3n Team t\u1EEB Cloud",error:_}));break}let x=await m.json(),b=Array.isArray(x?.documents)?x.documents:[];b.length<o?s=!1:a+=o;for(let y of b){let _=y.$id||y.id;c.add(_);let S=(y.platform||"zalo").toLowerCase(),R=S==="web"||S.includes("zalo")?"zalo":S,B=y.owner_type,T=y.current_owner,z=y.status,F=Number(y.lock_expires_at||0),G=Number(y.last_heartbeat||0),ee=!!this.engine.channelRunnerRegistry.get(R,_);if(!(y.nightWorkerEnabled===!0||y.night_worker_enabled===1||y.night_worker_enabled===!0)){ee&&(this.logger.warn(`\u{1F6AB} [Unselected Account] T\xE0i kho\u1EA3n ${_} (${y.accountName||""}) kh\xF4ng \u0111\u01B0\u1EE3c ch\u1ECDn ch\u1EA1y Worker 24/7 (nightWorkerEnabled=false). Bu\u1ED9c ng\u1EAFt WSS ngay l\u1EADp t\u1EE9c...`),this.engine.channelRunnerRegistry.unregister(R,_),this.engine.unregisterAccount(_),this.engine.lockManager.releaseLock(_));continue}if(ee&&(B==="desktop"||z==="active_desktop")){this.logger.info(`\u26A1 Master Preemption: Desktop reclaimed account ${_}. Stopping worker runner...`),this.engine.channelRunnerRegistry.unregister(R,_),this.engine.unregisterAccount(_),this.engine.lockManager.releaseLock(_);continue}let pe=this.config.workerId.startsWith("worker_")?this.config.workerId:`worker_${this.config.workerId}`;if(z==="deleted"||z==="expired"||z==="error"||z==="disabled"||z==="checkpoint"){ee&&(this.engine.channelRunnerRegistry.unregister(R,_),this.engine.unregisterAccount(_),this.engine.lockManager.releaseLock(_));continue}let ue=B==="worker"&&T===pe,ve=B==="desktop"&&n-G>6e4,me=B==="worker"&&F<n;if((z==="needs_worker"||ue||ve&&F<n||me)&&!ee){let oe=this.engine.channelRunnerRegistry.getCount(),ae=oe>=i;if(!ue&&(ae||oe/i>.8)){let ce=(await this.getActivePeerWorkers()).find(Ee=>Ee.currentLoad/Ee.maxCapacity<oe/i-.25);if(ce){this.logger.debug(`[Least-Loaded Yield] Nh\u01B0\u1EDDng t\xE0i kho\u1EA3n ${_} cho worker r\u1EA3nh h\u01A1n: ${ce.workerId} (T\u1EA3i peer: ${ce.currentLoad}/${ce.maxCapacity}, T\u1EA3i hi\u1EC7n t\u1EA1i: ${oe}/${i})`);continue}}if(ae){let ie=Ac();this.logger.warn(`\u26A0\uFE0F [Server Spec Capacity Alert] Worker ${this.config.workerId} hi\u1EC7n \u0111ang m\u1EDF ${oe+1}/${i} k\u1EBFt n\u1ED1i WSS. \u0110\xE3 v\u01B0\u1EE3t ng\u01B0\u1EE1ng khuy\u1EBFn ngh\u1ECB theo c\u1EA5u h\xECnh m\xE1y ch\u1EE7 (${Math.round(ie.totalMemMb/1024)}GB RAM, ${ie.cpuCount} CPUs, ${ie.freeMemMb}MB Free). Theo ch\xEDnh s\xE1ch trao quy\u1EC1n quy\u1EBFt \u0111\u1ECBnh cho kh\xE1ch h\xE0ng, Worker v\u1EABn ti\u1EBFp t\u1EE5c k\u1EBFt n\u1ED1i WSS cho t\xE0i kho\u1EA3n ${_}.`)}if(await this.engine.lockManager.acquireLockRemote(_,pe,6e4)){let ie=ue?"Resumed previous session":me?"Failover takeover (previous worker died)":ae?"Over-capacity active takeover (per customer policy)":"Active takeover";this.logger.info(`\u2705 Cluster takeover: [${ie}] Claimed account ${_} for team ${this.config.teamId}`),await this.spawnRunnerForAccount(y)}}}}let u=this.engine.channelRunnerRegistry.getAll();for(let f of u)c.has(f.accountId)||(this.logger.info(`\u{1F9F9} [ClusterSentinel] Thu h\u1ED3i runner ngo\u1EA1i lai ${f.accountId} (${f.platform}) do kh\xF4ng thu\u1ED9c Team [${this.config.teamId}]...`),this.engine.channelRunnerRegistry.unregister(f.platform,f.accountId),this.engine.unregisterAccount(f.accountId),await this.engine.lockManager.releaseLock(f.accountId))}catch(t){this.logger.debug("syncTeamAccounts warning:",t?.message)}finally{this.isSyncingAccounts=!1}}}async spawnRunnerForAccount(t){let r=t.$id||t.id,n=(t.platform||"zalo").toLowerCase(),i=n==="web"||n.includes("zalo")?"zalo":n;if(this.engine.channelRunnerRegistry.get(i,r))return;if(!(t.nightWorkerEnabled===!0||t.night_worker_enabled===1||t.night_worker_enabled===!0)){this.logger.warn(`\u{1F6AB} [ClusterSentinel] T\u1EEB ch\u1ED1i kh\u1EDFi ch\u1EA1y WSS cho t\xE0i kho\u1EA3n unselected: ${r}`);return}let o={};if(t.authSession){let c=[];if(Array.isArray(t.$permissions))for(let f of t.$permissions){let d=String(f).match(/user:([a-zA-Z0-9_-]+)/);d&&d[1]&&c.push(d[1])}t.user_id&&c.push(t.user_id),t.userId&&c.push(t.userId),this.config.userId&&c.push(this.config.userId);let l=Array.from(new Set([this.config.teamId,t.team_id,t.teamId,...c,"default"].filter(Boolean)));o=pa.CloudCrypto.parseCloudSession(t.authSession,this.config.teamId,l)||{},!!(o?.cookie||o?.cookies||o?.accessToken||o?.token||o?.botToken)?this.logger.info(`[ClusterSentinel] \u{1F513} Gi\u1EA3i m\xE3 th\xE0nh c\xF4ng phi\xEAn ho\u1EA1t \u0111\u1ED9ng cho ${r} qua CloudCrypto.`):this.logger.warn(`[ClusterSentinel] \u26A0\uFE0F Kh\xF4ng th\u1EC3 gi\u1EA3i m\xE3 phi\xEAn h\u1EE3p l\u1EC7 cho ${r}. Scopes \u0111\xE3 th\u1EED: [${l.join(", ")}]`)}let s=await wo.createRunner(i,r,o);if(s){this.engine.registerRunner(s),await s.start();let c=s.getStatus();if(c==="expired"||c==="error"){this.logger.warn(`\u274C [ClusterSentinel] Phi\xEAn \u0111\u0103ng nh\u1EADp c\u1EE7a t\xE0i kho\u1EA3n ${r} \u0111\xE3 h\u1EBFt h\u1EA1n/l\u1ED7i [status: ${c}]. T\u1EF1 \u0111\u1ED9ng g\u1EA1t t\u1EAFt tr\u1EF1c chi\u1EBFn v\xE0 gi\u1EA3i ph\xF3ng lock...`),this.engine.channelRunnerRegistry.unregister(i,r),this.engine.unregisterAccount(r),await this.engine.lockManager.releaseLock(r);try{let l=this.config.appwriteEndpoint,u=this.config.databaseId||"zplus_app",f=`${l}/databases/${u}/collections/channel_accounts/documents/${r}`;await fetch(f,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify({data:{status:c,nightWorkerEnabled:!1,current_owner:null,owner_type:"none"}})})}catch(l){this.logger.debug(`[ClusterSentinel] Cloud mark expired error for ${r}:`,l?.message)}return}this.engine.registerAccount({id:r,platform:i,accountName:t.accountName||r,status:c,nightWorkerEnabled:!0}),this.logger.info(`\u2705 Runner registered for ${i} account ${r} [status: ${c}]`)}}};var s4=le(it());var t4=le(it()),$p=class{constructor(t,r){this.config=t;this.logger=r||(0,t4.createLogger)("AppwriteDbDriver"),this.databaseId=t.databaseId||"zplus_app"}logger;databaseId;getHeaders(){let t={"Content-Type":"application/json","X-Appwrite-Project":this.config.projectId};return this.config.sessionToken?(t["X-Appwrite-Session"]=this.config.sessionToken,t.Cookie=`a_session_${this.config.projectId}=${this.config.sessionToken}; a_session_${this.config.projectId}_legacy=${this.config.sessionToken}`,this.config.sessionToken.startsWith("eyJ")&&(t["X-Fallback-Cookies"]=JSON.stringify({[`a_session_${this.config.projectId}`]:this.config.sessionToken,[`a_session_${this.config.projectId}_legacy`]:this.config.sessionToken}))):this.config.jwt&&(t["X-Appwrite-JWT"]=this.config.jwt),t}async getDocument(t,r){try{let n=`${this.config.endpoint}/databases/${this.databaseId}/collections/${t}/documents/${r}`,i=await fetch(n,{method:"GET",headers:this.getHeaders()});if(!i.ok){if(i.status===404)return null;throw new Error(`Failed to get document: HTTP ${i.status}`)}return await i.json()}catch(n){return this.logger.debug(`getDocument error for ${t}/${r}:`,n?.message),null}}async createDocument(t,r,n){let i=r.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),a=`${this.config.endpoint}/databases/${this.databaseId}/collections/${t}/documents`,o=await fetch(a,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({documentId:i,data:n})});if(!o.ok){let s=await this.parseCleanError(o,"T\u1EA1o document th\u1EA5t b\u1EA1i");throw new Error(`Failed to create document in ${t}: ${s}`)}return await o.json()}async parseCleanError(t,r){try{let n=await t.text();try{let i=JSON.parse(n);if(i?.message)return`HTTP ${t.status}: ${i.message}`}catch{if(n.includes("<title>")){let i=n.match(/<title>([^<]+)<\/title>/i);if(i)return`HTTP ${t.status}: ${i[1].trim()}`}else if(n&&n.length<150)return`HTTP ${t.status}: ${n.trim()}`}}catch{}return`HTTP ${t.status} (${t.statusText||r})`}async updateDocument(t,r,n){let i=r.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),a=`${this.config.endpoint}/databases/${this.databaseId}/collections/${t}/documents/${i}`,o=await fetch(a,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify({data:n})});if(!o.ok){let s=await this.parseCleanError(o,"C\u1EADp nh\u1EADt document th\u1EA5t b\u1EA1i");throw new Error(`Failed to update document in ${t}: ${s}`)}return await o.json()}async upsertDocument(t,r,n){try{return await this.updateDocument(t,r,n)}catch(i){if(String(i?.message||"").includes("404"))return await this.createDocument(t,r,n);throw i}}async queryDocuments(t,r){try{let n=[];if(r.filters&&r.filters.length>0)for(let c of r.filters)c.operator==="eq"?n.push(JSON.stringify({method:"equal",attribute:c.field,values:Array.isArray(c.value)?c.value:[c.value]})):c.operator==="neq"?n.push(JSON.stringify({method:"notEqual",attribute:c.field,values:Array.isArray(c.value)?c.value:[c.value]})):c.operator==="gt"?n.push(JSON.stringify({method:"greaterThan",attribute:c.field,values:[c.value]})):c.operator==="gte"?n.push(JSON.stringify({method:"greaterThanEqual",attribute:c.field,values:[c.value]})):c.operator==="lt"?n.push(JSON.stringify({method:"lessThan",attribute:c.field,values:[c.value]})):c.operator==="lte"?n.push(JSON.stringify({method:"lessThanEqual",attribute:c.field,values:[c.value]})):c.operator==="in"&&Array.isArray(c.value)&&n.push(JSON.stringify({method:"equal",attribute:c.field,values:c.value}));r.limit&&n.push(JSON.stringify({method:"limit",values:[r.limit]})),r.offset&&n.push(JSON.stringify({method:"offset",values:[r.offset]})),r.orderBy&&n.push(JSON.stringify({method:r.orderBy.direction==="desc"?"orderDesc":"orderAsc",attribute:r.orderBy.field}));let i=n.map(c=>`queries[]=${encodeURIComponent(c)}`).join("&"),a=`${this.config.endpoint}/databases/${this.databaseId}/collections/${t}/documents${i?`?${i}`:""}`,o=await fetch(a,{method:"GET",headers:this.getHeaders()});if(!o.ok)return[];let s=await o.json();return Array.isArray(s?.documents)?s.documents:[]}catch(n){return this.logger.debug(`queryDocuments error in ${t}:`,n?.message),[]}}async deleteDocument(t,r){try{let n=`${this.config.endpoint}/databases/${this.databaseId}/collections/${t}/documents/${r}`;return(await fetch(n,{method:"DELETE",headers:this.getHeaders()})).ok}catch{return!1}}};var r4=le(it()),zp=class{constructor(t,r){this.config=t;this.logger=r||(0,r4.createLogger)("AppwriteLockDriver"),this.collectionId=t.collectionId||"channel_accounts",this.databaseId=t.databaseId||"zplus_app"}logger;collectionId;databaseId;getHeaders(){let t={"Content-Type":"application/json","X-Appwrite-Project":this.config.projectId};return this.config.sessionToken?(t["X-Appwrite-Session"]=this.config.sessionToken,t.Cookie=`a_session_${this.config.projectId}=${this.config.sessionToken}; a_session_${this.config.projectId}_legacy=${this.config.sessionToken}`,this.config.sessionToken.startsWith("eyJ")&&(t["X-Fallback-Cookies"]=JSON.stringify({[`a_session_${this.config.projectId}`]:this.config.sessionToken,[`a_session_${this.config.projectId}_legacy`]:this.config.sessionToken}))):this.config.jwt&&(t["X-Appwrite-JWT"]=this.config.jwt),t}async acquireLock(t,r,n){let i=Date.now();try{let a=`${this.config.endpoint}/databases/${this.databaseId}/collections/${this.collectionId}/documents/${t}`,o=await fetch(a,{method:"GET",headers:this.getHeaders()});if(!o.ok)return!1;let s=await o.json(),c=s.current_owner,l=Number(s.lock_expires_at||0);if(c&&c!==r&&l>i)return!1;let u=`${this.config.endpoint}/databases/${this.databaseId}/collections/${this.collectionId}/documents/${t}`;if((await fetch(u,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify({data:{current_owner:r,owner_type:r.startsWith("worker")?"worker":"desktop",lock_expires_at:i+n,last_heartbeat:i,status:r.startsWith("worker")?"active_worker":"active_desktop"}})})).ok){await new Promise(h=>setTimeout(h,30+Math.floor(Math.random()*40)));let d=await fetch(a,{method:"GET",headers:this.getHeaders()});if(d.ok&&(await d.json()).current_owner===r)return!0}return!1}catch(a){return this.logger.debug("acquireLock error:",a?.message),!1}}async releaseLock(t,r){try{if(r){let a=`${this.config.endpoint}/databases/${this.databaseId}/collections/${this.collectionId}/documents/${t}`,o=await fetch(a,{method:"GET",headers:this.getHeaders()});if(o.ok){let s=await o.json();if(s.current_owner&&s.current_owner!==r)return!1}}let n=`${this.config.endpoint}/databases/${this.databaseId}/collections/${this.collectionId}/documents/${t}`;return(await fetch(n,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify({data:{current_owner:null,owner_type:"none",lock_expires_at:0,status:"offline"}})})).ok}catch{return!1}}async renewLock(t,r,n){try{let i=`${this.config.endpoint}/databases/${this.databaseId}/collections/${this.collectionId}/documents/${t}`;return(await fetch(i,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify({data:{lock_expires_at:Date.now()+n,last_heartbeat:Date.now()}})})).ok}catch{return!1}}async getLock(t){try{let r=`${this.config.endpoint}/databases/${this.databaseId}/collections/${this.collectionId}/documents/${t}`,n=await fetch(r,{method:"GET",headers:this.getHeaders()});if(!n.ok)return null;let i=await n.json();return{resourceId:t,ownerId:i.current_owner||"",ownerType:i.owner_type,expiresAt:Number(i.lock_expires_at||0),lastHeartbeat:Number(i.last_heartbeat||0)}}catch{return null}}};var n4=le(it()),jp=class{constructor(t,r){this.config=t;this.logger=r||(0,n4.createLogger)("AppwriteCoordinator"),this.databaseId=t.databaseId||"zplus_app"}logger;databaseId;getHeaders(){let t={"Content-Type":"application/json","X-Appwrite-Project":this.config.projectId};return this.config.sessionToken?(t["X-Appwrite-Session"]=this.config.sessionToken,t.Cookie=`a_session_${this.config.projectId}=${this.config.sessionToken}; a_session_${this.config.projectId}_legacy=${this.config.sessionToken}`,this.config.sessionToken.startsWith("eyJ")&&(t["X-Fallback-Cookies"]=JSON.stringify({[`a_session_${this.config.projectId}`]:this.config.sessionToken,[`a_session_${this.config.projectId}_legacy`]:this.config.sessionToken}))):this.config.jwt&&(t["X-Appwrite-JWT"]=this.config.jwt),t}async registerNode(t){try{let r=t.workerId.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),n=`${this.config.endpoint}/databases/${this.databaseId}/collections/team_workers/documents/${r}`,i={data:{worker_id:t.workerId,team_id:t.teamId,worker_name:t.workerName,max_capacity:t.maxCapacity,recommended_capacity:t.recommendedCapacity||t.maxCapacity,current_load:t.currentLoad,is_overloaded:t.isOverloaded??!1,system_specs:t.systemSpecs?JSON.stringify(t.systemSpecs):void 0,status:t.status,last_ping:Date.now()}};if((await fetch(n,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify(i)})).status===404){let o=`${this.config.endpoint}/databases/${this.databaseId}/collections/team_workers/documents`;await fetch(o,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({documentId:r,...i})})}}catch(r){this.logger.warn("registerNode warning:",r?.message)}}async pingHeartbeat(t,r){try{let n=t.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),i=`${this.config.endpoint}/databases/${this.databaseId}/collections/team_workers/documents/${n}`;await fetch(i,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify({data:{current_load:r.currentLoad,is_overloaded:r.isOverloaded??!1,system_specs:r.systemSpecs?JSON.stringify(r.systemSpecs):void 0,last_ping:r.lastPing,status:r.status||"online"}})})}catch{}}async fetchPendingAccounts(t,r=100,n=0){try{let i=[`queries[]=${encodeURIComponent(JSON.stringify({method:"equal",attribute:"team_id",values:[t]}))}`,`queries[]=${encodeURIComponent(JSON.stringify({method:"limit",values:[r]}))}`,`queries[]=${encodeURIComponent(JSON.stringify({method:"offset",values:[n]}))}`].join("&"),a=`${this.config.endpoint}/databases/${this.databaseId}/collections/channel_accounts/documents?${i}`,o=await fetch(a,{method:"GET",headers:this.getHeaders()});if(!o.ok)return[];let s=await o.json();return Array.isArray(s?.documents)?s.documents:[]}catch(i){return this.logger.debug("fetchPendingAccounts error:",i?.message),[]}}async fetchActiveNodes(t){try{let r=[`queries[]=${encodeURIComponent(JSON.stringify({method:"equal",attribute:"team_id",values:[t]}))}`,`queries[]=${encodeURIComponent(JSON.stringify({method:"limit",values:[50]}))}`].join("&"),n=`${this.config.endpoint}/databases/${this.databaseId}/collections/team_workers/documents?${r}`,i=await fetch(n,{method:"GET",headers:this.getHeaders()});if(!i.ok)return[];let a=await i.json();return(Array.isArray(a?.documents)?a.documents:[]).map(s=>({workerId:s.worker_id||s.$id,teamId:s.team_id,workerName:s.worker_name||"",maxCapacity:Number(s.max_capacity||50),currentLoad:Number(s.current_load||0),status:s.status||"online",lastPing:Number(s.last_ping||0),isOverloaded:!!s.is_overloaded,recommendedCapacity:Number(s.recommended_capacity||s.max_capacity||50),systemSpecs:s.system_specs?typeof s.system_specs=="string"?JSON.parse(s.system_specs):s.system_specs:void 0}))}catch(r){return this.logger.debug("fetchActiveNodes error:",r?.message),[]}}async markNodeOffline(t){try{let r=t.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),n=`${this.config.endpoint}/databases/${this.databaseId}/collections/team_workers/documents/${r}`;await fetch(n,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify({data:{status:"offline",last_ping:Date.now()}})})}catch{}}};var i4=le(it()),Mp=class{constructor(t,r){this.config=t;this.logger=r||(0,i4.createLogger)("AppwriteAuthDriver")}logger;async verifySessionToken(t){try{let r=`${this.config.endpoint}/account`,n=await fetch(r,{method:"GET",headers:{"Content-Type":"application/json","X-Appwrite-Project":this.config.projectId,"X-Appwrite-Session":t,Cookie:`a_session_${this.config.projectId}=${t}; a_session_${this.config.projectId}_legacy=${t}`,...t.startsWith("eyJ")?{"X-Fallback-Cookies":JSON.stringify({[`a_session_${this.config.projectId}`]:t,[`a_session_${this.config.projectId}_legacy`]:t})}:{}}});if(!n.ok)return{allowed:!1,userId:"",userName:"Unknown",email:"",teamId:"default",isOwner:!1,isPremium:!1,reason:`Phi\xEAn \u0111\u0103ng nh\u1EADp kh\xF4ng h\u1EE3p l\u1EC7 (HTTP ${n.status}).`};let i=await n.json(),a=i.$id||i.id||"",o=i.name||"Ng\u01B0\u1EDDi d\xF9ng ZPlus",s=i.email||"",c=i.prefs||{},l=c.entitlements||{},u=!!(l.isPremium??c.isPremium??c.plan==="enterprise"),f=!!(l.isOwner??c.isOwner??!0),d=l.allowedCloudSync!==!1&&c.allowedCloudSync!==!1,h=u?-1:Number(l.cloudTtlDays||c.cloudTtlDays||7),v=u||f||d,w=c.teamId||l.teamId||"default";return{allowed:v,userId:a,userName:o,email:s,teamId:w,isOwner:f,isPremium:u,reason:v?u?"H\u1EE3p l\u1EC7":`T\xE0i kho\u1EA3n Mi\u1EC5n Ph\xED (Free Tier) - \u0110\u1EC7m Cloud ${h} ng\xE0y.`:"Y\xEAu c\u1EA7u quy\u1EC1n Enterprise ho\u1EB7c ch\u1EBF \u0111\u1ED9 \u0111\u1EC7m Cloud \u0111\u1EC3 ch\u1EA1y Worker 24/7."}}catch(r){return this.logger.error("verifySessionToken error:",r),{allowed:!1,userId:"",userName:"Unknown",email:"",teamId:"default",isOwner:!1,isPremium:!1,reason:r?.message||"L\u1ED7i k\u1EBFt n\u1ED1i x\xE1c th\u1EF1c."}}}async checkEntitlements(t){return this.config.sessionToken?this.verifySessionToken(this.config.sessionToken):{allowed:!0,userId:t,userName:"Worker Node",email:"",teamId:"default",isOwner:!0,isPremium:!0}}};var O0=le(require("fs")),F0=require("stream"),a4=require("stream/promises"),o4=le(it()),qp=class{constructor(t,r){this.config=t;this.logger=r||(0,o4.createLogger)("AppwriteStorageDriver")}logger;getHeaders(){let t={"X-Appwrite-Project":this.config.projectId};return this.config.sessionToken?(t["X-Appwrite-Session"]=this.config.sessionToken,t.Cookie=`a_session_${this.config.projectId}=${this.config.sessionToken}; a_session_${this.config.projectId}_legacy=${this.config.sessionToken}`,this.config.sessionToken.startsWith("eyJ")&&(t["X-Fallback-Cookies"]=JSON.stringify({[`a_session_${this.config.projectId}`]:this.config.sessionToken,[`a_session_${this.config.projectId}_legacy`]:this.config.sessionToken}))):this.config.jwt&&(t["X-Appwrite-JWT"]=this.config.jwt),t}async createFile(t,r,n,i,a){let o=r==="unique()"?"unique()":r.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),s=`${this.config.endpoint}/storage/buckets/${t}/files`,c=new FormData;c.append("fileId",o);let l=Buffer.isBuffer(n)?n:Buffer.from(n),u=new Blob([l]);if(c.append("file",u,i),a&&a.length>0)for(let h=0;h<a.length;h++)c.append(`permissions[${h}]`,a[h]);let f=await fetch(s,{method:"POST",headers:this.getHeaders(),body:c});if(!f.ok){let h=await f.text();throw new Error(`Failed to upload file to storage: HTTP ${f.status} - ${h}`)}let d=await f.json();return{$id:d.$id||r,name:d.name||i,sizeOriginal:d.sizeOriginal||l.length,mimeType:d.mimeType,$createdAt:d.$createdAt,$updatedAt:d.$updatedAt}}async getFileDownload(t,r){let n=`${this.config.endpoint}/storage/buckets/${t}/files/${r}/download`,i=await fetch(n,{method:"GET",headers:this.getHeaders()});if(!i.ok)throw new Error(`Failed to download file: HTTP ${i.status}`);let a=await i.arrayBuffer();return Buffer.from(a)}async downloadFileToPath(t,r,n){let i=`${this.config.endpoint}/storage/buckets/${t}/files/${r}/download`,a=await fetch(i,{method:"GET",headers:this.getHeaders()});if(!a.ok)throw new Error(`Failed to download file: HTTP ${a.status}`);if(typeof F0.Readable.fromWeb=="function"&&a.body)await(0,a4.pipeline)(F0.Readable.fromWeb(a.body),O0.default.createWriteStream(n));else{let o=await a.arrayBuffer();await O0.default.promises.writeFile(n,Buffer.from(o))}return!0}async deleteFile(t,r){let n=`${this.config.endpoint}/storage/buckets/${t}/files/${r}`;return(await fetch(n,{method:"DELETE",headers:this.getHeaders()})).ok}async listFiles(t){let r=`${this.config.endpoint}/storage/buckets/${t}/files`,n=await fetch(r,{method:"GET",headers:this.getHeaders()});if(!n.ok)return{files:[],total:0};let i=await n.json();return{files:(i.files||[]).map(a=>({$id:a.$id,name:a.name,sizeOriginal:a.sizeOriginal,mimeType:a.mimeType})),total:i.total||0}}async getFile(t,r){let n=`${this.config.endpoint}/storage/buckets/${t}/files/${r}`,i=await fetch(n,{method:"GET",headers:this.getHeaders()});return i.ok?await i.json():null}};var Hp=class{constructor(t,r){this.config=t;this.logger=r||(0,s4.createLogger)("AppwriteCloudAdapter");let n={get endpoint(){return t.cloudEndpoint||t.appwriteEndpoint||"https://api.softty.net/v1"},get projectId(){return t.cloudProjectId||t.appwriteProjectId||"699cfc3100136099c1c1"},get databaseId(){return t.cloudDatabaseId||t.databaseId||"zplus_app"},get sessionToken(){return t.cloudSessionToken||t.appwriteSessionToken},get jwt(){return t.cloudJwt||t.appwriteJwt}};this.database=new $p(n,this.logger),this.lockStorage=new zp(n,this.logger),this.coordinator=new jp(n,this.logger),this.auth=new Mp(n,this.logger),this.storage=new qp(n,this.logger)}providerName="appwrite";database;lockStorage;coordinator;auth;storage;logger;async start(){this.logger.info("\u2705 Appwrite Cloud Adapter initialized.")}async stop(){this.logger.info("Appwrite Cloud Adapter stopped.")}};var c4=le(it()),Wp=class{constructor(t,r){this.config=t;this.logger=r||(0,c4.createLogger)("CustomApiAdapter");let n=t.cloudEndpoint||"https://api.softty.net/custom/v1",a={"Content-Type":"application/json",Authorization:`Bearer ${t.cloudSessionToken||t.cloudJwt||""}`,"X-Tenant-ID":t.teamId||"default"};this.database={async getDocument(o,s){try{let c=await fetch(`${n}/data/${o}/${s}`,{headers:a});return c.ok?await c.json():null}catch{return null}},async createDocument(o,s,c){return await(await fetch(`${n}/data/${o}`,{method:"POST",headers:a,body:JSON.stringify({id:s,...c})})).json()},async updateDocument(o,s,c){return await(await fetch(`${n}/data/${o}/${s}`,{method:"PATCH",headers:a,body:JSON.stringify(c)})).json()},async upsertDocument(o,s,c){return await(await fetch(`${n}/data/${o}/${s}/upsert`,{method:"POST",headers:a,body:JSON.stringify(c)})).json()},async queryDocuments(o,s){try{let c=await fetch(`${n}/data/${o}/query`,{method:"POST",headers:a,body:JSON.stringify(s)});if(!c.ok)return[];let l=await c.json();return Array.isArray(l?.items)?l.items:[]}catch{return[]}},async deleteDocument(o,s){try{return(await fetch(`${n}/data/${o}/${s}`,{method:"DELETE",headers:a})).ok}catch{return!1}}},this.lockStorage={async acquireLock(o,s,c){try{let l=await fetch(`${n}/locks/acquire`,{method:"POST",headers:a,body:JSON.stringify({resourceId:o,ownerId:s,ttlMs:c})});return l.ok?!!(await l.json())?.acquired:!1}catch{return!1}},async releaseLock(o,s){try{return(await fetch(`${n}/locks/release`,{method:"POST",headers:a,body:JSON.stringify({resourceId:o,ownerId:s})})).ok}catch{return!1}},async renewLock(o,s,c){try{return(await fetch(`${n}/locks/renew`,{method:"POST",headers:a,body:JSON.stringify({resourceId:o,ownerId:s,ttlMs:c})})).ok}catch{return!1}},async getLock(o){try{let s=await fetch(`${n}/locks/${o}`,{headers:a});return s.ok?await s.json():null}catch{return null}}},this.coordinator={async registerNode(o){try{await fetch(`${n}/cluster/nodes/register`,{method:"POST",headers:a,body:JSON.stringify(o)})}catch{}},async pingHeartbeat(o,s){try{await fetch(`${n}/cluster/nodes/${o}/heartbeat`,{method:"POST",headers:a,body:JSON.stringify(s)})}catch{}},async fetchPendingAccounts(o,s=100,c=0){try{let l=await fetch(`${n}/cluster/accounts/pending?teamId=${o}&limit=${s}&offset=${c}`,{headers:a});if(!l.ok)return[];let u=await l.json();return Array.isArray(u?.accounts)?u.accounts:[]}catch{return[]}},async markNodeOffline(o){try{await fetch(`${n}/cluster/nodes/${o}/offline`,{method:"POST",headers:a})}catch{}}},this.auth={async verifySessionToken(o){try{let s=await fetch(`${n}/auth/verify`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`}});return s.ok?await s.json():{allowed:!1,userId:"",userName:"Unknown",email:"",teamId:"default",isOwner:!1,isPremium:!1,reason:"Invalid session token"}}catch(s){return{allowed:!1,userId:"",userName:"Unknown",email:"",teamId:"default",isOwner:!1,isPremium:!1,reason:s?.message}}},async checkEntitlements(o){return{allowed:!0,userId:o,userName:"User",email:"",teamId:"default",isOwner:!0,isPremium:!0}}}}providerName="custom-api";database;lockStorage;coordinator;auth;logger;async start(){this.logger.info("\u{1F50C} Custom API Cloud Adapter initialized.")}async stop(){this.logger.info("Custom API Cloud Adapter stopped.")}};var l4=le(it()),Gp=class{providerName="in-memory";database;lockStorage;coordinator;auth;logger;tables=new Map;locks=new Map;nodes=new Map;constructor(t,r){this.logger=r||(0,l4.createLogger)("InMemoryCloudAdapter");let n=i=>{let a=this.tables.get(i);return a||(a=new Map,this.tables.set(i,a)),a};this.database={async getDocument(i,a){return n(i).get(a)||null},async createDocument(i,a,o){return n(i).set(a,{$id:a,id:a,...o}),n(i).get(a)},async updateDocument(i,a,o){let c={...n(i).get(a)||{$id:a,id:a},...o};return n(i).set(a,c),c},async upsertDocument(i,a,o){return this.updateDocument(i,a,o)},async queryDocuments(i,a){let o=Array.from(n(i).values());if(a.filters)for(let s of a.filters)s.operator==="eq"&&(o=o.filter(c=>c[s.field]===s.value));return a.limit&&(o=o.slice(0,a.limit)),o},async deleteDocument(i,a){return n(i).delete(a)}},this.lockStorage={acquireLock:async(i,a,o)=>{let s=Date.now(),c=this.locks.get(i);return c&&c.expiresAt>s&&c.ownerId!==a?!1:(this.locks.set(i,{resourceId:i,ownerId:a,ownerType:a.startsWith("worker")?"worker":"desktop",expiresAt:s+o,lastHeartbeat:s}),!0)},releaseLock:async(i,a)=>{let o=this.locks.get(i);return o?a&&o.ownerId!==a?!1:(this.locks.delete(i),!0):!0},renewLock:async(i,a,o)=>this.lockStorage.acquireLock(i,a,o),getLock:async i=>this.locks.get(i)||null},this.coordinator={registerNode:async i=>{this.nodes.set(i.workerId,i)},pingHeartbeat:async(i,a)=>{let o=this.nodes.get(i);o&&(o.currentLoad=a.currentLoad,o.lastPing=a.lastPing,o.status=a.status||"online")},fetchPendingAccounts:async i=>Array.from(n("channel_accounts").values()).filter(o=>o.team_id===i||o.teamId===i),markNodeOffline:async i=>{let a=this.nodes.get(i);a&&(a.status="offline")}},this.auth={verifySessionToken:async i=>({allowed:!!i,userId:"user_test_in_memory",userName:"Test User",email:"test@softty.net",teamId:"team_test",isOwner:!0,isPremium:!0}),checkEntitlements:async i=>({allowed:!0,userId:i,userName:"Test User",email:"test@softty.net",teamId:"team_test",isOwner:!0,isPremium:!0})}}async start(){this.logger.info("\u{1F9EA} In-Memory Cloud Adapter initialized.")}async stop(){this.logger.info("In-Memory Cloud Adapter stopped.")}};var u4=le(it()),Vp=class{static create(t,r){let n=r||(0,u4.createLogger)("CloudAdapterFactory");switch(t.cloudProvider||"appwrite"){case"custom-api":return n.info("Creating Custom API Cloud Adapter..."),new Wp(t,n);case"in-memory":return n.info("Creating In-Memory Cloud Adapter..."),new Gp(t,n);case"appwrite":default:return n.info("Creating Appwrite Cloud Adapter..."),new Hp(t,n)}}};var p4=le(it()),Jp=class{constructor(t,r,n){this.engine=t;this.cloudDb=r;this.logger=n||(0,p4.createLogger)(`WorkerOutboundDispatchService:${this.engine.config.workerId}`)}logger;isProcessing=!1;pollInterval;start(t=4e3){this.pollInterval||(this.logger.info(`Starting Worker Outbound Dispatcher (polling every ${t}ms)...`),this.pollInterval=setInterval(()=>{this.drainPendingQueue().catch(r=>{this.logger.debug("drainPendingQueue error:",r?.message)})},t))}stop(){this.pollInterval&&(clearInterval(this.pollInterval),this.pollInterval=void 0,this.logger.info("Worker Outbound Dispatcher stopped."))}async drainPendingQueue(){if(!this.isProcessing){this.isProcessing=!0;try{let t=await this.cloudDb.queryDocuments("outbound_queue",{filters:[{field:"status",operator:"eq",value:"pending"}],limit:10});if(t&&t.length>0)for(let r of t)await this.processSingleMessage(r)}finally{this.isProcessing=!1}}}async processSingleMessage(t){let r=t.$id||t.id;if(!r||!t.account_id||!t.thread_id)return;let n=Number(t.created_at)||0;if(n>0&&Date.now()-n>7200*1e3){this.logger.warn(`[WorkerOutbound] \u{1F6E1}\uFE0F Outbound task ${r} is older than 2 hours, marking failed (expired)`),await this.cloudDb.updateDocument("outbound_queue",r,{status:"failed",error_message:"Expired: Task is older than 2 hours",processed_at:Date.now(),updated_at:Date.now()}).catch(()=>{});return}let a=this.engine.channelRunnerRegistry.getAll().find(f=>f.accountId===t.account_id);if(!a)return;let o=t.content||"",s=Array.isArray(t.media_urls)?[...t.media_urls]:[],c=t.media_type,l;if(typeof o=="string"&&o.trim().startsWith("{"))try{let f=JSON.parse(o);if(f&&f.__zplus_relay_v1===!0){let d=new Set(["sendMessage","sendImage","sendImages"]);if(f.action&&!d.has(String(f.action)))return;let h=f.payload||{};if(o=String(h.content??h.text??h.message??h.caption??""),Array.isArray(f.mediaItems)&&f.mediaItems.length>0){let v=f.mediaItems.filter(w=>w?.url&&w.role!=="thumbnail").map(w=>String(w.url));v.length>0&&(s=v)}else Array.isArray(h.mediaUrls)&&h.mediaUrls.length>0&&(s=h.mediaUrls);(f.action==="sendImage"||f.action==="sendImages")&&!c&&(c="image"),(f.clientMsgId||h.clientMsgId)&&(l=String(f.clientMsgId||h.clientMsgId))}}catch{}let u=`worker_${this.engine.config.workerId}`;try{await this.cloudDb.updateDocument("outbound_queue",r,{status:"processing",dispatcher_id:u,updated_at:Date.now()})}catch{return}try{let f={id:l||`msg_out_${Date.now()}_${Math.random().toString(36).substring(2,6)}`,cliMsgId:l,platform:a.platform,threadId:t.thread_id,conversationId:t.thread_id,accountId:a.accountId,senderId:a.accountId,senderName:"T\xF4i",senderType:"agent",messageType:c==="image"?"image":"text",content:o,attachments:s.map(h=>({url:h,mimeType:"image/jpeg"})),timestamp:Date.now(),isSelf:!0,status:"sent"};if(await a.sendMessage(f))await this.cloudDb.updateDocument("outbound_queue",r,{status:"completed",processed_at:Date.now(),updated_at:Date.now()}),this.logger.info(`[WorkerOutbound] \u2705 Dispatched outbound message ${r} via ${a.platform}`);else throw new Error("Channel runner sendMessage returned false")}catch(f){this.logger.error(`[WorkerOutbound] \u274C Failed to dispatch message ${r}:`,f);let d=(t.retry_count||0)+1;await this.cloudDb.updateDocument("outbound_queue",r,{status:d>=3?"failed":"pending",retry_count:d,error_message:f?.message||String(f),updated_at:Date.now()})}}};var Kp=class{logger;channelRunnerRegistry;lockManager;deltaQueue;automationEngine;pushDispatcher;httpServer;clusterSentinel;cloudAdapter;outboundDispatcher;status="idle";lastError;startTime=0;activeAccounts=new Map;messagesProcessed=0;heartbeatTimer;storageQuotaExceeded=!1;config;constructor(t){this.config={enableHttp:!1,teamId:"default",workerName:`Worker_${t.workerId}`,version:t.version||Vt,maxCapacity:50,clusterPollIntervalMs:5e3,heartbeatIntervalMs:15e3,logLevel:"info",...t,workerId:t.workerId},this.logger=(0,Yp.createLogger)(`WorkerEngine:${this.config.workerId}`),this.channelRunnerRegistry=new Oc(this.logger),this.lockManager=new Fc(6e4,this.logger),this.cloudAdapter=Vp.create(this.config,this.logger),(this.config.cloudEndpoint||this.config.appwriteEndpoint)&&this.lockManager.setStorageProvider(this.cloudAdapter.lockStorage);let r=process.env.WORKER_DATA_DIR||process.env.DATA_DIR||da.default.join(Zp.default.homedir(),".zplus","data"),n=da.default.join(r,`pending_messages_${this.config.workerId}.json`);this.deltaQueue=new Dc(1e4,this.logger,n),this.automationEngine=new Bc(this.logger,{enabled:!1,apiKey:this.config.deepseekApiKey||this.config.geminiApiKey||this.config.openaiApiKey||this.config.anthropicApiKey||this.config.customAiApiKey,baseUrl:this.config.aiBaseUrl,provider:this.config.aiProvider,model:this.config.aiModel,systemPrompt:this.config.nightSystemPrompt,fallbackMessage:this.config.nightFallbackReply}),this.pushDispatcher=new Nc(this.logger),this.clusterSentinel=new Up(this.config,this,this.logger),this.httpServer=this.config.enableHttp&&this.config.port?new Fp(this.config.port,this,this.lockManager,this.deltaQueue,this.logger):null,this.outboundDispatcher=new Jp(this,this.cloudAdapter.database,this.logger),this.lockManager.onPreempt(async i=>{this.logger.info(`Preemption callback: stopping WSS for account ${i}...`);let a=this.channelRunnerRegistry.getAll();for(let o of a)o.accountId===i&&await o.stop()})}async start(){if(this.status==="running"){this.logger.warn("Worker is already running.");return}if(this.logger.info("Starting ZPlus 24/7 Headless Worker Engine..."),this.status="initializing",this.startTime=Date.now(),this.httpServer)try{await this.httpServer.start()}catch(r){this.logger.error("Failed to start Worker HTTP Ingress Server:",r)}else this.logger.info("\u{1F6E1}\uFE0F Ch\u1EBF \u0111\u1ED9 Zero-Port (Outbound-only) \u0111ang ho\u1EA1t \u0111\u1ED9ng: Worker kh\xF4ng m\u1EDF b\u1EA5t k\u1EF3 c\u1ED5ng l\u1EAFng nghe Inbound n\xE0o.");try{await this.cloudAdapter.start()}catch(r){this.logger.error("Failed to start Cloud Adapter:",r)}if(this.config.isStandby){this.status="idle",this.logger.warn(`\u23F8\uFE0F Worker is in STANDBY mode: ${this.config.standbyReason||"Unauthorized / Free Tier / Non-owner"}. Worker will NOT process accounts.`),this.clusterSentinel.startAutoUpdaterOnly(),this.writeLocalHeartbeat(),this.heartbeatTimer=setInterval(()=>{this.writeLocalHeartbeat()},3e4);return}this.heartbeatTimer=setInterval(()=>{this.sendHeartbeat()},this.config.heartbeatIntervalMs);try{await this.clusterSentinel.start()}catch(r){this.logger.error("Failed to start Cluster Sentinel:",r)}this.outboundDispatcher.start(),this.status="running",this.writeLocalHeartbeat();let t=this.config.enableHttp?`Port: ${this.config.port}`:"Zero-Port Headless Daemon";this.logger.info(`\u2705 ZPlus Worker Engine started successfully [ID: ${this.config.workerId}, Mode: ${t}]`),this.deltaQueue.getCount()>0&&this.flushPendingMessages().catch(r=>{this.logger.warn("Error flushing pending messages on startup:",r?.message)});try{typeof global.gc=="function"&&global.gc()}catch{}}async stop(){this.logger.info("Stopping ZPlus Worker Engine..."),this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=void 0),await this.clusterSentinel.stop(),await this.cloudAdapter.stop(),this.httpServer&&await this.httpServer.stop(),this.clearLocalHeartbeat(),this.outboundDispatcher.stop(),await this.channelRunnerRegistry.stopAll(),this.status="stopped",this.logger.info("ZPlus Worker Engine stopped.")}registerRunner(t){t.onMessage?.(r=>{this.handleIncomingMessage(r,t)}),this.channelRunnerRegistry.register(t)}registerAccount(t){this.activeAccounts.set(t.id,t),this.logger.info(`Registered active account: ${t.accountName} [${t.platform}]`),this.writeLocalHeartbeat()}unregisterAccount(t){this.activeAccounts.delete(t),this.logger.info(`Unregistered account: ${t}`),this.writeLocalHeartbeat()}recordMessageProcessed(){this.messagesProcessed++}async handleIncomingMessage(t,r){if(this.status==="auth_error"||this.status==="paused"||this.status==="stopped"){this.logger.warn(`\u23F8\uFE0F [StateGuard] B\u1ECF qua x\u1EED l\xFD tin nh\u1EAFn ${t.id} v\xEC Worker \u0111ang \u1EDF tr\u1EA1ng th\xE1i [${this.status}].`);return}this.recordMessageProcessed(),this.deltaQueue.enqueue(t);try{await this.pushMessageToCloud(t),this.deltaQueue.remove(t.id)}catch(n){this.logger.warn(`\u26A0\uFE0F [CloudSync] Kh\xF4ng th\u1EC3 \u0111\u1EA9y tin ${t.id} l\xEAn Cloud, gi\u1EEF l\u1EA1i trong \u0111\u1EC7m: ${n?.message}`)}try{let n=await this.automationEngine.evaluateIncomingMessage(t);if(n&&r){this.logger.info(`[NightAutoReply] Sending automated reply to thread ${t.threadId}: "${n}"`);let i={id:`reply_${Date.now()}`,platform:t.platform,conversationId:t.conversationId,threadId:t.threadId,accountId:t.accountId,senderId:t.accountId,senderName:"ZPlus Night Assistant",senderType:"agent",messageType:"text",content:n,timestamp:Date.now(),isSelf:!0,status:"sent"};if(await r.sendMessage(i)){this.deltaQueue.enqueue(i);try{await this.pushMessageToCloud(i),this.deltaQueue.remove(i.id)}catch(o){this.logger.warn(`\u26A0\uFE0F [NightAutoReply] Kh\xF4ng th\u1EC3 \u0111\u1EA9y tin ph\u1EA3n h\u1ED3i l\xEAn Cloud: ${o?.message}`)}}else this.logger.warn(`[NightAutoReply] Socket delivery failed for thread ${t.threadId}. Skipped cloud push to prevent ghost message.`)}}catch(n){this.logger.warn("Auto-reply evaluation notice:",n)}try{await this.pushDispatcher.enqueueNotification(t,this.cloudAdapter.database,{teamId:this.config.teamId,userId:this.config.userId})}catch(n){this.logger.debug("Push notification enqueue notice:",n)}}async pushMessageToCloud(t){if(!(!this.config.cloudEndpoint&&!this.config.appwriteEndpoint))try{let r=t.id.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),n=new Date().toISOString(),i=t.threadId||t.conversationId,a=t.mediaUrl||t.metadata?.mediaUrl||Array.isArray(t.attachments)&&t.attachments[0]?.url||void 0,o;if(a&&this.cloudAdapter.storage&&!this.storageQuotaExceeded&&["chat.photo","chat.voice","chat.sticker","chat.doodle","image","audio","voice"].includes((t.messageType||t.type||"").toLowerCase()))try{let v=(t.messageType||t.type||"").toLowerCase(),w=v.includes("voice")||v.includes("audio")?".aac":".jpg",k=`media_${r}${w}`,m=await fetch(a,{headers:{"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",Referer:"https://chat.zalo.me/"}});if(m.ok){let x=await m.arrayBuffer(),b=Buffer.from(x);if(b.length>0&&b.length<=20*1024*1024){let y=this.config.storageBucketId||"zplus-media-vault",_=await this.cloudAdapter.storage.createFile(y,r,b,k);_?.$id&&(o=_.$id,this.logger.info(`\u2601\uFE0F [MediaSync] In-memory streamed media (${(b.length/1024).toFixed(1)} KB) to Cloud Storage: ${o}`))}}else m.status===403&&this.logger.warn(`[MediaSync] Media URL already expired (403): ${a}`)}catch(v){let w=String(v?.message||"").toLowerCase();w.includes("quota")||w.includes("403")||w.includes("limit")?(this.storageQuotaExceeded=!0,this.logger.warn(`\u26A0\uFE0F [MediaSync] Cloud Storage quota exceeded for team ${this.config.teamId}. Pausing cloud media uploads.`)):this.logger.debug("[MediaSync] Cloud media upload notice:",v)}let s=t.metadata?.rawPayload?.data||t.metadata?.rawPayload||t.rawPayload?.data||t.rawPayload||{},c=Array.isArray(t.attachments)?t.attachments:Array.isArray(s.attachments)?s.attachments:a?[{url:a,cloud_file_id:o}]:[],l=t.metadata?.rawMsgType||s.msgType||t.msgType||t.messageType||t.type||"chat.text",u=Yp.LeanMessageNormalizer.normalizeMessage({msgType:l,content:t.content||t.text||s.content||"",attachments:c,quote:t.quote||t.quotedMessage||s.quote,mentions:t.mentions||s.mentions,reactions:t.reactions||t.metadata?.reactions||s.reactions||s.reaction,cliMsgId:t.cliMsgId||t.clientMsgId||s.cliMsgId||void 0,senderName:t.senderName||void 0,cloudFileId:o||void 0}),f={...u.leanPayload,...a?{mediaUrl:a}:{},...o?{cloud_file_id:o}:{}},d=(u.cleanContent||t.content||t.text||"").slice(0,3e3),h={conversation_id:t.conversationId||t.threadId,thread_id:i,account_id:t.accountId,sender_id:t.senderId,sender_name:(t.senderName||"").slice(0,255),senderType:t.senderType||"customer",messageType:l,content:d,payload:JSON.stringify(f).slice(0,3e3),timestamp:t.timestamp||Date.now(),is_self:!!(t.isSelf||t.senderId==="0"||t.accountId&&String(t.senderId)===String(t.accountId)),is_recall:0,status:t.status||"sent",team_id:this.config.teamId||"",zplus_action:"INSERT",zplus_updated_at:n};if(await this.cloudAdapter.database.upsertDocument("messages",r,h),this.logger.info(`\u2601\uFE0F [CloudSync] Pushed message ${t.id} to Cloud DB via ${this.cloudAdapter.providerName}.`),i&&t.accountId)try{let v=`${i}:${t.accountId}`,k=`z_${d4.default.createHash("md5").update(`conversations:${v}`).digest("hex")}`,m=(d||(u.cleanAttachments.length>0?"[\u0110\xEDnh k\xE8m]":"")).slice(0,500),b=!!(t.isGroup||t.groupName||t.metadata?.rawPayload?.type===1||t.metadata?.rawPayload?.data?.type===1||String(i).startsWith("g"))?t.groupName||"Nh\xF3m Zalo":t.senderName||i,y={thread_id:i,account_id:t.accountId,team_id:this.config.teamId||"",name:b.slice(0,255),last_message:JSON.stringify({content:m,senderId:t.senderId,timestamp:t.timestamp||Date.now(),msgType:l}),timestamp:t.timestamp||Date.now(),unread_count:1,peerId:t.senderId,peerName:(t.senderName||"").slice(0,255),platform:t.platform||"zalo",isPinned:!1,zplus_action:"UPDATE",zplus_updated_at:n};await this.cloudAdapter.database.upsertDocument("conversations",k,y)}catch(v){this.logger.debug(`[CloudSync] Note updating conversations on cloud: ${v?.message}`)}}catch(r){this.logger.error(`\u274C [CloudSync] Failed to push message ${t.id} to Cloud DB: ${r?.message||r}`)}}getMetrics(){let t=this.startTime>0?Math.floor((Date.now()-this.startTime)/1e3):0,r=process.memoryUsage().rss/(1024*1024);return{workerId:this.config.workerId,status:this.status,uptimeSeconds:t,activeAccountsCount:this.activeAccounts.size,totalMessagesProcessed:this.messagesProcessed,memoryUsageMb:Math.round(r*100)/100,lastHeartbeat:new Date().toISOString()}}sendHeartbeat(){let t=this.getMetrics();this.writeLocalHeartbeat(),this.logger.info(`\u{1F493} Heartbeat: status=${t.status}, accounts=${t.activeAccountsCount}, msgs=${t.totalMessagesProcessed}, pendingDelta=${this.deltaQueue.getCount()}, uptime=${t.uptimeSeconds}s`)}setStatus(t,r){let n=this.status;this.status=t,r!==void 0&&(this.lastError=r),t==="auth_error"||t==="paused"?n==="running"&&(this.logger.warn(`\u23F8\uFE0F [StateGuard] Chuy\u1EC3n sang tr\u1EA1ng th\xE1i [${t}]. T\u1EA1m d\u1EEBng (PAUSE) to\xE0n b\u1ED9 Channel Runners.`),this.channelRunnerRegistry.pauseAll().catch(i=>{this.logger.error("Error pausing runners:",i)})):t==="running"&&(n==="auth_error"||n==="paused")&&(this.logger.info("\u25B6\uFE0F [StateGuard] Ph\u1EE5c h\u1ED3i tr\u1EA1ng th\xE1i [running]. K\xEDch ho\u1EA1t l\u1EA1i to\xE0n b\u1ED9 Channel Runners & X\u1EA3 h\xE0ng \u0111\u1EE3i."),this.channelRunnerRegistry.resumeAll().catch(i=>{this.logger.error("Error resuming runners:",i)}),this.flushPendingMessages().catch(i=>{this.logger.warn("Error flushing pending messages on resume:",i?.message)})),this.writeLocalHeartbeat()}async flushPendingMessages(){let t=this.deltaQueue.getAll();if(t.length===0)return;this.logger.info(`\u{1F680} [FlushQueue] B\u1EAFt \u0111\u1EA7u x\u1EA3 ${t.length} tin nh\u1EAFn t\u1ED3n \u0111\u1ECDng l\xEAn Cloud DB...`);let r=0;for(let n of t)try{await this.pushMessageToCloud(n),this.deltaQueue.remove(n.id),r++}catch(i){this.logger.debug(`[FlushQueue] G\u1EB7p l\u1ED7i khi \u0111\u1EA9y tin ${n.id}: ${i?.message}`)}r>0&&(this.logger.info(`\u2705 [FlushQueue] \u0110\xE3 x\u1EA3 th\xE0nh c\xF4ng ${r}/${t.length} tin nh\u1EAFn l\xEAn Cloud DB!`),this.writeLocalHeartbeat())}writeLocalHeartbeat(){try{let t=process.env.ZPLUS_HOME||da.default.join(Zp.default.homedir(),".zplus");Si.default.existsSync(t)||Si.default.mkdirSync(t,{recursive:!0});let r=da.default.join(t,"worker_heartbeat.json"),n=this.getMetrics(),i={vendor:"Softtynet Co., Ltd.",product:"Softty ZPlus Platform",daemonTitle:"ZPlus 24/7 Headless Worker Daemon",version:this.config.version||"1.0.10",homepage:"https://softty.net",supportEmail:"support@softty.net",processTitle:process.title||"zplus-worker (Softtynet Co., Ltd.)",status:this.status,lastError:this.lastError||null,workerId:this.config.workerId,workerName:this.config.workerName,teamId:this.config.teamId,pid:process.pid,uptimeSeconds:n.uptimeSeconds,activeAccountsCount:n.activeAccountsCount,activeRunners:this.channelRunnerRegistry.getCount(),accounts:Array.from(this.activeAccounts.values()).map(o=>({id:o.id,name:o.accountName||o.id,platform:o.platform||"zalo",status:o.status||"active",nightWorkerEnabled:o.nightWorkerEnabled,proxyId:o.proxyId||null})),totalMessagesProcessed:n.totalMessagesProcessed,pendingDeltaMessages:this.deltaQueue.getCount(),memoryUsageMb:n.memoryUsageMb,isZeroPort:!this.config.enableHttp,port:this.config.enableHttp?this.config.port:null,lastPing:Date.now(),timestamp:Date.now()},a=`${r}.${process.pid}.tmp`;Si.default.writeFileSync(a,JSON.stringify(i,null,2)),Si.default.renameSync(a,r)}catch{}}clearLocalHeartbeat(){try{let t=process.env.ZPLUS_HOME||da.default.join(Zp.default.homedir(),".zplus"),r=da.default.join(t,"worker_heartbeat.json");if(Si.default.existsSync(r)){let n={status:"stopped",workerId:this.config.workerId,pid:process.pid,lastPing:Date.now(),timestamp:Date.now()},i=`${r}.${process.pid}.tmp`;Si.default.writeFileSync(i,JSON.stringify(n,null,2)),Si.default.renameSync(i,r)}}catch{}}};var ir=le(require("os")),Ye=le(require("fs")),ft=le(require("path")),et=require("child_process"),f4=le(it()),Xp=class{logger;constructor(t){this.logger=t||(0,f4.createLogger)("WorkerAutostartManager")}getExecutableInfo(){let t=process.execPath,r=ft.default.resolve(__dirname,"cli.js");Ye.default.existsSync(r)||(r=ft.default.resolve(__dirname,"../dist/cli.js"));let n=r.includes("_npx")||r.includes("npm-cache");if(!Ye.default.existsSync(r)||n){let i="";try{let a=process.platform==="win32"?"where zplus-worker":"which zplus-worker",o=(0,et.execSync)(a,{encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim().split(`
69
+ \u23F8\uFE0F Worker chuy\u1EC3n sang ch\u1EBF \u0111\u1ED9 STANDBY (Kh\xF4ng nh\u1EADn vi\u1EC7c, kh\xF4ng ti\xEAu t\u1ED1n t\xE0i nguy\xEAn).`),k}};var Up=class{constructor(t,r,n){this.config=t;this.engine=r;this.logger=n||(0,pa.createLogger)(`ClusterSentinel:${t.workerId}`),this.autoUpdater=new Bp(this.logger),this.authManager=new ko(this.logger)}logger;autoUpdater;authManager;refreshPromise=null;isRunning=!1;pollTimer;heartbeatTimer;cachedPeerWorkers=[];lastPeerCheckTime=0;lastNightConfigUpdatedAt=0;lastNightConfigCheck=0;lastAuthFailureTime=0;lastAuthErrorLogTime=0;isSyncingAccounts=!1;getHeaders(){let t=this.config.appwriteProjectId||"",r={"Content-Type":"application/json","X-Appwrite-Project":t};if(this.config.appwriteSessionToken){let n=this.config.appwriteSessionToken;n.includes(".")&&n.split(".").length===3?r["X-Appwrite-JWT"]=n:(r["X-Appwrite-Session"]=n,r.Cookie=`a_session_${t}=${n}; a_session_${t}_legacy=${n}`,n.startsWith("eyJ")&&(r["X-Fallback-Cookies"]=JSON.stringify({[`a_session_${t}`]:n,[`a_session_${t}_legacy`]:n})))}else this.config.appwriteJwt&&(r["X-Appwrite-JWT"]=this.config.appwriteJwt);return r}getWorkerPermissions(){let t=[],r=this.config.userId,n=this.config.teamId;return r&&t.push(`read("user:${r}")`,`update("user:${r}")`,`delete("user:${r}")`),n&&n!==r&&n!=="default"&&t.push(`read("team:${n}")`,`update("team:${n}")`,`delete("team:${n}")`),t.length===0&&t.push('read("users")','update("users")','delete("users")'),t}async handleAuthExpired(){return this.refreshPromise?await this.refreshPromise:(this.refreshPromise=(async()=>{try{let t=this.authManager.loadStoredAuth();if(t?.sessionToken&&t.sessionToken!==this.config.appwriteSessionToken){let i=await this.authManager.verifyEntitlements(t.sessionToken,this.config.appwriteEndpoint,this.config.appwriteProjectId,this.config.teamId);if(i.allowed)return this.config.appwriteSessionToken=t.sessionToken,this.config.cloudSessionToken=t.sessionToken,i.teamId&&i.teamId!=="default"&&(this.config.teamId=i.teamId),this.lastAuthFailureTime=0,this.engine.setStatus("running"),this.logger.info(`\u2705 [ClusterSentinel] \u0110\xE3 t\u1EF1 \u0111\u1ED9ng n\u1EA1p phi\xEAn \u0111\u0103ng nh\u1EADp m\u1EDBi t\u1EEB worker_auth.json! (${i.userName})`),!0}let r=Date.now();if(this.lastAuthFailureTime>0&&r-this.lastAuthFailureTime<6e4)return!1;this.logger.warn("\u26A0\uFE0F [ClusterSentinel] Phi\xEAn x\xE1c th\u1EF1c Cloud \u0111\xE3 h\u1EBFt h\u1EA1n (HTTP 401). \u0110ang k\xEDch ho\u1EA1t Silent Refresh Token 24/7...");let n=await this.authManager.ensureValidSession(this.config.appwriteEndpoint,this.config.appwriteProjectId,!0);return n?.sessionToken?(this.config.appwriteSessionToken=n.sessionToken,this.config.cloudSessionToken=n.sessionToken,n.teamId&&n.teamId!=="default"&&(this.config.teamId=n.teamId),this.lastAuthFailureTime=0,this.engine.setStatus("running"),this.logger.info(`\u2705 [ClusterSentinel] \u0110\xE3 t\u1EF1 \u0111\u1ED9ng kh\xF4i ph\u1EE5c quy\u1EC1n h\u1EA1n 24/7 th\xE0nh c\xF4ng! (${n.userName})`),!0):(this.lastAuthFailureTime=Date.now(),Date.now()-this.lastAuthErrorLogTime>300*1e3&&(this.lastAuthErrorLogTime=Date.now(),this.logger.error("\u274C [ClusterSentinel] Kh\xF4ng th\u1EC3 t\u1EF1 \u0111\u1ED9ng l\xE0m m\u1EDBi phi\xEAn. Vui l\xF2ng \u0111\u0103ng nh\u1EADp l\u1EA1i Worker qua l\u1EC7nh: zplus-worker login")),this.engine.setStatus("auth_error","M\xE1y ch\u1EE7 tr\u1EF1c ban 24/7 b\u1ECB h\u1EBFt h\u1EA1n phi\xEAn. Vui l\xF2ng ch\u1EA1y l\u1EC7nh 'zplus-worker login' \u0111\u1EC3 c\u1EA5p l\u1EA1i phi\xEAn l\xE0m vi\u1EC7c."),!1)}catch(t){return this.lastAuthFailureTime=Date.now(),this.logger.error("\u274C [ClusterSentinel] L\u1ED7i ngo\u1EA1i l\u1EC7 trong Silent Refresh Token:",t?.message),this.engine.setStatus("auth_error",`L\u1ED7i ngo\u1EA1i l\u1EC7 x\xE1c th\u1EF1c: ${t?.message||"Kh\xF4ng x\xE1c \u0111\u1ECBnh"}`),!1}finally{this.refreshPromise=null}})(),await this.refreshPromise)}isCloudConfigured(){return!!(this.config.appwriteEndpoint&&this.config.appwriteProjectId&&(this.config.appwriteSessionToken||this.config.appwriteJwt))}startAutoUpdaterOnly(){this.autoUpdater.startPeriodicAutoUpdate(this.config.version||Vt)}async start(){if(this.isRunning)return;if(this.isRunning=!0,this.startAutoUpdaterOnly(),!this.isCloudConfigured()){this.logger.info("Appwrite Cloud credentials not fully configured. Running in standalone local mode.");return}this.logger.info(`\u{1F680} Initializing Team Cluster Sentinel for Team [${this.config.teamId}] (Worker: ${this.config.workerId}, Capacity: ${this.config.maxCapacity})`),this.config.appwriteSessionToken&&this.authManager.reconcileWorkerSession(this.config.appwriteSessionToken,this.config.appwriteEndpoint,this.config.appwriteProjectId,!1).catch(()=>{}),await this.registerWorkerInstance(),this.heartbeatTimer=setInterval(()=>{this.pingWorkerHeartbeat().catch(r=>{this.logger.debug("Worker heartbeat ping error:",r?.message)})},15e3);let t=this.config.clusterPollIntervalMs||3e3;this.pollTimer=setInterval(()=>{this.syncTeamAccounts().catch(n=>{this.logger.debug("Cluster account sync error:",n?.message)});let r=Date.now();r-this.lastNightConfigCheck>3e4&&(this.lastNightConfigCheck=r,this.syncNightShiftConfig().catch(()=>{}))},t),this.syncTeamAccounts().catch(()=>{}),this.syncNightShiftConfig().catch(()=>{})}async stop(){this.isRunning=!1,this.autoUpdater.stop(),this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=void 0),this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=void 0),this.isCloudConfigured()&&await this.markWorkerOffline(),this.logger.info("Cluster Sentinel stopped.")}async syncNightShiftConfig(){if(!(!this.isRunning||!this.isCloudConfigured()||!this.config.teamId))try{let t=this.config.appwriteEndpoint,r=this.config.databaseId||"zplus_app",n=`night_cfg_${this.config.teamId}`.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),i=`${t}/databases/${r}/collections/cluster_settings/documents/${n}`,a=await fetch(i,{method:"GET",headers:this.getHeaders()});if(!a.ok)return;let o=await a.json(),s=Number(o.updated_at||0);if(s>this.lastNightConfigUpdatedAt&&o.config_json)try{let c=JSON.parse(o.config_json);if(c.encryptedWorkerRecovery)try{let l=pa.CloudCrypto.decryptFromCloud(c.encryptedWorkerRecovery,this.config.teamId,[this.config.userId||"default","default"]),u=JSON.parse(l);u?.refreshToken&&this.authManager.syncRecoveryTokenFromCloud(u.refreshToken)}catch{}this.engine.automationEngine.configure(c),this.lastNightConfigUpdatedAt=s,this.logger.info(`\u{1F319} [ClusterSentinel] Synchronized latest Night AI config from Cloud DB (Provider: ${c.provider||"default"}, Enabled: ${c.enabled})`)}catch(c){this.logger.debug("Failed to parse night config JSON from Cloud DB:",c?.message)}}catch{}}async getActivePeerWorkers(){let t=Date.now();if(t-this.lastPeerCheckTime<15e3&&this.cachedPeerWorkers.length>0)return this.cachedPeerWorkers;try{let r=this.config.appwriteEndpoint,n=this.config.databaseId||"zplus_app",i=JSON.stringify({method:"equal",attribute:"team_id",values:[this.config.teamId]}),a=JSON.stringify({method:"limit",values:[25]}),o=`${r}/databases/${n}/collections/team_workers/documents?queries[]=${encodeURIComponent(i)}&queries[]=${encodeURIComponent(a)}`,s=await fetch(o,{method:"GET",headers:this.getHeaders()});if(s.ok){let c=await s.json(),l=Array.isArray(c?.documents)?c.documents:[];this.cachedPeerWorkers=l.filter(u=>u.worker_id!==this.config.workerId&&u.status==="online"&&t-Number(u.last_ping||0)<45e3).map(u=>({workerId:u.worker_id,currentLoad:Number(u.current_load||0),maxCapacity:Number(u.max_capacity||50),lastPing:Number(u.last_ping||0)})),this.lastPeerCheckTime=t}}catch{}return this.cachedPeerWorkers}async registerWorkerInstance(){try{let t=this.config.appwriteEndpoint,r=this.config.databaseId||"zplus_app",n=this.config.workerId.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),i=Ac(),a=this.engine.channelRunnerRegistry.getCount(),o=a>this.config.maxCapacity,s=`${t}/databases/${r}/collections/team_workers/documents/${n}`,c={data:{worker_id:this.config.workerId,team_id:this.config.teamId,worker_name:this.config.workerName,max_capacity:this.config.maxCapacity,recommended_capacity:this.config.recommendedCapacity||this.config.maxCapacity,current_load:a,is_overloaded:o,system_specs:JSON.stringify({...i,version:this.config.version||Vt}),status:"online",last_ping:Date.now()}},l=await fetch(s,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify(c)});if(l.status===401&&await this.handleAuthExpired()&&(l=await fetch(s,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify(c)})),l.ok){this.logger.info(`\u2705 Worker registered in Team Cluster: ${this.config.workerId}`);return}if(l.status===404){let u=`${t}/databases/${r}/collections/team_workers/documents`,f=this.getWorkerPermissions(),d=await fetch(u,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({documentId:n,permissions:f,...c})});if(d.status===401&&await this.handleAuthExpired()&&(d=await fetch(u,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({documentId:n,permissions:f,...c})})),!d.ok&&d.status===400){let h=this.config.userId?[`read("user:${this.config.userId}")`,`update("user:${this.config.userId}")`,`delete("user:${this.config.userId}")`]:['read("users")','update("users")','delete("users")'],v={data:{worker_id:this.config.workerId,team_id:this.config.teamId,worker_name:this.config.workerName,max_capacity:this.config.maxCapacity,current_load:a,status:"online",last_ping:Date.now()}};d=await fetch(u,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({documentId:n,permissions:h,...v})})}d.ok?this.logger.info(`\u2705 Worker registered in Team Cluster: ${this.config.workerId}`):this.logger.warn(`\u26A0\uFE0F Could not register in team_workers: HTTP ${d.status}`)}else this.logger.warn(`\u26A0\uFE0F Could not patch team_workers: HTTP ${l.status}`)}catch(t){this.logger.warn("Could not register in team_workers:",t?.message)}}async pingWorkerHeartbeat(){if(!(!this.isRunning||!this.isCloudConfigured()))try{let t=this.config.appwriteEndpoint,r=this.config.databaseId||"zplus_app",n=this.config.workerId.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),i=`${t}/databases/${r}/collections/team_workers/documents/${n}`,a=Ac(),o=this.engine.channelRunnerRegistry.getCount(),s=o>this.config.maxCapacity,c={current_load:o,is_overloaded:s,system_specs:JSON.stringify({...a,version:this.config.version||Vt}),last_ping:Date.now(),status:"online"},l=await fetch(i,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify({data:c})});if(l.status===401){await this.handleAuthExpired();return}if(l.ok)try{let d=await l.json()||{};d?.command==="UPGRADE"&&(this.logger.info("\u{1F4E1} [ClusterSentinel] Nh\u1EADn l\u1EC7nh UPGRADE t\u1EEB xa!"),this.autoUpdater.performUpdateAndRestart().catch(()=>{})),d?.max_capacity&&Number(d.max_capacity)!==this.config.maxCapacity&&(this.config.maxCapacity=Number(d.max_capacity),this.logger.info(`\u2699\uFE0F [ClusterSentinel] \u0110\xE3 c\u1EADp nh\u1EADt gi\u1EDBi h\u1EA1n t\u1EA3i t\u1EEB xa: ${this.config.maxCapacity}`))}catch{}else l.status===404?await this.registerWorkerInstance():l.status===400&&await fetch(i,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify({data:{current_load:o,last_ping:Date.now(),status:"online"}})}).catch(()=>{});let u=this.config.workerId.startsWith("worker_")?this.config.workerId:`worker_${this.config.workerId}`,f=this.engine.channelRunnerRegistry.getAll();for(let d of f)try{await this.engine.lockManager.renewLockRemote(d.accountId,u,6e4)}catch{}}catch{}}async markWorkerOffline(){try{let t=this.config.appwriteEndpoint,r=this.config.databaseId||"zplus_app",n=this.config.workerId.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),i=`${t}/databases/${r}/collections/team_workers/documents/${n}`;await fetch(i,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify({data:{status:"offline",last_ping:Date.now()}})})}catch{}}async syncTeamAccounts(){if(!(!this.isRunning||!this.isCloudConfigured()||this.isSyncingAccounts)){this.isSyncingAccounts=!0;try{let t=this.config.appwriteEndpoint,r=this.config.databaseId||"zplus_app",n=Date.now(),i=this.config.maxCapacity,a=0,o=100,s=!0,c=new Set,l=!1;for(;s&&this.isRunning;){let d=!!this.config.teamId&&this.config.teamId!=="default"?[this.config.teamId]:["default"],h=JSON.stringify({method:"equal",attribute:"team_id",values:d}),v=JSON.stringify({method:"limit",values:[o]}),w=JSON.stringify({method:"offset",values:[a]}),k=`${t}/databases/${r}/collections/channel_accounts/documents?queries[]=${encodeURIComponent(h)}&queries[]=${encodeURIComponent(v)}&queries[]=${encodeURIComponent(w)}`,m=await fetch(k,{method:"GET",headers:this.getHeaders()});if(!m.ok){if(m.status===401){if(await this.handleAuthExpired()&&!l){l=!0;continue}break}let y=await m.text().catch(()=>""),_=`HTTP ${m.status}`;try{let S=JSON.parse(y);S?.message&&(_+=`: ${S.message}`)}catch{if(y.includes("<title>")){let S=y.match(/<title>([^<]+)<\/title>/i);S&&(_+=`: ${S[1].trim()}`)}else y&&y.length<150&&(_+=`: ${y.trim()}`)}this.logger.warn((0,pa.formatActionableError)({context:"ClusterSentinel",action:"\u0110\u1ED3ng b\u1ED9 t\xE0i kho\u1EA3n Team t\u1EEB Cloud",error:_}));break}let x=await m.json(),b=Array.isArray(x?.documents)?x.documents:[];b.length<o?s=!1:a+=o;for(let y of b){let _=y.$id||y.id;c.add(_);let S=(y.platform||"zalo").toLowerCase(),R=S==="web"||S.includes("zalo")?"zalo":S,B=y.owner_type,T=y.current_owner,z=y.status,F=Number(y.lock_expires_at||0),G=Number(y.last_heartbeat||0),ee=!!this.engine.channelRunnerRegistry.get(R,_);if(!(y.nightWorkerEnabled===!0||y.night_worker_enabled===1||y.night_worker_enabled===!0)){ee&&(this.logger.warn(`\u{1F6AB} [Unselected Account] T\xE0i kho\u1EA3n ${_} (${y.accountName||""}) kh\xF4ng \u0111\u01B0\u1EE3c ch\u1ECDn ch\u1EA1y Worker 24/7 (nightWorkerEnabled=false). Bu\u1ED9c ng\u1EAFt WSS ngay l\u1EADp t\u1EE9c...`),this.engine.channelRunnerRegistry.unregister(R,_),this.engine.unregisterAccount(_),this.engine.lockManager.releaseLock(_));continue}if(ee&&(B==="desktop"||z==="active_desktop")){this.logger.info(`\u26A1 Master Preemption: Desktop reclaimed account ${_}. Stopping worker runner...`),this.engine.channelRunnerRegistry.unregister(R,_),this.engine.unregisterAccount(_),this.engine.lockManager.releaseLock(_);continue}let pe=this.config.workerId.startsWith("worker_")?this.config.workerId:`worker_${this.config.workerId}`;if(z==="deleted"||z==="expired"||z==="error"||z==="disabled"||z==="checkpoint"){ee&&(this.engine.channelRunnerRegistry.unregister(R,_),this.engine.unregisterAccount(_),this.engine.lockManager.releaseLock(_));continue}let ue=B==="worker"&&T===pe,ve=B==="desktop"&&n-G>6e4,me=B==="worker"&&F<n;if((z==="needs_worker"||ue||ve&&F<n||me)&&!ee){let oe=this.engine.channelRunnerRegistry.getCount(),ae=oe>=i;if(!ue&&(ae||oe/i>.8)){let ce=(await this.getActivePeerWorkers()).find(Ee=>Ee.currentLoad/Ee.maxCapacity<oe/i-.25);if(ce){this.logger.debug(`[Least-Loaded Yield] Nh\u01B0\u1EDDng t\xE0i kho\u1EA3n ${_} cho worker r\u1EA3nh h\u01A1n: ${ce.workerId} (T\u1EA3i peer: ${ce.currentLoad}/${ce.maxCapacity}, T\u1EA3i hi\u1EC7n t\u1EA1i: ${oe}/${i})`);continue}}if(ae){let ie=Ac();this.logger.warn(`\u26A0\uFE0F [Server Spec Capacity Alert] Worker ${this.config.workerId} hi\u1EC7n \u0111ang m\u1EDF ${oe+1}/${i} k\u1EBFt n\u1ED1i WSS. \u0110\xE3 v\u01B0\u1EE3t ng\u01B0\u1EE1ng khuy\u1EBFn ngh\u1ECB theo c\u1EA5u h\xECnh m\xE1y ch\u1EE7 (${Math.round(ie.totalMemMb/1024)}GB RAM, ${ie.cpuCount} CPUs, ${ie.freeMemMb}MB Free). Theo ch\xEDnh s\xE1ch trao quy\u1EC1n quy\u1EBFt \u0111\u1ECBnh cho kh\xE1ch h\xE0ng, Worker v\u1EABn ti\u1EBFp t\u1EE5c k\u1EBFt n\u1ED1i WSS cho t\xE0i kho\u1EA3n ${_}.`)}if(await this.engine.lockManager.acquireLockRemote(_,pe,6e4)){let ie=ue?"Resumed previous session":me?"Failover takeover (previous worker died)":ae?"Over-capacity active takeover (per customer policy)":"Active takeover";this.logger.info(`\u2705 Cluster takeover: [${ie}] Claimed account ${_} for team ${this.config.teamId}`),await this.spawnRunnerForAccount(y)}}}}let u=this.engine.channelRunnerRegistry.getAll();for(let f of u)c.has(f.accountId)||(this.logger.info(`\u{1F9F9} [ClusterSentinel] Thu h\u1ED3i runner ngo\u1EA1i lai ${f.accountId} (${f.platform}) do kh\xF4ng thu\u1ED9c Team [${this.config.teamId}]...`),this.engine.channelRunnerRegistry.unregister(f.platform,f.accountId),this.engine.unregisterAccount(f.accountId),await this.engine.lockManager.releaseLock(f.accountId))}catch(t){this.logger.debug("syncTeamAccounts warning:",t?.message)}finally{this.isSyncingAccounts=!1}}}async spawnRunnerForAccount(t){let r=t.$id||t.id,n=(t.platform||"zalo").toLowerCase(),i=n==="web"||n.includes("zalo")?"zalo":n;if(this.engine.channelRunnerRegistry.get(i,r))return;if(!(t.nightWorkerEnabled===!0||t.night_worker_enabled===1||t.night_worker_enabled===!0)){this.logger.warn(`\u{1F6AB} [ClusterSentinel] T\u1EEB ch\u1ED1i kh\u1EDFi ch\u1EA1y WSS cho t\xE0i kho\u1EA3n unselected: ${r}`);return}let o={};if(t.authSession){let c=[];if(Array.isArray(t.$permissions))for(let f of t.$permissions){let d=String(f).match(/user:([a-zA-Z0-9_-]+)/);d&&d[1]&&c.push(d[1])}t.user_id&&c.push(t.user_id),t.userId&&c.push(t.userId),this.config.userId&&c.push(this.config.userId);let l=Array.from(new Set([this.config.teamId,t.team_id,t.teamId,...c,"default"].filter(Boolean)));o=pa.CloudCrypto.parseCloudSession(t.authSession,this.config.teamId,l)||{},!!(o?.cookie||o?.cookies||o?.accessToken||o?.token||o?.botToken)?this.logger.info(`[ClusterSentinel] \u{1F513} Gi\u1EA3i m\xE3 th\xE0nh c\xF4ng phi\xEAn ho\u1EA1t \u0111\u1ED9ng cho ${r} qua CloudCrypto.`):this.logger.warn(`[ClusterSentinel] \u26A0\uFE0F Kh\xF4ng th\u1EC3 gi\u1EA3i m\xE3 phi\xEAn h\u1EE3p l\u1EC7 cho ${r}. Scopes \u0111\xE3 th\u1EED: [${l.join(", ")}]`)}let s=await wo.createRunner(i,r,o);if(s){this.engine.registerRunner(s),await s.start();let c=s.getStatus();if(c==="expired"||c==="error"){this.logger.warn(`\u274C [ClusterSentinel] Phi\xEAn \u0111\u0103ng nh\u1EADp c\u1EE7a t\xE0i kho\u1EA3n ${r} \u0111\xE3 h\u1EBFt h\u1EA1n/l\u1ED7i [status: ${c}]. T\u1EF1 \u0111\u1ED9ng g\u1EA1t t\u1EAFt tr\u1EF1c chi\u1EBFn v\xE0 gi\u1EA3i ph\xF3ng lock...`),this.engine.channelRunnerRegistry.unregister(i,r),this.engine.unregisterAccount(r),await this.engine.lockManager.releaseLock(r);try{let l=this.config.appwriteEndpoint,u=this.config.databaseId||"zplus_app",f=`${l}/databases/${u}/collections/channel_accounts/documents/${r}`;await fetch(f,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify({data:{status:c,nightWorkerEnabled:!1,current_owner:null,owner_type:"none"}})})}catch(l){this.logger.debug(`[ClusterSentinel] Cloud mark expired error for ${r}:`,l?.message)}return}this.engine.registerAccount({id:r,platform:i,accountName:t.accountName||r,status:c,nightWorkerEnabled:!0}),this.logger.info(`\u2705 Runner registered for ${i} account ${r} [status: ${c}]`)}}};var s4=le(it());var t4=le(it()),$p=class{constructor(t,r){this.config=t;this.logger=r||(0,t4.createLogger)("AppwriteDbDriver"),this.databaseId=t.databaseId||"zplus_app"}logger;databaseId;getHeaders(){let t={"Content-Type":"application/json","X-Appwrite-Project":this.config.projectId};return this.config.sessionToken?(t["X-Appwrite-Session"]=this.config.sessionToken,t.Cookie=`a_session_${this.config.projectId}=${this.config.sessionToken}; a_session_${this.config.projectId}_legacy=${this.config.sessionToken}`,this.config.sessionToken.startsWith("eyJ")&&(t["X-Fallback-Cookies"]=JSON.stringify({[`a_session_${this.config.projectId}`]:this.config.sessionToken,[`a_session_${this.config.projectId}_legacy`]:this.config.sessionToken}))):this.config.jwt&&(t["X-Appwrite-JWT"]=this.config.jwt),t}async getDocument(t,r){try{let n=`${this.config.endpoint}/databases/${this.databaseId}/collections/${t}/documents/${r}`,i=await fetch(n,{method:"GET",headers:this.getHeaders()});if(!i.ok){if(i.status===404)return null;throw new Error(`Failed to get document: HTTP ${i.status}`)}return await i.json()}catch(n){return this.logger.debug(`getDocument error for ${t}/${r}:`,n?.message),null}}async createDocument(t,r,n){let i=r.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),a=`${this.config.endpoint}/databases/${this.databaseId}/collections/${t}/documents`,o=await fetch(a,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({documentId:i,data:n})});if(!o.ok){let s=await this.parseCleanError(o,"T\u1EA1o document th\u1EA5t b\u1EA1i");throw new Error(`Failed to create document in ${t}: ${s}`)}return await o.json()}async parseCleanError(t,r){try{let n=await t.text();try{let i=JSON.parse(n);if(i?.message)return`HTTP ${t.status}: ${i.message}`}catch{if(n.includes("<title>")){let i=n.match(/<title>([^<]+)<\/title>/i);if(i)return`HTTP ${t.status}: ${i[1].trim()}`}else if(n&&n.length<150)return`HTTP ${t.status}: ${n.trim()}`}}catch{}return`HTTP ${t.status} (${t.statusText||r})`}async updateDocument(t,r,n){let i=r.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),a=`${this.config.endpoint}/databases/${this.databaseId}/collections/${t}/documents/${i}`,o=await fetch(a,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify({data:n})});if(!o.ok){let s=await this.parseCleanError(o,"C\u1EADp nh\u1EADt document th\u1EA5t b\u1EA1i");throw new Error(`Failed to update document in ${t}: ${s}`)}return await o.json()}async upsertDocument(t,r,n){try{return await this.updateDocument(t,r,n)}catch(i){if(String(i?.message||"").includes("404"))return await this.createDocument(t,r,n);throw i}}async queryDocuments(t,r){try{let n=[];if(r.filters&&r.filters.length>0)for(let c of r.filters)c.operator==="eq"?n.push(JSON.stringify({method:"equal",attribute:c.field,values:Array.isArray(c.value)?c.value:[c.value]})):c.operator==="neq"?n.push(JSON.stringify({method:"notEqual",attribute:c.field,values:Array.isArray(c.value)?c.value:[c.value]})):c.operator==="gt"?n.push(JSON.stringify({method:"greaterThan",attribute:c.field,values:[c.value]})):c.operator==="gte"?n.push(JSON.stringify({method:"greaterThanEqual",attribute:c.field,values:[c.value]})):c.operator==="lt"?n.push(JSON.stringify({method:"lessThan",attribute:c.field,values:[c.value]})):c.operator==="lte"?n.push(JSON.stringify({method:"lessThanEqual",attribute:c.field,values:[c.value]})):c.operator==="in"&&Array.isArray(c.value)&&n.push(JSON.stringify({method:"equal",attribute:c.field,values:c.value}));r.limit&&n.push(JSON.stringify({method:"limit",values:[r.limit]})),r.offset&&n.push(JSON.stringify({method:"offset",values:[r.offset]})),r.orderBy&&n.push(JSON.stringify({method:r.orderBy.direction==="desc"?"orderDesc":"orderAsc",attribute:r.orderBy.field}));let i=n.map(c=>`queries[]=${encodeURIComponent(c)}`).join("&"),a=`${this.config.endpoint}/databases/${this.databaseId}/collections/${t}/documents${i?`?${i}`:""}`,o=await fetch(a,{method:"GET",headers:this.getHeaders()});if(!o.ok)return[];let s=await o.json();return Array.isArray(s?.documents)?s.documents:[]}catch(n){return this.logger.debug(`queryDocuments error in ${t}:`,n?.message),[]}}async deleteDocument(t,r){try{let n=`${this.config.endpoint}/databases/${this.databaseId}/collections/${t}/documents/${r}`;return(await fetch(n,{method:"DELETE",headers:this.getHeaders()})).ok}catch{return!1}}};var r4=le(it()),zp=class{constructor(t,r){this.config=t;this.logger=r||(0,r4.createLogger)("AppwriteLockDriver"),this.collectionId=t.collectionId||"channel_accounts",this.databaseId=t.databaseId||"zplus_app"}logger;collectionId;databaseId;getHeaders(){let t={"Content-Type":"application/json","X-Appwrite-Project":this.config.projectId};return this.config.sessionToken?(t["X-Appwrite-Session"]=this.config.sessionToken,t.Cookie=`a_session_${this.config.projectId}=${this.config.sessionToken}; a_session_${this.config.projectId}_legacy=${this.config.sessionToken}`,this.config.sessionToken.startsWith("eyJ")&&(t["X-Fallback-Cookies"]=JSON.stringify({[`a_session_${this.config.projectId}`]:this.config.sessionToken,[`a_session_${this.config.projectId}_legacy`]:this.config.sessionToken}))):this.config.jwt&&(t["X-Appwrite-JWT"]=this.config.jwt),t}async acquireLock(t,r,n){let i=Date.now();try{let a=`${this.config.endpoint}/databases/${this.databaseId}/collections/${this.collectionId}/documents/${t}`,o=await fetch(a,{method:"GET",headers:this.getHeaders()});if(!o.ok)return!1;let s=await o.json(),c=s.current_owner,l=Number(s.lock_expires_at||0);if(c&&c!==r&&l>i)return!1;let u=`${this.config.endpoint}/databases/${this.databaseId}/collections/${this.collectionId}/documents/${t}`;if((await fetch(u,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify({data:{current_owner:r,owner_type:r.startsWith("worker")?"worker":"desktop",lock_expires_at:i+n,last_heartbeat:i,status:r.startsWith("worker")?"active_worker":"active_desktop"}})})).ok){await new Promise(h=>setTimeout(h,30+Math.floor(Math.random()*40)));let d=await fetch(a,{method:"GET",headers:this.getHeaders()});if(d.ok&&(await d.json()).current_owner===r)return!0}return!1}catch(a){return this.logger.debug("acquireLock error:",a?.message),!1}}async releaseLock(t,r){try{if(r){let a=`${this.config.endpoint}/databases/${this.databaseId}/collections/${this.collectionId}/documents/${t}`,o=await fetch(a,{method:"GET",headers:this.getHeaders()});if(o.ok){let s=await o.json();if(s.current_owner&&s.current_owner!==r)return!1}}let n=`${this.config.endpoint}/databases/${this.databaseId}/collections/${this.collectionId}/documents/${t}`;return(await fetch(n,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify({data:{current_owner:null,owner_type:"none",lock_expires_at:0,status:"offline"}})})).ok}catch{return!1}}async renewLock(t,r,n){try{let i=`${this.config.endpoint}/databases/${this.databaseId}/collections/${this.collectionId}/documents/${t}`;return(await fetch(i,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify({data:{lock_expires_at:Date.now()+n,last_heartbeat:Date.now()}})})).ok}catch{return!1}}async getLock(t){try{let r=`${this.config.endpoint}/databases/${this.databaseId}/collections/${this.collectionId}/documents/${t}`,n=await fetch(r,{method:"GET",headers:this.getHeaders()});if(!n.ok)return null;let i=await n.json();return{resourceId:t,ownerId:i.current_owner||"",ownerType:i.owner_type,expiresAt:Number(i.lock_expires_at||0),lastHeartbeat:Number(i.last_heartbeat||0)}}catch{return null}}};var n4=le(it()),jp=class{constructor(t,r){this.config=t;this.logger=r||(0,n4.createLogger)("AppwriteCoordinator"),this.databaseId=t.databaseId||"zplus_app"}logger;databaseId;getHeaders(){let t={"Content-Type":"application/json","X-Appwrite-Project":this.config.projectId};return this.config.sessionToken?(t["X-Appwrite-Session"]=this.config.sessionToken,t.Cookie=`a_session_${this.config.projectId}=${this.config.sessionToken}; a_session_${this.config.projectId}_legacy=${this.config.sessionToken}`,this.config.sessionToken.startsWith("eyJ")&&(t["X-Fallback-Cookies"]=JSON.stringify({[`a_session_${this.config.projectId}`]:this.config.sessionToken,[`a_session_${this.config.projectId}_legacy`]:this.config.sessionToken}))):this.config.jwt&&(t["X-Appwrite-JWT"]=this.config.jwt),t}async registerNode(t){try{let r=t.workerId.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),n=`${this.config.endpoint}/databases/${this.databaseId}/collections/team_workers/documents/${r}`,i={data:{worker_id:t.workerId,team_id:t.teamId,worker_name:t.workerName,max_capacity:t.maxCapacity,recommended_capacity:t.recommendedCapacity||t.maxCapacity,current_load:t.currentLoad,is_overloaded:t.isOverloaded??!1,system_specs:t.systemSpecs?JSON.stringify(t.systemSpecs):void 0,status:t.status,last_ping:Date.now()}};if((await fetch(n,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify(i)})).status===404){let o=`${this.config.endpoint}/databases/${this.databaseId}/collections/team_workers/documents`;await fetch(o,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({documentId:r,...i})})}}catch(r){this.logger.warn("registerNode warning:",r?.message)}}async pingHeartbeat(t,r){try{let n=t.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),i=`${this.config.endpoint}/databases/${this.databaseId}/collections/team_workers/documents/${n}`;await fetch(i,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify({data:{current_load:r.currentLoad,is_overloaded:r.isOverloaded??!1,system_specs:r.systemSpecs?JSON.stringify(r.systemSpecs):void 0,last_ping:r.lastPing,status:r.status||"online"}})})}catch{}}async fetchPendingAccounts(t,r=100,n=0){try{let i=[`queries[]=${encodeURIComponent(JSON.stringify({method:"equal",attribute:"team_id",values:[t]}))}`,`queries[]=${encodeURIComponent(JSON.stringify({method:"limit",values:[r]}))}`,`queries[]=${encodeURIComponent(JSON.stringify({method:"offset",values:[n]}))}`].join("&"),a=`${this.config.endpoint}/databases/${this.databaseId}/collections/channel_accounts/documents?${i}`,o=await fetch(a,{method:"GET",headers:this.getHeaders()});if(!o.ok)return[];let s=await o.json();return Array.isArray(s?.documents)?s.documents:[]}catch(i){return this.logger.debug("fetchPendingAccounts error:",i?.message),[]}}async fetchActiveNodes(t){try{let r=[`queries[]=${encodeURIComponent(JSON.stringify({method:"equal",attribute:"team_id",values:[t]}))}`,`queries[]=${encodeURIComponent(JSON.stringify({method:"limit",values:[50]}))}`].join("&"),n=`${this.config.endpoint}/databases/${this.databaseId}/collections/team_workers/documents?${r}`,i=await fetch(n,{method:"GET",headers:this.getHeaders()});if(!i.ok)return[];let a=await i.json();return(Array.isArray(a?.documents)?a.documents:[]).map(s=>({workerId:s.worker_id||s.$id,teamId:s.team_id,workerName:s.worker_name||"",maxCapacity:Number(s.max_capacity||50),currentLoad:Number(s.current_load||0),status:s.status||"online",lastPing:Number(s.last_ping||0),isOverloaded:!!s.is_overloaded,recommendedCapacity:Number(s.recommended_capacity||s.max_capacity||50),systemSpecs:s.system_specs?typeof s.system_specs=="string"?JSON.parse(s.system_specs):s.system_specs:void 0}))}catch(r){return this.logger.debug("fetchActiveNodes error:",r?.message),[]}}async markNodeOffline(t){try{let r=t.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),n=`${this.config.endpoint}/databases/${this.databaseId}/collections/team_workers/documents/${r}`;await fetch(n,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify({data:{status:"offline",last_ping:Date.now()}})})}catch{}}};var i4=le(it()),Mp=class{constructor(t,r){this.config=t;this.logger=r||(0,i4.createLogger)("AppwriteAuthDriver")}logger;async verifySessionToken(t){try{let r=`${this.config.endpoint}/account`,n=await fetch(r,{method:"GET",headers:{"Content-Type":"application/json","X-Appwrite-Project":this.config.projectId,"X-Appwrite-Session":t,Cookie:`a_session_${this.config.projectId}=${t}; a_session_${this.config.projectId}_legacy=${t}`,...t.startsWith("eyJ")?{"X-Fallback-Cookies":JSON.stringify({[`a_session_${this.config.projectId}`]:t,[`a_session_${this.config.projectId}_legacy`]:t})}:{}}});if(!n.ok)return{allowed:!1,userId:"",userName:"Unknown",email:"",teamId:"default",isOwner:!1,isPremium:!1,reason:`Phi\xEAn \u0111\u0103ng nh\u1EADp kh\xF4ng h\u1EE3p l\u1EC7 (HTTP ${n.status}).`};let i=await n.json(),a=i.$id||i.id||"",o=i.name||"Ng\u01B0\u1EDDi d\xF9ng ZPlus",s=i.email||"",c=i.prefs||{},l=c.entitlements||{},u=!!(l.isPremium??c.isPremium??c.plan==="enterprise"),f=!!(l.isOwner??c.isOwner??!0),d=l.allowedCloudSync!==!1&&c.allowedCloudSync!==!1,h=u?-1:Number(l.cloudTtlDays||c.cloudTtlDays||7),v=u||f||d,w=c.teamId||l.teamId||"default";return{allowed:v,userId:a,userName:o,email:s,teamId:w,isOwner:f,isPremium:u,reason:v?u?"H\u1EE3p l\u1EC7":`T\xE0i kho\u1EA3n Mi\u1EC5n Ph\xED (Free Tier) - \u0110\u1EC7m Cloud ${h} ng\xE0y.`:"Y\xEAu c\u1EA7u quy\u1EC1n Enterprise ho\u1EB7c ch\u1EBF \u0111\u1ED9 \u0111\u1EC7m Cloud \u0111\u1EC3 ch\u1EA1y Worker 24/7."}}catch(r){return this.logger.error("verifySessionToken error:",r),{allowed:!1,userId:"",userName:"Unknown",email:"",teamId:"default",isOwner:!1,isPremium:!1,reason:r?.message||"L\u1ED7i k\u1EBFt n\u1ED1i x\xE1c th\u1EF1c."}}}async checkEntitlements(t){return this.config.sessionToken?this.verifySessionToken(this.config.sessionToken):{allowed:!0,userId:t,userName:"Worker Node",email:"",teamId:"default",isOwner:!0,isPremium:!0}}};var O0=le(require("fs")),F0=require("stream"),a4=require("stream/promises"),o4=le(it()),qp=class{constructor(t,r){this.config=t;this.logger=r||(0,o4.createLogger)("AppwriteStorageDriver")}logger;getHeaders(){let t={"X-Appwrite-Project":this.config.projectId};return this.config.sessionToken?(t["X-Appwrite-Session"]=this.config.sessionToken,t.Cookie=`a_session_${this.config.projectId}=${this.config.sessionToken}; a_session_${this.config.projectId}_legacy=${this.config.sessionToken}`,this.config.sessionToken.startsWith("eyJ")&&(t["X-Fallback-Cookies"]=JSON.stringify({[`a_session_${this.config.projectId}`]:this.config.sessionToken,[`a_session_${this.config.projectId}_legacy`]:this.config.sessionToken}))):this.config.jwt&&(t["X-Appwrite-JWT"]=this.config.jwt),t}async createFile(t,r,n,i,a){let o=r==="unique()"?"unique()":r.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),s=`${this.config.endpoint}/storage/buckets/${t}/files`,c=new FormData;c.append("fileId",o);let l=Buffer.isBuffer(n)?n:Buffer.from(n),u=new Blob([l]);if(c.append("file",u,i),a&&a.length>0)for(let h=0;h<a.length;h++)c.append(`permissions[${h}]`,a[h]);let f=await fetch(s,{method:"POST",headers:this.getHeaders(),body:c});if(!f.ok){let h=await f.text();throw new Error(`Failed to upload file to storage: HTTP ${f.status} - ${h}`)}let d=await f.json();return{$id:d.$id||r,name:d.name||i,sizeOriginal:d.sizeOriginal||l.length,mimeType:d.mimeType,$createdAt:d.$createdAt,$updatedAt:d.$updatedAt}}async getFileDownload(t,r){let n=`${this.config.endpoint}/storage/buckets/${t}/files/${r}/download`,i=await fetch(n,{method:"GET",headers:this.getHeaders()});if(!i.ok)throw new Error(`Failed to download file: HTTP ${i.status}`);let a=await i.arrayBuffer();return Buffer.from(a)}async downloadFileToPath(t,r,n){let i=`${this.config.endpoint}/storage/buckets/${t}/files/${r}/download`,a=await fetch(i,{method:"GET",headers:this.getHeaders()});if(!a.ok)throw new Error(`Failed to download file: HTTP ${a.status}`);if(typeof F0.Readable.fromWeb=="function"&&a.body)await(0,a4.pipeline)(F0.Readable.fromWeb(a.body),O0.default.createWriteStream(n));else{let o=await a.arrayBuffer();await O0.default.promises.writeFile(n,Buffer.from(o))}return!0}async deleteFile(t,r){let n=`${this.config.endpoint}/storage/buckets/${t}/files/${r}`;return(await fetch(n,{method:"DELETE",headers:this.getHeaders()})).ok}async listFiles(t){let r=`${this.config.endpoint}/storage/buckets/${t}/files`,n=await fetch(r,{method:"GET",headers:this.getHeaders()});if(!n.ok)return{files:[],total:0};let i=await n.json();return{files:(i.files||[]).map(a=>({$id:a.$id,name:a.name,sizeOriginal:a.sizeOriginal,mimeType:a.mimeType})),total:i.total||0}}async getFile(t,r){let n=`${this.config.endpoint}/storage/buckets/${t}/files/${r}`,i=await fetch(n,{method:"GET",headers:this.getHeaders()});return i.ok?await i.json():null}};var Hp=class{constructor(t,r){this.config=t;this.logger=r||(0,s4.createLogger)("AppwriteCloudAdapter");let n={get endpoint(){return t.cloudEndpoint||t.appwriteEndpoint||"https://api.softty.net/v1"},get projectId(){return t.cloudProjectId||t.appwriteProjectId||"699cfc3100136099c1c1"},get databaseId(){return t.cloudDatabaseId||t.databaseId||"zplus_app"},get sessionToken(){return t.cloudSessionToken||t.appwriteSessionToken},get jwt(){return t.cloudJwt||t.appwriteJwt}};this.database=new $p(n,this.logger),this.lockStorage=new zp(n,this.logger),this.coordinator=new jp(n,this.logger),this.auth=new Mp(n,this.logger),this.storage=new qp(n,this.logger)}providerName="appwrite";database;lockStorage;coordinator;auth;storage;logger;async start(){this.logger.info("\u2705 Appwrite Cloud Adapter initialized.")}async stop(){this.logger.info("Appwrite Cloud Adapter stopped.")}};var c4=le(it()),Wp=class{constructor(t,r){this.config=t;this.logger=r||(0,c4.createLogger)("CustomApiAdapter");let n=t.cloudEndpoint||"https://api.softty.net/custom/v1",a={"Content-Type":"application/json",Authorization:`Bearer ${t.cloudSessionToken||t.cloudJwt||""}`,"X-Tenant-ID":t.teamId||"default"};this.database={async getDocument(o,s){try{let c=await fetch(`${n}/data/${o}/${s}`,{headers:a});return c.ok?await c.json():null}catch{return null}},async createDocument(o,s,c){return await(await fetch(`${n}/data/${o}`,{method:"POST",headers:a,body:JSON.stringify({id:s,...c})})).json()},async updateDocument(o,s,c){return await(await fetch(`${n}/data/${o}/${s}`,{method:"PATCH",headers:a,body:JSON.stringify(c)})).json()},async upsertDocument(o,s,c){return await(await fetch(`${n}/data/${o}/${s}/upsert`,{method:"POST",headers:a,body:JSON.stringify(c)})).json()},async queryDocuments(o,s){try{let c=await fetch(`${n}/data/${o}/query`,{method:"POST",headers:a,body:JSON.stringify(s)});if(!c.ok)return[];let l=await c.json();return Array.isArray(l?.items)?l.items:[]}catch{return[]}},async deleteDocument(o,s){try{return(await fetch(`${n}/data/${o}/${s}`,{method:"DELETE",headers:a})).ok}catch{return!1}}},this.lockStorage={async acquireLock(o,s,c){try{let l=await fetch(`${n}/locks/acquire`,{method:"POST",headers:a,body:JSON.stringify({resourceId:o,ownerId:s,ttlMs:c})});return l.ok?!!(await l.json())?.acquired:!1}catch{return!1}},async releaseLock(o,s){try{return(await fetch(`${n}/locks/release`,{method:"POST",headers:a,body:JSON.stringify({resourceId:o,ownerId:s})})).ok}catch{return!1}},async renewLock(o,s,c){try{return(await fetch(`${n}/locks/renew`,{method:"POST",headers:a,body:JSON.stringify({resourceId:o,ownerId:s,ttlMs:c})})).ok}catch{return!1}},async getLock(o){try{let s=await fetch(`${n}/locks/${o}`,{headers:a});return s.ok?await s.json():null}catch{return null}}},this.coordinator={async registerNode(o){try{await fetch(`${n}/cluster/nodes/register`,{method:"POST",headers:a,body:JSON.stringify(o)})}catch{}},async pingHeartbeat(o,s){try{await fetch(`${n}/cluster/nodes/${o}/heartbeat`,{method:"POST",headers:a,body:JSON.stringify(s)})}catch{}},async fetchPendingAccounts(o,s=100,c=0){try{let l=await fetch(`${n}/cluster/accounts/pending?teamId=${o}&limit=${s}&offset=${c}`,{headers:a});if(!l.ok)return[];let u=await l.json();return Array.isArray(u?.accounts)?u.accounts:[]}catch{return[]}},async markNodeOffline(o){try{await fetch(`${n}/cluster/nodes/${o}/offline`,{method:"POST",headers:a})}catch{}}},this.auth={async verifySessionToken(o){try{let s=await fetch(`${n}/auth/verify`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`}});return s.ok?await s.json():{allowed:!1,userId:"",userName:"Unknown",email:"",teamId:"default",isOwner:!1,isPremium:!1,reason:"Invalid session token"}}catch(s){return{allowed:!1,userId:"",userName:"Unknown",email:"",teamId:"default",isOwner:!1,isPremium:!1,reason:s?.message}}},async checkEntitlements(o){return{allowed:!0,userId:o,userName:"User",email:"",teamId:"default",isOwner:!0,isPremium:!0}}}}providerName="custom-api";database;lockStorage;coordinator;auth;logger;async start(){this.logger.info("\u{1F50C} Custom API Cloud Adapter initialized.")}async stop(){this.logger.info("Custom API Cloud Adapter stopped.")}};var l4=le(it()),Gp=class{providerName="in-memory";database;lockStorage;coordinator;auth;logger;tables=new Map;locks=new Map;nodes=new Map;constructor(t,r){this.logger=r||(0,l4.createLogger)("InMemoryCloudAdapter");let n=i=>{let a=this.tables.get(i);return a||(a=new Map,this.tables.set(i,a)),a};this.database={async getDocument(i,a){return n(i).get(a)||null},async createDocument(i,a,o){return n(i).set(a,{$id:a,id:a,...o}),n(i).get(a)},async updateDocument(i,a,o){let c={...n(i).get(a)||{$id:a,id:a},...o};return n(i).set(a,c),c},async upsertDocument(i,a,o){return this.updateDocument(i,a,o)},async queryDocuments(i,a){let o=Array.from(n(i).values());if(a.filters)for(let s of a.filters)s.operator==="eq"&&(o=o.filter(c=>c[s.field]===s.value));return a.limit&&(o=o.slice(0,a.limit)),o},async deleteDocument(i,a){return n(i).delete(a)}},this.lockStorage={acquireLock:async(i,a,o)=>{let s=Date.now(),c=this.locks.get(i);return c&&c.expiresAt>s&&c.ownerId!==a?!1:(this.locks.set(i,{resourceId:i,ownerId:a,ownerType:a.startsWith("worker")?"worker":"desktop",expiresAt:s+o,lastHeartbeat:s}),!0)},releaseLock:async(i,a)=>{let o=this.locks.get(i);return o?a&&o.ownerId!==a?!1:(this.locks.delete(i),!0):!0},renewLock:async(i,a,o)=>this.lockStorage.acquireLock(i,a,o),getLock:async i=>this.locks.get(i)||null},this.coordinator={registerNode:async i=>{this.nodes.set(i.workerId,i)},pingHeartbeat:async(i,a)=>{let o=this.nodes.get(i);o&&(o.currentLoad=a.currentLoad,o.lastPing=a.lastPing,o.status=a.status||"online")},fetchPendingAccounts:async i=>Array.from(n("channel_accounts").values()).filter(o=>o.team_id===i||o.teamId===i),markNodeOffline:async i=>{let a=this.nodes.get(i);a&&(a.status="offline")}},this.auth={verifySessionToken:async i=>({allowed:!!i,userId:"user_test_in_memory",userName:"Test User",email:"test@softty.net",teamId:"team_test",isOwner:!0,isPremium:!0}),checkEntitlements:async i=>({allowed:!0,userId:i,userName:"Test User",email:"test@softty.net",teamId:"team_test",isOwner:!0,isPremium:!0})}}async start(){this.logger.info("\u{1F9EA} In-Memory Cloud Adapter initialized.")}async stop(){this.logger.info("In-Memory Cloud Adapter stopped.")}};var u4=le(it()),Vp=class{static create(t,r){let n=r||(0,u4.createLogger)("CloudAdapterFactory");switch(t.cloudProvider||"appwrite"){case"custom-api":return n.info("Creating Custom API Cloud Adapter..."),new Wp(t,n);case"in-memory":return n.info("Creating In-Memory Cloud Adapter..."),new Gp(t,n);case"appwrite":default:return n.info("Creating Appwrite Cloud Adapter..."),new Hp(t,n)}}};var p4=le(it()),Jp=class{constructor(t,r,n){this.engine=t;this.cloudDb=r;this.logger=n||(0,p4.createLogger)(`WorkerOutboundDispatchService:${this.engine.config.workerId}`)}logger;isProcessing=!1;pollInterval;start(t=4e3){this.pollInterval||(this.logger.info(`Starting Worker Outbound Dispatcher (polling every ${t}ms)...`),this.pollInterval=setInterval(()=>{this.drainPendingQueue().catch(r=>{this.logger.debug("drainPendingQueue error:",r?.message)})},t))}stop(){this.pollInterval&&(clearInterval(this.pollInterval),this.pollInterval=void 0,this.logger.info("Worker Outbound Dispatcher stopped."))}async drainPendingQueue(){if(!this.isProcessing){this.isProcessing=!0;try{let t=await this.cloudDb.queryDocuments("outbound_queue",{filters:[{field:"status",operator:"eq",value:"pending"}],limit:10});if(t&&t.length>0)for(let r of t)await this.processSingleMessage(r)}finally{this.isProcessing=!1}}}async processSingleMessage(t){let r=t.$id||t.id;if(!r||!t.account_id||!t.thread_id)return;let n=Number(t.created_at)||0;if(n>0&&Date.now()-n>7200*1e3){this.logger.warn(`[WorkerOutbound] \u{1F6E1}\uFE0F Outbound task ${r} is older than 2 hours, marking failed (expired)`),await this.cloudDb.updateDocument("outbound_queue",r,{status:"failed",error_message:"Expired: Task is older than 2 hours",processed_at:Date.now(),updated_at:Date.now()}).catch(()=>{});return}let a=this.engine.channelRunnerRegistry.getAll().find(u=>u.accountId===t.account_id);if(!a)return;let o=t.content||"",s=Array.isArray(t.media_urls)?[...t.media_urls]:[],c=t.media_type,l;if(typeof o=="string"&&o.trim().startsWith("{"))try{let u=JSON.parse(o);if(u&&u.__zplus_relay_v1===!0){let f=new Set(["sendMessage","sendImage","sendImages"]);if(u.action&&!f.has(String(u.action)))return;let d=u.payload||{};if(o=String(d.content??d.text??d.message??d.caption??""),Array.isArray(u.mediaItems)&&u.mediaItems.length>0){let h=u.mediaItems.filter(v=>v?.url&&v.role!=="thumbnail").map(v=>String(v.url));h.length>0&&(s=h)}else Array.isArray(d.mediaUrls)&&d.mediaUrls.length>0&&(s=d.mediaUrls);(u.action==="sendImage"||u.action==="sendImages")&&!c&&(c="image"),(u.clientMsgId||d.clientMsgId)&&(l=String(u.clientMsgId||d.clientMsgId))}}catch{}try{await this.cloudDb.updateDocument("outbound_queue",r,{status:"processing"})}catch{return}try{let u={id:l||`msg_out_${Date.now()}_${Math.random().toString(36).substring(2,6)}`,cliMsgId:l,platform:a.platform,threadId:t.thread_id,conversationId:t.thread_id,accountId:a.accountId,senderId:a.accountId,senderName:"T\xF4i",senderType:"agent",messageType:c==="image"?"image":"text",content:o,attachments:s.map(d=>({url:d,mimeType:"image/jpeg"})),timestamp:Date.now(),isSelf:!0,status:"sent"};if(await a.sendMessage(u))await this.cloudDb.updateDocument("outbound_queue",r,{status:"completed",processed_at:Date.now()}),this.logger.info(`[WorkerOutbound] \u2705 Dispatched outbound message ${r} via ${a.platform}`);else throw new Error("Channel runner sendMessage returned false")}catch(u){this.logger.error(`[WorkerOutbound] \u274C Failed to dispatch message ${r}:`,u);let f=(t.retry_count||0)+1;await this.cloudDb.updateDocument("outbound_queue",r,{status:f>=3?"failed":"pending",retry_count:f,error_message:u?.message||String(u)})}}};var Kp=class{logger;channelRunnerRegistry;lockManager;deltaQueue;automationEngine;pushDispatcher;httpServer;clusterSentinel;cloudAdapter;outboundDispatcher;status="idle";lastError;startTime=0;activeAccounts=new Map;messagesProcessed=0;heartbeatTimer;storageQuotaExceeded=!1;config;constructor(t){this.config={enableHttp:!1,teamId:"default",workerName:`Worker_${t.workerId}`,version:t.version||Vt,maxCapacity:50,clusterPollIntervalMs:5e3,heartbeatIntervalMs:15e3,logLevel:"info",...t,workerId:t.workerId},this.logger=(0,Yp.createLogger)(`WorkerEngine:${this.config.workerId}`),this.channelRunnerRegistry=new Oc(this.logger),this.lockManager=new Fc(6e4,this.logger),this.cloudAdapter=Vp.create(this.config,this.logger),(this.config.cloudEndpoint||this.config.appwriteEndpoint)&&this.lockManager.setStorageProvider(this.cloudAdapter.lockStorage);let r=process.env.WORKER_DATA_DIR||process.env.DATA_DIR||da.default.join(Zp.default.homedir(),".zplus","data"),n=da.default.join(r,`pending_messages_${this.config.workerId}.json`);this.deltaQueue=new Dc(1e4,this.logger,n),this.automationEngine=new Bc(this.logger,{enabled:!1,apiKey:this.config.deepseekApiKey||this.config.geminiApiKey||this.config.openaiApiKey||this.config.anthropicApiKey||this.config.customAiApiKey,baseUrl:this.config.aiBaseUrl,provider:this.config.aiProvider,model:this.config.aiModel,systemPrompt:this.config.nightSystemPrompt,fallbackMessage:this.config.nightFallbackReply}),this.pushDispatcher=new Nc(this.logger),this.clusterSentinel=new Up(this.config,this,this.logger),this.httpServer=this.config.enableHttp&&this.config.port?new Fp(this.config.port,this,this.lockManager,this.deltaQueue,this.logger):null,this.outboundDispatcher=new Jp(this,this.cloudAdapter.database,this.logger),this.lockManager.onPreempt(async i=>{this.logger.info(`Preemption callback: stopping WSS for account ${i}...`);let a=this.channelRunnerRegistry.getAll();for(let o of a)o.accountId===i&&await o.stop()})}async start(){if(this.status==="running"){this.logger.warn("Worker is already running.");return}if(this.logger.info("Starting ZPlus 24/7 Headless Worker Engine..."),this.status="initializing",this.startTime=Date.now(),this.httpServer)try{await this.httpServer.start()}catch(r){this.logger.error("Failed to start Worker HTTP Ingress Server:",r)}else this.logger.info("\u{1F6E1}\uFE0F Ch\u1EBF \u0111\u1ED9 Zero-Port (Outbound-only) \u0111ang ho\u1EA1t \u0111\u1ED9ng: Worker kh\xF4ng m\u1EDF b\u1EA5t k\u1EF3 c\u1ED5ng l\u1EAFng nghe Inbound n\xE0o.");try{await this.cloudAdapter.start()}catch(r){this.logger.error("Failed to start Cloud Adapter:",r)}if(this.config.isStandby){this.status="idle",this.logger.warn(`\u23F8\uFE0F Worker is in STANDBY mode: ${this.config.standbyReason||"Unauthorized / Free Tier / Non-owner"}. Worker will NOT process accounts.`),this.clusterSentinel.startAutoUpdaterOnly(),this.writeLocalHeartbeat(),this.heartbeatTimer=setInterval(()=>{this.writeLocalHeartbeat()},3e4);return}this.heartbeatTimer=setInterval(()=>{this.sendHeartbeat()},this.config.heartbeatIntervalMs);try{await this.clusterSentinel.start()}catch(r){this.logger.error("Failed to start Cluster Sentinel:",r)}this.outboundDispatcher.start(),this.status="running",this.writeLocalHeartbeat();let t=this.config.enableHttp?`Port: ${this.config.port}`:"Zero-Port Headless Daemon";this.logger.info(`\u2705 ZPlus Worker Engine started successfully [ID: ${this.config.workerId}, Mode: ${t}]`),this.deltaQueue.getCount()>0&&this.flushPendingMessages().catch(r=>{this.logger.warn("Error flushing pending messages on startup:",r?.message)});try{typeof global.gc=="function"&&global.gc()}catch{}}async stop(){this.logger.info("Stopping ZPlus Worker Engine..."),this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=void 0),await this.clusterSentinel.stop(),await this.cloudAdapter.stop(),this.httpServer&&await this.httpServer.stop(),this.clearLocalHeartbeat(),this.outboundDispatcher.stop(),await this.channelRunnerRegistry.stopAll(),this.status="stopped",this.logger.info("ZPlus Worker Engine stopped.")}registerRunner(t){t.onMessage?.(r=>{this.handleIncomingMessage(r,t)}),this.channelRunnerRegistry.register(t)}registerAccount(t){this.activeAccounts.set(t.id,t),this.logger.info(`Registered active account: ${t.accountName} [${t.platform}]`),this.writeLocalHeartbeat()}unregisterAccount(t){this.activeAccounts.delete(t),this.logger.info(`Unregistered account: ${t}`),this.writeLocalHeartbeat()}recordMessageProcessed(){this.messagesProcessed++}async handleIncomingMessage(t,r){if(this.status==="auth_error"||this.status==="paused"||this.status==="stopped"){this.logger.warn(`\u23F8\uFE0F [StateGuard] B\u1ECF qua x\u1EED l\xFD tin nh\u1EAFn ${t.id} v\xEC Worker \u0111ang \u1EDF tr\u1EA1ng th\xE1i [${this.status}].`);return}this.recordMessageProcessed(),this.deltaQueue.enqueue(t);try{await this.pushMessageToCloud(t),this.deltaQueue.remove(t.id)}catch(n){this.logger.warn(`\u26A0\uFE0F [CloudSync] Kh\xF4ng th\u1EC3 \u0111\u1EA9y tin ${t.id} l\xEAn Cloud, gi\u1EEF l\u1EA1i trong \u0111\u1EC7m: ${n?.message}`)}try{let n=await this.automationEngine.evaluateIncomingMessage(t);if(n&&r){this.logger.info(`[NightAutoReply] Sending automated reply to thread ${t.threadId}: "${n}"`);let i={id:`reply_${Date.now()}`,platform:t.platform,conversationId:t.conversationId,threadId:t.threadId,accountId:t.accountId,senderId:t.accountId,senderName:"ZPlus Night Assistant",senderType:"agent",messageType:"text",content:n,timestamp:Date.now(),isSelf:!0,status:"sent"};if(await r.sendMessage(i)){this.deltaQueue.enqueue(i);try{await this.pushMessageToCloud(i),this.deltaQueue.remove(i.id)}catch(o){this.logger.warn(`\u26A0\uFE0F [NightAutoReply] Kh\xF4ng th\u1EC3 \u0111\u1EA9y tin ph\u1EA3n h\u1ED3i l\xEAn Cloud: ${o?.message}`)}}else this.logger.warn(`[NightAutoReply] Socket delivery failed for thread ${t.threadId}. Skipped cloud push to prevent ghost message.`)}}catch(n){this.logger.warn("Auto-reply evaluation notice:",n)}try{await this.pushDispatcher.enqueueNotification(t,this.cloudAdapter.database,{teamId:this.config.teamId,userId:this.config.userId})}catch(n){this.logger.debug("Push notification enqueue notice:",n)}}async pushMessageToCloud(t){if(!(!this.config.cloudEndpoint&&!this.config.appwriteEndpoint))try{let r=t.id.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,36),n=new Date().toISOString(),i=t.threadId||t.conversationId,a=t.mediaUrl||t.metadata?.mediaUrl||Array.isArray(t.attachments)&&t.attachments[0]?.url||void 0,o;if(a&&this.cloudAdapter.storage&&!this.storageQuotaExceeded&&["chat.photo","chat.voice","chat.sticker","chat.doodle","image","audio","voice"].includes((t.messageType||t.type||"").toLowerCase()))try{let v=(t.messageType||t.type||"").toLowerCase(),w=v.includes("voice")||v.includes("audio")?".aac":".jpg",k=`media_${r}${w}`,m=await fetch(a,{headers:{"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",Referer:"https://chat.zalo.me/"}});if(m.ok){let x=await m.arrayBuffer(),b=Buffer.from(x);if(b.length>0&&b.length<=20*1024*1024){let y=this.config.storageBucketId||"zplus-media-vault",_=await this.cloudAdapter.storage.createFile(y,r,b,k);_?.$id&&(o=_.$id,this.logger.info(`\u2601\uFE0F [MediaSync] In-memory streamed media (${(b.length/1024).toFixed(1)} KB) to Cloud Storage: ${o}`))}}else m.status===403&&this.logger.warn(`[MediaSync] Media URL already expired (403): ${a}`)}catch(v){let w=String(v?.message||"").toLowerCase();w.includes("quota")||w.includes("403")||w.includes("limit")?(this.storageQuotaExceeded=!0,this.logger.warn(`\u26A0\uFE0F [MediaSync] Cloud Storage quota exceeded for team ${this.config.teamId}. Pausing cloud media uploads.`)):this.logger.debug("[MediaSync] Cloud media upload notice:",v)}let s=t.metadata?.rawPayload?.data||t.metadata?.rawPayload||t.rawPayload?.data||t.rawPayload||{},c=Array.isArray(t.attachments)?t.attachments:Array.isArray(s.attachments)?s.attachments:a?[{url:a,cloud_file_id:o}]:[],l=t.metadata?.rawMsgType||s.msgType||t.msgType||t.messageType||t.type||"chat.text",u=Yp.LeanMessageNormalizer.normalizeMessage({msgType:l,content:t.content||t.text||s.content||"",attachments:c,quote:t.quote||t.quotedMessage||s.quote,mentions:t.mentions||s.mentions,reactions:t.reactions||t.metadata?.reactions||s.reactions||s.reaction,cliMsgId:t.cliMsgId||t.clientMsgId||s.cliMsgId||void 0,senderName:t.senderName||void 0,cloudFileId:o||void 0}),f={...u.leanPayload,...a?{mediaUrl:a}:{},...o?{cloud_file_id:o}:{}},d=(u.cleanContent||t.content||t.text||"").slice(0,3e3),h={conversation_id:t.conversationId||t.threadId,thread_id:i,account_id:t.accountId,sender_id:t.senderId,sender_name:(t.senderName||"").slice(0,255),senderType:t.senderType||"customer",messageType:l,content:d,payload:JSON.stringify(f).slice(0,3e3),timestamp:t.timestamp||Date.now(),is_self:!!(t.isSelf||t.senderId==="0"||t.accountId&&String(t.senderId)===String(t.accountId)),is_recall:0,status:t.status||"sent",team_id:this.config.teamId||"",zplus_action:"INSERT",zplus_updated_at:n};if(await this.cloudAdapter.database.upsertDocument("messages",r,h),this.logger.info(`\u2601\uFE0F [CloudSync] Pushed message ${t.id} to Cloud DB via ${this.cloudAdapter.providerName}.`),i&&t.accountId)try{let v=`${i}:${t.accountId}`,k=`z_${d4.default.createHash("md5").update(`conversations:${v}`).digest("hex")}`,m=(d||(u.cleanAttachments.length>0?"[\u0110\xEDnh k\xE8m]":"")).slice(0,500),b=!!(t.isGroup||t.groupName||t.metadata?.rawPayload?.type===1||t.metadata?.rawPayload?.data?.type===1||String(i).startsWith("g"))?t.groupName||"Nh\xF3m Zalo":t.senderName||i,y={thread_id:i,account_id:t.accountId,team_id:this.config.teamId||"",name:b.slice(0,255),last_message:JSON.stringify({content:m,senderId:t.senderId,timestamp:t.timestamp||Date.now(),msgType:l}),timestamp:t.timestamp||Date.now(),unread_count:1,peerId:t.senderId,peerName:(t.senderName||"").slice(0,255),platform:t.platform||"zalo",isPinned:!1,zplus_action:"UPDATE",zplus_updated_at:n};await this.cloudAdapter.database.upsertDocument("conversations",k,y)}catch(v){this.logger.debug(`[CloudSync] Note updating conversations on cloud: ${v?.message}`)}}catch(r){this.logger.error(`\u274C [CloudSync] Failed to push message ${t.id} to Cloud DB: ${r?.message||r}`)}}getMetrics(){let t=this.startTime>0?Math.floor((Date.now()-this.startTime)/1e3):0,r=process.memoryUsage().rss/(1024*1024);return{workerId:this.config.workerId,status:this.status,uptimeSeconds:t,activeAccountsCount:this.activeAccounts.size,totalMessagesProcessed:this.messagesProcessed,memoryUsageMb:Math.round(r*100)/100,lastHeartbeat:new Date().toISOString()}}sendHeartbeat(){let t=this.getMetrics();this.writeLocalHeartbeat(),this.logger.info(`\u{1F493} Heartbeat: status=${t.status}, accounts=${t.activeAccountsCount}, msgs=${t.totalMessagesProcessed}, pendingDelta=${this.deltaQueue.getCount()}, uptime=${t.uptimeSeconds}s`)}setStatus(t,r){let n=this.status;this.status=t,r!==void 0&&(this.lastError=r),t==="auth_error"||t==="paused"?n==="running"&&(this.logger.warn(`\u23F8\uFE0F [StateGuard] Chuy\u1EC3n sang tr\u1EA1ng th\xE1i [${t}]. T\u1EA1m d\u1EEBng (PAUSE) to\xE0n b\u1ED9 Channel Runners.`),this.channelRunnerRegistry.pauseAll().catch(i=>{this.logger.error("Error pausing runners:",i)})):t==="running"&&(n==="auth_error"||n==="paused")&&(this.logger.info("\u25B6\uFE0F [StateGuard] Ph\u1EE5c h\u1ED3i tr\u1EA1ng th\xE1i [running]. K\xEDch ho\u1EA1t l\u1EA1i to\xE0n b\u1ED9 Channel Runners & X\u1EA3 h\xE0ng \u0111\u1EE3i."),this.channelRunnerRegistry.resumeAll().catch(i=>{this.logger.error("Error resuming runners:",i)}),this.flushPendingMessages().catch(i=>{this.logger.warn("Error flushing pending messages on resume:",i?.message)})),this.writeLocalHeartbeat()}async flushPendingMessages(){let t=this.deltaQueue.getAll();if(t.length===0)return;this.logger.info(`\u{1F680} [FlushQueue] B\u1EAFt \u0111\u1EA7u x\u1EA3 ${t.length} tin nh\u1EAFn t\u1ED3n \u0111\u1ECDng l\xEAn Cloud DB...`);let r=0;for(let n of t)try{await this.pushMessageToCloud(n),this.deltaQueue.remove(n.id),r++}catch(i){this.logger.debug(`[FlushQueue] G\u1EB7p l\u1ED7i khi \u0111\u1EA9y tin ${n.id}: ${i?.message}`)}r>0&&(this.logger.info(`\u2705 [FlushQueue] \u0110\xE3 x\u1EA3 th\xE0nh c\xF4ng ${r}/${t.length} tin nh\u1EAFn l\xEAn Cloud DB!`),this.writeLocalHeartbeat())}writeLocalHeartbeat(){try{let t=process.env.ZPLUS_HOME||da.default.join(Zp.default.homedir(),".zplus");Si.default.existsSync(t)||Si.default.mkdirSync(t,{recursive:!0});let r=da.default.join(t,"worker_heartbeat.json"),n=this.getMetrics(),i={vendor:"Softtynet Co., Ltd.",product:"Softty ZPlus Platform",daemonTitle:"ZPlus 24/7 Headless Worker Daemon",version:this.config.version||"1.0.10",homepage:"https://softty.net",supportEmail:"support@softty.net",processTitle:process.title||"zplus-worker (Softtynet Co., Ltd.)",status:this.status,lastError:this.lastError||null,workerId:this.config.workerId,workerName:this.config.workerName,teamId:this.config.teamId,pid:process.pid,uptimeSeconds:n.uptimeSeconds,activeAccountsCount:n.activeAccountsCount,activeRunners:this.channelRunnerRegistry.getCount(),accounts:Array.from(this.activeAccounts.values()).map(o=>({id:o.id,name:o.accountName||o.id,platform:o.platform||"zalo",status:o.status||"active",nightWorkerEnabled:o.nightWorkerEnabled,proxyId:o.proxyId||null})),totalMessagesProcessed:n.totalMessagesProcessed,pendingDeltaMessages:this.deltaQueue.getCount(),memoryUsageMb:n.memoryUsageMb,isZeroPort:!this.config.enableHttp,port:this.config.enableHttp?this.config.port:null,lastPing:Date.now(),timestamp:Date.now()},a=`${r}.${process.pid}.tmp`;Si.default.writeFileSync(a,JSON.stringify(i,null,2)),Si.default.renameSync(a,r)}catch{}}clearLocalHeartbeat(){try{let t=process.env.ZPLUS_HOME||da.default.join(Zp.default.homedir(),".zplus"),r=da.default.join(t,"worker_heartbeat.json");if(Si.default.existsSync(r)){let n={status:"stopped",workerId:this.config.workerId,pid:process.pid,lastPing:Date.now(),timestamp:Date.now()},i=`${r}.${process.pid}.tmp`;Si.default.writeFileSync(i,JSON.stringify(n,null,2)),Si.default.renameSync(i,r)}}catch{}}};var ir=le(require("os")),Ye=le(require("fs")),ft=le(require("path")),et=require("child_process"),f4=le(it()),Xp=class{logger;constructor(t){this.logger=t||(0,f4.createLogger)("WorkerAutostartManager")}getExecutableInfo(){let t=process.execPath,r=ft.default.resolve(__dirname,"cli.js");Ye.default.existsSync(r)||(r=ft.default.resolve(__dirname,"../dist/cli.js"));let n=r.includes("_npx")||r.includes("npm-cache");if(!Ye.default.existsSync(r)||n){let i="";try{let a=process.platform==="win32"?"where zplus-worker":"which zplus-worker",o=(0,et.execSync)(a,{encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim().split(`
70
70
  `)[0].trim();o&&!o.includes("_npx")&&Ye.default.existsSync(o)&&(i=o)}catch{}if(i)r=i;else{let a=process.env.ZPLUS_HOME||process.env.DATA_DIR||ft.default.join(ir.default.homedir(),".zplus"),o=ft.default.join(a,"runtime"),s=ft.default.join(o,"cli.js");try{Ye.default.existsSync(r)&&(Ye.default.existsSync(o)||Ye.default.mkdirSync(o,{recursive:!0}),Ye.default.copyFileSync(r,s),Ye.default.chmodSync(s,493),r=s)}catch{Ye.default.existsSync(r)||(r=ft.default.resolve(process.cwd(),"dist/cli.js"))}}}return{nodePath:t,cliPath:r}}getStatus(){let t=process.platform;if(t==="linux"){let r=ft.default.join(ir.default.homedir(),".config/systemd/user/zplus-worker.service"),n="/etc/systemd/system/zplus-worker.service",i=Ye.default.existsSync(r)||Ye.default.existsSync(n),a=!1;try{a=(0,et.execSync)("pm2 list",{encoding:"utf-8",stdio:["pipe","pipe","ignore"]}).includes("zplus-worker")}catch{a=!1}return{platform:"linux",isSupported:!0,isEnabled:i||a,serviceType:i?"systemd":a?"pm2":"systemd",targetPath:Ye.default.existsSync(r)?r:n,details:i?"\u0110\xE3 c\u1EA5u h\xECnh Systemd t\u1EF1 kh\u1EDFi \u0111\u1ED9ng c\xF9ng Linux.":a?"\u0110ang ch\u1EA1y v\xE0 t\u1EF1 duy tr\xEC qua PM2 Daemon.":"Ch\u01B0a k\xEDch ho\u1EA1t t\u1EF1 kh\u1EDFi \u0111\u1ED9ng."}}if(t==="darwin"){let r=ft.default.join(ir.default.homedir(),"Library/LaunchAgents/net.softty.zplus-worker.plist"),n=Ye.default.existsSync(r);return{platform:"darwin",isSupported:!0,isEnabled:n,serviceType:"launchd",targetPath:r,details:n?"\u0110\xE3 c\u1EA5u h\xECnh macOS LaunchAgent t\u1EF1 b\u1EADt khi kh\u1EDFi \u0111\u1ED9ng m\xE1y.":"Ch\u01B0a k\xEDch ho\u1EA1t t\u1EF1 kh\u1EDFi \u0111\u1ED9ng tr\xEAn macOS."}}if(t==="win32"){let r=!1;try{r=(0,et.execSync)('schtasks /query /tn "ZPlusWorker"',{encoding:"utf-8",stdio:["pipe","pipe","ignore"]}).includes("ZPlusWorker")}catch{r=!1}return{platform:"win32",isSupported:!0,isEnabled:r,serviceType:"schtasks",details:r?"\u0110\xE3 c\u1EA5u h\xECnh Windows Task Scheduler t\u1EF1 kh\u1EDFi \u0111\u1ED9ng c\xF9ng Windows (onstart).":"Ch\u01B0a k\xEDch ho\u1EA1t t\u1EF1 kh\u1EDFi \u0111\u1ED9ng tr\xEAn Windows."}}return{platform:t,isSupported:!1,isEnabled:!1,serviceType:"unknown",details:`H\u1EC7 \u0111i\u1EC1u h\xE0nh [${t}] kh\xF4ng h\u1ED7 tr\u1EE3 tr\xECnh t\u1EF1 kh\u1EDFi \u0111\u1ED9ng t\u1EF1 \u0111\u1ED9ng.`}}enableAutostart(){let t=process.platform,{nodePath:r,cliPath:n}=this.getExecutableInfo(),i=ft.default.join(ir.default.homedir(),".zplus");Ye.default.existsSync(i)||Ye.default.mkdirSync(i,{recursive:!0});try{if(t==="linux"){let a=typeof process.getuid=="function"&&process.getuid()===0,o=`[Unit]
71
71
  Description=Softty ZPlus 24/7 Zalo Automation Worker Daemon (Softtynet Co., Ltd.)
72
72
  Documentation=https://softty.net https://docs.zplus.app
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softtynet/zplus-worker",
3
- "version": "1.0.51",
3
+ "version": "1.0.52",
4
4
  "description": "ZPlus 24/7 Headless Personal Zalo Automation Worker & Cloud Sync Sentinel",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",