const blocked = [ '0', '0000', '9998', '9999' ]; import dotenv from 'dotenv'; dotenv.config({ quiet: true }) import AMISocket from 'ami'; const sock = new AMISocket({ connect: { host: '127.0.0.1', port: 5038 }, credentials: { username: process.env.AMI_USER, secret: process.env.AMI_SECRET }, events: true }) import Discord from 'discord.js'; const hook = new Discord.WebhookClient({ url: process.env.DISCORD_WEBHOOK_URL }); const cfTypes = { CF: "Unconditional", CFB: "Busy", CFU: "Unavailable", } const main = () => { var respData = []; console.log('checking') // getList for CF, CFB, CFU sock.getList({ action: 'DBGetTree', family: 'CF' }).then(async (response) => { // Responses are an array of objects. The first should always have eventlist: 'start', and last should have eventlist: 'complete'. Remove these, make an array of objects {key, val} based on the rest of the response objects. let entries = response.filter(r => r.eventlist !== 'start' && r.eventlist !== 'Complete').map(r => ({ key: r.key, val: r.val })); for (let entry of entries) { let stuff = entry.key.split('/'); let type = stuff[1]; let ext = stuff[2]; console respData.push({ extension: ext, type: type, target: entry.val }); } }).then(() => { sock.getList({ action: 'DBGetTree', family: 'CFB' }).then(async (response) => { let entries = response.filter(r => r.eventlist !== 'start' && r.eventlist !== 'Complete').map(r => ({ key: r.key, val: r.val })); for (let entry of entries) { let stuff = entry.key.split('/'); let type = stuff[1]; let ext = stuff[2]; console respData.push({ extension: ext, type: type, target: entry.val }); } }).then(() => { sock.getList({ action: 'DBGetTree', family: 'CFU' }).then(async (response) => { let entries = response.filter(r => r.eventlist !== 'start' && r.eventlist !== 'Complete').map(r => ({ key: r.key, val: r.val })); for (let entry of entries) { let stuff = entry.key.split('/'); let type = stuff[1]; let ext = stuff[2]; console respData.push({ extension: ext, type: type, target: entry.val }); } }).then(() => { console.log(`Found ${respData.length} call forwards.`); for (let cf of respData) { // Check if forward target is anything in the 700-800 range, or is a number in the blocked list if ((cf.target >= 700 && cf.target < 800) || blocked.includes(cf.target)) { // Violation. Remove call forward from db. console.log(`---> Violation found on extension ${cf.extension}. Removing call forward to ${cf.target}`); sock.send({ action: 'DBDel', family: cf.type, key: cf.extension }).then((resp) => { console.log(`-----> Call forward removed successfully.`); hook.send(`:no_entry: **Call Forward Removed** :no_entry:\nExtension **${cf.extension}** had a **${cfTypes[cf.type]}** call forward to **${cf.target}** The call forward has been removed.`); }) } }; setTimeout(main, 5000); // Repeat every 60 seconds }); }); }) } const startup = async () => { sock.connect().then(() => { console.log(sock.amiVersion) main(); }).catch((err) => { console.error('Error connecting to AMI:', err); setTimeout(startup, 10000); // Retry after 10 seconds }); } startup();