Заработало.
Короче, не без помощи chatGPT я во всём разобрался и теперь по порядку.
JavaScript:
let task = ''
let times = ''
bot.setMyCommands([
{command: '/add_task', description: 'Добавить задачу' }
])
bot.onText(/\/start/, msg => {
const chatId = msg.chat.id
bot.sendMessage(chatId, 'Добро пожаловать! \n\n Данный бот поможет вам в организации дня')
bot.onText(/\/add_task/, (msg) => {
const chatId = msg.chat.id
bot.sendMessage(chatId, 'Введите задачу')
bot.onText(/(.+)/, (msg, match) => {
const chatId = msg.chat.id;
const receivedMessage = match[1];
if (!task) {
task = receivedMessage;
bot.sendMessage(chatId, `Задача "${task}" добавлена.`);
}
bot.sendMessage(chatId, 'Введите время выполнения задачи')
bot.onText(/(.+)/, (msg, time) =>{
const chatId = msg.chat.id
const minutes = time[1]
if (!times) {
times = minutes;
bot.sendMessage(chatId, `Время выбрано: ${minutes}`);
}
})
})
const job = schedule.scheduleJob(`${parseInt(times)} * * * *`, function() {
bot.sendMessage(chatId, `Уведомление о задаче: \n\n Вы задавали задачу: ${task}`)
})
})
Это первый
говнокод, который у меня получился и в итоге не работал. В целом, он почти не отличается от моего нынешнего, не считая одну тему, о которой скажу позже. Из говна здесь то, что я пошёл трудным, тупым и при этом нерабочим путём. Чтобы параметры 'times' и 'task' сделать глобальными и использовать их в других функциях я просто пошёл через 'if'. Если кому интересно, как это работает - напишите. Следующей ошибкой было то, что я пытался после перевода 'times' в глобальную переменную (после её ввода в чате бота в телеграме пользователем) сразу пытался вставить это время в планировщик задач, соответственно в параметр, отвечающий за время. "const job = schedule.scheduleJob(`${parseInt(times)} * * * *`". Однако, кроме этого я делал и через new Data. Это ещё один способ указать время, просто он пишется на отдельной строке и в строку, которая выше, вместо тех одинарных скобок вставляется заданная переменная. Пример:
JavaScript:
const data = new Data('2023, 7, 16, 13, 32')
const job = schedule.scheduleJob(data, function() {
bot.sendMessage(chatId, 'Вы начали писать пост.')
})
В месяце 7, потому что месяца в JavaScript идут от 0 до 11. Я пытался сделать так:
JavaScript:
const data = new Data('2023, 7, 16, ${times}')
const job = schedule.scheduleJob(data, function() {
bot.sendMessage(chatId, 'Это уведомление отправлено в минуту ${times}')
})
Однако, с этим у меня тоже не сработало. Также я пытался сделать через правила, но там та же история.
Следующей совершенно незначительной ошибкой было то, что я сообщения принимал через bot.onText (задачу и время), хотя это было совершенно необязательно, потому что при вводе /add_task и последующем двойном bot.on, который принимает любые сообщения, программа ждала как раз таки два сообщения от пользователя, откуда можно было брать задачу и время.
Теперь перейдём к коду, который у меня получился в итоге благодаря нейросети.
JavaScript:
const userTasks = {};
bot.onText(/\/add_task/, (msg) => {
const chatId = msg.chat.id;
bot.sendMessage(chatId, 'Введите задачу:');
bot.once('message', (addedMsg) => {
const task = addedMsg.text;
bot.sendMessage(chatId, `Задача "${task}" добавлена.`);
bot.sendMessage(chatId, 'Введите время уведомления (в формате ЧЧ:ММ):');
bot.once('message', (timeMsg) => {
const time = timeMsg.text;
userTasks[chatId] = { task, time };
scheduleTask(chatId, task, time);
bot.sendMessage(chatId, `Время уведомления для задачи "${task}" установлено на ${time}.`);
});
});
});
function scheduleTask(chatId, task, time) {
const [hours, minutes] = time.split(':');
const notificationTime = new Date();
notificationTime.setHours(hours);
notificationTime.setMinutes(minutes);
schedule.scheduleJob(notificationTime, () => {
bot.sendMessage(chatId, `Время начать задачу "${task}"!`);
delete userTasks[chatId];
});
}
Можно не смотреть на то, что все ответные сообщения для пользователя написано более логично, как оно и должно быть. После просьбы разъяснить, как это можно сделать он кинул мне готовый код :/
Здесь самое главное отличие - создание функции scheduleTask, которая:
- Создаёт массив, состоящий из заданного часа и заданной минуты пользователем. Пользователь задаёт, к примеру, '13:46' одним сообщение, эта строка передаётся в переменную 'time'. Новое, что я узнал это то, что строку можно разделить, буквально, на две+ части и оно в таком виде передаётся в массив. В нашем случае строка разделяется знаком ':' через оператор 'split'. Однако, туда можно поставить что угодно.
- Создаёт дату, как я показывал выше. Однако, вместо 'date' в моём случае - создаётся notificationTime.
- С помощью 'setHours' и 'setMinutes' передаёт из массива в первой строке функции час и минуту, заданную пользователем. О них я не знал, кстати. (я про setHours и setMinutes)
- С помощью знакомого нам метода мы добавляем планировщик, вставляем вместо даты 'notificationTime'.
- В функции мы выводим само уведомление и удаляем задачу. После удаления уведомление не придёт на следующий день в это время.
А теперь главный для меня вопрос - почему также не работало без функции и 'setHours' 'setMinutes' и т.д.?
. . .
А я сам не знаю. Скорее всего, это добавлено специально для таких нужд, как ввод времени пользователем.
Также бот вместо bot.on вставил bot.once. Компилятор сам по себе его нормально не переваривает, подсвечивает предупреждением, но оно всё равно работает. Вот комментарий chatGPT по bot.once прямым текстом.
bot.once используется для создания "одноразового слушателя" в Discord.js. Когда указанное событие происходит впервые, данный слушатель выполнит указанный код и затем удалится. Это полезно, когда нужно выполнить какое-то действие только один раз, например, при запуске бота или при подключении к серверу Discord.
И эта штука реально решила мою проблему с прошлым кодом, которая, как мне казалась, происходила из-за неправильной расставки зон видимости.
Слева - bot.on, справа - bot.once. Думаю, разница на лицо. 'node-telegram-bot-api' после ввода пользователем сообщения возвращает выполнение функции к первой строке для присваивания переменных и заново выполняет. С bot.once каждая строка выполняется лишь один раз. Скорее всего, я объяснил неправильно, но я так это понимаю.
Ну и, вроде как, последнее отличие - вместо двух переменных task и time в этом коде они заменяются одним массивом.
Результат на сегодняшний день на правом скриншоте.