replace lexicala with wordnik

This commit is contained in:
Evert Prants 2021-09-15 21:50:28 +03:00
parent 4f887e3331
commit 2b42fb63f4
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
3 changed files with 137 additions and 67 deletions

View File

@ -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": []

View File

@ -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;
}
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 });
response = JSON.parse(response);
} catch (e) {
msg.resolve('Server did not respond.');
if (lastQuery > Date.now() - rate * 1000 && !wordCache[word]) {
msg.resolve('You\'re doing that too fast!');
return true;
}
if (!response.n_results || response.n_results === 0 || !response.results) {
msg.resolve('Nothing found.');
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://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 || !response.length) {
msg.resolve('No definitions found.');
return true;
}
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(),
}
wordCache[word] = cached;
chosenDefinition = cached.definitions[0];
definitionCount = cached.definitions.length;
logger.log(`[diction] Dictionary cached the word "${word}"`);
flushCache();
}
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);
const { partOfSpeech, text } = chosenDefinition;
resolve.push({
word: wd,
type: wdp,
results,
});
}
msg.resolve(`(${definitionIndex + 1}/${definitionCount}) ${word}${
partOfSpeech ? ` - ${partOfSpeech}` : ''
} - ${text}`);
const str = resolve.slice(0, 4).map((rep: any) => {
return `${rep.word} (${rep.type}):\n` + rep.results.join('\n');
}).join('\n');
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>'
});
}
}

View File

@ -11,7 +11,7 @@
},
{
"name": "diction",
"version": "1.1.0"
"version": "1.2.1"
},
{
"name": "fun",