-
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.
feat: initial draft of nodetifications
need to add more providers and modes of notifications
- Loading branch information
1 parent
b020e75
commit adf4e72
Showing
6 changed files
with
288 additions
and
0 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 |
---|---|---|
@@ -1,2 +1,27 @@ | ||
# nodetifications | ||
|
||
Notifications made easy in NodeJS! | ||
|
||
## Features | ||
- Very (c)lean package! < 4kB zipped and < 8kB unzipped, and documented with JSDoc annotations. | ||
- Multiple providers and notification modes in 1 package. | ||
- Very lean dependency, which means less points of failure. | ||
- Highly flexible to your needs, change provider/creds anywhere in between. | ||
- Standardized response formats. All successful requests will return JSON responses. | ||
- Promise based for asynchronous support and no [callback hell](http://callbackhell.com/). | ||
|
||
## Installation | ||
|
||
```zsh | ||
npm install nodetifications | ||
``` | ||
|
||
## Usage | ||
|
||
Complete usage docs with sample code - COMING SOON. | ||
|
||
## Contributing | ||
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. | ||
|
||
## License | ||
[MIT](https://choosealicense.com/licenses/mit/) |
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,77 @@ | ||
import fetch, { Headers } from 'node-fetch'; | ||
|
||
import { GenericError } from './utils/errors.js'; | ||
|
||
const errorCheck = (from, to, userId, password) => { | ||
if (!userId || !password) { | ||
throw new GenericError({ | ||
errType: 'INVALID_CREDENTIALS', | ||
errMsg: 'Invalid userId and password provided, check the credentials again' | ||
}) | ||
} | ||
if (!from) throw new GenericError({ | ||
errType: 'INVALID_FROM', | ||
errMsg: 'Invalid From Number' | ||
}) | ||
if (!to) throw new GenericError({ | ||
errType: 'INVALID_TO', | ||
errMsg: 'Invalid To Number' | ||
}) | ||
} | ||
|
||
const gupShupSMSBaseURL = 'https://enterprise.smsgupshup.com/GatewayAPI/rest'; | ||
const twilioSMSBaseURL = (userId) => `https://api.twilio.com/2010-04-01/Accounts/${userId}/Messages.json`; | ||
|
||
export class SMS { | ||
constructor({ userId, password, provider, from } = {}) { | ||
this.userId = userId; | ||
this.password = password; | ||
this.provider = provider; | ||
this.from = from; | ||
} | ||
|
||
sendSMS({ | ||
provider = this.provider, | ||
from = this.from, | ||
to, | ||
message = [], | ||
userId = this.userId, | ||
password = this.password | ||
} = {}) { | ||
if (provider !== this.provider && (userId === this.userId || password === this.password)) { | ||
throw new GenericError({ | ||
errType: 'INVALID_CREDENTIALS', | ||
errMsg: 'Provider has changed but the credentials have not, if you\'re using the same creds in multiple places, please stop. Get some help.' | ||
}) | ||
} | ||
let encodedMessage; | ||
errorCheck(from, to, userId, password); | ||
if (typeof message !== 'string') { | ||
if (message[0]) { | ||
encodedMessage = message.reduce( | ||
(interimMessage, line, index) => `${interimMessage}${encodeURIComponent(line)}${index === message.length - 1 ? '' : '%0A'}` | ||
, ''); | ||
} else { | ||
encodedMessage = '' | ||
} | ||
} else { | ||
message = encodeURIComponent(message); | ||
} | ||
switch (provider) { | ||
case 'gupshup': return fetch(`${gupShupSMSBaseURL}?method=SendMessage&send_to=${to}&msg=${encodedMessage}&msg_type=TEXT&userid=${userId}&auth_scheme=plain&password=${password}&v=1.1&format=json`).then(result => result.json()); | ||
case 'twilio': const headers = new Headers(); | ||
const auth = Buffer.from(`${userId}:${password}`); | ||
headers.append('Authorization', 'Basic ' + auth.toString('base64')); | ||
return fetch(twilioSMSBaseURL(userId), { method: 'POST', headers, body: { Body: encodedMessage, From: encodeURIComponent(from), To: encodeURIComponent(to) } }).then(response => response.json()); | ||
default: throw new GenericError({ | ||
errType: 'PROVIDER_ERR', | ||
errMsg: 'Invalid provider', | ||
additionalDetails: 'If you would like to see this provider integrated, please raise an issue on https://github.com/ParadoxInfinite/nodetifications/issues/.' | ||
}); | ||
} | ||
} | ||
} | ||
|
||
export default { | ||
SMS | ||
}; |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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,34 @@ | ||
{ | ||
"name": "nodetifications", | ||
"version": "0.0.1", | ||
"description": "Notifications made easy in NodeJS", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"type": "module", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/ParadoxInfinite/nodetifications.git" | ||
}, | ||
"keywords": [ | ||
"notifications", | ||
"node", | ||
"gupshup" | ||
], | ||
"types": "./types/index.d.ts", | ||
"files": [ | ||
"index.js", | ||
"types/index.d.ts", | ||
"utils/errors.js" | ||
], | ||
"author": "Samarth Kulkarni", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/ParadoxInfinite/nodetifications/issues" | ||
}, | ||
"homepage": "https://github.com/ParadoxInfinite/nodetifications#readme", | ||
"dependencies": { | ||
"node-fetch": "^3.0.0" | ||
} | ||
} |
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,32 @@ | ||
export class SMS { | ||
/** | ||
* @param {string} userId - User ID to authenticate with the provider | ||
* @param {string} password - Password to authenticate with the provider | ||
* @param {string} provider - Provider to send messages from. Currently valid providers: `twilio` and `gupshup` | ||
* @param {string} from - Number from which to send the SMS, can be changed per request too, @see `SMS.sendSMS` | ||
*/ | ||
constructor({ userId, password, provider, from }: { | ||
userId: string, | ||
password: string, | ||
provider: string, | ||
from: string | ||
}) | ||
|
||
/** | ||
* @param {string} provider - Defaults to constructor value, but can give a different `provider` than before, however this makes `userId` and `password` mandatory. | ||
* @param {string} from - Defaults to constructor value, but can be different than the `from` before. | ||
* @param {string} to - Mandatory value, recipients's phone number. | ||
* @param {Array} message - Array of strings, each element is a new line. Blank string(without whitespace) for a blank new line. | ||
* @param {string} userId - Defaults to constructor value, but mandatory when `provider` is passed and different from constructor. | ||
* @param {string} password - Defaults to constructor value, but mandatory when `provider` is passed and different from constructor. | ||
* @returns {Promise} A response promise from the provider, if successful, the response will be in JSON format. Errors need to be handled separately. | ||
*/ | ||
sendSMS({ provider, from, to, message, userId, password }: { | ||
provider: string, | ||
from: string, | ||
to: string, | ||
message: Array<string>, | ||
userId: string, | ||
password: string | ||
}): Promise<any> | ||
} |
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,22 @@ | ||
const Reset = "\x1b[0m" | ||
const Bright = "\x1b[1m" | ||
|
||
const FgWhite = "\x1b[37m" | ||
|
||
const BgRed = "\x1b[41m" | ||
|
||
export class GenericError extends Error { | ||
constructor({ | ||
errType = 'UNKNOWN_ERROR', | ||
errMsg = 'Unknown error occured', | ||
additionalDetails = "If you would like to report this to the author, please raise an issue here: https://github.com/ParadoxInfinite/nodetifications/issues/" | ||
}) { | ||
super(); | ||
this.name = `${Bright}${BgRed}${FgWhite}${errType}`, | ||
this.message = `${errMsg}.${Reset}\n${additionalDetails}` | ||
} | ||
} | ||
|
||
export default { | ||
GenericError | ||
} |