Menerapkan konferensi audio di Telegram + Asterisk





Di artikel sebelumnya, saya menjelaskan implementasi pilihan tempat tinggal pengguna saat mendaftar di bot telegram saya , yang saya buat terinspirasi oleh ide "Telephony" . Di artikel yang sama, saya akan menjelaskan integrasi bot dengan Asterisk .



Untuk apa?



Banyak orang tidak menyukai kenyataan bahwa panggilan grup tidak dapat dilakukan di Telegram.



Nah, jangan gunakan Viber?



Ada juga beberapa kasus untuk implementasi seperti itu, misalnya:



  • Untuk konferensi audio anonim, ketika Anda tidak ingin "menyalakan" nomor atau id Anda di antara peserta konferensi (hari Sabat peretas atau klub Alcoholics Anonymous langsung terlintas dalam pikiran). Tidak perlu berada di grup, komunitas, saluran mana pun
  • Ketika Anda tidak tahu siapa yang akan terhubung ke konferensi sama sekali, tetapi Anda perlu membatasi akses dengan kata sandi
  • Semua kesenangan Asterisk: manajemen konferensi (mute / umute, kick), konferensi audio hybrid dengan klien yang terdaftar di asterisk, telegram dan PSTN. Anda dapat menghemat banyak untuk panggilan internasional
  • Organisasi panggilan balik perusahaan melalui telegram, dll.


Banyak pilihan muncul di benak, ada banyak di antaranya, hanya dibatasi oleh imajinasi. Setelah bertahun-tahun bekerja dengan Asterisk, saya percaya bahwa hal utama adalah meneleponnya, dan kemudian Anda dapat melakukan apa pun yang sesuai dengannya, bahkan mengirimkannya ke luar angkasa.



Bundel VoIP VoIP-Telegram Asterisk



Bundel VoIP itu sendiri diimplementasikan berkat pustaka tg2sip . Penggunaannya dijelaskan di repositori itu sendiri di bagian Penggunaan. Ada beberapa artikel lagi tentang kustomisasi. Bahkan ada gambar Docker .

Penjelasan tentang paket ini berada di luar cakupan artikel ini.



Satu-satunya nuansa yang ingin saya sampaikan adalah Anda tidak bisa menelepon telegram_id, yang nomornya tidak ada di buku kontak Anda. Oleh karena itu, Anda perlu menghubungi nomor telepon tempat terdaftarnya telegram.



Di bot sayadiimplementasikan sebagai konferensi audio publik (Ethers), di mana siapa pun dapat terhubung, dan konferensi audio pribadi dengan akses kata sandi. Kamar / kata sandi pribadi dibuat oleh pengguna sendiri dan dapat menggunakan bot sebagai platform untuk konferensi audio, rapat, dll.



Bot telegram interaksi - Asterisk



Skema interaksi di bot saya terlihat seperti ini.



Pengguna memilih ruangan yang diinginkan di menu bot, bot memanggil fungsi interaksi dengan Asterisk melalui API dengan meneruskan parameter koneksi dalam permintaan POST:



  • nomor telepon pelanggan
  • ID ruang konferensi
  • callerid untuk presentasi di ruang konferensi
  • bahasa untuk membunyikan pemberitahuan kepada pengguna di sistem Asterisk dalam bahasa asli


Selanjutnya, Asterisk melakukan panggilan keluar melalui saluran telegram ke nomor yang ditentukan dalam parameter permintaan. Setelah pengguna menjawab panggilan tersebut, Asterisk menghubungkannya ke ruangan yang sesuai.



Dimungkinkan untuk menggunakan koneksi langsung dari bot ke Astersik AMI , tetapi saya lebih suka bekerja melalui API, semakin sederhana semakin baik.



API di sisi server Asterisk



Kode API sederhana di python. File. Panggilan digunakan untuk memulai panggilan



#!/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)


Dalam hal ini, dialplan Asterisk dalam bentuk yang sederhana terlihat seperti ini:



[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


API ini dapat digunakan dalam kasus lain, misalnya, untuk mengatur tombol panggilan balik yang sama "Telepon saya kembali", dll.



Fungsi panggilan 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, ".  .  ."


Kedua alat ini sudah cukup untuk integrasi ke bot Anda, bungkus dalam logika Anda dan gunakan.



Contoh bot untuk memulai panggilan ke ruang konferensi



#!/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)


Dalam contoh ini, nomor telepon disetel secara statis, tetapi kenyataannya, misalnya, Anda dapat membuat permintaan ke database untuk mencocokkan message.chat.id - nomor telepon.



Semoga artikel saya membantu seseorang membuat proyek keren dan pada gilirannya membagikannya dengan komunitas.



All Articles