2022-01-31 13:50:48 +01:00
|
|
|
import path from 'path'
|
|
|
|
import Game from './game.js'
|
|
|
|
import emoji from 'node-emoji'
|
|
|
|
import logTimestamp from 'log-timestamp'
|
|
|
|
import commander from 'bot-commander'
|
|
|
|
import showdown from 'showdown'
|
|
|
|
import uniqueRandomArray from 'unique-random-array'
|
|
|
|
import words from './assets/words.js'
|
|
|
|
|
|
|
|
import {
|
2022-01-31 15:06:48 +01:00
|
|
|
fileURLToPath
|
2022-01-31 13:50:48 +01:00
|
|
|
} from 'url'
|
|
|
|
|
|
|
|
import {
|
2022-01-31 15:06:48 +01:00
|
|
|
MatrixClient,
|
|
|
|
MatrixAuth,
|
|
|
|
SimpleFsStorageProvider,
|
|
|
|
RustSdkCryptoStorageProvider,
|
|
|
|
AutojoinRoomsMixin
|
2022-01-31 13:50:48 +01:00
|
|
|
} from 'matrix-bot-sdk'
|
|
|
|
|
|
|
|
const converter = new showdown.Converter()
|
|
|
|
const __filename = fileURLToPath(import.meta.url)
|
|
|
|
const __dirname = path.dirname(__filename)
|
|
|
|
|
|
|
|
const datasPath = process.env.MATRIX_DATA ?? (__dirname + '/datas')
|
|
|
|
const storage = new SimpleFsStorageProvider(datasPath + '/bot.json')
|
|
|
|
const cryptoProvider = new RustSdkCryptoStorageProvider(datasPath + '/crypto')
|
|
|
|
|
|
|
|
const url = process.env.MATRIX_URL
|
|
|
|
const username = process.env.MATRIX_USERNAME
|
|
|
|
const password = process.env.MATRIX_PASSWORD
|
|
|
|
|
|
|
|
const auth = new MatrixAuth(url)
|
|
|
|
const authClient = await auth.passwordLogin(username, password)
|
|
|
|
const token = authClient.accessToken
|
|
|
|
|
|
|
|
const client = new MatrixClient(url, token, storage, cryptoProvider)
|
|
|
|
|
|
|
|
const games = []
|
|
|
|
const randomWord = uniqueRandomArray(words);
|
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
const sendMessage = async (room, text) => {
|
|
|
|
client.sendMessage(room, {
|
|
|
|
'msgtype': 'm.text',
|
|
|
|
'format': 'org.matrix.custom.html',
|
|
|
|
'body': text,
|
|
|
|
'formatted_body': converter.makeHtml(text),
|
|
|
|
});
|
2022-01-31 13:50:48 +01:00
|
|
|
}
|
|
|
|
|
2022-02-01 16:54:52 +01:00
|
|
|
const renderMatrix = (game, options) => {
|
2022-01-31 15:06:48 +01:00
|
|
|
const chars = {
|
|
|
|
0: ':large_blue_square:',
|
|
|
|
1: ':large_blue_square:',
|
|
|
|
2: ':large_yellow_circle:',
|
|
|
|
3: ':large_red_square:',
|
|
|
|
}
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-02-01 16:54:52 +01:00
|
|
|
options = options ?? {}
|
|
|
|
options.onlySigns = options.onlySigns ?? false
|
|
|
|
options.hideNotPlayedLines = options.hideNotPlayedLines ?? false
|
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
let render = '<table>'
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
for (let row of game.matrix()) {
|
|
|
|
const letters = (row.word ?? '.'.repeat(game.expectedWord.length)).split('')
|
2022-02-01 16:54:52 +01:00
|
|
|
|
|
|
|
if (options.hideNotPlayedLines && !row.word) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
let signs = []
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
for (let index in row.result) {
|
|
|
|
signs.push(chars[row.result[index]])
|
|
|
|
}
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-02-01 16:54:52 +01:00
|
|
|
const elements = options.onlySigns ? {signs} : {letters, signs}
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-02-01 16:54:52 +01:00
|
|
|
for (let key in elements) {
|
2022-01-31 15:06:48 +01:00
|
|
|
render += '<tr>'
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-02-01 16:54:52 +01:00
|
|
|
for (let item of elements[key]) {
|
2022-01-31 15:06:48 +01:00
|
|
|
render += `<td>${item}</td>`
|
|
|
|
}
|
|
|
|
|
|
|
|
render += '</tr>'
|
2022-01-31 13:50:48 +01:00
|
|
|
}
|
2022-01-31 15:06:48 +01:00
|
|
|
}
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
render + '</table>'
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
const markdown = emoji.emojify(render)
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
return markdown
|
2022-01-31 13:50:48 +01:00
|
|
|
}
|
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
const startGame = async (meta) => {
|
|
|
|
const word = randomWord()
|
|
|
|
games[meta.room] = new Game(word, words)
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
await sendMessage(meta.room, 'Le mot commence par la lettre `' + word.substr(0, 1) + '`')
|
|
|
|
await sendMessage(meta.room, renderMatrix(games[meta.room]))
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
console.log(`${meta.sender} on room ${meta.room} starts the game (${word})`)
|
2022-01-31 13:50:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
commander
|
2022-01-31 15:06:48 +01:00
|
|
|
.command('help')
|
|
|
|
.description('`help` : affiche l\'aide')
|
|
|
|
.action(async (meta) => {
|
|
|
|
let message = []
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
for (let command of commander.commands) {
|
|
|
|
message.push('* ' + command._description)
|
|
|
|
}
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
const text = message.join("\n")
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
sendMessage(meta.room, text);
|
|
|
|
})
|
2022-01-31 13:50:48 +01:00
|
|
|
|
|
|
|
commander
|
2022-01-31 15:06:48 +01:00
|
|
|
.command('start')
|
|
|
|
.description('`start` : démarrer une partie')
|
|
|
|
.action(async (meta) => {
|
|
|
|
if (games.hasOwnProperty(meta.room)) {
|
|
|
|
const currentGame = games[meta.room]
|
|
|
|
|
|
|
|
if (!currentGame.isFinish()) {
|
|
|
|
for (let item of [
|
|
|
|
'Il y a une partie en cours !',
|
|
|
|
'Le mot commence par la lettre `' + currentGame.expectedWord.substr(0, 1) + '`',
|
|
|
|
renderMatrix(currentGame),
|
|
|
|
]) {
|
|
|
|
await sendMessage(meta.room, item)
|
2022-01-31 13:50:48 +01:00
|
|
|
}
|
2022-01-31 15:06:48 +01:00
|
|
|
}
|
|
|
|
}
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
startGame(meta)
|
|
|
|
})
|
2022-01-31 13:50:48 +01:00
|
|
|
|
|
|
|
commander
|
2022-01-31 15:06:48 +01:00
|
|
|
.command('restart')
|
|
|
|
.description('`restart` : démarrer une nouvelle partie')
|
|
|
|
.action(async (meta) => {
|
|
|
|
startGame(meta)
|
|
|
|
})
|
2022-01-31 13:50:48 +01:00
|
|
|
|
|
|
|
commander
|
2022-01-31 15:06:48 +01:00
|
|
|
.command('test [word]')
|
|
|
|
.description('`test mot` : tester le mot `mot`')
|
|
|
|
.action(async (meta, word) => {
|
|
|
|
if (!games.hasOwnProperty(meta.room)) {
|
|
|
|
return await sendMessage(
|
|
|
|
meta.room,
|
|
|
|
'Il n\'y pas de partie en cours. Taper `start` pour en lancer une.'
|
|
|
|
)
|
|
|
|
}
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
const currentGame = games[meta.room]
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
if (currentGame.isFinish()) {
|
|
|
|
return await sendMessage(
|
|
|
|
meta.room,
|
|
|
|
'La partie est terminée. Taper `restart` pour en lancer une nouvelle.'
|
|
|
|
)
|
|
|
|
}
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
if (!currentGame.tryWord(word)) {
|
|
|
|
return await sendMessage(
|
|
|
|
meta.room,
|
|
|
|
'Le mot de ne fait pas la bonne longueur ou n\'apparait pas dans le dictionnaire.'
|
|
|
|
)
|
|
|
|
}
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
if (currentGame.isWon()) {
|
2022-02-01 16:54:52 +01:00
|
|
|
await sendMessage(meta.room, 'Bravo ! Tu as découvert le mot !')
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-02-01 16:54:52 +01:00
|
|
|
return await sendMessage(meta.room, renderMatrix(currentGame, {
|
|
|
|
onlySigns: true,
|
|
|
|
hideNotPlayedLines: true,
|
|
|
|
}))
|
2022-01-31 15:06:48 +01:00
|
|
|
}
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
if (currentGame.isFinish()) {
|
|
|
|
const expectedWord = currentGame.expectedWord
|
|
|
|
|
|
|
|
await sendMessage(
|
|
|
|
meta.room,
|
|
|
|
`Tes propositions sont épuisées… Le mot a deviner était \`${expectedWord}\``
|
|
|
|
)
|
2022-02-01 16:54:52 +01:00
|
|
|
|
|
|
|
return await sendMessage(meta.room, renderMatrix(currentGame, {
|
|
|
|
onlySigns: true,
|
|
|
|
hideNotPlayedLines: true,
|
|
|
|
}))
|
2022-01-31 15:06:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
await sendMessage(meta.room, renderMatrix(currentGame))
|
|
|
|
})
|
2022-01-31 13:50:48 +01:00
|
|
|
|
|
|
|
AutojoinRoomsMixin.setupOnClient(client)
|
|
|
|
|
|
|
|
client
|
2022-01-31 15:06:48 +01:00
|
|
|
.start()
|
|
|
|
.then(() => console.log('Client started'))
|
|
|
|
.catch(() => {
|
|
|
|
console.error('An error occurred')
|
|
|
|
})
|
2022-01-31 13:50:48 +01:00
|
|
|
|
|
|
|
client.on('room.message', (roomId, event) => {
|
2022-01-31 15:06:48 +01:00
|
|
|
if (!event['content']) {
|
|
|
|
return
|
|
|
|
}
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
const meta = {
|
|
|
|
sender: event['sender'],
|
|
|
|
body: event['content']['body'],
|
|
|
|
room: roomId,
|
|
|
|
}
|
2022-01-31 13:50:48 +01:00
|
|
|
|
2022-01-31 15:06:48 +01:00
|
|
|
commander.parse(meta.body.toLowerCase(), meta)
|
2022-01-31 13:50:48 +01:00
|
|
|
})
|