Im vorherigen Artikel habe ich die Implementierung der Wahl des Wohnorts des Benutzers bei der Registrierung in meinem Telegramm- Bot beschrieben, den ich inspiriert von der Idee der "Telefonie" erstellt habe . Im selben Artikel werde ich die Integration des Bots in Asterisk beschreiben .
Wozu?
Vielen Menschen gefällt die Tatsache nicht, dass Gruppenanrufe nicht per Telegramm getätigt werden können.
Verwenden Sie Viber nicht?
Es gibt auch eine Reihe von Fällen für eine solche Implementierung, zum Beispiel:
- Bei anonymen Audiokonferenzen, wenn Sie Ihre Nummer oder ID unter den Konferenzteilnehmern nicht "aufleuchten" möchten (der Sabbat der Hacker oder der Club der anonymen Alkoholiker fällt Ihnen ein). Sie müssen nicht in einer Gruppe, Community oder einem Kanal sein
- Wenn Sie nicht wissen, wer überhaupt eine Verbindung zur Konferenz herstellen wird, Sie den Zugriff jedoch mit einem Kennwort einschränken müssen
- Alle Freuden von Asterisk: Konferenzmanagement (Stumm / Umute, Kick), Hybrid-Audiokonferenzen mit Kunden, die auf Asterisk, Telegramm und PSTN registriert sind. Bei Auslandsgesprächen können Sie viel sparen
- Organisation von Unternehmensrückrufen per Telegramm usw.
Es gibt eine Reihe von Optionen, von denen es viele gibt, die nur durch die Vorstellungskraft begrenzt sind. Nach vielen Jahren der Arbeit mit Asterisk glaube ich, dass die Hauptsache darin besteht, einen Anruf zu tätigen, und dann können Sie alles tun, was dazu passt, und es sogar in den Weltraum schicken.
Asterisk VoIP-Telegramm VoIP Bundle
Das VoIP-Bundle selbst ist dank der tg2sip- Bibliothek implementiert . Die Verwendung wird im Repository selbst im Abschnitt Verwendung beschrieben. Es gibt noch einige Artikel zur Anpassung. Es gibt sogar ein Docker-Image .
Eine Beschreibung dieses Bundles würde den Rahmen dieses Artikels sprengen.
Die einzige Nuance, die ich ansprechen möchte, ist, dass Sie telegram_id nicht anrufen können. Diese Nummer befindet sich nicht in Ihrem Kontaktbuch. Daher müssen Sie die Telefonnummer anrufen, unter der das Telegramm registriert ist.
In meinem Botimplementiert als öffentliche Audiokonferenzen (Ethers), zu denen sich jeder verbinden kann, und private Audiokonferenzen mit Kennwortzugriff. Private Räume / Passwörter werden von Benutzern selbst erstellt und können den Bot als Plattform für Audiokonferenzen, Besprechungen usw. verwenden.
Interaktionstelegramm-Bot - Sternchen
Das Interaktionsschema in meinem Bot sieht so aus.
Der Benutzer wählt den gewünschten Raum im Bot-Menü aus. Der Bot ruft die Funktion der Interaktion mit Asterisk über die API auf, indem er die Verbindungsparameter in der POST-Anforderung übergibt:
- Telefonnummer des Teilnehmers
- Konferenzraum-ID
- Anruferid zur Präsentation in einem Konferenzraum
- Sprache zum Verbalisieren von Benachrichtigungen an den Benutzer im Asterisk-System in seiner Muttersprache
Außerdem tätigt Asterisk einen ausgehenden Anruf über Telegrammkanäle an die in den Anforderungsparametern angegebene Nummer. Nachdem der Benutzer den Anruf beantwortet hat, verbindet ihn Asterisk mit dem entsprechenden Raum.
Es wäre möglich, eine direkte Verbindung vom Bot zum Astersik AMI zu verwenden , aber ich arbeite lieber über die API, je einfacher desto besser.
API auf der Asterisk-Serverseite
Einfacher API-Code in Python. Anrufdateien werden verwendet, um einen Anruf einzuleiten
#!/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)
In diesem Fall sieht der Asterisk-Wählplan in einfacher Form folgendermaßen aus:
[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
Diese API kann in anderen Fällen verwendet werden, um beispielsweise dieselbe Rückruftaste "Rückruf" usw. zu organisieren.
API-Aufruffunktion
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, ". . ."
Diese beiden Tools reichen bereits für die Integration in Ihren Bot aus, wickeln Sie ihn in Ihre Logik ein und verwenden Sie ihn.
Ein Beispiel für einen Bot zum Einleiten eines Anrufs in einen Konferenzraum
#!/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)
In diesem Beispiel wird die Telefonnummer statisch festgelegt. In der Realität können Sie jedoch beispielsweise Anfragen an die Datenbank richten, um die Nachricht message.chat.id - die Telefonnummer - abzugleichen.
Ich hoffe, mein Artikel hilft jemandem dabei, coole Projekte zu erstellen und diese wiederum mit der Community zu teilen.