added urban dicionary, wikipedia, currency conversion, hash generator
This commit is contained in:
parent
d5ff48ec4f
commit
8979cf12f0
589
discord/index.js
589
discord/index.js
|
@ -11,6 +11,19 @@ const {
|
||||||
const axios = require("axios");
|
const axios = require("axios");
|
||||||
const ping = require("ping");
|
const ping = require("ping");
|
||||||
const whois = require('whois-json');
|
const whois = require('whois-json');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const tempDir = path.join(__dirname, '../temp');
|
||||||
|
if (fs.existsSync(tempDir)) {
|
||||||
|
console.log("Cleaning up temp directory...");
|
||||||
|
const files = fs.readdirSync(tempDir);
|
||||||
|
for (const file of files) {
|
||||||
|
fs.unlinkSync(path.join(tempDir, file));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fs.mkdirSync(tempDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
const client = new Client({
|
const client = new Client({
|
||||||
intents: [
|
intents: [
|
||||||
|
@ -256,6 +269,116 @@ const globalCommands = [
|
||||||
required: true,
|
required: true,
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "wikipedia",
|
||||||
|
description: "Get a summary of a Wikipedia article",
|
||||||
|
type: ApplicationCommandType.ChatInput,
|
||||||
|
dm_permission: true,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: "query",
|
||||||
|
description: "The topic to search for on Wikipedia",
|
||||||
|
type: ApplicationCommandOptionType.String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "language",
|
||||||
|
description: "Wikipedia language (default: en)",
|
||||||
|
type: ApplicationCommandOptionType.String,
|
||||||
|
required: false,
|
||||||
|
choices: [
|
||||||
|
{ name: "English", value: "en" },
|
||||||
|
{ name: "Spanish", value: "es" },
|
||||||
|
{ name: "French", value: "fr" },
|
||||||
|
{ name: "German", value: "de" },
|
||||||
|
{ name: "Russian", value: "ru" },
|
||||||
|
{ name: "Japanese", value: "ja" },
|
||||||
|
{ name: "Chinese", value: "zh" },
|
||||||
|
{ name: "Turkish", value: "tr" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "urban",
|
||||||
|
description: "Look up a term on Urban Dictionary",
|
||||||
|
type: ApplicationCommandType.ChatInput,
|
||||||
|
dm_permission: true,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: "term",
|
||||||
|
description: "The slang term to look up",
|
||||||
|
type: ApplicationCommandOptionType.String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "random",
|
||||||
|
description: "Get a random definition instead",
|
||||||
|
type: ApplicationCommandOptionType.Boolean,
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "currency",
|
||||||
|
description: "Convert between currencies using real-time exchange rates",
|
||||||
|
type: ApplicationCommandType.ChatInput,
|
||||||
|
dm_permission: true,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: "amount",
|
||||||
|
description: "Amount to convert",
|
||||||
|
type: ApplicationCommandOptionType.Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "from",
|
||||||
|
description: "Source currency code (e.g., USD)",
|
||||||
|
type: ApplicationCommandOptionType.String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "to",
|
||||||
|
description: "Target currency code (e.g., EUR)",
|
||||||
|
type: ApplicationCommandOptionType.String,
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "hash",
|
||||||
|
description: "Generate hash of text or file (up to 500MB)",
|
||||||
|
type: ApplicationCommandType.ChatInput,
|
||||||
|
dm_permission: true,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: "algorithm",
|
||||||
|
description: "Hash algorithm to use",
|
||||||
|
type: ApplicationCommandOptionType.String,
|
||||||
|
required: true,
|
||||||
|
choices: [
|
||||||
|
{ name: "MD5", value: "md5" },
|
||||||
|
{ name: "SHA-1", value: "sha1" },
|
||||||
|
{ name: "SHA-256", value: "sha256" },
|
||||||
|
{ name: "SHA-512", value: "sha512" },
|
||||||
|
{ name: "SHA3-256", value: "sha3-256" },
|
||||||
|
{ name: "SHA3-512", value: "sha3-512" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "text",
|
||||||
|
description: "Text to hash (if not uploading a file)",
|
||||||
|
type: ApplicationCommandOptionType.String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "file",
|
||||||
|
description: "File to hash (up to 500MB)",
|
||||||
|
type: ApplicationCommandOptionType.Attachment,
|
||||||
|
required: false,
|
||||||
|
}
|
||||||
|
],
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -952,6 +1075,97 @@ client.on("interactionCreate", async (interaction) => {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "wikipedia":
|
||||||
|
try {
|
||||||
|
await interaction.deferReply();
|
||||||
|
const query = interaction.options.getString("query");
|
||||||
|
const language = interaction.options.getString("language") || "en";
|
||||||
|
|
||||||
|
// Import the wikipedia package
|
||||||
|
const wikipedia = require('wikipedia');
|
||||||
|
|
||||||
|
// Set the language
|
||||||
|
wikipedia.setLang(language);
|
||||||
|
|
||||||
|
// Search for the query
|
||||||
|
const searchResults = await wikipedia.search(query);
|
||||||
|
|
||||||
|
if (!searchResults.results || searchResults.results.length === 0) {
|
||||||
|
await interaction.editReply({
|
||||||
|
content: `No results found for "${query}" on Wikipedia.`,
|
||||||
|
ephemeral: true
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the first result
|
||||||
|
const page = await wikipedia.page(searchResults.results[0].title);
|
||||||
|
|
||||||
|
// Get summary and basic info
|
||||||
|
const summary = await page.summary();
|
||||||
|
|
||||||
|
// Create a rich embed
|
||||||
|
const wikiEmbed = {
|
||||||
|
title: summary.title,
|
||||||
|
url: summary.content_urls.desktop.page,
|
||||||
|
description: summary.extract.length > 1000
|
||||||
|
? summary.extract.substring(0, 1000) + "..."
|
||||||
|
: summary.extract,
|
||||||
|
color: 0x0099ff,
|
||||||
|
thumbnail: summary.thumbnail
|
||||||
|
? { url: summary.thumbnail.source }
|
||||||
|
: null,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: "Page ID",
|
||||||
|
value: summary.pageid.toString(),
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Language",
|
||||||
|
value: language.toUpperCase(),
|
||||||
|
inline: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
footer: {
|
||||||
|
text: "Powered by Wikipedia",
|
||||||
|
icon_url: "https://upload.wikimedia.org/wikipedia/commons/thumb/8/80/Wikipedia-logo-v2.svg/103px-Wikipedia-logo-v2.svg.png"
|
||||||
|
},
|
||||||
|
timestamp: new Date()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add a related articles field if we have other search results
|
||||||
|
if (searchResults.results.length > 1) {
|
||||||
|
const relatedArticles = searchResults.results
|
||||||
|
.slice(1, 4) // Get 3 related articles
|
||||||
|
.map(result => `[${result.title}](https://${language}.wikipedia.org/wiki/${encodeURIComponent(result.title.replace(/ /g, '_'))})`)
|
||||||
|
.join('\n');
|
||||||
|
|
||||||
|
wikiEmbed.fields.push({
|
||||||
|
name: "Related Articles",
|
||||||
|
value: relatedArticles
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await interaction.editReply({ embeds: [wikiEmbed] });
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
|
||||||
|
// Handle specific Wikipedia errors
|
||||||
|
if (error.message.includes("No article found")) {
|
||||||
|
await interaction.editReply({
|
||||||
|
content: "Couldn't find a specific Wikipedia article with that title. Try a different search term.",
|
||||||
|
ephemeral: true
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
await interaction.editReply({
|
||||||
|
content: "Error fetching Wikipedia data. Please try again later.",
|
||||||
|
ephemeral: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case "whois":
|
case "whois":
|
||||||
try {
|
try {
|
||||||
await interaction.deferReply();
|
await interaction.deferReply();
|
||||||
|
@ -1115,6 +1329,381 @@ client.on("interactionCreate", async (interaction) => {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "urban":
|
||||||
|
try {
|
||||||
|
await interaction.deferReply();
|
||||||
|
const term = interaction.options.getString("term");
|
||||||
|
const isRandom = interaction.options.getBoolean("random") || false;
|
||||||
|
|
||||||
|
// API endpoint
|
||||||
|
const endpoint = isRandom
|
||||||
|
? "https://api.urbandictionary.com/v0/random"
|
||||||
|
: `https://api.urbandictionary.com/v0/define?term=${encodeURIComponent(term)}`;
|
||||||
|
|
||||||
|
const response = await axios.get(endpoint);
|
||||||
|
|
||||||
|
if (!response.data.list || response.data.list.length === 0) {
|
||||||
|
await interaction.editReply({
|
||||||
|
content: `No definitions found for "${term}" on Urban Dictionary.`,
|
||||||
|
ephemeral: true
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort by thumbs up count if there are multiple definitions
|
||||||
|
const definitions = response.data.list.sort((a, b) => b.thumbs_up - a.thumbs_up);
|
||||||
|
const definition = definitions[0];
|
||||||
|
|
||||||
|
// Clean up the text by replacing square brackets with formatted links
|
||||||
|
let cleanDefinition = definition.definition.replace(/\[([^\]]+)\]/g, '**$1**');
|
||||||
|
let cleanExample = definition.example.replace(/\[([^\]]+)\]/g, '**$1**');
|
||||||
|
|
||||||
|
// Truncate if too long
|
||||||
|
if (cleanDefinition.length > 1024) {
|
||||||
|
cleanDefinition = cleanDefinition.substring(0, 1021) + '...';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cleanExample.length > 1024) {
|
||||||
|
cleanExample = cleanExample.substring(0, 1021) + '...';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a rich embed
|
||||||
|
const urbanEmbed = {
|
||||||
|
title: isRandom ? definition.word : term,
|
||||||
|
url: definition.permalink,
|
||||||
|
color: 0xEFFF00, // Urban Dictionary yellow
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: "Definition",
|
||||||
|
value: cleanDefinition || "No definition provided"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
footer: {
|
||||||
|
text: `👍 ${definition.thumbs_up} | 👎 ${definition.thumbs_down} | Written by ${definition.author}`,
|
||||||
|
icon_url: "https://i.imgur.com/VFXr0ID.jpg"
|
||||||
|
},
|
||||||
|
timestamp: new Date(definition.written_on)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add example if it exists
|
||||||
|
if (cleanExample && cleanExample.trim().length > 0) {
|
||||||
|
urbanEmbed.fields.push({
|
||||||
|
name: "Example",
|
||||||
|
value: cleanExample
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add related definitions if there are more
|
||||||
|
if (definitions.length > 1) {
|
||||||
|
const relatedCount = Math.min(definitions.length - 1, 3);
|
||||||
|
urbanEmbed.fields.push({
|
||||||
|
name: `${relatedCount} More Definition${relatedCount > 1 ? 's' : ''}`,
|
||||||
|
value: `This term has ${definitions.length} definitions. Use the link above to see them all.`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a warning that content might be offensive
|
||||||
|
const warningMessage = "⚠️ **Note:** Urban Dictionary contains user-submitted content that may be offensive or inappropriate.";
|
||||||
|
|
||||||
|
await interaction.editReply({
|
||||||
|
content: warningMessage,
|
||||||
|
embeds: [urbanEmbed]
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
await interaction.editReply({
|
||||||
|
content: "Error fetching Urban Dictionary definition. Please try again later.",
|
||||||
|
ephemeral: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "currency":
|
||||||
|
try {
|
||||||
|
await interaction.deferReply();
|
||||||
|
const amount = interaction.options.getNumber("amount");
|
||||||
|
const fromCurrency = interaction.options.getString("from").toUpperCase();
|
||||||
|
const toCurrency = interaction.options.getString("to").toUpperCase();
|
||||||
|
|
||||||
|
// Check if API key is configured
|
||||||
|
if (!process.env.EXCHANGE_RATE_API_KEY) {
|
||||||
|
await interaction.editReply({
|
||||||
|
content: "Exchange Rate API key not configured. Please add EXCHANGE_RATE_API_KEY to your environment variables.",
|
||||||
|
ephemeral: true
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate amount
|
||||||
|
if (amount <= 0) {
|
||||||
|
await interaction.editReply({
|
||||||
|
content: "Please provide a positive amount to convert.",
|
||||||
|
ephemeral: true
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch exchange rates
|
||||||
|
const apiUrl = `https://v6.exchangerate-api.com/v6/${process.env.EXCHANGE_RATE_API_KEY}/latest/${fromCurrency}`;
|
||||||
|
const response = await axios.get(apiUrl);
|
||||||
|
|
||||||
|
// Check if the source currency is valid
|
||||||
|
if (response.data.result === "error") {
|
||||||
|
await interaction.editReply({
|
||||||
|
content: `Error: ${response.data.error-type || "Invalid request"}. Please check your currency codes.`,
|
||||||
|
ephemeral: true
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if target currency exists in the response
|
||||||
|
if (!response.data.conversion_rates[toCurrency]) {
|
||||||
|
await interaction.editReply({
|
||||||
|
content: `Could not find exchange rate for ${toCurrency}. Please check your currency code.`,
|
||||||
|
ephemeral: true
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the converted amount
|
||||||
|
const rate = response.data.conversion_rates[toCurrency];
|
||||||
|
const convertedAmount = amount * rate;
|
||||||
|
|
||||||
|
// Format numbers with proper separators and decimals
|
||||||
|
const formatNumber = (num) => {
|
||||||
|
return new Intl.NumberFormat('en-US', {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 4
|
||||||
|
}).format(num);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get currency information to display symbols
|
||||||
|
const currencyInfo = {
|
||||||
|
USD: { symbol: '$', name: 'US Dollar' },
|
||||||
|
EUR: { symbol: '€', name: 'Euro' },
|
||||||
|
GBP: { symbol: '£', name: 'British Pound' },
|
||||||
|
JPY: { symbol: '¥', name: 'Japanese Yen' },
|
||||||
|
TRY: { symbol: '₺', name: 'Turkish Lira' },
|
||||||
|
// Add more currencies as needed
|
||||||
|
};
|
||||||
|
|
||||||
|
const fromCurrencyInfo = currencyInfo[fromCurrency] || { symbol: '', name: fromCurrency };
|
||||||
|
const toCurrencyInfo = currencyInfo[toCurrency] || { symbol: '', name: toCurrency };
|
||||||
|
|
||||||
|
// Create a rich embed
|
||||||
|
const conversionEmbed = {
|
||||||
|
title: "Currency Conversion",
|
||||||
|
color: 0x4CAF50, // Green
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: "From",
|
||||||
|
value: `${fromCurrencyInfo.symbol} ${formatNumber(amount)} ${fromCurrency} (${fromCurrencyInfo.name})`,
|
||||||
|
inline: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "To",
|
||||||
|
value: `${toCurrencyInfo.symbol} ${formatNumber(convertedAmount)} ${toCurrency} (${toCurrencyInfo.name})`,
|
||||||
|
inline: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Exchange Rate",
|
||||||
|
value: `1 ${fromCurrency} = ${formatNumber(rate)} ${toCurrency}`,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Last Updated",
|
||||||
|
value: new Date(response.data.time_last_update_unix * 1000).toLocaleString(),
|
||||||
|
inline: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
footer: {
|
||||||
|
text: "Powered by ExchangeRate-API"
|
||||||
|
},
|
||||||
|
timestamp: new Date()
|
||||||
|
};
|
||||||
|
|
||||||
|
await interaction.editReply({ embeds: [conversionEmbed] });
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
const errorMessage = error.response?.data?.error || "Error fetching exchange rates. Please try again later.";
|
||||||
|
await interaction.editReply({
|
||||||
|
content: errorMessage,
|
||||||
|
ephemeral: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "hash":
|
||||||
|
try {
|
||||||
|
await interaction.deferReply();
|
||||||
|
const algorithm = interaction.options.getString("algorithm");
|
||||||
|
const text = interaction.options.getString("text");
|
||||||
|
const file = interaction.options.getAttachment("file");
|
||||||
|
|
||||||
|
// Validate that either text or file is provided
|
||||||
|
if (!text && !file) {
|
||||||
|
await interaction.editReply({
|
||||||
|
content: "Please provide either text or a file to hash.",
|
||||||
|
ephemeral: true
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If both are provided, prioritize the file
|
||||||
|
if (text && file) {
|
||||||
|
await interaction.followUp({
|
||||||
|
content: "Both text and file were provided. Processing the file and ignoring the text.",
|
||||||
|
ephemeral: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// For text input, generate hash directly
|
||||||
|
if (text && !file) {
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const hash = crypto.createHash(algorithm).update(text).digest('hex');
|
||||||
|
|
||||||
|
const hashEmbed = {
|
||||||
|
title: `${algorithm.toUpperCase()} Hash`,
|
||||||
|
description: "Text hash generated successfully",
|
||||||
|
color: 0x3498db,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: "Input Text",
|
||||||
|
value: text.length > 1024 ? text.substring(0, 1021) + "..." : text
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Hash",
|
||||||
|
value: "```\n" + hash + "\n```"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
timestamp: new Date(),
|
||||||
|
footer: { text: `Algorithm: ${algorithm.toUpperCase()}` }
|
||||||
|
};
|
||||||
|
|
||||||
|
await interaction.editReply({ embeds: [hashEmbed] });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For file input, download and hash the file
|
||||||
|
if (file) {
|
||||||
|
// Check file size (500MB limit)
|
||||||
|
const maxSize = 500 * 1024 * 1024; // 500MB in bytes
|
||||||
|
if (file.size > maxSize) {
|
||||||
|
await interaction.editReply({
|
||||||
|
content: `File is too large. Maximum size is 500MB. Your file is ${(file.size / (1024 * 1024)).toFixed(2)}MB.`,
|
||||||
|
ephemeral: true
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If file is larger than 25MB, warn the user it might take a while
|
||||||
|
if (file.size > 25 * 1024 * 1024) {
|
||||||
|
await interaction.editReply({
|
||||||
|
content: `Processing a ${(file.size / (1024 * 1024)).toFixed(2)}MB file. This might take a while...`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the file using streams for efficiency
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const stream = require('stream');
|
||||||
|
const { promisify } = require('util');
|
||||||
|
const pipeline = promisify(stream.pipeline);
|
||||||
|
const axios = require('axios');
|
||||||
|
|
||||||
|
// Create a temporary file path
|
||||||
|
const tempDir = path.join(__dirname, '../temp');
|
||||||
|
if (!fs.existsSync(tempDir)) {
|
||||||
|
fs.mkdirSync(tempDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const tempFile = path.join(tempDir, `${Date.now()}_${file.name.replace(/[^a-zA-Z0-9.]/g, '_')}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Download the file
|
||||||
|
const writer = fs.createWriteStream(tempFile);
|
||||||
|
const response = await axios({
|
||||||
|
method: 'GET',
|
||||||
|
url: file.url,
|
||||||
|
responseType: 'stream'
|
||||||
|
});
|
||||||
|
|
||||||
|
await pipeline(response.data, writer);
|
||||||
|
|
||||||
|
// After download completes, hash the file with progress updates
|
||||||
|
const fileSize = fs.statSync(tempFile).size;
|
||||||
|
const hash = crypto.createHash(algorithm);
|
||||||
|
const input = fs.createReadStream(tempFile);
|
||||||
|
|
||||||
|
let processedBytes = 0;
|
||||||
|
let lastProgressUpdate = Date.now();
|
||||||
|
|
||||||
|
input.on('data', (chunk) => {
|
||||||
|
hash.update(chunk);
|
||||||
|
processedBytes += chunk.length;
|
||||||
|
|
||||||
|
// Update progress every 3 seconds for files larger than 50MB
|
||||||
|
const now = Date.now();
|
||||||
|
if (fileSize > 50 * 1024 * 1024 && now - lastProgressUpdate > 3000) {
|
||||||
|
const progress = (processedBytes / fileSize * 100).toFixed(2);
|
||||||
|
interaction.editReply({
|
||||||
|
content: `Processing file: ${progress}% complete...`
|
||||||
|
}).catch(console.error);
|
||||||
|
lastProgressUpdate = now;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait for the hash to complete
|
||||||
|
const hashHex = await new Promise((resolve, reject) => {
|
||||||
|
input.on('end', () => resolve(hash.digest('hex')));
|
||||||
|
input.on('error', reject);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clean up the temp file
|
||||||
|
fs.unlinkSync(tempFile);
|
||||||
|
|
||||||
|
// Create the response embed
|
||||||
|
const fileExtension = path.extname(file.name).toLowerCase();
|
||||||
|
const hashEmbed = {
|
||||||
|
title: `${algorithm.toUpperCase()} Hash Generated`,
|
||||||
|
description: "File hash calculated successfully",
|
||||||
|
color: 0x00ff00,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: "File",
|
||||||
|
value: `${file.name} (${(file.size / (1024 * 1024)).toFixed(2)} MB)`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Hash",
|
||||||
|
value: "```\n" + hashHex + "\n```"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
timestamp: new Date(),
|
||||||
|
footer: { text: `Algorithm: ${algorithm.toUpperCase()}` }
|
||||||
|
};
|
||||||
|
|
||||||
|
await interaction.editReply({ embeds: [hashEmbed] });
|
||||||
|
} catch (fileError) {
|
||||||
|
console.error("File processing error:", fileError);
|
||||||
|
|
||||||
|
// Clean up temp file if it exists
|
||||||
|
if (fs.existsSync(tempFile)) {
|
||||||
|
fs.unlinkSync(tempFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
await interaction.editReply({
|
||||||
|
content: "Error processing file. The file might be inaccessible or corrupted.",
|
||||||
|
ephemeral: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Hash command error:", error);
|
||||||
|
await interaction.editReply({
|
||||||
|
content: "Error generating hash. Please try again with a smaller file or different input.",
|
||||||
|
ephemeral: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: `Command '${interaction.commandName}' not implemented yet.`,
|
content: `Command '${interaction.commandName}' not implemented yet.`,
|
||||||
|
|
1344
package-lock.json
generated
1344
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -26,6 +26,8 @@
|
||||||
"dotenv": "^16.4.7",
|
"dotenv": "^16.4.7",
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
"nodejs": "^0.0.0",
|
"nodejs": "^0.0.0",
|
||||||
"ping": "^0.4.4"
|
"ping": "^0.4.4",
|
||||||
|
"whois-json": "^2.0.4",
|
||||||
|
"wikipedia": "^2.1.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue