From 4fd1e69e5962ee1ad1417ad76fd2d2347e9d91de Mon Sep 17 00:00:00 2001 From: dsumberac <146445066+dsTw5@users.noreply.github.com> Date: Tue, 11 Jun 2024 15:30:04 +0100 Subject: [PATCH] Add files via upload --- number-activity/assets/index.html | 603 +++++ number-activity/assets/styles.css | 24 + number-activity/functions/get_account.js | 17 + number-activity/functions/listNumbers.js | 53 + number-activity/functions/mask_account.js | 15 + number-activity/functions/usageNumber.js | 501 +++++ number-activity/package.json | 7 + number-activity/readme.txt | 19 + number-usage/assets/index.html | 2472 +++++++++++++++++++++ number-usage/assets/styles.css | 35 + number-usage/functions/call_log.js | 51 + number-usage/functions/get_account.js | 18 + number-usage/functions/mask_account.js | 15 + number-usage/functions/message_log.js | 51 + number-usage/package.json | 7 + 15 files changed, 3888 insertions(+) create mode 100644 number-activity/assets/index.html create mode 100644 number-activity/assets/styles.css create mode 100644 number-activity/functions/get_account.js create mode 100644 number-activity/functions/listNumbers.js create mode 100644 number-activity/functions/mask_account.js create mode 100644 number-activity/functions/usageNumber.js create mode 100644 number-activity/package.json create mode 100644 number-activity/readme.txt create mode 100644 number-usage/assets/index.html create mode 100644 number-usage/assets/styles.css create mode 100644 number-usage/functions/call_log.js create mode 100644 number-usage/functions/get_account.js create mode 100644 number-usage/functions/mask_account.js create mode 100644 number-usage/functions/message_log.js create mode 100644 number-usage/package.json diff --git a/number-activity/assets/index.html b/number-activity/assets/index.html new file mode 100644 index 000000000..75d8db7b8 --- /dev/null +++ b/number-activity/assets/index.html @@ -0,0 +1,603 @@ + + + + + + + + Check Number Activity + + + + + + + +
+
+ + +
+
+
+
+

+ +
+

Welcome!

+

Your live application with Twilio is ready to use!

+
+

+ +

+ Before you start, make sure that the checkbox "Add my Twilio + Credentials (ACCOUNT_SID) and (AUTH_TOKEN) to ENV" is checked in the + "Environmental Variables" of this Function. If it's not checked, + enable it and click "Deploy All" at the bottom. +

+

Check activity per number on main account or subaccounts

+ +

+ This page allows you to check if there is SMS/MMS and/or Call activity + for each number that is currently active on your Main account or the inserted subaccount. If in + the results the SMS/MMS, Whatsapp or Call SID is present, it means that there was + activity with the number in the selected time-period. The columns with the word "Date" show the date of the most recent activity of the number.
+ The columns that have "Volume" in their names + show how many SMS/MMS, Whatsapp requests or Calls were made in the selected time-period. + The SMS/MMS volumes shows the number of SMS/MMS requests, not the number of + segments. The data is checked based on UTC timezone. +
+ Because the Messaging API only displays messages that were sent in the + last 400 days, make sure that the selected From Date is within the + last 400 days. An error will be returned if it's not. +

+ Be careful, if you deleted your Message and/or Call logs, or + they are deleted automatically for your account, those messages/calls will + not be returned nor counted with this report.
+ SIP Trunking calls are not checked with this app, since those calls are logged differently in the format "sip:number@domain;edge/location"
+ If you have a large amount of numbers on your account, use the + "Check Activity and + Download Without Listing Data" button, which will download the + results directly without listing them on this page.
+ Results listed on this page will be limited to 200 numbers. "Check Activity and + Download Without Listing Data" button has no limits. +

+ While the number activity is being checked, a progress log will be displayed at the bottom. +

+ +

+ Because this is a publicly accessible URL that automatically uses your + Account SID and auth_token, to limit it's access, please set a + password in your + Function + - open the Function and click on "Environment Variables" in the bottom + left corner, and change the value of Password. Click + "Deploy All" afterwards in the bottom left corner. +
+

+ Password:
+
+

You are working with account:

+
+
+
+
+

+ Enter the subaccount SID. Leave empty if you want to check the activity + on your main account. +

+
+
+

+ Enter the Twilio number for which you would like to check activity. Leave + empty if you want to check the activity for all Twilio numbers present on + the account. +

+
+

+ Only show results for numbers that start with (filter based on country-code): +

+
+
+ From Date: + To Date: +
+
+ Use volume limits? + +   Maximum number of messages/calls to check per number (1-2000): + +
+ +

+
Select the format that will be used when the data is downloaded:
+ +
+ +

+
+
+
+

+ +
+ + +
+

+        
+ + +
+
+ +
+
+ + + + diff --git a/number-activity/assets/styles.css b/number-activity/assets/styles.css new file mode 100644 index 000000000..de92476af --- /dev/null +++ b/number-activity/assets/styles.css @@ -0,0 +1,24 @@ +pre { + white-space: pre-wrap; + word-wrap: break-word; +} + +.alert { + padding: 15px; + margin-top: 10px; + border: 1px solid transparent; + border-radius: 4px; +} + +.alert-info { + border-color: #bce8f1; + color: #31708f; + background-color: #d9edf7; + word-wrap: break-word; +} + +.alert-error { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} diff --git a/number-activity/functions/get_account.js b/number-activity/functions/get_account.js new file mode 100644 index 000000000..e6db74707 --- /dev/null +++ b/number-activity/functions/get_account.js @@ -0,0 +1,17 @@ +exports.handler = async function (context, event, callback) { + let finalData = null; + const accountSid = { acc: process.env.ACCOUNT_SID }; + + if (event.request.headers.authorization !== process.env.Password) { + finalData = { er: 0 }; + return callback(null, finalData); + } + try { + return callback(null, accountSid); + } catch (error) { + console.error(error.message); + response.setStatusCode(error.status || 400); + response.setBody({ error: error.message }); + return callback(null, response); + } +}; diff --git a/number-activity/functions/listNumbers.js b/number-activity/functions/listNumbers.js new file mode 100644 index 000000000..43d679877 --- /dev/null +++ b/number-activity/functions/listNumbers.js @@ -0,0 +1,53 @@ +exports.handler = async function (context, event, callback) { + let finalData = null; + let resp = null; + let pageResp = null; + let str = ''; + const accountSid = process.env.ACCOUNT_SID; + const authToken = process.env.AUTH_TOKEN; + const subAccount = event.subAcc; + const client = require('twilio')(accountSid, authToken, { + accountSid: subAccount, + }); + + const response = new Twilio.Response(); + response.appendHeader('Content-Type', 'application/json'); + + if (event.request.headers.authorization !== process.env.Password) { + finalData = { er: 0 }; + return callback(null, finalData); + } + try { + if (event.number !== undefined) { + pageResp = await client.incomingPhoneNumbers.list({ + limit: 1, + phoneNumber: event.number, + }); + + str = JSON.stringify(pageResp).length; + if (str < 3) { + response.setStatusCode(200); + response.setBody('number not found'); + return callback(null, response); + } + + return callback(null, pageResp); + } else if (event.pageSize > 0) { + pageResp = await client.incomingPhoneNumbers.page({ + pageSize: event.pageSize, + Page: event.page, + pageToken: event.pageToken, + }); + + return callback(null, pageResp); + } + aaa; + resp = await client.incomingPhoneNumbers.list(); + return callback(null, resp); + } catch (error) { + console.error(error.message); + response.setStatusCode(error.status || 400); + response.setBody({ error: error.message }); + return callback(null, response); + } +}; diff --git a/number-activity/functions/mask_account.js b/number-activity/functions/mask_account.js new file mode 100644 index 000000000..8d020501b --- /dev/null +++ b/number-activity/functions/mask_account.js @@ -0,0 +1,15 @@ +exports.handler = async function (context, event, callback) { + const masked = + String(process.env.ACCOUNT_SID).slice(0, 28).replace(/./g, '*') + + String(process.env.ACCOUNT_SID).slice(-6); + const accountSid = { acc: masked }; + + try { + return callback(null, accountSid); + } catch (error) { + console.error(error.message); + response.setStatusCode(error.status || 400); + response.setBody({ error: error.message }); + return callback(null, response); + } +}; diff --git a/number-activity/functions/usageNumber.js b/number-activity/functions/usageNumber.js new file mode 100644 index 000000000..ed92f01ac --- /dev/null +++ b/number-activity/functions/usageNumber.js @@ -0,0 +1,501 @@ +exports.handler = async function (context, event, callback) { + let finalData = null; + let inboundSMS = null; + let outboundSMS = null; + let inboundCall = null; + let outboundCall = null; + let smsInboundUsage = null; + let smsOutboundUsage = null; + let whatsappInboundSMS = null; + let whatsappInboundUsage = null; + let whatsappOutboundSMS = null; + let whatsappOutboundUsage = null; + let callInboundUsage = null; + let callOutboundUsage = null; + let lim = Number(event.limit); + let inboundSMSDate = null; + let outboundSMSDate = null; + let inboundCallDate = null; + let outboundCallDate = null; + let whatsappInboundSMSDate = null; + let whatsappOutboundSMSDate = null; + + let wNumber = 'whatsapp:' + event.number; + + const accountSid = process.env.ACCOUNT_SID; + const authToken = process.env.AUTH_TOKEN; + const subAccount = event.subAcc; + const client = require('twilio')(accountSid, authToken, { + accountSid: subAccount, + }); + + const response = new Twilio.Response(); + + if (event.request.headers.authorization !== process.env.Password) { + finalData = { er: 0 }; + return callback(null, finalData); + } + + try { + if (event.limit === undefined) { + // SMS or MMS + await client.messages + .list({ + dateSentAfter: new Date( + Date.UTC( + event.startDate.split('-')[0], + event.startDate.split('-')[1] - 1, + event.startDate.split('-')[2], + 0, + 0, + 0 + ) + ), + dateSentBefore: new Date( + Date.UTC( + event.endDate.split('-')[0], + event.endDate.split('-')[1] - 1, + event.endDate.split('-')[2], + 0, + 0, + 0 + ) + ), + to: event.number, + }) + .then((messages) => { + for (let m in messages) { + inboundSMS = messages[m].sid; + smsInboundUsage = messages.length; + inboundSMSDate = messages[m].dateCreated; + break; + } + }); + + await client.messages + .list({ + dateSentAfter: new Date( + Date.UTC( + event.startDate.split('-')[0], + event.startDate.split('-')[1] - 1, + event.startDate.split('-')[2], + 0, + 0, + 0 + ) + ), + dateSentBefore: new Date( + Date.UTC( + event.endDate.split('-')[0], + event.endDate.split('-')[1] - 1, + event.endDate.split('-')[2], + 0, + 0, + 0 + ) + ), + from: event.number, + }) + .then((messages) => { + for (let m in messages) { + outboundSMS = messages[m].sid; + smsOutboundUsage = messages.length; + outboundSMSDate = messages[m].dateCreated; + break; + } + }); + + // Whatsapp + await client.messages + .list({ + dateSentAfter: new Date( + Date.UTC( + event.startDate.split('-')[0], + event.startDate.split('-')[1] - 1, + event.startDate.split('-')[2], + 0, + 0, + 0 + ) + ), + dateSentBefore: new Date( + Date.UTC( + event.endDate.split('-')[0], + event.endDate.split('-')[1] - 1, + event.endDate.split('-')[2], + 0, + 0, + 0 + ) + ), + to: wNumber, + }) + .then((messages) => { + for (let m in messages) { + whatsappInboundSMS = messages[m].sid; + whatsappInboundUsage = messages.length; + whatsappInboundSMSDate = messages[m].dateCreated; + break; + } + }); + + await client.messages + .list({ + dateSentAfter: new Date( + Date.UTC( + event.startDate.split('-')[0], + event.startDate.split('-')[1] - 1, + event.startDate.split('-')[2], + 0, + 0, + 0 + ) + ), + dateSentBefore: new Date( + Date.UTC( + event.endDate.split('-')[0], + event.endDate.split('-')[1] - 1, + event.endDate.split('-')[2], + 0, + 0, + 0 + ) + ), + from: wNumber, + }) + .then((messages) => { + for (let m in messages) { + whatsappOutboundSMS = messages[m].sid; + whatsappOutboundUsage = messages.length; + whatsappOutboundSMSDate = messages[m].dateCreated; + break; + } + }); + + await client.calls + .list({ + startTimeAfter: new Date( + Date.UTC( + event.startDate.split('-')[0], + event.startDate.split('-')[1] - 1, + event.startDate.split('-')[2], + 0, + 0, + 0 + ) + ), + startTimeBefore: new Date( + Date.UTC( + event.endDate.split('-')[0], + event.endDate.split('-')[1] - 1, + event.endDate.split('-')[2], + 0, + 0, + 0 + ) + ), + to: event.number, + }) + .then((calls) => { + for (let c in calls) { + inboundCall = calls[c].sid; + callInboundUsage = calls.length; + inboundCallDate = calls[c].dateCreated; + break; + } + }); + + await client.calls + .list({ + startTimeAfter: new Date( + Date.UTC( + event.startDate.split('-')[0], + event.startDate.split('-')[1] - 1, + event.startDate.split('-')[2], + 0, + 0, + 0 + ) + ), + startTimeBefore: new Date( + Date.UTC( + event.endDate.split('-')[0], + event.endDate.split('-')[1] - 1, + event.endDate.split('-')[2], + 0, + 0, + 0 + ) + ), + from: event.number, + }) + .then((calls) => { + for (let c in calls) { + outboundCall = calls[c].sid; + callOutboundUsage = calls.length; + outboundCallDate = calls[c].dateCreated; + break; + } + }); + + finalData = { + 0: inboundSMS, + 1: inboundSMSDate, + 2: outboundSMS, + 3: outboundSMSDate, + 4: whatsappInboundSMS, + 5: whatsappInboundSMSDate, + 6: whatsappOutboundSMS, + 7: whatsappOutboundSMSDate, + 8: inboundCall, + 9: inboundCallDate, + 10: outboundCall, + 11: outboundCallDate, + 12: smsInboundUsage, + 13: smsOutboundUsage, + 14: whatsappInboundUsage, + 15: whatsappOutboundUsage, + 16: callInboundUsage, + 17: callOutboundUsage, + }; + + console.log(finalData); + return callback(null, finalData); + } else { + await client.messages + .list({ + dateSentAfter: new Date( + Date.UTC( + event.startDate.split('-')[0], + event.startDate.split('-')[1] - 1, + event.startDate.split('-')[2], + 0, + 0, + 0 + ) + ), + dateSentBefore: new Date( + Date.UTC( + event.endDate.split('-')[0], + event.endDate.split('-')[1] - 1, + event.endDate.split('-')[2], + 0, + 0, + 0 + ) + ), + to: event.number, + limit: lim, + }) + .then((messages) => { + for (let m in messages) { + inboundSMS = messages[m].sid; + smsInboundUsage = messages.length; + inboundSMSDate = messages[m].dateCreated; + break; + } + }); + + await client.messages + .list({ + dateSentAfter: new Date( + Date.UTC( + event.startDate.split('-')[0], + event.startDate.split('-')[1] - 1, + event.startDate.split('-')[2], + 0, + 0, + 0 + ) + ), + dateSentBefore: new Date( + Date.UTC( + event.endDate.split('-')[0], + event.endDate.split('-')[1] - 1, + event.endDate.split('-')[2], + 0, + 0, + 0 + ) + ), + from: event.number, + limit: lim, + }) + .then((messages) => { + for (let m in messages) { + outboundSMS = messages[m].sid; + smsOutboundUsage = messages.length; + outboundSMSDate = messages[m].dateCreated; + break; + } + }); + + // Whatsapp + await client.messages + .list({ + dateSentAfter: new Date( + Date.UTC( + event.startDate.split('-')[0], + event.startDate.split('-')[1] - 1, + event.startDate.split('-')[2], + 0, + 0, + 0 + ) + ), + dateSentBefore: new Date( + Date.UTC( + event.endDate.split('-')[0], + event.endDate.split('-')[1] - 1, + event.endDate.split('-')[2], + 0, + 0, + 0 + ) + ), + to: wNumber, + limit: lim, + }) + .then((messages) => { + for (let m in messages) { + whatsappInboundSMS = messages[m].sid; + whatsappInboundUsage = messages.length; + whatsappInboundSMSDate = messages[m].dateCreated; + break; + } + }); + + await client.messages + .list({ + dateSentAfter: new Date( + Date.UTC( + event.startDate.split('-')[0], + event.startDate.split('-')[1] - 1, + event.startDate.split('-')[2], + 0, + 0, + 0 + ) + ), + dateSentBefore: new Date( + Date.UTC( + event.endDate.split('-')[0], + event.endDate.split('-')[1] - 1, + event.endDate.split('-')[2], + 0, + 0, + 0 + ) + ), + from: wNumber, + limit: lim, + }) + .then((messages) => { + for (let m in messages) { + whatsappOutboundSMS = messages[m].sid; + whatsappOutboundUsage = messages.length; + whatsappOutboundSMSDate = messages[m].dateCreated; + break; + } + }); + + // Calls + await client.calls + .list({ + startTimeAfter: new Date( + Date.UTC( + event.startDate.split('-')[0], + event.startDate.split('-')[1] - 1, + event.startDate.split('-')[2], + 0, + 0, + 0 + ) + ), + startTimeBefore: new Date( + Date.UTC( + event.endDate.split('-')[0], + event.endDate.split('-')[1] - 1, + event.endDate.split('-')[2], + 0, + 0, + 0 + ) + ), + to: event.number, + limit: lim, + }) + .then((calls) => { + for (let c in calls) { + inboundCall = calls[c].sid; + callInboundUsage = calls.length; + inboundCallDate = calls[c].dateCreated; + break; + } + }); + + await client.calls + .list({ + startTimeAfter: new Date( + Date.UTC( + event.startDate.split('-')[0], + event.startDate.split('-')[1] - 1, + event.startDate.split('-')[2], + 0, + 0, + 0 + ) + ), + startTimeBefore: new Date( + Date.UTC( + event.endDate.split('-')[0], + event.endDate.split('-')[1] - 1, + event.endDate.split('-')[2], + 0, + 0, + 0 + ) + ), + from: event.number, + limit: lim, + }) + .then((calls) => { + for (let c in calls) { + outboundCall = calls[c].sid; + callOutboundUsage = calls.length; + outboundCallDate = calls[c].dateCreated; + break; + } + }); + + finalData = { + 0: inboundSMS, + 1: inboundSMSDate, + 2: outboundSMS, + 3: outboundSMSDate, + 4: whatsappInboundSMS, + 5: whatsappInboundSMSDate, + 6: whatsappOutboundSMS, + 7: whatsappOutboundSMSDate, + 8: inboundCall, + 9: inboundCallDate, + 10: outboundCall, + 11: outboundCallDate, + 12: smsInboundUsage, + 13: smsOutboundUsage, + 14: whatsappInboundUsage, + 15: whatsappOutboundUsage, + 16: callInboundUsage, + 17: callOutboundUsage, + }; + + console.log(finalData); + return callback(null, finalData); + } + } catch (error) { + console.error(error.message); + response.setStatusCode(error.status || 400); + response.setBody({ error: error.message }); + return callback(null, response); + } +}; diff --git a/number-activity/package.json b/number-activity/package.json new file mode 100644 index 000000000..25969df01 --- /dev/null +++ b/number-activity/package.json @@ -0,0 +1,7 @@ +{ + "version": "1.0.0", + "private": true, + "dependencies": { + "twilio": "^3.61.0" + } +} diff --git a/number-activity/readme.txt b/number-activity/readme.txt new file mode 100644 index 000000000..0ab24f041 --- /dev/null +++ b/number-activity/readme.txt @@ -0,0 +1,19 @@ +Instructions + +On index.html you will see various fields and buttons that you can use. + +The 1st one is to insert the password. This is important as the app will not work without a correct password. +To change the password, you need to open your function, click on Environmental Variables and edit the Password variable. + +The 2nd one is the section that shows which Main account you are working with. +Because this is a public URL, your account SID is masked by default and you can unmask it by inserting the correct password and clicking on "Show Account" button. If the password is incorrect, the message "Wrong password" will be displayed. + +In the next section you can insert the sub account SID for which you want to check the usage for each number on the sub account. + +In the following section, you can insert the phone number for which you want to check the usage. You need to insert the number that is present on the main account (if the sub-account field is empty) or a number that is present on the inserted sub-account. If the number is not present on the account, an error will be displayed. + +Select the desired timeline and use one of the 2 buttons "Check and List Activity" or "Check Activity and Download Without Listing Data". + +The 1st button checks the usage per number and displays the results on the page, while the 2nd button checks the usage and directly downloads the results without displaying them. + +If you list the data, you can clear the list with the "Clear list" button or download the results with "Download listed numbers" button. \ No newline at end of file diff --git a/number-usage/assets/index.html b/number-usage/assets/index.html new file mode 100644 index 000000000..d786891a3 --- /dev/null +++ b/number-usage/assets/index.html @@ -0,0 +1,2472 @@ + + + + + + + + Check To/From Usage + + + + + + + +
+
+ + +
+
+
+
+

+ +
+

Welcome!

+

Your live application with Twilio is ready to use!

+
+

+ +

+ Before you start, make sure that the checkbox "Add my Twilio + Credentials (ACCOUNT_SID) and (AUTH_TOKEN) to ENV" is checked in the + "Environmental Variables" of this Function. If it's not checked, + enable it and click "Deploy All" at the bottom. +

+

Check usage per To and From on main account or subaccounts

+ +

+ This page allows you to check how many messages and calls are associated with the To and From used to send/receive messages or calls.
+ The reults include alpha senders, SIP trunking, outbound replies to inbound messages etc... The data is divided based on the "Direction" of the message and call. Check the Message Resource and + Call Resource to see all possible message/call "Direction" and what they mean.
+ If in the results "From" is shown as "null", it means that this is an inbound message/call and the "To" column needs to be looked at. Same applies if "To" is "null", in which case "From" needs to be looked at as it's an outbound message/call.
+ The Segments column applies to Messages, while the Minutes column applies to Calls. The column Assets shows the related To or From with the difference that the number is extracted from the Whastapp log and from the SIP Trunking log. Assets can be used to filter the results regardless of traffic type and direction. +

+ Because the Messaging API only displays messages that were sent in the + last 400 days, make sure that the selected From Date is within the + last 400 days. An error will be returned if it's not. +

+ The section "Group based on Country?" allows you to check from where the inbound messages/calls came from, and where your outbound messages/calls were sent to. For inbound traffic the country of the From is checked, while for outbound the country of the To is checked.
+ The Country is checked based on the "Country list" section. You are free to add and change the prefixes and country name as you see fit. The format must be "+prefix countryName". The countryName must start with a letter and it can only contain letters, - sign, and _ sign. +
+ The prefix search is done from longest to shortest. For example, if an inbound message is received from the number "+15556789", and in the country list you have the prefixes "+1 US-CA" and "+1555 US-movies", in the results the country will be marked as "US-movies" because the longer prefix +1555 was detected for the number "+15556789". +
If the prefix of a number is not on the country list, in the results those messages/calls will be marked with country 'Other'. Similarly, if you received inbound messages from alpha senders or short codes, they will be marked as "Alpha" and "ShortCode" respectively. For calls where the country is not detected, it will be marked as "TwilioClient" or "Other".

Because there could be many prefixes to check, the app might be slower if you are grouping by country. In order to speed up the app, delete the prefixes/countries you don't need. The default +1 prefix is marked as "United_States-Canada".

+ + Be careful, if you deleted your Message and/or Call logs, or + they are deleted automatically for your account, those messages/calls will + not be part of the results with this report. Only messages/calls which are part of the 2 mentioned APIs will be included in the results. Same applies to the price/cost of the message/call - if there are costs associated with the message/call that are not part of the API, those costs will not be included in the results.

+ If you used many different numbers to send/receive messages, many alpha senders and similar, use the + "Check Usage and + Download Without Listing Data" button, which will download the + results directly without listing them on this page.
+ + If you are experiencing timeouts, adjust the "Maximum # of messages/calls per page" field. Regarless which number you input, all message and call logs will be checked. + +

+ While the number usage is being checked, a progress log will be displayed at the bottom. +

+ +

+ Because this is a publicly accessible URL that automatically uses your + Account SID and auth_token, to limit it's access, please set a + password in your + Function + - open the Function and click on "Environment Variables" in the bottom + left corner, and change the value of Password. Click + "Deploy All" afterwards in the bottom left corner. +
+

+ Password:
+
+

You are working with account:

+
+
+
+
+

+ Enter the subaccount SID. Leave empty if you want to check usage + on your main account. +

+
+
+
+ From Date: + To Date (before): + Maximum # of messages/calls per page (1-1000): +
+ +
Include traffic type: + +   + +
+
+ +
Group based on Country? + +
+ Country list:
+ +
+
+ +

+
Select the format that will be used when the data is downloaded:
+ +
+ +

+
+
+
+

+ +
+ + +
+

+        
+ + +
+
+ +
+
+ + + + \ No newline at end of file diff --git a/number-usage/assets/styles.css b/number-usage/assets/styles.css new file mode 100644 index 000000000..72a1e9988 --- /dev/null +++ b/number-usage/assets/styles.css @@ -0,0 +1,35 @@ +pre { + white-space: pre-wrap; + word-wrap: break-word; +} + +.alert { + padding: 15px; + margin-top: 10px; + border: 1px solid transparent; + border-radius: 4px; +} + +.alert-info { + border-color: #bce8f1; + color: #31708f; + background-color: #d9edf7; +} + +.alert-error { + color: #c21e1e; + background-color: #f2dede; + border-color: #ebccd1; +} + +.alert-success { + border-color: #bce8f1; + color: #31708f; + background-color: #d9edf7; +} + +.alert-warning { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} diff --git a/number-usage/functions/call_log.js b/number-usage/functions/call_log.js new file mode 100644 index 000000000..945e6eb16 --- /dev/null +++ b/number-usage/functions/call_log.js @@ -0,0 +1,51 @@ +exports.handler = async function (context, event, callback) { + let result = null; + const accountSid = process.env.ACCOUNT_SID; + const authToken = process.env.AUTH_TOKEN; + const subAccount = event.subAcc; + const client = require('twilio')(accountSid, authToken, { + accountSid: subAccount, + }); + + const response = new Twilio.Response(); + + if (event.request.headers.authorization !== process.env.Password) { + finalData = { er: 0 }; + return callback(null, finalData); + } + + try { + result = await client.calls.page({ + startTimeAfter: new Date( + Date.UTC( + event.startDate.split('-')[0], + event.startDate.split('-')[1] - 1, + event.startDate.split('-')[2], + 0, + 0, + 0 + ) + ), + startTimeBefore: new Date( + Date.UTC( + event.endDate.split('-')[0], + event.endDate.split('-')[1] - 1, + event.endDate.split('-')[2], + 0, + 0, + 0 + ) + ), + pageSize: event.pageSize, + Page: event.page, + pageToken: event.pageToken, + }); + + return callback(null, result); + } catch (error) { + console.error(error.message); + response.setStatusCode(error.status || 400); + response.setBody({ error: error.message }); + return callback(null, response); + } +}; diff --git a/number-usage/functions/get_account.js b/number-usage/functions/get_account.js new file mode 100644 index 000000000..9d5bfb3e8 --- /dev/null +++ b/number-usage/functions/get_account.js @@ -0,0 +1,18 @@ +exports.handler = async function (context, event, callback) { + let finalData = null; + const accountSid = { acc: process.env.ACCOUNT_SID }; + + if (event.request.headers.authorization !== process.env.Password) { + finalData = { er: 0 }; + return callback(null, finalData); + } + + try { + return callback(null, accountSid); + } catch (error) { + console.error(error.message); + response.setStatusCode(error.status || 400); + response.setBody({ error: error.message }); + return callback(null, response); + } +}; diff --git a/number-usage/functions/mask_account.js b/number-usage/functions/mask_account.js new file mode 100644 index 000000000..8d020501b --- /dev/null +++ b/number-usage/functions/mask_account.js @@ -0,0 +1,15 @@ +exports.handler = async function (context, event, callback) { + const masked = + String(process.env.ACCOUNT_SID).slice(0, 28).replace(/./g, '*') + + String(process.env.ACCOUNT_SID).slice(-6); + const accountSid = { acc: masked }; + + try { + return callback(null, accountSid); + } catch (error) { + console.error(error.message); + response.setStatusCode(error.status || 400); + response.setBody({ error: error.message }); + return callback(null, response); + } +}; diff --git a/number-usage/functions/message_log.js b/number-usage/functions/message_log.js new file mode 100644 index 000000000..72d032d33 --- /dev/null +++ b/number-usage/functions/message_log.js @@ -0,0 +1,51 @@ +exports.handler = async function (context, event, callback) { + let result = null; + const accountSid = process.env.ACCOUNT_SID; + const authToken = process.env.AUTH_TOKEN; + const subAccount = event.subAcc; + const client = require('twilio')(accountSid, authToken, { + accountSid: subAccount, + }); + + const response = new Twilio.Response(); + + if (event.request.headers.authorization !== process.env.Password) { + finalData = { er: 0 }; + return callback(null, finalData); + } + + try { + result = await client.messages.page({ + dateSentAfter: new Date( + Date.UTC( + event.startDate.split('-')[0], + event.startDate.split('-')[1] - 1, + event.startDate.split('-')[2], + 0, + 0, + 0 + ) + ), + dateSentBefore: new Date( + Date.UTC( + event.endDate.split('-')[0], + event.endDate.split('-')[1] - 1, + event.endDate.split('-')[2], + 0, + 0, + 0 + ) + ), + pageSize: event.pageSize, + Page: event.page, + pageToken: event.pageToken, + }); + + return callback(null, result); + } catch (error) { + console.error(error.message); + response.setStatusCode(error.status || 400); + response.setBody({ error: error.message }); + return callback(null, response); + } +}; diff --git a/number-usage/package.json b/number-usage/package.json new file mode 100644 index 000000000..25969df01 --- /dev/null +++ b/number-usage/package.json @@ -0,0 +1,7 @@ +{ + "version": "1.0.0", + "private": true, + "dependencies": { + "twilio": "^3.61.0" + } +}