diff --git a/DOCS.md b/DOCS.md index 69177f53..7ee7085b 100644 --- a/DOCS.md +++ b/DOCS.md @@ -17,6 +17,7 @@ * [`api.getCurrentUserID`](#getCurrentUserID) * [`api.getEmojiUrl`](#getEmojiUrl) * [`api.getFriendsList`](#getFriendsList) +* [`api.getNotifications`](#getNotifications) * [`api.getThreadHistory`](#getThreadHistory) * [`api.getThreadInfo`](#getThreadInfo) * [`api.getThreadList`](#getThreadList) @@ -544,6 +545,37 @@ login({appState: JSON.parse(fs.readFileSync('appstate.json', 'utf8'))}, (err, ap --------------------------------------- + +### api.getNotifications(amount, callback) + +Returns an array of objects with up to `amount` most recent notifications. + +__Arguments__ + +* `callback(err, arr)` - A callback called when the query is done (either with an error or with an confirmation object). `arr` is an array of objects with the following fields: `id`, `text`, `html`, `time`, `seen`, `read`. `html` is the same as `text` but with ranges emphasized. `time`, `seen`, and `read` are all millisecond timestamps. + +__Example__ + +```js +const fs = require("fs"); +const login = require("facebook-chat-api"); + +login({appState: JSON.parse(fs.readFileSync('appstate.json', 'utf8'))}, (err, api) => { + if(err) return console.error(err); + + api.getNotifications((err, data) => { + if(err) return console.error(err); + + data.forEach(notification => { + if(!notification.seen) + console.log(new Date(notification.time), notification.text); + }); + }); +}); +``` + +--------------------------------------- + ### api.getThreadHistory(threadID, amount, timestamp, callback) diff --git a/README.md b/README.md index efec9d3b..67d3ee25 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ Result: * [`api.getAppState`](DOCS.md#getAppState) * [`api.getCurrentUserID`](DOCS.md#getCurrentUserID) * [`api.getFriendsList`](DOCS.md#getFriendsList) +* [`api.getNotifications`](DOCS.md#getNotifications) * [`api.getThreadHistory`](DOCS.md#getThreadHistory) * [`api.getThreadInfo`](DOCS.md#getThreadInfo) * [`api.getThreadList`](DOCS.md#getThreadList) diff --git a/index.js b/index.js index 95a6785f..b7cfe1b1 100644 --- a/index.js +++ b/index.js @@ -91,6 +91,7 @@ function buildAPI(globalOptions, html, jar) { 'getCurrentUserID', 'getEmojiUrl', 'getFriendsList', + 'getNotifications', 'getThreadHistory', 'getThreadInfo', 'getThreadList', diff --git a/src/getNotifications.js b/src/getNotifications.js new file mode 100644 index 00000000..081d97fc --- /dev/null +++ b/src/getNotifications.js @@ -0,0 +1,61 @@ +"use strict"; + +var utils = require("../utils"); +var log = require("npmlog"); + +function formatText(notification, boldStart, boldEnd) { + const boldChars = boldStart.length + boldEnd.length + let formattedText = notification.title.text + notification.title.ranges.forEach( (range, i) => { + let start = range.offset + i * boldChars + let end = range.offset + range.length + i * boldChars + formattedText = + formattedText.slice( 0, start ) + boldStart + + formattedText.slice( start, end ) + boldEnd + + formattedText.slice( end ) + }) + return formattedText; +} + +function formatData(obj) { + return obj.nodes.map( notification => { + return { + id: notification.alert_id, + text: notification.title.text, + html: formatText(notification, "", ""), + time: notification.timestamp.time * 1000, + seen: notification.first_seen_time * 1000, + read: notification.first_read_time * 1000 + }; + }); +} + +module.exports = function(defaultFuncs, api, ctx) { + return function getNotifications(amount, callback) { + if (!callback) { + throw { error: "getNotifications: need callback" }; + } + + defaultFuncs + .postFormData( + "https://www.facebook.com/ajax/notifications/client/get.php", + ctx.jar, + {}, + { length: amount } + ) + .then(utils.parseAndCheckLogin(ctx, defaultFuncs)) + .then(function(resData) { + if (!resData) { + throw { error: "getNotifications returned empty object." }; + } + if (resData.error) { + throw resData; + } + callback(null, formatData(resData.payload)); + }) + .catch(function(err) { + log.error("getNotifications", err); + return callback(err); + }); + }; +}; diff --git a/test/test.js b/test/test.js index 15760837..5beeb18b 100644 --- a/test/test.js +++ b/test/test.js @@ -366,6 +366,26 @@ describe('Login:', function() { }); }); + it('should get notifications', function (done) { + api.getNotifications(function(err, data) { + try { + checkErr(done)(err); + assert(getType(data) === "Array"); + data.map(v => { + assert(getType(v.id) === "String"); + assert(getType(v.text) === "String"); + assert(getType(v.html) === "String"); + assert(getType(v.time) === "Number"); + assert(getType(v.seen) === "Number"); + assert(getType(v.read) === "Number"); + }) + done(); + } catch(e){ + done(e); + } + }); + }); + it('should parse share attachment correctly', function () { var formatted = formatDeltaMessage(shareAttachmentFixture); assert(formatted.attachments[0].type === "share");