Телеграм бот, для работы с Asterisk или как пробросить номер через VoIP-сервер.

В офисе установлена 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>';
 
?>

Скрыть содержимое папок можно через веб-сервер

или .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 чата для админа). Для регистрации необходимо боту отправить команду

.

Для отправки сообщения написал скрипт, который получает 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)

Куда писать — если вы хотите получать уведомления о всех входящих вызовах, в тот контекст

, который указан у вас в настройках транка для USER Context

, либо во вложенный контекст, который будет выполняться во всех входящих контекстах(транков у вас может быть несколько и контексты для них разные, например у меня для определения номера во все входящие контексты вложен один и тот же, туда же можно добавить уведомление о вызовах). Если только при переадресации, то соответственно в контекст переадресации.

Проверили, уведомления пошли. Далее пишу команды для администратора(для работы прямо из телеграма):

Показать

<?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;
?>

Ну и собственно описание работы бота:

Бот для телеграмм(@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" администратору

 

Ну и пара скринов: