Commit 98fefde3 authored by TheDreamSaver's avatar TheDreamSaver
Browse files

setting things up

parent c23369e5
# alexa-rocketchat-notification
\ No newline at end of file
<p align="center">
<img src="https://user-images.githubusercontent.com/41849970/57236777-691ae200-7043-11e9-8d8e-67e05e60a8e4.png">
</p>
<h3 align="center">
Innovating Incredible New User Experiences In The Alexa Ecosystem
</h3>
---
# Let's Get Started with Notifications
**Note:** The rest of this readme assumes you have your developer environment ready to go and that you have some familiarity with CLI (Command Line Interface) Tools, [AWS](https://aws.amazon.com/), and the [ASK Developer Portal](https://developer.amazon.com/alexa-skills-kit).
### Repository Contents
* `index.js` - Microservice Logic for sending notifications to the hosted on [Rocket Chat Alexa Skill](https://github.com/RocketChat/alexa-rocketchat)
## Setup w/ ASK CLI
### Pre-requisites
* Node.js (> v8.10)
* Register for an [AWS Account](https://aws.amazon.com/)
* Register for an [Amazon Developer Account](https://developer.amazon.com/)
* Install and Setup [ASK CLI](https://developer.amazon.com/docs/smapi/quick-start-alexa-skills-kit-command-line-interface.html)
* Rocket Chat Server updated to [Release 1.0.0-rc3](https://github.com/RocketChat/Rocket.Chat/releases/tag/1.0.0-rc.3) or later
* Setup a [Rocket Chat Alexa Skill](https://github.com/RocketChat/alexa-rocketchat)
### Installation
1. Clone the repository.
```bash
$ git clone https://github.com/RocketChat/alexa-rocketchat-notification.git
```
2. Navigating into the repository's root folder.
```bash
$ cd alexa-rocketchat-notification
```
3. Install npm dependencies by running the npm command: `npm install`
```bash
$ npm install
```
### Deployment
ASK CLI will create the skill and the lambda function for you. The Lambda function will be created in ```us-east-1 (Northern Virginia)``` by default.
1. Log into your AWS Account and create a new Lambda function. Make sure to choose Runtime as `Node.js 10.x`. In the permissions create a new role, and then go to the IAM console and add policies to access DynamoDB and Cloudwatch.
2. Once the function is created, increase the Timeout of the function to 15 minutes in the basic settings down below. Also set a few Environment variables values.
e.g:
1. **SERVER_URL** https://yourservername.rocket.chat
2. **DDB_NAME** (The name of the Dynamo DB table being used by your skill)
3. **CLIENT_ID** (The client ID from your Alexa Developer Console in the Permissions Section of the skill)
4. **CLIENT_SECRET** (The client secret from your Alexa Developer Console in the Permissions Section of the skill)
5. **API_REGION** (For North/South America use US, For Europe/India use EU, For Japan use FE)
### Configuring Cloudwatch Rules to Run the Microservice
1. Log into your AWS Account and go to cloudwatch.
2. Click on Rules -> Create Rule. Give it a fixed rate of 7 minutes. Every 7 minutes it will run the lambda function to check for new messages. We can run it every minute but the minimum expiry time for an Alexa Notification is 5 minutes. So we will check for notification every 7 minutes.
3. Click on Add Target. Choose the Lambda function you created above. Click on configure details and give it a name. Click create rule.
### Making Changes to the main skill to add notifications
1. The above setup is an external microservice which takes care of sending notifications. But we still need to add the ability for user to sign up for notifications. Please follow the notification steps given in the main repo for adding it to the skill.
2. Also it will be worth checking out this video to get insights
3. Click on Add Target. Choose the Lambda function you created above. Click on configure details and give it a name. Click create rule.
### Testing
1. Before testing, you must make sure that Account Linking with the main skill has completed. Go to alexa.amazon.com or your alexa app and click **account linking** to complete the link. And also ensure that you have given the permission to receive notifications.
2. To test, you just need to receive a message, and you'll soon receive a notification on your Alexa Device. Your Alexa Device will light up in green color with a chime sound. You can say "Alexa, what are my notifications." to hear them.
## Customization
1. ```./index.js```
You can change the notification expiry time, or pre-configured output text.
See the [Proactive Events API Documentation](https://developer.amazon.com/docs/smapi/schemas-for-proactive-events.html#message-alert) for more information.
## Documentation To Refer
1. ```Rocket.Chat API Documentation```
The REST API allows you to control and extend Rocket.Chat with ease - [REST API Documentation]( https://rocket.chat/docs/developer-guides/rest-api/ )
2. ```Axios Documentation```
Promise based HTTP client for the browser and node.js - [Github Page](https://github.com/axios/axios )
3. ```Proactive Events API Documentation```
You can use the Proactive Events API to send events to Alexa. The events represent factual data that might interest a customer. Upon receiving an event, Alexa proactively delivers the information to customers subscribed to receive these events. This API currently supports one proactive channel, Alexa Notifications - [Documentation Page](https://developer.amazon.com/docs/smapi/proactive-events-api.html)
4. ```Dabble Lab Video on Proactive Events```
This video explains the proactive events API and setup instructions with example - [Alexa Notifications with Proactive Events - Dabble Lab #125](https://www.youtube.com/watch?v=oMcHTMZDTVQ)
4. ```ASK Utils Proactive Events```
This NPM package helps send proactive events in a much simpler way - [ASK Utils Proactive Events](https://github.com/ask-utils/proactive-event)
## Contact Us
Keep an eye on our issues. We are just beginning and will surely appreciate all the help we can get. All ideas are welcome.
Feel free to join the discussion in our Alexa channel - [Rocket.Chat Alexa Channel](https://open.rocket.chat/channel/alexa)
const proactive = require('@ask-utils/proactive-event');
const moment = require("moment");
const axios = require('axios');
const AWS = require('aws-sdk');
const paramsDDB = {
TableName: process.env.DDB_NAME,
Limit: 5000
};
const docClient = new AWS.DynamoDB.DocumentClient();
const Client = proactive.Client;
const MessageAlert = proactive.MessageAlert;
const client = new Client({
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
apiRegion: process.env.API_REGION
})
const PayloadBuilder = MessageAlert.Activated.PayloadFactory.init()
let getSubscriptionEndpoint = `${process.env.SERVER_URL}/api/v1/subscriptions.get?updatedSince=`;
async function sendNotifications() {
let userList = await getUsers();
for (let i = 0; i < userList.length; i++) {
try {
if (userList[i].attributes.hasOwnProperty("personalAccessToken")) {
let headers = {
'X-Auth-Token': userList[i].attributes.personalAccessToken,
'X-User-Id': userList[i].attributes.profileId
};
let userId = userList[i].id;
let total = await getSubscriptionCount(headers);
if (userList[i].attributes.notificationsSettings == 'userMentions' && total.userMentions > 0) {
PayloadBuilder.setMessageCreator(`All Channels, Groups and DMs and ${total.userMentions} user mentions`)
.setMessageCount(total.unreads)
.setMessageStatus('UNREAD')
.getParameter()
client.setEvent(PayloadBuilder.getParameter())
.setReferenceId(userId.slice(-40))
.setExpiryTime(moment().add(1, 'hour').toISOString())
.setRelevantAudience('Unicast', { "user": userId })
.requestEvent()
.then(result => console.log(result))
.catch(result => console.log(result))
}
else if (userList[i].attributes.notificationsSettings == 'unreads' && total.unreads > 0) {
PayloadBuilder.setMessageCreator(`All Channels, Groups and DMs ${total.userMentions == 0 ? `` : ` and ${total.userMentions} user mentions `} `)
.setMessageCount(total.unreads)
.setMessageStatus('UNREAD')
.getParameter()
client.setEvent(PayloadBuilder.getParameter())
.setReferenceId(userId.slice(-40))
.setExpiryTime(moment().add(1, 'hour').toISOString())
.setRelevantAudience('Unicast', { "user": userId })
.requestEvent()
.then(result => console.log(result))
.catch(result => console.log(result))
}
else {
console.log("No new notification right now!")
}
}
} catch (error) {
console.error(error);
}
}
}
async function getSubscriptionCount(headers) {
let updatedSince = moment().subtract(6, 'minutes').toISOString();
return await axios.get(`${getSubscriptionEndpoint}${updatedSince}`,
{ params: {}, headers: headers })
.then(res => res.data)
.then(res => {
if (res.update.length > 0) {
let total = { unreads: 0, userMentions: 0 }
for (let i = 0; i < res.update.length; i++) {
total.unreads += res.update[i].unread;
total.userMentions += res.update[i].userMentions;
}
return total;
}
else{
return { unreads: 0, userMentions: 0 }
}
})
.catch(err => {
return { unreads: 0, userMentions: 0 };
});
}
async function getUsers() {
return docClient.scan(paramsDDB).promise().then((data) => {
return data.Items;
})
.catch(err => console.log(err));
}
module.exports.handler = (event, context, callback) => {
sendNotifications();
callback(null);
};
{
"name": "notifications",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@ask-utils/proactive-event": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/@ask-utils/proactive-event/-/proactive-event-0.2.3.tgz",
"integrity": "sha512-EkVuqgc7LjwZcD+pz+UGMLId0iZ/9RxvYf0SgOs7V6MoX6s9pqiQ/ZndicxNST9Vw5nxt8yXabr4g/8H6JwZ9A=="
},
"aws-sdk": {
"version": "2.474.0",
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.474.0.tgz",
"integrity": "sha512-nyTZNeVRJix1AStgvH5zcacemgXOhrMrhsXHMmvPkvaXBp3Boj+A79/G8KMd3f/zfjgjRPi9VG0I/BNzfsP3HQ==",
"requires": {
"buffer": "4.9.1",
"events": "1.1.1",
"ieee754": "1.1.8",
"jmespath": "0.15.0",
"querystring": "0.2.0",
"sax": "1.2.1",
"url": "0.10.3",
"uuid": "3.3.2",
"xml2js": "0.4.19"
}
},
"axios": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz",
"integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==",
"requires": {
"follow-redirects": "1.5.10",
"is-buffer": "^2.0.2"
}
},
"base64-js": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz",
"integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw=="
},
"buffer": {
"version": "4.9.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
"integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
"requires": {
"base64-js": "^1.0.2",
"ieee754": "^1.1.4",
"isarray": "^1.0.0"
}
},
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"requires": {
"ms": "2.0.0"
}
},
"events": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
"integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
},
"follow-redirects": {
"version": "1.5.10",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
"integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
"requires": {
"debug": "=3.1.0"
}
},
"ieee754": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz",
"integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q="
},
"is-buffer": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz",
"integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw=="
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"jmespath": {
"version": "0.15.0",
"resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz",
"integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc="
},
"moment": {
"version": "2.24.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"punycode": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
"integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
},
"querystring": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
"integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
},
"sax": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
"integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o="
},
"url": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz",
"integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=",
"requires": {
"punycode": "1.3.2",
"querystring": "0.2.0"
}
},
"uuid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
},
"xml2js": {
"version": "0.4.19",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
"integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
"requires": {
"sax": ">=0.6.0",
"xmlbuilder": "~9.0.1"
}
},
"xmlbuilder": {
"version": "9.0.7",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
}
}
}
{
"name": "notifications",
"version": "1.0.0",
"description": "A microservice to send Notifications to Alexa Devices",
"main": "manpost.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Ashish-Jha",
"license": "ISC",
"dependencies": {
"@ask-utils/proactive-event": "^0.2.3",
"aws-sdk": "^2.474.0",
"axios": "^0.19.0",
"moment": "^2.24.0"
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment