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 { fileURLToPath } from 'url' import { MatrixClient, MatrixAuth, SimpleFsStorageProvider, RustSdkCryptoStorageProvider, AutojoinRoomsMixin } 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); const sendMessage = (room, text) => { client.sendMessage(room, { 'msgtype': 'm.text', 'format': 'org.matrix.custom.html', 'body': text, 'formatted_body': converter.makeHtml(text), }); } const renderMatrix = (game) => { const chars = { 0: ':large_blue_square:', 1: ':large_blue_square:', 2: ':large_yellow_circle:', 3: ':large_red_square:', } let render = '' for (let row of game.matrix()) { const letters = (row.word ?? '.'.repeat(game.expectedWord.length)).split('') let signs = [] for (let index in row.result) { signs.push(chars[row.result[index]]) } for (let element of [letters, signs]) { render += '' for (let item of element) { render += `` } render += '' } } render + '
${item}
' const markdown = emoji.emojify(render) return markdown } const startGame = (meta) => { const word = randomWord() games[meta.room] = new Game(word, words) sendMessage(meta.room, 'Le mot commence par la lettre `' + word.substr(0, 1) + '`') sendMessage(meta.room, renderMatrix(games[meta.room])) console.log(`${meta.sender} on room ${meta.room} starts the game (${word})`) } commander .command('help') .description('`help` : affiche l\'aide') .action((meta) => { let message = [] for (let command of commander.commands) { message.push('* ' + command._description) } const text = message.join("\n") sendMessage(meta.room, text); }) commander .command('start') .description('`start` : démarrer une partie') .action((meta) => { if (games.hasOwnProperty(meta.room)) { if (!games[meta.room].isFinish()) { sendMessage(meta.room, 'Il y a une partie en cours !') sendMessage(meta.room, 'Le mot commence par la lettre `' + games[meta.room].expectedWord.substr(0, 1) + '`') return sendMessage(meta.room, renderMatrix(games[meta.room])) } } startGame(meta) }) commander .command('restart') .description('`restart` : démarrer une nouvelle partie') .action((meta) => { startGame(meta) }) commander .command('test [word]') .description('`test mot` : tester le mot `mot`') .action((meta, word) => { if (games.hasOwnProperty(meta.room)) { if (games[meta.room].isFinish()) { return sendMessage(meta.room, 'La partie est terminée. Taper `restart` pour en lancer une nouvelle.') } } else { return sendMessage(meta.room, 'Il n\'y pas de partie en cours. Taper `help` pour afficher l\'aide.') } const state = games[meta.room].tryWord(word) if (!state) { return sendMessage(meta.room, 'Le mot de ne fait pas la bonne longueur ou n\'apparait pas dans le dictionnaire.') } if (games[meta.room].isWon()) { return sendMessage(meta.room, 'Bravo ! Tu as découvert le mot !') } if (games[meta.room].isFinish()) { const expectedWord = games[meta.room].expectedWord sendMessage(meta.room, `Tes propositions sont épuisées… Le mot a deviner était \`${expectedWord}\``) } sendMessage(meta.room, renderMatrix(games[meta.room])) }) AutojoinRoomsMixin.setupOnClient(client) client .start() .then(() => console.log('Client started')) .catch(() => { console.error('An error occurred') }) client.on('room.message', (roomId, event) => { if (!event['content']) { return } const meta = { sender: event['sender'], body: event['content']['body'], room: roomId, } commander.parse(meta.body.toLowerCase(), meta) })