@softtynet/zplus-worker 1.0.34 → 1.0.36

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 +4 -4
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -104,7 +104,7 @@ ${m}`,k="",T="",z=Math.min(y,a);hw(g)&&(k+=Kj(g,S,a),x=x.slice(g.length),z-=g.le
104
104
  ${m}${k}
105
105
  ${v}`),w.pop(),`{${k}}`}case"number":return isFinite(g)?String(g):t?t(g):"null";case"boolean":return g===!0?"true":"false";case"undefined":return;case"bigint":if(n)return String(g);default:return t?t(g):void 0}}function p(h,g,w){switch(typeof g){case"string":return bo(g);case"object":{if(g===null)return"null";if(typeof g.toJSON=="function"){if(g=g.toJSON(h),typeof g!="object")return p(h,g,w);if(g===null)return"null"}if(w.indexOf(g)!==-1)return r;let _="",m=g.length!==void 0;if(m&&Array.isArray(g)){if(g.length===0)return"[]";if(s<w.length+1)return'"[Array]"';w.push(g);let k=Math.min(g.length,a),T=0;for(;T<k-1;T++){let C=p(String(T),g[T],w);_+=C!==void 0?C:"null",_+=","}let z=p(String(T),g[T],w);if(_+=z!==void 0?z:"null",g.length-1>a){let C=g.length-a-1;_+=`,"... ${_s(C)} not stringified"`}return w.pop(),`[${_}]`}let v=Object.keys(g),x=v.length;if(x===0)return"{}";if(s<w.length+1)return'"[Object]"';let y="",S=Math.min(x,a);m&&hw(g)&&(_+=Kj(g,",",a),v=v.slice(g.length),S-=g.length,y=","),i&&(v=dw(v,o)),w.push(g);for(let k=0;k<S;k++){let T=v[k],z=p(T,g[T],w);z!==void 0&&(_+=`${y}${bo(T)}:${z}`,y=",")}if(x>a){let k=x-a;_+=`${y}"...":"${_s(k)} not stringified"`}return w.pop(),`{${_}}`}case"number":return isFinite(g)?String(g):t?t(g):"null";case"boolean":return g===!0?"true":"false";case"undefined":return;case"bigint":if(n)return String(g);default:return t?t(g):void 0}}function d(h,g,w){if(arguments.length>1){let _="";if(typeof w=="number"?_=" ".repeat(Math.min(w,10)):typeof w=="string"&&(_=w.slice(0,10)),g!=null){if(typeof g=="function")return c("",{"":h},[],g,_,"");if(Array.isArray(g))return u("",h,[],Qce(g),_,"")}if(_.length!==0)return l("",h,[],_,"")}return p("",h,[])}return d}});var n$=O((mPe,r$)=>{"use strict";var yw=Symbol.for("pino.metadata"),{DEFAULT_LEVELS:t$}=Kh(),tle=t$.info;function rle(e,t){e=e||[],t=t||{dedupe:!1};let r=Object.create(t$);r.silent=1/0,t.levels&&typeof t.levels=="object"&&Object.keys(t.levels).forEach(p=>{r[p]=t.levels[p]});let n={write:i,add:a,remove:c,emit:o,flushSync:s,end:u,minLevel:0,lastId:0,streams:[],clone:l,[yw]:!0,streamLevels:r};return Array.isArray(e)?e.forEach(a,n):a.call(n,e),e=null,n;function i(p){let d,h=this.lastLevel,{streams:g}=this,w=0,_;for(let m=nle(g.length,t.dedupe);ole(m,g.length,t.dedupe);m=ile(m,t.dedupe))if(d=g[m],d.level<=h){if(w!==0&&w!==d.level)break;if(_=d.stream,_[yw]){let{lastTime:v,lastMsg:x,lastObj:y,lastLogger:S}=this;_.lastLevel=h,_.lastTime=v,_.lastMsg=x,_.lastObj=y,_.lastLogger=S}_.write(p),t.dedupe&&(w=d.level)}else if(!t.dedupe)break}function o(...p){for(let{stream:d}of this.streams)typeof d.emit=="function"&&d.emit(...p)}function s(){for(let{stream:p}of this.streams)typeof p.flushSync=="function"&&p.flushSync()}function a(p){if(!p)return n;let d=typeof p.write=="function"||p.stream,h=p.write?p:p.stream;if(!d)throw Error("stream object needs to implement either StreamEntry or DestinationStream interface");let{streams:g,streamLevels:w}=this,_;typeof p.levelVal=="number"?_=p.levelVal:typeof p.level=="string"?_=w[p.level]:typeof p.level=="number"?_=p.level:_=tle;let m={stream:h,level:_,levelVal:void 0,id:++n.lastId};return g.unshift(m),g.sort(e$),this.minLevel=g[0].level,n}function c(p){let{streams:d}=this,h=d.findIndex(g=>g.id===p);return h>=0&&(d.splice(h,1),d.sort(e$),this.minLevel=d.length>0?d[0].level:-1),n}function u(){for(let{stream:p}of this.streams)typeof p.flushSync=="function"&&p.flushSync(),p.end()}function l(p){let d=new Array(this.streams.length);for(let h=0;h<d.length;h++)d[h]={level:p,stream:this.streams[h].stream};return{write:i,add:a,remove:c,minLevel:p,streams:d,clone:l,emit:o,flushSync:s,[yw]:!0}}}function e$(e,t){return e.level-t.level}function nle(e,t){return t?e-1:0}function ile(e,t){return t?e-1:e+1}function ole(e,t,r){return r?e>=0:e<t}r$.exports=rle});var y$=O((gPe,un)=>{"use strict";var sle=require("node:os"),p$=jv(),ale=$v(),cle=qv(),f$=K6(),lle=Zj(),d$=Ja(),{configure:ule}=Qj(),{assertDefaultLevelFound:ple,mappings:h$,genLsCache:fle,genLevelComparison:dle,assertLevelComparison:hle}=cw(),{DEFAULT_LEVELS:m$,SORTING_ORDER:mle}=Kh(),{createArgsNormalizer:gle,asChindings:yle,buildSafeSonicBoom:i$,buildFormatters:xle,stringify:xw,normalizeDestFileDescriptor:o$,noop:ble}=Zh(),{version:vle}=lw(),{chindingsSym:s$,redactFmtSym:wle,serializersSym:a$,timeSym:_le,timeSliceIndexSym:Sle,streamSym:kle,stringifySym:c$,stringifySafeSym:bw,stringifiersSym:l$,setLevelSym:Ele,endSym:Ale,formatOptsSym:Cle,messageKeySym:Rle,errorKeySym:Tle,nestedKeySym:Ile,mixinSym:Ple,levelCompSym:Ole,useOnlyCustomLevelsSym:Fle,formattersSym:u$,hooksSym:Dle,nestedKeyStrSym:Ble,mixinMergeStrategySym:Lle,msgPrefixSym:Nle}=d$,{epochTime:g$,nullTime:Ule}=f$,{pid:jle}=process,$le=sle.hostname(),zle=p$.err,Mle={level:"info",levelComparison:mle.ASC,levels:m$,messageKey:"msg",errorKey:"err",nestedKey:null,enabled:!0,base:{pid:jle,hostname:$le},serializers:Object.assign(Object.create(null),{err:zle}),formatters:Object.assign(Object.create(null),{bindings(e){return e},level(e,t){return{level:t}}}),hooks:{logMethod:void 0,streamWrite:void 0},timestamp:g$,name:void 0,redact:null,customLevels:null,useOnlyCustomLevels:!1,depthLimit:5,edgeLimit:100},qle=gle(Mle),Hle=Object.assign(Object.create(null),p$);function vw(...e){let t={},{opts:r,stream:n}=qle(t,ale(),...e);r.level&&typeof r.level=="string"&&m$[r.level.toLowerCase()]!==void 0&&(r.level=r.level.toLowerCase());let{redact:i,crlf:o,serializers:s,timestamp:a,messageKey:c,errorKey:u,nestedKey:l,base:p,name:d,level:h,customLevels:g,levelComparison:w,mixin:_,mixinMergeStrategy:m,useOnlyCustomLevels:v,formatters:x,hooks:y,depthLimit:S,edgeLimit:k,onChild:T,msgPrefix:z}=r,C=ule({maximumDepth:S,maximumBreadth:k}),N=xle(x.level,x.bindings,x.log),P=xw.bind({[bw]:C}),V=i?cle(i,P):{},Q=i?{stringify:V[wle]}:{stringify:P},J="}"+(o?`\r
106
106
  `:`
107
- `),fe=yle.bind(null,{[s$]:"",[a$]:s,[l$]:V,[c$]:xw,[bw]:C,[u$]:N}),de="";p!==null&&(d===void 0?de=fe(p):de=fe(Object.assign({},p,{name:d})));let be=a instanceof Function?a:a?g$:Ule,xe=be().indexOf(":")+1;if(v&&!g)throw Error("customLevels is required if useOnlyCustomLevels is set true");if(_&&typeof _!="function")throw Error(`Unknown mixin type "${typeof _}" - expected "function"`);if(z&&typeof z!="string")throw Error(`Unknown msgPrefix type "${typeof z}" - expected "string"`);ple(h,g,v);let K=h$(g,v);typeof n.emit=="function"&&n.emit("message",{code:"PINO_CONFIG",config:{levels:K,messageKey:c,errorKey:u}}),hle(w);let ie=dle(w);return Object.assign(t,{levels:K,[Ole]:ie,[Fle]:v,[kle]:n,[_le]:be,[Sle]:xe,[c$]:xw,[bw]:C,[l$]:V,[Ale]:J,[Cle]:Q,[Rle]:c,[Tle]:u,[Ile]:l,[Ble]:l?`,${JSON.stringify(l)}:{`:"",[a$]:s,[Ple]:_,[Lle]:m,[s$]:de,[u$]:N,[Dle]:y,silent:ble,onChild:T,[Nle]:z}),Object.setPrototypeOf(t,lle()),fle(t),t[Ele](h),t}un.exports=vw;un.exports.destination=(e=process.stdout.fd)=>typeof e=="object"?(e.dest=o$(e.dest||process.stdout.fd),i$(e)):i$({dest:o$(e),minLength:0});un.exports.transport=rw();un.exports.multistream=n$();un.exports.levels=h$();un.exports.stdSerializers=Hle;un.exports.stdTimeFunctions=Object.assign({},f$);un.exports.symbols=d$;un.exports.version=vle;un.exports.default=vw;un.exports.pino=vw});function em(e,t){let r=e.key,n=e.message,i=r.remoteJid||"",o="";r.fromMe?o=t:o=r.participant||r.remoteJid||"";let s="",a="text",c="";n?n.conversation?(s=n.conversation,a="text"):n.extendedTextMessage?(s=n.extendedTextMessage.text||"",a="text"):n.imageMessage?(s=n.imageMessage.caption||"",a="image",c=n.imageMessage.url||""):n.videoMessage?(s=n.videoMessage.caption||"",a="video",c=n.videoMessage.url||""):n.audioMessage?(a="audio",c=n.audioMessage.url||""):n.documentMessage?(s=n.documentMessage.title||n.documentMessage.fileName||"",a="file",c=n.documentMessage.url||""):n.stickerMessage?(a="sticker",c=n.stickerMessage.url||""):n.protocolMessage||n.senderKeyDistributionMessage?(a="system",s="System message"):(a="other",s="[Tin nh\u1EAFn kh\xF4ng \u0111\u01B0\u1EE3c h\u1ED7 tr\u1EE3]"):(a="other",s="");let u={rawMsg:Wle(e)};if(e.pushName&&(u.pushName=e.pushName),n?.extendedTextMessage?.contextInfo?.quotedMessage){let p=n.extendedTextMessage.contextInfo;u.quotedMessage={participant:p.participant,stanzaId:p.stanzaId,text:p.quotedMessage?.conversation||p.quotedMessage?.extendedTextMessage?.text||""}}let l=e.messageTimestamp?Number(e.messageTimestamp)*1e3:Date.now();return{id:r.id||"",conversationId:i,senderId:o,senderName:e.pushName||void 0,text:s,type:a,mediaUrl:c,timestamp:l,platform:"whatsapp",isFromMe:!!r.fromMe,metadata:u}}function Wle(e){if(!e||typeof e!="object")return e;let t={};if(e.key&&(t.key={remoteJid:e.key.remoteJid,fromMe:e.key.fromMe,id:e.key.id,participant:e.key.participant}),e.pushName&&(t.pushName=e.pushName),e.messageTimestamp&&(t.messageTimestamp=e.messageTimestamp),e.status&&(t.status=e.status),e.message){let r=e.message;t.message={},r.conversation&&(t.message.conversation=r.conversation),r.extendedTextMessage&&(t.message.extendedTextMessage={text:r.extendedTextMessage.text},r.extendedTextMessage.contextInfo&&(t.message.extendedTextMessage.contextInfo={stanzaId:r.extendedTextMessage.contextInfo.stanzaId,participant:r.extendedTextMessage.contextInfo.participant})),r.imageMessage&&(t.message.imageMessage={caption:r.imageMessage.caption,mimetype:r.imageMessage.mimetype}),r.videoMessage&&(t.message.videoMessage={caption:r.videoMessage.caption,mimetype:r.videoMessage.mimetype}),r.audioMessage&&(t.message.audioMessage={mimetype:r.audioMessage.mimetype,seconds:r.audioMessage.seconds}),r.documentMessage&&(t.message.documentMessage={title:r.documentMessage.title,fileName:r.documentMessage.fileName,mimetype:r.documentMessage.mimetype}),r.stickerMessage&&(t.message.stickerMessage={mimetype:r.stickerMessage.mimetype})}return t}var x$=F(()=>{"use strict"});function fu(e,t){let r=String(e.id||e.jid||""),n=String(e.name||e.verifiedName||e.notify||"WhatsApp User"),i=String(e.imgUrl||e.avatar||"");return{id:r,name:n,avatarUrl:i||void 0,platform:"whatsapp",phoneNumber:t||e.phoneNumber||void 0,rawContact:e}}function b$(e){let t=String(e.id||e.jid||""),r=String(e.name||e.displayName||"WhatsApp Chat"),n=String(e.imgUrl||e.avatar||""),i="direct";return(t.endsWith("@g.us")||e.isGroup)&&(i="group"),{id:t,name:r,avatarUrl:n||void 0,type:i,unreadCount:Number(e.unreadCount||0),platform:"whatsapp",rawConversation:e}}var v$=F(()=>{"use strict"});var E$={};qi(E$,{WhatsAppAdapter:()=>ww});var vo,w$,_$,S$,k$,ww,A$=F(()=>{"use strict";vo=le(require("@whiskeysockets/baileys")),w$=le(y$()),_$=le(Rd()),S$=le(Id()),k$=le(Dd());kl();x$();v$();ww=class{accountId;platform="whatsapp";eventBus=new ei;status="disconnected";socket=null;session=null;isReconnecting=!1;chatsMap=new Map;contactsMap=new Map;constructor(t){this.accountId=t}async initialize(t){this.session=t,this.status="connecting",this.eventBus.emit("session:status_changed","connecting");let r=t.authData.sessionPath||`./sessions/whatsapp_${this.accountId}`;try{let{state:n,saveCreds:i}=await(0,vo.useMultiFileAuthState)(r),o=(0,w$.default)({level:"silent"}),s=[2,3e3,1023223821];try{let c=await(0,vo.fetchLatestBaileysVersion)();c&&c.version&&(s=c.version)}catch{}let a={version:s,auth:n,logger:o,printQRInTerminal:!1,defaultQueryTimeoutMs:3e4,connectTimeoutMs:3e4};if(t.proxy){let c=this.createProxyAgent(t.proxy);c&&(a.agent=c)}this.socket=(0,vo.default)(a),this.socket.ev.on("creds.update",i),this.setupListeners()}catch(n){throw this.status="disconnected",this.eventBus.emit("session:status_changed","disconnected",n.message||String(n)),n}}async disconnect(){if(this.isReconnecting=!1,this.socket){try{this.socket.end(void 0)}catch{}this.socket=null}this.status="disconnected",this.eventBus.emit("session:status_changed","disconnected")}async sendMessage(t,r){if(!this.socket)throw new Error("WhatsApp adapter not initialized");await this.sendTyping(t,!0);let n=Math.floor(Math.random()*2e3)+1500;await new Promise(s=>setTimeout(s,n)),await this.sendTyping(t,!1);let i={};if(r.type==="text")i={text:r.text};else if(r.type==="image")i={image:{url:r.url||r.filePath},caption:r.caption||""};else if(r.type==="sticker")i={sticker:{url:r.url||r.filePath||r.stickerId}};else if(r.type==="file")i={document:{url:r.url||r.filePath},fileName:r.filename||"file"};else throw new Error(`Unsupported message payload type: ${r.type}`);r.quoteId&&(i.contextInfo={stanzaId:r.quoteId,participant:t.endsWith("@g.us")?void 0:t,quotedMessage:{conversation:"[Tr\xEDch d\u1EABn tin nh\u1EAFn]"}});let o=await this.socket.sendMessage(t,i);if(!o)throw new Error("Failed to send WhatsApp message");return em(o,this.accountId)}async getConversations(t=20){let r=Array.from(this.chatsMap.values());return r.sort((n,i)=>Number(i.conversationTimestamp||0)-Number(n.conversationTimestamp||0)),r.slice(0,t).map(b$)}async getMessageHistory(t,r=50,n){return[]}async getCurrentUser(){if(!this.socket)return null;let t=this.socket.authState?.creds?.me||this.socket.user;if(!t)return null;let r=t.id;r.includes(":")&&(r=r.split(":")[0]+"@s.whatsapp.net");let n=t.name||this.socket.user?.name||"WhatsApp User",i="";try{i=await this.socket.profilePictureUrl(r,"image")||""}catch{}return fu({id:r,name:n,imgUrl:i},this.accountId)}async getContactInfo(t){if(this.contactsMap.has(t))return fu(this.contactsMap.get(t));if(!this.socket)throw new Error("WhatsApp adapter not initialized");try{let r=await this.socket.profilePictureUrl(t,"image");return fu({id:t,name:"WhatsApp User",imgUrl:r})}catch{return fu({id:t,name:"WhatsApp User"})}}async markAsRead(t){if(this.socket)try{await this.socket.sendPresenceUpdate("paused",t)}catch{}}async sendTyping(t,r){if(this.socket)try{await this.socket.sendPresenceUpdate(r?"composing":"paused",t)}catch{}}getUnderlyingClient(){return this.socket}setupListeners(){this.socket&&(this.socket.ev.on("connection.update",t=>{let{connection:r,lastDisconnect:n,qr:i}=t;i&&this.eventBus.emit("auth:qr_received",i),r==="connecting"&&(this.status="connecting",this.eventBus.emit("session:status_changed","connecting")),r==="open"&&(this.status="connected",this.eventBus.emit("session:status_changed","connected")),r==="close"&&(n?.error?.output?.statusCode!==vo.DisconnectReason.loggedOut&&this.session?(this.isReconnecting=!0,this.initialize(this.session)):(this.status="disconnected",this.eventBus.emit("session:status_changed","disconnected","Session logged out or expired")))}),this.socket.ev.on("messages.upsert",t=>{if(t.type==="notify"){for(let r of t.messages)if(r.message)try{let n=em(r,this.accountId);this.eventBus.emit("message:received",n)}catch{}}}),this.socket.ev.on("presence.update",t=>{try{let r=t.id,n=Object.keys(t.presences);if(n.length>0){let i=n[0],o=t.presences[i];o&&this.eventBus.emit("chat:typing",{conversationId:r,senderId:i,isTyping:o.lastKnownPresence==="composing"})}}catch{}}),this.socket.ev.on("messaging-history.set",t=>{let{chats:r,contacts:n,messages:i}=t;if(r)for(let o of r)o.id&&this.chatsMap.set(o.id,o);if(n)for(let o of n)o.id&&this.contactsMap.set(o.id,o);if(i){for(let o of i)if(o.message)try{let s=em(o,this.accountId);this.eventBus.emit("message:received",s)}catch{}}}),this.socket.ev.on("chats.upsert",t=>{for(let r of t)r.id&&this.chatsMap.set(r.id,r)}),this.socket.ev.on("chats.update",t=>{for(let r of t)if(r.id&&this.chatsMap.has(r.id)){let n=this.chatsMap.get(r.id);this.chatsMap.set(r.id,{...n,...r})}}),this.socket.ev.on("contacts.upsert",t=>{for(let r of t)r.id&&this.contactsMap.set(r.id,r)}),this.socket.ev.on("contacts.update",t=>{for(let r of t)if(r.id&&this.contactsMap.has(r.id)){let n=this.contactsMap.get(r.id);this.contactsMap.set(r.id,{...n,...r})}}))}createProxyAgent(t){try{return t.startsWith("socks")?new _$.SocksProxyAgent(t):t.startsWith("https")?new k$.HttpsProxyAgent(t):new S$.HttpProxyAgent(t)}catch{return}}}});var C$={};qi(C$,{WhatsAppChannelRunner:()=>_w});var du,_w,R$=F(()=>{"use strict";du=le(nt()),_w=class{constructor(t,r,n,i){this.accountId=t;this.sessionData=r;this.proxyData=n;this.logger=i||(0,du.createLogger)(`WhatsAppRunner:${t}`)}platform="whatsapp";status="offline";logger;messageHandler;adapter;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 WhatsApp runner for account ${this.accountId}${t}...`);let r=this.sessionData;if(this.sessionData?.encryptedSession?r=du.CloudCrypto.parseCloudSession(this.sessionData.encryptedSession):typeof this.sessionData=="string"&&(r=du.CloudCrypto.parseCloudSession(this.sessionData)),!!(r?.sessionPath||r?.creds||r?.keys||r?.authSession))try{let{WhatsAppAdapter:i}=await Promise.resolve().then(()=>(A$(),E$));this.adapter=new i(this.accountId),this.adapter.eventBus.on("message:received",s=>{this.receiveIncomingMessage(s)});let o;if(this.proxyData?.host&&this.proxyData?.port){let s=this.proxyData.username&&this.proxyData.password?`${this.proxyData.username}:${this.proxyData.password}@`:"";o=`${this.proxyData.protocol||"http"}://${s}${this.proxyData.host}:${this.proxyData.port}`}await this.adapter.initialize({accountId:this.accountId,platform:"whatsapp",status:"connecting",authData:{sessionPath:r.sessionPath,creds:r.creds,keys:r.keys},proxy:o}),this.logger.info(`Headless WhatsApp socket connected & listening for ${this.accountId}`)}catch(i){this.logger.warn(`Could not initialize live WhatsApp client: ${i?.message}. Runner active in standby mode.`)}else this.logger.debug("No direct WhatsApp credentials/session provided. Running in standby mode.");this.status="active"}async stop(){if(this.logger.info(`Stopping headless WhatsApp runner for account ${this.accountId}...`),this.adapter)try{await this.adapter.disconnect()}catch(t){this.logger.debug(`Error disconnecting WhatsApp adapter for ${this.accountId}:`,t?.message)}this.status="offline"}getStatus(){return this.status}async sendMessage(t){if(this.adapter&&this.status==="active")try{return await this.adapter.sendMessage(t.threadId||t.conversationId,{type:t.messageType==="image"?"image":"text",text:t.content}),!0}catch(r){return this.logger.warn(`Failed to send WhatsApp message via adapter for ${this.accountId}:`,r?.message),!1}return this.logger.info(`Headless WhatsApp runner sending message ${t.id} to thread ${t.threadId}`),!0}receiveIncomingMessage(t){this.status==="active"&&(this.logger.info(`\u{1F4E9} [WhatsAppRunner:${this.accountId}] Received message ${t.id} from sender ${t.senderName||t.senderId}: "${(t.content||"").slice(0,60)}"`),this.messageHandler?.(t))}}});var Wt=le(require("fs")),oi=le(require("path")),mt=le(require("os")),K$=le(require("readline")),vt=require("child_process");var pi=le(require("os")),Hi=le(require("fs")),dc=le(require("path")),k_=le(require("crypto"));function OM(){return"1.0.34"}var Hr=OM();function Wu(){return{totalMemMb:Math.round(pi.default.totalmem()/(1024*1024)),freeMemMb:Math.round(pi.default.freemem()/(1024*1024)),cpuCount:pi.default.cpus()?.length||1,platform:pi.default.platform()}}function FM(e){try{let t=dc.default.join(pi.default.homedir(),".zplus");Hi.default.existsSync(t)||Hi.default.mkdirSync(t,{recursive:!0});let r=e?`_slot_${e.replace(/[^a-zA-Z0-9_-]/g,"")}`:"",n=dc.default.join(t,`worker_identity${r}.json`);if(Hi.default.existsSync(n)){let p=JSON.parse(Hi.default.readFileSync(n,"utf-8"));if(p&&p.workerId)return{workerId:p.workerId,workerName:p.workerName||p.workerId}}let o=(pi.default.hostname()||"node").replace(/[^a-zA-Z0-9_-]/g,"_").toLowerCase().slice(0,14),s=k_.default.randomBytes(2).toString("hex"),a=`worker_${o}${r}_${s}`,c=e?` #${e}`:"",u=`Worker ${o.toUpperCase()}${c}`,l={workerId:a,workerName:u,slot:e||"default",createdAt:new Date().toISOString()};return Hi.default.writeFileSync(n,JSON.stringify(l,null,2),"utf-8"),l}catch{let t=e?`_slot_${e}`:"",r=`worker_${pi.default.hostname().replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,14)||"node"}${t}`;return{workerId:r,workerName:r}}}var Hu=class{static loadFromEnv(t=process.argv.slice(2)){let r=z=>{for(let C of t){if(C.startsWith(`--${z}=`))return C.split("=").slice(1).join("=");if(C===`--${z}`&&t[t.indexOf(C)+1])return t[t.indexOf(C)+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,o=r("jwt")||process.env.CLOUD_JWT||process.env.APPWRITE_JWT||process.env.JWT,s=r("secret")||process.env.DESKTOP_SECRET,a=r("team-id")||process.env.TEAM_ID||"default",c=t.includes("--enable-http")||r("enable-http")==="true"||process.env.ENABLE_HTTP==="true"||!1,u=r("port")||process.env.PORT,l=u?Number(u):c?8080:void 0,p=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",g=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(pi.default.totalmem()/(1024*1024*1024))),_=Math.min(200,Math.max(20,w*25)),m=r("max-capacity")||process.env.MAX_CAPACITY,v=Number(m||_),x=r("slot")||process.env.WORKER_SLOT||process.env.pm_id||process.env.NODE_APP_INSTANCE,y=FM(x),S=r("worker-id")||process.env.WORKER_ID||y.workerId,k=r("worker-name")||process.env.WORKER_NAME||process.env.HOSTNAME||y.workerName,T=r("user-id")||process.env.USER_ID||process.env.SOFTTY_USER_ID;return{workerId:S,version:Hr,enableHttp:c,port:l,userId:T,teamId:a,workerName:k,maxCapacity:v,recommendedCapacity:_,clusterPollIntervalMs:Number(r("poll-interval")||process.env.CLUSTER_POLL_INTERVAL_MS||5e3),cloudProvider:n,cloudEndpoint:p,cloudProjectId:d,cloudSessionToken:i,cloudJwt:o,cloudDatabaseId:h,appwriteEndpoint:p,appwriteProjectId:d,appwriteSessionToken:i,appwriteJwt:o,storageBucketId:g,desktopSecret:s,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 wo=le(require("fs")),Ew=le(require("os")),ks=le(require("path")),V$=le(require("crypto")),J$=le(nt());var O_=le(nt()),Zu=class{runners=new Map;logger;constructor(t){this.logger=t||(0,O_.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(o=>{this.logger.error(`Error stopping runner ${n} during unregister`,o)}),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()}};var F_=le(nt()),Ku=class{constructor(t=6e4,r,n){this.defaultTtlMs=t;this.logger=r||(0,F_.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(),o=this.locks.get(t);return o&&o.expiresAt>i&&o.ownerId!==r?(this.logger.warn(`Lock denied for account ${t}: currently held by ${o.ownerId} (expires in ${o.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(s=>{try{return Promise.resolve(s(t,r))}catch(a){return this.logger.error(`Error in preempt callback for ${t}:`,a),Promise.resolve()}});await Promise.race([Promise.all(i),new Promise(s=>setTimeout(s,1e3))]);let o=Date.now();return this.locks.set(t,{accountId:t,ownerId:r,acquiredAt:o,expiresAt:o+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 $s=le(require("fs")),D_=le(require("path")),B_=le(nt()),Yu=class{logger;queue=[];maxCapacity;persistenceFilePath;constructor(t=1e4,r,n){this.maxCapacity=t,this.logger=r||(0,B_.createLogger)("CloudPendingMessageQueue"),this.persistenceFilePath=n,this.loadFromDisk()}loadFromDisk(){if(this.persistenceFilePath)try{if($s.default.existsSync(this.persistenceFilePath)){let t=$s.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=D_.default.dirname(this.persistenceFilePath);$s.default.existsSync(t)||$s.default.mkdirSync(t,{recursive:!0}),$s.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,o=n.timestamp>=r;return i&&o})}purgeSynced(t,r){let n=this.queue.length,i=[];for(let s=0;s<this.queue.length;s++){let a=this.queue[s];a.timestamp<=t&&(!r||a.accountId===r)&&i.push(s)}for(let s=i.length-1;s>=0;s--)this.queue.splice(i[s],1);let o=n-this.queue.length;return o>0&&(this.saveToDisk(),this.logger.info(`Purged ${o} synced delta messages from queue.`)),o}getCount(){return this.queue.length}clear(){this.queue.length=0,this.saveToDisk()}};var L_=le(nt()),Xu=class{logger;campaigns=new Map;rules=new Map;threadHistory=new Map;lastReplyTimes=new Map;aiConfig={enabled:!1};constructor(t,r){this.logger=t||(0,L_.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 o=t.content.trim(),s=this.getThreadHistory(r);if(s.push({role:"user",content:o,timestamp:n}),s.length>6&&s.splice(0,s.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 a=t.accountId,c=this.aiConfig.accountBotConfigs,u=a&&c?c[a]:void 0;if(!u||!u.isBotEnabled)return this.logger.debug(`[HeadlessAutomation] Account [${a||"unknown"}] has not been configured or enabled for Bot AI by user in Chatbot settings. Message saved, no auto-reply sent.`),null;let l=t,p=!!l.isGroup||!!l.groupId||typeof t.threadId=="string"&&t.threadId.startsWith("g")||typeof t.conversationId=="string"&&t.conversationId.startsWith("g"),d=u.replyTarget||"all";if(d==="individual"&&p)return this.logger.debug(`[HeadlessAutomation] Account [${a}] configured for individual chat only. Skipping group message ${r}.`),null;if(d==="group"&&!p)return this.logger.debug(`[HeadlessAutomation] Account [${a}] configured for group chat only. Skipping direct message ${r}.`),null;let h=u.scheduleType||"always";if(h!=="always"){let S=new Date().getHours(),k=u.scheduleStartHour??8,T=u.scheduleEndHour??18;if(h==="working_hours"){if(S<k||S>=T)return this.logger.debug(`[HeadlessAutomation] Outside working hours (${S}h, allowed: ${k}h-${T}h). Skipping reply.`),null}else if(h==="outside_hours"&&S>=k&&S<T)return this.logger.debug(`[HeadlessAutomation] Inside working hours (${S}h, allowed outside: ${k}h-${T}h). Skipping reply.`),null}let g=u.excludeContactIds||[];if(!p&&g.length>0){let S=String(t.senderId||"");if(g.includes(S))return this.logger.debug(`[HeadlessAutomation] Sender ${S} is in contact blacklist. Skipping reply.`),null}if(p){let S=String(l.groupId||l.threadId||r||""),k=u.excludeGroupIds||[],T=u.includeGroupIds||[];if(k.length>0&&k.includes(S))return this.logger.debug(`[HeadlessAutomation] Group ${S} is in group blacklist. Skipping reply.`),null;if(T.length>0&&!T.includes(S))return this.logger.debug(`[HeadlessAutomation] Group ${S} is not in group whitelist. Skipping reply.`),null}let w=u.excludeKeywords||[],_=u.includeKeywords||[],m=o.toLowerCase();if(w.length>0&&w.some(k=>{let T=k.trim().toLowerCase();return T.length>0&&m.includes(T)}))return this.logger.debug("[HeadlessAutomation] Message contains blacklisted keyword. Skipping reply."),null;if(_.length>0&&!_.some(k=>{let T=k.trim().toLowerCase();return T.length>0&&m.includes(T)}))return this.logger.debug("[HeadlessAutomation] Message does not match any whitelist keyword. Skipping reply."),null;let v=u.systemPrompt&&u.systemPrompt.trim()?u.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 x=this.aiConfig.provider,y=this.aiConfig.apiKey;if(y||(x==="openai"?y=process.env.OPENAI_API_KEY:x==="deepseek"?y=process.env.DEEPSEEK_API_KEY:x==="anthropic"?y=process.env.ANTHROPIC_API_KEY:x==="custom"?y=process.env.CUSTOM_AI_API_KEY:x==="gemini"&&(y=process.env.GEMINI_API_KEY||process.env.GOOGLE_API_KEY)),!y&&x!=="custom")return this.logger.debug(`[HeadlessAutomation] No API key found for provider [${x}]. No auto-reply sent.`),null;try{let S=null;if(x==="openai"||x==="custom"||x==="deepseek")S=await this.callOpenAiCompatible(o,s,y||"",v);else if(x==="anthropic")S=await this.callAnthropic(o,s,y||"",v);else if(x==="gemini")S=await this.callGemini(o,s,y||"",v);else return this.logger.warn(`[HeadlessAutomation] Unsupported AI provider [${x}]. No reply generated.`),null;if(S&&S.trim().length>0){let k=S.trim();return s.push({role:"model",content:k,timestamp:Date.now()}),this.lastReplyTimes.set(r,Date.now()),k}}catch(S){this.logger.warn(`[HeadlessAutomation] AI generation error with provider [${x}] (${S?.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 s=`https://generativelanguage.googleapis.com/v1beta/models/${this.aiConfig.model||"gemini-2.0-flash"}:generateContent?key=${n}`,a=r.map(d=>({role:d.role==="model"?"model":"user",parts:[{text:d.content}]}));(a.length===0||a[a.length-1].parts[0]?.text!==t)&&a.push({role:"user",parts:[{text:t}]});let c={contents:a,generationConfig:{temperature:this.aiConfig.temperature??.7,maxOutputTokens:this.aiConfig.maxTokens??300}},u=i||this.aiConfig.systemPrompt;u&&u.trim()&&(c.systemInstruction={parts:[{text:u.trim()}]});let l=new AbortController,p=setTimeout(()=>l.abort(),7e3);try{let d=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(c),signal:l.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(p)}}async callOpenAiCompatible(t,r,n,i){let o=(this.aiConfig.baseUrl||(this.aiConfig.provider==="deepseek"?"https://api.deepseek.com/v1":"https://api.openai.com/v1")).replace(/\/+$/,"");o.includes("api.deepseek.com")&&!o.endsWith("/v1")?o+="/v1":(o.includes("11434")||o.includes("ollama"))&&(o=o.replace(/\/api$/,"").replace(/\/+$/,""),o.endsWith("/v1")||(o+="/v1"));let s=`${o}/chat/completions`,a=this.aiConfig.model||(this.aiConfig.provider==="deepseek"?"deepseek-chat":this.aiConfig.provider==="openai"?"gpt-4o-mini":"deepseek-chat"),c=i||this.aiConfig.systemPrompt,u=[...c&&c.trim()?[{role:"system",content:c.trim()}]:[],...r.map(h=>({role:h.role==="model"?"assistant":"user",content:h.content}))],l={"Content-Type":"application/json"};n&&(l.Authorization=`Bearer ${n}`);let p=new AbortController,d=setTimeout(()=>p.abort(),8e3);try{let h=await fetch(s,{method:"POST",headers:l,body:JSON.stringify({model:a,messages:u,temperature:this.aiConfig.temperature??.7,max_tokens:this.aiConfig.maxTokens??300}),signal:p.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 o="https://api.anthropic.com/v1/messages",s=this.aiConfig.model||"claude-3-5-haiku-20241022",a=r.map(l=>({role:l.role==="model"?"assistant":"user",content:l.content}));(a.length===0||a[a.length-1].content!==t)&&a.push({role:"user",content:t});let c=new AbortController,u=setTimeout(()=>c.abort(),8e3);try{let l=i||this.aiConfig.systemPrompt,p={model:s,messages:a,max_tokens:this.aiConfig.maxTokens??300,temperature:this.aiConfig.temperature??.7};l&&l.trim()&&(p.system=l.trim());let d=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":n,"anthropic-version":"2023-06-01"},body:JSON.stringify(p),signal:c.signal});if(!d.ok){let g=await d.text();return this.logger.warn(`[HeadlessAutomation] Anthropic API returned status ${d.status}: ${g.slice(0,200)}`),null}return(await d.json())?.content?.[0]?.text||null}finally{clearTimeout(u)}}clear(){this.campaigns.clear(),this.rules.clear(),this.threadHistory.clear(),this.lastReplyTimes.clear()}};var N_=le(nt()),Qu=class{logger;constructor(t){this.logger=t||(0,N_.createLogger)("PushNotificationDispatcher")}async dispatchMessageAlert(t,r){let n=`${r.senderName} (${r.platform.toUpperCase()})`,i=r.content||"New multimedia message received";return this.sendNotification({recipientToken:t,title:n,body:i,data:{messageId:r.id,threadId:r.threadId,platform:r.platform,accountId:r.accountId}})}async sendNotification(t){return this.logger.debug(`Dispatching push notification to device token: ${t.recipientToken.slice(0,8)}...`),!0}};var I$=le(require("http")),P$=require("url"),O$=le(nt());var T$=le(nt()),Ya=class{static logger=(0,T$.createLogger)("ChannelRunnerFactory");static async createRunner(t,r,n,i){let o=(t||"zalo").toLowerCase(),s=o==="web"||o.includes("zalo")?"zalo":o;try{if(s==="zalo"){let{ZaloChannelRunner:a}=await Promise.resolve().then(()=>(TL(),RL));return new a(r,n,i)}if(s==="facebook"){let{FacebookChannelRunner:a}=await Promise.resolve().then(()=>(p6(),u6));return new a(r,n,i)}if(s==="telegram"){let{TelegramChannelRunner:a}=await Promise.resolve().then(()=>(g6(),m6));return new a(r,n,i)}if(s==="whatsapp"){let{WhatsAppChannelRunner:a}=await Promise.resolve().then(()=>(R$(),C$));return new a(r,n,i)}return this.logger.warn(`Unsupported platform for ChannelRunner: ${t}`),null}catch(a){return this.logger.error(`Failed to dynamically initialize runner for ${s}:${r}:`,a?.message||a),null}}};var tm=class{constructor(t,r,n,i,o){this.port=t;this.engine=r;this.lockManager=n;this.deltaQueue=i;this.logger=o||(0,O$.createLogger)("WorkerHttpServer")}logger;server=null;async start(){if(!this.server)return new Promise((t,r)=>{this.server=I$.default.createServer((n,i)=>{this.handleRequest(n,i).catch(o=>{this.logger.error("Unhandled HTTP error:",o),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 P$.URL(t.url||"/",`http://${t.headers.host||"localhost"}`),i=n.pathname,o=(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"),o==="OPTIONS"){r.writeHead(204),r.end();return}if(o==="GET"&&i==="/health"){let s=this.engine.getMetrics();r.writeHead(200,{"Content-Type":"application/json"}),r.end(JSON.stringify({status:"healthy",timestamp:Date.now(),pendingDeltaMessages:this.deltaQueue.getCount(),metrics:s}));return}if(i.startsWith("/api/v1/")){let s=this.engine.config.desktopSecret;if(s){let a=t.headers["x-desktop-secret"]||t.headers.authorization;if((typeof a=="string"&&a.startsWith("Bearer ")?a.slice(7):a)!==s){r.writeHead(401,{"Content-Type":"application/json"}),r.end(JSON.stringify({error:"Unauthorized: Invalid or missing X-Desktop-Secret"}));return}}}if(o==="POST"&&i==="/api/v1/sentinel/handover"){let s=await this.readJsonBody(t),{deviceId:a,sessions:c,aiConfig:u}=s||{};if(u&&(this.engine.automationEngine.configure(u),this.logger.info(`[Handover] Configured 24/7 AI automation engine with provider: ${u.provider||"gemini"}, model: ${u.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 ${a||"unknown"} with ${c.length} sessions.`);let l=0;for(let p of c){if(!p.id||!p.nightWorkerEnabled)continue;if(!this.lockManager.acquireLock(p.id,`worker_${p.id}`)){this.logger.warn(`Skipping account ${p.id} because lock was not acquired.`);continue}let h=(p.platform||"zalo").toLowerCase(),g=h==="web"||h.includes("zalo")?"zalo":h,w=await Ya.createRunner(g,p.id,p.sessionData);w&&(this.engine.registerRunner(w),await w.start(),this.engine.registerAccount({id:p.id,platform:g,accountName:p.accountName||p.id,status:"active",nightWorkerEnabled:!0}),l++)}r.writeHead(200,{"Content-Type":"application/json"}),r.end(JSON.stringify({success:!0,message:"Sessions handed over successfully",activatedCount:l,timestamp:Date.now()}));return}if(o==="POST"&&i==="/api/v1/sentinel/reclaim"){let s=await this.readJsonBody(t),{deviceId:a}=s||{};this.logger.info(`[Reclaim] Master device ${a||"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(o==="POST"){let s=await this.readJsonBody(t);s&&(this.engine.automationEngine.configure(s),this.logger.info(`[NightConfig] Updated 24/7 AI config dynamically: provider=${s.provider||"gemini"}, model=${s.model||"default"}`)),r.writeHead(200,{"Content-Type":"application/json"}),r.end(JSON.stringify({success:!0,config:this.engine.automationEngine.getAiConfig()}));return}else if(o==="GET"){r.writeHead(200,{"Content-Type":"application/json"}),r.end(JSON.stringify({success:!0,config:this.engine.automationEngine.getAiConfig()}));return}}if(o==="GET"&&i==="/api/v1/sync/delta"){let s=n.searchParams.get("accountId")||void 0,a=parseInt(n.searchParams.get("since")||"0",10),c=this.deltaQueue.getDeltas(s,a);this.logger.info(`[DeltaSync] Serving ${c.length} night messages (since: ${a}, account: ${s||"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 ec=le(nt());var Xa=require("child_process"),F$=le(nt()),rm=class e{logger;timer;isUpdating=!1;constructor(t){this.logger=t||(0,F$.createLogger)("WorkerAutoUpdater")}static isNewerVersion(t,r){let n=l=>l.replace(/^v/,"").trim().split(".").map(p=>parseInt(p,10)||0),[i=0,o=0,s=0]=n(t),[a=0,c=0,u=0]=n(r);return i>a||i===a&&o>c||i===a&&o===c&&s>u}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 o=await i.json();if(o?.version)return String(o.version).trim()}}catch{}try{return(0,Xa.execSync)(`npm view ${t} version`,{encoding:"utf-8",timeout:8e3,stdio:["ignore","pipe","ignore"]}).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?`@softtynet/zplus-worker@${t}`:"@softtynet/zplus-worker@latest";this.logger.info(`\u{1F680} [AutoUpdater] B\u1EAFt \u0111\u1EA7u t\u1EF1 \u0111\u1ED9ng n\xE2ng c\u1EA5p Worker l\xEAn ${r}...`);try{return(0,Xa.execSync)(`npm install -g ${r}`,{stdio:"inherit",timeout:12e4}),this.logger.info(`\u2705 [AutoUpdater] \u0110\xE3 c\xE0i \u0111\u1EB7t th\xE0nh c\xF4ng ${r}!`),this.triggerRestart(),!0}catch(n){return this.isUpdating=!1,this.logger.error(`\u274C [AutoUpdater] N\xE2ng c\u1EA5p th\u1EA5t b\u1EA1i: ${n?.message||n}`),!1}}triggerRestart(){try{if((0,Xa.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'..."),(0,Xa.spawn)("pm2",["restart","zplus-worker"],{detached:!0,stdio:"ignore"}).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), 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 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 (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: 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 Di=le(require("fs")),nm=le(require("path")),D$=le(require("os")),B$=le(require("readline")),im=le(nt()),Qa=class{logger;constructor(t){this.logger=t||(0,im.createLogger)("WorkerAuthManager")}getAuthFilePath(){let t=process.env.DATA_DIR||nm.default.join(D$.default.homedir(),".zplus");return nm.default.join(t,"worker_auth.json")}loadStoredAuth(){try{let t=this.getAuthFilePath();if(!Di.default.existsSync(t))return null;let r=Di.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=nm.default.dirname(r);Di.default.existsSync(n)||Di.default.mkdirSync(n,{recursive:!0,mode:448}),Di.default.writeFileSync(r,JSON.stringify(t,null,2),{encoding:"utf-8",mode:384});try{Di.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(){try{let t=this.getAuthFilePath();Di.default.existsSync(t)&&Di.default.unlinkSync(t),this.logger.info("\u0110\xE3 x\xF3a phi\xEAn \u0111\u0103ng nh\u1EADp c\u1EE7a Worker.")}catch(t){this.logger.debug("clearAuth error:",t?.message)}}async verifyEntitlements(t,r="https://api.softty.net/v1",n="699cfc3100136099c1c1",i="default"){try{let o=`${r}/account`,s=t.includes(".")&&t.split(".").length===3,a={"Content-Type":"application/json","X-Appwrite-Project":n};s?a["X-Appwrite-JWT"]=t:(a["X-Appwrite-Session"]=t,a.Cookie=`a_session_${n}=${t}; a_session_${n}_legacy=${t}`,t.startsWith("eyJ")&&(a["X-Fallback-Cookies"]=JSON.stringify({[`a_session_${n}`]:t,[`a_session_${n}_legacy`]:t})));let c=await fetch(o,{method:"GET",headers:a});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 u=await c.json(),l=u.$id||u.id||"",p=u.name||"Ng\u01B0\u1EDDi d\xF9ng ZPlus",d=u.email||"",h=Array.isArray(u.labels)?u.labels:[],g=u.prefs||{},_=!h.some(y=>y.toLowerCase()==="member")&&g.isOwner!==!1,m=h.some(y=>y.toLowerCase()==="free")||g.tier==="free",v=!m&&(g.isPremium===!0||h.some(y=>y.toLowerCase()==="premium"||y.toLowerCase()==="enterprise")),x=g.teamId||g.storage?.teamId||u.teamId||i;if((!x||x==="default")&&g.entitlements)try{let y=typeof g.entitlements=="string"?JSON.parse(g.entitlements):g.entitlements;y?.storage?.teamId&&(x=y.storage.teamId)}catch{}if((!x||x==="default")&&u.entitlements)try{let y=typeof u.entitlements=="string"?JSON.parse(u.entitlements):u.entitlements;y?.storage?.teamId&&(x=y.storage.teamId)}catch{}if(!x||x==="default")try{let y=await fetch(`${r}/teams`,{method:"GET",headers:a});if(y.ok){let S=await y.json().catch(()=>({})),k=Array.isArray(S.teams)?S.teams:[];k.length>0&&k[0].$id&&(x=k[0].$id)}}catch{}return m?{allowed:!1,userId:l,userName:p,email:d,teamId:x,isOwner:_,isPremium:!1,reason:`\u26A0\uFE0F T\xE0i kho\u1EA3n [${d}] \u0111ang \u1EDF G\xF3i Mi\u1EC5n Ph\xED (Free Tier). G\xF3i n\xE0y kh\xF4ng h\u1ED7 tr\u1EE3 c\u1EE5m Worker 24/7 (Y\xEAu c\u1EA7u g\xF3i Team Enterprise).`}:_?{allowed:!0,userId:l,userName:p,email:d,teamId:x,isOwner:!0,isPremium:!0,reason:`\u2705 X\xE1c th\u1EF1c th\xE0nh c\xF4ng: Tr\u01B0\u1EDFng nh\xF3m [${p}] (${d}) - G\xF3i Doanh Nghi\u1EC7p Active.`}:{allowed:!1,userId:l,userName:p,email:d,teamId:x,isOwner:!1,isPremium:v,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(o){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: ${o?.message}`}}}async loginWithCredentials(t,r,n="https://api.softty.net/v1",i="699cfc3100136099c1c1"){let o=t?.trim(),s=r;if(!o||!s){console.log(`
107
+ `),fe=yle.bind(null,{[s$]:"",[a$]:s,[l$]:V,[c$]:xw,[bw]:C,[u$]:N}),de="";p!==null&&(d===void 0?de=fe(p):de=fe(Object.assign({},p,{name:d})));let be=a instanceof Function?a:a?g$:Ule,xe=be().indexOf(":")+1;if(v&&!g)throw Error("customLevels is required if useOnlyCustomLevels is set true");if(_&&typeof _!="function")throw Error(`Unknown mixin type "${typeof _}" - expected "function"`);if(z&&typeof z!="string")throw Error(`Unknown msgPrefix type "${typeof z}" - expected "string"`);ple(h,g,v);let K=h$(g,v);typeof n.emit=="function"&&n.emit("message",{code:"PINO_CONFIG",config:{levels:K,messageKey:c,errorKey:u}}),hle(w);let ie=dle(w);return Object.assign(t,{levels:K,[Ole]:ie,[Fle]:v,[kle]:n,[_le]:be,[Sle]:xe,[c$]:xw,[bw]:C,[l$]:V,[Ale]:J,[Cle]:Q,[Rle]:c,[Tle]:u,[Ile]:l,[Ble]:l?`,${JSON.stringify(l)}:{`:"",[a$]:s,[Ple]:_,[Lle]:m,[s$]:de,[u$]:N,[Dle]:y,silent:ble,onChild:T,[Nle]:z}),Object.setPrototypeOf(t,lle()),fle(t),t[Ele](h),t}un.exports=vw;un.exports.destination=(e=process.stdout.fd)=>typeof e=="object"?(e.dest=o$(e.dest||process.stdout.fd),i$(e)):i$({dest:o$(e),minLength:0});un.exports.transport=rw();un.exports.multistream=n$();un.exports.levels=h$();un.exports.stdSerializers=Hle;un.exports.stdTimeFunctions=Object.assign({},f$);un.exports.symbols=d$;un.exports.version=vle;un.exports.default=vw;un.exports.pino=vw});function em(e,t){let r=e.key,n=e.message,i=r.remoteJid||"",o="";r.fromMe?o=t:o=r.participant||r.remoteJid||"";let s="",a="text",c="";n?n.conversation?(s=n.conversation,a="text"):n.extendedTextMessage?(s=n.extendedTextMessage.text||"",a="text"):n.imageMessage?(s=n.imageMessage.caption||"",a="image",c=n.imageMessage.url||""):n.videoMessage?(s=n.videoMessage.caption||"",a="video",c=n.videoMessage.url||""):n.audioMessage?(a="audio",c=n.audioMessage.url||""):n.documentMessage?(s=n.documentMessage.title||n.documentMessage.fileName||"",a="file",c=n.documentMessage.url||""):n.stickerMessage?(a="sticker",c=n.stickerMessage.url||""):n.protocolMessage||n.senderKeyDistributionMessage?(a="system",s="System message"):(a="other",s="[Tin nh\u1EAFn kh\xF4ng \u0111\u01B0\u1EE3c h\u1ED7 tr\u1EE3]"):(a="other",s="");let u={rawMsg:Wle(e)};if(e.pushName&&(u.pushName=e.pushName),n?.extendedTextMessage?.contextInfo?.quotedMessage){let p=n.extendedTextMessage.contextInfo;u.quotedMessage={participant:p.participant,stanzaId:p.stanzaId,text:p.quotedMessage?.conversation||p.quotedMessage?.extendedTextMessage?.text||""}}let l=e.messageTimestamp?Number(e.messageTimestamp)*1e3:Date.now();return{id:r.id||"",conversationId:i,senderId:o,senderName:e.pushName||void 0,text:s,type:a,mediaUrl:c,timestamp:l,platform:"whatsapp",isFromMe:!!r.fromMe,metadata:u}}function Wle(e){if(!e||typeof e!="object")return e;let t={};if(e.key&&(t.key={remoteJid:e.key.remoteJid,fromMe:e.key.fromMe,id:e.key.id,participant:e.key.participant}),e.pushName&&(t.pushName=e.pushName),e.messageTimestamp&&(t.messageTimestamp=e.messageTimestamp),e.status&&(t.status=e.status),e.message){let r=e.message;t.message={},r.conversation&&(t.message.conversation=r.conversation),r.extendedTextMessage&&(t.message.extendedTextMessage={text:r.extendedTextMessage.text},r.extendedTextMessage.contextInfo&&(t.message.extendedTextMessage.contextInfo={stanzaId:r.extendedTextMessage.contextInfo.stanzaId,participant:r.extendedTextMessage.contextInfo.participant})),r.imageMessage&&(t.message.imageMessage={caption:r.imageMessage.caption,mimetype:r.imageMessage.mimetype}),r.videoMessage&&(t.message.videoMessage={caption:r.videoMessage.caption,mimetype:r.videoMessage.mimetype}),r.audioMessage&&(t.message.audioMessage={mimetype:r.audioMessage.mimetype,seconds:r.audioMessage.seconds}),r.documentMessage&&(t.message.documentMessage={title:r.documentMessage.title,fileName:r.documentMessage.fileName,mimetype:r.documentMessage.mimetype}),r.stickerMessage&&(t.message.stickerMessage={mimetype:r.stickerMessage.mimetype})}return t}var x$=F(()=>{"use strict"});function fu(e,t){let r=String(e.id||e.jid||""),n=String(e.name||e.verifiedName||e.notify||"WhatsApp User"),i=String(e.imgUrl||e.avatar||"");return{id:r,name:n,avatarUrl:i||void 0,platform:"whatsapp",phoneNumber:t||e.phoneNumber||void 0,rawContact:e}}function b$(e){let t=String(e.id||e.jid||""),r=String(e.name||e.displayName||"WhatsApp Chat"),n=String(e.imgUrl||e.avatar||""),i="direct";return(t.endsWith("@g.us")||e.isGroup)&&(i="group"),{id:t,name:r,avatarUrl:n||void 0,type:i,unreadCount:Number(e.unreadCount||0),platform:"whatsapp",rawConversation:e}}var v$=F(()=>{"use strict"});var E$={};qi(E$,{WhatsAppAdapter:()=>ww});var vo,w$,_$,S$,k$,ww,A$=F(()=>{"use strict";vo=le(require("@whiskeysockets/baileys")),w$=le(y$()),_$=le(Rd()),S$=le(Id()),k$=le(Dd());kl();x$();v$();ww=class{accountId;platform="whatsapp";eventBus=new ei;status="disconnected";socket=null;session=null;isReconnecting=!1;chatsMap=new Map;contactsMap=new Map;constructor(t){this.accountId=t}async initialize(t){this.session=t,this.status="connecting",this.eventBus.emit("session:status_changed","connecting");let r=t.authData.sessionPath||`./sessions/whatsapp_${this.accountId}`;try{let{state:n,saveCreds:i}=await(0,vo.useMultiFileAuthState)(r),o=(0,w$.default)({level:"silent"}),s=[2,3e3,1023223821];try{let c=await(0,vo.fetchLatestBaileysVersion)();c&&c.version&&(s=c.version)}catch{}let a={version:s,auth:n,logger:o,printQRInTerminal:!1,defaultQueryTimeoutMs:3e4,connectTimeoutMs:3e4};if(t.proxy){let c=this.createProxyAgent(t.proxy);c&&(a.agent=c)}this.socket=(0,vo.default)(a),this.socket.ev.on("creds.update",i),this.setupListeners()}catch(n){throw this.status="disconnected",this.eventBus.emit("session:status_changed","disconnected",n.message||String(n)),n}}async disconnect(){if(this.isReconnecting=!1,this.socket){try{this.socket.end(void 0)}catch{}this.socket=null}this.status="disconnected",this.eventBus.emit("session:status_changed","disconnected")}async sendMessage(t,r){if(!this.socket)throw new Error("WhatsApp adapter not initialized");await this.sendTyping(t,!0);let n=Math.floor(Math.random()*2e3)+1500;await new Promise(s=>setTimeout(s,n)),await this.sendTyping(t,!1);let i={};if(r.type==="text")i={text:r.text};else if(r.type==="image")i={image:{url:r.url||r.filePath},caption:r.caption||""};else if(r.type==="sticker")i={sticker:{url:r.url||r.filePath||r.stickerId}};else if(r.type==="file")i={document:{url:r.url||r.filePath},fileName:r.filename||"file"};else throw new Error(`Unsupported message payload type: ${r.type}`);r.quoteId&&(i.contextInfo={stanzaId:r.quoteId,participant:t.endsWith("@g.us")?void 0:t,quotedMessage:{conversation:"[Tr\xEDch d\u1EABn tin nh\u1EAFn]"}});let o=await this.socket.sendMessage(t,i);if(!o)throw new Error("Failed to send WhatsApp message");return em(o,this.accountId)}async getConversations(t=20){let r=Array.from(this.chatsMap.values());return r.sort((n,i)=>Number(i.conversationTimestamp||0)-Number(n.conversationTimestamp||0)),r.slice(0,t).map(b$)}async getMessageHistory(t,r=50,n){return[]}async getCurrentUser(){if(!this.socket)return null;let t=this.socket.authState?.creds?.me||this.socket.user;if(!t)return null;let r=t.id;r.includes(":")&&(r=r.split(":")[0]+"@s.whatsapp.net");let n=t.name||this.socket.user?.name||"WhatsApp User",i="";try{i=await this.socket.profilePictureUrl(r,"image")||""}catch{}return fu({id:r,name:n,imgUrl:i},this.accountId)}async getContactInfo(t){if(this.contactsMap.has(t))return fu(this.contactsMap.get(t));if(!this.socket)throw new Error("WhatsApp adapter not initialized");try{let r=await this.socket.profilePictureUrl(t,"image");return fu({id:t,name:"WhatsApp User",imgUrl:r})}catch{return fu({id:t,name:"WhatsApp User"})}}async markAsRead(t){if(this.socket)try{await this.socket.sendPresenceUpdate("paused",t)}catch{}}async sendTyping(t,r){if(this.socket)try{await this.socket.sendPresenceUpdate(r?"composing":"paused",t)}catch{}}getUnderlyingClient(){return this.socket}setupListeners(){this.socket&&(this.socket.ev.on("connection.update",t=>{let{connection:r,lastDisconnect:n,qr:i}=t;i&&this.eventBus.emit("auth:qr_received",i),r==="connecting"&&(this.status="connecting",this.eventBus.emit("session:status_changed","connecting")),r==="open"&&(this.status="connected",this.eventBus.emit("session:status_changed","connected")),r==="close"&&(n?.error?.output?.statusCode!==vo.DisconnectReason.loggedOut&&this.session?(this.isReconnecting=!0,this.initialize(this.session)):(this.status="disconnected",this.eventBus.emit("session:status_changed","disconnected","Session logged out or expired")))}),this.socket.ev.on("messages.upsert",t=>{if(t.type==="notify"){for(let r of t.messages)if(r.message)try{let n=em(r,this.accountId);this.eventBus.emit("message:received",n)}catch{}}}),this.socket.ev.on("presence.update",t=>{try{let r=t.id,n=Object.keys(t.presences);if(n.length>0){let i=n[0],o=t.presences[i];o&&this.eventBus.emit("chat:typing",{conversationId:r,senderId:i,isTyping:o.lastKnownPresence==="composing"})}}catch{}}),this.socket.ev.on("messaging-history.set",t=>{let{chats:r,contacts:n,messages:i}=t;if(r)for(let o of r)o.id&&this.chatsMap.set(o.id,o);if(n)for(let o of n)o.id&&this.contactsMap.set(o.id,o);if(i){for(let o of i)if(o.message)try{let s=em(o,this.accountId);this.eventBus.emit("message:received",s)}catch{}}}),this.socket.ev.on("chats.upsert",t=>{for(let r of t)r.id&&this.chatsMap.set(r.id,r)}),this.socket.ev.on("chats.update",t=>{for(let r of t)if(r.id&&this.chatsMap.has(r.id)){let n=this.chatsMap.get(r.id);this.chatsMap.set(r.id,{...n,...r})}}),this.socket.ev.on("contacts.upsert",t=>{for(let r of t)r.id&&this.contactsMap.set(r.id,r)}),this.socket.ev.on("contacts.update",t=>{for(let r of t)if(r.id&&this.contactsMap.has(r.id)){let n=this.contactsMap.get(r.id);this.contactsMap.set(r.id,{...n,...r})}}))}createProxyAgent(t){try{return t.startsWith("socks")?new _$.SocksProxyAgent(t):t.startsWith("https")?new k$.HttpsProxyAgent(t):new S$.HttpProxyAgent(t)}catch{return}}}});var C$={};qi(C$,{WhatsAppChannelRunner:()=>_w});var du,_w,R$=F(()=>{"use strict";du=le(nt()),_w=class{constructor(t,r,n,i){this.accountId=t;this.sessionData=r;this.proxyData=n;this.logger=i||(0,du.createLogger)(`WhatsAppRunner:${t}`)}platform="whatsapp";status="offline";logger;messageHandler;adapter;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 WhatsApp runner for account ${this.accountId}${t}...`);let r=this.sessionData;if(this.sessionData?.encryptedSession?r=du.CloudCrypto.parseCloudSession(this.sessionData.encryptedSession):typeof this.sessionData=="string"&&(r=du.CloudCrypto.parseCloudSession(this.sessionData)),!!(r?.sessionPath||r?.creds||r?.keys||r?.authSession))try{let{WhatsAppAdapter:i}=await Promise.resolve().then(()=>(A$(),E$));this.adapter=new i(this.accountId),this.adapter.eventBus.on("message:received",s=>{this.receiveIncomingMessage(s)});let o;if(this.proxyData?.host&&this.proxyData?.port){let s=this.proxyData.username&&this.proxyData.password?`${this.proxyData.username}:${this.proxyData.password}@`:"";o=`${this.proxyData.protocol||"http"}://${s}${this.proxyData.host}:${this.proxyData.port}`}await this.adapter.initialize({accountId:this.accountId,platform:"whatsapp",status:"connecting",authData:{sessionPath:r.sessionPath,creds:r.creds,keys:r.keys},proxy:o}),this.logger.info(`Headless WhatsApp socket connected & listening for ${this.accountId}`)}catch(i){this.logger.warn(`Could not initialize live WhatsApp client: ${i?.message}. Runner active in standby mode.`)}else this.logger.debug("No direct WhatsApp credentials/session provided. Running in standby mode.");this.status="active"}async stop(){if(this.logger.info(`Stopping headless WhatsApp runner for account ${this.accountId}...`),this.adapter)try{await this.adapter.disconnect()}catch(t){this.logger.debug(`Error disconnecting WhatsApp adapter for ${this.accountId}:`,t?.message)}this.status="offline"}getStatus(){return this.status}async sendMessage(t){if(this.adapter&&this.status==="active")try{return await this.adapter.sendMessage(t.threadId||t.conversationId,{type:t.messageType==="image"?"image":"text",text:t.content}),!0}catch(r){return this.logger.warn(`Failed to send WhatsApp message via adapter for ${this.accountId}:`,r?.message),!1}return this.logger.info(`Headless WhatsApp runner sending message ${t.id} to thread ${t.threadId}`),!0}receiveIncomingMessage(t){this.status==="active"&&(this.logger.info(`\u{1F4E9} [WhatsAppRunner:${this.accountId}] Received message ${t.id} from sender ${t.senderName||t.senderId}: "${(t.content||"").slice(0,60)}"`),this.messageHandler?.(t))}}});var Wt=le(require("fs")),oi=le(require("path")),mt=le(require("os")),K$=le(require("readline")),vt=require("child_process");var pi=le(require("os")),Hi=le(require("fs")),dc=le(require("path")),k_=le(require("crypto"));function OM(){return"1.0.36"}var Hr=OM();function Wu(){return{totalMemMb:Math.round(pi.default.totalmem()/(1024*1024)),freeMemMb:Math.round(pi.default.freemem()/(1024*1024)),cpuCount:pi.default.cpus()?.length||1,platform:pi.default.platform()}}function FM(e){try{let t=dc.default.join(pi.default.homedir(),".zplus");Hi.default.existsSync(t)||Hi.default.mkdirSync(t,{recursive:!0});let r=e?`_slot_${e.replace(/[^a-zA-Z0-9_-]/g,"")}`:"",n=dc.default.join(t,`worker_identity${r}.json`);if(Hi.default.existsSync(n)){let p=JSON.parse(Hi.default.readFileSync(n,"utf-8"));if(p&&p.workerId)return{workerId:p.workerId,workerName:p.workerName||p.workerId}}let o=(pi.default.hostname()||"node").replace(/[^a-zA-Z0-9_-]/g,"_").toLowerCase().slice(0,14),s=k_.default.randomBytes(2).toString("hex"),a=`worker_${o}${r}_${s}`,c=e?` #${e}`:"",u=`Worker ${o.toUpperCase()}${c}`,l={workerId:a,workerName:u,slot:e||"default",createdAt:new Date().toISOString()};return Hi.default.writeFileSync(n,JSON.stringify(l,null,2),"utf-8"),l}catch{let t=e?`_slot_${e}`:"",r=`worker_${pi.default.hostname().replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,14)||"node"}${t}`;return{workerId:r,workerName:r}}}var Hu=class{static loadFromEnv(t=process.argv.slice(2)){let r=z=>{for(let C of t){if(C.startsWith(`--${z}=`))return C.split("=").slice(1).join("=");if(C===`--${z}`&&t[t.indexOf(C)+1])return t[t.indexOf(C)+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,o=r("jwt")||process.env.CLOUD_JWT||process.env.APPWRITE_JWT||process.env.JWT,s=r("secret")||process.env.DESKTOP_SECRET,a=r("team-id")||process.env.TEAM_ID||"default",c=t.includes("--enable-http")||r("enable-http")==="true"||process.env.ENABLE_HTTP==="true"||!1,u=r("port")||process.env.PORT,l=u?Number(u):c?8080:void 0,p=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",g=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(pi.default.totalmem()/(1024*1024*1024))),_=Math.min(200,Math.max(20,w*25)),m=r("max-capacity")||process.env.MAX_CAPACITY,v=Number(m||_),x=r("slot")||process.env.WORKER_SLOT||process.env.pm_id||process.env.NODE_APP_INSTANCE,y=FM(x),S=r("worker-id")||process.env.WORKER_ID||y.workerId,k=r("worker-name")||process.env.WORKER_NAME||process.env.HOSTNAME||y.workerName,T=r("user-id")||process.env.USER_ID||process.env.SOFTTY_USER_ID;return{workerId:S,version:Hr,enableHttp:c,port:l,userId:T,teamId:a,workerName:k,maxCapacity:v,recommendedCapacity:_,clusterPollIntervalMs:Number(r("poll-interval")||process.env.CLUSTER_POLL_INTERVAL_MS||5e3),cloudProvider:n,cloudEndpoint:p,cloudProjectId:d,cloudSessionToken:i,cloudJwt:o,cloudDatabaseId:h,appwriteEndpoint:p,appwriteProjectId:d,appwriteSessionToken:i,appwriteJwt:o,storageBucketId:g,desktopSecret:s,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 wo=le(require("fs")),Ew=le(require("os")),ks=le(require("path")),V$=le(require("crypto")),J$=le(nt());var O_=le(nt()),Zu=class{runners=new Map;logger;constructor(t){this.logger=t||(0,O_.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(o=>{this.logger.error(`Error stopping runner ${n} during unregister`,o)}),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()}};var F_=le(nt()),Ku=class{constructor(t=6e4,r,n){this.defaultTtlMs=t;this.logger=r||(0,F_.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(),o=this.locks.get(t);return o&&o.expiresAt>i&&o.ownerId!==r?(this.logger.warn(`Lock denied for account ${t}: currently held by ${o.ownerId} (expires in ${o.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(s=>{try{return Promise.resolve(s(t,r))}catch(a){return this.logger.error(`Error in preempt callback for ${t}:`,a),Promise.resolve()}});await Promise.race([Promise.all(i),new Promise(s=>setTimeout(s,1e3))]);let o=Date.now();return this.locks.set(t,{accountId:t,ownerId:r,acquiredAt:o,expiresAt:o+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 $s=le(require("fs")),D_=le(require("path")),B_=le(nt()),Yu=class{logger;queue=[];maxCapacity;persistenceFilePath;constructor(t=1e4,r,n){this.maxCapacity=t,this.logger=r||(0,B_.createLogger)("CloudPendingMessageQueue"),this.persistenceFilePath=n,this.loadFromDisk()}loadFromDisk(){if(this.persistenceFilePath)try{if($s.default.existsSync(this.persistenceFilePath)){let t=$s.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=D_.default.dirname(this.persistenceFilePath);$s.default.existsSync(t)||$s.default.mkdirSync(t,{recursive:!0}),$s.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,o=n.timestamp>=r;return i&&o})}purgeSynced(t,r){let n=this.queue.length,i=[];for(let s=0;s<this.queue.length;s++){let a=this.queue[s];a.timestamp<=t&&(!r||a.accountId===r)&&i.push(s)}for(let s=i.length-1;s>=0;s--)this.queue.splice(i[s],1);let o=n-this.queue.length;return o>0&&(this.saveToDisk(),this.logger.info(`Purged ${o} synced delta messages from queue.`)),o}getCount(){return this.queue.length}clear(){this.queue.length=0,this.saveToDisk()}};var L_=le(nt()),Xu=class{logger;campaigns=new Map;rules=new Map;threadHistory=new Map;lastReplyTimes=new Map;aiConfig={enabled:!1};constructor(t,r){this.logger=t||(0,L_.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 o=t.content.trim(),s=this.getThreadHistory(r);if(s.push({role:"user",content:o,timestamp:n}),s.length>6&&s.splice(0,s.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 a=t.accountId,c=this.aiConfig.accountBotConfigs,u=a&&c?c[a]:void 0;if(!u||!u.isBotEnabled)return this.logger.debug(`[HeadlessAutomation] Account [${a||"unknown"}] has not been configured or enabled for Bot AI by user in Chatbot settings. Message saved, no auto-reply sent.`),null;let l=t,p=!!l.isGroup||!!l.groupId||typeof t.threadId=="string"&&t.threadId.startsWith("g")||typeof t.conversationId=="string"&&t.conversationId.startsWith("g"),d=u.replyTarget||"all";if(d==="individual"&&p)return this.logger.debug(`[HeadlessAutomation] Account [${a}] configured for individual chat only. Skipping group message ${r}.`),null;if(d==="group"&&!p)return this.logger.debug(`[HeadlessAutomation] Account [${a}] configured for group chat only. Skipping direct message ${r}.`),null;let h=u.scheduleType||"always";if(h!=="always"){let S=new Date().getHours(),k=u.scheduleStartHour??8,T=u.scheduleEndHour??18;if(h==="working_hours"){if(S<k||S>=T)return this.logger.debug(`[HeadlessAutomation] Outside working hours (${S}h, allowed: ${k}h-${T}h). Skipping reply.`),null}else if(h==="outside_hours"&&S>=k&&S<T)return this.logger.debug(`[HeadlessAutomation] Inside working hours (${S}h, allowed outside: ${k}h-${T}h). Skipping reply.`),null}let g=u.excludeContactIds||[];if(!p&&g.length>0){let S=String(t.senderId||"");if(g.includes(S))return this.logger.debug(`[HeadlessAutomation] Sender ${S} is in contact blacklist. Skipping reply.`),null}if(p){let S=String(l.groupId||l.threadId||r||""),k=u.excludeGroupIds||[],T=u.includeGroupIds||[];if(k.length>0&&k.includes(S))return this.logger.debug(`[HeadlessAutomation] Group ${S} is in group blacklist. Skipping reply.`),null;if(T.length>0&&!T.includes(S))return this.logger.debug(`[HeadlessAutomation] Group ${S} is not in group whitelist. Skipping reply.`),null}let w=u.excludeKeywords||[],_=u.includeKeywords||[],m=o.toLowerCase();if(w.length>0&&w.some(k=>{let T=k.trim().toLowerCase();return T.length>0&&m.includes(T)}))return this.logger.debug("[HeadlessAutomation] Message contains blacklisted keyword. Skipping reply."),null;if(_.length>0&&!_.some(k=>{let T=k.trim().toLowerCase();return T.length>0&&m.includes(T)}))return this.logger.debug("[HeadlessAutomation] Message does not match any whitelist keyword. Skipping reply."),null;let v=u.systemPrompt&&u.systemPrompt.trim()?u.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 x=this.aiConfig.provider,y=this.aiConfig.apiKey;if(y||(x==="openai"?y=process.env.OPENAI_API_KEY:x==="deepseek"?y=process.env.DEEPSEEK_API_KEY:x==="anthropic"?y=process.env.ANTHROPIC_API_KEY:x==="custom"?y=process.env.CUSTOM_AI_API_KEY:x==="gemini"&&(y=process.env.GEMINI_API_KEY||process.env.GOOGLE_API_KEY)),!y&&x!=="custom")return this.logger.debug(`[HeadlessAutomation] No API key found for provider [${x}]. No auto-reply sent.`),null;try{let S=null;if(x==="openai"||x==="custom"||x==="deepseek")S=await this.callOpenAiCompatible(o,s,y||"",v);else if(x==="anthropic")S=await this.callAnthropic(o,s,y||"",v);else if(x==="gemini")S=await this.callGemini(o,s,y||"",v);else return this.logger.warn(`[HeadlessAutomation] Unsupported AI provider [${x}]. No reply generated.`),null;if(S&&S.trim().length>0){let k=S.trim();return s.push({role:"model",content:k,timestamp:Date.now()}),this.lastReplyTimes.set(r,Date.now()),k}}catch(S){this.logger.warn(`[HeadlessAutomation] AI generation error with provider [${x}] (${S?.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 s=`https://generativelanguage.googleapis.com/v1beta/models/${this.aiConfig.model||"gemini-2.0-flash"}:generateContent?key=${n}`,a=r.map(d=>({role:d.role==="model"?"model":"user",parts:[{text:d.content}]}));(a.length===0||a[a.length-1].parts[0]?.text!==t)&&a.push({role:"user",parts:[{text:t}]});let c={contents:a,generationConfig:{temperature:this.aiConfig.temperature??.7,maxOutputTokens:this.aiConfig.maxTokens??300}},u=i||this.aiConfig.systemPrompt;u&&u.trim()&&(c.systemInstruction={parts:[{text:u.trim()}]});let l=new AbortController,p=setTimeout(()=>l.abort(),7e3);try{let d=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(c),signal:l.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(p)}}async callOpenAiCompatible(t,r,n,i){let o=(this.aiConfig.baseUrl||(this.aiConfig.provider==="deepseek"?"https://api.deepseek.com/v1":"https://api.openai.com/v1")).replace(/\/+$/,"");o.includes("api.deepseek.com")&&!o.endsWith("/v1")?o+="/v1":(o.includes("11434")||o.includes("ollama"))&&(o=o.replace(/\/api$/,"").replace(/\/+$/,""),o.endsWith("/v1")||(o+="/v1"));let s=`${o}/chat/completions`,a=this.aiConfig.model||(this.aiConfig.provider==="deepseek"?"deepseek-chat":this.aiConfig.provider==="openai"?"gpt-4o-mini":"deepseek-chat"),c=i||this.aiConfig.systemPrompt,u=[...c&&c.trim()?[{role:"system",content:c.trim()}]:[],...r.map(h=>({role:h.role==="model"?"assistant":"user",content:h.content}))],l={"Content-Type":"application/json"};n&&(l.Authorization=`Bearer ${n}`);let p=new AbortController,d=setTimeout(()=>p.abort(),8e3);try{let h=await fetch(s,{method:"POST",headers:l,body:JSON.stringify({model:a,messages:u,temperature:this.aiConfig.temperature??.7,max_tokens:this.aiConfig.maxTokens??300}),signal:p.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 o="https://api.anthropic.com/v1/messages",s=this.aiConfig.model||"claude-3-5-haiku-20241022",a=r.map(l=>({role:l.role==="model"?"assistant":"user",content:l.content}));(a.length===0||a[a.length-1].content!==t)&&a.push({role:"user",content:t});let c=new AbortController,u=setTimeout(()=>c.abort(),8e3);try{let l=i||this.aiConfig.systemPrompt,p={model:s,messages:a,max_tokens:this.aiConfig.maxTokens??300,temperature:this.aiConfig.temperature??.7};l&&l.trim()&&(p.system=l.trim());let d=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":n,"anthropic-version":"2023-06-01"},body:JSON.stringify(p),signal:c.signal});if(!d.ok){let g=await d.text();return this.logger.warn(`[HeadlessAutomation] Anthropic API returned status ${d.status}: ${g.slice(0,200)}`),null}return(await d.json())?.content?.[0]?.text||null}finally{clearTimeout(u)}}clear(){this.campaigns.clear(),this.rules.clear(),this.threadHistory.clear(),this.lastReplyTimes.clear()}};var N_=le(nt()),Qu=class{logger;constructor(t){this.logger=t||(0,N_.createLogger)("PushNotificationDispatcher")}async dispatchMessageAlert(t,r){let n=`${r.senderName} (${r.platform.toUpperCase()})`,i=r.content||"New multimedia message received";return this.sendNotification({recipientToken:t,title:n,body:i,data:{messageId:r.id,threadId:r.threadId,platform:r.platform,accountId:r.accountId}})}async sendNotification(t){return this.logger.debug(`Dispatching push notification to device token: ${t.recipientToken.slice(0,8)}...`),!0}};var I$=le(require("http")),P$=require("url"),O$=le(nt());var T$=le(nt()),Ya=class{static logger=(0,T$.createLogger)("ChannelRunnerFactory");static async createRunner(t,r,n,i){let o=(t||"zalo").toLowerCase(),s=o==="web"||o.includes("zalo")?"zalo":o;try{if(s==="zalo"){let{ZaloChannelRunner:a}=await Promise.resolve().then(()=>(TL(),RL));return new a(r,n,i)}if(s==="facebook"){let{FacebookChannelRunner:a}=await Promise.resolve().then(()=>(p6(),u6));return new a(r,n,i)}if(s==="telegram"){let{TelegramChannelRunner:a}=await Promise.resolve().then(()=>(g6(),m6));return new a(r,n,i)}if(s==="whatsapp"){let{WhatsAppChannelRunner:a}=await Promise.resolve().then(()=>(R$(),C$));return new a(r,n,i)}return this.logger.warn(`Unsupported platform for ChannelRunner: ${t}`),null}catch(a){return this.logger.error(`Failed to dynamically initialize runner for ${s}:${r}:`,a?.message||a),null}}};var tm=class{constructor(t,r,n,i,o){this.port=t;this.engine=r;this.lockManager=n;this.deltaQueue=i;this.logger=o||(0,O$.createLogger)("WorkerHttpServer")}logger;server=null;async start(){if(!this.server)return new Promise((t,r)=>{this.server=I$.default.createServer((n,i)=>{this.handleRequest(n,i).catch(o=>{this.logger.error("Unhandled HTTP error:",o),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 P$.URL(t.url||"/",`http://${t.headers.host||"localhost"}`),i=n.pathname,o=(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"),o==="OPTIONS"){r.writeHead(204),r.end();return}if(o==="GET"&&i==="/health"){let s=this.engine.getMetrics();r.writeHead(200,{"Content-Type":"application/json"}),r.end(JSON.stringify({status:"healthy",timestamp:Date.now(),pendingDeltaMessages:this.deltaQueue.getCount(),metrics:s}));return}if(i.startsWith("/api/v1/")){let s=this.engine.config.desktopSecret;if(s){let a=t.headers["x-desktop-secret"]||t.headers.authorization;if((typeof a=="string"&&a.startsWith("Bearer ")?a.slice(7):a)!==s){r.writeHead(401,{"Content-Type":"application/json"}),r.end(JSON.stringify({error:"Unauthorized: Invalid or missing X-Desktop-Secret"}));return}}}if(o==="POST"&&i==="/api/v1/sentinel/handover"){let s=await this.readJsonBody(t),{deviceId:a,sessions:c,aiConfig:u}=s||{};if(u&&(this.engine.automationEngine.configure(u),this.logger.info(`[Handover] Configured 24/7 AI automation engine with provider: ${u.provider||"gemini"}, model: ${u.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 ${a||"unknown"} with ${c.length} sessions.`);let l=0;for(let p of c){if(!p.id||!p.nightWorkerEnabled)continue;if(!this.lockManager.acquireLock(p.id,`worker_${p.id}`)){this.logger.warn(`Skipping account ${p.id} because lock was not acquired.`);continue}let h=(p.platform||"zalo").toLowerCase(),g=h==="web"||h.includes("zalo")?"zalo":h,w=await Ya.createRunner(g,p.id,p.sessionData);w&&(this.engine.registerRunner(w),await w.start(),this.engine.registerAccount({id:p.id,platform:g,accountName:p.accountName||p.id,status:"active",nightWorkerEnabled:!0}),l++)}r.writeHead(200,{"Content-Type":"application/json"}),r.end(JSON.stringify({success:!0,message:"Sessions handed over successfully",activatedCount:l,timestamp:Date.now()}));return}if(o==="POST"&&i==="/api/v1/sentinel/reclaim"){let s=await this.readJsonBody(t),{deviceId:a}=s||{};this.logger.info(`[Reclaim] Master device ${a||"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(o==="POST"){let s=await this.readJsonBody(t);s&&(this.engine.automationEngine.configure(s),this.logger.info(`[NightConfig] Updated 24/7 AI config dynamically: provider=${s.provider||"gemini"}, model=${s.model||"default"}`)),r.writeHead(200,{"Content-Type":"application/json"}),r.end(JSON.stringify({success:!0,config:this.engine.automationEngine.getAiConfig()}));return}else if(o==="GET"){r.writeHead(200,{"Content-Type":"application/json"}),r.end(JSON.stringify({success:!0,config:this.engine.automationEngine.getAiConfig()}));return}}if(o==="GET"&&i==="/api/v1/sync/delta"){let s=n.searchParams.get("accountId")||void 0,a=parseInt(n.searchParams.get("since")||"0",10),c=this.deltaQueue.getDeltas(s,a);this.logger.info(`[DeltaSync] Serving ${c.length} night messages (since: ${a}, account: ${s||"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 ec=le(nt());var Xa=require("child_process"),F$=le(nt()),rm=class e{logger;timer;isUpdating=!1;constructor(t){this.logger=t||(0,F$.createLogger)("WorkerAutoUpdater")}static isNewerVersion(t,r){let n=l=>l.replace(/^v/,"").trim().split(".").map(p=>parseInt(p,10)||0),[i=0,o=0,s=0]=n(t),[a=0,c=0,u=0]=n(r);return i>a||i===a&&o>c||i===a&&o===c&&s>u}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 o=await i.json();if(o?.version)return String(o.version).trim()}}catch{}try{return(0,Xa.execSync)(`npm view ${t} version`,{encoding:"utf-8",timeout:8e3,stdio:["ignore","pipe","ignore"]}).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?`@softtynet/zplus-worker@${t}`:"@softtynet/zplus-worker@latest";this.logger.info(`\u{1F680} [AutoUpdater] B\u1EAFt \u0111\u1EA7u t\u1EF1 \u0111\u1ED9ng n\xE2ng c\u1EA5p Worker l\xEAn ${r}...`);try{return(0,Xa.execSync)(`npm install -g ${r}`,{stdio:"inherit",timeout:12e4}),this.logger.info(`\u2705 [AutoUpdater] \u0110\xE3 c\xE0i \u0111\u1EB7t th\xE0nh c\xF4ng ${r}!`),this.triggerRestart(),!0}catch(n){return this.isUpdating=!1,this.logger.error(`\u274C [AutoUpdater] N\xE2ng c\u1EA5p th\u1EA5t b\u1EA1i: ${n?.message||n}`),!1}}triggerRestart(){try{if((0,Xa.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'..."),(0,Xa.spawn)("pm2",["restart","zplus-worker"],{detached:!0,stdio:"ignore"}).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), 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 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 (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: 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 Di=le(require("fs")),nm=le(require("path")),D$=le(require("os")),B$=le(require("readline")),im=le(nt()),Qa=class{logger;constructor(t){this.logger=t||(0,im.createLogger)("WorkerAuthManager")}getAuthFilePath(){let t=process.env.DATA_DIR||nm.default.join(D$.default.homedir(),".zplus");return nm.default.join(t,"worker_auth.json")}loadStoredAuth(){try{let t=this.getAuthFilePath();if(!Di.default.existsSync(t))return null;let r=Di.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=nm.default.dirname(r);Di.default.existsSync(n)||Di.default.mkdirSync(n,{recursive:!0,mode:448}),Di.default.writeFileSync(r,JSON.stringify(t,null,2),{encoding:"utf-8",mode:384});try{Di.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(){try{let t=this.getAuthFilePath();Di.default.existsSync(t)&&Di.default.unlinkSync(t),this.logger.info("\u0110\xE3 x\xF3a phi\xEAn \u0111\u0103ng nh\u1EADp c\u1EE7a Worker.")}catch(t){this.logger.debug("clearAuth error:",t?.message)}}async verifyEntitlements(t,r="https://api.softty.net/v1",n="699cfc3100136099c1c1",i="default"){try{let o=`${r}/account`,s=t.includes(".")&&t.split(".").length===3,a={"Content-Type":"application/json","X-Appwrite-Project":n};s?a["X-Appwrite-JWT"]=t:(a["X-Appwrite-Session"]=t,a.Cookie=`a_session_${n}=${t}; a_session_${n}_legacy=${t}`,t.startsWith("eyJ")&&(a["X-Fallback-Cookies"]=JSON.stringify({[`a_session_${n}`]:t,[`a_session_${n}_legacy`]:t})));let c=await fetch(o,{method:"GET",headers:a});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 u=await c.json(),l=u.$id||u.id||"",p=u.name||"Ng\u01B0\u1EDDi d\xF9ng ZPlus",d=u.email||"",h=Array.isArray(u.labels)?u.labels:[],g=u.prefs||{},_=!h.some(y=>y.toLowerCase()==="member")&&g.isOwner!==!1,m=h.some(y=>y.toLowerCase()==="free")||g.tier==="free",v=!m&&(g.isPremium===!0||h.some(y=>y.toLowerCase()==="premium"||y.toLowerCase()==="enterprise")),x=g.teamId||g.storage?.teamId||u.teamId||i;if((!x||x==="default")&&g.entitlements)try{let y=typeof g.entitlements=="string"?JSON.parse(g.entitlements):g.entitlements;y?.storage?.teamId&&(x=y.storage.teamId)}catch{}if((!x||x==="default")&&u.entitlements)try{let y=typeof u.entitlements=="string"?JSON.parse(u.entitlements):u.entitlements;y?.storage?.teamId&&(x=y.storage.teamId)}catch{}if(!x||x==="default")try{let y=await fetch(`${r}/teams`,{method:"GET",headers:a});if(y.ok){let S=await y.json().catch(()=>({})),k=Array.isArray(S.teams)?S.teams:[];k.length>0&&k[0].$id&&(x=k[0].$id)}}catch{}return m?{allowed:!1,userId:l,userName:p,email:d,teamId:x,isOwner:_,isPremium:!1,reason:`\u26A0\uFE0F T\xE0i kho\u1EA3n [${d}] \u0111ang \u1EDF G\xF3i Mi\u1EC5n Ph\xED (Free Tier). G\xF3i n\xE0y kh\xF4ng h\u1ED7 tr\u1EE3 c\u1EE5m Worker 24/7 (Y\xEAu c\u1EA7u g\xF3i Team Enterprise).`}:_?{allowed:!0,userId:l,userName:p,email:d,teamId:x,isOwner:!0,isPremium:!0,reason:`\u2705 X\xE1c th\u1EF1c th\xE0nh c\xF4ng: Tr\u01B0\u1EDFng nh\xF3m [${p}] (${d}) - G\xF3i Doanh Nghi\u1EC7p Active.`}:{allowed:!1,userId:l,userName:p,email:d,teamId:x,isOwner:!1,isPremium:v,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(o){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: ${o?.message}`}}}async loginWithCredentials(t,r,n="https://api.softty.net/v1",i="699cfc3100136099c1c1"){let o=t?.trim(),s=r;if(!o||!s){console.log(`
108
108
  ==================================================================`),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 a=B$.default.createInterface({input:process.stdin,output:process.stdout}),c=u=>new Promise(l=>a.question(u,l));o||(o=(await c("? Nh\u1EADp Email Tr\u01B0\u1EDFng nh\xF3m (Softty ID): ")).trim()),s||(s=await c("? Nh\u1EADp M\u1EADt kh\u1EA9u: ")),a.close()}if(!o||!s)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(`
109
109
  \u23F3 \u0110ang x\xE1c th\u1EF1c v\u1EDBi m\xE1y ch\u1EE7 Softty Cloud...`);let a=`${n}/account/sessions/email`,c=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json","X-Appwrite-Project":i},body:JSON.stringify({email:o,password:s})});if(!c.ok){let h=await c.json().catch(()=>({}));return console.error(`\u274C \u0110\u0103ng nh\u1EADp th\u1EA5t b\u1EA1i: ${h?.message||"Email ho\u1EB7c m\u1EADt kh\u1EA9u kh\xF4ng ch\xEDnh x\xE1c."}`),null}let l=(await c.json().catch(()=>({}))).secret||"";if(l||(l=c.headers.get("x-appwrite-session")||""),!l){let h=typeof c.headers.getSetCookie=="function"?c.headers.getSetCookie():[c.headers.get("set-cookie")||""];for(let g of h){let w=g.match(/a_session_[^=]+=([^;]+)/);if(w&&w[1]){l=decodeURIComponent(w[1]);break}}}if(!l)try{let h=c.headers.get("x-fallback-cookies");if(h){let g=JSON.parse(h);for(let w of Object.keys(g))if(w.startsWith("a_session_")){l=g[w];break}}}catch{}if(!l)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 p=await this.verifyEntitlements(l,n,i);if(console.log(`
110
110
  `+p.reason),!p.allowed&&!p.userId)return console.warn(`
@@ -112,9 +112,9 @@ ${v}`),w.pop(),`{${k}}`}case"number":return isFinite(g)?String(g):t?t(g):"null";
112
112
  \u{1F680} C\u1EE5m Worker 24/7 \u0111\xE3 s\u1EB5n s\xE0ng ho\u1EA1t \u0111\u1ED9ng!`):console.warn(`
113
113
  \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).`),d}catch(a){return console.error("\u274C L\u1ED7i m\u1EA1ng khi \u0111\u0103ng nh\u1EADp:",a?.message),null}}async refreshSessionToken(t,r="https://api.softty.net/v1",n="699cfc3100136099c1c1"){try{this.logger.info("\u{1F504} [Silent Refresh] \u0110ang t\u1EF1 \u0111\u1ED9ng l\xE0m m\u1EDBi quy\u1EC1n h\u1EA1n qua Softty Passport...");let i="https://accounts.softty.net/api/oauth/v1/token",o="https://accounts.softty.net/api/oauth/v1/exchange-appwrite",s="e70e2a103aac09a3b1f57822b5cfd301",a=new URLSearchParams;a.append("grant_type","refresh_token"),a.append("refresh_token",t),a.append("client_id",s);let c=await fetch(i,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:a.toString()});if(!c.ok)return this.logger.warn(`[Silent Refresh] L\u1ED7i c\u1EA5p l\u1EA1i access token t\u1EEB Softty Passport: HTTP ${c.status}`),null;let u=await c.json(),l=u.access_token,p=u.refresh_token||t;if(!l)return this.logger.warn("[Silent Refresh] Ph\u1EA3n h\u1ED3i kh\xF4ng c\xF3 access_token."),null;let d=await fetch(o,{method:"POST",headers:{Authorization:`Bearer ${l}`,"Content-Type":"application/json"},body:JSON.stringify({})});if(!d.ok)return this.logger.warn(`[Silent Refresh] L\u1ED7i exchange Appwrite: HTTP ${d.status}`),null;let h=await d.json(),g=h.sessionSecret,w=h.secret,_=h.userId;if(!g&&w&&_)try{let y=await fetch(`${r}/account/sessions/token`,{method:"POST",headers:{"Content-Type":"application/json","X-Appwrite-Project":n},body:JSON.stringify({userId:_,secret:w})});if(y.ok){let S=await y.json();S?.secret&&(g=S.secret)}}catch(y){this.logger.debug("[Silent Refresh] /account/sessions/token error:",y?.message)}let m=g||w||h.jwt;if(!m)return this.logger.warn("[Silent Refresh] Kh\xF4ng nh\u1EADn \u0111\u01B0\u1EE3c Session Token h\u1EE3p l\u1EC7 t\u1EEB Cloud."),null;let v=Number(u.expires_in||3600),x=Date.now()+v*1e3;return this.logger.info("\u2705 [Silent Refresh] \u0110\xE3 c\u1EA5p m\u1EDBi phi\xEAn l\xE0m vi\u1EC7c Appwrite th\xE0nh c\xF4ng!"),{sessionToken:m,refreshToken:p,userId:_||h.userId,tokenExpiresAt:x}}catch(i){return this.logger.error("[Silent Refresh] L\u1ED7i kh\xF4ng mong mu\u1ED1n khi l\xE0m m\u1EDBi token:",i?.message),null}}async ensureValidSession(t="https://api.softty.net/v1",r="699cfc3100136099c1c1",n=!1){let i=this.loadStoredAuth();if(!i)return this.logger.warn("\u26A0\uFE0F Worker ch\u01B0a c\xF3 th\xF4ng tin \u0111\u0103ng nh\u1EADp."),null;let o=!!(i.tokenExpiresAt&&Date.now()>i.tokenExpiresAt-300*1e3);if((o||n)&&i.refreshToken){this.logger.info(`\u{1F504} Phi\xEAn l\xE0m vi\u1EC7c c\u1EE7a [${i.email}] c\u1EA7n \u0111\u01B0\u1EE3c l\xE0m m\u1EDBi (isAboutToExpire: ${o}, forceRefresh: ${n}). K\xEDch ho\u1EA1t Silent Auto-Refresh 24/7...`);let s=await this.refreshSessionToken(i.refreshToken,t,r);if(s){let a=await this.verifyEntitlements(s.sessionToken,t,r,i.teamId),c={...i,sessionToken:s.sessionToken,refreshToken:s.refreshToken,tokenExpiresAt:s.tokenExpiresAt,userId:s.userId||a.userId||i.userId,userName:a.userName||i.userName,email:a.email||i.email,teamId:a.teamId||i.teamId,isOwner:a.isOwner,isPremium:a.isPremium,isAllowed:a.allowed,statusMessage:a.reason,savedAt:Date.now()};return this.saveAuth(c),this.logger.info(`\u2705 Phi\xEAn tr\u1EF1c chi\u1EBFn 24/7 \u0111\xE3 \u0111\u01B0\u1EE3c gia h\u1EA1n t\u1EF1 \u0111\u1ED9ng! (${c.userName} - ${c.email})`),c}}if(i.sessionToken&&!n&&(await this.verifyEntitlements(i.sessionToken,t,r,i.teamId)).allowed)return i;if(i.refreshToken){this.logger.info(`\u{1F504} Token hi\u1EC7n t\u1EA1i kh\xF4ng h\u1EE3p l\u1EC7. Th\u1EED ph\u1EE5c h\u1ED3i qua Refresh Token cho [${i.email}]...`);let s=await this.refreshSessionToken(i.refreshToken,t,r);if(s){let a=await this.verifyEntitlements(s.sessionToken,t,r,i.teamId),c={...i,sessionToken:s.sessionToken,refreshToken:s.refreshToken,tokenExpiresAt:s.tokenExpiresAt,userId:s.userId||a.userId||i.userId,userName:a.userName||i.userName,email:a.email||i.email,teamId:a.teamId||i.teamId,isOwner:a.isOwner,isPremium:a.isPremium,isAllowed:a.allowed,statusMessage:a.reason,savedAt:Date.now()};return this.saveAuth(c),this.logger.info(`\u2705 Phi\xEAn tr\u1EF1c chi\u1EBFn 24/7 \u0111\xE3 \u0111\u01B0\u1EE3c ph\u1EE5c h\u1ED3i t\u1EF1 \u0111\u1ED9ng! (${c.userName} - ${c.email})`),c}}return this.logger.warn("\u26A0\uFE0F Phi\xEAn l\xE0m vi\u1EC7c \u0111\xE3 h\u1EBFt h\u1EA1n v\xE0 kh\xF4ng th\u1EC3 t\u1EF1 \u0111\u1ED9ng gia h\u1EA1n (Thi\u1EBFu Refresh Token ho\u1EB7c Refresh Token \u0111\xE3 h\u1EBFt h\u1EA1n)."),null}async loginWithToken(t,r="https://api.softty.net/v1",n="699cfc3100136099c1c1",i="default"){console.log(`
114
114
  \u23F3 \u0110ang ki\u1EC3m tra m\xE3 gh\xE9p n\u1ED1i v\u1EDBi m\xE1y ch\u1EE7 Cloud...`);let o=t,s,a,c=i;if(t.startsWith("eyJ")||t.length>50)try{let g=Buffer.from(t,"base64").toString("utf-8");if(g.startsWith("CLD-")||t.startsWith("CLD-")){let w=g.startsWith("CLD-")?g:t;try{g=im.CloudCrypto.decryptFromCloud(w,"zplus_worker_pairing",["default",i])}catch(_){this.logger.warn("\u26A0\uFE0F Kh\xF4ng th\u1EC3 gi\u1EA3i m\xE3 Token CloudCrypto:",_?.message)}}if(g.startsWith("{")&&g.endsWith("}")){let w=JSON.parse(g);if(w.issuedAt&&typeof w.issuedAt=="number"&&Date.now()-w.issuedAt>9e5)return console.error(`
115
- \u274C L\u1ED7i: M\xE3 gh\xE9p n\u1ED1i \u0111\xE3 h\u1EBFt h\u1EA1n (ch\u1EC9 c\xF3 hi\u1EC7u l\u1EF1c trong v\xF2ng 15 ph\xFAt k\u1EC3 t\u1EEB khi t\u1EA1o). Vui l\xF2ng t\u1EA1o m\xE3 m\u1EDBi t\u1EEB ZPlus Desktop.`),null;if(w.refreshToken&&(s=w.refreshToken),w.userId&&(a=w.userId),w.teamId&&w.teamId!=="default"&&(c=w.teamId),w.sessionToken?o=w.sessionToken:w.secret&&(o=w.secret),w.userId&&w.secret)try{let _=await fetch(`${r}/account/sessions/token`,{method:"POST",headers:{"Content-Type":"application/json","X-Appwrite-Project":n},body:JSON.stringify({userId:w.userId,secret:w.secret})});if(_.ok){let m=await _.json();m?.secret&&(o=m.secret,this.logger.info("\u{1F511} \u0110\xE3 n\xE2ng c\u1EA5p l\xEAn Persistent Session Secret d\xE0i h\u1EA1n t\u1EEB Cloud."))}}catch(_){this.logger.debug("Token exchange fallback:",_?.message)}}}catch{}let u=await this.verifyEntitlements(o,r,n,c);if(console.log(`
116
- `+u.reason),!u.allowed&&!u.userId)return console.warn(`
117
- \u23F8\uFE0F M\xE3 gh\xE9p n\u1ED1i kh\xF4ng h\u1EE3p l\u1EC7 ho\u1EB7c \u0111\xE3 h\u1EBFt h\u1EA1n. Vui l\xF2ng l\u1EA5y m\xE3 m\u1EDBi t\u1EEB ZPlus Desktop.`),null;let l=o,p=s,d=s?Date.now()+3600*1e3:void 0;if(s&&u.allowed)try{this.logger.info("\u{1F525} [Burn-on-Use] K\xEDch ho\u1EA1t Refresh Token Rotation \u0111\u1EC3 h\u1EE7y m\xE3 gh\xE9p n\u1ED1i c\u0169 tr\xEAn server...");let g=await this.refreshSessionToken(s,r,n);g&&(l=g.sessionToken,p=g.refreshToken,d=g.tokenExpiresAt,this.logger.info("\u2705 [Burn-on-Use] \u0110\xE3 c\u1EA5p m\u1EDBi phi\xEAn \u0111\u1ED9c quy\u1EC1n cho Worker. M\xE3 gh\xE9p n\u1ED1i c\u0169 \u0111\xE3 b\u1ECB h\u1EE7y v\u0129nh vi\u1EC5n tr\xEAn server!"))}catch(g){this.logger.debug("[Burn-on-Use] rotation error:",g?.message)}let h={userId:u.userId||a||"",userName:u.userName,email:u.email,teamId:u.teamId||c,sessionToken:l,refreshToken:p,tokenExpiresAt:d,authType:p?"oauth_pair":"token",isOwner:u.isOwner,isPremium:u.isPremium,isAllowed:u.allowed,statusMessage:u.reason,savedAt:Date.now()};return this.saveAuth(h),u.allowed?console.log(`
115
+ \u274C L\u1ED7i: M\xE3 gh\xE9p n\u1ED1i \u0111\xE3 h\u1EBFt h\u1EA1n (ch\u1EC9 c\xF3 hi\u1EC7u l\u1EF1c trong v\xF2ng 15 ph\xFAt k\u1EC3 t\u1EEB khi t\u1EA1o). Vui l\xF2ng t\u1EA1o m\xE3 m\u1EDBi t\u1EEB ZPlus Desktop.`),null;if(w.refreshToken&&(s=w.refreshToken),w.userId&&(a=w.userId),w.teamId&&w.teamId!=="default"&&(c=w.teamId),w.sessionToken?o=w.sessionToken:w.secret&&(o=w.secret),w.userId&&w.secret)try{let _=await fetch(`${r}/account/sessions/token`,{method:"POST",headers:{"Content-Type":"application/json","X-Appwrite-Project":n},body:JSON.stringify({userId:w.userId,secret:w.secret})});if(_.ok){let m=await _.json();m?.secret&&(o=m.secret,this.logger.info("\u{1F511} \u0110\xE3 n\xE2ng c\u1EA5p l\xEAn Persistent Session Secret d\xE0i h\u1EA1n t\u1EEB Cloud."))}}catch(_){this.logger.debug("Token exchange fallback:",_?.message)}}}catch{}let u=o,l=s,p=s?Date.now()+3600*1e3:void 0;if(s)try{this.logger.info("\u{1F525} [Burn-on-Use] K\xEDch ho\u1EA1t Refresh Token Rotation \u0111\u1EC3 c\u1EA5p phi\xEAn m\u1EDBi \u0111\u1ED9c quy\u1EC1n cho Worker...");let g=await this.refreshSessionToken(s,r,n);g&&(u=g.sessionToken,l=g.refreshToken,p=g.tokenExpiresAt,g.userId&&(a=g.userId),this.logger.info("\u2705 [Burn-on-Use] \u0110\xE3 c\u1EA5p m\u1EDBi phi\xEAn \u0111\u1ED9c quy\u1EC1n cho Worker. M\xE3 gh\xE9p n\u1ED1i c\u0169 \u0111\xE3 b\u1ECB h\u1EE7y v\u0129nh vi\u1EC5n tr\xEAn server!"))}catch(g){this.logger.debug("[Burn-on-Use] rotation error:",g?.message)}let d=await this.verifyEntitlements(u,r,n,c);if(console.log(`
116
+ `+d.reason),!d.allowed&&!d.userId&&!a)return console.warn(`
117
+ \u23F8\uFE0F M\xE3 gh\xE9p n\u1ED1i kh\xF4ng h\u1EE3p l\u1EC7 ho\u1EB7c \u0111\xE3 h\u1EBFt h\u1EA1n. Vui l\xF2ng l\u1EA5y m\xE3 m\u1EDBi t\u1EEB ZPlus Desktop.`),null;let h={userId:d.userId||a||"",userName:d.userName,email:d.email,teamId:d.teamId||c,sessionToken:u,refreshToken:l,tokenExpiresAt:p,authType:l?"oauth_pair":"token",isOwner:d.isOwner,isPremium:d.isPremium,isAllowed:d.allowed,statusMessage:d.reason,savedAt:Date.now()};return this.saveAuth(h),d.allowed?console.log(`
118
118
  \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(`
119
119
  \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).`),h}};var om=require("child_process"),L$=le(require("os")),sm=class{static lastAlertTimes=new Map;static notify(t,r,n="default",i=600*1e3){let o=Date.now(),s=this.lastAlertTimes.get(n)||0;if(o-s<i)return!1;this.lastAlertTimes.set(n,o);let a=L$.default.platform();try{if(a==="darwin"){let c=t.replace(/"/g,'\\"'),l=`display notification "${r.replace(/"/g,'\\"')}" with title "${c}" sound name "Basso"`;return(0,om.spawn)("osascript",["-e",l],{detached:!0,stdio:"ignore"}).unref(),!0}else{if(a==="linux")return(0,om.spawn)("notify-send",["-u","critical",t,r],{detached:!0,stdio:"ignore"}).unref(),!0;if(a==="win32"){let c=t.replace(/"/g,'`"'),u=r.replace(/"/g,'`"'),l=`
120
120
  [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softtynet/zplus-worker",
3
- "version": "1.0.34",
3
+ "version": "1.0.36",
4
4
  "description": "ZPlus 24/7 Headless Social Automation Worker & AI Omnichannel Sentinel",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",