@jikey/fcazero
Version:
Facebook Messenger bot, and is one of the most advanced next-generation Facebook Chat API (FCA)
2 lines (1 loc) • 6.9 kB
JavaScript
;var J=Object.create;var S=Object.defineProperty;var $=Object.getOwnPropertyDescriptor;var F=Object.getOwnPropertyNames;var U=Object.getPrototypeOf,B=Object.prototype.hasOwnProperty;var G=(c,n)=>{for(var o in n)S(c,o,{get:n[o],enumerable:!0})},v=(c,n,o,e)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of F(n))!B.call(c,r)&&r!==o&&S(c,r,{get:()=>n[r],enumerable:!(e=$(n,r))||e.enumerable});return c};var q=(c,n,o)=>(o=c!=null?J(U(c)):{},v(n||!c||!c.__esModule?S(o,"default",{value:c,enumerable:!0}):o,c)),V=c=>v(S({},"__esModule",{value:!0}),c);var W={};G(W,{default:()=>E});module.exports=V(W);var A=q(require("mqtt"),1),D=q(require("ws"),1),R=require("proxy-agent"),a=q(require("../utils/logger.js"),1),w=require("../utils/constants.js"),O=require("../utils/clients.js"),b=require("../utils/formatters.js"),C=q(require("./core/parseDelta.js"),1),L=require("./core/messageEmitter.js");class E{constructor(n,o,e){this.defaultFuncs=n;this.api=o;this.ctx=e;this.listenMqtt=async(n,o,e,r)=>{try{a.default.info("listenMQTT: Creating MQTT client...");const t=e.globalOptions.online,i=e.region,l=Math.floor(Math.random()*Number.MAX_SAFE_INTEGER)+1,g=e.clientID,Q=new C.default(n,o,e,r),T={u:e.userID,s:l,chat_on:t,fg:!0,d:g,ct:"websocket",aid:e.mqttAppID,aids:null,mqtt_sid:"",cp:3,ecp:10,st:[],pm:[],p:null,dc:"",no_auto_fg:!0,php_override:"",gas:null,pack:[],a:e.globalOptions.userAgent},m=e.jar.getCookiesSync("https://www.facebook.com").join("; "),y="wss://edge-chat.messenger.com/chat",f=i?`${y}?region=${i.toLowerCase()}&sid=${l}&cid=${g}`:`${y}?sid=${l}&cid=${g}`;a.default.info(`listenMQTT: Using host ${f}`);const h={clientId:T.d??w.Constants.getGUID(),protocolId:"MQIsdp",protocolVersion:3,username:JSON.stringify(T),clean:!0,wsOptions:{headers:{cookie:m,origin:"https://www.messenger.com","user-agent":T.a,referer:"https://www.messenger.com/",host:new URL(f).hostname},origin:"https://www.messenger.com",protocolVersion:13},keepalive:10,reschedulePings:!0,connectTimeout:6e4,reconnectPeriod:1e3};e.globalOptions.proxy&&(h.wsOptions.agent=new R.ProxyAgent({getProxyForUrl:()=>e.globalOptions.proxy}));const P=()=>{const u=new D.default(f,h.wsOptions);return(0,D.createWebSocketStream)(u)},p=new A.default.Client(P,h);e.mqttClient=p,p.on("connect",async()=>{await Promise.all(w.Constants.topics.map(d=>p.subscribe(d)));const u={sync_api_version:10,max_deltas_able_to_process:1e3,delta_batch_size:500,encoding:"JSON",entity_fbid:e.userID,initial_titan_sequence_id:e.lastSeqId,device_params:null};p.publish("/foreground_state",JSON.stringify({foreground:t}),{qos:1}),p.publish("/set_client_settings",JSON.stringify({make_user_available_when_in_foreground:!0}),{qos:1}),p.publish("/messenger_sync_create_queue",JSON.stringify(u),{qos:1,retain:!1}),a.default.info("listenMQTT: Connected to MQTT!")});let M;e.globalOptions.updatePresence&&(M=setInterval(()=>{if(p.connected){const u=w.Constants.generatePresence(e.userID??"");p.publish("/orca_presence",JSON.stringify({p:u}),d=>{d&&a.default.error({err:d},"Failed to send presence update:")})}},5e4));const k=()=>{M&&(clearInterval(M),M=void 0)};p.on("message",async(u,d,X)=>{let N=Buffer.isBuffer(d)?Buffer.from(d).toString():d,s;try{s=JSON.parse(N)}catch{s={}}if(s.type==="jewel_requests_add")r(null,{type:"friend_request_received",actorFbId:s.from.toString()??"",timestamp:Date.now().toString()});else if(s.type==="jewel_requests_remove_old")r(null,{type:"friend_request_cancel",actorFbId:s.from.toString(),timestamp:Date.now().toString()});else if(u==="/t_ms"){s.firstDeltaSeqId&&s.syncToken&&(e.lastSeqId=s.firstDeltaSeqId,e.syncToken=s.syncToken),s.lastIssuedSeqId&&(e.lastSeqId=String(parseInt(s.lastIssuedSeqId)));for(const _ in s.deltas){const I=s.deltas[_];Q.parse({delta:I})}}else if(u==="/thread_typing"||u==="/orca_typing_notifications"){const _={type:"typ",isTyping:!!s.state,from:s.sender_fbid.toString(),threadID:b.Formatters.formatID((s.thread||s.sender_fbid).toString())};(function(){r(null,_)})()}else if(u==="/orca_presence"&&!e.globalOptions.updatePresence)for(const _ in s.list){const I=s.list[_],j={type:"presence",userID:I.u.toString(),timestamp:I.l*1e3,statuses:I.p};(function(){r(null,j)})()}}),p.on("close",()=>{k(),a.default.info("listenMQTT: MQTT connection closed.")}),p.on("reconnect",()=>{a.default.info("listenMQTT: Reconnecting MQTT client...")}),p.on("end",()=>{k(),a.default.info("listenMQTT: MQTT connection ended.")}),p.on("error",u=>{k(),p.end(),a.default.error({err:u},"listenMQTT: MQTT connection error:"),e.globalOptions.autoReconnect?this.listenMqtt(n,o,e,r):O.Clients.checkLiveCookie(e,n).then(()=>{r(new Error("Connection refused: Server unavailable"),null)}).catch(()=>{const d=new Error("Maybe your account is blocked by facebook, please login and check at https://facebook.com");d.type="account_inactive",r(d,null)})})}catch(t){a.default.error({err:t},"listenMqtt"),r&&typeof r=="function"&&r(t instanceof Error?t:new Error(String(t)))}}}async getSeqID(n,o,e,r,t){try{const i={queries:JSON.stringify({o0:{doc_id:"3336396659757871",query_params:{limit:1,before:null,tags:["INBOX"],includeDeliveryReceipts:!1,includeSeqID:!0}}})},l=await n.post("https://www.facebook.com/api/graphqlbatch/",e.jar,i).then(O.Clients.parseAndCheckLogin(e,n));if(w.Constants.getType(l)!="Array"||l&&l.error==1357001)throw l;if(Array.isArray(l)&&l[0]?.o0?.data?.viewer?.message_threads?.sync_sequence_id)e.lastSeqId=l[0].o0.data.viewer.message_threads.sync_sequence_id;else throw new Error("Unexpected response format when fetching sequence ID");return t(n,o,e,r)}catch(i){return a.default.error({err:i},"getSeqID"),r(i instanceof Error?i:new Error(String(i)))}}async scheduleReconnect(n,o){a.default.info("listenMQTT: Scheduling reconnect in 20 minutes...");let e=setTimeout(()=>{a.default.info("listenMQTT: Reconnecting MQTT with new clientID..."),o.mqttClient&&n.hardRestart()},1e3*60*20);n.on("stop",()=>{e&&(clearTimeout(e),e=null)})}call(n,o){return new Promise((e,r)=>{try{const{ctx:t,api:i,defaultFuncs:l,listenMqtt:g,getSeqID:Q}=this;let T=(y,f)=>{if(y)return m.emit("error",y);(f.type==="message"||f.type==="message_reply")&&i.markAsRead.call({threadID:String(f.threadID)},h=>{h&&a.default.error({err:h},"markAsRead MQTT")}),f&&(m.emit("message",f),o(null,f))};const m=new L.MessageEmitter(t,g,l,i,T);t.emittery=m,!t.firstListen||!t.lastSeqId?Q(l,i,t,T,g):g(l,i,t,T),t.firstListen,t.firstListen=!1,this.scheduleReconnect(m,t),i.stopListeningAsync={call:()=>m.stopListeningAsync()},i.softReconnectAsync={call:()=>m.softReconnect()},i.hardRestartAsync={call:()=>m.hardRestart()},setInterval(()=>{i.refreshConfigRequest.call(null,(y,f)=>{y?a.default.error({err:y},"Error in refreshConfigRequest"):a.default.info("refreshConfigRequest: Successfully refreshed config.")})},1e3*60*20),e(m)}catch(t){a.default.error({err:t},"listenMQTT"),o(t instanceof Error?t:new Error(String(t)),null),r(t)}})}}