From 1ab6746d9a74b6255cacce834b2dbec73328ecf9 Mon Sep 17 00:00:00 2001 From: ale Date: Sun, 29 Sep 2024 02:52:17 +0200 Subject: [PATCH] initial commit --- .gitignore | 1 + README.md | 17 ++++++++++ config.js | 5 +++ index.js | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 27 ++++++++++++++++ 5 files changed, 137 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 config.js create mode 100644 index.js create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..7578114 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# Chess Bot for Mastodon + +## Install + + npm i or yarn + +## Config + + edit config.js + +## Run + + npm start + +## License + + MIT \ No newline at end of file diff --git a/config.js b/config.js new file mode 100644 index 0000000..4c17a9b --- /dev/null +++ b/config.js @@ -0,0 +1,5 @@ +module.exports = { + nick: 'chessbot', + accessToken: '', + url: 'mastodon.manalejandro.com' +} \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..e5f74ba --- /dev/null +++ b/index.js @@ -0,0 +1,87 @@ +const { createRestAPIClient, createStreamingAPIClient } = require('masto'), + jsChessEngine = require('js-chess-engine'), + ChessImageGenerator = require('chess-image-generator'), + config = require('./config.js'), + fs = require('fs'); + +(async () => { + const nick = config.nick, + rest = createRestAPIClient({ + url: `https://${config.url}`, + accessToken: config.accessToken, + requestInit: { + headers: [ + ['User-Agent', nick] + ] + } + }), + ws = createStreamingAPIClient({ + streamingApiUrl: `wss://${config.url}`, + accessToken: config.accessToken, + retry: true + }), + sendMessage = async (game, aimove, status, msg) => { + const imageGenerator = new ChessImageGenerator({ + size: 720, + light: 'rgb(200, 200, 200)', + dark: '#333333', + style: 'merida' + }) + await imageGenerator.loadFEN(game.exportFEN()) + const buf = await imageGenerator.generateBuffer(), + statusImage = await rest.v2.media.create({ + file: new Blob([buf], { type: 'image/png' }), + skipPolling: true, + description: aimove ? `Chessbot move ${Object.keys(aimove)[0]} to ${Object.values(aimove)[0]}` : 'Chessbot' + }) + let canmove + if (aimove) { + moves = game.moves() + canmove = Object.keys(moves).map(key => `move ${key} to ${moves[key].join(', ')}`) + } + await rest.v1.statuses.create({ + status: `${msg}${aimove ? '\nMovimientos posibles:\n' + canmove.join('\n') : ''}`, + mediaIds: [statusImage.id], + visibility: 'public', + inReplyToId: status?.id, + language: status?.language + }) + } + let game + if (fs.existsSync('game.txt')) { + game = new jsChessEngine.Game(JSON.parse(fs.readFileSync('game.txt').toString())) + sendMessage(game, null, null, `Partida en juego. Su turno.`) + } + for await (const notification of ws.user.notification.subscribe()) { + if (notification.payload['type'] === 'mention' && notification.payload['status']) { + const status = notification.payload['status'] + if (status && status.visibility !== 'direct' && status.account.acct !== nick && status.content.trim() !== '') { + const content = ('' + status.content).replace(/<[^>]*>?/gm, '').split(' ').filter(token => !token.startsWith('@')) + if (!game || game?.status?.isFinished) { + game = new jsChessEngine.Game() + sendMessage(game, status, 'Una partidita de ajedrez profesor Falken?') + } + else if (content.length > 1 + && content[0] === 'move' + && content[1].match(/^[A-H]{1}[1-8]{1}$/) + && content[2].match(/^[A-H]{1}[1-8]{1}$/)) { + game.move(content[1], content[2]) + const d = Date.now(), + levelIA = Math.floor(Math.random() * 5), + aimove = game.aiMove(levelIA), + time = Date.now() - d + if (game?.status && game?.status?.checkMate) { + await sendMessage(game, aimove, status, 'Jaque.') + } else { + await sendMessage(game, aimove, status, `Su turno, movimiento IA ${Object.keys(aimove)[0]} a ${Object.values(aimove)[0]} nivel ${levelIA + 1} en ${time / 1000}s`) + } + } + if (game?.status?.isFinished) { + fs.rmSync('game.txt') + } else { + fs.writeFileSync('game.txt', JSON.stringify(game.exportJson())) + } + } + } + } +})() \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..918b83f --- /dev/null +++ b/package.json @@ -0,0 +1,27 @@ +{ + "name": "chessbot-mastodon", + "version": "1.0.0", + "description": "Chess Bot for mastodon", + "main": "index.js", + "private": true, + "scripts": { + "start": "node index.js" + }, + "repository": { + "type": "git", + "url": "https://git.manalejandro.com/ale/chessbot-mastodon" + }, + "keywords": [ + "bot", + "activity", + "mastodon", + "chess" + ], + "author": "ale", + "license": "MIT", + "dependencies": { + "chess-image-generator": "^1.0.9", + "js-chess-engine": "^1.0.2", + "masto": "^6.8.0" + } +}