bvs-nitro-did/bvs.js

193 lines
5.7 KiB
JavaScript

async function getPremiumDIDs() {
return new Promise((resolve, reject) => {
fetch(`https://portal.bulkvs.com/api/v1.0/tnRecord?Status=Active&Trunk%20Group=${process.env.TRUNK_GROUP}`, {
headers: {
"Authorization": `Bearer ${process.env.BVS_TOKEN}`,
}
})
.then(res => {
if (!res.ok) {
throw new Error(`Error fetching DIDs: ${res.status} ${res.statusText}`);
}
return res.json();
})
.then(data => {
// data.forEach(record => {
// console.log(record.ReferenceID);
// });
// data is array of objects. If object.ReferenceID.split(";;")[0] is premDID, then [1] is the user id, and anything after is a note
const dids = data.filter(record => record.ReferenceID && record.ReferenceID.startsWith(";;")).map(record => {
// Get all flags (just keep looking at the next split item until its not a valid flag, after that, it's all a custom note, most likely to be used fo)
let validFlags = ["bypassNitroReq"];
let flags = [];
let note = "";
let splitReference = record.ReferenceID.split(";;");
for (let i = 1; i < splitReference.length; i++) {
if (validFlags.includes(splitReference[i])) {
flags.push(splitReference[i]);
}
}
return {
did: record.TN,
userId: record.ReferenceID.split(";;")[1],
flags: flags,
rawRef: record.ReferenceID
}
});
resolve(dids);
})
.catch(error => {
console.error("Error fetching DIDs:", error);
reject(error);
});
});
}
async function getAllDIDs() {
// Use the same BVS API endpoint, but just get all the results, not just premium ones.
return new Promise((resolve, reject) => {
fetch(`https://portal.bulkvs.com/api/v1.0/tnRecord?Status=Active&Trunk%20Group=${process.env.TRUNK_GROUP}`, {
headers: {
"Authorization": `Bearer ${process.env.BVS_TOKEN}`,
}
})
.then(res => {
if (!res.ok) {
throw new Error(`Error fetching DIDs: ${res.status} ${res.statusText}`);
}
return res.json();
})
.then(data => {
const dids = data.map(record => record.TN);
resolve(dids);
})
.catch(error => {
console.error("Error fetching DIDs:", error);
reject(error);
});
});
}
async function getAccountInfo() {
const res = await fetch("https://portal.bulkvs.com/api/v1.0/accountDetail", {
headers: {
"Authorization": `Bearer ${process.env.BVS_TOKEN}`,
}
});
if (!res.ok) {
throw new Error(`BVS_TOKEN is invalid: ${res.status} ${res.statusText}`);
}
return res.json();
}
async function searchDIDs(query) {
// Query will either be NPA, or NPANXX. Validate with regex, then use the API to find some.
// API Example: GET https://portal.bulkvs.com/api/v1.0/orderTn?Npa=310&Nxx=906&Lca=true&Limit=100
query = query.replace(/\D/g, ""); // Remove all non-digit characters
// Validate query w regex
if (!/^\d{3}$/.test(query) && !/^\d{6}$/.test(query)) {
throw new Error("Query must be either NPA (3 digits) or NPANXX (6 digits)");
}
const res = await fetch(`https://portal.bulkvs.com/api/v1.0/orderTn?Npa=${query.slice(0, 3)}&Nxx=${query.slice(3, 6)}&Lca=true&Limit=100`, {
headers: {
"Authorization": `Bearer ${process.env.BVS_TOKEN}`,
}
});
if (!res.ok) {
throw new Error(`Error searching DIDs: ${res.status} ${res.statusText}`);
}
return res.json();
}
async function searchPurchasableDIDs(query) {
// Use searchDIDs, then filter down to 6 random from the results where the Nrc value == "0.05" and Mrc == "0.06"
const dids = await searchDIDs(query).catch(error => {
console.error("Error searching DIDs:", error);
return [];
});
// console.log(dids)
const purchasableDIDs = dids.filter(did => did.Nrc <= "0.50" && did.Mrc === "0.06");
// console.log(purchasableDIDs)
// Shuffle the purchasableDIDs array, then take the first 6
let shuffled = [...purchasableDIDs];
for (let i = 0; i < 5; i++) {
shuffled = shuffled.sort(() => 0.5 - Math.random());
}
// shuffle more
return shuffled.slice(0, 6);
}
async function purchaseDID(did, userId) {
// POST /orderTn with body:
/*
{
"TN": "did to purchase",
"Lidb": "LITENET",
"Portout Pin": `${random 12 digit number}`,
"ReferenceID": `;;${userId}`,
"Trunk Group": `${process.env.TRUNK_GROUP}`,
"Sms": false,
"Mms": false,
"Webhook": "Default"
}
*/
let portoutPin = "";
const digits = "0123456789";
for (let i = 0; i < 12; i++) {
portoutPin += digits[Math.floor(Math.random() * digits.length)];
}
const res = await fetch("https://portal.bulkvs.com/api/v1.0/orderTn", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.BVS_TOKEN}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"TN": did,
"Lidb": "LITENET",
"Portout Pin": portoutPin,
"ReferenceID": `;;${userId}`,
"Trunk Group": `${process.env.TRUNK_GROUP}`,
"Sms": false,
"Mms": false,
"Webhook": "Default"
})
});
// If response is 404, check body.json().Description, return the json body.
if (res.status === 404) {
const errorData = await res.json();
throw new Error(`Error purchasing DID: ${res.status} ${res.statusText} - ${errorData.Description}`);
}
if (!res.ok) {
throw new Error(`Error purchasing DID: ${res.status} ${res.statusText}`);
}
return res.json();
}
function formatPhoneNumber(input) {
if (/^\d{10}$/.test(input)) {
input = `1${input}`;
}
// Regex to make sure it's a valid 11 digit NA phone number.
if (!/^\d{11}$/.test(input)) {
throw new Error("Phone number must be 10 or 11 digits, including country code (1 for US/Canada).");
}
// Format to human readable format: +1 (310) 906-1234
return `+${input[0]} (${input.slice(1, 4)}) ${input.slice(4, 7)}-${input.slice(7)}`;
}
module.exports = {
getAllDIDs,
getAccountInfo,
getPremiumDIDs,
searchDIDs,
searchPurchasableDIDs,
purchaseDID,
formatPhoneNumber
}