في المقال السابق ، وصفت تنفيذ اختيار المستخدم لمكان الإقامة عند التسجيل في برنامج Telegram bot ، والذي أنشأته مستوحى من فكرة "Telephony" . في نفس المقالة ، سأصف تكامل الروبوت مع النجمة .
لاجل ماذا؟
كثير من الناس لا يحبون حقيقة أن المكالمات الجماعية لا يمكن إجراؤها في Telegram.
حسنًا ، لا تستخدم فايبر؟
هناك أيضًا عدد من الحالات لمثل هذا التنفيذ ، على سبيل المثال:
- بالنسبة للمؤتمرات الصوتية المجهولة ، عندما لا ترغب في "إضاءة" رقمك أو هويتك بين المشاركين في المؤتمر (يتبادر إلى الذهن يوم سبت المتسللين أو نادي مدمني الكحول المجهولين). لا داعي لأن تكون في أي مجموعة أو مجتمع أو قناة
- عندما لا تعرف من سيتصل بالمؤتمر على الإطلاق ، لكنك تحتاج إلى تقييد الوصول بكلمة مرور
- جميع مزايا النجمة: إدارة المؤتمرات (كتم الصوت / umute ، ركلة) ، مؤتمرات صوتية مختلطة مع العملاء المسجلين على النجمة والبرقية و PSTN. يمكنك توفير الكثير على المكالمات الدولية
- تنظيم رد الاتصال المؤسسي عبر برقية ، إلخ.
يتبادر إلى الذهن الكثير من الخيارات ، وهناك العديد منها ، محدودة فقط بالخيال. بعد سنوات عديدة من العمل مع Asterisk ، أعتقد أن الشيء الرئيسي هو الاتصال بها ، وبعد ذلك يمكنك فعل ما يناسبها ، حتى إرسالها إلى الفضاء.
حزمة Asterisk VoIP-Telegram VoIP
يتم تنفيذ حزمة VoIP نفسها بفضل مكتبة tg2sip . يتم وصف استخدامه في المستودع نفسه في قسم الاستخدام. هناك العديد من المقالات حول التخصيص. حتى أن هناك صورة Docker .
وصف هذه الحزمة خارج نطاق هذه المقالة.
الفارق البسيط الوحيد الذي أود التعبير عنه هو أنه لا يمكنك الاتصال ب telegram_id ، وهو الرقم غير الموجود في دفتر جهات الاتصال الخاص بك. لذلك ، تحتاج إلى الاتصال برقم الهاتف المسجل به البرقية.
في الروبوت الخاص بيتم تنفيذها كمؤتمرات صوتية عامة (Ethers) ، يمكن لأي شخص الاتصال بها ، ومؤتمرات صوتية خاصة مع الوصول إلى كلمة المرور. يتم إنشاء الغرف / كلمات المرور الخاصة من قبل المستخدمين أنفسهم ويمكنهم استخدام الروبوت كمنصة لعقد المؤتمرات الصوتية والاجتماعات وما إلى ذلك.
روبوت برقية التفاعل - النجمة
مخطط التفاعل في الروبوت الخاص بي يبدو هكذا.
يختار المستخدم الغرفة المطلوبة في قائمة bot ، ويستدعي الروبوت وظيفة التفاعل مع Asterisk عبر واجهة برمجة التطبيقات عن طريق تمرير معلمات الاتصال في طلب POST:
- رقم هاتف المشترك
- معرف غرفة الاجتماعات
- المتصل للعرض التقديمي في غرفة الاجتماعات
- لغة لإصدار الإشعارات للمستخدم في نظام النجمة باللغة الأم
علاوة على ذلك ، تقوم النجمة بإجراء مكالمة صادرة عبر قنوات برقية إلى الرقم المحدد في معلمات الطلب. بعد أن يجيب المستخدم على المكالمة ، تقوم النجمة بتوصيله بالغرفة المناسبة.
سيكون من الممكن استخدام اتصال مباشر من الروبوت إلى Astersik AMI ، لكنني أفضل العمل من خلال API ، كلما كان ذلك أبسط كان ذلك أفضل.
API على جانب خادم النجمة
كود API بسيط في بيثون. تستخدم ملفات المكالمات لبدء المكالمة
#!/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)
في هذه الحالة ، يبدو مخطط الطلب النجمة بشكل بسيط كالتالي:
[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
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, ". . ."
هاتان الأداتان كافيتان بالفعل للاندماج في الروبوت الخاص بك ، ولفه بمنطقك واستخدمه.
مثال على روبوت لبدء مكالمة إلى غرفة اجتماعات
#!/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)
في هذا المثال ، يتم تعيين رقم الهاتف بشكل ثابت ، ولكن في الواقع ، على سبيل المثال ، يمكنك تقديم طلبات إلى قاعدة البيانات لمطابقة message.chat.id - رقم الهاتف.
آمل أن تساعد مقالتي شخصًا ما في إنشاء مشاريع رائعة ومن ثم مشاركتها مع المجتمع.