В офисе установлена VoIP АТС на базе asterisk(elastix 4). Если кто-либо звонит на АТС через FXO-шлюз(подключенные внешние линии), а после переадресовывается на внешний номер(т.е. городской(или gsm) номер[1] -> порт FXO[2] -> АТС[3] -> порт FXO[4] -> городской(или gsm) номер[5]), то, естественно, при определении входящего номера на аппарате 5 будет виден номер порта 4. Пробросить же номер 1 через порт 4(чтобы он был виден на определителе номера 5) в городскую/gsm-сеть не представляется возможны. При этом нужно каким-либо образом передать информацию о звонке абоненту на номере 5.
Для решения этой задачи был реализован бот телеграм.
Для создания бота необходимо написать @BotFather, зарегистрировать бота и получить ключ API.
Для работы бота нужны ssl-сертификаты, поэтому нужно его получить. Пути здесь три:
1)купить
2)получить через Let’s Encrypt
3)сгенерировать самоподписанный(такой тоже прокатит)
Далее, как обычно создаю файл настроек(тут уже все):
<?php //Настройка бота $APIKEY = '*****************************'; //ключ апи $siteurl = 'https://******/tgsocks'; //адрес папки при доступе из интернета //$cert = '/cert/telega.crt'; нужно только в случае самоподписанного $fileurl = '/var/www/************'; //адрес папки при доступе из файловой системы(для отправки README.txt например) $adminId = '236255988'; // администратор $adminEmail = 'admin@sergdudko.tk'; //email для отправки уведомлений $file = '/var/log/telegramm/'.date("Y-m-d").'.log'; //файл лога //Настройка MySQL: $dbaddr = '****'; //адрес $dbuser = '*****'; //юзер $dbpass = '*****'; //пароль $db = 'telegramm'; //Настройка mainapi $mainkey = '***************************'; //мой ключ ?>
Создаю папку для логов, указанную в файле настроек(с правами записи), таблицу в базе данных:
Ну или так:
CREATE TABLE `registeruser` ( `Id` int(11) NOT NULL AUTO_INCREMENT, `date` varchar(255) DEFAULT NULL, `time` varchar(255) DEFAULT NULL, `username` varchar(255) DEFAULT NULL, `uid` varchar(255) DEFAULT NULL, `first_name` varchar(255) DEFAULT NULL, `last_name` varchar(255) DEFAULT NULL, `tel` varchar(255) NOT NULL DEFAULT 'null', `password` varchar(255) DEFAULT NULL, `ban` int(11) NOT NULL DEFAULT '10', PRIMARY KEY (`Id`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
Создаю папку с files и в ней описание, создаю папку mailer и в ней класс для работы с почтой(её содержимое описывать не буду, т.к. вариантов в интернете хватает). Там должен быть mailer.php, который получив REST-запрос с message, отправит это сообщение на email из файла settings.php
Далее создаю файл скрипт для регистрации бота, для разнообразия регистрация сертификатов будет из консоли:
<?php include 'settings.php'; //для самоподписанного сертификата //exec('curl -F "url='.$siteurl.'/webhook.php" -F "certificate=@'.$cert.'" https://api.telegram.org/bot'.$APIKEY.'/setWebhook'); exec('curl -F "url='.$siteurl.'/webhook.php" https://api.telegram.org/bot'.$APIKEY.'/setWebhook'); sleep(2); echo exec('curl https://api.telegram.org/bot'.$APIKEY.'/getWebhookInfo'); ?>
Запускаю его и проверяю, что всё ок (полное описание будет в самом низу).
Создаю файл index.php, просто чтобы что-то открывалось:
<?php include 'settings.php'; echo '<br><br><br><br><br><center> Привет, я бот для Телеграмм. <br><br> Чтобы начать пользоваться мной, нужно написать мне в <a href="https://telegram.org/">Telegramm</a> сообщение "/start", а также мне на <a href="'.$adminEmail.'">email: '.$adminEmail.'</a> ваш номер телефона.</center>'; ?>
Скрыть содержимое папок можно через веб-сервер
1 |
Options -Indexes |
или .htaccess.
Далее необходимо написать веб-хук, куда будет цепляться ответ от telegrama(ответ получать абсолютно не обязательно, но так у нас будет рабочее меню в боте, а не только рассылка информации), мой веб-хук анализирует id чата и делит всех на две группы:
1)админ(указан в настройках)
2)остальные
вот его состав:
<?php include 'settings.php'; $current = file_get_contents($file); $content = file_get_contents("php://input"); $update = json_decode($content, TRUE); $message = $update["message"]; $chatId = $message["chat"]["id"]; $chatUd = $message["chat"]["username"]; $fName = $message["chat"]["first_name"]; $lName = $message["chat"]["last_name"]; $text = $message["text"]; $connectdb = new mysqli($dbaddr, $dbuser, $dbpass, $db); if ($connectdb->connect_errno) { $current .= date("Y-m-d H:i:s").' '."Не удалось подключиться к MySQL:".$connectdb->connect_error.PHP_EOL;; exit; } $connectdb->query("SET NAMES utf8"); $result = $connectdb->query("SELECT * FROM `registeruser` WHERE uid = '$chatId' limit 1"); $row = $result->fetch_array(); if($text == '/start'){ $current .= date("Y-m-d H:i:s").' '.'Добавлен ID:'.$chatId.' с именем @'.$chatUd.PHP_EOL; if ($row != null) { $connectdb->query("UPDATE `registeruser` SET `date`='".date("Y-m-d")."',`time`='".date("H:i:s")."',`username`='".$chatUd."',`first_name`='".$fName."',`last_name`='".$lName."' WHERE `uid`='".$chatId."'"); $current .= date("Y-m-d H:i:s").' '.'Данные в MySQL обновлены.'.PHP_EOL; } else { $connectdb->query("insert into `registeruser`(date, time, username, uid, first_name, last_name) values ('".date("Y-m-d")."', '".date("H:i:s")."', '".$chatUd."', '".$chatId."', '".$fName."', '".$lName."')"); $current .= date("Y-m-d H:i:s").' '.'Данные в MySQL добавлены.'.PHP_EOL; } $privet = urlencode('Здравствуйте, '.$fName.'. Вы успешно подключились к боту АТС ОДО Фармин.'.(PHP_EOL).'После подтверждения администратором вы будете получать информацию о переадресованных вызовах с рабочего номера.'); $admprivet = urlencode('Зарегистрирован новый пользователь:'.$chatUd.' с ид:'.$chatId); usleep(500); $sendmail = file_get_contents($siteurl.'/mailer/mailer.php?message='.$admprivet); $current .= date("Y-m-d H:i:s").' '.'Уведомление на почту отправлено:'.PHP_EOL; usleep(500); $answer = file_get_contents($siteurl.'/sendtg.php?id='.$adminId.'&message='.$admprivet); $answerarr = json_decode($answer, TRUE); $realanswer = 'false'; if($answerarr["ok"] == true) $realanswer = 'true'; $current .= date("Y-m-d H:i:s").' '.'Уведомление админу отправлено:'.$realanswer.PHP_EOL; usleep(500); $answer = file_get_contents($siteurl.'/sendtg.php?id='.$chatId.'&message='.$privet); $answerarr = json_decode($answer, TRUE); $realanswer = 'false'; if($answerarr["ok"] == true) $realanswer = 'true'; $current .= date("Y-m-d H:i:s").' '.'Приветствие отправлено:'.$realanswer.PHP_EOL; $current .= PHP_EOL; } else { if($chatId == $adminId){ include 'adminsession.php'; } else { include 'usersession.php'; } } $connectdb->close(); // Пишем содержимое обратно в файл file_put_contents($file, $current); ?>
Расширение функционала будет проходить в скриптах adminsession и usersession соответственно. Все бы неплохо, но пока наш бот не умеет ничего отправлять, только слушать. Но это уже неплохо(можно например в логах определить id чата для админа). Для регистрации необходимо боту отправить команду
1 |
/start |
.
Для отправки сообщения написал скрипт, который получает id чата и сообщение, либо имя документа и отправляет соответственно. Отправку файлов сделал из консоли, если переписать ее на php(curl library), то при переезде с php 5.4 на 7.0 были бы проблемы. Вот код(рекомендую изменить, дополнив каким-нибудь секретным ключом):
<?php include 'settings.php'; $id = $_GET['id']; $message = $_GET['message']; $document = $_GET['document']; if(isset($message)) { $url = 'https://api.telegram.org/bot'.$APIKEY.'/sendMessage'; $data = array('chat_id'=>$id,'text'=>$message); $json = json_encode($data); $ch = curl_init($url); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_POSTFIELDS, $json); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json', 'Content-Length: ' . strlen($json)) ); $result = curl_exec($ch); } else { if(isset($document)) { $url = 'https://api.telegram.org/bot'.$APIKEY.'/sendDocument?chat_id='.$id; $result = exec('curl -F name=document -F document=@'.$fileurl.'files/'.$document.' '.$url); } } echo $result; ?>
для php 5.4 отправка файла выглядит так:
@{$fileLocation.$file}
А для 7.0:
new CURLFile($fileLocation,'multipart/form-data',$file)
Проверим отправку через простейший html:
<html> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <form action="sendtg.php?" enctype="multipart/form-data"> <input type="text" name="id"> <input type="text" name="message"> <input type="submit" value="Отправить"> </form> </html>
Отправка прошла, значит все ок. Теперь самое время написать API для приема сообщений от asterisk, обмен будет в json:
<?php include 'settings.php'; $content = file_get_contents("php://input"); $update = json_decode($content, TRUE); $usernum = $update["usernum"]; $calleridname = $update["calleridname"]; $calleridnum = $update["calleridnum"]; $time = $update["time"]; $key = $update["key"]; $current = file_get_contents($file); if($key == $mainkey){ $connectdb = new mysqli($dbaddr, $dbuser, $dbpass, $db); if ($connectdb->connect_errno) { $current .= date("Y-m-d H:i:s").' '."Не удалось подключиться к MySQL:".$connectdb->connect_error.PHP_EOL;; exit; } $connectdb->query("SET NAMES utf8"); $result = $connectdb->query("SELECT * FROM `registeruser` WHERE tel = '$usernum' limit 1"); $row = $result->fetch_array(); if($row != null){ $curlcontent = urlencode('В '.$time.' вам звонил '.$calleridname.'<'.$calleridnum.'>'); $answer = file_get_contents($siteurl.'/sendtg.php?id='.$row['uid'].'&message='.$curlcontent); $answerarr = json_decode($answer, TRUE); $realanswer = 'false'; if($answerarr["ok"] == true) $realanswer = 'true'; if($realanswer == 'true') $current .= date("Y-m-d H:i:s").' '.'Уведомление '.$row['first_name'].' '.$row['last_name'].'('.$row['uid'].') о звонке отправлено.'.PHP_EOL; else $current .= date("Y-m-d H:i:s").' '.'Ошибка отправки уведомления о звонке пользователю '.$row['first_name'].' '.$row['last_name'].'('.$row['uid'].')'.PHP_EOL; } else $current .= date("Y-m-d H:i:s").' '.'Номер '.$usernum.' отсутствует в БД'.PHP_EOL; $connectdb->close(); } else $current .= date("Y-m-d H:i:s").' '.'ОБРАЩЕНИЕ С НЕ ВЕРНЫМ КЛЮЧОМ!'.PHP_EOL; $current .= PHP_EOL; // Пишем содержимое обратно в файл file_put_contents($file, $current); ?>
Проверить отправку можно из консоли:
curl -k -H "Content-Type: application/json" -X POST -d '{"usernum":"563","calleridname":"xyваыываы аыаыz","calleridnum":"666","time":"21:21:21","key":"***********"}' https://**********/mainapi.php
Теперь добавим эту отправку в Asterisk. Для этого редактируем
vi /etc/asterisk/extensions_custom.conf
В соответствующий контекст необходимо добавить строку:
exten => s,n,SYSTEM(curl -k -H "Content-Type: application/json" -X POST -d '{"usernum":"${ARG1}","calleridname":"${CALLERID(name)}","calleridnum":"${CALLERID(number)}","time":"${STRFTIME(${EPOCH},,%H:%M:%S)}","key":"**********************"}' https://*****************/tgsocks/mainapi.php)
Куда писать — если вы хотите получать уведомления о всех входящих вызовах, в тот контекст
1 |
[context_primer] |
, который указан у вас в настройках транка для USER Context
1 |
context=context_primer |
, либо во вложенный контекст, который будет выполняться во всех входящих контекстах(транков у вас может быть несколько и контексты для них разные, например у меня для определения номера во все входящие контексты вложен один и тот же, туда же можно добавить уведомление о вызовах). Если только при переадресации, то соответственно в контекст переадресации.
Проверили, уведомления пошли. Далее пишу команды для администратора(для работы прямо из телеграма):
<?php $newstr = PHP_EOL; if($chatId == $adminId) { $current .= date("Y-m-d H:i:s").' '.'Начата Админ-сессия с ID :'.$chatId.' от имени @'.$chatUd.PHP_EOL; $j=0; $txt; for($i=0;$i<strlen($text);$i++){ if($text[$i] != ' ') if($txt[$j] != null) $txt[$j]=$txt[$j].$text[$i]; else $txt[$j]=$text[$i]; else $j++; } if($txt[0] == '/help'){ $notice = urlencode('Справка по коммандам:'.$newstr); $notice = $notice.urlencode($newstr); $notice = $notice.urlencode('/help -> выведет список административных команд.'.$newstr); $notice = $notice.urlencode('/users -> выведет список всех пользователей.'.$newstr); $notice = $notice.urlencode('/newuser пользователь телефон -> обновит или добавит указанному пользователю номер.'.$newstr); $notice = $notice.urlencode('/deluser пользователь -> удалит указанному пользователю телефон.'.$newstr); $notice = $notice.urlencode('/block пользователь -> запретит пользователю менять телефон.'.$newstr); $notice = $notice.urlencode('/unblock пользователь -> разрешит пользователю менять телефон.'.$newstr); $notice = $notice.urlencode('/tel пользователь -> вернет телефон заданного пользователя.'.$newstr); $notice = $notice.urlencode('/readme -> выведет описание работы чата.'); $answer = file_get_contents($siteurl.'/sendtg.php?id='.$adminId.'&message='.$notice); $answerarr = json_decode($answer, TRUE); $realanswer = 'false'; if($answerarr["ok"] == true) $realanswer = 'true'; $current .= date("Y-m-d H:i:s").' '.'Уведомление админу(HELP) отправлено:'.$realanswer.PHP_EOL; } if(($txt[0] != '/help') && ($txt[0] != '/users') && ($txt[0] != '/newuser') && ($txt[0] != '/deluser') && ($txt[0] != '/tel') && ($txt[0] != '/block') && ($txt[0] != '/unblock') && ($txt[0] != '/readme')){ $notice = urlencode('Неправильный запрос.'.$newstr); $notice = $notice.urlencode('Наберите /help для справки по коммандам.'); $answer = file_get_contents($siteurl.'/sendtg.php?id='.$adminId.'&message='.$notice); $answerarr = json_decode($answer, TRUE); $realanswer = 'false'; if($answerarr["ok"] == true) $realanswer = 'true'; $current .= date("Y-m-d H:i:s").' '.'Уведомление админу(NO COMMAND) отправлено:'.$realanswer.PHP_EOL; } if($txt[0] == '/newuser'){ if($txt[1][0] != '@') $result = $connectdb->query("SELECT * FROM `registeruser` WHERE uid = '".$txt[1]."' limit 1"); else $result = $connectdb->query("SELECT * FROM `registeruser` WHERE username = '".substr($txt[1], 1)."' limit 1"); $row = $result->fetch_array(); if($row != null){ $current .= date("Y-m-d H:i:s").' '.'Добавляем пользователю:'.$txt[1].' телефон '.$txt[2].PHP_EOL; if($txt[1][0] != '@') $connectdb->query("UPDATE `registeruser` SET `tel`='".$txt[2]."' WHERE `uid`='".$txt[1]."'"); else $connectdb->query("UPDATE `registeruser` SET `tel`='".$txt[2]."' WHERE `username`='".substr($txt[1], 1)."'"); $notice = urlencode('Пользователю '.$txt[1].' добавлен номер '.$txt[2].'.'); } else { $current .= date("Y-m-d H:i:s").' '.'Пользователь:'.$txt[1].' не найден.'.PHP_EOL; $notice = urlencode('Пользователь:'.$txt[1].' не найден.'); } $answer = file_get_contents($siteurl.'/sendtg.php?id='.$adminId.'&message='.$notice); $answerarr = json_decode($answer, TRUE); $realanswer = 'false'; if($answerarr["ok"] == true) $realanswer = 'true'; $current .= date("Y-m-d H:i:s").' '.'Уведомление админу(изменение номера) отправлено:'.$realanswer.PHP_EOL; } if($txt[0] == '/deluser'){ if($txt[1][0] != '@') $result = $connectdb->query("SELECT * FROM `registeruser` WHERE uid = '".$txt[1]."' limit 1"); else $result = $connectdb->query("SELECT * FROM `registeruser` WHERE username = '".substr($txt[1], 1)."' limit 1"); $row = $result->fetch_array(); if($row != null){ $current .= date("Y-m-d H:i:s").' '.'Удаляем пользователю:'.$txt[1].' телефон.'.PHP_EOL; if($txt[1][0] != '@') $connectdb->query("UPDATE `registeruser` SET `tel`='null' WHERE `uid`='".$txt[1]."'"); else $connectdb->query("UPDATE `registeruser` SET `tel`='null' WHERE `username`='".substr($txt[1], 1)."'"); $notice = urlencode('Пользователю '.$txt[1].' удален номер.'); } else { $current .= date("Y-m-d H:i:s").' '.'Пользователь:'.$txt[1].' не найден.'.PHP_EOL; $notice = urlencode('Пользователь:'.$txt[1].' не найден.'); } $answer = file_get_contents($siteurl.'/sendtg.php?id='.$adminId.'&message='.$notice); $answerarr = json_decode($answer, TRUE); $realanswer = 'false'; if($answerarr["ok"] == true) $realanswer = 'true'; $current .= date("Y-m-d H:i:s").' '.'Уведомление админу(удаление номера) отправлено:'.$realanswer.PHP_EOL; } if($txt[0] == '/tel'){ if($txt[1][0] != '@') $result = $connectdb->query("SELECT * FROM `registeruser` WHERE uid = '".$txt[1]."' limit 1"); else $result = $connectdb->query("SELECT * FROM `registeruser` WHERE username = '".substr($txt[1], 1)."' limit 1"); $row = $result->fetch_array(); if($row != null){ $current .= date("Y-m-d H:i:s").' '.'У пользователя:'.$txt[1].' телефон '.$row['tel'].'.'.PHP_EOL; $notice = urlencode('У пользователя:'.$txt[1].' телефон '.$row['tel'].'.'); } else { $current .= date("Y-m-d H:i:s").' '.'Пользователь:'.$txt[1].' не найден.'.PHP_EOL; $notice = urlencode('Пользователь:'.$txt[1].' не найден.'); } $answer = file_get_contents($siteurl.'/sendtg.php?id='.$adminId.'&message='.$notice); $answerarr = json_decode($answer, TRUE); $realanswer = 'false'; if($answerarr["ok"] == true) $realanswer = 'true'; $current .= date("Y-m-d H:i:s").' '.'Уведомление админу(инфа о юзере) отправлено:'.$realanswer.PHP_EOL; } if($txt[0] == '/users'){ $result = $connectdb->query('SELECT * FROM `registeruser` ORDER BY id'); $i=0; while( $row = $result->fetch_assoc() ){ $arraydb[$i] = $row; $i++; } $result->close(); for($i=0;$i<count($arraydb);$i++){ $current .= date("Y-m-d H:i:s").' '.'Пользователь '.$arraydb[$i]['username'].' ('.$arraydb[$i]['first_name'].' '.$arraydb[$i]['last_name'].') id='.$arraydb[$i]['uid'].' tel='.$arraydb[$i]['tel'].' block='.$arraydb[$i]['ban'].PHP_EOL; if($i == 0) $notice = urlencode('Пользователь @'.$arraydb[$i]['username'].' ('.$arraydb[$i]['first_name'].' '.$arraydb[$i]['last_name'].') id='.$arraydb[$i]['uid'].' tel='.$arraydb[$i]['tel'].' block='.$arraydb[$i]['ban'].$newstr.$newstr); else $notice = $notice.urlencode('Пользователь @'.$arraydb[$i]['username'].' ('.$arraydb[$i]['first_name'].' '.$arraydb[$i]['last_name'].') id='.$arraydb[$i]['uid'].' tel='.$arraydb[$i]['tel'].' block='.$arraydb[$i]['ban'].$newstr.$newstr); } $answer = file_get_contents($siteurl.'/sendtg.php?id='.$adminId.'&message='.$notice); $answerarr = json_decode($answer, TRUE); $realanswer = 'false'; if($answerarr["ok"] == true) $realanswer = 'true'; $current .= date("Y-m-d H:i:s").' '.'Уведомление админу(инфа о всех юзерах) отправлено:'.$realanswer.PHP_EOL; } if($txt[0] == '/block'){ if($txt[1][0] != '@') $result = $connectdb->query("SELECT * FROM `registeruser` WHERE uid = '".$txt[1]."' limit 1"); else $result = $connectdb->query("SELECT * FROM `registeruser` WHERE username = '".substr($txt[1], 1)."' limit 1"); $row = $result->fetch_array(); if($row != null){ $current .= date("Y-m-d H:i:s").' '.'Блокируем пользователю изменение телефона:'.$txt[1].PHP_EOL; if($txt[1][0] != '@') $connectdb->query("UPDATE `registeruser` SET `ban`='".(0)."' WHERE `uid`='".$txt[1]."'"); else $connectdb->query("UPDATE `registeruser` SET `ban`='".(0)."' WHERE `username`='".substr($txt[1], 1)."'"); $notice = urlencode('Блокируем пользователю изменение телефона:'.$txt[1]); } else { $current .= date("Y-m-d H:i:s").' '.'Пользователь:'.$txt[1].' не найден.'.PHP_EOL; $notice = urlencode('Пользователь:'.$txt[1].' не найден.'); } $answer = file_get_contents($siteurl.'/sendtg.php?id='.$adminId.'&message='.$notice); $answerarr = json_decode($answer, TRUE); $realanswer = 'false'; if($answerarr["ok"] == true) $realanswer = 'true'; $current .= date("Y-m-d H:i:s").' '.'Уведомление админу(блокировка изменения телефона) отправлено:'.$realanswer.PHP_EOL; } if($txt[0] == '/unblock'){ if($txt[1][0] != '@') $result = $connectdb->query("SELECT * FROM `registeruser` WHERE uid = '".$txt[1]."' limit 1"); else $result = $connectdb->query("SELECT * FROM `registeruser` WHERE username = '".substr($txt[1], 1)."' limit 1"); $row = $result->fetch_array(); if($row != null){ $current .= date("Y-m-d H:i:s").' '.'Разблокируем пользователю изменение телефона:'.$txt[1].PHP_EOL; if($txt[1][0] != '@') $connectdb->query("UPDATE `registeruser` SET `ban`='".(10)."' WHERE `uid`='".$txt[1]."'"); else $connectdb->query("UPDATE `registeruser` SET `ban`='".(10)."' WHERE `username`='".substr($txt[1], 1)."'"); $notice = urlencode('Разблокируем пользователю изменение телефона:'.$txt[1]); } else { $current .= date("Y-m-d H:i:s").' '.'Пользователь:'.$txt[1].' не найден.'.PHP_EOL; $notice = urlencode('Пользователь:'.$txt[1].' не найден.'); } $answer = file_get_contents($siteurl.'/sendtg.php?id='.$adminId.'&message='.$notice); $answerarr = json_decode($answer, TRUE); $realanswer = 'false'; if($answerarr["ok"] == true) $realanswer = 'true'; $current .= date("Y-m-d H:i:s").' '.'Уведомление админу(разблокировка изменения телефона) отправлено:'.$realanswer.PHP_EOL; } if($txt[0] == '/readme'){ $notice = 'README.txt'; $answer = file_get_contents($siteurl.'/sendtg.php?id='.$adminId.'&document='.$notice); $answerarr = json_decode($answer, TRUE); $realanswer = 'false'; if($answerarr["ok"] == true) $realanswer = 'true'; $current .= date("Y-m-d H:i:s").' '.'Файл README.txt админу отправлен:'.$realanswer.PHP_EOL; } $current .= PHP_EOL; } ?>
И для юзера:
<?php $newstr = PHP_EOL; $current .= date("Y-m-d H:i:s").' '.'Начата Юзер-сессия с ID :'.$chatId.' от имени @'.$chatUd.PHP_EOL; $j=0; $txt; for($i=0;$i<strlen($text);$i++){ if($text[$i] != ' ') if($txt[$j] != null) $txt[$j]=$txt[$j].$text[$i]; else $txt[$j]=$text[$i]; else $j++; } if($txt[0] == '/help'){ $notice = urlencode('Справка по коммандам:'.$newstr); $notice = $notice.urlencode($newstr); $notice = $notice.urlencode('/help -> выведет список административных команд.'.$newstr); $notice = $notice.urlencode('/admin сообщение-> сообщение администратору.'.$newstr); $notice = $notice.urlencode('/phone пароль телефон -> обновить или добавить рабочий номер(служебный внутренний на ОДО Фармин).'); $answer = file_get_contents($siteurl.'/sendtg.php?id='.$chatId.'&message='.$notice); $answerarr = json_decode($answer, TRUE); $realanswer = 'false'; if($answerarr["ok"] == true) $realanswer = 'true'; $current .= date("Y-m-d H:i:s").' '.'Уведомление юзеру(HELP) отправлено:'.$realanswer.PHP_EOL; } if(($txt[0] != '/help') && ($txt[0] != '/phone') && ($txt[0] != '/admin')){ $notice = urlencode('Неправильный запрос.'.$newstr); $notice = $notice.urlencode('Наберите /help для справки по коммандам.'); $answer = file_get_contents($siteurl.'/sendtg.php?id='.$chatId.'&message='.$notice); $answerarr = json_decode($answer, TRUE); $realanswer = 'false'; if($answerarr["ok"] == true) $realanswer = 'true'; $current .= date("Y-m-d H:i:s").' '.'Уведомление юзеру(NO COMMAND) отправлено:'.$realanswer.PHP_EOL; } if($txt[0] == '/phone'){ $result = $connectdb->query("SELECT * FROM `registeruser` WHERE uid = '".$chatId."' limit 1"); $row = $result->fetch_array(); $current .= date("Y-m-d H:i:s").' '.'Пользователь :'.$chatId.' изменяет телефон.'.PHP_EOL; if($row['ban'] > 0){ if($txt[1] == $row['password']){ $current .= date("Y-m-d H:i:s").' '.'Изменение телефона успешно.'.PHP_EOL; $notice = urlencode('Изменение телефона успешно.'); $connectdb->query("UPDATE `registeruser` SET `tel`='".$txt[2]."' WHERE `uid`='".$chatId."'"); $notice2 = urlencode('Пользователь:'.$chatId.' изменил телефон на '.$txt[2].'.'.$newstr); $answer = file_get_contents($siteurl.'/sendtg.php?id='.$adminId.'&message='.$notice2); $answerarr = json_decode($answer, TRUE); $realanswer = 'false'; if($answerarr["ok"] == true) $realanswer = 'true'; $current .= date("Y-m-d H:i:s").' '.'Уведомление админу(изменение номера) отправлено:'.$realanswer.PHP_EOL; } else { $current .= date("Y-m-d H:i:s").' '.'Изменение телефона неудачно. Пароль не верен. Осталось попыток:'.($row['ban']-1).PHP_EOL; $notice = urlencode('Изменение телефона неудачно. Пароль не верен. Осталось попыток:'.($row['ban']-1)); $connectdb->query("UPDATE `registeruser` SET `ban`='".($row['ban']-1)."' WHERE `uid`='".$chatId."'"); $notice2 = urlencode('Пользователь:'.$chatId.' осталось попыток:'.($row['ban']-1).$newstr); if(($row['ban']-1) == 0){ $notice2 = $notice2.urlencode('ПОЛЬЗОВАТЕЛЬ ЗАБЛОКИРОВАН'.$newstr); } $answer = file_get_contents($siteurl.'/sendtg.php?id='.$adminId.'&message='.$notice2.$notice); $answerarr = json_decode($answer, TRUE); $realanswer = 'false'; if($answerarr["ok"] == true) $realanswer = 'true'; $current .= date("Y-m-d H:i:s").' '.'Уведомление админу(не верный пароль) отправлено:'.$realanswer.PHP_EOL; } } else { $current .= date("Y-m-d H:i:s").' '.'Вам была заблокирована данная процедура. Обратитесь к администратору командой /admin сообщение'.PHP_EOL; $notice = urlencode('Вам была заблокирована данная процедура. Обратитесь к администратору командой /admin сообщение'); } $answer = file_get_contents($siteurl.'/sendtg.php?id='.$chatId.'&message='.$notice); $answerarr = json_decode($answer, TRUE); $realanswer = 'false'; if($answerarr["ok"] == true) $realanswer = 'true'; $current .= date("Y-m-d H:i:s").' '.'Уведомление юзеру(изменение номера) отправлено:'.$realanswer.PHP_EOL; } if($txt[0] == '/admin'){ for($i=1;$i<count($txt);$i++) if($i==1) $notice = urlencode('Пользователь: @'.$chatUd.$newstr.$txt[$i].' '); else $notice = $notice.urlencode($txt[$i].' '); $answer = file_get_contents($siteurl.'/sendtg.php?id='.$adminId.'&message='.$notice); $answerarr = json_decode($answer, TRUE); $realanswer = 'false'; if($answerarr["ok"] == true) $realanswer = 'true'; $current .= date("Y-m-d H:i:s").' '.'Уведомление админу(мессендж от юзера) отправлено:'.$realanswer.PHP_EOL; if($realanswer == 'true') $notice = urlencode('Сообщение админу отправлено.'); else $notice = urlencode('Отправка не удалась.'); $answer = file_get_contents($siteurl.'/sendtg.php?id='.$chatId.'&message='.$notice); $answerarr = json_decode($answer, TRUE); $realanswer = 'false'; if($answerarr["ok"] == true) $realanswer = 'true'; $current .= date("Y-m-d H:i:s").' '.'Уведомление юзеру(статус отправки) отправлено:'.$realanswer.PHP_EOL; } $current .= PHP_EOL; ?>
Ну и собственно описание работы бота:
1 |
Бот для телеграмм(@farmin_ats_bot) Как это работает: При обращениее к mainapi.php методом POST, формат запроса json: { "usernum": "563", "calleridname": "xyваыываы аыаыz", "calleridnum": "666", "time": "21:21:21", "key": "*************************" } Проверяется id пользователя в MySQL, которому соответствует номер 563. Если такой пользователь существует, на данный id передается сообщение вида: "В 21:21:21 вам звонил xyваыываы аыаыz<666>" Для того, чтобы передать сообщение пользователю, необходимо получить его уникальный id. При регистрации пользователя боту передается сообщение "/start", получив его бот пишет в базу данных указанные Имя, Фамилию, Username, Id, текущее время в базу данных. В случае повторной отправки "/start", информация обновится. При этом администратору(Id указан в файле настроек) приходит мессендж о регистрации пользователя. Далее Администратору необходимо проверить, привязан ли номер телефона пользователю(при повторной регистрации номер не затирается) командой "/tel пользователь", при этом здесь и далее под пользователем понимается его Id или @username. также можно проверить информацию о всех пользователях командой "/users". Если номер не привязан, его необходимо привязать командой "/newuser пользователь номер", по которой в БД будет записан номер соответствующему пользователю. Внимание: номер должен быть уникальным, в противном случае уведомление будет доставлено только первому пользователю. Если номер уже привязан к другому пользователю, его необходимо затереть командой "/deluser пользователь" Список всех команд выводится по команде "/help", набор команд для пользователя и администратора отличается и прописан в usersession.php и adminsession.php соответственно. Пользователю доступна обратная связь с админом командой "/admin сообщение(допустимо множество слов)" Отключено по соображениям безопасности(пользователь может установить себе любой номер): для пользователя команда "/phone пароль номер", которая устанавливает ему номер телефона. Пароль по умолчанию не задается, соответственно пользователь воспользоваться данной командой не сможет. для администратора команды "/block пользователь" и "/unblock пользователь", которые установят количество попыток ввода пароля в 0 и 10 соответственно. для администратора команда "/readme" вышлет данное описание на Telegramm. Техническая часть: Структура бота: index.php - страничка отбойник для URL[програмной роли не выполняет] settings.php - файл настроек sendtg.php - API для отправки данных на API Telegramm, зависима от settings.php [запрос sendtg.php?id=236255988&message=блаблабла] send.html - страничка теста отправки запросов с помощью sendtg.php [програмной функции не выполняет] set.php - API для регистрации бота(и ssl-сертификата) на сервере Telegramm, зависит от settings.php [без запроса. с сертификатом Lets Encrypt не заработало, самоподписанный на 10 лет норм работает] mainapi.php - API для уведомлений пользователя по номеру телефона, запросы принимает в json, зависит от settings.php [запрос curl -k -H "Content-Type: application/json" -X POST -d '{"usernum":"563","calleridname":"xyваыываы аыаыz","calleridnum":"666","time":"21:21:21","key":"КЛЮЧ"}' https://tgsocks.sergdudko.tk/mainapi.php] пример использования в Asterisk: exten => s,n,SYSTEM(curl -k -H "Content-Type: application/json" -X POST -d '{"usernum":"${ARG1}","calleridname":"${CALLERID(name)}","calleridnum":"${CALLERID(number)}","time":"${STRFTIME(${EPOCH},,%H:%M:%S)}","key":"КЛЮЧ"}' https://tgsocks.sergdudko.tk/mainapi.php) webhook.php - API для обратной связи от Telegramm, обработка команды /start, зависит от settings.php, adminsession.php, usersession.php [принимает запрос в json: {"ok":true,"result":{"message_id":482,"from":{"id":413290793,"first_name":"ATS","username":"farmin_ats_bot"},"chat":{"id":236255988,"first_name":"Name","last_name":"V.","username":"Namev","type":"private"},"date":1501367615,"text":"asdas ass"}}] adminsession.php - описание поведения бота с администратором [инклудится в webhook.php] usersession.php - описание поведения бота с юзером [инклудится в webhook.php] log/ - папка с логами по дате mailer/ - обработчик remote smtp mailer/mailer.php - API для входящих запросов отправки почты, зависит от smtp-func.php [запрос mailer.php?message=блаблабла] mailer/smtp-func.php - API для remote smtp [инклудится в mailer.php] mailer/mailform.php - страничка теста почты для отправки с помощью mailer.php[програмной функции не выполняет] mailer/mailform.html - форма теста почты [инклудится в mailform.php, програмной функции не выполняет] files/ - папка с файлами(на данный момент с текущим описанием функционала) files/README.txt - данное описание Структура MySQL: `База Данных`.`registeruser` - InnoDB/UTF8/utf8_general_ci: id,date,time,username,uid,first_name,last_name,tel,password,ban type: id,ban - int type: date,time,username,uid,first_name,last_name,tel,password - varchar(255) id - автоинкремент tel - 'null' по умолчанию ban - 10 по умолчанию Дополнение командами: $chatId - ID юзера из ответа $chatUd - @имя юзера из ответа $fName - реальное имя юзера из ответа $lName - реальная фамилия юзера из ответа $text - текст всего сообщения $adminId - ID администратора из настроек Текст сообщения $text разбивается на слова(1 промежуточный пробел вырезается) в массив $txt[], где $txt[0] - команда, таким образом добавление новой команда осуществляется вставкой кода: if($txt[0] == '/команда'){ код } При этом в коде могут использоваться операнды(формат по умолчанию), запись в лог: $current .= date("Y-m-d H:i:s").' '.'ТЕКСТ СООБЩЕНИЯ'.PHP_EOL; запрос в БД: $connectdb->query("ТЕКСТ ЗАПРОСА"); сообщение в телеграмм: file_get_contents($siteurl.'/sendtg.php?id=@ИМЯ ИЛИ ИД&message=СООБЩЕНИЕ); при этом сообщение должно быть в urlencode(ТЕКСТ); если присвоить file_get_contents() переменной, Telegramm вернет ответ в json, его можно разобрать на массив json_decode(ПЕРЕМЕННАЯ, TRUE); аналогично можно отправить email: file_get_contents($siteurl.'/mailer/mailer.php?message=СООБЩЕНИЕ); отправка файла в телеграмм из папки files: file_get_contents($siteurl.'/sendtg.php?id=@ИМЯ ИЛИ ИД&document=имя_файла.txt); и т.д. Файл настроек settings.php: //Настройка бота $APIKEY - ключ API полученный от @BotFather $siteurl - url сайта(только https) $cert - путь к ssl сертификату $adminId - id администратора $fileurl - путь к каталогу с сайтом //Настройка MySQL: $dbaddr - адрес БД $dbuser - имя пользователя БД $dbpass - пароль пользователя БД $db - наименование БД //Настройка mainapi $mainkey - ключ для работы с mainapi.php (указывается в json-запросе как {"key":"КЛЮЧ"}) *ДОПОЛНИТЕЛЬНО: Выставить права на папку log/ rw(для пользователя apache или того от кого запущен веб-сервер) Указать date.timezone = 'Europe/Minsk' в php.ini 30.07.17 ИСКЛЮЧЕНО: post-json-xml.php - API для отправки json-данных на указанный url [функция http_post($url, $json)] убрана зависимость от него sendtg.php добавлена команда "/readme" администратору