Сергей Маликов
25.08.2019
21665

Отправка сообщений о пропущенных вызовах в Telegram для Asterisk Vanilla и Freepbx.

Отправка сообщений в Telegram о пропущенных вызовах позволит не упустить ни одного важного звонка. В статье рассматривается создание простой системы уведомлений. Для этого необходимо: зарегистрировать в мессенджере telegram своего бота, написать agi скрипт, и внести изменения в диалплан. Регистрация собственного бота в Telegram. Вначале необходимо зарегистрировать своего бота. Для этого нужно зайти в Telegram и […]

Пропущенные вызовы в Telegram для Asterisk Vanilla и Freepbx

Отправка сообщений в Telegram о пропущенных вызовах позволит не упустить ни одного важного звонка. В статье рассматривается создание простой системы уведомлений. Для этого необходимо: зарегистрировать в мессенджере telegram своего бота, написать agi скрипт, и внести изменения в диалплан.

Регистрация собственного бота в Telegram.

Вначале необходимо зарегистрировать своего бота. Для этого нужно зайти в Telegram и начать чат с @BotFather. Откроется список поддерживаемых команд, отправить команду /newbot.

Добавление нового бота – чат с @BotFather
Добавление нового бота – чат с @BotFather

Затем выбрать название бота(name) и его имя(username), по которому бот будет доступен для поиска. По названию нет особых требований, имя бота обязательно должно быть уникально и оканчиваться на «bot». Боту можно добавить описание и аватар. По окончанию процесса создания бота,@BotFather отправит токен созданного бота. Так как токен предназначен для управления и работы с ботом через HTTP-запросы, @BotFather выводит предупреждение, что токен необходимо хранить в безопасности и не передавать.Также, скомпрометированный токен можно сгенерировать заново.

Добавление нового бота – полученный токен @TestGramBot

Добавление нового бота – полученный токен @TestGramBot

По умолчанию в настройках бота включен режим приватности – все сообщения, отправляемые определенному пользователю, не видны остальным участникам переписки.

Для того, чтобы @TestGramBot мог отправлять сообщения какому-либо оператору в чат, или в группу необходимо узнать chatid оператора или созданной группы. Оператору необходимо войти в свой аккаунт в телеграм, и начать диалог с @TestGramBot (нажать start или отправить /start, и, затем отправить сообщение, например Hello).

Инициирование диалога с @TestGramBot

Инициирование диалога с @TestGramBot

Если после этого необходимо открыть браузер и перейти по адресу https://api.telegram.org/bot[ТОКЕН_БОТА]/getUpdates. Например https://api.telegram.org/bot123411111:AAABBBbGQDz1111_AAAAbb00aaa1111111/getUpdates

В пришедшем ответе, найдите поле chat, а в нём —  id.  Если  type: private это внутренний chatid (id контакта в телеграме).

Определение chatid оператора или группы

Определение chatid оператора или группы

Создание agi скрипта на php.

Узнав chatid операторов, необходимо создать php скрипт в папке /var/lib/asterisk/agi-bin/ /var/lib/asterisk/agi-bin/telegram.php. По умолчанию файл создается от пользователя root c правами 644. Скрипт должен иметь права 664, владелец:asterisk, группа:asterisk. Также необходимо разрешить выполнение скрипта командой chmod +x /var/lib/asterisk/agi-bin/telegram.php.

В скрипт будут передаваться два параметра – номер звонившего и дата звонка. Данные для отправки занесем в переменную $text. Для отправки в телеграм также потребуется прокси. В переменной $token необходимо присвоить токен ранее созданного бота, $chatid – id оператора в телеграм, которому будут отправляться сообщения. Сообщение отправляется с помощью post запроса php функцией curl_exec().

#!/usr/bin/php -q
<?php
require('phpagi.php'); //подключаем библиотеку phpagi.php
$agi = new AGI(); 
$stdin = fopen('php://stdin', 'r');
$stdout = fopen('php://stdout', 'w');
/*
Вынесем отправку в телеграм в отдельную функцию send, последний параметр укажем как необязательный т.к. для тестовых сообщений используются бесплатные прокси – без пароля
*/
function send($token, $chatid, $text, $proxy, $auth=NULL){
$ch=curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.telegram.org/bot'.$token.'/sendMessage');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'chat_id='.$chatid.'&text='.urlencode($text));
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
curl_setopt($ch, CURLOPT_PROXY, $proxy);
if($auth){
	curl_setopt($ch, CURLOPT_PROXYUSERPWD, $auth);
}
// Отправляем сообщение
$result=curl_exec($ch);
/*
Для отладки в скрипте можно добавить dump какой-либо переменной, например $result. Результат вывода var_dump($result) отобразится в консоли Астериска при включенном режиме отладки agi -  agi set debug on
*/
var_dump($result);
curl_close($ch);
return $result;
}
// Токен бота и идентификатор чата
$token='735067350:AAFPVUdGQDz7350_TchKxvAOhr38wU7350';
//id чата оператора в telegram
$chatid = 213213213;
/* Текст сообщения. Переданные в скрипт аргументы (номер звонящего и дата звонка) - $argv[1]  и $argv[2] */
$text='Звонил ' . $argv[1] . ' Дата ' .  $argv[2];
// Настройки прокси
$proxy='23.23.179.254:3128';
//$auth='login:password'; //пароль, если прокси – с паролем, в формате 'login:password'
// Отправка сообщения в личный Telergam чат
send($token, $chatid, $text, $proxy);
fclose ($stdin);
fclose ($stdout);
exit(0);
?>

Изменение диалплана.

Также необходимо добавить в диалплан вызов AGI скрипта /var/lib/asterisk/agi-bin/telegram.php. Предположим, что все вызовы поступают в голосовое меню. Если используется freepbx необходимо отредактировать файл /etc/asterisk/extensions_override_freepbx.conf и добавить контекст [ivr-1], где 1-номер ivr. Если используется Asterisk Vanilla — /etc/asterisk/extensions.conf.

Id голосового меню отображается при его редактировании в адресной строке
Id голосового меню отображается при его редактировании в адресной строке

В экстеншене h (hangup), который выполняется после завершения вызова, вызовем agi-скрипт, который отправит сообщение о пропущенном вызове в телеграм если на звонок не ответили (noanswer) или звонок был завершен с сообщением “занято”; в скрипт также передаются 2 параметра – номер звонившего и дата звонка.

[ivr-1] 
[ivr-1]
exten => h,1,ExecIf($["${DIALSTATUS}" = "NOANSWER"] | $["${DIALSTATUS}" = "BUSY"])?AGI(telegram.php, ${CALLERID(num)}, ${STRFTIME(${EPOCH},,%Y.%m.%d-%H:%M:%S)})
same  => n,Hangup()

После сохранения, для применения настроек необходимо в консоли Астериска сделать релоад модулей:

аsterisk –rvvvv    — для входа в консоль

 (в CLI) dialplan reload

Пример сообщения о пропущенном звонке, отправленного ботом в telegram
Пример сообщения о пропущенном звонке, отправленного ботом в telegram
Подписаться
Уведомить о
guest
16 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
andrey
andrey
24.02.2020 11:54

Добрый день, а если нет необходимости получать с основного транка все звонки, а только по своему номеру внутренему .
Я так понимаю тогда мы правим
/etc/asterisk/extensions_additional.conf
[ext-local]
Что нам сюда нужно перенести чтоб заработало?
Спасибо!

Sergey Malikov
Sergey Malikov
25.02.2020 14:04
Ответить на  andrey

Добрый день.

Файл /etc/asterisk/extensions_additional.conf править не нужно, т.к. изменения в него вносятся только через веб-админку.

Необходимо редактировать файл
/etc/asterisk/extensions_override_freepbx.conf , добавив туда

[ext-local]
exten => h,1,ExecIf($[$[«$CDR(disposition)»=»NO ANSWER»] & $[${DEXTEN}=333]])?AGI(telegram.php, ${CALLERID(num)}, ${STRFTIME(${EPOCH},,%Y.%m.%d-%H:%M:%S)})
exten => h,n,Macro(hangupcall,)

333 — внутренний номер, по которому отслеживаются пропущенные)
и применить настройки (asterisk -rx ‘dialplan reload’ )

Андрей
Андрей
05.08.2020 15:08
Ответить на  Sergey Malikov

Добрый день.
В файл /etc/asterisk/extensions_override_freepbx.conf добавил:

[ext-local]
exten => h,1,ExecIf($[$[«$CDR(disposition)»=»NOANSWER»] & $[${DEXTEN}=229]])?AGI(telegram.php, ${CALLERID(num)}, ${STRFTIME(${EPOCH},,%Y.%m.%d-%H:%M:%S)})
exten => h,n,Macro(hangupcall,)

Применил настройки asterisk -r ‘dialplan reload’

Имитирую пропущенные вызовы, сообщения не приходят. Сам скрипт telegram.php рабочий, уведомления отправляет, проверял запуском в консоли. В самом CLI некаких упоминаний об telegram.php или extensions_override_freepbx.conf.
Будто asterisk не читает extensions_override_freepbx.conf.

В чем может быть проблема? Очень прошу вашей помощи.

Sergey Malikov
Sergey Malikov
05.08.2020 15:35
Ответить на  Андрей

Попробуйте выполнить следующее:

Установка необходимых прав на директории
fwconsole chown
Выполнить релоад
asterisk -rx ‘core reload’

назначить права AGI скрипту
chmod +x /var/lib/asterisk/agi-bin/telegram.php

Войти в консоль включить дебаг AGI
asterisk -rvvv
agi set debug on

После этого протестировать(сделать пропущенный)
в консоли должно отобразиться сообщение о вызове скрипта — AGI(telegram.php).
Также, будет подробный вывод о работе AGI скрипта.

упоминаний об extensions_override_freepbx.conf в CLI и не должно быть

И, т.к. ранее телеграм был запрещен(а сейчас разрешен), в скрипте закомментировть опции, назначающие прокси.
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
curl_setopt($ch, CURLOPT_PROXY, $proxy);
if($auth){
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $auth);
}

Андрей
Андрей
05.08.2020 16:31
Ответить на  Sergey Malikov

Настройки прокси сразу же убрал. Сам php скрипт у меня работает. У меня проблема в том что asterisk не вызывает этот скрипт. права на выполнение telegram.php есть, владелец asterisk. В файле /etc/asterisk/extensions_override_freepbx.conf у меня прописано: [ext-local] exten => h,1,ExecIf($[$[«$CDR(disposition)»=»NOANSWER»] & $[${DEXTEN}=229]])?AGI(telegram.php,${CALLERID(num)},${STRFTIME(${EPOCH},,%Y.%m.%d-%H:%M:%S)}) exten => h,n,Macro(hangupcall,) Вошел в консоль и включил дебаг AGI asterisk -rvvv agi set debug on После этого звоню: Вывод в CLI: SIP/229-00000009 Internal Gosub(func-apply-sipheaders,s,1) start   — Executing [s@func-apply-sipheaders:1] NoOp(«SIP/229-00000009», «Applying SIP Headers to channel SIP/229-00000009») in new stack   — Executing [s@func-apply-sipheaders:2] Set(«SIP/229-00000009», «TECH=SIP») in new stack   — Executing [s@func-apply-sipheaders:3] Set(«SIP/229-00000009», «SIPHEADERKEYS=») in new stack   — Executing [s@func-apply-sipheaders:4] While(«SIP/229-00000009»,… Подробнее »

Sergey Malikov
Sergey Malikov
05.08.2020 17:19
Ответить на  Андрей
по логам не видно ничего про контекст ext-local. 
но выполняется h@from-internal:1
В 
/etc/asterisk/extensions_override_freepbx.conf
перепишите


[from-internal]
include => from-internal-noxfer
include => from-internal-xfer
include => bad-number ; auto-generated
;изменения
exten => h,1,...(добавить вызов agi скрипта)
;конец изменений
exten => h,n,Macro(hangupcall)


и кавычки в ExecIf (при сравнении) должны быть двойными -"" 
(также. лучше набирать вручную, потому что при может не совпадать кодировка)
и
asterisk -rx'dialplan reload'
asterisk -rvvv
CLI>agi set debug on
Андрей
Андрей
06.08.2020 14:53
Ответить на  Sergey Malikov

Спасибо огромное Вам, Сергей!
За статью и за отзывчивость в комментариях.
Наконец начал хоть что-то понимать))

Для тех кто вдруг столкнется с такими же трудностями как у меня:

Вот здесь $[$[«$CDR(disposition)»=»NO ANSWER»] пропущены фигурные({}) скобки перед CDR и ),
должно быть так: $[$[«${CDR(disposition)}»=»NO ANSWER»]

Виталий
Виталий
14.09.2021 00:07
Ответить на  Андрей

Как проверил скрипт telegram.php?

Сергей
Сергей
02.07.2020 16:07

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

Sergey Malikov
Sergey Malikov
13.07.2020 18:07
Ответить на  Сергей

В рамках данной статьи рассматривается только возможность реализации отправки уведомления в Телеграм при пропущенном вызове.

yetanother
yetanother
30.12.2020 19:55

а если звонок приходит на группу 777, например, что нужно добавить в конфиги freepbx?

Apostol
Apostol
07.04.2021 09:26

Добрый день.
Сразу прошу прощения за вопрос. Я только начал изучать asterisk и следовательно много чего не понятно. /etc/asterisk/extensions_override_freepbx.conf у меня пустой. Я правильно понимаю, что именно в него нужно добавлять строчки
[ivr-3]
[ivr-3]
exten => h,1,ExecIf($[«${DIALSTATUS}» = «NOANSWER»] | $[«${DIALSTATUS}» = «BUSY»])?AGI(telegram.php, ${CALLERID(num)}, ${STRFTIME(${EPOCH},,%Y.%m.%d-%H:%M:%S)})
same => n,Hangup()

Буду очень благодарен за помощь.

Sergey Malikov
Sergey Malikov
12.04.2021 17:43
Ответить на  Apostol

Добрый день. Файл /etc/asterisk/extensions_override_freepbx.conf и должен быть пустой, если в него ранее не добавляли диалплан, переписывающий системный (который находится в файле /etc/asterisk/extensions_additional.conf и который сгенерировался системой после применения Apply Config в веб-интерфейсе). В данном месте в статье опечатка — не нужно два раза указывать контекст ([ivr-3] [ivr-3]). Переписывать ivr-3 необходимо, если требуются оповещения о пропущенных в ivr с id 3, которые завершились на ivr. Для отслеживания неотвеченного в очереди нужно переписывать контекст ext-queues Также смотрите статьи https://voxlink.ru/kb/freepbx/missed-call-freepbx/ https://voxlink.ru/kb/asterisk-configuration/nastroika-uvedomlenii-o-propuschennyh/ Как посмотреть какой id у ivr-написано в статье-см.скриншот. При копировании диалплана с сайта и др.внешних источников имейте в виду, что может не… Подробнее »

Apostol
Apostol
12.04.2021 17:18

Добрый день. Подскажите, что в логах не так? Почему пересылка от бота не идет? \Спасибо — PJSIP/2296-00001334 Internal Gosub(func-apply-sipheaders,s,1) complete GOSUB_RETVAL=   — Called PJSIP/2296/sip:[email protected]:5060   — Local/2296@from-queue-00002f56;1 is ringing  == Using SIP RTP Audio TOS bits 184  == Using SIP RTP Audio TOS bits 184 in TCLASS field.  == Using SIP RTP Audio CoS mark 5  == Using SIP RTP Video TOS bits 136  == Using SIP RTP Video TOS bits 136 in TCLASS field.  == Using SIP RTP Video CoS mark 4   — Connected line update to Local/2296@from-queue-00002f56;2 prevented.   — PJSIP/2296-00001334 is ringing   — PJSIP/2296-00001334 is ringing   — Local/2296@from-queue-00002f56;1 is… Подробнее »

Дмитрий
Дмитрий
29.04.2021 12:35
Ответить на  Apostol

Здравствуйте. В логе можно выделить ряд причин такого поведения:

  1. 0?System — означает, что условие ExecIf — ложно и последующий оператор System не будет выполнен
  2. chat_id= — во всех строках отсутствует числовой идентификатор группы или чата в который нужно отправить сообщение
Виталий
Виталий
13.09.2021 22:59

Все привет. А как реализовать такую схему: есть очереди, когда оператор берет трубку, в телеграмм приходит номер вызывающего? Спасибо

Остались вопросы?

Я - Кондрашин Игорь, менеджер компании Voxlink. Хотите уточнить детали или готовы оставить заявку? Укажите номер телефона, я перезвоню в течение 3-х секунд.

VoIP оборудование


ближайшие курсы

10 доводов в пользу Asterisk

Распространяется бесплатно.

Asterisk – программное обеспечение с открытым исходным кодом, распространяется по лицензии GPL. Следовательно, установив один раз Asterisk вам не придется дополнительно платить за новых абонентов, подключение новых транков, расширение функционала и прочие лицензии. Это приближает стоимость владения станцией к нулю.

Безопасен в использовании.

Любое программное обеспечение может стать объектом интереса злоумышленников, в том числе телефонная станция. Однако, сам Asterisk, а также операционная система, на которой он работает, дают множество инструментов защиты от любых атак. При грамотной настройке безопасности у злоумышленников нет никаких шансов попасть на станцию.

Надежен в эксплуатации.

Время работы серверов некоторых наших клиентов исчисляется годами. Это значит, что Asterisk работает несколько лет, ему не требуются никакие перезагрузки или принудительные отключения. А еще это говорит о том, что в районе отличная ситуация с электроэнергией, но это уже не заслуга Asterisk.

Гибкий в настройке.

Зачастую возможности Asterisk ограничивает только фантазия пользователя. Ни один конструктор шаблонов не сравнится с Asterisk по гибкости настройки. Это позволяет решать с помощью Asterisk любые бизнес задачи, даже те, в которых выбор в его пользу не кажется изначально очевидным.

Имеет огромный функционал.

Во многом именно Asterisk показал какой должна быть современная телефонная станция. За многие годы развития функциональность Asterisk расширилась, а все основные возможности по-прежнему доступны бесплатно сразу после установки.

Интегрируется с любыми системами.

То, что Asterisk не умеет сам, он позволяет реализовать за счет интеграции. Это могут быть интеграции с коммерческими телефонными станциями, CRM, ERP системами, биллингом, сервисами колл-трекинга, колл-бэка и модулями статистики и аналитики.

Позволяет телефонизировать офис за считанные часы.

В нашей практике были проекты, реализованные за один рабочий день. Это значит, что утром к нам обращался клиент, а уже через несколько часов он пользовался новой IP-АТС. Безусловно, такая скорость редкость, ведь АТС – инструмент зарабатывания денег для многих компаний и спешка во внедрении не уместна. Но в случае острой необходимости Asterisk готов к быстрому старту.

Отличная масштабируемость.

Очень утомительно постоянно возвращаться к одному и тому же вопросу. Такое часто бывает в случае некачественного исполнения работ или выбора заведомо неподходящего бизнес-решения. С Asterisk точно не будет такой проблемы! Телефонная станция, построенная на Asterisk может быть масштабируема до немыслимых размеров. Главное – правильно подобрать оборудование.

Повышает управляемость бизнеса.

Asterisk дает не просто набор полезных функций, он повышает управляемость организации, качества и комфортности управления, а также увеличивает прозрачность бизнеса для руководства. Достичь этого можно, например, за счет автоматизации отчетов, подключения бота в Telegram, санкционированного доступа к станции из любой точки мира.

Снижает расходы на связь.

Связь между внутренними абонентами IP-АТС бесплатна всегда, независимо от их географического расположения. Также к Asterisk можно подключить любых операторов телефонии, в том числе GSM сим-карты и настроить маршрутизацию вызовов по наиболее выгодному тарифу. Всё это позволяет экономить с первых минут пользования станцией.