Progress has been made

This commit is contained in:
Christopher Cookman 2026-06-14 00:02:42 -06:00
parent 70978819ee
commit bc468fa475
3 changed files with 119 additions and 32 deletions

20
bvs.js
View file

@ -83,6 +83,7 @@ async function getAccountInfo() {
} }
async function searchDIDs(query) { async function searchDIDs(query) {
// console.log(`q is ${query}`)
// Query will either be NPA, or NPANXX. Validate with regex, then use the API to find some. // 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 // 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 query = query.replace(/\D/g, ""); // Remove all non-digit characters
@ -105,13 +106,14 @@ async function searchDIDs(query) {
} }
async function searchPurchasableDIDs(query) { async function searchPurchasableDIDs(query) {
// console.log(`Searching purchasable DIDs with query ${query}`);
// Use searchDIDs, then filter down to 6 random from the results where the Nrc value == "0.05" and Mrc == "0.06" // 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 => { const dids = await searchDIDs(query).catch(error => {
console.error("Error searching DIDs:", error); console.error("Error searching DIDs:", error);
return []; return [];
}); });
// console.log(dids) // console.log(dids)
const purchasableDIDs = dids.filter(did => did.Nrc <= "0.50" && did.Mrc === "0.06"); const purchasableDIDs = dids.filter(did => did.Nrc <= "0.50" && did.Mrc <= "0.10");
// console.log(purchasableDIDs) // console.log(purchasableDIDs)
// Shuffle the purchasableDIDs array, then take the first 6 // Shuffle the purchasableDIDs array, then take the first 6
let shuffled = [...purchasableDIDs]; let shuffled = [...purchasableDIDs];
@ -182,6 +184,22 @@ function formatPhoneNumber(input) {
return `+${input[0]} (${input.slice(1, 4)}) ${input.slice(4, 7)}-${input.slice(7)}`; return `+${input[0]} (${input.slice(1, 4)}) ${input.slice(4, 7)}-${input.slice(7)}`;
} }
function deleteDID(did) {
// API to delete msg, DELETE https://portal.bulkvs.com/api/v1.0/tnRecord?Number=did
return fetch(`https://portal.bulkvs.com/api/v1.0/tnRecord?Number=${did}`, {
method: "DELETE",
headers: {
"Authorization": `Bearer ${process.env.BVS_TOKEN}`,
}
})
.then(res => {
if (!res.ok) {
throw new Error(`Error deleting DID: ${res.status} ${res.statusText}`);
}
return res.json();
});
}
module.exports = { module.exports = {
getAllDIDs, getAllDIDs,
getAccountInfo, getAccountInfo,

View file

@ -1,21 +1,60 @@
module.exports = (interaction, client, bvs) => { module.exports = (interaction, client, bvs) => {
const choice = interaction.options.getNumber('choice');
if (!choice) { const member = interaction.guild.members.cache.get(interaction.user.id);
return interaction.reply({ content: `You must provide a choice from the latest run of \`/searchnumbers\`. Use \`/searchnumbers\` to see available DIDs and their corresponding choices.`, ephemeral: true });
if (!member) {
interaction.reply({ content: `Could not find member with ID ${user.id}.`, ephemeral: true });
return;
} }
if (!global.tempPurchasableDIDs || !global.tempPurchasableDIDs[interaction.user.id]) { if (!member.premiumSince) {
return interaction.reply({ content: `You must provide a choice from the latest run of \`/searchnumbers\`. Use \`/searchnumbers\` to see available DIDs and their corresponding choices.`, ephemeral: true }); return interaction.reply({ content: `You must be boosting the server to use this command.`, ephemeral: true });
} }
const dids = global.tempPurchasableDIDs[interaction.user.id]; // Check that the member doesn't already have a number.
const index = parseInt(choice) - 1; bvs.getPremiumDIDs().then(dids => {
if (isNaN(index) || index < 0 || index >= dids.length) { const userDIDs = dids.filter(did => did.userId === interaction.user.id);
return interaction.reply({ content: `Invalid choice. You must provide a choice from the latest run of \`/searchnumbers\`. Use \`/searchnumbers\` to see available DIDs and their corresponding choices.`, ephemeral: true }); if (userDIDs.length === 0) {
}
const didToPurchase = dids[index]; const choice = interaction.options.getNumber('choice');
return interaction.reply({ content: `Attempting to purchase DID \`${bvs.formatPhoneNumber(didToPurchase)}\`...`, ephemeral: true }).then(() => { if (!choice) {
// wait, we are in dev phase, dont buy lol return interaction.reply({ content: `You must provide a choice from the latest run of \`/searchnumbers\`. Use \`/searchnumbers\` to see available DIDs and their corresponding choices.`, ephemeral: true });
}
if (global.purchaseConfirmations && global.purchaseConfirmations[interaction.user.id]) {
if (choice === 1) {
// proceed with purchase
const didToPurchase = global.purchaseConfirmations[interaction.user.id];
delete global.purchaseConfirmations[interaction.user.id];
delete global.tempPurchasableDIDs[interaction.user.id];
return interaction.reply({ content: `Purchasing DID \`${bvs.formatPhoneNumber(didToPurchase)}\`...`, ephemeral: true })
// todo: impl actually buying did
} else {
delete global.purchaseConfirmations[interaction.user.id];
return interaction.reply({ content: `Cancelled. You can either choose a different DID from the latest run of \`/searchnumbers\` or start a new search by running \`/searchnumbers\` again.`, ephemeral: true });
}
}
if (!global.tempPurchasableDIDs || !global.tempPurchasableDIDs[interaction.user.id]) {
return interaction.reply({ content: `You must provide a choice from the latest run of \`/searchnumbers\`. Use \`/searchnumbers\` to see available DIDs and their corresponding choices.`, ephemeral: true });
}
const dids = global.tempPurchasableDIDs[interaction.user.id];
const index = parseInt(choice) - 1;
if (isNaN(index) || index < 0 || index >= dids.length) {
return interaction.reply({ content: `Invalid choice. You must provide a choice from the latest run of \`/searchnumbers\`. Use \`/searchnumbers\` to see available DIDs and their corresponding choices.`, ephemeral: true });
}
const didToPurchase = dids[index];
// Store the choice in a global temp variable with the user id so the user can confirm their purchase by running the command again with the same choice. This is a bit janky but it works for now.
global.purchaseConfirmations = global.purchaseConfirmations || {};
global.purchaseConfirmations[interaction.user.id] = didToPurchase;
return interaction.reply({ content: `You have selected DID \`${bvs.formatPhoneNumber(didToPurchase)}\` for purchase. If you want to proceed with purchasing this DID, run \`/getnumber\` with choice \`1\`. If you want to cancel, run the command again with a different choice or run \`/searchnumbers\` again to start a new search.`, ephemeral: true });
} else {
interaction.reply({ content: `Your DID is \`${bvs.formatPhoneNumber(userDIDs[0].did)}\``, ephemeral: true });
}
}).catch(error => {
console.error("Error fetching premium DIDs:", error);
interaction.reply({ content: `There was an error fetching your DID. Please try again later.`, ephemeral: true });
}); });
} }

View file

@ -1,25 +1,55 @@
module.exports = (interaction, client, bvs) => { module.exports = (interaction, client, bvs) => {
const areaCode = interaction.options.getNumber('area_code'); const member = interaction.guild.members.cache.get(interaction.user.id);
const officeCode = interaction.options.getNumber('office_code');
// Validate input if (!member) {
if (!/^\d{3}$/.test(areaCode)) { interaction.reply({ content: `Could not find member with ID ${user.id}.`, ephemeral: true });
return interaction.reply({ content: `Area code must be 3 digits.`, ephemeral: true }); return;
} }
if (officeCode && !/^\d{3}$/.test(officeCode)) {
return interaction.reply({ content: `Office code must be 3 digits.`, ephemeral: true }); if (!member.premiumSince) {
return interaction.reply({ content: `You must be boosting the server to use this command.`, ephemeral: true });
} }
bvs.searchPurchasableDIDs(areaCode + (officeCode || "")).then(dids => {
if (dids.length === 0) { bvs.getPremiumDIDs().then(dids => {
return interaction.reply({ content: `No results for search query. Try again.`, ephemeral: true }); const userDIDs = dids.filter(did => did.userId === interaction.user.id);
if (userDIDs.length === 0) {
const areaCode = interaction.options.getNumber('area_code');
const officeCode = interaction.options.getNumber('office_code');
// Clear purchase confirmation and temp purchasable DIDs for the user, since they're starting a new search. This prevents confusion where a user searches for DIDs, then tries to purchase one, but the purchasable DIDs from the previous search are still stored and they accidentally purchase a DID from the previous search results instead of the new ones.
if (global.purchaseConfirmations) {
delete global.purchaseConfirmations[interaction.user.id];
}
if (global.tempPurchasableDIDs) {
delete global.tempPurchasableDIDs[interaction.user.id];
}
// Validate input
if (!/^\d{3}$/.test(areaCode)) {
return interaction.reply({ content: `Area code must be 3 digits.`, ephemeral: true });
}
if (officeCode && !/^\d{3}$/.test(officeCode)) {
return interaction.reply({ content: `Office code must be 3 digits.`, ephemeral: true });
}
bvs.searchPurchasableDIDs(`${areaCode}${officeCode || ""}`).then(dids => {
if (dids.length === 0) {
return interaction.reply({ content: `No results for search query. Try again.`, ephemeral: true });
}
// console.log(dids)
interaction.reply({ content: `Found the following DIDs\n\`\`\`\n${dids.map((did, index) => `${index + 1}. ${bvs.formatPhoneNumber(did.TN)}`).join("\n")}\n\`\`\`\nUse \`/getnumber <choice>\` to purchase one of these DIDs! (Choice is one of the numbers listed above by index, not phone number)`, ephemeral: true });
// Store the DIDs in a global temp variable with the user id so the user can purchase by 1, 2, 3, etc. in the /getnumber command. This is a bit janky but it works for now.
global.tempPurchasableDIDs = global.tempPurchasableDIDs || {};
global.tempPurchasableDIDs[interaction.user.id] = dids.map(did => did.TN);
// console.log(global.tempPurchasableDIDs)
}).catch(error => {
console.error("Error searching DIDs:", error);
interaction.reply({ content: `There was an error searching for DIDs. Please try again later.`, ephemeral: true });
});
} else {
interaction.reply({ content: `Your DID is \`${bvs.formatPhoneNumber(userDIDs[0].did)}\``, ephemeral: true });
} }
console.log(dids)
interaction.reply({ content: `Found the following DIDs\n\`\`\`\n${dids.map((did, index) => `${index + 1}. ${bvs.formatPhoneNumber(did.TN)}`).join("\n")}\n\`\`\`\nUse \`/getnumber <choice>\` to purchase one of these DIDs! (Choice is one of the numbers listed above by index, not phone number)`, ephemeral: true });
// Store the DIDs in a global temp variable with the user id so the user can purchase by 1, 2, 3, etc. in the /getnumber command. This is a bit janky but it works for now.
global.tempPurchasableDIDs = global.tempPurchasableDIDs || {};
global.tempPurchasableDIDs[interaction.user.id] = dids.map(did => did.TN);
console.log(global.tempPurchasableDIDs)
}).catch(error => { }).catch(error => {
console.error("Error searching DIDs:", error); console.error("Error fetching premium DIDs:", error);
interaction.reply({ content: `There was an error searching for DIDs. Please try again later.`, ephemeral: true }); interaction.reply({ content: `There was an error fetching your DID. Please try again later.`, ephemeral: true });
}); });
} }