Compare commits

...

2 Commits

Author SHA1 Message Date
7ff5a62fed added wrapper to fix broken API 2023-03-04 15:03:19 -06:00
0923d3b58a update discord to roblox api 2022-10-21 23:04:23 -05:00
2 changed files with 131 additions and 13 deletions

@ -2,13 +2,13 @@ const { SlashCommandBuilder } = require('@discordjs/builders');
const { parse } = require("csv-parse/sync");
const fs = require('node:fs');
const noblox = require("noblox.js");
const axios = require("axios").default
const axios = require("axios").default;
async function robloxUserFromDiscord(id) {
if (isNaN(id)) return undefined;
try {
const res = await axios.get(`https://verify.eryn.io/api/user/${id}`)
return res.data.robloxId
const res = await axios.get(`https://api.fiveman1.net/v1/users/${id}`);
return res.data.result.robloxId;
} catch (error) {
return undefined;
}
@ -17,17 +17,17 @@ async function robloxUserFromDiscord(id) {
async function robloxUsernameFromId(id) {
if (isNaN(id)) return undefined;
try {
const res = await axios.get(`https://users.roblox.com/v1/users/${id}`)
return res.data.name
const res = await axios.get(`https://users.roblox.com/v1/users/${id}`);
return res.data.name;
} catch (error) {
return undefined;
}
}
async function execute(interaction) {
const userId = await robloxUserFromDiscord(interaction.user.id)
const userId = await robloxUserFromDiscord(interaction.user.id);
if (!userId) {
const msg = "You don't have a Roblox account linked with your Discord account. Visit https://verify.eryn.io/";
const msg = "You don't have a Roblox account linked with your Discord account. Use !link with rbhop dog to link your account.";
await interaction.reply({content: msg, ephemeral: true});
return;
}
@ -48,7 +48,7 @@ async function execute(interaction) {
const id = interaction.options.getInteger("asset_id");
try {
const info = await noblox.getProductInfo(id);
const info = await getProductInfo(id);
if (info.AssetTypeId != 10) {
await interaction.reply({content: `(id: ${id}) is not a valid model ID.`, ephemeral: true});
return;
@ -104,4 +104,37 @@ module.exports = {
.setRequired(true))
,
execute
};
};
function getProductInfo (asset) {
return new Promise(async (resolve, reject) => {
const httpOpt = {
url: `//economy.roblox.com/v2/assets/${asset}/details`,
options: {
resolveWithFullResponse: true,
method: 'GET'
}
}
try {
const res = await noblox.http(httpOpt);
if (res.statusCode === 200) {
resolve(JSON.parse(res.body));
} else {
// Sourced from: https://stackoverflow.com/a/32278428
const isAnObject = (val_1) => !!(val_1 instanceof Array || val_1 instanceof Object);
const body = isAnObject(res.body) ? JSON.parse(res.body) : {};
if (body.errors && body.errors.length > 0) {
const errors = body.errors.map((e) => {
return e.message;
});
reject(new Error(`${res.statusCode} ${errors.join(', ')}`));
} else {
reject(new Error(`${res.statusCode} ${res.body}`));
}
}
} catch (error) {
return reject(error);
}
})
}

@ -14,10 +14,10 @@ async function execute(interaction) {
}
const id = interaction.options.getInteger("asset_id");
await noblox.setCookie(cookie).then(async () => {
let info;
// validate that this is a model
try {
const info = await noblox.getProductInfo(id);
info = await getProductInfo(id);
if (info.AssetTypeId != 10) {
await interaction.reply({content: `(id: ${id}) is not a valid model ID.`, ephemeral: true});
return;
@ -28,7 +28,7 @@ async function execute(interaction) {
return;
}
noblox.buy(id, 0).then(async () => {
buy(undefined, await noblox.getGeneralToken(), info, 0).then(async () => {
await interaction.reply(
`
Now that your map (id: ${id}) has been taken by the ${game} maptest bot you can load it into the ${game} maptest place. To load your map, join the game and say
@ -66,4 +66,89 @@ module.exports = {
.setRequired(true))
,
execute
};
};
async function buy (jar, token, product, price) {
const robux = product.PriceInRobux || 0
const productId = product.ProductId
if (price) {
if (typeof price === 'number') {
if (robux !== price) {
throw new Error('Price requirement not met. Requested price: ' + price + ' Actual price: ' + robux)
}
} else if (typeof price === 'object') {
const high = price.high
const low = price.low
if (high) {
if (robux > high) {
throw new Error('Price requirement not met. Requested price: <=' + high + ' Actual price: ' + robux)
}
}
if (low) {
if (robux < low) {
throw new Error('Price requirement not met. Requested price: >=' + low + ' Actual price: ' + robux)
}
}
}
}
const httpOpt = {
url: '//economy.roblox.com/v1/purchases/products/' + productId,
options: {
method: 'POST',
jar: jar,
headers: {
'X-CSRF-TOKEN': token
},
json: {
expectedCurrency: 1,
expectedPrice: robux,
expectedSellerId: product.Creator.Id
}
}
}
const json = await noblox.http(httpOpt);
let err = json.errorMsg;
if (json.reason === 'InsufficientFunds') {
err = 'You need ' + json.shortfallPrice + ' more robux to purchase this item.';
} else if (json.errorMsg) {
err = json.errorMsg;
}
if (!err) {
return { productId, price: robux };
} else {
throw new Error(err);
}
}
function getProductInfo (asset) {
return new Promise(async (resolve, reject) => {
const httpOpt = {
url: `//economy.roblox.com/v2/assets/${asset}/details`,
options: {
resolveWithFullResponse: true,
method: 'GET'
}
}
try {
const res = await noblox.http(httpOpt);
if (res.statusCode === 200) {
resolve(JSON.parse(res.body));
} else {
// Sourced from: https://stackoverflow.com/a/32278428
const isAnObject = (val_1) => !!(val_1 instanceof Array || val_1 instanceof Object);
const body = isAnObject(res.body) ? JSON.parse(res.body) : {};
if (body.errors && body.errors.length > 0) {
const errors = body.errors.map((e) => {
return e.message;
});
reject(new Error(`${res.statusCode} ${errors.join(', ')}`));
} else {
reject(new Error(`${res.statusCode} ${res.body}`));
}
}
} catch (error) {
return reject(error);
}
})
}