Compare commits
37 Commits
055440418e
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59dd7c793a | ||
|
|
a9f733227c | ||
|
|
19feb9a55f | ||
|
|
df3c682ff6 | ||
|
|
aca9a4b597 | ||
|
|
e4055ad99c | ||
|
|
5dcb928c35 | ||
|
|
8c7995340e | ||
|
|
84025d6a8b | ||
|
|
84b158cf21 | ||
|
|
7531a69904 | ||
|
|
c402628161 | ||
|
|
e9df99bdcb | ||
|
|
a0f1914ce6 | ||
|
|
857f1816f0 | ||
|
|
5ac935cc95 | ||
|
|
af9f15d11d | ||
|
|
7747eabce2 | ||
|
|
990e18d3da | ||
|
|
234bbb2bbc | ||
|
|
f46d5f008b | ||
|
|
a86ef925ff | ||
|
|
ad26d2635c | ||
|
|
8d98581cd9 | ||
|
|
c2cdd55f2d | ||
|
|
34b3269d54 | ||
|
|
5aa5b1852a | ||
|
|
c3cadc3169 | ||
|
|
29cbd77e35 | ||
|
|
2310352ad6 | ||
|
|
5cc3a428f3 | ||
|
|
bbe573d8f3 | ||
|
|
3196877c37 | ||
|
|
ab25066936 | ||
|
|
f384d595e4 | ||
|
|
4ada601fb2 | ||
|
|
13e0bb9a8c |
@@ -15,6 +15,6 @@
|
|||||||
"no-console": 0,
|
"no-console": 0,
|
||||||
"indent": ["error", "tab"],
|
"indent": ["error", "tab"],
|
||||||
"no-tabs": 0,
|
"no-tabs": 0,
|
||||||
"max-len": [2, {"code": 400, "tabWidth": 4, "ignoreUrls": true}]
|
"max-len": 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -4,5 +4,5 @@ config/*
|
|||||||
*.config.js
|
*.config.js
|
||||||
!ecosystem.config.js
|
!ecosystem.config.js
|
||||||
*.sqlite
|
*.sqlite
|
||||||
points*.json
|
points/*
|
||||||
assets/mash-words.json
|
assets/mash-words.json
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const fs = require('fs').promises;
|
const fs = require('fs').promises;
|
||||||
|
|
||||||
|
/*
|
||||||
const inflect = require('inflect');
|
const inflect = require('inflect');
|
||||||
const tensify = require('tensify');
|
const tensify = require('tensify');
|
||||||
|
|
||||||
const dictionary = require('./dictionary.json');
|
|
||||||
|
|
||||||
function getTenses(word) {
|
function getTenses(word) {
|
||||||
try {
|
try {
|
||||||
const { past, past_participle: participle } = tensify(word);
|
const { past, past_participle: participle } = tensify(word);
|
||||||
@@ -15,26 +15,40 @@ function getTenses(word) {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
const dictionary = require('./dictionary.json');
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
|
/*
|
||||||
const formsDictionary = Object.fromEntries(Object.entries(dictionary).flatMap(([word, definition]) => {
|
const formsDictionary = Object.fromEntries(Object.entries(dictionary).flatMap(([word, definition]) => {
|
||||||
const plural = inflect.pluralize(word);
|
const plural = inflect.pluralize(word);
|
||||||
const { past, participle } = getTenses(word);
|
const { past, participle } = getTenses(word);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
[word, definition],
|
[word, definition],
|
||||||
...(plural && !dictionary[plural] ? [[plural, `Plural of ${word}`]] : []),
|
...(plural && !dictionary[plural] ? [[plural, definition]] : []),
|
||||||
...(past && !dictionary[past] ? [[past, `Past tense of ${word}`]] : []),
|
...(past && !dictionary[past] ? [[past, definition]] : []),
|
||||||
...(participle && !dictionary[participle] ? [[past, `Past participle of ${word}`]] : []),
|
...(participle && !dictionary[participle] ? [[past, definition]] : []),
|
||||||
];
|
];
|
||||||
}));
|
}));
|
||||||
|
*/
|
||||||
|
|
||||||
const validWords = Object.entries(formsDictionary).filter(([word]) => /^[a-zA-Z]+$/.test(word));
|
const validWords = Object.entries(dictionary).filter(([word]) => /^[a-zA-Z]+$/.test(word));
|
||||||
|
|
||||||
const sortedWords = validWords.reduce((acc, [rawWord, fullDefinition]) => {
|
const sortedWords = validWords.reduce((acc, [rawWord, fullDefinition]) => {
|
||||||
const word = rawWord.toLowerCase();
|
const word = rawWord.toLowerCase();
|
||||||
const anagram = word.split('').sort().join('');
|
const anagram = word.split('').sort().join('');
|
||||||
const definitions = fullDefinition?.split(/\d+\.\s+/).filter(Boolean).map((definition) => definition.split('.')[0].toLowerCase());
|
const definitions = fullDefinition
|
||||||
|
?.split(/\d+\.\s+/).filter(Boolean).map((definition) => {
|
||||||
|
const splitIndex = definition.indexOf('.', 16); // split after n characters to avoid splitting on e.g. abbreviated categories at the start of the definition: (Anat.)
|
||||||
|
|
||||||
|
if (splitIndex > -1) {
|
||||||
|
return definition.slice(0, splitIndex).trim().toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
return definition.toLowerCase();
|
||||||
|
}) || [];
|
||||||
|
|
||||||
if (!acc[anagram.length]) {
|
if (!acc[anagram.length]) {
|
||||||
acc[anagram.length] = {};
|
acc[anagram.length] = {};
|
||||||
|
|||||||
180182
assets/dictionary.json
Executable file → Normal file
180182
assets/dictionary.json
Executable file → Normal file
File diff suppressed because one or more lines are too long
102260
assets/dictionary_old.json
Executable file
102260
assets/dictionary_old.json
Executable file
File diff suppressed because one or more lines are too long
31
assets/words-to-dictionary.js
Normal file
31
assets/words-to-dictionary.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const fs = require('fs').promises;
|
||||||
|
|
||||||
|
const words = require('./words.json');
|
||||||
|
const wordsBlacklist = require('./words_blacklist.json');
|
||||||
|
const dictionary = require('./dictionary.json');
|
||||||
|
|
||||||
|
// mainly lowercase names
|
||||||
|
const blacklist = new Set(wordsBlacklist);
|
||||||
|
|
||||||
|
async function init() {
|
||||||
|
const notNameWords = words.filter((word) => word.charAt(0) === word.charAt(0).toLowerCase() && !blacklist.has(word)); // don't include names for places, products, people, etc.
|
||||||
|
|
||||||
|
const definitions = Object.fromEntries(notNameWords.map((word) => {
|
||||||
|
const normalizedWord = word.normalize('NFD').replace(/\p{Diacritic}/ug, '').toLowerCase().trim();
|
||||||
|
const definition = dictionary[normalizedWord];
|
||||||
|
const singular = normalizedWord.replace(/s$/, '');
|
||||||
|
const singularDefinition = dictionary[singular];
|
||||||
|
|
||||||
|
return [normalizedWord, definition || singularDefinition || null];
|
||||||
|
}));
|
||||||
|
|
||||||
|
const string = JSON.stringify(definitions, null, 4);
|
||||||
|
|
||||||
|
await fs.writeFile('./dictionary.json', string);
|
||||||
|
|
||||||
|
console.log(`Wrote ${Object.keys(definitions).length} words to ./dictionary.json`);
|
||||||
|
}
|
||||||
|
|
||||||
|
init();
|
||||||
89686
assets/words.json
Normal file
89686
assets/words.json
Normal file
File diff suppressed because it is too large
Load Diff
4
assets/words_blacklist.json
Normal file
4
assets/words_blacklist.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[
|
||||||
|
"ioctl",
|
||||||
|
"xterm"
|
||||||
|
]
|
||||||
@@ -136,8 +136,9 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
wordle: {
|
wordle: {
|
||||||
minLength: 3,
|
minLength: 3,
|
||||||
defaultLength: 5,
|
length: 5,
|
||||||
highlightRepeat: false, // in wordle, if the I in the guess HINDI is in the wrong place, only the first I is orange
|
bonusDictionaryThreshold: 1000, // minimum dictionary size to assign bonus points, prevent people from scoring full bonus points from 1-word dictionaries
|
||||||
|
mode: 'easy',
|
||||||
},
|
},
|
||||||
numbers: {
|
numbers: {
|
||||||
length: 6,
|
length: 6,
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "schat2-clive",
|
"name": "schat2-clive",
|
||||||
"version": "1.29.1",
|
"version": "1.30.8",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "schat2-clive",
|
"name": "schat2-clive",
|
||||||
"version": "1.29.1",
|
"version": "1.30.8",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"better-sqlite3": "^8.3.0",
|
"better-sqlite3": "^8.3.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "schat2-clive",
|
"name": "schat2-clive",
|
||||||
"version": "1.29.1",
|
"version": "1.30.8",
|
||||||
"description": "Game host for SChat 2-powered chat sites",
|
"description": "Game host for SChat 2-powered chat sites",
|
||||||
"main": "src/app.js",
|
"main": "src/app.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ function start(length, context, attempt = 0) {
|
|||||||
|
|
||||||
if (answers.some((answer) => answer.word === anagram)) {
|
if (answers.some((answer) => answer.word === anagram)) {
|
||||||
if (attempt >= 10) {
|
if (attempt >= 10) {
|
||||||
context.sendMessage(`Sorry, I did not find a mashable ${length}-letter word`);
|
context.sendMessage(`Sorry, I did not find a mashable ${length}-letter word`, context.room.id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +81,9 @@ function play(rawWord, context, shouted) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (answer) {
|
if (answer) {
|
||||||
const definition = answer.definitions[0] ? `: ${style.italic(`${answer.definitions[0].slice(0, 100)}${mash.answers[0].definitions[0].length > 100 ? '...' : ''}`)}` : '';
|
const definition = answer.definitions[0]
|
||||||
|
? `: ${style.italic(`${answer.definitions[0].slice(0, 100)}${answer.definitions[0].length > 100 ? '...' : ''}`)}`
|
||||||
|
: '';
|
||||||
|
|
||||||
context.sendMessage(mash.answers.length === 1
|
context.sendMessage(mash.answers.length === 1
|
||||||
? `${style.bold(style.yellow(word))} is the right answer${definition}, ${style.bold(style.cyan(`${config.usernamePrefix}${context.user.username}`))} now has ${style.bold(`${context.user.points + 1} ${context.user.points === 0 ? 'point' : 'points'}`)}! There were no other options for ${style.bold(mash.anagram)}.`
|
? `${style.bold(style.yellow(word))} is the right answer${definition}, ${style.bold(style.cyan(`${config.usernamePrefix}${context.user.username}`))} now has ${style.bold(`${context.user.points + 1} ${context.user.points === 0 ? 'point' : 'points'}`)}! There were no other options for ${style.bold(mash.anagram)}.`
|
||||||
@@ -144,10 +146,19 @@ function define(word, context) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.sendMessage(`No definition available for ${style.bold(word)}, ${config.usernamePrefix}${context.user.username}`, context.room.id);
|
if (answer) {
|
||||||
|
context.sendMessage(`${style.bold(word)} is in my dictionary, but I cannot provide a definition, ${config.usernamePrefix}${context.user.username}`, context.room.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.sendMessage(`${style.bold(word)} is not in my dictionary, ${config.usernamePrefix}${context.user.username}`, context.room.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function sanitizeDefinition(definition, answers) {
|
function sanitizeDefinition(definition, answers) {
|
||||||
|
if (!definition) {
|
||||||
|
return 'No definition';
|
||||||
|
}
|
||||||
|
|
||||||
return definition.replaceAll(/\w+/g, (word) => {
|
return definition.replaceAll(/\w+/g, (word) => {
|
||||||
if (answers.some((answer) => answer.word.includes(word))) {
|
if (answers.some((answer) => answer.word.includes(word))) {
|
||||||
return '*'.repeat(word.length);
|
return '*'.repeat(word.length);
|
||||||
|
|||||||
@@ -58,15 +58,15 @@ function getBoard(letters, showLetters, context) {
|
|||||||
return config.platform === 'irc'
|
return config.platform === 'irc'
|
||||||
? letter
|
? letter
|
||||||
: style.grey(letter);
|
: style.grey(letter);
|
||||||
}).join(' ');
|
}).join(config.platform === 'irc' ? ' ' : ' '); // regular space vs em space
|
||||||
|
|
||||||
return `${prefix}${middle}${suffix} Letters: ${letterBoard}`; // eslint-disable-line no-irregular-whitespace
|
return `${prefix}${middle}${suffix}${wordle.mode === 'hard' ? ' (Hard)' : ''} Letters: ${letterBoard}`; // eslint-disable-line no-irregular-whitespace
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${prefix}${middle}${suffix}`;
|
return `${prefix}${middle}${suffix}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function start(length = settings.defaultLength, context) {
|
function start(length = settings.length, mode = settings.mode, context) {
|
||||||
const wordPool = words[length];
|
const wordPool = words[length];
|
||||||
|
|
||||||
if (length < settings.minLength) {
|
if (length < settings.minLength) {
|
||||||
@@ -85,15 +85,16 @@ function start(length = settings.defaultLength, context) {
|
|||||||
wordles.set(context.room.id, {
|
wordles.set(context.room.id, {
|
||||||
word: word.word.toUpperCase(),
|
word: word.word.toUpperCase(),
|
||||||
wordList,
|
wordList,
|
||||||
|
mode,
|
||||||
definitions: word.definitions,
|
definitions: word.definitions,
|
||||||
letters: new Map(alphabet.map((letter) => [letter, null])),
|
letters: new Map(alphabet.map((letter) => [letter, null])),
|
||||||
guesses: [],
|
guesses: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (config.platform === 'irc') {
|
if (config.platform === 'irc') {
|
||||||
context.sendMessage(`${getBoard(Array.from({ length }, () => null), false, context)} guess the word with ${config.prefix}w [word]! ${style.bgsilver(' X ')} not in word; ${style.bgyellow(` X${style.yellow('?')}`)} wrong position; ${style.bggreen(` X${style.green('*')}`)} correct position.`, context.room.id); // eslint-disable-line no-irregular-whitespace
|
context.sendMessage(`${getBoard(Array.from({ length }, () => null), false, context)}${mode === 'hard' ? ' (Hard)' : ''} guess the word with ${config.prefix}w [word]! ${style.bgsilver(' X ')} not in word; ${style.bgyellow(` X${style.yellow('?')}`)} wrong position; ${style.bggreen(` X${style.green('*')}`)} correct position.`, context.room.id); // eslint-disable-line no-irregular-whitespace
|
||||||
} else {
|
} else {
|
||||||
context.sendMessage(`${getBoard(Array.from({ length }, () => null), false, context)} guess the word with ${config.prefix}w [word]! ${style.grey(style.bold('X'))} not in word; ${style.orange(style.bold('X'))} wrong position; ${style.green(style.bold('X'))} correct position.`, context.room.id);
|
context.sendMessage(`${getBoard(Array.from({ length }, () => null), false, context)}${mode === 'hard' ? ' (Hard)' : ''} guess the word with ${config.prefix}w [word]! ${style.grey(style.bold('X'))} not in word; ${style.orange(style.bold('X'))} wrong position; ${style.green(style.bold('X'))} correct position.`, context.room.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.logger.info(`Wordle started: ${word.word.toUpperCase()}`);
|
context.logger.info(`Wordle started: ${word.word.toUpperCase()}`);
|
||||||
@@ -118,39 +119,82 @@ function play(guess, context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const upperGuess = guess.toUpperCase();
|
const upperGuess = guess.toUpperCase();
|
||||||
const processed = new Set();
|
const occurrences = wordle.word.split('').reduce((acc, letter) => acc.set(letter, (acc.get(letter) || 0) + 1), new Map());
|
||||||
|
|
||||||
const check = upperGuess.split('').map((letter, index) => {
|
const guessLetters = upperGuess.split('');
|
||||||
const alreadySeen = settings.highlightRepeat ? false : processed.has(letter);
|
const check = guessLetters.map((letter) => [letter, null]);
|
||||||
|
const prevGuess = wordle.guesses.at(-1)?.[1];
|
||||||
|
|
||||||
processed.add(letter);
|
if (wordle.mode === 'hard' && prevGuess) {
|
||||||
|
const prevLetters = prevGuess.split('');
|
||||||
|
|
||||||
|
const valid = prevLetters.every((letter, index) => {
|
||||||
|
if (wordle.letters.get(letter) === false && !guessLetters.includes(letter)) {
|
||||||
|
context.sendMessage(`(Hard) Your guess must include the letter ${config.platform === 'irc'
|
||||||
|
? style.bgyellow(` ${letter} `)
|
||||||
|
: `${style.grey(style.code('['))}${style.orange(style.bold(style.code(letter)))}${style.grey(style.code(']'))}`
|
||||||
|
}.`, context.room.id);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wordle.letters.get(letter) === true && letter === wordle.word[index] && letter !== guessLetters[index]) {
|
||||||
|
context.sendMessage(`(Hard) Your guess must include the letter ${config.platform === 'irc'
|
||||||
|
? style.bggreen(` ${letter} `)
|
||||||
|
: `${style.grey(style.code('['))}${style.green(style.bold(style.code(letter)))}${style.grey(style.code(']'))}`
|
||||||
|
} in the correct position.`, context.room.id);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// correct
|
||||||
|
guessLetters.forEach((letter, index) => {
|
||||||
if (wordle.word[index] === letter) {
|
if (wordle.word[index] === letter) {
|
||||||
wordle.letters.set(letter, true);
|
wordle.letters.set(letter, true);
|
||||||
return [letter, true];
|
check[index] = [letter, true];
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// wrong place
|
||||||
|
guessLetters.forEach((letter, index) => {
|
||||||
if (wordle.word.includes(letter)) {
|
if (wordle.word.includes(letter)) {
|
||||||
if (wordle.letters.get(letter) !== true) {
|
if (wordle.letters.get(letter) !== true) {
|
||||||
wordle.letters.set(letter, false);
|
wordle.letters.set(letter, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return [letter, alreadySeen ? null : false]; // repeating letter in the wrong place is not highlighted
|
const marks = check.filter(([checkLetter, status]) => checkLetter === letter && status !== null).length;
|
||||||
|
|
||||||
|
if (check[index][1] !== true && marks < occurrences.get(letter)) {
|
||||||
|
check[index] = [letter, false];
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wordle.letters.delete(letter);
|
wordle.letters.delete(letter);
|
||||||
|
|
||||||
return [letter, null];
|
|
||||||
});
|
});
|
||||||
|
|
||||||
wordle.guesses = wordle.guesses.concat([[context.user.username, upperGuess]]);
|
wordle.guesses = wordle.guesses.concat([[context.user.username, upperGuess]]);
|
||||||
|
|
||||||
if (upperGuess === wordle.word) {
|
if (upperGuess === wordle.word) {
|
||||||
const points = Math.max((wordle.word.length + 1) - wordle.guesses.length, 1);
|
const assignBonusPoints = wordle.wordList.length > config.wordle.bonusDictionaryThreshold;
|
||||||
|
const points = assignBonusPoints
|
||||||
|
? Math.max((wordle.word.length + 1) - wordle.guesses.length, 1)
|
||||||
|
: 1;
|
||||||
|
|
||||||
const definition = wordle.definitions[0] ? `: ${style.italic(`${wordle.definitions[0].slice(0, 100)}${wordle.definitions[0].length > 100 ? '...' : ''}`)}` : '';
|
const definition = wordle.definitions[0] ? `: ${style.italic(`${wordle.definitions[0].slice(0, 100)}${wordle.definitions[0].length > 100 ? '...' : ''}`)}` : '';
|
||||||
|
|
||||||
context.setPoints(context.user, points);
|
context.setPoints(context.user, points, { key: wordle.mode === 'hard' ? 'hardle' : 'wordle' });
|
||||||
context.sendMessage(`${getBoard(check, false, context)} is correct in ${wordle.guesses.length} guesses! ${style.bold(style.cyan(`${config.usernamePrefix}${context.user.username}`))} gets ${points} ${points > 1 ? 'points' : 'point'}. ${style.bold(wordle.word)}${definition}`, context.room.id);
|
|
||||||
|
context.sendMessage(`${getBoard(check, false, context)} is correct in ${wordle.guesses.length} guesses! ${style.bold(style.cyan(`${config.usernamePrefix}${context.user.username}`))} gets ${points} ${points > 1 ? 'points' : 'point'}${assignBonusPoints ? '. ' : ` (${wordle.word.length}-letter dictionary too small for bonus points). `}${style.bold(wordle.word)}${definition}`, context.room.id);
|
||||||
|
|
||||||
wordles.delete(context.room.id);
|
wordles.delete(context.room.id);
|
||||||
|
|
||||||
@@ -162,7 +206,10 @@ function play(guess, context) {
|
|||||||
|
|
||||||
function onCommand(args, context) {
|
function onCommand(args, context) {
|
||||||
const wordle = wordles.get(context.room.id);
|
const wordle = wordles.get(context.room.id);
|
||||||
const length = Number(args[0]) || settings.defaultLength;
|
const length = args.map((arg) => Number(arg)).find(Boolean) || settings.length;
|
||||||
|
const mode = args.find((arg) => arg === 'easy' || arg === 'hard')
|
||||||
|
|| (context.command === 'hardle' && 'hard')
|
||||||
|
|| settings.mode;
|
||||||
|
|
||||||
if (['guess', 'w'].includes(context.command)) {
|
if (['guess', 'w'].includes(context.command)) {
|
||||||
play(args[0], context);
|
play(args[0], context);
|
||||||
@@ -182,7 +229,7 @@ function onCommand(args, context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!wordle && context.room.id) {
|
if (!wordle && context.room.id) {
|
||||||
start(length, context);
|
start(length, mode, context);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,8 +238,8 @@ function onCommand(args, context) {
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'Wordle',
|
name: 'Wordle',
|
||||||
commands: ['wordle', 'guess', 'w'],
|
commands: ['wordle', 'hardle', 'lingo', 'guess', 'w'],
|
||||||
help: `Guess the ${settings.defaultLength}-letter word on the board. Submit a guess with ${config.prefix}w [word]. If the letter is green, it is in the correct place. If it is yellow, it is part of the word, but not in the correct place. The number of letters in the word is the highest score you can get. You lose 1 point per guess, down to 1 point.`,
|
help: `Guess the ${settings.length}-letter word on the board. Submit a guess with ${config.prefix}w [word]. If the letter is green, it is in the correct place. If it is yellow, it is part of the word, but not in the correct place. The number of letters in the word is the highest score you can get. You lose 1 point per guess, down to 1 point. Change the numbers of letters or switch to hard mode with ~wordle [length] [hard] or ~hardle [length].`,
|
||||||
onCommand,
|
onCommand,
|
||||||
// onMessage,
|
// onMessage,
|
||||||
};
|
};
|
||||||
|
|||||||
15
src/play.js
15
src/play.js
@@ -3,6 +3,7 @@
|
|||||||
const config = require('config');
|
const config = require('config');
|
||||||
const fs = require('fs').promises;
|
const fs = require('fs').promises;
|
||||||
const logger = require('simple-node-logger').createSimpleLogger();
|
const logger = require('simple-node-logger').createSimpleLogger();
|
||||||
|
const { getWeek } = require('date-fns');
|
||||||
const { argv } = require('yargs');
|
const { argv } = require('yargs');
|
||||||
// const timers = require('timers/promises');
|
// const timers = require('timers/promises');
|
||||||
|
|
||||||
@@ -15,14 +16,16 @@ const points = {};
|
|||||||
|
|
||||||
async function initPoints(identifier) {
|
async function initPoints(identifier) {
|
||||||
try {
|
try {
|
||||||
const pointsFile = await fs.readFile(`./points-${identifier}.json`, 'utf-8');
|
const pointsFile = await fs.readFile(`./points/points-${identifier}.json`, 'utf-8');
|
||||||
|
|
||||||
Object.assign(points, JSON.parse(pointsFile));
|
Object.assign(points, JSON.parse(pointsFile));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.code === 'ENOENT') {
|
if (error.code === 'ENOENT') {
|
||||||
logger.info('Creating new points file');
|
logger.info('Creating new points file');
|
||||||
|
|
||||||
await fs.writeFile(`./points-${identifier}.json`, '{}');
|
await fs.mkdir('./points', { recursive: true });
|
||||||
|
|
||||||
|
await fs.writeFile(`./points/points-${identifier}.json`, '{}');
|
||||||
await initPoints(identifier);
|
await initPoints(identifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -50,7 +53,8 @@ async function setPoints(identifier, defaultKey, user, value, { mode = 'add', ke
|
|||||||
points[gameKey][userKey] = value;
|
points[gameKey][userKey] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
await fs.writeFile(`./points-${identifier}.json`, JSON.stringify(points, null, 4));
|
await fs.writeFile(`./points/points-${identifier}_backup${getWeek(new Date())}.json`, JSON.stringify(points, null, 4)); // weekly back-up
|
||||||
|
await fs.writeFile(`./points/points-${identifier}.json`, JSON.stringify(points, null, 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPoints(game, rawUsername, { user, room, command }) {
|
function getPoints(game, rawUsername, { user, room, command }) {
|
||||||
@@ -117,6 +121,11 @@ async function getGames(bot, identifier) {
|
|||||||
const sendMessage = (body, roomId, options, recipient) => {
|
const sendMessage = (body, roomId, options, recipient) => {
|
||||||
const curatedBody = curateMessageBody(body, game, key, options);
|
const curatedBody = curateMessageBody(body, game, key, options);
|
||||||
|
|
||||||
|
if (!roomId && !recipient) {
|
||||||
|
logger.error(`Missing room ID or recipient for message: ${body}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (config.platform === 'irc') {
|
if (config.platform === 'irc') {
|
||||||
bot.client.say(/^#/.test(roomId) ? roomId : recipient, curatedBody);
|
bot.client.say(/^#/.test(roomId) ? roomId : recipient, curatedBody);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,6 +130,8 @@ function handleError(error, socket, domain, data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const pongRegex = /^pong:\d+$/;
|
||||||
|
|
||||||
async function connect(bot, games) {
|
async function connect(bot, games) {
|
||||||
const socket = {
|
const socket = {
|
||||||
ws: { readyState: 0 },
|
ws: { readyState: 0 },
|
||||||
@@ -154,7 +156,7 @@ async function connect(bot, games) {
|
|||||||
socket.ws.on('message', async (msgData) => {
|
socket.ws.on('message', async (msgData) => {
|
||||||
const msg = msgData.toString();
|
const msg = msgData.toString();
|
||||||
|
|
||||||
if (typeof msg === 'string' && msg.includes('pong')) {
|
if (typeof msg === 'string' && pongRegex.test(msg)) {
|
||||||
logger.debug(`Received pong ${msg.split(':')[1]}`);
|
logger.debug(`Received pong ${msg.split(':')[1]}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user