
No artigo anterior, descrevi a implementação da escolha do local de residência do usuário ao se cadastrar no meu bot de telegramas , que criei inspirado na ideia de "Telefonia" . No mesmo artigo, descreverei a integração do bot com o Asterisk .
Pelo que?
Muitas pessoas não gostam do fato de que chamadas em grupo não podem ser feitas no Telegram.
Bem, não use o Viber?
Também há vários casos para essa implementação, por exemplo:
- Para audioconferências anônimas, quando você não quer "iluminar" o seu número ou id entre os participantes da conferência (um sábado de hackers ou um clube de alcoólatras anônimos vem à mente). Não há necessidade de estar em nenhum grupo, comunidade, canal
- Quando você não sabe quem se conectará à conferência, mas precisa restringir o acesso com uma senha
- Todas as delícias do Asterisk: gerenciamento de conferências (mudo / umute, chute), audioconferência híbrida com clientes cadastrados no asterisk, telegrama e PSTN. Você pode economizar muito em ligações internacionais
- Organização de callback corporativo via telegrama, etc.
Muitas opções vêm à mente, existem muitas delas, limitadas apenas pela imaginação. Depois de muitos anos trabalhando com o Asterisk, acredito que o principal é fazer uma ligação para ele, e então você pode fazer o que for adequado com ele, até mandá-lo para o espaço.
Pacote VoIP Asterisk VoIP-Telegram
O pacote VoIP em si é implementado graças à biblioteca tg2sip . Seu uso é descrito no próprio repositório na seção Uso. Existem mais alguns artigos sobre personalização. Existe até uma imagem Docker .
Uma descrição desse pacote está além do escopo deste artigo.
A única nuance que gostaria de expressar é que você não pode chamar telegram_id, cujo número não está em sua agenda de contatos. Portanto, você precisa ligar para o número de telefone no qual o telegrama está registrado.
No meu botimplementadas como conferências de áudio públicas (Ethers), às quais qualquer pessoa pode se conectar, e conferências de áudio privadas com acesso por senha. Salas privadas / senhas são criadas pelos próprios usuários e podem usar o bot como uma plataforma para audioconferências, reuniões, etc.
Bot de telegrama de interação - Asterisk
O esquema de interação no meu bot é assim.
O usuário seleciona a sala desejada no menu do bot, o bot chama a função de interagir com o Asterisk via API passando os parâmetros de conexão na solicitação POST:
- número de telefone do assinante
- ID da sala de conferência
- identificador de chamadas para apresentação em uma sala de conferência
- idioma para emitir notificações ao usuário no sistema Asterisk no idioma nativo
Além disso, o Asterisk faz uma chamada de saída via canais de telegrama para o número especificado nos parâmetros de solicitação. Depois que o usuário atende a chamada, o Asterisk o conecta à sala apropriada.
Seria possível usar uma conexão direta do bot com o Astersik AMI , mas prefiro trabalhar através da API, quanto mais simples melhor.
API no lado do servidor Asterisk
Código API simples em python. Os arquivos .Call são usados para iniciar uma chamada
#!/usr/bin/python3
from flask import Flask, request, jsonify
import codecs
import json
import glob
import shutil
api_key = "s0m3_v3ry_str0ng_k3y"
app = Flask(__name__)
@app.route('/api/conf', methods= ['POST'])
def go_conf():
content = request.get_json()
##
if not "api_key" in content:
return jsonify({'error': 'Authentication required', 'message': 'Please specify api key'}), 401
if not content["api_key"] == api_key:
return jsonify({'error': 'Authentication failure', 'message': 'Wrong api key'}), 401
##
if not "phone_number" in content or not "room_name" in content or not "caller_id" in content:
return jsonify({'error': 'not all parameters are specified'}), 400
if not "lang" in content:
lang = "ru"
else:
lang = content["lang"]
phone_number = content["phone_number"]
room_name = content["room_name"]
caller_id = content["caller_id"]
calls = glob.glob(f"/var/spool/asterisk/outgoing/*-{phone_number}*")
callfile = "cb_conf-" + phone_number + "-" + room_name + ".call"
filename = "/var/spool/asterisk/" + callfile
if calls:
return jsonify({'message': 'error', "text": "call already in progress"})
with codecs.open(filename, "w", encoding='utf8') as f:
f.write("Channel: LOCAL/" + phone_number + "@telegram-out\n")
f.write("CallerID: <" + caller_id + ">\n")
f.write("MaxRetries: 0\nRetryTime: 5\nWaitTime: 30\n")
f.write("Set: LANG=" + lang + "\nContext: conf-in\n")
f.write("Extension: " + room_name + "\nArchive: Yes\n")
shutil.chown(filename, user="asterisk", group="asterisk")
shutil.move(filename, "/var/spool/asterisk/outgoing/" + callfile)
return jsonify({'message': 'ok'})
if __name__ == '__main__':
app.run(debug=True,host='0.0.0.0', port=8080)
Neste caso, o plano de discagem do Asterisk em uma forma simples se parece com isto:
[telegram-out]
exten => _+.!,1,NoOp()
same => n,Dial(SIP/${EXTEN}@telegram)
exten => _X!,1,NoOp()
same => n,Dial(SIP/+${EXTEN}@telegram)
[conf-in]
exten => _.!,1,NoOp()
same => n,Answer()
same => n,Wait(3)
same => n,Playback(beep)
same => n,Set(CHANNEL(language)=${LANG})
same => n,ConfBridge(${EXTEN})
same => n,Hangup
Esta API pode ser usada em outros casos, por exemplo, para organizar o mesmo botão de callback "Call me back", etc.
Função de chamada API
telephony_api.py
import requests, json
# example.com url
url = "http://example.com:8080/api/conf"
api_key = "s0m3_v3ry_str0ng_k3y"
def go_to_conf(phone_number, room_name, caller_id, lang="ru"):
payload = {}
payload["phone_number"] = phone_number
payload["room_name"] = room_name
payload["caller_id"] = caller_id
payload["lang"] = lang
payload["api_key"] = api_key
headers = {
'content-type': "application/json",
'cache-control': "no-cache",
}
try:
response = requests.request("POST", url, data=json.dumps(payload), headers=headers, timeout=2, verify=False)
if "call already in progress" in response.text:
return False, ". ."
elif "error" in response.text:
print(response.text)
return False, ". . ."
else:
return True, response.text
except:
return False, ". . ."
Essas duas ferramentas já são suficientes para integração em seu bot, envolva-as em sua lógica e use-as.
Um exemplo de um bot para iniciar uma chamada para uma sala de conferência
#!/usr/bin/python3.6
import telebot
from telephony_api import go_to_conf
bot = telebot.TeleBot("TOKEN")
pnone_number = "799999999999"# , telegram
@bot.message_handler(content_types=['text'])
def main_text_handler(message):
if message.text == " ":
bot.send_message(message.chat.id, "Ok. telegram , ")
func_result, func_message = go_to_conf(pnone_number, "ROOM1", "Bob", "ru")
if not func_result:
bot.send_message(chat_id=message.chat.id, text=func_message)
if __name__ == "__main__":)
print("bot started")
bot.polling(none_stop=True)
Neste exemplo, o número de telefone é definido estaticamente, mas na realidade, por exemplo, você pode fazer solicitações ao banco de dados para correspondência de message.chat.id - o número de telefone.
Espero que meu artigo ajude alguém a criar projetos legais e, por sua vez, compartilhá-los com a comunidade.