-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add push notifications for reminders
- Loading branch information
Marcel Kalveram
committed
May 5, 2019
1 parent
fc19b74
commit de1b670
Showing
11 changed files
with
428 additions
and
190 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#!/usr/bin/env node | ||
|
||
const mongoose = require("mongoose") | ||
const dotenv = require("dotenv") | ||
const remindersController = require("../controllers/reminders") | ||
|
||
/** | ||
* Load environment variables from .env file, where API keys and passwords are configured. | ||
*/ | ||
dotenv.load({ path: ".env" }) | ||
|
||
/** | ||
* Connect to MongoDB. | ||
*/ | ||
mongoose.Promise = global.Promise | ||
mongoose.connect(process.env.MONGODB_URI || "mongodb://localhost:27017/vlctechhub", { | ||
user: process.env.MONGODB_USER, | ||
pass: process.env.MONGODB_PASS, | ||
}) | ||
mongoose.connection.on("error", err => { | ||
console.error(err) | ||
console.log("%s MongoDB connection error. Please make sure MongoDB is running.", chalk.red("✗")) | ||
process.exit() | ||
}) | ||
|
||
remindersController.sendRemindersForEventsOnDate(new Date()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,28 @@ | ||
const User = require("../models/User"); | ||
const remoteApi = require("../services/remoteApi"); | ||
const Expo = require("expo-server-sdk"); | ||
const User = require("../models/User") | ||
const remoteApi = require("../services/remoteApi") | ||
const pushNotificationsHelper = require("../services/pushNotifications") | ||
|
||
const notificationTitles = { | ||
events: "Hay un nuevo evento", | ||
jobs: "Hay una nueva oferta de trabajo" | ||
}; | ||
|
||
// Create a new Expo SDK client | ||
const expo = new Expo(); | ||
|
||
const sendNotifications = (tokens, { title, message }) => { | ||
let messages = []; | ||
for (let token of tokens) { | ||
if (!Expo.isExpoPushToken(token)) { | ||
console.error(`Push token ${token} is not a valid Expo push token`); | ||
continue; | ||
} | ||
messages.push({ | ||
to: token, | ||
sound: "default", | ||
title: title, | ||
body: message | ||
}); | ||
} | ||
|
||
let chunks = expo.chunkPushNotifications(messages); | ||
let tickets = []; | ||
(async () => { | ||
for (let chunk of chunks) { | ||
try { | ||
let ticketChunk = await expo.sendPushNotificationsAsync(chunk); | ||
tickets.push(...ticketChunk); | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
} | ||
})(); | ||
}; | ||
events: "Hay un nuevo evento", | ||
jobs: "Hay una nueva oferta de trabajo", | ||
} | ||
|
||
const sendPushNotificationsForType = type => { | ||
remoteApi.getLatestItemForType(type).then(latestItem => { | ||
User.getUsersByType(type, latestItem.id).then(users => { | ||
const tokens = users.map(user => user.token); | ||
sendNotifications(tokens, { | ||
title: notificationTitles[type], | ||
message: | ||
type === "events" | ||
? latestItem.title | ||
: `${latestItem.title} en ${latestItem.company.name}` | ||
}); | ||
User.setLatestItemIdForUser(tokens, type, latestItem.id).then(res => res); | ||
}); | ||
}); | ||
}; | ||
remoteApi.fetchLatestItemForType(type).then(latestItem => { | ||
User.getUsersByType(type, latestItem.id).then(users => { | ||
const tokens = users.map(user => user.token) | ||
pushNotificationsHelper.sendNotifications(tokens, { | ||
title: notificationTitles[type], | ||
message: | ||
type === "events" | ||
? latestItem.title | ||
: `${latestItem.title} en ${latestItem.company.name}`, | ||
}) | ||
User.setLatestItemIdForUser(tokens, type, latestItem.id).then(res => res) | ||
}) | ||
}) | ||
} | ||
|
||
module.exports = { | ||
sendPushNotificationsForType | ||
}; | ||
sendPushNotificationsForType, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
const User = require("../models/User") | ||
const remoteApi = require("../services/remoteApi") | ||
const pushNotificationsHelper = require("../services/pushNotifications") | ||
|
||
const sendRemindersForEventsOnDate = date => { | ||
remoteApi.fetchEventsByDate(date).then(sendRemindersForEvents) | ||
} | ||
|
||
const sendRemindersForEvents = events => { | ||
for (event of events) { | ||
sendRemindersForEvent(event) | ||
} | ||
} | ||
|
||
const sendRemindersForEvent = event => { | ||
User.getUsersByEventId(event.id).then(users => { | ||
const tokens = users.map(user => user.token) | ||
pushNotificationsHelper.sendNotifications(tokens, { | ||
title: "Recordatorio para el evento", | ||
message: event.title, | ||
}) | ||
}) | ||
} | ||
|
||
module.exports = { | ||
sendRemindersForEventsOnDate, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
const Expo = require("expo-server-sdk") | ||
|
||
// Create a new Expo SDK client | ||
const expo = new Expo() | ||
|
||
const sendNotifications = (tokens, { title, message }) => { | ||
let messages = [] | ||
for (let token of tokens) { | ||
if (!Expo.isExpoPushToken(token)) { | ||
console.error(`Push token ${token} is not a valid Expo push token`) | ||
continue | ||
} | ||
messages.push({ | ||
to: token, | ||
sound: "default", | ||
title: title, | ||
body: message, | ||
}) | ||
} | ||
|
||
let chunks = expo.chunkPushNotifications(messages) | ||
let tickets = [] | ||
;(async () => { | ||
for (let chunk of chunks) { | ||
try { | ||
let ticketChunk = await expo.sendPushNotificationsAsync(chunk) | ||
tickets.push(...ticketChunk) | ||
} catch (error) { | ||
console.error(error) | ||
} | ||
} | ||
})() | ||
} | ||
|
||
module.exports = { | ||
sendNotifications, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,54 +1,76 @@ | ||
const fetch = require("node-fetch"); | ||
const API_URI = "https://api.vlctechhub.org/v1"; | ||
const fetch = require("node-fetch") | ||
const API_URI = "https://api.vlctechhub.org/v1" | ||
|
||
const remoteApiCalls = { | ||
events: { | ||
uri: "/events?category=next", | ||
responseObject: "events" | ||
}, | ||
jobs: { | ||
uri: "/jobs", | ||
responseObject: "jobs" | ||
} | ||
}; | ||
events: { | ||
uri: "/events?category=next", | ||
responseObject: "events", | ||
}, | ||
jobs: { | ||
uri: "/jobs", | ||
responseObject: "jobs", | ||
}, | ||
} | ||
|
||
const fetchData = function(uri) { | ||
return new Promise((resolve, reject) => { | ||
fetch(`${API_URI}/${uri}`, { | ||
method: "GET", | ||
headers: { | ||
Accept: "application/json" | ||
} | ||
}).then(response => resolve(response.json()), err => reject(err)); | ||
}); | ||
}; | ||
return new Promise((resolve, reject) => { | ||
fetch(`${API_URI}/${uri}`, { | ||
method: "GET", | ||
headers: { | ||
Accept: "application/json", | ||
}, | ||
}).then(response => resolve(response.json()), err => reject(err)) | ||
}) | ||
} | ||
|
||
const getLatestItem = (field, items) => { | ||
items.sort((a, b) => { | ||
const dateA = new Date(a[field]); | ||
const dateB = new Date(b[field]); | ||
if (dateA < dateB) return 1; | ||
if (dateA > dateB) return -1; | ||
return 0; | ||
}); | ||
return items[0]; | ||
}; | ||
|
||
const getLatestItemForType = (type, fetch = fetchData) => { | ||
return new Promise((res, rej) => { | ||
fetch(remoteApiCalls[type].uri).then(json => | ||
res( | ||
getLatestItem( | ||
type === "jobs" ? "published_at" : "date", | ||
json[remoteApiCalls[type].responseObject] | ||
items.sort((a, b) => { | ||
const dateA = new Date(a[field]) | ||
const dateB = new Date(b[field]) | ||
if (dateA < dateB) return 1 | ||
if (dateA > dateB) return -1 | ||
return 0 | ||
}) | ||
return items[0] | ||
} | ||
|
||
const fetchLatestItemForType = (type, fetch = fetchData) => { | ||
return new Promise((res, rej) => { | ||
fetch(remoteApiCalls[type].uri).then(json => | ||
res( | ||
getLatestItem( | ||
type === "jobs" ? "published_at" : "date", | ||
json[remoteApiCalls[type].responseObject], | ||
), | ||
), | ||
) | ||
) | ||
); | ||
}); | ||
}; | ||
}) | ||
} | ||
|
||
const compareDate = (a, b) => { | ||
const dateA = new Date(a) | ||
const dateB = new Date(b) | ||
return ( | ||
dateA.getDate() === dateB.getDate() && | ||
dateA.getMonth() == dateB.getMonth() && | ||
dateA.getFullYear() == dateB.getFullYear() | ||
) | ||
} | ||
|
||
const getEventsByDate = (events, date) => { | ||
return events.filter(e => compareDate(e.date, date)) | ||
} | ||
|
||
const fetchEventsByDate = (date, fetch = fetchData) => { | ||
return new Promise((res, rej) => { | ||
fetch(remoteApiCalls["events"].uri).then(json => res(getEventsByDate(json["events"], date))) | ||
}) | ||
} | ||
|
||
module.exports = { | ||
fetchData, | ||
getLatestItem, | ||
getLatestItemForType | ||
}; | ||
fetchData, | ||
fetchEventsByDate, | ||
getLatestItem, | ||
fetchLatestItemForType, | ||
compareDate, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
const { expect } = require("chai") | ||
const sinon = require("sinon") | ||
|
||
const remindersController = require("../../controllers/reminders") | ||
const remoteApi = require("../../services/remoteApi") | ||
const pushNotificationsHelper = require("../../services/pushNotifications") | ||
const User = require("../../models/User") | ||
|
||
sinon | ||
.stub(remoteApi, "fetchEventsByDate") | ||
.resolves([ | ||
{ date: "2019-05-03T16:00:00Z", title: "test-1" }, | ||
{ date: "2019-05-03T16:00:00Z", title: "test-2" }, | ||
{ date: "2019-06-03T16:00:00Z", title: "test-3" }, | ||
]) | ||
|
||
sinon.stub(User, "getUsersByEventId").resolves([{ token: "abc" }, { token: "def" }]) | ||
const pushSpy = sinon.spy(pushNotificationsHelper, "sendNotifications") | ||
|
||
describe("Test send reminders functions", () => { | ||
it("should test the reminders for events date function", done => { | ||
remindersController.sendRemindersForEventsOnDate("2019-05-03") | ||
setTimeout(function() { | ||
expect(pushSpy.called).to.eq(true) | ||
expect(pushSpy.firstCall.args[0]).to.eql(["abc", "def"]) | ||
expect(pushSpy.secondCall.args[1].message).to.eql("test-2") | ||
done() | ||
}, 100) | ||
}) | ||
}) |
Oops, something went wrong.