From 781c16f2195bc00795589b026c73e390c4fd7432 Mon Sep 17 00:00:00 2001
From: Hossam Mansour <6911267+7osCraft@users.noreply.github.com>
Date: Thu, 28 Nov 2019 00:47:47 +0200
Subject: [PATCH 01/10] Added support for MQTT
---
index.js | 2 +
package-lock.json | 483 +++++++++++++++++++++++++++++++++++++++--
package.json | 1 +
src/listenMqtt.js | 443 +++++++++++++++++++++++++++++++++++++
src/markAsDelivered.js | 46 ++++
src/mqtt/fbconnect.js | 139 ++++++++++++
src/mqtt/fbws.js | 93 ++++++++
7 files changed, 1185 insertions(+), 22 deletions(-)
create mode 100644 src/listenMqtt.js
create mode 100644 src/markAsDelivered.js
create mode 100644 src/mqtt/fbconnect.js
create mode 100644 src/mqtt/fbws.js
diff --git a/index.js b/index.js
index 4214511f..5bbf365d 100644
--- a/index.js
+++ b/index.js
@@ -99,7 +99,9 @@ function buildAPI(globalOptions, html, jar) {
'getUserInfo',
'handleMessageRequest',
'listen',
+ 'listenMqtt',
'logout',
+ 'markAsDelivered',
'markAsRead',
'markAsReadAll',
'muteThread',
diff --git a/package-lock.json b/package-lock.json
index 4920970b..1b49c33b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -119,6 +119,11 @@
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
},
+ "async-limiter": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
+ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
+ },
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -172,8 +177,12 @@
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
- "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
- "dev": true
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+ },
+ "base64-js": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
+ "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
},
"bcrypt-pbkdf": {
"version": "1.0.2",
@@ -183,6 +192,15 @@
"tweetnacl": "^0.14.3"
}
},
+ "bl": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
+ "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==",
+ "requires": {
+ "readable-stream": "^2.3.5",
+ "safe-buffer": "^5.1.1"
+ }
+ },
"bluebird": {
"version": "2.11.0",
"resolved": "http://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz",
@@ -197,7 +215,6 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -206,8 +223,16 @@
"buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
- "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
- "dev": true
+ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
+ },
+ "callback-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/callback-stream/-/callback-stream-1.1.0.tgz",
+ "integrity": "sha1-RwGlEmbwbgbqpx/BcjOCLYdfSQg=",
+ "requires": {
+ "inherits": "^2.0.1",
+ "readable-stream": "> 1.0.0 < 3.0.0"
+ }
},
"caller-path": {
"version": "0.1.0",
@@ -344,17 +369,31 @@
"integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=",
"dev": true
},
+ "commist": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz",
+ "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==",
+ "requires": {
+ "leven": "^2.1.0",
+ "minimist": "^1.1.0"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
+ }
+ }
+ },
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
- "dev": true
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"concat-stream": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
- "dev": true,
"requires": {
"buffer-from": "^1.0.0",
"inherits": "^2.0.3",
@@ -394,6 +433,15 @@
"resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz",
"integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0="
},
+ "d": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
+ "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
+ "requires": {
+ "es5-ext": "^0.10.50",
+ "type": "^1.0.1"
+ }
+ },
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@@ -495,6 +543,17 @@
"domelementtype": "1"
}
},
+ "duplexify": {
+ "version": "3.7.1",
+ "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
+ "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
+ "requires": {
+ "end-of-stream": "^1.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
"ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
@@ -504,11 +563,84 @@
"safer-buffer": "^2.1.0"
}
},
+ "end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
"entities": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
"integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA="
},
+ "es5-ext": {
+ "version": "0.10.53",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz",
+ "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==",
+ "requires": {
+ "es6-iterator": "~2.0.3",
+ "es6-symbol": "~3.1.3",
+ "next-tick": "~1.0.0"
+ }
+ },
+ "es6-iterator": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
+ "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
+ "requires": {
+ "d": "1",
+ "es5-ext": "^0.10.35",
+ "es6-symbol": "^3.1.1"
+ }
+ },
+ "es6-map": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz",
+ "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=",
+ "requires": {
+ "d": "1",
+ "es5-ext": "~0.10.14",
+ "es6-iterator": "~2.0.1",
+ "es6-set": "~0.1.5",
+ "es6-symbol": "~3.1.1",
+ "event-emitter": "~0.3.5"
+ }
+ },
+ "es6-set": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz",
+ "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=",
+ "requires": {
+ "d": "1",
+ "es5-ext": "~0.10.14",
+ "es6-iterator": "~2.0.1",
+ "es6-symbol": "3.1.1",
+ "event-emitter": "~0.3.5"
+ },
+ "dependencies": {
+ "es6-symbol": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
+ "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
+ "requires": {
+ "d": "1",
+ "es5-ext": "~0.10.14"
+ }
+ }
+ }
+ },
+ "es6-symbol": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
+ "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
+ "requires": {
+ "d": "^1.0.1",
+ "ext": "^1.1.2"
+ }
+ },
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
@@ -623,6 +755,30 @@
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
"dev": true
},
+ "event-emitter": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
+ "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
+ "requires": {
+ "d": "1",
+ "es5-ext": "~0.10.14"
+ }
+ },
+ "ext": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ext/-/ext-1.2.1.tgz",
+ "integrity": "sha512-x+OKKC57tNiLhDW26UmWtvQBpvO+2wxdC/A0jP7RkmjAc4gze9/U98hQyIYJUzo9A+o9ntMHpC+LH3pWMSbrVQ==",
+ "requires": {
+ "type": "^2.0.0"
+ },
+ "dependencies": {
+ "type": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz",
+ "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow=="
+ }
+ }
+ },
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@@ -719,8 +875,7 @@
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
- "dev": true
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"functional-red-black-tree": {
"version": "1.0.1",
@@ -752,7 +907,6 @@
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
"integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
- "dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -762,6 +916,32 @@
"path-is-absolute": "^1.0.0"
}
},
+ "glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "requires": {
+ "is-glob": "^3.1.0",
+ "path-dirname": "^1.0.0"
+ }
+ },
+ "glob-stream": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz",
+ "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=",
+ "requires": {
+ "extend": "^3.0.0",
+ "glob": "^7.1.1",
+ "glob-parent": "^3.1.0",
+ "is-negated-glob": "^1.0.0",
+ "ordered-read-streams": "^1.0.0",
+ "pumpify": "^1.3.5",
+ "readable-stream": "^2.1.5",
+ "remove-trailing-separator": "^1.0.1",
+ "to-absolute-glob": "^2.0.0",
+ "unique-stream": "^2.0.2"
+ }
+ },
"globals": {
"version": "11.8.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.8.0.tgz",
@@ -828,6 +1008,17 @@
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
},
+ "help-me": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/help-me/-/help-me-1.1.0.tgz",
+ "integrity": "sha1-jy1QjQYAtKRW2i8IZVbn5cBWo8Y=",
+ "requires": {
+ "callback-stream": "^1.0.2",
+ "glob-stream": "^6.1.0",
+ "through2": "^2.0.1",
+ "xtend": "^4.0.0"
+ }
+ },
"htmlparser2": {
"version": "3.9.2",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz",
@@ -876,7 +1067,6 @@
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
- "dev": true,
"requires": {
"once": "^1.3.0",
"wrappy": "1"
@@ -909,12 +1099,39 @@
"through": "^2.3.6"
}
},
+ "is-absolute": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz",
+ "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==",
+ "requires": {
+ "is-relative": "^1.0.0",
+ "is-windows": "^1.0.1"
+ }
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
+ },
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
"dev": true
},
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "requires": {
+ "is-extglob": "^2.1.0"
+ }
+ },
+ "is-negated-glob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz",
+ "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI="
+ },
"is-path-cwd": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
@@ -945,6 +1162,14 @@
"integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
"dev": true
},
+ "is-relative": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
+ "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==",
+ "requires": {
+ "is-unc-path": "^1.0.0"
+ }
+ },
"is-resolvable": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
@@ -956,6 +1181,19 @@
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
+ "is-unc-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz",
+ "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==",
+ "requires": {
+ "unc-path-regex": "^0.1.2"
+ }
+ },
+ "is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="
+ },
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -1030,8 +1268,7 @@
"json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
- "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
- "dev": true
+ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE="
},
"json-stringify-safe": {
"version": "5.0.1",
@@ -1049,6 +1286,11 @@
"verror": "1.10.0"
}
},
+ "leven": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz",
+ "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA="
+ },
"levn": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
@@ -1173,7 +1415,6 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
- "dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -1266,6 +1507,46 @@
}
}
},
+ "mqtt": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-3.0.0.tgz",
+ "integrity": "sha512-0nKV6MAc1ibKZwaZQUTb3iIdT4NVpj541BsYrqrGBcQdQ7Jd0MnZD1/6/nj1UFdGTboK9ZEUXvkCu2nPCugHFA==",
+ "requires": {
+ "base64-js": "^1.3.0",
+ "commist": "^1.0.0",
+ "concat-stream": "^1.6.2",
+ "end-of-stream": "^1.4.1",
+ "es6-map": "^0.1.5",
+ "help-me": "^1.0.1",
+ "inherits": "^2.0.3",
+ "minimist": "^1.2.0",
+ "mqtt-packet": "^6.0.0",
+ "pump": "^3.0.0",
+ "readable-stream": "^2.3.6",
+ "reinterval": "^1.1.0",
+ "split2": "^3.1.0",
+ "websocket-stream": "^5.1.2",
+ "xtend": "^4.0.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
+ }
+ }
+ },
+ "mqtt-packet": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.2.1.tgz",
+ "integrity": "sha512-ZxG5QVb7+gMix5n4DClym9dQoCZC6DoNEqgMkMi/GMXvIU4Wsdx+/6KBavw50HHFH9kN1lBSY7phxNlAS2+jnw==",
+ "requires": {
+ "bl": "^1.2.2",
+ "inherits": "^2.0.3",
+ "process-nextick-args": "^2.0.0",
+ "safe-buffer": "^5.1.2"
+ }
+ },
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
@@ -1284,6 +1565,11 @@
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
"dev": true
},
+ "next-tick": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
+ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
+ },
"npmlog": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-1.2.1.tgz",
@@ -1317,7 +1603,6 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
- "dev": true,
"requires": {
"wrappy": "1"
}
@@ -1345,17 +1630,29 @@
"wordwrap": "~1.0.0"
}
},
+ "ordered-read-streams": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz",
+ "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=",
+ "requires": {
+ "readable-stream": "^2.0.1"
+ }
+ },
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true
},
+ "path-dirname": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
+ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA="
+ },
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
- "dev": true
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"path-is-inside": {
"version": "1.0.2",
@@ -1429,6 +1726,36 @@
"resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz",
"integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ=="
},
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "pumpify": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
+ "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
+ "requires": {
+ "duplexify": "^3.6.0",
+ "inherits": "^2.0.3",
+ "pump": "^2.0.0"
+ },
+ "dependencies": {
+ "pump": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+ "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ }
+ }
+ },
"punycode": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
@@ -1459,6 +1786,16 @@
"integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==",
"dev": true
},
+ "reinterval": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz",
+ "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc="
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
+ },
"request": {
"version": "2.88.0",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
@@ -1597,6 +1934,26 @@
"is-fullwidth-code-point": "^2.0.0"
}
},
+ "split2": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/split2/-/split2-3.1.1.tgz",
+ "integrity": "sha512-emNzr1s7ruq4N+1993yht631/JH+jaj0NYBosuKmLcq+JkGQ9MmTw1RB1fGaTCzUuseRIClrlSLHRNYGwWQ58Q==",
+ "requires": {
+ "readable-stream": "^3.0.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz",
+ "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
@@ -1619,6 +1976,11 @@
"tweetnacl": "~0.14.0"
}
},
+ "stream-shift": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
+ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI="
+ },
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
@@ -1692,6 +2054,24 @@
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
"dev": true
},
+ "through2": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
+ "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
+ "requires": {
+ "readable-stream": "~2.3.6",
+ "xtend": "~4.0.1"
+ }
+ },
+ "through2-filter": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz",
+ "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==",
+ "requires": {
+ "through2": "~2.0.0",
+ "xtend": "~4.0.0"
+ }
+ },
"tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
@@ -1701,6 +2081,15 @@
"os-tmpdir": "~1.0.2"
}
},
+ "to-absolute-glob": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz",
+ "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=",
+ "requires": {
+ "is-absolute": "^1.0.0",
+ "is-negated-glob": "^1.0.0"
+ }
+ },
"to-iso-string": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz",
@@ -1729,6 +2118,11 @@
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
},
+ "type": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
+ "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
+ },
"type-check": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
@@ -1741,8 +2135,26 @@
"typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
- "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
- "dev": true
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
+ },
+ "ultron": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
+ "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og=="
+ },
+ "unc-path-regex": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
+ "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo="
+ },
+ "unique-stream": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz",
+ "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==",
+ "requires": {
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "through2-filter": "^3.0.0"
+ }
},
"util-deprecate": {
"version": "1.0.2",
@@ -1764,6 +2176,19 @@
"extsprintf": "^1.2.0"
}
},
+ "websocket-stream": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/websocket-stream/-/websocket-stream-5.5.0.tgz",
+ "integrity": "sha512-EXy/zXb9kNHI07TIMz1oIUIrPZxQRA8aeJ5XYg5ihV8K4kD1DuA+FY6R96HfdIHzlSzS8HiISAfrm+vVQkZBug==",
+ "requires": {
+ "duplexify": "^3.5.1",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.3.3",
+ "safe-buffer": "^5.1.2",
+ "ws": "^3.2.0",
+ "xtend": "^4.0.0"
+ }
+ },
"which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
@@ -1782,8 +2207,7 @@
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
- "dev": true
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"write": {
"version": "0.2.1",
@@ -1794,6 +2218,21 @@
"mkdirp": "^0.5.1"
}
},
+ "ws": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
+ "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
+ "requires": {
+ "async-limiter": "~1.0.0",
+ "safe-buffer": "~5.1.0",
+ "ultron": "~1.1.0"
+ }
+ },
+ "xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
+ },
"yallist": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
diff --git a/package.json b/package.json
index ce597202..133a6ec9 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
"dependencies": {
"bluebird": "^2.9.27",
"cheerio": "^0.22.0",
+ "mqtt": "^3.0.0",
"npmlog": "^1.2.0",
"request": "^2.53.0"
},
diff --git a/src/listenMqtt.js b/src/listenMqtt.js
new file mode 100644
index 00000000..7d54c76f
--- /dev/null
+++ b/src/listenMqtt.js
@@ -0,0 +1,443 @@
+"use strict";
+var fbconnect = require("./mqtt/fbconnect");
+var utils = require("../utils");
+var log = require("npmlog");
+
+var identity = function () { };
+var lastSeqId = 0;
+
+var defaultFuncs = undefined;
+
+function listenMqtt(ctx, globalCallback) {
+ var sessionID = Math.floor(Math.random() * 9007199254740991) + 1;
+ var username = {
+ u: ctx.userID,
+ s: sessionID,
+ cp: 3,
+ ecp: 10,
+ chat_on: true,
+ fg: false,
+ d: utils.getGUID(),
+ ct: "websocket",
+ mqtt_sid: "",
+ //App id from facebook
+ aid: "219994525426954",
+ st: [],
+ pm: [],
+ dc: "",
+ no_auto_fg: true,
+ gas: null
+ };
+ var cookies = ctx.jar.getCookies("https://www.facebook.com").join("; ");
+
+ //Region could be changed for better ping.
+ var host = 'wss://edge-chat.facebook.com/chat?region=atn&sid=' + sessionID;
+
+ var options = {
+ clientId: "mqttwsclient",
+ protocolId: 'MQIsdp',
+ protocolVersion: 3,
+ username: JSON.stringify(username),
+ wsOptions: {
+ 'headers': {
+ 'Cookie': cookies,
+ 'Origin': 'https://www.facebook.com',
+ 'User-Agent': ctx.globalOptions.userAgent,
+ 'Referer': 'https://www.facebook.com',
+ },
+ origin: 'https://www.facebook.com',
+ protocolVersion: 13
+ }
+ };
+
+ var client = fbconnect.connect(host, options);
+
+ client.on('error', function (err) {
+ log.error(err);
+ client.end();
+ });
+
+ client.on('connect', function () {
+ client.subscribe(["/legacy_web", "/webrtc", "/br_sr", "/sr_res", "/t_ms", "/thread_typing", "/orca_typing_notifications", "/notify_disconnect", "/orca_presence"],
+ (err, granted) => {
+ client.unsubscribe('/orca_message_notifications', (err) => {
+ var queue = {
+ sync_api_version: 10,
+ max_deltas_able_to_process: 1000,
+ delta_batch_size: 500,
+ encoding: "JSON",
+ entity_fbid: ctx.userID,
+ initial_titan_sequence_id: lastSeqId,
+ device_params: null
+ };
+
+ client.publish('/messenger_sync_create_queue', JSON.stringify(queue), { qos: 0, retain: false })
+ });
+ });
+ });
+
+ client.on('message', function (topic, message, packet) {
+ var jsonMessage = JSON.parse(message);
+ if (topic === "/t_ms") {
+ if (jsonMessage.lastIssuedSeqId) {
+ lastSeqId = parseInt(jsonMessage.lastIssuedSeqId);
+ } else {
+ if (jsonMessage.deltas) {
+ lastSeqId = parseInt(jsonMessage.deltas[0].irisSeqId);
+ }
+ }
+
+ //If it contains more than 1 delta
+ for (var i in jsonMessage.deltas) {
+ var delta = jsonMessage.deltas[i];
+ parseDelta(ctx, globalCallback, { "delta": delta });
+ }
+ } else if (topic === "/thread_typing" || topic === "/orca_typing_notifications") {
+ var typ = {
+ type: "typ",
+ isTyping: !!jsonMessage.state,
+ from: jsonMessage.sender_fbid.toString(),
+ threadID: utils.formatID((jsonMessage.thread || jsonMessage.sender_fbid).toString())
+ }
+ globalCallback(null, typ);
+ } else if (topic === "/orca_presence") {
+ if (!ctx.globalOptions.updatePresence) {
+ for (var i in jsonMessage.list) {
+ var data = jsonMessage.list[i];
+ var userID = data["u"];
+
+ var presence = {
+ type: "presence",
+ userID: userID,
+ timestamp: data["l"],
+ statuses: data["p"]
+ };
+ globalCallback(null, presence);
+ }
+ }
+ }
+
+ });
+
+ client.on('close', function () {
+ // client.end();
+ });
+}
+
+function parseDelta(ctx, globalCallback, v) {
+ if (v.delta.class == "NewMessage") {
+ //Not tested for pages
+ if (ctx.globalOptions.pageID &&
+ ctx.globalOptions.pageID != v.queue
+ )
+ return;
+
+ (function resolveAttachmentUrl(i) {
+ if (i == v.delta.attachments.length) {
+ var fmtMsg;
+ try {
+ fmtMsg = utils.formatDeltaMessage(v);
+ } catch (err) {
+ return globalCallback({
+ error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
+ detail: err,
+ res: v,
+ type: "parse_error"
+ });
+ }
+ return !ctx.globalOptions.selfListen &&
+ fmtMsg.senderID === ctx.userID ?
+ undefined :
+ globalCallback(null, fmtMsg);
+ } else {
+ if (
+ v.delta.attachments[i].mercury.attach_type == "photo"
+ ) {
+ api.resolvePhotoUrl(
+ v.delta.attachments[i].fbid,
+ (err, url) => {
+ if (!err)
+ v.delta.attachments[
+ i
+ ].mercury.metadata.url = url;
+ return resolveAttachmentUrl(i + 1);
+ }
+ );
+ } else {
+ return resolveAttachmentUrl(i + 1);
+ }
+ }
+ })(0);
+ }
+
+ if (v.delta.class == "ClientPayload") {
+ var clientPayload = utils.decodeClientPayload(
+ v.delta.payload
+ );
+ if (clientPayload && clientPayload.deltas) {
+ for (var i in clientPayload.deltas) {
+ var delta = clientPayload.deltas[i];
+ if (delta.deltaMessageReaction && !!ctx.globalOptions.listenEvents) {
+ globalCallback(null, {
+ type: "message_reaction",
+ threadID: delta.deltaMessageReaction.threadKey
+ .threadFbId ?
+ delta.deltaMessageReaction.threadKey.threadFbId : delta.deltaMessageReaction.threadKey
+ .otherUserFbId,
+ messageID: delta.deltaMessageReaction.messageId,
+ reaction: delta.deltaMessageReaction.reaction,
+ senderID: delta.deltaMessageReaction.senderId,
+ userID: delta.deltaMessageReaction.userId,
+ timestamp: delta.deltaMessageReaction.timestamp
+ });
+ } else if (delta.deltaRecallMessageData && !!ctx.globalOptions.listenEvents) {
+ globalCallback(null, {
+ type: "message_unsend",
+ threadID: delta.deltaRecallMessageData.threadKey.threadFbId ?
+ delta.deltaRecallMessageData.threadKey.threadFbId : delta.deltaRecallMessageData.threadKey
+ .otherUserFbId,
+ messageID: delta.deltaRecallMessageData.messageID,
+ senderID: delta.deltaRecallMessageData.senderID,
+ deletionTimestamp: delta.deltaRecallMessageData.deletionTimestamp,
+ timestamp: delta.deltaRecallMessageData.timestamp
+ });
+ } else if (delta.deltaMessageReply) {
+ //Mention block - #1
+ var mdata =
+ delta.deltaMessageReply.message.data === undefined ? [] :
+ delta.deltaMessageReply.message.data.prng === undefined ? [] :
+ JSON.parse(delta.deltaMessageReply.message.data.prng);
+ var m_id = mdata.map(u => u.i);
+ var m_offset = mdata.map(u => u.o);
+ var m_length = mdata.map(u => u.l);
+
+ var mentions = {};
+
+ for (var i = 0; i < m_id.length; i++) {
+ mentions[m_id[i]] = delta.deltaMessageReply.message.body.substring(
+ m_offset[i],
+ m_offset[i] + m_length[i]
+ );
+ }
+ //Mention block - 1#
+ //Mention block - #2
+ var mdata =
+ delta.deltaMessageReply.repliedToMessage.data === undefined ? [] :
+ delta.deltaMessageReply.repliedToMessage.data.prng === undefined ? [] :
+ JSON.parse(delta.deltaMessageReply.repliedToMessage.data.prng);
+ var m_id = mdata.map(u => u.i);
+ var m_offset = mdata.map(u => u.o);
+ var m_length = mdata.map(u => u.l);
+
+ var rmentions = {};
+
+ for (var i = 0; i < m_id.length; i++) {
+ rmentions[m_id[i]] = delta.deltaMessageReply.repliedToMessage.body.substring(
+ m_offset[i],
+ m_offset[i] + m_length[i]
+ );
+ }
+ //Mention block - 2#
+
+ globalCallback(null, {
+ type: "message_reply",
+ threadID: delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId ?
+ delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.message.messageMetadata.threadKey
+ .otherUserFbId,
+ messageID: delta.deltaMessageReply.message.messageMetadata.messageId,
+ senderID: delta.deltaMessageReply.message.messageMetadata.actorFbId,
+ attachments: delta.deltaMessageReply.message.attachments.map(function (att) {
+ var mercury = JSON.parse(att.mercuryJSON);
+ Object.assign(att, mercury);
+ return att;
+ }).map(att => utils._formatAttachment(att)),
+ body: delta.deltaMessageReply.message.body || "",
+ isGroup: !!delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId,
+ mentions: mentions,
+ timestamp: delta.deltaMessageReply.repliedToMessage.messageMetadata.timestamp,
+ messageReply: {
+ threadID: delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId ?
+ delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey
+ .otherUserFbId,
+ messageID: delta.deltaMessageReply.repliedToMessage.messageMetadata.messageId,
+ senderID: delta.deltaMessageReply.repliedToMessage.messageMetadata.actorFbId,
+ attachments: delta.deltaMessageReply.repliedToMessage.attachments.map(function (att) {
+ var mercury = JSON.parse(att.mercuryJSON);
+ Object.assign(att, mercury);
+ return att;
+ }).map(att => utils._formatAttachment(att)),
+ body: delta.deltaMessageReply.repliedToMessage.body || "",
+ isGroup: !!delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId,
+ mentions: rmentions
+ }
+ });
+ }
+ }
+ return;
+ }
+ }
+
+ if (v.delta.class !== "NewMessage" &&
+ !ctx.globalOptions.listenEvents
+ )
+ return;
+ switch (v.delta.class) {
+ case "ReadReceipt":
+ var fmtMsg;
+ try {
+ fmtMsg = utils.formatDeltaReadReceipt(v.delta);
+ } catch (err) {
+ return globalCallback({
+ error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
+ detail: err,
+ res: v.delta,
+ type: "parse_error"
+ });
+ }
+ return globalCallback(null, fmtMsg);
+ case "AdminTextMessage":
+ switch (v.delta.type) {
+ case "change_thread_theme":
+ case "change_thread_nickname":
+ case "change_thread_icon":
+ break;
+ case "group_poll":
+ var fmtMsg;
+ try {
+ fmtMsg = utils.formatDeltaEvent(v.delta);
+ } catch (err) {
+ return globalCallback({
+ error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
+ detail: err,
+ res: v.delta,
+ type: "parse_error"
+ });
+ }
+ return globalCallback(null, fmtMsg);
+ break;
+ default:
+ return;
+ }
+ //For group images
+ case "ForcedFetch":
+ var mid = v.delta.messageId;
+ var tid = v.delta.threadKey.threadFbId.toString();
+ const form = {
+ "av": ctx.globalOptions.pageID,
+ "queries": JSON.stringify({
+ "o0": {
+ "doc_id": "1768656253222505",
+ "query_params": {
+ "thread_and_message_id": {
+ "thread_id": tid,
+ "message_id": mid,
+ }
+ }
+ }
+ })
+ };
+
+ defaultFuncs
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
+ .then((resData) => {
+ if (resData[resData.length - 1].error_results > 0) {
+ throw resData[0].o0.errors;
+ }
+
+ if (resData[resData.length - 1].successful_results === 0) {
+ throw { error: "forcedFetch: there was no successful_results", res: resData };
+ }
+
+ var fetchData = resData[0].o0.data.message;
+
+ globalCallback(null, {
+ type: "change_thread_image",
+ threadID: utils.formatID(tid.toString()),
+ snippet: fetchData.snippet,
+ timestamp: fetchData.timestamp_precise,
+ author: fetchData.message_sender.id,
+ image: {
+ attachmentID: fetchData.image_with_metadata.legacy_attachment_id,
+ width: fetchData.image_with_metadata.original_dimensions.x,
+ height: fetchData.image_with_metadata.original_dimensions.y,
+ url: fetchData.image_with_metadata.preview.uri
+ }
+ });
+ })
+ .catch((err) => {
+ log.error("forcedFetch", err);
+ });
+ break;
+ case "ThreadName":
+ case "ParticipantsAddedToGroupThread":
+ case "ParticipantLeftGroupThread":
+ var formattedEvent;
+ try {
+ formattedEvent = utils.formatDeltaEvent(v.delta);
+ } catch (err) {
+ return globalCallback({
+ error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
+ detail: err,
+ res: v.delta,
+ type: "parse_error"
+ });
+ }
+ return (!ctx.globalOptions.selfListen &&
+ formattedEvent.author.toString() === ctx.userID) ||
+ !ctx.loggedIn ?
+ undefined :
+ globalCallback(null, formattedEvent);
+ }
+}
+
+module.exports = function (df, api, ctx) {
+ var currentlyRunning = null;
+ var globalCallback = identity;
+ defaultFuncs = df;
+ return function (callback) {
+ globalCallback = callback;
+ const form = {
+ "av": ctx.globalOptions.pageID,
+ "queries": JSON.stringify({
+ "o0": {
+ "doc_id": "1349387578499440",
+ "query_params": {
+ "limit": 1,
+ "before": null,
+ "tags": ["INBOX"],
+ "includeDeliveryReceipts": false,
+ "includeSeqID": true
+ }
+ }
+ })
+ };
+
+ defaultFuncs
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
+ .then((resData) => {
+ if (resData[resData.length - 1].error_results > 0) {
+ throw resData[0].o0.errors;
+ }
+
+ if (resData[resData.length - 1].successful_results === 0) {
+ throw { error: "getSeqId: there was no successful_results", res: resData };
+ }
+
+ if (resData[0].o0.data.viewer.message_threads.sync_sequence_id) {
+ lastSeqId = resData[0].o0.data.viewer.message_threads.sync_sequence_id;
+ listenMqtt(ctx, globalCallback);
+ }
+
+ })
+ .catch((err) => {
+ log.error("getSeqId", err);
+ return callback(err);
+ });
+
+
+ //return function(){};
+ }
+};
+
diff --git a/src/markAsDelivered.js b/src/markAsDelivered.js
new file mode 100644
index 00000000..e4ba9c17
--- /dev/null
+++ b/src/markAsDelivered.js
@@ -0,0 +1,46 @@
+"use strict";
+
+var utils = require("../utils");
+var log = require("npmlog");
+
+module.exports = function(defaultFuncs, api, ctx) {
+
+ return function markAsDelivered(threadID, messageID, callback) {
+ if (!callback) {
+ callback = function() {};
+ }
+
+ if(!threadID || !messageID)
+ {
+ return callback("Error: messageID or threadID is not defined");
+ }
+
+ var form = {};
+
+ form["message_ids[0]"] = messageID;
+ form["thread_ids[" + threadID + "][0]"] = messageID;
+
+
+ console.log(form);
+
+ defaultFuncs
+ .post(
+ "https://www.facebook.com/ajax/mercury/delivery_receipts.php",
+ ctx.jar,
+ form
+ )
+ .then(utils.saveCookies(ctx.jar))
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
+ .then(function(resData) {
+ if (resData.error) {
+ throw resData;
+ }
+
+ return callback();
+ })
+ .catch(function(err) {
+ log.error("markAsDelivered", err);
+ return callback(err);
+ });
+ };
+};
diff --git a/src/mqtt/fbconnect.js b/src/mqtt/fbconnect.js
new file mode 100644
index 00000000..9dfd7be9
--- /dev/null
+++ b/src/mqtt/fbconnect.js
@@ -0,0 +1,139 @@
+'use strict'
+
+var mqtt = require('mqtt')
+var url = require('url')
+var xtend = require('xtend')
+var protocols = {}
+protocols.ws = require('./fbws')
+protocols.wss = require('./fbws')
+
+/**
+ * Parse the auth attribute and merge username and password in the options object.
+ *
+ * @param {Object} [opts] option object
+ */
+function parseAuthOptions (opts) {
+ var matches
+ if (opts.auth) {
+ matches = opts.auth.match(/^(.+):(.+)$/)
+ if (matches) {
+ opts.username = matches[1]
+ opts.password = matches[2]
+ } else {
+ opts.username = opts.auth
+ }
+ }
+}
+
+/**
+ * connect - connect to an MQTT broker.
+ *
+ * @param {String} [brokerUrl] - url of the broker, optional
+ * @param {Object} opts - see MqttClient#constructor
+ */
+function connect (brokerUrl, opts) {
+ if ((typeof brokerUrl === 'object') && !opts) {
+ opts = brokerUrl
+ brokerUrl = null
+ }
+
+ opts = opts || {}
+
+ if (brokerUrl) {
+ var parsed = url.parse(brokerUrl, true)
+ if (parsed.port != null) {
+ parsed.port = Number(parsed.port)
+ }
+
+ opts = xtend(parsed, opts)
+
+ if (opts.protocol === null) {
+ throw new Error('Missing protocol')
+ }
+ opts.protocol = opts.protocol.replace(/:$/, '')
+ }
+
+ // merge in the auth options if supplied
+ parseAuthOptions(opts)
+
+ // support clientId passed in the query string of the url
+ if (opts.query && typeof opts.query.clientId === 'string') {
+ opts.clientId = opts.query.clientId
+ }
+
+ if (opts.cert && opts.key) {
+ if (opts.protocol) {
+ if (['mqtts', 'wss', 'wxs', 'alis'].indexOf(opts.protocol) === -1) {
+ switch (opts.protocol) {
+ case 'mqtt':
+ opts.protocol = 'mqtts'
+ break
+ case 'ws':
+ opts.protocol = 'wss'
+ break
+ case 'wx':
+ opts.protocol = 'wxs'
+ break
+ case 'ali':
+ opts.protocol = 'alis'
+ break
+ default:
+ throw new Error('Unknown protocol for secure connection: "' + opts.protocol + '"!')
+ }
+ }
+ } else {
+ // don't know what protocol he want to use, mqtts or wss
+ throw new Error('Missing secure protocol key')
+ }
+ }
+
+ if (!protocols[opts.protocol]) {
+ var isSecure = ['mqtts', 'wss'].indexOf(opts.protocol) !== -1
+ opts.protocol = [
+ 'mqtt',
+ 'mqtts',
+ 'ws',
+ 'wss',
+ 'wx',
+ 'wxs',
+ 'ali',
+ 'alis'
+ ].filter(function (key, index) {
+ if (isSecure && index % 2 === 0) {
+ // Skip insecure protocols when requesting a secure one.
+ return false
+ }
+ return (typeof protocols[key] === 'function')
+ })[0]
+ }
+
+ if (opts.clean === false && !opts.clientId) {
+ throw new Error('Missing clientId for unclean clients')
+ }
+
+ if (opts.protocol) {
+ opts.defaultProtocol = opts.protocol
+ }
+
+ function wrapper (client) {
+ if (opts.servers) {
+ if (!client._reconnectCount || client._reconnectCount === opts.servers.length) {
+ client._reconnectCount = 0
+ }
+
+ opts.host = opts.servers[client._reconnectCount].host
+ opts.port = opts.servers[client._reconnectCount].port
+ opts.protocol = (!opts.servers[client._reconnectCount].protocol ? opts.defaultProtocol : opts.servers[client._reconnectCount].protocol)
+ opts.hostname = opts.host
+
+ client._reconnectCount++
+ }
+
+ return protocols[opts.protocol](client, opts)
+ }
+
+ return new mqtt.Client(wrapper, opts)
+}
+
+module.exports = connect
+module.exports.connect = connect
\ No newline at end of file
diff --git a/src/mqtt/fbws.js b/src/mqtt/fbws.js
new file mode 100644
index 00000000..20135ddc
--- /dev/null
+++ b/src/mqtt/fbws.js
@@ -0,0 +1,93 @@
+//From mqtt.js
+'use strict'
+
+var websocket = require('websocket-stream')
+var urlModule = require('url')
+var WSS_OPTIONS = [
+ 'rejectUnauthorized',
+ 'ca',
+ 'cert',
+ 'key',
+ 'pfx',
+ 'passphrase'
+]
+var IS_BROWSER = process.title === 'browser'
+
+function buildUrl (opts, client) {
+ var url = opts.protocol + '://' + opts.hostname + ':' + opts.port + opts.path
+ if (typeof (opts.transformWsUrl) === 'function') {
+ url = opts.transformWsUrl(url, opts, client)
+ }
+ return url
+}
+
+function setDefaultOpts (opts) {
+ if (!opts.hostname) {
+ opts.hostname = 'localhost'
+ }
+ if (!opts.port) {
+ if (opts.protocol === 'wss') {
+ opts.port = 443
+ } else {
+ opts.port = 80
+ }
+ }
+ if (!opts.path) {
+ opts.path = '/'
+ }
+
+ if (!opts.wsOptions) {
+ opts.wsOptions = {}
+ }
+ if (!IS_BROWSER && opts.protocol === 'wss') {
+ // Add cert/key/ca etc options
+ WSS_OPTIONS.forEach(function (prop) {
+ if (opts.hasOwnProperty(prop) && !opts.wsOptions.hasOwnProperty(prop)) {
+ opts.wsOptions[prop] = opts[prop]
+ }
+ })
+ }
+}
+
+function createWebSocket (client, opts) {
+ var websocketSubProtocol =
+ (opts.protocolId === 'MQIsdp') && (opts.protocolVersion === 3)
+ ? 'mqttv3.1'
+ : 'mqtt'
+
+ setDefaultOpts(opts)
+ var url = buildUrl(opts, client)
+ return websocket(url, undefined, opts.wsOptions)
+}
+
+function buildBuilder (client, opts) {
+ return createWebSocket(client, opts)
+}
+
+function buildBuilderBrowser (client, opts) {
+ if (!opts.hostname) {
+ opts.hostname = opts.host
+ }
+
+ if (!opts.hostname) {
+ // Throwing an error in a Web Worker if no `hostname` is given, because we
+ // can not determine the `hostname` automatically. If connecting to
+ // localhost, please supply the `hostname` as an argument.
+ if (typeof (document) === 'undefined') {
+ throw new Error('Could not determine host. Specify host manually.')
+ }
+ var parsed = urlModule.parse(document.URL)
+ opts.hostname = parsed.hostname
+
+ if (!opts.port) {
+ opts.port = parsed.port
+ }
+ }
+ return createWebSocket(client, opts)
+}
+
+if (IS_BROWSER) {
+ module.exports = buildBuilderBrowser
+} else {
+ module.exports = buildBuilder
+}
\ No newline at end of file
From 0d073dca32889e5907ff48e094c48a2bc378071d Mon Sep 17 00:00:00 2001
From: Hossam Mansour <6911267+7osCraft@users.noreply.github.com>
Date: Thu, 28 Nov 2019 02:46:30 +0200
Subject: [PATCH 02/10] Added docs for listenMqtt
---
DOCS.md | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/DOCS.md b/DOCS.md
index 39812cc6..ffd5ace9 100644
--- a/DOCS.md
+++ b/DOCS.md
@@ -25,6 +25,7 @@
* [`api.getUserInfo`](#getUserInfo)
* [`api.handleMessageRequest`](#handleMessageRequest)
* [`api.listen`](#listen)
+* [`api.listenMqtt`](#listenMqtt)
* [`api.logout`](#logout)
* [`api.markAsRead`](#markAsRead)
* [`api.markAsReadAll`](#markAsReadAll)
@@ -1308,6 +1309,20 @@ login({appState: JSON.parse(fs.readFileSync('appstate.json', 'utf8'))}, (err, ap
---------------------------------------
+
+### api.listenMqtt(callback) (Experimental)
+Same as [`api.listen`](#listen) but uses MQTT to recieve data.
+Will call `callback` when a new message is received on this account.
+By default this won't receive events (joining/leaving a chat, title change etc...) but it can be activated with `api.setOptions({listenEvents: true})`. This will by default ignore messages sent by the current account, you can enable listening to your own messages with `api.setOptions({selfListen: true})`.
+
+__Arguments__
+
+- `callback(error, message)`: A callback called every time the logged-in account receives a new message.
+
+Messages and Events are the same as [`api.listen`](#listen)
+
+---------------------------------------
+
### api.logout([callback])
From af94fe10fb9516ead49ddd8e7710886f93b0a7f8 Mon Sep 17 00:00:00 2001
From: Hossam Mohsen <6911267+7osCraft@users.noreply.github.com>
Date: Thu, 28 Nov 2019 02:56:05 +0200
Subject: [PATCH 03/10] Update listenMqtt.js
---
src/listenMqtt.js | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/src/listenMqtt.js b/src/listenMqtt.js
index 7d54c76f..d7b9137e 100644
--- a/src/listenMqtt.js
+++ b/src/listenMqtt.js
@@ -6,9 +6,7 @@ var log = require("npmlog");
var identity = function () { };
var lastSeqId = 0;
-var defaultFuncs = undefined;
-
-function listenMqtt(ctx, globalCallback) {
+function listenMqtt(ctx, globalCallback, defaultFuncs) {
var sessionID = Math.floor(Math.random() * 9007199254740991) + 1;
var username = {
u: ctx.userID,
@@ -90,7 +88,7 @@ function listenMqtt(ctx, globalCallback) {
//If it contains more than 1 delta
for (var i in jsonMessage.deltas) {
var delta = jsonMessage.deltas[i];
- parseDelta(ctx, globalCallback, { "delta": delta });
+ parseDelta(ctx, globalCallback, defaultFuncs, { "delta": delta });
}
} else if (topic === "/thread_typing" || topic === "/orca_typing_notifications") {
var typ = {
@@ -124,7 +122,7 @@ function listenMqtt(ctx, globalCallback) {
});
}
-function parseDelta(ctx, globalCallback, v) {
+function parseDelta(ctx, globalCallback, defaultFuncs, v) {
if (v.delta.class == "NewMessage") {
//Not tested for pages
if (ctx.globalOptions.pageID &&
@@ -394,7 +392,6 @@ function parseDelta(ctx, globalCallback, v) {
module.exports = function (df, api, ctx) {
var currentlyRunning = null;
var globalCallback = identity;
- defaultFuncs = df;
return function (callback) {
globalCallback = callback;
const form = {
@@ -427,7 +424,7 @@ module.exports = function (df, api, ctx) {
if (resData[0].o0.data.viewer.message_threads.sync_sequence_id) {
lastSeqId = resData[0].o0.data.viewer.message_threads.sync_sequence_id;
- listenMqtt(ctx, globalCallback);
+ listenMqtt(ctx, globalCallback, df);
}
})
From 89e10b0be71be29a76fdc503707148046ae3f338 Mon Sep 17 00:00:00 2001
From: Hossam Mansour <6911267+7osCraft@users.noreply.github.com>
Date: Thu, 28 Nov 2019 11:09:22 +0200
Subject: [PATCH 04/10] Fixed listenMqtt error
---
src/listenMqtt.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/listenMqtt.js b/src/listenMqtt.js
index d7b9137e..530975a6 100644
--- a/src/listenMqtt.js
+++ b/src/listenMqtt.js
@@ -389,7 +389,7 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
}
}
-module.exports = function (df, api, ctx) {
+module.exports = function (defaultFuncs, api, ctx) {
var currentlyRunning = null;
var globalCallback = identity;
return function (callback) {
@@ -424,7 +424,7 @@ module.exports = function (df, api, ctx) {
if (resData[0].o0.data.viewer.message_threads.sync_sequence_id) {
lastSeqId = resData[0].o0.data.viewer.message_threads.sync_sequence_id;
- listenMqtt(ctx, globalCallback, df);
+ listenMqtt(ctx, globalCallback, defaultFuncs);
}
})
From dd61e5dfc8110a26ca0de762ebd9860a5f0a45fd Mon Sep 17 00:00:00 2001
From: Hossam Mansour <6911267+7osCraft@users.noreply.github.com>
Date: Thu, 28 Nov 2019 22:21:42 +0200
Subject: [PATCH 05/10] Fixed indentation. Fixed some bugs too.
---
DOCS.md | 4 +-
src/listenMqtt.js | 867 +++++++++++++++++++++--------------------
src/markAsDelivered.js | 18 +-
src/mqtt/fbconnect.js | 6 +-
src/mqtt/fbws.js | 10 +-
5 files changed, 461 insertions(+), 444 deletions(-)
diff --git a/DOCS.md b/DOCS.md
index ffd5ace9..94546f56 100644
--- a/DOCS.md
+++ b/DOCS.md
@@ -1312,8 +1312,10 @@ login({appState: JSON.parse(fs.readFileSync('appstate.json', 'utf8'))}, (err, ap
### api.listenMqtt(callback) (Experimental)
Same as [`api.listen`](#listen) but uses MQTT to recieve data.
+
Will call `callback` when a new message is received on this account.
-By default this won't receive events (joining/leaving a chat, title change etc...) but it can be activated with `api.setOptions({listenEvents: true})`. This will by default ignore messages sent by the current account, you can enable listening to your own messages with `api.setOptions({selfListen: true})`.
+By default this won't receive events (joining/leaving a chat, title change etc...) but it can be activated with `api.setOptions({listenEvents: true})`. This will by default ignore messages sent by the current account, you can enable listening to your own messages with `api.setOptions({selfListen: true})`. This returns `stopListening` that will stop the `listen` loop and is guaranteed to prevent any future calls to the callback given to `listenMqtt`. An immediate call to `stopListening` when an error occurs will prevent the listen function to continue.
+
__Arguments__
diff --git a/src/listenMqtt.js b/src/listenMqtt.js
index 530975a6..1abcc3be 100644
--- a/src/listenMqtt.js
+++ b/src/listenMqtt.js
@@ -5,436 +5,453 @@ var log = require("npmlog");
var identity = function () { };
var lastSeqId = 0;
+var client = undefined;
function listenMqtt(ctx, globalCallback, defaultFuncs) {
- var sessionID = Math.floor(Math.random() * 9007199254740991) + 1;
- var username = {
- u: ctx.userID,
- s: sessionID,
- cp: 3,
- ecp: 10,
- chat_on: true,
- fg: false,
- d: utils.getGUID(),
- ct: "websocket",
- mqtt_sid: "",
- //App id from facebook
- aid: "219994525426954",
- st: [],
- pm: [],
- dc: "",
- no_auto_fg: true,
- gas: null
- };
- var cookies = ctx.jar.getCookies("https://www.facebook.com").join("; ");
-
- //Region could be changed for better ping.
- var host = 'wss://edge-chat.facebook.com/chat?region=atn&sid=' + sessionID;
-
- var options = {
- clientId: "mqttwsclient",
- protocolId: 'MQIsdp',
- protocolVersion: 3,
- username: JSON.stringify(username),
- wsOptions: {
- 'headers': {
- 'Cookie': cookies,
- 'Origin': 'https://www.facebook.com',
- 'User-Agent': ctx.globalOptions.userAgent,
- 'Referer': 'https://www.facebook.com',
- },
- origin: 'https://www.facebook.com',
- protocolVersion: 13
- }
- };
-
- var client = fbconnect.connect(host, options);
-
- client.on('error', function (err) {
- log.error(err);
- client.end();
- });
-
- client.on('connect', function () {
- client.subscribe(["/legacy_web", "/webrtc", "/br_sr", "/sr_res", "/t_ms", "/thread_typing", "/orca_typing_notifications", "/notify_disconnect", "/orca_presence"],
- (err, granted) => {
- client.unsubscribe('/orca_message_notifications', (err) => {
- var queue = {
- sync_api_version: 10,
- max_deltas_able_to_process: 1000,
- delta_batch_size: 500,
- encoding: "JSON",
- entity_fbid: ctx.userID,
- initial_titan_sequence_id: lastSeqId,
- device_params: null
- };
-
- client.publish('/messenger_sync_create_queue', JSON.stringify(queue), { qos: 0, retain: false })
- });
- });
- });
-
- client.on('message', function (topic, message, packet) {
- var jsonMessage = JSON.parse(message);
- if (topic === "/t_ms") {
- if (jsonMessage.lastIssuedSeqId) {
- lastSeqId = parseInt(jsonMessage.lastIssuedSeqId);
- } else {
- if (jsonMessage.deltas) {
- lastSeqId = parseInt(jsonMessage.deltas[0].irisSeqId);
- }
- }
-
- //If it contains more than 1 delta
- for (var i in jsonMessage.deltas) {
- var delta = jsonMessage.deltas[i];
- parseDelta(ctx, globalCallback, defaultFuncs, { "delta": delta });
- }
- } else if (topic === "/thread_typing" || topic === "/orca_typing_notifications") {
- var typ = {
- type: "typ",
- isTyping: !!jsonMessage.state,
- from: jsonMessage.sender_fbid.toString(),
- threadID: utils.formatID((jsonMessage.thread || jsonMessage.sender_fbid).toString())
- }
- globalCallback(null, typ);
- } else if (topic === "/orca_presence") {
- if (!ctx.globalOptions.updatePresence) {
- for (var i in jsonMessage.list) {
- var data = jsonMessage.list[i];
- var userID = data["u"];
-
- var presence = {
- type: "presence",
- userID: userID,
- timestamp: data["l"],
- statuses: data["p"]
- };
- globalCallback(null, presence);
- }
- }
- }
-
- });
-
- client.on('close', function () {
- // client.end();
- });
+ var sessionID = Math.floor(Math.random() * 9007199254740991) + 1;
+ var username = {
+ u: ctx.userID,
+ s: sessionID,
+ cp: 3,
+ ecp: 10,
+ chat_on: true,
+ fg: false,
+ d: utils.getGUID(),
+ ct: "websocket",
+ mqtt_sid: "",
+ //App id from facebook
+ aid: "219994525426954",
+ st: [],
+ pm: [],
+ dc: "",
+ no_auto_fg: true,
+ gas: null
+ };
+ var cookies = ctx.jar.getCookies("https://www.facebook.com").join("; ");
+
+ //Region could be changed for better ping.
+ var host = 'wss://edge-chat.facebook.com/chat?region=atn&sid=' + sessionID;
+
+ var options = {
+ clientId: "mqttwsclient",
+ protocolId: 'MQIsdp',
+ protocolVersion: 3,
+ username: JSON.stringify(username),
+ wsOptions: {
+ 'headers': {
+ 'Cookie': cookies,
+ 'Origin': 'https://www.facebook.com',
+ 'User-Agent': ctx.globalOptions.userAgent,
+ 'Referer': 'https://www.facebook.com',
+ },
+ origin: 'https://www.facebook.com',
+ protocolVersion: 13
+ }
+ };
+
+ client = fbconnect.connect(host, options);
+
+ client.on('error', function (err) {
+ log.error(err);
+ client.end();
+ });
+
+ client.on('connect', function () {
+ client.subscribe(["/legacy_web", "/webrtc", "/br_sr", "/sr_res", "/t_ms", "/thread_typing", "/orca_typing_notifications", "/notify_disconnect", "/orca_presence"],
+ (err, granted) => {
+ client.unsubscribe('/orca_message_notifications', (err) => {
+ var queue = {
+ sync_api_version: 10,
+ max_deltas_able_to_process: 1000,
+ delta_batch_size: 500,
+ encoding: "JSON",
+ entity_fbid: ctx.userID,
+ initial_titan_sequence_id: lastSeqId,
+ device_params: null
+ };
+
+ client.publish('/messenger_sync_create_queue', JSON.stringify(queue), { qos: 0, retain: false })
+ });
+ });
+ });
+
+ client.on('message', function (topic, message, packet) {
+ var jsonMessage = JSON.parse(message);
+ if (topic === "/t_ms") {
+ if (jsonMessage.lastIssuedSeqId) {
+ lastSeqId = parseInt(jsonMessage.lastIssuedSeqId);
+ } else {
+ if (jsonMessage.deltas) {
+ lastSeqId = parseInt(jsonMessage.deltas[0].irisSeqId);
+ }
+ }
+
+ //If it contains more than 1 delta
+ for (var i in jsonMessage.deltas) {
+ var delta = jsonMessage.deltas[i];
+ parseDelta(ctx, globalCallback, defaultFuncs, { "delta": delta });
+ }
+ } else if (topic === "/thread_typing" || topic === "/orca_typing_notifications") {
+ var typ = {
+ type: "typ",
+ isTyping: !!jsonMessage.state,
+ from: jsonMessage.sender_fbid.toString(),
+ threadID: utils.formatID((jsonMessage.thread || jsonMessage.sender_fbid).toString())
+ }
+ globalCallback(null, typ);
+ } else if (topic === "/orca_presence") {
+ if (!ctx.globalOptions.updatePresence) {
+ for (var i in jsonMessage.list) {
+ var data = jsonMessage.list[i];
+ var userID = data["u"];
+
+ var presence = {
+ type: "presence",
+ userID: userID,
+ timestamp: data["l"],
+ statuses: data["p"]
+ };
+ globalCallback(null, presence);
+ }
+ }
+ }
+
+ });
+
+ client.on('close', function () {
+ // client.end();
+ });
}
function parseDelta(ctx, globalCallback, defaultFuncs, v) {
- if (v.delta.class == "NewMessage") {
- //Not tested for pages
- if (ctx.globalOptions.pageID &&
- ctx.globalOptions.pageID != v.queue
- )
- return;
-
- (function resolveAttachmentUrl(i) {
- if (i == v.delta.attachments.length) {
- var fmtMsg;
- try {
- fmtMsg = utils.formatDeltaMessage(v);
- } catch (err) {
- return globalCallback({
- error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
- detail: err,
- res: v,
- type: "parse_error"
- });
- }
- return !ctx.globalOptions.selfListen &&
- fmtMsg.senderID === ctx.userID ?
- undefined :
- globalCallback(null, fmtMsg);
- } else {
- if (
- v.delta.attachments[i].mercury.attach_type == "photo"
- ) {
- api.resolvePhotoUrl(
- v.delta.attachments[i].fbid,
- (err, url) => {
- if (!err)
- v.delta.attachments[
- i
- ].mercury.metadata.url = url;
- return resolveAttachmentUrl(i + 1);
- }
- );
- } else {
- return resolveAttachmentUrl(i + 1);
- }
- }
- })(0);
- }
-
- if (v.delta.class == "ClientPayload") {
- var clientPayload = utils.decodeClientPayload(
- v.delta.payload
- );
- if (clientPayload && clientPayload.deltas) {
- for (var i in clientPayload.deltas) {
- var delta = clientPayload.deltas[i];
- if (delta.deltaMessageReaction && !!ctx.globalOptions.listenEvents) {
- globalCallback(null, {
- type: "message_reaction",
- threadID: delta.deltaMessageReaction.threadKey
- .threadFbId ?
- delta.deltaMessageReaction.threadKey.threadFbId : delta.deltaMessageReaction.threadKey
- .otherUserFbId,
- messageID: delta.deltaMessageReaction.messageId,
- reaction: delta.deltaMessageReaction.reaction,
- senderID: delta.deltaMessageReaction.senderId,
- userID: delta.deltaMessageReaction.userId,
- timestamp: delta.deltaMessageReaction.timestamp
- });
- } else if (delta.deltaRecallMessageData && !!ctx.globalOptions.listenEvents) {
- globalCallback(null, {
- type: "message_unsend",
- threadID: delta.deltaRecallMessageData.threadKey.threadFbId ?
- delta.deltaRecallMessageData.threadKey.threadFbId : delta.deltaRecallMessageData.threadKey
- .otherUserFbId,
- messageID: delta.deltaRecallMessageData.messageID,
- senderID: delta.deltaRecallMessageData.senderID,
- deletionTimestamp: delta.deltaRecallMessageData.deletionTimestamp,
- timestamp: delta.deltaRecallMessageData.timestamp
- });
- } else if (delta.deltaMessageReply) {
- //Mention block - #1
- var mdata =
- delta.deltaMessageReply.message.data === undefined ? [] :
- delta.deltaMessageReply.message.data.prng === undefined ? [] :
- JSON.parse(delta.deltaMessageReply.message.data.prng);
- var m_id = mdata.map(u => u.i);
- var m_offset = mdata.map(u => u.o);
- var m_length = mdata.map(u => u.l);
-
- var mentions = {};
-
- for (var i = 0; i < m_id.length; i++) {
- mentions[m_id[i]] = delta.deltaMessageReply.message.body.substring(
- m_offset[i],
- m_offset[i] + m_length[i]
- );
- }
- //Mention block - 1#
- //Mention block - #2
- var mdata =
- delta.deltaMessageReply.repliedToMessage.data === undefined ? [] :
- delta.deltaMessageReply.repliedToMessage.data.prng === undefined ? [] :
- JSON.parse(delta.deltaMessageReply.repliedToMessage.data.prng);
- var m_id = mdata.map(u => u.i);
- var m_offset = mdata.map(u => u.o);
- var m_length = mdata.map(u => u.l);
-
- var rmentions = {};
-
- for (var i = 0; i < m_id.length; i++) {
- rmentions[m_id[i]] = delta.deltaMessageReply.repliedToMessage.body.substring(
- m_offset[i],
- m_offset[i] + m_length[i]
- );
- }
- //Mention block - 2#
-
- globalCallback(null, {
- type: "message_reply",
- threadID: delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId ?
- delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.message.messageMetadata.threadKey
- .otherUserFbId,
- messageID: delta.deltaMessageReply.message.messageMetadata.messageId,
- senderID: delta.deltaMessageReply.message.messageMetadata.actorFbId,
- attachments: delta.deltaMessageReply.message.attachments.map(function (att) {
- var mercury = JSON.parse(att.mercuryJSON);
- Object.assign(att, mercury);
- return att;
- }).map(att => utils._formatAttachment(att)),
- body: delta.deltaMessageReply.message.body || "",
- isGroup: !!delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId,
- mentions: mentions,
- timestamp: delta.deltaMessageReply.repliedToMessage.messageMetadata.timestamp,
- messageReply: {
- threadID: delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId ?
- delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey
- .otherUserFbId,
- messageID: delta.deltaMessageReply.repliedToMessage.messageMetadata.messageId,
- senderID: delta.deltaMessageReply.repliedToMessage.messageMetadata.actorFbId,
- attachments: delta.deltaMessageReply.repliedToMessage.attachments.map(function (att) {
- var mercury = JSON.parse(att.mercuryJSON);
- Object.assign(att, mercury);
- return att;
- }).map(att => utils._formatAttachment(att)),
- body: delta.deltaMessageReply.repliedToMessage.body || "",
- isGroup: !!delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId,
- mentions: rmentions
- }
- });
- }
- }
- return;
- }
- }
-
- if (v.delta.class !== "NewMessage" &&
- !ctx.globalOptions.listenEvents
- )
- return;
- switch (v.delta.class) {
- case "ReadReceipt":
- var fmtMsg;
- try {
- fmtMsg = utils.formatDeltaReadReceipt(v.delta);
- } catch (err) {
- return globalCallback({
- error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
- detail: err,
- res: v.delta,
- type: "parse_error"
- });
- }
- return globalCallback(null, fmtMsg);
- case "AdminTextMessage":
- switch (v.delta.type) {
- case "change_thread_theme":
- case "change_thread_nickname":
- case "change_thread_icon":
- break;
- case "group_poll":
- var fmtMsg;
- try {
- fmtMsg = utils.formatDeltaEvent(v.delta);
- } catch (err) {
- return globalCallback({
- error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
- detail: err,
- res: v.delta,
- type: "parse_error"
- });
- }
- return globalCallback(null, fmtMsg);
- break;
- default:
- return;
- }
- //For group images
- case "ForcedFetch":
- var mid = v.delta.messageId;
- var tid = v.delta.threadKey.threadFbId.toString();
- const form = {
- "av": ctx.globalOptions.pageID,
- "queries": JSON.stringify({
- "o0": {
- "doc_id": "1768656253222505",
- "query_params": {
- "thread_and_message_id": {
- "thread_id": tid,
- "message_id": mid,
- }
- }
- }
- })
- };
-
- defaultFuncs
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
- .then((resData) => {
- if (resData[resData.length - 1].error_results > 0) {
- throw resData[0].o0.errors;
- }
-
- if (resData[resData.length - 1].successful_results === 0) {
- throw { error: "forcedFetch: there was no successful_results", res: resData };
- }
-
- var fetchData = resData[0].o0.data.message;
-
- globalCallback(null, {
- type: "change_thread_image",
- threadID: utils.formatID(tid.toString()),
- snippet: fetchData.snippet,
- timestamp: fetchData.timestamp_precise,
- author: fetchData.message_sender.id,
- image: {
- attachmentID: fetchData.image_with_metadata.legacy_attachment_id,
- width: fetchData.image_with_metadata.original_dimensions.x,
- height: fetchData.image_with_metadata.original_dimensions.y,
- url: fetchData.image_with_metadata.preview.uri
- }
- });
- })
- .catch((err) => {
- log.error("forcedFetch", err);
- });
- break;
- case "ThreadName":
- case "ParticipantsAddedToGroupThread":
- case "ParticipantLeftGroupThread":
- var formattedEvent;
- try {
- formattedEvent = utils.formatDeltaEvent(v.delta);
- } catch (err) {
- return globalCallback({
- error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
- detail: err,
- res: v.delta,
- type: "parse_error"
- });
- }
- return (!ctx.globalOptions.selfListen &&
- formattedEvent.author.toString() === ctx.userID) ||
- !ctx.loggedIn ?
- undefined :
- globalCallback(null, formattedEvent);
- }
+ console.log(JSON.stringify(v, null, 4));
+ if (v.delta.class == "NewMessage") {
+ //Not tested for pages
+ if (ctx.globalOptions.pageID &&
+ ctx.globalOptions.pageID != v.queue
+ )
+ return;
+
+ (function resolveAttachmentUrl(i) {
+ if (i == v.delta.attachments.length) {
+ var fmtMsg;
+ try {
+ fmtMsg = utils.formatDeltaMessage(v);
+ } catch (err) {
+ return globalCallback({
+ error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
+ detail: err,
+ res: v,
+ type: "parse_error"
+ });
+ }
+ return !ctx.globalOptions.selfListen &&
+ fmtMsg.senderID === ctx.userID ?
+ undefined :
+ globalCallback(null, fmtMsg);
+ } else {
+ if (
+ v.delta.attachments[i].mercury.attach_type == "photo"
+ ) {
+ api.resolvePhotoUrl(
+ v.delta.attachments[i].fbid,
+ (err, url) => {
+ if (!err)
+ v.delta.attachments[
+ i
+ ].mercury.metadata.url = url;
+ return resolveAttachmentUrl(i + 1);
+ }
+ );
+ } else {
+ return resolveAttachmentUrl(i + 1);
+ }
+ }
+ })(0);
+ }
+
+ if (v.delta.class == "ClientPayload") {
+ var clientPayload = utils.decodeClientPayload(
+ v.delta.payload
+ );
+ if (clientPayload && clientPayload.deltas) {
+ for (var i in clientPayload.deltas) {
+ var delta = clientPayload.deltas[i];
+ console.log(JSON.stringify(delta, null, 4));
+ if (delta.deltaMessageReaction && !!ctx.globalOptions.listenEvents) {
+ globalCallback(null, {
+ type: "message_reaction",
+ threadID: delta.deltaMessageReaction.threadKey
+ .threadFbId ?
+ delta.deltaMessageReaction.threadKey.threadFbId : delta.deltaMessageReaction.threadKey
+ .otherUserFbId,
+ messageID: delta.deltaMessageReaction.messageId,
+ reaction: delta.deltaMessageReaction.reaction,
+ senderID: delta.deltaMessageReaction.senderId,
+ userID: delta.deltaMessageReaction.userId
+ });
+ } else if (delta.deltaRecallMessageData && !!ctx.globalOptions.listenEvents) {
+ globalCallback(null, {
+ type: "message_unsend",
+ threadID: delta.deltaRecallMessageData.threadKey.threadFbId ?
+ delta.deltaRecallMessageData.threadKey.threadFbId : delta.deltaRecallMessageData.threadKey
+ .otherUserFbId,
+ messageID: delta.deltaRecallMessageData.messageID,
+ senderID: delta.deltaRecallMessageData.senderID,
+ deletionTimestamp: delta.deltaRecallMessageData.deletionTimestamp,
+ timestamp: delta.deltaRecallMessageData.timestamp
+ });
+ } else if (delta.deltaMessageReply) {
+ //Mention block - #1
+ var mdata =
+ delta.deltaMessageReply.message === undefined ? [] :
+ delta.deltaMessageReply.message.data === undefined ? [] :
+ delta.deltaMessageReply.message.data.prng === undefined ? [] :
+ JSON.parse(delta.deltaMessageReply.message.data.prng);
+ var m_id = mdata.map(u => u.i);
+ var m_offset = mdata.map(u => u.o);
+ var m_length = mdata.map(u => u.l);
+
+ var mentions = {};
+
+ for (var i = 0; i < m_id.length; i++) {
+ mentions[m_id[i]] = delta.deltaMessageReply.message.body.substring(
+ m_offset[i],
+ m_offset[i] + m_length[i]
+ );
+ }
+ //Mention block - 1#
+ //Mention block - #2
+ var mdata =
+ delta.deltaMessageReply.repliedToMessage === undefined ? [] :
+ delta.deltaMessageReply.repliedToMessage.data === undefined ? [] :
+ delta.deltaMessageReply.repliedToMessage.data.prng === undefined ? [] :
+ JSON.parse(delta.deltaMessageReply.repliedToMessage.data.prng);
+ var m_id = mdata.map(u => u.i);
+ var m_offset = mdata.map(u => u.o);
+ var m_length = mdata.map(u => u.l);
+
+ var rmentions = {};
+
+ for (var i = 0; i < m_id.length; i++) {
+ rmentions[m_id[i]] = delta.deltaMessageReply.repliedToMessage.body.substring(
+ m_offset[i],
+ m_offset[i] + m_length[i]
+ );
+ }
+ //Mention block - 2#
+
+ var callbackToReturn = {
+ type: "message_reply",
+ threadID: delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId ?
+ delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.message.messageMetadata.threadKey
+ .otherUserFbId,
+ messageID: delta.deltaMessageReply.message.messageMetadata.messageId,
+ senderID: delta.deltaMessageReply.message.messageMetadata.actorFbId,
+ attachments: delta.deltaMessageReply.message.attachments.map(function (att) {
+ var mercury = JSON.parse(att.mercuryJSON);
+ Object.assign(att, mercury);
+ return att;
+ }).map(att => utils._formatAttachment(att)),
+ body: delta.deltaMessageReply.message.body || "",
+ isGroup: !!delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId,
+ mentions: mentions,
+ timestamp: delta.deltaMessageReply.message.messageMetadata.timestamp,
+
+ };
+
+ if (delta.deltaMessageReply.repliedToMessage) {
+ callbackToReturn.messageReply = {
+ threadID: delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId ?
+ delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey
+ .otherUserFbId,
+ messageID: delta.deltaMessageReply.repliedToMessage.messageMetadata.messageId,
+ senderID: delta.deltaMessageReply.repliedToMessage.messageMetadata.actorFbId,
+ attachments: delta.deltaMessageReply.repliedToMessage.attachments.map(function (att) {
+ var mercury = JSON.parse(att.mercuryJSON);
+ Object.assign(att, mercury);
+ return att;
+ }).map(att => utils._formatAttachment(att)),
+ body: delta.deltaMessageReply.repliedToMessage.body || "",
+ isGroup: !!delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId,
+ mentions: rmentions,
+ timestamp: delta.deltaMessageReply.repliedToMessage.messageMetadata.timestamp,
+ };
+ }
+
+ globalCallback(null, callbackToReturn);
+ }
+ }
+ return;
+ }
+ }
+
+ if (v.delta.class !== "NewMessage" &&
+ !ctx.globalOptions.listenEvents
+ )
+ return;
+ switch (v.delta.class) {
+ case "ReadReceipt":
+ var fmtMsg;
+ try {
+ fmtMsg = utils.formatDeltaReadReceipt(v.delta);
+ } catch (err) {
+ return globalCallback({
+ error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
+ detail: err,
+ res: v.delta,
+ type: "parse_error"
+ });
+ }
+ return globalCallback(null, fmtMsg);
+ case "AdminTextMessage":
+ switch (v.delta.type) {
+ case "change_thread_theme":
+ case "change_thread_nickname":
+ case "change_thread_icon":
+ break;
+ case "group_poll":
+ var fmtMsg;
+ try {
+ fmtMsg = utils.formatDeltaEvent(v.delta);
+ } catch (err) {
+ return globalCallback({
+ error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
+ detail: err,
+ res: v.delta,
+ type: "parse_error"
+ });
+ }
+ return globalCallback(null, fmtMsg);
+ break;
+ default:
+ return;
+ }
+ //For group images
+ case "ForcedFetch":
+ var mid = v.delta.messageId;
+ var tid = v.delta.threadKey.threadFbId.toString();
+ const form = {
+ "av": ctx.globalOptions.pageID,
+ "queries": JSON.stringify({
+ "o0": {
+ "doc_id": "1768656253222505",
+ "query_params": {
+ "thread_and_message_id": {
+ "thread_id": tid,
+ "message_id": mid,
+ }
+ }
+ }
+ })
+ };
+
+ defaultFuncs
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
+ .then((resData) => {
+ if (resData[resData.length - 1].error_results > 0) {
+ throw resData[0].o0.errors;
+ }
+
+ if (resData[resData.length - 1].successful_results === 0) {
+ throw { error: "forcedFetch: there was no successful_results", res: resData };
+ }
+
+ var fetchData = resData[0].o0.data.message;
+
+ (!ctx.globalOptions.selfListen &&
+ formattedEvent.author.toString() === ctx.userID) ||
+ !ctx.loggedIn ?
+ undefined :
+ globalCallback(null, {
+ type: "change_thread_image",
+ threadID: utils.formatID(tid.toString()),
+ snippet: fetchData.snippet,
+ timestamp: fetchData.timestamp_precise,
+ author: fetchData.message_sender.id,
+ image: {
+ attachmentID: fetchData.image_with_metadata.legacy_attachment_id,
+ width: fetchData.image_with_metadata.original_dimensions.x,
+ height: fetchData.image_with_metadata.original_dimensions.y,
+ url: fetchData.image_with_metadata.preview.uri
+ }
+ });
+ })
+ .catch((err) => {
+ log.error("forcedFetch", err);
+ });
+ break;
+ case "ThreadName":
+ case "ParticipantsAddedToGroupThread":
+ case "ParticipantLeftGroupThread":
+ var formattedEvent;
+ try {
+ formattedEvent = utils.formatDeltaEvent(v.delta);
+ } catch (err) {
+ return globalCallback({
+ error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
+ detail: err,
+ res: v.delta,
+ type: "parse_error"
+ });
+ }
+ return (!ctx.globalOptions.selfListen &&
+ formattedEvent.author.toString() === ctx.userID) ||
+ !ctx.loggedIn ?
+ undefined :
+ globalCallback(null, formattedEvent);
+ }
}
module.exports = function (defaultFuncs, api, ctx) {
- var currentlyRunning = null;
- var globalCallback = identity;
- return function (callback) {
- globalCallback = callback;
- const form = {
- "av": ctx.globalOptions.pageID,
- "queries": JSON.stringify({
- "o0": {
- "doc_id": "1349387578499440",
- "query_params": {
- "limit": 1,
- "before": null,
- "tags": ["INBOX"],
- "includeDeliveryReceipts": false,
- "includeSeqID": true
- }
- }
- })
- };
-
- defaultFuncs
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
- .then((resData) => {
- if (resData[resData.length - 1].error_results > 0) {
- throw resData[0].o0.errors;
- }
-
- if (resData[resData.length - 1].successful_results === 0) {
- throw { error: "getSeqId: there was no successful_results", res: resData };
- }
-
- if (resData[0].o0.data.viewer.message_threads.sync_sequence_id) {
- lastSeqId = resData[0].o0.data.viewer.message_threads.sync_sequence_id;
- listenMqtt(ctx, globalCallback, defaultFuncs);
- }
-
- })
- .catch((err) => {
- log.error("getSeqId", err);
- return callback(err);
- });
-
-
- //return function(){};
- }
-};
-
+ var globalCallback = identity;
+ return function (callback) {
+ globalCallback = callback;
+ const form = {
+ "av": ctx.globalOptions.pageID,
+ "queries": JSON.stringify({
+ "o0": {
+ "doc_id": "1349387578499440",
+ "query_params": {
+ "limit": 1,
+ "before": null,
+ "tags": ["INBOX"],
+ "includeDeliveryReceipts": false,
+ "includeSeqID": true
+ }
+ }
+ })
+ };
+
+ defaultFuncs
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
+ .then((resData) => {
+ if (resData[resData.length - 1].error_results > 0) {
+ throw resData[0].o0.errors;
+ }
+
+ if (resData[resData.length - 1].successful_results === 0) {
+ throw { error: "getSeqId: there was no successful_results", res: resData };
+ }
+
+ if (resData[0].o0.data.viewer.message_threads.sync_sequence_id) {
+ lastSeqId = resData[0].o0.data.viewer.message_threads.sync_sequence_id;
+ listenMqtt(ctx, globalCallback, defaultFuncs);
+ }
+
+ })
+ .catch((err) => {
+ log.error("getSeqId", err);
+ return callback(err);
+ });
+
+ var stopListening = function () {
+ globalCallback = identity;
+ client.end();
+ };
+
+ return stopListening;
+ }
+};
\ No newline at end of file
diff --git a/src/markAsDelivered.js b/src/markAsDelivered.js
index e4ba9c17..bfa3d9e4 100644
--- a/src/markAsDelivered.js
+++ b/src/markAsDelivered.js
@@ -3,17 +3,15 @@
var utils = require("../utils");
var log = require("npmlog");
-module.exports = function(defaultFuncs, api, ctx) {
-
+module.exports = function (defaultFuncs, api, ctx) {
return function markAsDelivered(threadID, messageID, callback) {
if (!callback) {
- callback = function() {};
+ callback = function () { };
}
- if(!threadID || !messageID)
- {
- return callback("Error: messageID or threadID is not defined");
- }
+ if (!threadID || !messageID) {
+ return callback("Error: messageID or threadID is not defined");
+ }
var form = {};
@@ -21,7 +19,7 @@ module.exports = function(defaultFuncs, api, ctx) {
form["thread_ids[" + threadID + "][0]"] = messageID;
- console.log(form);
+ console.log(form);
defaultFuncs
.post(
@@ -31,14 +29,14 @@ module.exports = function(defaultFuncs, api, ctx) {
)
.then(utils.saveCookies(ctx.jar))
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
- .then(function(resData) {
+ .then(function (resData) {
if (resData.error) {
throw resData;
}
return callback();
})
- .catch(function(err) {
+ .catch(function (err) {
log.error("markAsDelivered", err);
return callback(err);
});
diff --git a/src/mqtt/fbconnect.js b/src/mqtt/fbconnect.js
index 9dfd7be9..5eb84f22 100644
--- a/src/mqtt/fbconnect.js
+++ b/src/mqtt/fbconnect.js
@@ -12,7 +12,7 @@ protocols.wss = require('./fbws')
*
* @param {Object} [opts] option object
*/
-function parseAuthOptions (opts) {
+function parseAuthOptions(opts) {
var matches
if (opts.auth) {
matches = opts.auth.match(/^(.+):(.+)$/)
@@ -31,7 +31,7 @@ function parseAuthOptions (opts) {
* @param {String} [brokerUrl] - url of the broker, optional
* @param {Object} opts - see MqttClient#constructor
*/
-function connect (brokerUrl, opts) {
+function connect(brokerUrl, opts) {
if ((typeof brokerUrl === 'object') && !opts) {
opts = brokerUrl
brokerUrl = null
@@ -115,7 +115,7 @@ function connect (brokerUrl, opts) {
opts.defaultProtocol = opts.protocol
}
- function wrapper (client) {
+ function wrapper(client) {
if (opts.servers) {
if (!client._reconnectCount || client._reconnectCount === opts.servers.length) {
client._reconnectCount = 0
diff --git a/src/mqtt/fbws.js b/src/mqtt/fbws.js
index 20135ddc..5704a132 100644
--- a/src/mqtt/fbws.js
+++ b/src/mqtt/fbws.js
@@ -13,7 +13,7 @@ var WSS_OPTIONS = [
]
var IS_BROWSER = process.title === 'browser'
-function buildUrl (opts, client) {
+function buildUrl(opts, client) {
var url = opts.protocol + '://' + opts.hostname + ':' + opts.port + opts.path
if (typeof (opts.transformWsUrl) === 'function') {
url = opts.transformWsUrl(url, opts, client)
@@ -21,7 +21,7 @@ function buildUrl (opts, client) {
return url
}
-function setDefaultOpts (opts) {
+function setDefaultOpts(opts) {
if (!opts.hostname) {
opts.hostname = 'localhost'
}
@@ -49,7 +49,7 @@ function setDefaultOpts (opts) {
}
}
-function createWebSocket (client, opts) {
+function createWebSocket(client, opts) {
var websocketSubProtocol =
(opts.protocolId === 'MQIsdp') && (opts.protocolVersion === 3)
? 'mqttv3.1'
@@ -60,11 +60,11 @@ function createWebSocket (client, opts) {
return websocket(url, undefined, opts.wsOptions)
}
-function buildBuilder (client, opts) {
+function buildBuilder(client, opts) {
return createWebSocket(client, opts)
}
-function buildBuilderBrowser (client, opts) {
+function buildBuilderBrowser(client, opts) {
if (!opts.hostname) {
opts.hostname = opts.host
}
From 8afbee70d47064310068d76fd346c3ecaaa76243 Mon Sep 17 00:00:00 2001
From: Hossam Mansour <6911267+7osCraft@users.noreply.github.com>
Date: Thu, 28 Nov 2019 22:39:12 +0200
Subject: [PATCH 06/10] Fixed a mistake
---
src/listenMqtt.js | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/listenMqtt.js b/src/listenMqtt.js
index 1abcc3be..d860ce24 100644
--- a/src/listenMqtt.js
+++ b/src/listenMqtt.js
@@ -124,7 +124,6 @@ function listenMqtt(ctx, globalCallback, defaultFuncs) {
}
function parseDelta(ctx, globalCallback, defaultFuncs, v) {
- console.log(JSON.stringify(v, null, 4));
if (v.delta.class == "NewMessage") {
//Not tested for pages
if (ctx.globalOptions.pageID &&
@@ -177,7 +176,6 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
if (clientPayload && clientPayload.deltas) {
for (var i in clientPayload.deltas) {
var delta = clientPayload.deltas[i];
- console.log(JSON.stringify(delta, null, 4));
if (delta.deltaMessageReaction && !!ctx.globalOptions.listenEvents) {
globalCallback(null, {
type: "message_reaction",
@@ -428,7 +426,7 @@ module.exports = function (defaultFuncs, api, ctx) {
.post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
.then((resData) => {
- if (resData[resData.length - 1].error_results > 0) {
+ if (resData && resData[resData.length - 1].error_results > 0) {
throw resData[0].o0.errors;
}
From aa8a43b5a4daac223498e96321ebb607ce31858f Mon Sep 17 00:00:00 2001
From: Hossam Mansour <6911267+7osCraft@users.noreply.github.com>
Date: Sat, 30 Nov 2019 00:07:17 +0200
Subject: [PATCH 07/10] Fixed missing break.
---
src/listenMqtt.js | 1 +
src/markAsDelivered.js | 3 ---
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/listenMqtt.js b/src/listenMqtt.js
index d860ce24..dd06108e 100644
--- a/src/listenMqtt.js
+++ b/src/listenMqtt.js
@@ -325,6 +325,7 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
default:
return;
}
+ break;
//For group images
case "ForcedFetch":
var mid = v.delta.messageId;
diff --git a/src/markAsDelivered.js b/src/markAsDelivered.js
index bfa3d9e4..279a7524 100644
--- a/src/markAsDelivered.js
+++ b/src/markAsDelivered.js
@@ -18,9 +18,6 @@ module.exports = function (defaultFuncs, api, ctx) {
form["message_ids[0]"] = messageID;
form["thread_ids[" + threadID + "][0]"] = messageID;
-
- console.log(form);
-
defaultFuncs
.post(
"https://www.facebook.com/ajax/mercury/delivery_receipts.php",
From ca3c5544c9dc4a2c83de09edbf55a0db8de186b3 Mon Sep 17 00:00:00 2001
From: Hossam Mansour <6911267+7osCraft@users.noreply.github.com>
Date: Sat, 30 Nov 2019 23:18:33 +0200
Subject: [PATCH 08/10] Some refactoring and fixing
---
index.js | 3 +-
src/listenMqtt.js | 102 ++++++++++++++++++++++-------------------
src/markAsDelivered.js | 41 -----------------
src/mqtt/fbconnect.js | 15 ++----
src/mqtt/fbws.js | 34 ++------------
5 files changed, 61 insertions(+), 134 deletions(-)
delete mode 100644 src/markAsDelivered.js
diff --git a/index.js b/index.js
index 5bbf365d..d0013b1c 100644
--- a/index.js
+++ b/index.js
@@ -99,9 +99,8 @@ function buildAPI(globalOptions, html, jar) {
'getUserInfo',
'handleMessageRequest',
'listen',
- 'listenMqtt',
+ 'listenMqtt',
'logout',
- 'markAsDelivered',
'markAsRead',
'markAsReadAll',
'muteThread',
diff --git a/src/listenMqtt.js b/src/listenMqtt.js
index dd06108e..81d2191c 100644
--- a/src/listenMqtt.js
+++ b/src/listenMqtt.js
@@ -330,56 +330,62 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
case "ForcedFetch":
var mid = v.delta.messageId;
var tid = v.delta.threadKey.threadFbId.toString();
- const form = {
- "av": ctx.globalOptions.pageID,
- "queries": JSON.stringify({
- "o0": {
- "doc_id": "1768656253222505",
- "query_params": {
- "thread_and_message_id": {
- "thread_id": tid,
- "message_id": mid,
+ if(mid && tid)
+ {
+ const form = {
+ "av": ctx.globalOptions.pageID,
+ "queries": JSON.stringify({
+ "o0": {
+ "doc_id": "1768656253222505",
+ "query_params": {
+ "thread_and_message_id": {
+ "thread_id": tid,
+ "message_id": mid,
+ }
}
}
- }
- })
- };
-
- defaultFuncs
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
- .then((resData) => {
- if (resData[resData.length - 1].error_results > 0) {
- throw resData[0].o0.errors;
- }
-
- if (resData[resData.length - 1].successful_results === 0) {
- throw { error: "forcedFetch: there was no successful_results", res: resData };
- }
-
- var fetchData = resData[0].o0.data.message;
-
- (!ctx.globalOptions.selfListen &&
- formattedEvent.author.toString() === ctx.userID) ||
- !ctx.loggedIn ?
- undefined :
- globalCallback(null, {
- type: "change_thread_image",
- threadID: utils.formatID(tid.toString()),
- snippet: fetchData.snippet,
- timestamp: fetchData.timestamp_precise,
- author: fetchData.message_sender.id,
- image: {
- attachmentID: fetchData.image_with_metadata.legacy_attachment_id,
- width: fetchData.image_with_metadata.original_dimensions.x,
- height: fetchData.image_with_metadata.original_dimensions.y,
- url: fetchData.image_with_metadata.preview.uri
- }
- });
- })
- .catch((err) => {
- log.error("forcedFetch", err);
- });
+ })
+ };
+
+ defaultFuncs
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
+ .then((resData) => {
+ if (resData[resData.length - 1].error_results > 0) {
+ throw resData[0].o0.errors;
+ }
+
+ if (resData[resData.length - 1].successful_results === 0) {
+ throw { error: "forcedFetch: there was no successful_results", res: resData };
+ }
+
+ var fetchData = resData[0].o0.data.message;
+
+ if(fetchData && fetchData.__typename === "ThreadImageMessage")
+ {
+ (!ctx.globalOptions.selfListen &&
+ formattedEvent.author.toString() === ctx.userID) ||
+ !ctx.loggedIn ?
+ undefined :
+ globalCallback(null, {
+ type: "change_thread_image",
+ threadID: utils.formatID(tid.toString()),
+ snippet: fetchData.snippet,
+ timestamp: fetchData.timestamp_precise,
+ author: fetchData.message_sender.id,
+ image: {
+ attachmentID: fetchData.image_with_metadata.legacy_attachment_id,
+ width: fetchData.image_with_metadata.original_dimensions.x,
+ height: fetchData.image_with_metadata.original_dimensions.y,
+ url: fetchData.image_with_metadata.preview.uri
+ }
+ });
+ }
+ })
+ .catch((err) => {
+ log.error("forcedFetch", err);
+ });
+ }
break;
case "ThreadName":
case "ParticipantsAddedToGroupThread":
diff --git a/src/markAsDelivered.js b/src/markAsDelivered.js
deleted file mode 100644
index 279a7524..00000000
--- a/src/markAsDelivered.js
+++ /dev/null
@@ -1,41 +0,0 @@
-"use strict";
-
-var utils = require("../utils");
-var log = require("npmlog");
-
-module.exports = function (defaultFuncs, api, ctx) {
- return function markAsDelivered(threadID, messageID, callback) {
- if (!callback) {
- callback = function () { };
- }
-
- if (!threadID || !messageID) {
- return callback("Error: messageID or threadID is not defined");
- }
-
- var form = {};
-
- form["message_ids[0]"] = messageID;
- form["thread_ids[" + threadID + "][0]"] = messageID;
-
- defaultFuncs
- .post(
- "https://www.facebook.com/ajax/mercury/delivery_receipts.php",
- ctx.jar,
- form
- )
- .then(utils.saveCookies(ctx.jar))
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
- .then(function (resData) {
- if (resData.error) {
- throw resData;
- }
-
- return callback();
- })
- .catch(function (err) {
- log.error("markAsDelivered", err);
- return callback(err);
- });
- };
-};
diff --git a/src/mqtt/fbconnect.js b/src/mqtt/fbconnect.js
index 5eb84f22..b1a4b800 100644
--- a/src/mqtt/fbconnect.js
+++ b/src/mqtt/fbconnect.js
@@ -1,3 +1,4 @@
+//From MQTT.js (https://github.com/mqttjs/MQTT.js)
'use strict'
var mqtt = require('mqtt')
@@ -63,7 +64,7 @@ function connect(brokerUrl, opts) {
if (opts.cert && opts.key) {
if (opts.protocol) {
- if (['mqtts', 'wss', 'wxs', 'alis'].indexOf(opts.protocol) === -1) {
+ if (['mqtts', 'wss'].indexOf(opts.protocol) === -1) {
switch (opts.protocol) {
case 'mqtt':
opts.protocol = 'mqtts'
@@ -71,12 +72,6 @@ function connect(brokerUrl, opts) {
case 'ws':
opts.protocol = 'wss'
break
- case 'wx':
- opts.protocol = 'wxs'
- break
- case 'ali':
- opts.protocol = 'alis'
- break
default:
throw new Error('Unknown protocol for secure connection: "' + opts.protocol + '"!')
}
@@ -93,11 +88,7 @@ function connect(brokerUrl, opts) {
'mqtt',
'mqtts',
'ws',
- 'wss',
- 'wx',
- 'wxs',
- 'ali',
- 'alis'
+ 'wss'
].filter(function (key, index) {
if (isSecure && index % 2 === 0) {
// Skip insecure protocols when requesting a secure one.
diff --git a/src/mqtt/fbws.js b/src/mqtt/fbws.js
index 5704a132..1100f111 100644
--- a/src/mqtt/fbws.js
+++ b/src/mqtt/fbws.js
@@ -1,4 +1,4 @@
-//From mqtt.js
+//From MQTT.js (https://github.com/mqttjs/MQTT.js)
'use strict'
var websocket = require('websocket-stream')
@@ -11,8 +11,6 @@ var WSS_OPTIONS = [
'pfx',
'passphrase'
]
-var IS_BROWSER = process.title === 'browser'
-
function buildUrl(opts, client) {
var url = opts.protocol + '://' + opts.hostname + ':' + opts.port + opts.path
if (typeof (opts.transformWsUrl) === 'function') {
@@ -39,7 +37,7 @@ function setDefaultOpts(opts) {
if (!opts.wsOptions) {
opts.wsOptions = {}
}
- if (!IS_BROWSER && opts.protocol === 'wss') {
+ if (opts.protocol === 'wss') {
// Add cert/key/ca etc options
WSS_OPTIONS.forEach(function (prop) {
if (opts.hasOwnProperty(prop) && !opts.wsOptions.hasOwnProperty(prop)) {
@@ -64,30 +62,4 @@ function buildBuilder(client, opts) {
return createWebSocket(client, opts)
}
-function buildBuilderBrowser(client, opts) {
- if (!opts.hostname) {
- opts.hostname = opts.host
- }
-
- if (!opts.hostname) {
- // Throwing an error in a Web Worker if no `hostname` is given, because we
- // can not determine the `hostname` automatically. If connecting to
- // localhost, please supply the `hostname` as an argument.
- if (typeof (document) === 'undefined') {
- throw new Error('Could not determine host. Specify host manually.')
- }
- var parsed = urlModule.parse(document.URL)
- opts.hostname = parsed.hostname
-
- if (!opts.port) {
- opts.port = parsed.port
- }
- }
- return createWebSocket(client, opts)
-}
-
-if (IS_BROWSER) {
- module.exports = buildBuilderBrowser
-} else {
- module.exports = buildBuilder
-}
\ No newline at end of file
+module.exports = buildBuilder
\ No newline at end of file
From f5450306af7802939b5c6182b0db67ff81226b4f Mon Sep 17 00:00:00 2001
From: Hossam Mansour <6911267+7osCraft@users.noreply.github.com>
Date: Sat, 30 Nov 2019 23:47:09 +0200
Subject: [PATCH 09/10] Fixed line breaking and spacing
---
index.js | 2 +-
package-lock.json | 205 +++++++++++++---------------------------------
package.json | 4 +-
src/listenMqtt.js | 110 ++++++++++++-------------
4 files changed, 112 insertions(+), 209 deletions(-)
diff --git a/index.js b/index.js
index d0013b1c..49293365 100644
--- a/index.js
+++ b/index.js
@@ -99,7 +99,7 @@ function buildAPI(globalOptions, html, jar) {
'getUserInfo',
'handleMessageRequest',
'listen',
- 'listenMqtt',
+ 'listenMqtt',
'logout',
'markAsRead',
'markAsReadAll',
diff --git a/package-lock.json b/package-lock.json
index 1b49c33b..7718e665 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,7 +12,7 @@
},
"acorn-jsx": {
"version": "3.0.1",
- "resolved": "http://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
"integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
"dev": true,
"requires": {
@@ -50,9 +50,9 @@
"integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE="
},
"ansi-escapes": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
- "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
+ "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
"dev": true
},
"ansi-regex": {
@@ -85,27 +85,6 @@
"sprintf-js": "~1.0.2"
}
},
- "array-union": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
- "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
- "dev": true,
- "requires": {
- "array-uniq": "^1.0.1"
- }
- },
- "array-uniq": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
- "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
- "dev": true
- },
- "arrify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
- "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
- "dev": true
- },
"asn1": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
@@ -255,9 +234,9 @@
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
},
"chalk": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
- "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
@@ -465,21 +444,6 @@
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
"dev": true
},
- "del": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
- "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
- "dev": true,
- "requires": {
- "globby": "^5.0.0",
- "is-path-cwd": "^1.0.0",
- "is-path-in-cwd": "^1.0.0",
- "object-assign": "^4.0.1",
- "pify": "^2.0.0",
- "pinkie-promise": "^2.0.0",
- "rimraf": "^2.2.8"
- }
- },
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -649,7 +613,7 @@
},
"eslint": {
"version": "4.19.1",
- "resolved": "http://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz",
"integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==",
"dev": true,
"requires": {
@@ -704,9 +668,9 @@
}
},
"eslint-visitor-keys": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
- "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
+ "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==",
"dev": true
},
"espree": {
@@ -744,15 +708,15 @@
}
},
"estraverse": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
- "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
"dev": true
},
"esutils": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
- "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
"dev": true
},
"event-emitter": {
@@ -786,7 +750,7 @@
},
"external-editor": {
"version": "2.2.0",
- "resolved": "http://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
"integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==",
"dev": true,
"requires": {
@@ -836,14 +800,14 @@
}
},
"flat-cache": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz",
- "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=",
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz",
+ "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==",
"dev": true,
"requires": {
"circular-json": "^0.3.1",
- "del": "^2.0.2",
"graceful-fs": "^4.1.2",
+ "rimraf": "~2.6.2",
"write": "^0.2.1"
}
},
@@ -943,29 +907,15 @@
}
},
"globals": {
- "version": "11.8.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-11.8.0.tgz",
- "integrity": "sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA==",
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
"dev": true
},
- "globby": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
- "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
- "dev": true,
- "requires": {
- "array-union": "^1.0.1",
- "arrify": "^1.0.0",
- "glob": "^7.0.3",
- "object-assign": "^4.0.1",
- "pify": "^2.0.0",
- "pinkie-promise": "^2.0.0"
- }
- },
"graceful-fs": {
- "version": "4.1.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
- "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
+ "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
"dev": true
},
"growl": {
@@ -1132,30 +1082,6 @@
"resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz",
"integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI="
},
- "is-path-cwd": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
- "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=",
- "dev": true
- },
- "is-path-in-cwd": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
- "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==",
- "dev": true,
- "requires": {
- "is-path-inside": "^1.0.0"
- }
- },
- "is-path-inside": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
- "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
- "dev": true,
- "requires": {
- "path-is-inside": "^1.0.1"
- }
- },
"is-promise": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
@@ -1383,9 +1309,9 @@
"integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0="
},
"lru-cache": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz",
- "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==",
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
"dev": true,
"requires": {
"pseudomap": "^1.0.2",
@@ -1548,9 +1474,9 @@
}
},
"ms": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
- "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"mute-stream": {
@@ -1617,17 +1543,17 @@
}
},
"optionator": {
- "version": "0.8.2",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
- "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
+ "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
"dev": true,
"requires": {
"deep-is": "~0.1.3",
- "fast-levenshtein": "~2.0.4",
+ "fast-levenshtein": "~2.0.6",
"levn": "~0.3.0",
"prelude-ls": "~1.1.2",
"type-check": "~0.3.2",
- "wordwrap": "~1.0.0"
+ "word-wrap": "~1.2.3"
}
},
"ordered-read-streams": {
@@ -1665,27 +1591,6 @@
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
},
- "pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
- "dev": true
- },
- "pinkie": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
- "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
- "dev": true
- },
- "pinkie-promise": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
- "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
- "dev": true,
- "requires": {
- "pinkie": "^2.0.0"
- }
- },
"pluralize": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
@@ -1710,9 +1615,9 @@
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
},
"progress": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz",
- "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"dev": true
},
"pseudomap": {
@@ -1782,7 +1687,7 @@
},
"regexpp": {
"version": "1.1.0",
- "resolved": "http://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz",
"integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==",
"dev": true
},
@@ -1850,12 +1755,12 @@
}
},
"rimraf": {
- "version": "2.6.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
- "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
"dev": true,
"requires": {
- "glob": "^7.0.5"
+ "glob": "^7.1.3"
}
},
"run-async": {
@@ -1893,9 +1798,9 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"semver": {
- "version": "5.6.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
- "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
},
"shebang-command": {
@@ -2050,7 +1955,7 @@
},
"through": {
"version": "2.3.8",
- "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
"dev": true
},
@@ -2198,10 +2103,10 @@
"isexe": "^2.0.0"
}
},
- "wordwrap": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
- "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
+ "word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
"dev": true
},
"wrappy": {
diff --git a/package.json b/package.json
index 133a6ec9..8c96560e 100644
--- a/package.json
+++ b/package.json
@@ -32,9 +32,9 @@
"node": ">=4.x"
},
"devDependencies": {
+ "eslint": "^4.19.1",
"mocha": "^2.2.5",
- "prettier": "^1.11.1",
- "eslint": "^4.19.1"
+ "prettier": "^1.11.1"
},
"eslintConfig": {
"env": {
diff --git a/src/listenMqtt.js b/src/listenMqtt.js
index 81d2191c..51f0f011 100644
--- a/src/listenMqtt.js
+++ b/src/listenMqtt.js
@@ -3,7 +3,7 @@ var fbconnect = require("./mqtt/fbconnect");
var utils = require("../utils");
var log = require("npmlog");
-var identity = function () { };
+var identity = function() {};
var lastSeqId = 0;
var client = undefined;
@@ -51,12 +51,12 @@ function listenMqtt(ctx, globalCallback, defaultFuncs) {
client = fbconnect.connect(host, options);
- client.on('error', function (err) {
+ client.on('error', function(err) {
log.error(err);
client.end();
});
- client.on('connect', function () {
+ client.on('connect', function() {
client.subscribe(["/legacy_web", "/webrtc", "/br_sr", "/sr_res", "/t_ms", "/thread_typing", "/orca_typing_notifications", "/notify_disconnect", "/orca_presence"],
(err, granted) => {
client.unsubscribe('/orca_message_notifications', (err) => {
@@ -70,28 +70,28 @@ function listenMqtt(ctx, globalCallback, defaultFuncs) {
device_params: null
};
- client.publish('/messenger_sync_create_queue', JSON.stringify(queue), { qos: 0, retain: false })
+ client.publish('/messenger_sync_create_queue', JSON.stringify(queue), {qos: 0, retain: false})
});
});
});
- client.on('message', function (topic, message, packet) {
+ client.on('message', function(topic, message, packet) {
var jsonMessage = JSON.parse(message);
- if (topic === "/t_ms") {
- if (jsonMessage.lastIssuedSeqId) {
+ if(topic === "/t_ms") {
+ if(jsonMessage.lastIssuedSeqId) {
lastSeqId = parseInt(jsonMessage.lastIssuedSeqId);
} else {
- if (jsonMessage.deltas) {
+ if(jsonMessage.deltas) {
lastSeqId = parseInt(jsonMessage.deltas[0].irisSeqId);
}
}
//If it contains more than 1 delta
- for (var i in jsonMessage.deltas) {
+ for(var i in jsonMessage.deltas) {
var delta = jsonMessage.deltas[i];
- parseDelta(ctx, globalCallback, defaultFuncs, { "delta": delta });
+ parseDelta(ctx, globalCallback, defaultFuncs, {"delta": delta});
}
- } else if (topic === "/thread_typing" || topic === "/orca_typing_notifications") {
+ } else if(topic === "/thread_typing" || topic === "/orca_typing_notifications") {
var typ = {
type: "typ",
isTyping: !!jsonMessage.state,
@@ -99,9 +99,9 @@ function listenMqtt(ctx, globalCallback, defaultFuncs) {
threadID: utils.formatID((jsonMessage.thread || jsonMessage.sender_fbid).toString())
}
globalCallback(null, typ);
- } else if (topic === "/orca_presence") {
- if (!ctx.globalOptions.updatePresence) {
- for (var i in jsonMessage.list) {
+ } else if(topic === "/orca_presence") {
+ if(!ctx.globalOptions.updatePresence) {
+ for(var i in jsonMessage.list) {
var data = jsonMessage.list[i];
var userID = data["u"];
@@ -118,25 +118,25 @@ function listenMqtt(ctx, globalCallback, defaultFuncs) {
});
- client.on('close', function () {
+ client.on('close', function() {
// client.end();
});
}
function parseDelta(ctx, globalCallback, defaultFuncs, v) {
- if (v.delta.class == "NewMessage") {
+ if(v.delta.class == "NewMessage") {
//Not tested for pages
- if (ctx.globalOptions.pageID &&
+ if(ctx.globalOptions.pageID &&
ctx.globalOptions.pageID != v.queue
)
return;
(function resolveAttachmentUrl(i) {
- if (i == v.delta.attachments.length) {
+ if(i == v.delta.attachments.length) {
var fmtMsg;
try {
fmtMsg = utils.formatDeltaMessage(v);
- } catch (err) {
+ } catch(err) {
return globalCallback({
error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
detail: err,
@@ -149,13 +149,13 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
undefined :
globalCallback(null, fmtMsg);
} else {
- if (
+ if(
v.delta.attachments[i].mercury.attach_type == "photo"
) {
api.resolvePhotoUrl(
v.delta.attachments[i].fbid,
(err, url) => {
- if (!err)
+ if(!err)
v.delta.attachments[
i
].mercury.metadata.url = url;
@@ -169,14 +169,14 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
})(0);
}
- if (v.delta.class == "ClientPayload") {
+ if(v.delta.class == "ClientPayload") {
var clientPayload = utils.decodeClientPayload(
v.delta.payload
);
- if (clientPayload && clientPayload.deltas) {
- for (var i in clientPayload.deltas) {
+ if(clientPayload && clientPayload.deltas) {
+ for(var i in clientPayload.deltas) {
var delta = clientPayload.deltas[i];
- if (delta.deltaMessageReaction && !!ctx.globalOptions.listenEvents) {
+ if(delta.deltaMessageReaction && !!ctx.globalOptions.listenEvents) {
globalCallback(null, {
type: "message_reaction",
threadID: delta.deltaMessageReaction.threadKey
@@ -188,7 +188,7 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
senderID: delta.deltaMessageReaction.senderId,
userID: delta.deltaMessageReaction.userId
});
- } else if (delta.deltaRecallMessageData && !!ctx.globalOptions.listenEvents) {
+ } else if(delta.deltaRecallMessageData && !!ctx.globalOptions.listenEvents) {
globalCallback(null, {
type: "message_unsend",
threadID: delta.deltaRecallMessageData.threadKey.threadFbId ?
@@ -199,7 +199,7 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
deletionTimestamp: delta.deltaRecallMessageData.deletionTimestamp,
timestamp: delta.deltaRecallMessageData.timestamp
});
- } else if (delta.deltaMessageReply) {
+ } else if(delta.deltaMessageReply) {
//Mention block - #1
var mdata =
delta.deltaMessageReply.message === undefined ? [] :
@@ -212,7 +212,7 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
var mentions = {};
- for (var i = 0; i < m_id.length; i++) {
+ for(var i = 0; i < m_id.length; i++) {
mentions[m_id[i]] = delta.deltaMessageReply.message.body.substring(
m_offset[i],
m_offset[i] + m_length[i]
@@ -231,7 +231,7 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
var rmentions = {};
- for (var i = 0; i < m_id.length; i++) {
+ for(var i = 0; i < m_id.length; i++) {
rmentions[m_id[i]] = delta.deltaMessageReply.repliedToMessage.body.substring(
m_offset[i],
m_offset[i] + m_length[i]
@@ -246,7 +246,7 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
.otherUserFbId,
messageID: delta.deltaMessageReply.message.messageMetadata.messageId,
senderID: delta.deltaMessageReply.message.messageMetadata.actorFbId,
- attachments: delta.deltaMessageReply.message.attachments.map(function (att) {
+ attachments: delta.deltaMessageReply.message.attachments.map(function(att) {
var mercury = JSON.parse(att.mercuryJSON);
Object.assign(att, mercury);
return att;
@@ -258,14 +258,14 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
};
- if (delta.deltaMessageReply.repliedToMessage) {
+ if(delta.deltaMessageReply.repliedToMessage) {
callbackToReturn.messageReply = {
threadID: delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId ?
delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey
.otherUserFbId,
messageID: delta.deltaMessageReply.repliedToMessage.messageMetadata.messageId,
senderID: delta.deltaMessageReply.repliedToMessage.messageMetadata.actorFbId,
- attachments: delta.deltaMessageReply.repliedToMessage.attachments.map(function (att) {
+ attachments: delta.deltaMessageReply.repliedToMessage.attachments.map(function(att) {
var mercury = JSON.parse(att.mercuryJSON);
Object.assign(att, mercury);
return att;
@@ -284,16 +284,16 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
}
}
- if (v.delta.class !== "NewMessage" &&
+ if(v.delta.class !== "NewMessage" &&
!ctx.globalOptions.listenEvents
)
return;
- switch (v.delta.class) {
+ switch(v.delta.class) {
case "ReadReceipt":
var fmtMsg;
try {
fmtMsg = utils.formatDeltaReadReceipt(v.delta);
- } catch (err) {
+ } catch(err) {
return globalCallback({
error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
detail: err,
@@ -303,7 +303,7 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
}
return globalCallback(null, fmtMsg);
case "AdminTextMessage":
- switch (v.delta.type) {
+ switch(v.delta.type) {
case "change_thread_theme":
case "change_thread_nickname":
case "change_thread_icon":
@@ -312,7 +312,7 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
var fmtMsg;
try {
fmtMsg = utils.formatDeltaEvent(v.delta);
- } catch (err) {
+ } catch(err) {
return globalCallback({
error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
detail: err,
@@ -330,8 +330,7 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
case "ForcedFetch":
var mid = v.delta.messageId;
var tid = v.delta.threadKey.threadFbId.toString();
- if(mid && tid)
- {
+ if(mid && tid) {
const form = {
"av": ctx.globalOptions.pageID,
"queries": JSON.stringify({
@@ -346,23 +345,22 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
}
})
};
-
+
defaultFuncs
.post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
.then((resData) => {
- if (resData[resData.length - 1].error_results > 0) {
+ if(resData[resData.length - 1].error_results > 0) {
throw resData[0].o0.errors;
}
-
- if (resData[resData.length - 1].successful_results === 0) {
- throw { error: "forcedFetch: there was no successful_results", res: resData };
+
+ if(resData[resData.length - 1].successful_results === 0) {
+ throw {error: "forcedFetch: there was no successful_results", res: resData};
}
-
+
var fetchData = resData[0].o0.data.message;
-
- if(fetchData && fetchData.__typename === "ThreadImageMessage")
- {
+
+ if(fetchData && fetchData.__typename === "ThreadImageMessage") {
(!ctx.globalOptions.selfListen &&
formattedEvent.author.toString() === ctx.userID) ||
!ctx.loggedIn ?
@@ -393,7 +391,7 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
var formattedEvent;
try {
formattedEvent = utils.formatDeltaEvent(v.delta);
- } catch (err) {
+ } catch(err) {
return globalCallback({
error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
detail: err,
@@ -409,9 +407,9 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
}
}
-module.exports = function (defaultFuncs, api, ctx) {
+module.exports = function(defaultFuncs, api, ctx) {
var globalCallback = identity;
- return function (callback) {
+ return function(callback) {
globalCallback = callback;
const form = {
"av": ctx.globalOptions.pageID,
@@ -433,15 +431,15 @@ module.exports = function (defaultFuncs, api, ctx) {
.post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
.then((resData) => {
- if (resData && resData[resData.length - 1].error_results > 0) {
+ if(resData && resData[resData.length - 1].error_results > 0) {
throw resData[0].o0.errors;
}
- if (resData[resData.length - 1].successful_results === 0) {
- throw { error: "getSeqId: there was no successful_results", res: resData };
+ if(resData[resData.length - 1].successful_results === 0) {
+ throw {error: "getSeqId: there was no successful_results", res: resData};
}
- if (resData[0].o0.data.viewer.message_threads.sync_sequence_id) {
+ if(resData[0].o0.data.viewer.message_threads.sync_sequence_id) {
lastSeqId = resData[0].o0.data.viewer.message_threads.sync_sequence_id;
listenMqtt(ctx, globalCallback, defaultFuncs);
}
@@ -452,7 +450,7 @@ module.exports = function (defaultFuncs, api, ctx) {
return callback(err);
});
- var stopListening = function () {
+ var stopListening = function() {
globalCallback = identity;
client.end();
};
From 760dedf8854585bb3d2efb0fdac9eabcf119e174 Mon Sep 17 00:00:00 2001
From: Hossam Mansour <6911267+7osCraft@users.noreply.github.com>
Date: Mon, 2 Dec 2019 02:39:31 +0200
Subject: [PATCH 10/10] Fixed ForcedFetch and presence timestamp.
---
src/listenMqtt.js | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/listenMqtt.js b/src/listenMqtt.js
index 51f0f011..ec895c3f 100644
--- a/src/listenMqtt.js
+++ b/src/listenMqtt.js
@@ -108,7 +108,8 @@ function listenMqtt(ctx, globalCallback, defaultFuncs) {
var presence = {
type: "presence",
userID: userID,
- timestamp: data["l"],
+ //Convert to ms
+ timestamp: data["l"] * 1000,
statuses: data["p"]
};
globalCallback(null, presence);
@@ -329,7 +330,7 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
//For group images
case "ForcedFetch":
var mid = v.delta.messageId;
- var tid = v.delta.threadKey.threadFbId.toString();
+ var tid = v.delta.threadKey.threadFbId;
if(mid && tid) {
const form = {
"av": ctx.globalOptions.pageID,
@@ -338,7 +339,7 @@ function parseDelta(ctx, globalCallback, defaultFuncs, v) {
"doc_id": "1768656253222505",
"query_params": {
"thread_and_message_id": {
- "thread_id": tid,
+ "thread_id": tid.toString(),
"message_id": mid,
}
}