new detectors and reactions
This commit is contained in:
parent
73b906fd9b
commit
fe3fd9b1b6
11 changed files with 266 additions and 10 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1 +1,2 @@
|
|||
/node_modules
|
||||
/node_modules
|
||||
bun.lock
|
||||
|
|
@ -4,6 +4,8 @@ réponses troll et fun facts
|
|||
# dépendances
|
||||
bun add fr-compromise conjugation-fr discord.js
|
||||
|
||||
|
||||
# version
|
||||
0.1.1 : initialisation et création du code
|
||||
0.2.1 : ajout de modules de détection
|
||||
- 0.1.1 : initialisation et création du code
|
||||
- 0.2.1 : ajout de modules de détection
|
||||
- 0.2.2 : rajout de nouveaux comportement (détection d'un feur par quelqu'un d'autre, ...)
|
||||
27
detectors/basicDetector.js
Normal file
27
detectors/basicDetector.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import Detector from "./Detector.js";
|
||||
import { cleanMessageContent } from "../utils/strings.js";
|
||||
|
||||
//check the regex for "quoi"
|
||||
// trigger if it's at the end of the sentence (tu fais quoi)
|
||||
// trigger if it's followed by 1 to 3 words (c'est quoi ça)
|
||||
// skip if in the middle of a long sentence (je sais pas quoi faire demain)
|
||||
|
||||
const answers = [
|
||||
...Array(10).fill('feur'),
|
||||
'# feur',
|
||||
'||quoicoubeh|| feur'
|
||||
];
|
||||
|
||||
export default class BasicDetector extends Detector {
|
||||
detect(message) {
|
||||
return /(?:^|\b)quoi\b ?\??(\s\S+){0,3}$/i.test(cleanMessageContent(message));
|
||||
}
|
||||
|
||||
// randomize answer
|
||||
createSpecificReply(message) {
|
||||
if (this.detect(message)) {
|
||||
return Promise.resolve(answers[Math.floor(Math.random() * answers.length)]);
|
||||
}
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
}
|
||||
27
detectors/coubehDetector.js
Normal file
27
detectors/coubehDetector.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import Detector from "./Detector.js";
|
||||
import { cleanMessageContent } from "../utils/strings.js";
|
||||
|
||||
const answers = [
|
||||
'Motif de ban ça',
|
||||
"Non mais t'es pas bien toi ?",
|
||||
'https://tenor.com/view/kaamelott-leodagan-somme-sorte-provocateur-gif-18229391',
|
||||
'https://tenor.com/fr/view/movies-titanic-quotes-its-been-years-84years-gif-14851580',
|
||||
'https://tenor.com/fr/view/au-bucher-shouting-gif-15611785',
|
||||
'https://tenor.com/fr/view/kaamelott-r%C3%A9purgateur-h%C3%A9r%C3%A9tique-au-bucher-gif-18206884'
|
||||
|
||||
];
|
||||
|
||||
export default class QuoicoubehDetector extends Detector {
|
||||
triggerName = 'quoicoubeh';
|
||||
|
||||
detect(message) {
|
||||
return /(?:^|\b)(quoi)?coubeh(?:\b|$)/i.test(cleanMessageContent(message));
|
||||
}
|
||||
|
||||
createSpecificReply(message) {
|
||||
if (this.detect(message)) {
|
||||
return Promise.resolve(answers[Math.floor(Math.random() * answers.length)]);
|
||||
}
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
}
|
||||
|
|
@ -16,13 +16,10 @@ export function createTriggersChecklist() {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for all detectors
|
||||
* Using a Chain of Responsibility pattern
|
||||
*/
|
||||
// Base class for all detectors, using a Chain of Responsibility pattern
|
||||
export default class Detector {
|
||||
nextDetector = null;
|
||||
triggerName = 'quoi'; // Valeur par défaut
|
||||
triggerName = 'quoi'; // default value
|
||||
|
||||
/**
|
||||
* @param nextDetector The detector that will be checked if this one doesn't detect anything
|
||||
|
|
@ -56,7 +53,7 @@ export default class Detector {
|
|||
|
||||
const forcedRoleId = getSetting(message.guildId, 'forcedAnswerRoleId');
|
||||
|
||||
// Si l'utilisateur a le rôle forcé, on ignore le pourcentage (100%)
|
||||
// if user has a forced role, skip the percentage (100%)
|
||||
const threshold = (forcedRoleId != null && message.member?.roles.cache.has(forcedRoleId))
|
||||
? 100
|
||||
: this.getChanceToReply(message);
|
||||
|
|
|
|||
27
detectors/feurDetector.js
Normal file
27
detectors/feurDetector.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import Detector from "./Detector.js";
|
||||
import { cleanMessageContent } from "../utils/strings.js";
|
||||
|
||||
const answers = [
|
||||
"Toi t'es un bon",
|
||||
"ça j'aime, ça",
|
||||
"bien joué !",
|
||||
"aller !",
|
||||
'https://tenor.com/fr/view/deez-ha-got-heem-got-em-got-him-gif-4824899',
|
||||
'https://tenor.com/fr/view/kaamelott-joueur-voil%C3%A0-faites-plaisir-gif-18227872',
|
||||
'https://tenor.com/view/kaamelott-yvain-exp%C3%A9ience-champion-cest-lexp%C3%A9rience-qui-parle-gif-17313437'
|
||||
];
|
||||
|
||||
export default class FeurDetector extends Detector {
|
||||
triggerName = 'feur';
|
||||
|
||||
detect(message) {
|
||||
return /(?:^|\b)feur(?:\b|$)/i.test(cleanMessageContent(message));
|
||||
}
|
||||
|
||||
createSpecificReply(message) {
|
||||
if (this.detect(message)) {
|
||||
return Promise.resolve(answers[Math.floor(Math.random() * answers.length)]);
|
||||
}
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
}
|
||||
17
detectors/index.js
Normal file
17
detectors/index.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import basicDetector from "./basicDetector.js";
|
||||
import feurDetector from "./feurDetector.js";
|
||||
import pingDetector from "./pingDetector.js";
|
||||
import quoicoubehDetector from "./quoicoubehDetector.js";
|
||||
import suffixPrefixDetector from "./suffixPrefixDetector.js";
|
||||
import withPronounDetector from "./withPronounDetector.js"; // Nom aligné
|
||||
|
||||
const firstDetector = new WithPronounDetector(); // Utilisation du bon nom
|
||||
|
||||
firstDetector
|
||||
.setNextDetector(new suffixPrefixDetector())
|
||||
.setNextDetector(new basicDetector())
|
||||
.setNextDetector(new quoicoubehDetector())
|
||||
.setNextDetector(new feurDetector())
|
||||
.setNextDetector(new pingDetector());
|
||||
|
||||
export default firstDetector;
|
||||
|
|
@ -12,6 +12,7 @@ const answers = [
|
|||
export default class PingDetector extends Detector {
|
||||
triggerName = 'mention';
|
||||
|
||||
//prevent trigger if user is doing a troll on its own
|
||||
async detect(message) {
|
||||
if (/(^|\b)(feur|quoicoubeh)(\b|$)/i.test(cleanMessageContent(message))) {
|
||||
return false;
|
||||
|
|
|
|||
51
detectors/suffixDetector.js
Normal file
51
detectors/suffixDetector.js
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import Detector from "./Detector.js";
|
||||
import compromise from 'fr-compromise';
|
||||
import { cleanMessageContent } from "../utils/strings.js";
|
||||
|
||||
const suffixes = [
|
||||
', mon gars',
|
||||
', mec',
|
||||
", je crois",
|
||||
...Array(10).fill('')
|
||||
];
|
||||
|
||||
export default class SuffixPrefixDetector extends Detector {
|
||||
async createSpecificReply(message) {
|
||||
const reference = await message.fetchReference().catch(() => null);
|
||||
// check if it's a reply to the bot
|
||||
const isSelfTarget = (reference && reference.author.id === message.client.user?.id) ?? false;
|
||||
|
||||
const compromiseMatch = compromise(cleanMessageContent(message).toLowerCase()).match(`[<prefix>(!quoi){0,2} (#Verb|faire)? #Preposition?] quoi [<suffix2prefix>#Verb]? [<suffix>(#Determiner !quoi|!quoi)?]?$`);
|
||||
|
||||
if (compromiseMatch == null || compromiseMatch.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.conjugateResponse(compromiseMatch, isSelfTarget);
|
||||
}
|
||||
|
||||
conjugateResponse(compromiseMatch, isSelfTarget = false) {
|
||||
const parsed = compromiseMatch.json();
|
||||
const result = parsed[0];
|
||||
|
||||
let replyPrefix = trimPrefix(compromiseMatch.groups('prefix')?.text().trim() ?? '');
|
||||
const numberOfWordsInPrefix = replyPrefix.split(' ').length;
|
||||
if (numberOfWordsInPrefix > 7) {
|
||||
return null; // Too long, pass to next detector
|
||||
}
|
||||
const replysuffixToPrefix = compromiseMatch.groups('suffix2prefix')?.text().trim() ?? '';
|
||||
const replySuffix = compromiseMatch.groups('suffix')?.text().trim() ?? '';
|
||||
|
||||
if (result == null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return (`${replyPrefix} ${replysuffixToPrefix} feur ${replySuffix.length > 0 ? ` ${replySuffix}` : ''}${suffixes[Math.floor(Math.random() * suffixes.length)]}`).trim().replaceAll(' ', ' ').replace(' ,', ',');
|
||||
}
|
||||
}
|
||||
|
||||
function trimPrefix(prefix) {
|
||||
return (prefix
|
||||
.split(/(?=(?:ç|c)a)/).at(-1) ?? '')
|
||||
.trim();
|
||||
}
|
||||
104
detectors/withPronounDetector.js
Normal file
104
detectors/withPronounDetector.js
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
import Detector from "./Detector.js";
|
||||
import compromise from 'fr-compromise';
|
||||
import conj from 'conjugation-fr';
|
||||
import { toInfinitive } from "../data.js"; // check path ??
|
||||
import { cleanMessageContent } from "../utils/strings.js";
|
||||
|
||||
const suffixes = [
|
||||
', mon gars',
|
||||
', mec',
|
||||
", je crois",
|
||||
'',
|
||||
'',
|
||||
''
|
||||
];
|
||||
|
||||
// check the pronoun of the question to answer properly
|
||||
// exemple : tu fais quoi ? je fais feur
|
||||
|
||||
export default class withPronounDetector extends Detector {
|
||||
async createSpecificReply(message) {
|
||||
const reference = await message.fetchReference().catch(() => null);
|
||||
const isSelfTarget = (reference && reference.author.id === message.client.user?.id) ?? false;
|
||||
|
||||
const compromiseMatch = compromise(cleanMessageContent(message).toLowerCase()).match('(#Pronoun|ça|ca|tu) (#Verb|fait) #Infinitive? quoi [<suffix>!Verb{0,3}]$');
|
||||
|
||||
if (compromiseMatch == null || compromiseMatch.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.conjugateResponse(compromiseMatch, isSelfTarget);
|
||||
}
|
||||
|
||||
conjugateResponse(compromiseMatch, isSelfTarget = false) {
|
||||
const parsed = compromiseMatch.json();
|
||||
const result = parsed[0];
|
||||
|
||||
const replySuffix = compromiseMatch.groups('suffix')?.text().trim() ?? '';
|
||||
|
||||
if (result == null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// warning : result.terms[1] can't exist if the compromise structure change
|
||||
const verbTerm = result.terms[1];
|
||||
if (!verbTerm) return '';
|
||||
|
||||
const verbInfinitive = toInfinitive[verbTerm.text];
|
||||
if (!verbInfinitive) return ''; // safety check if the verb is in the list
|
||||
|
||||
let conjugated = '';
|
||||
const tenseTag = verbTerm.tags.find(t => t.endsWith('Tense')) ?? 'Present';
|
||||
|
||||
const getConjugation = (pronoun) => {
|
||||
const tenseData = conj.findTense(verbInfinitive, tenseTag);
|
||||
return tenseData.find(c => c.pronoun === pronoun)?.verb;
|
||||
};
|
||||
|
||||
switch (result.terms[0].text.toLowerCase()) {
|
||||
case 'je':
|
||||
case "j'":
|
||||
conjugated = `tu ${getConjugation('tu')}`;
|
||||
break;
|
||||
case 'tu':
|
||||
case "t'":
|
||||
if (isSelfTarget) {
|
||||
conjugated = `je ${getConjugation('je')}`;
|
||||
} else {
|
||||
conjugated = `il ${getConjugation('il')}`;
|
||||
}
|
||||
break;
|
||||
case 'il':
|
||||
conjugated = `il ${getConjugation('il')}`;
|
||||
break;
|
||||
case 'elle':
|
||||
conjugated = `elle ${getConjugation('il')}`; // 'elle' utilise la conjugaison 'il' dans cette lib souvent
|
||||
break;
|
||||
case 'on':
|
||||
conjugated = `on ${getConjugation('il')}`;
|
||||
break;
|
||||
case 'ça':
|
||||
conjugated = `ça ${getConjugation('il')}`;
|
||||
break;
|
||||
case 'nous':
|
||||
conjugated = `nous ${getConjugation('nous')}`;
|
||||
break;
|
||||
case 'vous':
|
||||
conjugated = `on ${getConjugation('il')}`;
|
||||
break;
|
||||
case 'ils':
|
||||
conjugated = `ils ${getConjugation('ils')}`;
|
||||
break;
|
||||
case 'elles':
|
||||
conjugated = `elles ${getConjugation('ils')}`;
|
||||
break;
|
||||
default:
|
||||
conjugated = '';
|
||||
break;
|
||||
}
|
||||
|
||||
const infinitiveVerb = result.terms.find(t => t.tags.includes('Infinitive'))?.text ?? '';
|
||||
|
||||
return (`${conjugated} ${infinitiveVerb} feur ${replySuffix}${suffixes[Math.floor(Math.random() * suffixes.length)]}`).trim().replaceAll(' ', ' ').replace(' ,', ',');
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,8 @@
|
|||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"discord.js": "^14.25.0"
|
||||
"conjugation-fr": "^0.3.4",
|
||||
"discord.js": "^14.25.0",
|
||||
"fr-compromise": "^0.2.8"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue