replace lexicala with wordnik
This commit is contained in:
parent
4f887e3331
commit
2b42fb63f4
@ -2,7 +2,7 @@
|
||||
"main": "plugin.js",
|
||||
"name": "diction",
|
||||
"description": "Find definitions for words",
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.1",
|
||||
"tags": ["commands", "utility", "dictionary"],
|
||||
"dependencies": ["simplecommands"],
|
||||
"npmDependencies": []
|
||||
|
@ -8,28 +8,60 @@ import {
|
||||
} from '@squeebot/core/lib/plugin';
|
||||
import { IMessage, MessageResolver } from '@squeebot/core/lib/types';
|
||||
|
||||
const poslist = [
|
||||
'noun',
|
||||
'verb',
|
||||
'adjective',
|
||||
'adverb',
|
||||
'participle',
|
||||
'article',
|
||||
'pronoun',
|
||||
'preposition',
|
||||
'conjunction',
|
||||
'interjection',
|
||||
'determiner',
|
||||
];
|
||||
interface IDefinition {
|
||||
partOfSpeech: string;
|
||||
text: string;
|
||||
}
|
||||
|
||||
interface IWordCache {
|
||||
lastIndex: {
|
||||
name: string;
|
||||
index: number;
|
||||
lastTime: number;
|
||||
}[];
|
||||
definitions: IDefinition[];
|
||||
inserted: number;
|
||||
}
|
||||
|
||||
let lastQuery = 0;
|
||||
const wordCache: Record<string, IWordCache> = {};
|
||||
|
||||
/**
|
||||
* Find and remove words that haven't been looked up for a day
|
||||
*/
|
||||
function flushCache() {
|
||||
let oldestWords: string[] = [];
|
||||
Object.keys(wordCache).forEach((word) => {
|
||||
const cached = wordCache[word];
|
||||
let notOld = false;
|
||||
|
||||
for (const person of cached.lastIndex) {
|
||||
if (person.lastTime > Date.now() - 24 * 60 * 60 * 1000) {
|
||||
notOld = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!notOld) {
|
||||
oldestWords.push(word);
|
||||
}
|
||||
});
|
||||
|
||||
if (!oldestWords.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
oldestWords.forEach((item) => {
|
||||
delete wordCache[item];
|
||||
});
|
||||
|
||||
logger.log(`[diction] Dictionary cleared of the previous words ${oldestWords.join(', ')}.`);
|
||||
}
|
||||
|
||||
@Configurable({
|
||||
lexicala: {
|
||||
username: '',
|
||||
password: '',
|
||||
},
|
||||
wordnik: '',
|
||||
cooldown: 5,
|
||||
limit: 5,
|
||||
})
|
||||
class DictionPlugin extends Plugin {
|
||||
@EventListener('pluginUnload')
|
||||
@ -41,13 +73,12 @@ class DictionPlugin extends Plugin {
|
||||
|
||||
@DependencyLoad('simplecommands')
|
||||
addCommands(cmd: any): void {
|
||||
const user = this.config.get('lexicala.username');
|
||||
const passwd = this.config.get('lexicala.password');
|
||||
const key = this.config.get('wordnik');
|
||||
const rate = this.config.get('cooldown', 5);
|
||||
const rauth = 'Basic ' + Buffer.from(`${user}:${passwd}`).toString('base64');
|
||||
const limit = this.config.get('limit', 5);
|
||||
|
||||
if (!user || !passwd) {
|
||||
logger.warn('Lexicala define command is disabled due to no credentials.');
|
||||
if (!key) {
|
||||
logger.warn('Wordnik define command is disabled due to no credentials.');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -55,66 +86,105 @@ class DictionPlugin extends Plugin {
|
||||
name: 'define',
|
||||
plugin: this.name,
|
||||
execute: async (msg: IMessage, msr: MessageResolver, spec: any, prefix: string, ...simplified: any[]): Promise<boolean> => {
|
||||
if (lastQuery > Date.now() - rate * 1000) {
|
||||
msg.resolve('You\'re doing that too fast!');
|
||||
return true;
|
||||
}
|
||||
|
||||
let pos: string | null = simplified[0];
|
||||
if (pos && poslist.indexOf(pos.toLowerCase()) !== -1 && simplified.length > 1) {
|
||||
pos = '&pos=' + pos;
|
||||
} else {
|
||||
pos = '';
|
||||
}
|
||||
|
||||
const word = encodeURIComponent(simplified.slice(pos ? 1 : 0).join(' '));
|
||||
const word = simplified.join(' ');
|
||||
|
||||
if (!word) {
|
||||
msg.resolve('Please specifiy a word or term!');
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lastQuery > Date.now() - rate * 1000 && !wordCache[word]) {
|
||||
msg.resolve('You\'re doing that too fast!');
|
||||
return true;
|
||||
}
|
||||
|
||||
let chosenDefinition: IDefinition;
|
||||
let definitionCount = 0;
|
||||
let definitionIndex = 0;
|
||||
|
||||
// Check cached definitions
|
||||
const userTarget = msg.fullSenderID as string;
|
||||
if (wordCache[word]) {
|
||||
const cached = wordCache[word];
|
||||
const alreadyAsked = cached.lastIndex.find((item) => item.name === userTarget);
|
||||
definitionCount = cached.definitions.length;
|
||||
|
||||
if (alreadyAsked) {
|
||||
let nextI = alreadyAsked.index + 1;
|
||||
|
||||
if (nextI >= cached.definitions.length) {
|
||||
nextI = 0;
|
||||
}
|
||||
|
||||
if (alreadyAsked.lastTime < Date.now() - 5 * 60 * 1000) {
|
||||
nextI = 0;
|
||||
}
|
||||
|
||||
alreadyAsked.lastTime = Date.now();
|
||||
alreadyAsked.index = nextI;
|
||||
definitionIndex = nextI;
|
||||
chosenDefinition = cached.definitions[nextI];
|
||||
} else {
|
||||
chosenDefinition = cached.definitions[0];
|
||||
cached.lastIndex.push({
|
||||
name: userTarget,
|
||||
index: 0,
|
||||
lastTime: Date.now(),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Request definition
|
||||
const encodedWord = encodeURIComponent(word);
|
||||
lastQuery = Date.now();
|
||||
|
||||
let response;
|
||||
try {
|
||||
const s = `https://dictapi.lexicala.com/search?source=global&language=en${pos}&text=${word}`;
|
||||
response = await httpGET(s, { Authorization: rauth });
|
||||
const s = `https://api.wordnik.com/v4/word.json/${encodedWord}/definitions?limit=${limit}&api_key=${key}`;
|
||||
response = await httpGET(s);
|
||||
response = JSON.parse(response);
|
||||
} catch (e) {
|
||||
msg.resolve('Server did not respond.');
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!response.n_results || response.n_results === 0 || !response.results) {
|
||||
msg.resolve('Nothing found.');
|
||||
if (!response || !response.length) {
|
||||
msg.resolve('No definitions found.');
|
||||
return true;
|
||||
}
|
||||
|
||||
const resolve = [];
|
||||
for (const def of response.results) {
|
||||
const wd = def.headword.text;
|
||||
const wdp = def.headword.pos;
|
||||
const results = def.senses.map((rep: any) => rep.definition).slice(0, 4);
|
||||
|
||||
resolve.push({
|
||||
word: wd,
|
||||
type: wdp,
|
||||
results,
|
||||
});
|
||||
const cached: IWordCache = {
|
||||
lastIndex: [
|
||||
{
|
||||
name: userTarget,
|
||||
index: 0,
|
||||
lastTime: Date.now(),
|
||||
}
|
||||
],
|
||||
definitions: (response as Record<string, string>[]).map(({ partOfSpeech, text }) => ({
|
||||
partOfSpeech, text: text.replace(/(<([^>]+)>)/ig, '')
|
||||
})),
|
||||
inserted: Date.now(),
|
||||
}
|
||||
|
||||
const str = resolve.slice(0, 4).map((rep: any) => {
|
||||
return `${rep.word} (${rep.type}):\n` + rep.results.join('\n');
|
||||
}).join('\n');
|
||||
wordCache[word] = cached;
|
||||
chosenDefinition = cached.definitions[0];
|
||||
definitionCount = cached.definitions.length;
|
||||
logger.log(`[diction] Dictionary cached the word "${word}"`);
|
||||
flushCache();
|
||||
}
|
||||
|
||||
const { partOfSpeech, text } = chosenDefinition;
|
||||
|
||||
msg.resolve(`(${definitionIndex + 1}/${definitionCount}) ${word}${
|
||||
partOfSpeech ? ` - ${partOfSpeech}` : ''
|
||||
} - ${text}`);
|
||||
|
||||
msg.resolve(str);
|
||||
return true;
|
||||
},
|
||||
match: /define (\w*)/,
|
||||
aliases: ['df'],
|
||||
description: 'Find definitions for words',
|
||||
usage: '[<pos>] <word>'
|
||||
description: 'Find definitions for words. Call again to advance to next definition',
|
||||
usage: '<word>'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
},
|
||||
{
|
||||
"name": "diction",
|
||||
"version": "1.1.0"
|
||||
"version": "1.2.1"
|
||||
},
|
||||
{
|
||||
"name": "fun",
|
||||
|
Loading…
Reference in New Issue
Block a user