2022-05-12 19:56:35 +00:00
|
|
|
const { SlashCommandBuilder } = require('@discordjs/builders');
|
|
|
|
const noblox = require("noblox.js");
|
2022-06-18 03:26:52 +00:00
|
|
|
const { bhopCookie, surfCookie, deathrunCookie } = require("../config/config.json");
|
2023-03-08 20:37:40 +00:00
|
|
|
const cookieDict = {
|
|
|
|
bhop: bhopCookie,
|
|
|
|
surf: surfCookie,
|
|
|
|
deathrun: deathrunCookie,
|
|
|
|
};
|
|
|
|
var commandChoices = [];
|
|
|
|
for (const [game, file] of Object.entries(gameDict)) {
|
|
|
|
commandChoices.push({name: game, value: game})
|
|
|
|
}
|
2022-05-12 19:56:35 +00:00
|
|
|
|
2022-05-13 17:01:16 +00:00
|
|
|
async function execute(interaction) {
|
|
|
|
const game = interaction.options.getString("game");
|
2023-03-08 20:37:40 +00:00
|
|
|
let cookie = cookieDict[game];
|
|
|
|
if (cookie === undefined) {
|
2022-05-13 17:01:16 +00:00
|
|
|
await interaction.reply({content: "Invalid game specified!", ephemeral: true});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const id = interaction.options.getInteger("asset_id");
|
|
|
|
await noblox.setCookie(cookie).then(async () => {
|
2023-03-04 21:09:41 +00:00
|
|
|
let info;
|
2022-05-13 17:01:16 +00:00
|
|
|
// validate that this is a model
|
|
|
|
try {
|
2023-03-04 21:09:41 +00:00
|
|
|
info = await getProductInfo(id);
|
2022-05-13 17:01:16 +00:00
|
|
|
if (info.AssetTypeId != 10) {
|
|
|
|
await interaction.reply({content: `(id: ${id}) is not a valid model ID.`, ephemeral: true});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
console.log(error);
|
|
|
|
await interaction.reply({content: `There is a problem with this asset ID (id: ${id}).`, ephemeral: true});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-03-04 21:09:41 +00:00
|
|
|
buy(undefined, await noblox.getGeneralToken(), info, 0).then(async () => {
|
2022-05-13 17:01:16 +00:00
|
|
|
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
|
|
|
|
\`\`\`
|
|
|
|
!map ${id}
|
|
|
|
\`\`\`Read what it says. If your map successfully loaded type !rtv and then choose your map.
|
|
|
|
If it did not load successfully, you can expand the chat to view the full error message by clicking and dragging on the edge of the chat.
|
|
|
|
`
|
|
|
|
);
|
|
|
|
})
|
|
|
|
.catch(async (error) => {
|
|
|
|
if (error.message == "You already own this item.") {
|
|
|
|
await interaction.reply({content: "The bot has already taken this model!", ephemeral: true});
|
|
|
|
} else {
|
|
|
|
await interaction.reply({content: `An error occured trying to take the model (id: ${id}). Make sure it is uncopylocked!`, ephemeral: true});
|
|
|
|
console.log(`Could not take asset ID ${id}: `);
|
|
|
|
console.log(error);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-05-12 19:56:35 +00:00
|
|
|
module.exports = {
|
|
|
|
data: new SlashCommandBuilder()
|
|
|
|
.setName('take')
|
|
|
|
.setDescription('Takes an asset ID')
|
2022-05-13 05:06:45 +00:00
|
|
|
.addStringOption(option =>
|
|
|
|
option.setName("game")
|
|
|
|
.setDescription("Select the maptest game")
|
|
|
|
.setRequired(true)
|
2023-03-08 20:37:40 +00:00
|
|
|
.addChoices(commandChoices))
|
2022-05-12 19:56:35 +00:00
|
|
|
.addIntegerOption(option =>
|
|
|
|
option.setName("asset_id")
|
|
|
|
.setDescription("The asset ID of the model")
|
|
|
|
.setRequired(true))
|
|
|
|
,
|
2022-05-13 17:01:16 +00:00
|
|
|
execute
|
2023-03-04 21:09:41 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|