Add sling messaging to buttons
This commit is contained in:
parent
2921a7c23c
commit
4ebb66cec5
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -139,3 +139,5 @@ dist
|
||||||
vite.config.js.timestamp-*
|
vite.config.js.timestamp-*
|
||||||
vite.config.ts.timestamp-*
|
vite.config.ts.timestamp-*
|
||||||
.vite/
|
.vite/
|
||||||
|
|
||||||
|
slingtoken.txt
|
||||||
34
buttons.json
34
buttons.json
|
|
@ -16,7 +16,7 @@
|
||||||
"text": "6PM Announcement",
|
"text": "6PM Announcement",
|
||||||
"btnClass": "btn-secondary",
|
"btnClass": "btn-secondary",
|
||||||
"faIcon": "",
|
"faIcon": "",
|
||||||
"name": "LivePage",
|
"name": "6PMAnnouncement",
|
||||||
"doubleHeight": false,
|
"doubleHeight": false,
|
||||||
"context": {
|
"context": {
|
||||||
"context": "custom-emergency.9001.1",
|
"context": "custom-emergency.9001.1",
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
"text": "15 Min Warning",
|
"text": "15 Min Warning",
|
||||||
"btnClass": "btn-info",
|
"btnClass": "btn-info",
|
||||||
"faIcon": "",
|
"faIcon": "",
|
||||||
"name": "LivePage",
|
"name": "CloseWarning",
|
||||||
"doubleHeight": false,
|
"doubleHeight": false,
|
||||||
"context": {
|
"context": {
|
||||||
"context": "custom-emergency.9001.1",
|
"context": "custom-emergency.9001.1",
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
"text": "Pool Closed",
|
"text": "Pool Closed",
|
||||||
"btnClass": "btn-warning",
|
"btnClass": "btn-warning",
|
||||||
"faIcon": "",
|
"faIcon": "",
|
||||||
"name": "LivePage",
|
"name": "PoolClosed",
|
||||||
"doubleHeight": false,
|
"doubleHeight": false,
|
||||||
"context": {
|
"context": {
|
||||||
"context": "custom-emergency.9001.1",
|
"context": "custom-emergency.9001.1",
|
||||||
|
|
@ -52,7 +52,7 @@
|
||||||
"text": "Health Code Violation",
|
"text": "Health Code Violation",
|
||||||
"btnClass": "btn-warning",
|
"btnClass": "btn-warning",
|
||||||
"faIcon": "",
|
"faIcon": "",
|
||||||
"name": "LivePage",
|
"name": "HealthCodeViolation",
|
||||||
"doubleHeight": false,
|
"doubleHeight": false,
|
||||||
"context": {
|
"context": {
|
||||||
"context": "custom-emergency.9001.1",
|
"context": "custom-emergency.9001.1",
|
||||||
|
|
@ -64,7 +64,7 @@
|
||||||
"text": "Snack Shop 15 Min Warning",
|
"text": "Snack Shop 15 Min Warning",
|
||||||
"btnClass": "btn-info",
|
"btnClass": "btn-info",
|
||||||
"faIcon": "",
|
"faIcon": "",
|
||||||
"name": "LivePage",
|
"name": "SnackShopWarning",
|
||||||
"doubleHeight": false,
|
"doubleHeight": false,
|
||||||
"context": {
|
"context": {
|
||||||
"context": "custom-emergency.9001.1",
|
"context": "custom-emergency.9001.1",
|
||||||
|
|
@ -77,7 +77,7 @@
|
||||||
"text": "Snack Shop Closed",
|
"text": "Snack Shop Closed",
|
||||||
"btnClass": "btn-warning",
|
"btnClass": "btn-warning",
|
||||||
"faIcon": "",
|
"faIcon": "",
|
||||||
"name": "LivePage",
|
"name": "SnackShopClosed",
|
||||||
"doubleHeight": false,
|
"doubleHeight": false,
|
||||||
"context": {
|
"context": {
|
||||||
"context": "custom-emergency.9001.1",
|
"context": "custom-emergency.9001.1",
|
||||||
|
|
@ -98,7 +98,9 @@
|
||||||
"context": "custom-emergency.9002.1",
|
"context": "custom-emergency.9002.1",
|
||||||
"timeout": 30000,
|
"timeout": 30000,
|
||||||
"cid": "Emergency Announcement"
|
"cid": "Emergency Announcement"
|
||||||
}
|
},
|
||||||
|
"sling_chat_id": "17132563",
|
||||||
|
"sling_chat_message": "A user has initiated an Emergency Announcement."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "Lightning Alert",
|
"text": "Lightning Alert",
|
||||||
|
|
@ -116,7 +118,7 @@
|
||||||
{
|
{
|
||||||
"text": "EAP Stand By",
|
"text": "EAP Stand By",
|
||||||
"btnClass": "btn-primary",
|
"btnClass": "btn-primary",
|
||||||
"name": "LightningAlert",
|
"name": "EAPStandBy",
|
||||||
"faIcon": "fa-duotone fa-solid fa-pause",
|
"faIcon": "fa-duotone fa-solid fa-pause",
|
||||||
"doubleHeight": false,
|
"doubleHeight": false,
|
||||||
"context": {
|
"context": {
|
||||||
|
|
@ -124,12 +126,14 @@
|
||||||
"timeout": 30000,
|
"timeout": 30000,
|
||||||
"cid": "\"Weather Alert\" <9000>",
|
"cid": "\"Weather Alert\" <9000>",
|
||||||
"dial": "9000"
|
"dial": "9000"
|
||||||
}
|
},
|
||||||
|
"sling_chat_id": "17132563",
|
||||||
|
"sling_chat_message": "CUDA ALERT: EAP Activation - Stand By"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "EAP Evacuate",
|
"text": "EAP Evacuate",
|
||||||
"btnClass": "btn-danger",
|
"btnClass": "btn-danger",
|
||||||
"name": "LightningAlert",
|
"name": "EAPEvac",
|
||||||
"faIcon": "fa-duotone fa-solid fa-person-to-door",
|
"faIcon": "fa-duotone fa-solid fa-person-to-door",
|
||||||
"doubleHeight": false,
|
"doubleHeight": false,
|
||||||
"context": {
|
"context": {
|
||||||
|
|
@ -137,12 +141,14 @@
|
||||||
"timeout": 30000,
|
"timeout": 30000,
|
||||||
"cid": "\"Weather Alert\" <9000>",
|
"cid": "\"Weather Alert\" <9000>",
|
||||||
"dial": "9000"
|
"dial": "9000"
|
||||||
}
|
},
|
||||||
|
"sling_chat_id": "17132563",
|
||||||
|
"sling_chat_message": "CUDA ALERT: EAP Activation - Evacuate"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "Fire Evac",
|
"text": "Fire Evac",
|
||||||
"btnClass": "btn-danger",
|
"btnClass": "btn-danger",
|
||||||
"name": "LightningAlert",
|
"name": "FireEvac",
|
||||||
"faIcon": "fa-duotone fa-solid fa-fire",
|
"faIcon": "fa-duotone fa-solid fa-fire",
|
||||||
"doubleHeight": false,
|
"doubleHeight": false,
|
||||||
"context": {
|
"context": {
|
||||||
|
|
@ -150,7 +156,9 @@
|
||||||
"timeout": 30000,
|
"timeout": 30000,
|
||||||
"cid": "\"Weather Alert\" <9000>",
|
"cid": "\"Weather Alert\" <9000>",
|
||||||
"dial": "9000"
|
"dial": "9000"
|
||||||
}
|
},
|
||||||
|
"sling_chat_id": "17132563",
|
||||||
|
"sling_chat_message": "Fire Evacuation"
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
|
||||||
74
index.js
74
index.js
|
|
@ -5,7 +5,16 @@ require('dotenv').config();
|
||||||
|
|
||||||
const phonesCfg = require('./phones.json');
|
const phonesCfg = require('./phones.json');
|
||||||
const buttonsCfg = require('./buttons.json');
|
const buttonsCfg = require('./buttons.json');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
if (!fs.existsSync(path.join(__dirname, 'slingtoken.txt'))) {
|
||||||
|
// Create empty file
|
||||||
|
fs.writeFileSync(path.join(__dirname, 'slingtoken.txt'), '', 'utf8');
|
||||||
|
console.warn('slingtoken.txt file created. Please add your Sling token to this file to use sling messaging!');
|
||||||
|
}
|
||||||
|
|
||||||
|
var slingToken = fs.readFileSync(path.join(__dirname, 'slingtoken.txt'), 'utf8').trim();
|
||||||
const contexts = {};
|
const contexts = {};
|
||||||
|
|
||||||
// Generate contexts from buttonsCfg
|
// Generate contexts from buttonsCfg
|
||||||
|
|
@ -16,24 +25,47 @@ Object.keys(buttonsCfg).forEach(category => {
|
||||||
context: button.context.context,
|
context: button.context.context,
|
||||||
timeout: button.context.timeout,
|
timeout: button.context.timeout,
|
||||||
cid: button.context.cid,
|
cid: button.context.cid,
|
||||||
...(button.context.dial && { dial: button.context.dial })
|
...(button.context.dial && { dial: button.context.dial }),
|
||||||
|
...(button.sling_chat_id && { sling_chat_id: button.sling_chat_id }),
|
||||||
|
...(button.sling_chat_message && { sling_chat_message: button.sling_chat_message })
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('Generated contexts:', contexts);
|
//console.log('Generated contexts:', contexts);
|
||||||
|
|
||||||
function trigCall(pageType, phone) {
|
function trigCall(pageType, phone) {
|
||||||
// If contexts[pageType] does not exist, return an error
|
// If contexts[pageType] does not exist, return an error
|
||||||
if (!contexts[pageType]) {
|
if (!contexts[pageType]) {
|
||||||
throw new Error(`Invalid page type: ${pageType}`);
|
throw new Error(`Invalid page type: ${pageType}`);
|
||||||
}
|
}
|
||||||
const { context, timeout, cid, dial } = contexts[pageType];
|
const { context, timeout, cid, dial, sling_chat_id, sling_chat_message } = contexts[pageType];
|
||||||
const targetNumber = dial || phone;
|
const targetNumber = dial || phone;
|
||||||
if (!targetNumber) {
|
if (!targetNumber) {
|
||||||
throw new Error(`Phone number is required for page type: ${pageType}`);
|
throw new Error(`Phone number is required for page type: ${pageType}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Slink chat notification
|
||||||
|
if (sling_chat_id && sling_chat_message) {
|
||||||
|
fetch(`https://api.getsling.com/v1/conversations/${sling_chat_id}/messages`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Authorization': `${slingToken}`,
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
'content': sling_chat_message
|
||||||
|
})
|
||||||
|
}).then(res => res.json()).then(data => {
|
||||||
|
if (data && data.success) {
|
||||||
|
console.log('Sling chat message sent successfully.');
|
||||||
|
} else {
|
||||||
|
console.error('Error sending Sling chat message:', data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
originateCall(targetNumber, context, 0, timeout, cid).then((output) => {
|
originateCall(targetNumber, context, 0, timeout, cid).then((output) => {
|
||||||
console.log(`Call originated: ${output}`);
|
console.log(`Call originated: ${output}`);
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
|
|
@ -68,6 +100,42 @@ function originateCall(number, context, delay, timeout, cid, variables = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Sling chat stuff; Check current token with GET https://api.getsling.com/v1/account/session, refresh with POST https://api.getsling.com/v1/account/session (GET NEW TOKEN FROM RETURN AUTHORIZATION HEADER)
|
||||||
|
async function slingAuthLoop() {
|
||||||
|
console.log("Start slingAuthLoop")
|
||||||
|
if (!slingToken) {
|
||||||
|
console.warn('No Sling token provided in environment variables.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setTimeout(slingAuthLoop, 15 * 60 * 1000); // Refresh every 15 minutes
|
||||||
|
const sessionCheck = await fetch('https://api.getsling.com/v1/account/session', {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Authorization': `${slingToken}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log(sessionCheck)
|
||||||
|
if (sessionCheck && sessionCheck.ok) {
|
||||||
|
console.log('Sling session is valid. Refreshing token...');
|
||||||
|
const sessionRefresh = await fetch('https://api.getsling.com/v1/account/session', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Authorization': `${slingToken}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const newToken = sessionRefresh.headers.get('Authorization');
|
||||||
|
if (newToken) {
|
||||||
|
slingToken = newToken;
|
||||||
|
fs.writeFileSync(path.join(__dirname, 'slingtoken.txt'), newToken, 'utf8');
|
||||||
|
console.log('Sling token refreshed.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error('Sling session is invalid. Please get a new token manually!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
slingAuthLoop();
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const HOST = process.env.HOST || 'localhost';
|
const HOST = process.env.HOST || 'localhost';
|
||||||
const PORT = process.env.PORT || 3000;
|
const PORT = process.env.PORT || 3000;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue