From 331df173184cb8218e64c2392bbd5d7f5a2e0da9 Mon Sep 17 00:00:00 2001 From: Hepller Date: Wed, 8 Sep 2021 23:13:31 +0300 Subject: [PATCH] v0.7.0 --- bot.js | 58 +++++++++++++++++++++ config.json | 6 +++ config.yml | 31 ------------ core/core.js | 134 ------------------------------------------------- core/logger.js | 51 ------------------- data.json | 4 +- package.json | 15 ++---- readme.md | 37 ++++++++++++-- 8 files changed, 104 insertions(+), 232 deletions(-) create mode 100644 bot.js create mode 100644 config.json delete mode 100644 config.yml delete mode 100644 core/core.js delete mode 100644 core/logger.js diff --git a/bot.js b/bot.js new file mode 100644 index 0000000..a0a0f47 --- /dev/null +++ b/bot.js @@ -0,0 +1,58 @@ +/** __ __ __ ___ ___ + * / ' / \ |__) | |__ \_/ + * \__. \__/ | \ | |___ / \ + * + * @copyright © 2021 hepller + */ + +// Импорт модулей и функций +const {VK} = require('vk-io') +const Markov = require('markov-generator') + +// Конфиг, паттерн и файл проекта +const config = require('./config') +const data = require(`./data`) +const project = require('./package') + +/** VK API */ +const vk = new VK({token: config.token, v: 5.131, apiLimit: 1}) + +// Префиксы для логирования +const succes_prefix = '\u001B[32m>\u001B[0m' +const warn_prefix = '\u001B[33m>\u001B[0m' +const error_prefix = '\u001B[31m>\u001B[0m' + +// Сообщения при запуске +console.log(succes_prefix, `Cortex Bot v${project.version}`) +console.log(succes_prefix, 'VK API connection ...') + +// Запуск обработчика событий ВК +vk.updates.startPolling().then(() => console.log(succes_prefix, 'Successfully connected')) + +// Обработчик сообщений ВК +vk.updates.on('message_new', async ctx => { + + // Игнорирование лишних сообщений + if (!ctx.isChat || ctx.isOutbox || ctx.isGroup) return + + // Генерация сообщения с определенным шансом + if (Math.random() * 100 < config.chance) { + + // Статус набора текста + ctx.setActivity() + + /** Сгенерированный текст */ + const sentence = new Markov({input: data, minLenght: config.min_words}).makeChain() + + // Предупреждение при превышении лимита символов + if (sentence.split('').length > config.max_symbols) return console.warn(warn_prefix, `#${ctx.chatId} Symbols limit exceeded (${sentence.split('').length}/${config.max_symbols})`) + + // Отправка сообщения + ctx.send(sentence) + .then(() => console.log(succes_prefix, `#${ctx.chatId} Text generated`)) + } +}) + +// Обработка возможных ошибок +process.on('uncaughtException', error => console.error(error_prefix, `Error: ${error.message}`)) +process.on('unhandledRejection', error => console.error(error_prefix, `Error: ${error.message}`)) \ No newline at end of file diff --git a/config.json b/config.json new file mode 100644 index 0000000..a7295f3 --- /dev/null +++ b/config.json @@ -0,0 +1,6 @@ +{ + "token": "TOKEN", + "chance": 10, + "min_words": 2, + "max_symbols": 250 +} \ No newline at end of file diff --git a/config.yml b/config.yml deleted file mode 100644 index bb4c636..0000000 --- a/config.yml +++ /dev/null @@ -1,31 +0,0 @@ -# __ __ __ ___ ___ -# / ' / \ |__) | |__ \_/ -# \__. \__/ | \ | |___ / \ - -# VK API -vk_api: - # Токен - token: TOKEN - -# Основное -general: - # Шанс генерации сообщения - chance: 20 - # Минимальное кол-во слов в тексте - min_words: 5 - # Максимальное кол-во символов в тексте - max_symbols: 250 - # ID бесед, в которых бот активен - active_chats: all - # Сохранение сообщений пользователей - # * Одинаковые строки не сохраняются - data_save: true - -# Формат текста -format: - # Строчные буквы - to_lower_case: true - # Заглавная буква в начале - capitalize_word: true - # Точка в конце - end_dot: true \ No newline at end of file diff --git a/core/core.js b/core/core.js deleted file mode 100644 index f6a877b..0000000 --- a/core/core.js +++ /dev/null @@ -1,134 +0,0 @@ -/** __ __ __ ___ ___ - * / ' / \ |__) | |__ \_/ - * \__. \__/ | \ | |___ / \ - * - * @copyright © 2021 hepller - */ - -// Импорт модулей -import {VK} from 'vk-io' -import YAML from 'yaml' -import Markov from 'markov-generator' -import fs from 'fs' -import Logger from './logger.js' - -/** Конфиг */ -let config = YAML.parse(fs.readFileSync('config.yml', 'utf8')) - -// БД и файл проекта -const db = JSON.parse(fs.readFileSync('data.json', 'utf8')) -const project = JSON.parse(fs.readFileSync('package.json', 'utf8')) - -/** VK API */ -const vk = new VK({token: config.vk_api.token, v: 5.130, apiLimit: 1}) - -/** - * Сохраняет БД - * @param {object} data БД - */ -db.write = (data) => { - fs.writeFileSync('data.json', JSON.stringify(data, null, '\t')) -} - -/** - * Получает объект чата из БД - * @param {number} id ID чата - */ -db.getChat = (id) => { - - // Поиск чата по ID - let chat = db.chats.find(chat => chat.id == id) - - // Создание нового объекта чата при отсутствии - if (!chat) { - - // Добавление в БД - db.chats.push({id: id, data: []}) - - // Запись БД - db.write(db) - - // Получение из БД - chat = db.chats.find(chat => chat.id == id) - } - - // Возвращение объекта чата - return chat -} - -// Сообщения при запуске -Logger.info(`Cortex Bot v${project.version}`) -Logger.info('Подключение к VK API ...') - -// Перезагрузка конфигурации при её изменении -fs.watchFile('config.yml', async () => { - - // Парсинг - config = YAML.parse(fs.readFileSync('config.yml', 'utf8')) - - // Запись в лог - Logger.info('Конфигурация перезагружена') -}) - -// Старт получения обновлений ВК -vk.updates.startPolling().then(() => Logger.info('VK API подключено')) - -// Обработчик сообщений ВК -vk.updates.on('message_new', async ctx => { - - // Игнорирование лишних сообщений - if (!ctx.isChat) return - if (config.general.active_chats != 'all' && !config.general.active_chats.includes(ctx.chatId)) return - - // Логирование сообщений - Logger.info(`#${ctx.chatId} ${ctx.senderId} ${ctx.isOutbox ? '<-' : '->'} ${ctx?.text ? ctx.text : ''} ${ctx?.attachments}`) - - // Завершение функции, если сообщение исходящее или от сообщества - if (ctx.isOutbox || ctx.isGroup) return - - // Объект пользователя - ctx.chat = await db.getChat(ctx.chatId) - - // Запись сообщения в БД - if (ctx.text && config.general.data_save && !ctx.chat.data.includes(ctx.text)) { - - // Запись в БД - ctx.chat.data.push(ctx.text) - - // Сохранение БД - db.write(db) - } - - // Генерация сообщения с определенным шансом - if (Math.random() * 100 < config.general.chance) { - - // Сообщение в консоль о генерации текста - Logger.info('Генерация текста ...') - - // Генерация текста - // Если данных будет недостаточно произойдет ошибка <> - let sentence = new Markov({input: ctx.chat.data, minLenght: config.general.min_words}).makeChain() - - // Форматирование текста - if (config.format.to_lower_case) sentence = sentence.toLowerCase() - if (config.format.capitalize_word) sentence = sentence.charAt(0).toUpperCase() + sentence.slice(1) - if (config.format.end_dot) sentence = sentence + '.' - - // Предупреждение при превышении лимита символов - if (sentence.split('').length > config.general.max_symbols) return Logger.warn(`#${ctx.chatId} Превышен лимит символов (${sentence.split('').length}/${config.general.max_symbols})`) - - // Статус набора текста - await ctx.setActivity() - - // Задержка перед отправкой сообщений - // Высчитывается на основе количества символов в тексте для имитации написания - await new Promise(resolve => setTimeout(resolve, sentence.split('').length * 2 + '00')) - - // Отправка сообщения - ctx.send(sentence) - } -}) - -// Обработчики ошибок -process.on('uncaughtException', error => Logger.error(error)) -process.on('unhandledRejection', error => Logger.error(error)) \ No newline at end of file diff --git a/core/logger.js b/core/logger.js deleted file mode 100644 index 1a7fada..0000000 --- a/core/logger.js +++ /dev/null @@ -1,51 +0,0 @@ -/** __ __ __ ___ ___ - * / ' / \ |__) | |__ \_/ - * \__. \__/ | \ | |___ / \ - * - * @copyright © 2021 hepller - */ - -/** Получает текущее время */ -const getTimeString = () => { - - // Переменные - let hours = new Date().getHours() - let minutes = new Date().getMinutes() - let seconds = new Date().getSeconds() - - // Исправление одинарных символов - if (hours < 10) hours = `0${hours}` - if (minutes < 10) minutes = `0${minutes}` - if (seconds < 10) seconds = `0${seconds}` - - // Возвращение строки - return `${hours}:${minutes}:${seconds}` -} - -/** Логер */ -export default class Logger { - - /** - * Выводит в лог информацию - * @param {string} text - Текст сообщения - */ - static info(text) { - console.log(`${getTimeString()} INFO - ${text}`) - } - - /** - * Выводит в лог предупреждения - * @param {string} text - Текст предупреждения - */ - static warn(text) { - console.log(`\u001B[33m${getTimeString()} WARN - ${text}\u001B[0m`) - } - - /** - * Выводит в лог ошибки - * @param {string} text - Текст ошибки - */ - static error(text) { - console.log(`\u001B[31m${getTimeString()} ERRO - ${text}\u001B[0m`) - } -} \ No newline at end of file diff --git a/data.json b/data.json index 2555953..0637a08 100644 --- a/data.json +++ b/data.json @@ -1,3 +1 @@ -{ - "chats": [] -} \ No newline at end of file +[] \ No newline at end of file diff --git a/package.json b/package.json index 0edbc56..7bfe7e6 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,8 @@ { "name": "cortex-bot", - "version": "0.6.5", - "description": "vk delirium generator bot", - "main": "core/core.js", - "type": "module", - "scripts": { - "start": "node ." - }, + "version": "0.7.0", + "description": "vk text generator bot", + "main": "bot.js", "repository": { "type": "git", "url": "git+https://github.com/hepller/cortex-bot.git" @@ -15,7 +11,7 @@ "vk", "bot", "markov", - "delirium", + "messages", "generator" ], "author": "hepller", @@ -26,7 +22,6 @@ "homepage": "https://github.com/hepller/cortex-bot#readme", "dependencies": { "markov-generator": "^1.2.3", - "vk-io": "^4.3.0", - "yaml": "^1.10.2" + "vk-io": "^4.4.0" } } diff --git a/readme.md b/readme.md index b0990de..038b387 100644 --- a/readme.md +++ b/readme.md @@ -1,12 +1,43 @@ # Cortex Bot -Бот ВКонтакте для генерации случайных сообщений на основе цепей Маркова +Бот ВКонтакте для генерации сообщений с помощью цепей Маркова --- -## Важная информация +## Конфигурация -При недостатке данных для генерации может возникать ошибка `Maximum call stack size exceeded` +```json +{ + "token": "TOKEN", // Токен доступа VK API + "chance": 10, // Шанс генерации сообщения + "min_words": 2, // Минимальное кол-во слов в сгенерированном сообщении + "max_symbols": 200, // Максимальное кол-во символов в сообщении +} +``` + +--- + +## Данные + +Перед началом использования загрузите свой датасет с достаточным объемом текста в файл `data.json` + +**Пример небольшого датасета:** + +```json +[ + "Я вот подумал. Если быстро заморозить человека, то в какой момент он умрет?", + "есть еще три:\n\nгносеоногия (эпистемология) - о познании", + "логика - о мышлении (из нее как ы слеуют большинство наук естественных и абстрактных (базируются на логических законах)", + "ну вот тут открытый же вопрос. С т.з. медицины: есть критерии естественной смерти, которые гуглятся", + "а с т.з. онтологии - тут может готового ответа и не быть. В этом как бы и отличие - очень часто нет готовых и четких ответов", + "ну, например, когда между нейронами сигналы перестанут бегать", + "Читаю, но как бы там все неолнозначно", + "клеточная смерть - не очень катит, т.к. те же волосы и ногти долго еще растут", + "Пульса нету, сердечной активности нету" +] +``` + +_При недостатке данных для генерации может возникать ошибка `Maximum call stack size exceeded`_ ---