← Вернуться к списку тем

Календарь телеграм бот

Помогите пожалуйста, у меня календарь с вашего сайта и есть бд, в ней 3 столбика открытие смены закрытие и айди пользователя, откоытие и закрытие вводится в форме год месяц день часы секунды, мне нужно при нажатии на кнопку календаря допустим 22 декабря что бы выводило информацию человек далее если человек отработал больше 8 часов выводиться такой то человек заполнено , если меньше то ошибка. Заранее спасибо 

<?php 
include('settings.php'); 
const TOKEN = '5660869677:AAEgGN4W3FgaBkJovJwBrBmcZPBa6mmWTGA'; 
const BASE_URL = 'https://api.telegram.org/bot' . TOKEN . '/'; 
 
$update = json_decode(file_get_contents('php://input')); 
 
//file_put_contents(__DIR__ .'/logs.txt', print_r($update, 1),FILE_APPEND); 
$chat_id = $update->message->chat->id ?? ''; 
$text = $update->message->text ?? ''; 
 
if($text == '/start') { 
    $res = send_request('sendMessage', [ 
        'chat_id' => $chat_id, 
        'text' => 'Привет, я бот которой подскажет вам о не внесенных часах в Timewebest + о внесенном времени', 
        ]); 
} 
 
function send_request($method, $params =[]) 
{ 
    if(!empty($params)) { 
        $url = BASE_URL . $method . '?' . http_build_query($params); 
    }else{ 
        $url = BASE_URL .$method; 
    } 
    return json_decode(file_get_contents($url)); 
} 
 
// токен бота 
$bot_token = "5660869677:AAEgGN4W3FgaBkJovJwBrBmcZPBa6mmWTGA"; 
 
// получаем данные от телеграм 
$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]); 
        $query("sendMessage", ["chat_id" => $chat_id, "text" => "Проверка вывода текста"]); 
    } 
    // если это другие кнопки 
    else { 
        // заглушим просто запрос 
        $notice($cbq_id, "This is notice for bot"); 
    } 
}

Авторизуйтесь через Telegram, чтобы оставить комментарий.
Откройте по ссылке или QR бот @iMakeBot, нажмите кнопку Старт/Start.
Следуйте инструкциям бота.

  • iMakeBots [1 год назад]

    Попробуйте вот этот вариант, соединение с БД реализуйте в примере есть комментарий где нужно будет применить выборку из БД

    <?php
    //include('settings.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);
        }
    };
    
    /** запустим старт бота
     * @param $chat_id
     */
    $start = function($chat_id)  use($query) {
        // получим инфо о текущей дете
        $now_date = getdate();
        // подготовим кнопку
        $buttons[][] = [
            "text" => "Открыть календарь",
            "callback_data" => "cal_" . $now_date['mon'] . "_" . $now_date['year']
        ];
        // готовим данные
        $data = [
            "chat_id" => $chat_id,
            "text" => "Привет, я бот которой подскажет вам о не внесенных часах в Timewebest + о внесенном времени",
            "parse_mode" => "html",
            "reply_markup" => json_encode(['inline_keyboard' => $buttons])
        ];
        // направим сообщение в чат
        $query("sendMessage", $data);
    };
    
    /** выведем информацию по нажатию кнопки
     * @param $cbq_id
     * @param $chat_id
     * @param $message_id
     * @param $date
     */
    $getInfo = function($cbq_id, $chat_id, $message_id, $date) use($notice, $query) {
        // гасим запрос
        $notice($cbq_id);
        // парсим дату
        $date_params = explode("-", $date);
        // готовим кнопку вернуться
        $buttons[][] = [
            "text" => "Вернуться",
            "callback_data" => "cal_" . $date_params[1] . "_" . $date_params[2]
        ];
    
        /**
         * Здесь вы делаете запрос в бд
         * Собираете текст ($text) из нужных данных из бд
         */
    
        // инициируете переменныю для текста + первые даные можно записать
        $text = "<b>Информация</b> по дате " . $date;
        // собирать текст можно через конкатенацию [https://www.php.net/manual/ru/language.operators.string.php]
        $text .= "\n---\nЕще данные для переменной \$text";
        // готовим данные
        $data = [
            "chat_id" => $chat_id,
            "message_id" => $message_id,
            "text" => $text,
            "parse_mode" => "html",
            "reply_markup" => json_encode(['inline_keyboard' => $buttons])
        ];
        // направим сообщение в чат
        $query("editMessageText", $data);
    };
    
    /**
     * Простой роутер бота
     */
    if (isset($data->message)) {
        // получим id чата
        $chat_id = $data->message->from->id;
        // проверим что это текстовое сообщение
        if (isset($data->message->text)) {
            // проверим что это старт бота
            if ($data->message->text == "/start") {
                // запустим старт
                $start($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;
        // получим message_id
        $message_id = $data->callback_query->message->message_id;
        // спарсим значения
        $params = explode("_", $c_data);
        // если это переключение между месяцами
        if ($params[0] == "cal") {
            // выведем календарь на экран по переданным параметрам
            $viewCal($params[1], $params[2], $chat_id, $cbq_id, $message_id);
        }
        // если это нажатие по кнопке для информации
        elseif ($params[0] == "info") {
            // выведем информацию
            $getInfo($cbq_id, $chat_id, $message_id, $params[1]);
        }
        // если это другие кнопки
        else {
            // заглушим просто запрос
            $notice($cbq_id, "This is notice for bot");
        }
    }
  • Сергей Ларичев(Череповец) [1 год назад → iMakeBots]

    Спасибо большое, только не очень понимаю как сделать такой запрос что бы именно на этот день инфа выводилась

  • iMakeBots [1 год назад → Сергей Ларичев(Череповец)]

    Посмотрите на методы работы с mysqli на оф.сайте PHP, попробуйте написать функцию и потом используйте ее для получения данных из БД. Результаты публикуйте - подскажу если не получиться.

  • Сергей Ларичев(Череповец) [1 год назад → iMakeBots]

    как я понял надо использовать timediff? Верно ? 

  • iMakeBots [1 год назад → Сергей Ларичев(Череповец)]

    Если вам нужно получить все записи где дата совпадает то используйте простое сравнение

    SELECT * FROM table WHERE date = '2022-11-24'
  • Сергей Ларичев(Череповец) [1 год назад → iMakeBots]

    у меня просто задача вывести не саму дату, а сначала посчитать сотрудник внес 8 часов или больше если так то вывести имя и заполнено, а если меньше то имя  не верно заполнили 

  • iMakeBots [1 год назад → Сергей Ларичев(Череповец)]

    )) сорри не понял ничего:

    Приведите структуру базы и что по итогу вы хотите получить.

  • Сергей Ларичев(Череповец) [1 год назад → iMakeBots]

    есть 3 столбика юзер айди  открытие смены и закрытие, допустим юзер 1 открыл смену 24 ноября в 10 утра и закрыл в 6 вечера, если так то выводим в наш календарь инфу  на этот день такой то человек заполнил, т е отработал 8 часов все четко, а юзер 2 открыл смену в 10 утра а закрыл  в 12 утра то заполнено не верно

  • iMakeBots [1 год назад → Сергей Ларичев(Череповец)]

    Тогда вам нужно найти записи пользователя по user_id, плюс по переданной дете и получить разницу в датах:

    SELECT 
       DATEDIFF(end, begin) as time 
    WHERE user_id = '123' 
    AND begin >='2022-11-24 00:00:00'
    AND begin < '2022-11-25 00:00:00'
  • Сергей Ларичев(Череповец) [1 год назад → iMakeBots]

    понял, а это уже связь со всем календарем или только на 1 дату

  • iMakeBots [1 год назад → Сергей Ларичев(Череповец)]

    Подставите переданную дату вместо 2022-11-24 и также следующий день 2022-11-25 рассчитаете +1 day - примеры есть в статье про календарь

  • Сергей Ларичев(Череповец) [1 год назад → iMakeBots]

    Понял, спасибо большое 

  • Сергей Ларичев(Череповец) [1 год назад → iMakeBots]

    Здравствуйте,  вообщем сделал я через процедуру, теперь сижу думаю как запрос сам написать в пхп, может будут идеи ?

    вот сама процедура: 

    BEGIN
        SELECT working_shifts.open_at, name, (TIMESTAMPDIFF(minute, open_at, close_at) / 60) as time_work 
        FROM users,working_shifts 
        WHERE users.id = user_id and DATE_FORMAT(working_shifts.open_at, '%Y-%m-%d') = time;
    END
  • iMakeBots [1 год назад → Сергей Ларичев(Череповец)]

    Это больше похоже на простой запрос. Зачем его упаковывать в хранимую процедуру? 

    Просто вызовите его через mysqli_query