Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions commands/define.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
const { getMeanings } = require('../services/dictionary');

const MAX_MEANINGS = 8;
const MAX_DEFINITIONS_PER_MEANING = 3;
const MAX_MESSAGE_LENGTH = 1900;

function summarizeMeaning(meaning) {
const definitions = meaning.definitions.slice(0, MAX_DEFINITIONS_PER_MEANING);
if (!definitions.length)
return null;

const partOfSpeech = meaning.partOfSpeech ? `${meaning.partOfSpeech}: ` : '';
return `${partOfSpeech}${definitions.join(' | ')}`;
}

function buildMeaningsMessage(term, meanings) {
const summaries = meanings
.map(summarizeMeaning)
.filter(Boolean)
.slice(0, MAX_MEANINGS);

const lines = [`Meanings for **${term}**:`];
let added = 0;

for (let i = 0; i < summaries.length; i++) {
const candidateLine = `${i + 1}. ${summaries[i]}`;
const preview = `${lines.join('\n')}\n${candidateLine}`;

if (preview.length > MAX_MESSAGE_LENGTH)
break;

lines.push(candidateLine);
added++;
}

const hiddenCount = Math.max(0, summaries.length - added) + Math.max(0, meanings.length - MAX_MEANINGS);
if (hiddenCount > 0)
lines.push(`...and ${hiddenCount} more meaning(s).`);

return lines.join('\n');
}

async function defineCommand(message, args) {
const term = args.join(' ').trim();

if (!term) {
await message.channel.send(`Please provide a term. Example: \`${message.client.prefix}define bitcoin\``);
return;
}

let meanings;
try {
meanings = await getMeanings(term);
} catch {
await message.channel.send('Unable to fetch definitions right now. Please try again later.');
return;
}

if (meanings.length === 0) {
await message.channel.send(`No meanings found for **${term}**.`);
return;
}

await message.channel.send(buildMeaningsMessage(term, meanings));
}

module.exports = {
define: {
execute: defineCommand
},
def: {
execute: defineCommand
}
};
42 changes: 42 additions & 0 deletions services/dictionary.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const axios = require('axios');

const DICTIONARY_API_URL = 'https://api.dictionaryapi.dev/api/v2/entries/en/';

function normalizeMeaning(meaning) {
const partOfSpeech = String(meaning?.partOfSpeech || '').trim();
const definitions = Array.isArray(meaning?.definitions)
? meaning.definitions
.map(definition => String(definition?.definition || '').trim())
.filter(Boolean)
: [];

return {
partOfSpeech,
definitions
};
}

async function getMeanings(term) {
const normalizedTerm = String(term || '').trim();
if (!normalizedTerm)
return [];

try {
const response = await axios.get(`${DICTIONARY_API_URL}${encodeURIComponent(normalizedTerm)}`);
const entries = Array.isArray(response.data) ? response.data : [];

return entries
.flatMap(entry => Array.isArray(entry?.meanings) ? entry.meanings : [])
.map(normalizeMeaning)
.filter(meaning => meaning.definitions.length > 0);
} catch (error) {
if (error.response?.status === 404)
return [];

throw new Error('Failed to fetch meanings.');
}
}

module.exports = {
getMeanings
};
Loading