Были вопросы в бот обратной связи по теме календаря, приведу пример для webHook на PHP и на NodeJS
Пример на PHP
<?php
// токен бота
$bot_token = "Токен вашего бота";
// получаем данные от телеграм
$data = json_decode(file_get_contents("php://input"));
/** Запрос в Телеграм
* @param $method
* @param array $fields
* @return mixed
*/
$query = function ($method, $fields = []) use ($bot_token) {
// откроем соединение
$ch = curl_init("https://api.telegram.org/bot" . $bot_token . "/" . $method);
// определим опции
curl_setopt_array($ch, [
CURLOPT_POST => count($fields),
CURLOPT_POSTFIELDS => http_build_query($fields),
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_TIMEOUT => 10
]);
// спарсим в объект результат запроса
$result = json_decode(curl_exec($ch), true);
// закроем соединение
curl_close($ch);
// вернем результат
return $result;
};
/**
* Выводим уведомление
* @param $cbq_id
* @param $text
*/
$notice = function ($cbq_id, $text = null) use ($query) {
// определим данные
$data = [
"callback_query_id" => $cbq_id,
"alert" => false
];
// если есть текст то добавим
if (!is_null($text)) {
$data['text'] = $text;
}
// отправим в Телеграм
$query("answerCallbackQuery", $data);
};
/** Переопределим номер дня недели
* @param $date DateTime
* @return int
*/
$getNumDayOfWeek = function ($date) {
// получим день недели
$day = $date->format("w");
// вернем на 1 меньше [0 - вск]
return ($day == 0) ? 6 : $day - 1;
};
/** Получим массив дней разбитых по неделям
* @param $month
* @param $year
* @return array
* @throws Exception
*/
$getDays = function ($month, $year) use ($getNumDayOfWeek) {
// создаем дату на начало месяца
$date = new DateTime($year . "-" . $month . "-01");
// массив дней
$days = [];
// начало массива
$line = 0;
// заполним начало если нужно пустыми значениями
for ($i = 0; $i < $getNumDayOfWeek($date); $i++) {
$days[$line][] = "-";
}
// перебираем дни пока месяц совпадает с переданным
while ($date->format("m") == $month) {
// добавляем в строку дни
$days[$line][] = $date->format("d");
// вс, последний день - перевод строки
if ($getNumDayOfWeek($date) % 7 == 6) {
// добавляем новую строку
$line += 1;
}
// переходим на следующий день
$date->modify('+1 day');
}
// дозаполняем последнюю строку пустыми значениями
if ($getNumDayOfWeek($date) != 0) {
for ($i = $getNumDayOfWeek($date); $i < 7; $i++) {
$days[$line][] = "-";
}
}
// вернем массив дней
return $days;
};
/** Выводим календарь
* @param $month
* @param $year
* @param $chat_id
* @param null $cbq_id
* @param null $message_id
*/
$viewCal = function ($month, $year, $chat_id, $cbq_id = null, $message_id = null) use ($getDays, $notice, $query) {
// получаем массив дней месяца
$dayLines = $getDays($month, $year);
// определим переданную дату
$current = new DateTime($year . "-" . $month . "-01");
// определим параметры переданного месяца
$current_info = $current->format("m-Y");
// определим кнопки
$buttons = [];
// первый ряд кнопок это навигация календаря
$buttons[] = [
[
"text" => "<<<",
"callback_data" => "cal_" . date("m_Y", strtotime('-1 month', $current->getTimestamp()))
],
[
"text" => $current_info,
"callback_data" => "info_" . $current_info
],
[
"text" => ">>>",
"callback_data" => "cal_" . date("m_Y", strtotime('+1 month', $current->getTimestamp()))
]
];
// выводим дни месяца
foreach ($dayLines as $line => $days) {
// переберем линию
foreach ($days as $day) {
// добавим кнопку в линию
$buttons[$line + 1][] = [
// выведем день
"text" => $day,
// поределим параметры
"callback_data" => $day > 0
// если это день
? "info_" . $day . "-" . $current_info
// другое значение
: "inline"
];
}
}
// готовим данные
$data = [
"chat_id" => $chat_id,
"text" => "<b>Календарь:</b>\n\n" . $current->format("F Y"),
"parse_mode" => "html",
"reply_markup" => json_encode(['inline_keyboard' => $buttons])
];
// проверим как отправлять: как новое или замена содержимого
if (!is_null($message_id)) {
// гасим запрос
$notice($cbq_id);
// добавим message_id
$data["message_id"] = $message_id;
// направим в Телеграм на изменение сообщения
$query("editMessageText", $data);
} else {
// направим сообщение в чат
$query("sendMessage", $data);
}
};
/**
* Простой роутер бота
*/
if (isset($data->message)) {
// получим id чата
$chat_id = $data->message->from->id;
// проверим что это текстовое сообщение
if (isset($data->message->text)) {
// проверим что это старт бота
if ($data->message->text == "/start") {
// получим инфо о текущей дете
$now_date = getdate();
// запустим вывод календаря текущего месяца
$viewCal($now_date['mon'], $now_date['year'], $chat_id);
}
}
// если это нажатие по кнопке
} elseif (isset($data->callback_query)) {
// получим id чата
$chat_id = $data->callback_query->from->id;
// получим callBackQuery_id
$cbq_id = $data->callback_query->id;
// получим переданное значение в кнопке
$c_data = $data->callback_query->data;
// спарсим значения
$params = explode("_", $c_data);
// если это переключение между месяцами
if ($params[0] == "cal") {
// выведем календарь на экран по переданным параметрам
$viewCal($params[1], $params[2], $chat_id, $cbq_id, $data->callback_query->message->message_id);
}
// если это нажатие по кнопке для информации
elseif ($params[0] == "info") {
// выведем информацию
$notice($cbq_id, $params[1]);
}
// если это другие кнопки
else {
// заглушим просто запрос
$notice($cbq_id, "This is notice for bot");
}
}
* * *
Пример на NodeJS
package.json
{
"name": "Calendar",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "iMakeBots.ru",
"license": "",
"dependencies": {
"request": "^2.88.0",
}
}
index.js
const request = require('request');
const http = require('http');
let config = {
token: "Токен вашего бота"
};
/**
* Создадим сервер на порту 8080
* @param request_
* @param response_
*/
http.createServer(function (request_, response_) {
// ответим 200 кодом
response_.writeHead(200);
// определим кодировку
request_.setEncoding('utf8');
// объявим
let body = '';
// обработаем
request_
// соберем body
.on('data', (chunk) => {
body += chunk;
})
// после
.on('end', () => {
// запустим роутер
route(JSON.parse(body));
});
// закроем
response_.end();
}).listen(8080);
/**
* Простой роутер
* @param data
*/
const route = function (data) {
// если это сообщение
if ('message' in data) {
// получим id чата
let chat_id = data.message.from.id;
// проверим что это текстовое сообщение
if ('text' in data.message) {
// проверим что это старт бота
if (data.message.text === "/start") {
// запустим вывод календаря текущего месяца
viewCal((new Date()).getFullYear(), (new Date()).getMonth(), chat_id);
}
}
}
// если это нажатие по кнопке
else if ('callback_query' in data) {
// получим id чата
let chat_id = data.callback_query.from.id;
// получим callBackQuery_id
let cbq_id = data.callback_query.id;
// получим переданное значение в кнопке
let c_data = data.callback_query.data;
// спарсим значения
let params = c_data.split("_");
// если это переключение между месяцами
if (params[0] === "cal") {
// выведем календарь на экран по переданным параметрам
viewCal(params[1], params[2], chat_id, cbq_id, data.callback_query.message.message_id);
}
// если это нажатие по кнопке для информации
else if (params[0] === "info") {
// выведем информацию
notice(cbq_id, params[1]);
} else {
// заглушим просто запрос
notice(cbq_id, "This is notice for bot");
}
}
};
/**
* Выведем календарь
* @param month
* @param year
* @param chat_id
* @param cbq_id
* @param message_id
*/
function viewCal(year, month, chat_id, cbq_id = null, message_id = null) {
// получаем массив дней месяца
let dayLines = getDays(year, month);
// определим переданную дату
let currentMonthDate = new Date(+year, +month);
// дата предыдущего месяца
let prevMonthDate = (new Date((new Date(currentMonthDate)).setMonth(currentMonthDate.getMonth() - 1)))
// дата следующего месяца
let nextMonthDate = (new Date((new Date(currentMonthDate)).setMonth(currentMonthDate.getMonth() + 1)))
// определим параметры переданного месяца
let current_info = setBeforeZero(currentMonthDate.getMonth() + 1) + "-" + currentMonthDate.getFullYear();
// определим кнопки
let buttons = [];
// первый ряд кнопок это навигация календаря
buttons.push([
{
text: "<<<",
callback_data: "cal_" + prevMonthDate.getFullYear() + "_" + prevMonthDate.getMonth()
},
{
text: current_info,
callback_data: "info_" + current_info
},
{
text: ">>>",
callback_data: "cal_" + nextMonthDate.getFullYear() + "_" + nextMonthDate.getMonth()
}
]);
// переберем дни
dayLines.forEach(function(line) {
// добавим ряд кнопок
buttons[buttons.length] = [];
// переберем линию дней
line.forEach(function(day) {
// добавим кнопку
buttons[buttons.length - 1].push({
text: day,
callback_data: day > 0
? "info_" + setBeforeZero(day) + "-" + current_info
: "inline"
});
});
});
// готовим данные
let data = {
chat_id: chat_id,
text: "<b>Календарь:</b>\n\n" + currentMonthDate.toLocaleString('ru', {month: 'long', year: 'numeric'}),
parse_mode: "html",
reply_markup: {inline_keyboard: buttons}
};
// проверим как отправлять: как новое или замена содержимого
if (message_id !== null) {
// гасим запрос
notice(cbq_id);
// добавим message_id
data.message_id = message_id;
// направим в Телеграм на изменение сообщения
query("editMessageText", data);
} else {
// направим сообщение в чат
query("sendMessage", data);
}
}
/**
* Получаем массив дней для календаря
* @param year
* @param month
* @returns {Array}
*/
function getDays(year, month) {
// получаем дату
let d = new Date(year, month);
// объявляем массив
let days = [];
// добавляем первую строку
days[days.length] = [];
// добавляем в первую строку пустые значения
for (let i = 0; i < getNumDayOfWeek(d); i++) {
days[days.length - 1].push("-");
}
// выходим пока месяц не перешел на другой
while (d.getMonth() === +month) {
// добавляем в строку дни
days[days.length - 1].push(d.getDate());
// вс, последний день - перевод строки
if (getNumDayOfWeek(d) % 7 === 6) {
// добавляем новую строку
days[days.length] = [];
}
// переходим на следующий день
d.setDate(d.getDate() + 1);
}
// дозаполняем последнюю строку пустыми значениями
if (getNumDayOfWeek(d) !== 0) {
for (let i = getNumDayOfWeek(d); i < 7; i++) {
days[days.length - 1].push("-");
}
}
// вернем массив
return days;
}
/**
* Переопределим номер дня недели
* @param date
* @return int
*/
function getNumDayOfWeek(date) {
// получим день недели
let day = date.getDay();
// вернем на 1 меньше [0 - вск]
return (day === 0) ? 6 : day - 1;
}
/**
* Выводим уведомление
* @param cbq_id
* @param text
*/
function notice(cbq_id, text = null) {
// определим данные
let data = {
callback_query_id: cbq_id,
alert: false
};
// если есть текст то добавим
if (text !== null) {
data.text = text;
}
// отправим в Телеграм
query("answerCallbackQuery", data);
}
/**
* Отправим запрос в Ттелеграм
* @param method
* @param fields
*/
function query(method, fields) {
request({
url: 'https://api.telegram.org/bot' + config.token + '/' + method,
method: 'post',
headers: {"content-type": "application/json"},
json: fields
});
}
/**
* Добавим ноль вперед
* @param num
* @returns {string}
*/
function setBeforeZero(num) {
return ("0" + (num)).slice(-2);
}
Откройте по ссылке или QR бот @iMakeBot, нажмите кнопку Старт/Start.
Следуйте инструкциям бота.
Что делает этот скрипт?
Просто пример вывода календаря в бот как на картинке в статье.
а вообще возможно вывести новое сообщение какое мне нужно при нажатии на число?
Конечно, это же для примера статья. Вы можете добавить любой функционал.
можете помочь пожалуйста, плохо разбираюсь, не понимаю какую строку надо править ((
В роутере замените строчку:
Спасибо огромное, очень помогли
Спасибо огромное за вариант с php, но он точно рабочий? Ни как не могу понять, в чем дело, создал чистейшего бота, вписал /start, указал его токен в файле и тишина.
Webhook настроили?
Спасибо, я только начал изучать эту тему, про это даже бы не допёр. Всего самого лучшего в этой жизни тебе