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'
2022-02-01 17:05:42 +01:00
import allWords from './assets/all_words.js'
2022-01-31 13:50:48 +01:00
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 = [ ]
2022-02-02 17:00:24 +01:00
const randomSeeds = uniqueRandomArray ( words . seeds ) ;
2022-01-31 13:50:48 +01:00
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-02-02 17:00:24 +01:00
const startGame = async ( meta , seed ) => {
let data
2022-01-31 13:50:48 +01:00
2022-02-02 17:00:24 +01:00
if ( seed ) {
const index = words . seeds . indexOf ( seed )
if ( index === - 1 ) {
return await sendMessage ( meta . room , 'Désolé mais cette seed n\'existe pas.' )
}
data = words . datas [ index ]
} else {
seed = randomSeeds ( )
data = words . datas [ words . seeds . indexOf ( seed ) ]
}
2022-02-02 17:06:29 +01:00
games [ meta . room ] = new Game ( data , allWords )
2022-02-02 17:00:24 +01:00
2022-02-02 17:07:39 +01:00
const firstLetter = data . substr ( 0 , 1 )
const size = data . length
2022-02-02 17:00:24 +01:00
2022-02-03 10:47:38 +01:00
await sendMessage ( meta . room , ` Le mot commence par la lettre \` ${ firstLetter } \` et contient ${ size } lettres. Vous pouvez partager cette grille avec sa seed : \` ${ seed } \` . ` )
2022-01-31 15:06:48 +01:00
await sendMessage ( meta . room , renderMatrix ( games [ meta . room ] ) )
2022-01-31 13:50:48 +01:00
2022-02-02 17:07:39 +01:00
console . log ( ` ${ meta . sender } on room ${ meta . room } starts the game ( ${ data } ) ` )
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-02-02 17:00:24 +01:00
. command ( 'start [seed]' )
. description ( '`start` ou `start seed` : démarrer une partie avec éventuellement la seed d\'une grille' )
. action ( async ( meta , seed ) => {
2022-01-31 15:06:48 +01:00
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-02-02 17:00:24 +01:00
return
2022-01-31 15:06:48 +01:00
}
}
2022-01-31 13:50:48 +01:00
2022-02-02 17:00:24 +01:00
startGame ( meta , seed )
2022-01-31 15:06:48 +01:00
} )
2022-01-31 13:50:48 +01:00
commander
2022-02-02 17:00:24 +01:00
. command ( 'restart [seed]' )
. description ( '`restart` ou `restart seed` : démarrer une nouvelle partie avec éventuellement la seed d\'une grille' )
. action ( async ( meta , seed ) => {
startGame ( meta , seed )
2022-01-31 15:06:48 +01:00
} )
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 ,
2022-02-03 10:47:38 +01:00
'Il n\'y a pas de partie en cours. Taper `start` pour en lancer une.'
2022-01-31 15:06:48 +01:00
)
}
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
} )