add richer dictionary results

This commit is contained in:
bignutty 2025-03-15 17:34:17 +01:00
parent 27cc17cd4a
commit 3f550a4822
2 changed files with 279 additions and 42 deletions

View file

@ -4,10 +4,11 @@ const {PERMISSION_GROUPS} = require("#constants");
const { createEmbed, page } = require('#utils/embed');
const { acknowledge } = require('#utils/interactions');
const { link, smallPill, icon, pill } = require('#utils/markdown')
const { link, smallPill, icon } = require('#utils/markdown')
const { editOrReply } = require('#utils/message')
const { ApplicationCommandOptionTypes, InteractionContextTypes, ApplicationIntegrationTypes } = require('detritus-client/lib/constants');
const {InteractiveComponentTypes, ResolveCallbackTypes} = require("#cardstack/constants");
// TODO(unity): single constant
const LABELS = {
@ -16,21 +17,21 @@ const LABELS = {
}
// TODO(unity)
function renderDictionaryEntry(context, result, definition, language) {
function renderDictionaryEntry(context, result, definition, resultIndex, definitionIndex) {
let card = createEmbed("default", context, {
description: `### ${result.word}\n-# ${result.phonetic}${definition.type}\n\n`,
description: `### ${result.word}\n-# ${result.phonetic ? `${result.phonetic}` : ""}${definition.type}\n\n`,
url: `https://en.wiktionary.org/wiki/${encodeURIComponent(result.word)}`,
fields: []
})
if(definition.labels?.filter((l)=>LABELS[l]).length >= 1) card.description += `-# ⚠ ${definition.labels.map((l)=>LABELS[l]).join(" ⚠ ")}\n`;
if(definition.labels?.filter((l)=>LABELS[l]).filter((e)=>e!==undefined).length >= 1) card.description += `-# ⚠ ${definition.labels.map((l)=>LABELS[l]).filter((e)=>e!==undefined).join(" ⚠ ")}\n`;
let defs = [];
let i = 1;
for(const d of definition.definitions){
let def = `${i++}. ${d.definition}`;
if(d.labels?.filter((l)=>LABELS[l]).length >= 1) def = `-# ⚠ ${d.labels.map((l)=>LABELS[l]).join(" ⚠ ")}\n` + def;
if(d.labels?.filter((l)=>LABELS[l]).filter((e)=>e!==undefined).length >= 1) def = `-# ⚠ ${d.labels.map((l)=>LABELS[l]).filter((e)=>e!==undefined).join(" ⚠ ")}\n` + def;
if(d.example) def += `\n - *${d.example}*`
let nyms = [];
@ -56,7 +57,17 @@ function renderDictionaryEntry(context, result, definition, language) {
}
card.description += defs.join("\n\n")
return page(card);
return page(card, {}, {
usage_examples: (definition.definitions.map((s)=>s.additional_examples).flat().filter((e)=>e!==undefined).length >= 1),
similar: (
definition.definitions.map((s)=>s.synonyms).flat().filter((e)=>e!==undefined).length >= 1 ||
definition.definitions.map((s)=>s.antonyms).flat().filter((e)=>e!==undefined).length >= 1
),
origin: (result.origin !== undefined),
result: resultIndex,
definition: definitionIndex,
term: result.word
});
}
module.exports = {
@ -96,14 +107,122 @@ module.exports = {
let pages = []
for(const r of search.body.results){
for(const d of r.entries){
pages.push(renderDictionaryEntry(context, r, d, "en"))
let ri = 0;
let di = 0;
for (const r of search.body.results) {
di = 0;
for (const d of r.entries) {
pages.push(renderDictionaryEntry(context, r, d, ri, di))
di++;
}
ri++;
}
return await createDynamicCardStack(context, {
cards: pages
cards: pages,
interactive: {
usage_examples: {
type: InteractiveComponentTypes.BUTTON,
label: "Usage Examples",
inline: true,
visible: true,
instantResult: true,
condition: (page) => {
return page.getState("usage_examples")
},
resolvePage: async (pg) => {
let result = search.body.results[pg.getState("result")]
let definition = result.entries[pg.getState("definition")];
let usageCard = createEmbed("default", context, {
description: `### ${pg.getState("term")}\n`,
})
let additional = definition.definitions.map((s)=>s.additional_examples).flat(2).filter((e)=>e!==undefined);
if (additional.length >= 1) usageCard.description += "- " +
additional.map(value => ({value, sort: Math.random()}))
.sort((a, b) => a.sort - b.sort)
.map(({value}) => value)
.splice(0, 7)
.join('\n- ');
if(search.body.trends){
usageCard.description += `\n\n-# Usage over time`
usageCard.image = { url: search.body.trends.image };
}
return {
type: ResolveCallbackTypes.SUBSTACK,
cards: [
page(usageCard)
]
};
}
},
similar_and_opposite: {
type: InteractiveComponentTypes.BUTTON,
label: "Similar and Opposite Words",
inline: true,
visible: true,
instantResult: true,
condition: (page) => {
return page.getState("similar")
},
resolvePage: async (pg) => {
let result = search.body.results[pg.getState("result")]
let definition = result.entries[pg.getState("definition")];
let similarCard = createEmbed("default", context, {
description: `### ${pg.getState("term")}\n-# ${definition.type}\n\n`,
})
let synonyms = definition.definitions.map((d)=>d.synonyms).flat(2).filter((e)=>e!==undefined);
let antonyms = definition.definitions.map((d)=>d.antonyms).flat(2).filter((e)=>e!==undefined);
if(synonyms.length >= 1){
similarCard.description += `**Similar**\n-# ${synonyms.map((s)=>smallPill(s)).join(" ")}\n\n`
}
if(antonyms.length >= 1){
similarCard.description += `**Opposite**\n-# ${antonyms.map((s)=>smallPill(s)).join(" ")}\n\n`
}
return {
type: ResolveCallbackTypes.SUBSTACK,
cards: [
page(similarCard)
]
};
}
},
term_origin: {
type: InteractiveComponentTypes.BUTTON,
label: "Origin",
inline: true,
visible: true,
instantResult: true,
condition: (page) => {
return page.getState("origin")
},
resolvePage: async (pg) => {
let result = search.body.results[pg.getState("result")];
let originCard = createEmbed("default", context, {
description: `### ${pg.getState("term")}\n${result.origin.description}`,
})
if(result.origin.image) originCard.image = { url: result.origin.image };
return {
type: ResolveCallbackTypes.SUBSTACK,
cards: [
page(originCard)
]
};
}
}
}
});
}catch(e){
if(e.response?.body?.status && e.response.body.status === 2) return editOrReply(context, createEmbed("warning", context, e.response.body.message))

View file

@ -1,12 +1,13 @@
const { dictionary } = require('#api');
const {dictionary} = require('#api');
const {createDynamicCardStack} = require("#cardstack/index");
const {PERMISSION_GROUPS} = require("#constants");
const { createEmbed, page } = require('#utils/embed');
const { acknowledge } = require('#utils/interactions');
const { link, smallPill, icon, pill } = require('#utils/markdown')
const { editOrReply } = require('#utils/message')
const { dictionaryGetCodeFromAny } = require('#utils/translate');
const {createEmbed, page} = require('#utils/embed');
const {acknowledge} = require('#utils/interactions');
const {link, smallPill, icon} = require('#utils/markdown')
const {editOrReply} = require('#utils/message')
const {dictionaryGetCodeFromAny} = require('#utils/translate');
const {InteractiveComponentTypes, ResolveCallbackTypes} = require("#cardstack/constants");
// TODO(unity): single constant
const LABELS = {
@ -15,33 +16,33 @@ const LABELS = {
}
// TODO(unity)
function renderDictionaryEntry(context, result, definition, language) {
function renderDictionaryEntry(context, result, definition, resultIndex, definitionIndex) {
let card = createEmbed("default", context, {
description: `### ${result.word}\n-# ${result.phonetic}${definition.type}\n\n`,
description: `### ${result.word}\n-# ${result.phonetic ? `${result.phonetic}` : ""}${definition.type}\n\n`,
url: `https://en.wiktionary.org/wiki/${encodeURIComponent(result.word)}`,
fields: []
})
if(definition.labels?.filter((l)=>LABELS[l]).length >= 1) card.description += `-# ⚠ ${definition.labels.map((l)=>LABELS[l]).join(" ⚠ ")}\n`;
if (definition.labels?.filter((l) => LABELS[l]).filter((e)=>e!==undefined).length >= 1) card.description += `-# ⚠ ${definition.labels.map((l) => LABELS[l]).filter((e)=>e!==undefined).join(" ⚠ ")}\n`;
let defs = [];
let i = 1;
for(const d of definition.definitions){
let def = `${i++}. ${d.definition}`;
for (const d of definition.definitions) {
let def = `${i++}. ${d.definition}`;
if(d.labels?.filter((l)=>LABELS[l]).length >= 1) def = `-# ⚠ ${d.labels.map((l)=>LABELS[l]).join(" ⚠ ")}\n` + def;
if(d.example) def += `\n - *${d.example}*`
if (d.labels?.filter((l) => LABELS[l]).filter((e)=>e!==undefined).length >= 1) def = `-# ⚠ ${d.labels.map((l) => LABELS[l]).filter((e)=>e!==undefined).join(" ⚠ ")}\n` + def;
if (d.example) def += `\n - *${d.example}*`
let nyms = [];
if(d.synonyms) nyms = nyms.concat(d.synonyms.map((sd)=>smallPill(sd)))
if (d.synonyms) nyms = nyms.concat(d.synonyms.map((sd) => smallPill(sd)))
// Display up to 6 random synonyms/antonyms
if(nyms.length >= 1) {
nyms = nyms.splice(0 ,6)
.map(value => ({ value, sort: Math.random() }))
.sort((a, b) => a.sort - b.sort)
.map(({ value }) => value)
if (nyms.length >= 1) {
nyms = nyms.splice(0, 6)
.map(value => ({value, sort: Math.random()}))
.sort((a, b) => a.sort - b.sort)
.map(({value}) => value)
def += `\n-# ${nyms.join(" ")}`
}
@ -49,13 +50,23 @@ function renderDictionaryEntry(context, result, definition, language) {
defs.push(def);
}
if(defs.length > 5){
if (defs.length > 5) {
defs = defs.splice(0, 5);
defs.push(link(`https://www.google.com/search?q=define+${encodeURIComponent(result.word)}`, `More Definitions ${icon("open_in_new")}`))
}
card.description += defs.join("\n\n")
return page(card);
return page(card, {}, {
usage_examples: (definition.definitions.map((s)=>s.additional_examples).flat().filter((e)=>e!==undefined).length >= 1),
similar: (
definition.definitions.map((s)=>s.synonyms).flat().filter((e)=>e!==undefined).length >= 1 ||
definition.definitions.map((s)=>s.antonyms).flat().filter((e)=>e!==undefined).length >= 1
),
origin: (result.origin !== undefined),
result: resultIndex,
definition: definitionIndex,
term: result.word
});
}
module.exports = {
@ -77,30 +88,137 @@ module.exports = {
run: async (context, args) => {
await acknowledge(context);
let language = dictionaryGetCodeFromAny(args.lang);
if(!language) return editOrReply(context, createEmbed("warning", context, "Invalid Language"))
if (!language) return editOrReply(context, createEmbed("warning", context, "Invalid Language"))
try{
try {
let search = await dictionary(context, args.query, language)
search = search.response
if(search.body.status === 1) return editOrReply(context, createEmbed("warning", context, search.body.message))
if (search.body.status === 1) return editOrReply(context, createEmbed("warning", context, search.body.message))
let pages = []
for(const r of search.body.results){
for(const d of r.entries){
pages.push(renderDictionaryEntry(context, r, d, language))
let ri = 0;
let di = 0;
for (const r of search.body.results) {
di = 0;
for (const d of r.entries) {
pages.push(renderDictionaryEntry(context, r, d, ri, di))
di++;
}
ri++;
}
return await createDynamicCardStack(context, {
cards: pages
cards: pages,
interactive: {
usage_examples: {
type: InteractiveComponentTypes.BUTTON,
label: "Usage Examples",
inline: true,
visible: true,
instantResult: true,
condition: (page) => {
return page.getState("usage_examples")
},
resolvePage: async (pg) => {
let result = search.body.results[pg.getState("result")]
let definition = result.entries[pg.getState("definition")];
let usageCard = createEmbed("default", context, {
description: `### ${pg.getState("term")}\n`,
})
let additional = definition.definitions.map((s)=>s.additional_examples).flat(2).filter((e)=>e!==undefined);
if (additional.length >= 1) usageCard.description += "- " +
additional.map(value => ({value, sort: Math.random()}))
.sort((a, b) => a.sort - b.sort)
.map(({value}) => value)
.splice(0, 7)
.join('\n- ');
if(search.body.trends){
usageCard.description += `\n\n-# Usage over time`
usageCard.image = { url: search.body.trends.image };
}
return {
type: ResolveCallbackTypes.SUBSTACK,
cards: [
page(usageCard)
]
};
}
},
similar_and_opposite: {
type: InteractiveComponentTypes.BUTTON,
label: "Similar and Opposite Words",
inline: true,
visible: true,
instantResult: true,
condition: (page) => {
return page.getState("similar")
},
resolvePage: async (pg) => {
let result = search.body.results[pg.getState("result")]
let definition = result.entries[pg.getState("definition")];
let similarCard = createEmbed("default", context, {
description: `### ${pg.getState("term")}\n-# ${definition.type}\n\n`,
})
let synonyms = definition.definitions.map((d)=>d.synonyms).flat(2).filter((e)=>e!==undefined);
let antonyms = definition.definitions.map((d)=>d.antonyms).flat(2).filter((e)=>e!==undefined);
if(synonyms.length >= 1){
similarCard.description += `**Similar**\n-# ${synonyms.map((s)=>smallPill(s)).join(" ")}\n\n`
}
if(antonyms.length >= 1){
similarCard.description += `**Opposite**\n-# ${antonyms.map((s)=>smallPill(s)).join(" ")}\n\n`
}
return {
type: ResolveCallbackTypes.SUBSTACK,
cards: [
page(similarCard)
]
};
}
},
term_origin: {
type: InteractiveComponentTypes.BUTTON,
label: "Origin",
inline: true,
visible: true,
instantResult: true,
condition: (page) => {
return page.getState("origin")
},
resolvePage: async (pg) => {
let result = search.body.results[pg.getState("result")];
let originCard = createEmbed("default", context, {
description: `### ${pg.getState("term")}\n${result.origin.description}`,
})
if(result.origin.image) originCard.image = { url: result.origin.image };
return {
type: ResolveCallbackTypes.SUBSTACK,
cards: [
page(originCard)
]
};
}
}
}
});
}catch(e){
if(e.response?.body?.status && e.response.body.status === 2) return editOrReply(context, createEmbed("warning", context, e.response.body.message))
} catch (e) {
if (e.response?.body?.status && e.response.body.status === 2) return editOrReply(context, createEmbed("warning", context, e.response.body.message))
console.log(e)
return editOrReply(context, createEmbed("error", context, `Unable to perform dictionary lookup.`))
}