Erstellen wir ein einfaches Empfangssystem mit dem serverlosen Python-Framework Chalice und Twilio

Was du machen willst

Ich habe über das Empfangssystem geschrieben, aber was ich tun möchte, ist im Grunde eine Erweiterung des folgenden Schnellstarts.

PYTHON-Schnellstart: Rufen Sie über Ihren Browser an

employee-call.png

Als ich mich fragte, ob ich mit WebRTC des Twilio-Clients etwas anfangen könnte, dachte ich, ich könnte das im Unternehmen übliche Empfangstelefon mit einem Webbrowser wie einem Tablet serverloser implementieren.

Twilio hat offiziell einen Beispielcode für Browseraufrufe mit Flask, aber die Informationen zu twilio-python und twilio.js sind etwas alt, daher hat es nicht so funktioniert, wie es war, also funktioniert es mit dem neuesten Code. Ich versuche es zu tun.

Anstatt ein Nebenstellentelefon zu verwenden, können Sie direkt auf Ihr persönliches Smartphone telefonieren. Der Vorteil ist, dass Sie kein festes Telefon benötigen und Ihre persönliche Telefonnummer nicht angeben müssen. Da es ohne Server implementiert wird, ist es außerdem wartungsfrei und kostengünstig. (Anrufgebühren fallen an ...)

Umgebung

Dinge notwendig

Dieses Mal wollte ich schnell eine Umgebung mit AWS Lambda + API GateWay erstellen, daher habe ich AWS Chalice verwendet.

Installation der erforderlichen Bibliotheken

$ pip install chalice

Legen Sie als Nächstes die AWS-Anmeldeinformationen fest. Wenn Sie es bereits mit boto3 usw. eingerichtet haben, brauchen Sie es wahrscheinlich nicht.

$ mkdir ~/.aws
$ vim ~/.aws/credentials
[default]
aws_access_key_id=YOUR_ACCESS_KEY_HERE
aws_secret_access_key=YOUR_SECRET_ACCESS_KEY
region=YOUR_REGION (such as us-west-2, us-west-1, etc)

Erstellen einer Lambda-Funktion

Erstellen Sie ein Projekt in Chalice.

$ chalice new-project EmployeeCaller
$ cd EmployeeCaller

Wenn Sie den obigen Befehl ausführen, wird eine Datei unter dem Verzeichnis erstellt. Bearbeiten Sie diese Datei.

Schreiben Sie zunächst die Bibliothek, die bereitgestellt werden soll, in die Datei require.txt.

$ vim requirements.txt
twilio==6.0.0

Bearbeiten Sie dann app.py und geben Sie den Code ein.

app.py


import os, json
from urlparse import parse_qs
from chalice import Chalice, Response
from twilio.jwt.client import ClientCapabilityToken
from twilio.twiml.voice_response import VoiceResponse

app = Chalice(app_name='EmployeeCaller')

#Generieren Sie TwiML, Endpunkt für Sprachanrufe
@app.route('/voice', methods=['POST'], content_types=['application/x-www-form-urlencoded'], cors=True)
def voice():
    parsed = parse_qs(app.current_request.raw_body)
    dest_number = parsed.get('PhoneNumber', [])

    resp = VoiceResponse()

    resp.dial(dest_number[0], caller_id=os.environ['TWILIO_CALLER_ID'])
    return Response(body=str(resp), status_code=200, headers={'Content-Type': 'application/xml'})

#Stellen Sie einen Token aus
@app.route('/client', methods=['GET'])
def client():
    request = app.current_request

    account_sid = os.environ['TWILIO_ACCOUNT_SID']
    auth_token = os.environ['TWILIO_AUTH_TOKEN']
    application_sid = os.environ['TWILIO_TWIML_APP_SID']

    capability = ClientCapabilityToken(account_sid, auth_token)
    capability.allow_client_outgoing(application_sid)
    capability.allow_client_incoming(os.environ['DEFAULT_CLIENT'])
    token = capability.to_jwt()

    callback = request.query_params['callback']
    return str(callback) + "(" + json.dumps({"token": token}) + ")"

Chalice ist eine kleine Ergänzung zu Chalice und basiert auf einem Mikroframework namens Flask. Ich denke, Sie sollten sich die Flask-Dokumentation für das Routing usw. ansehen.

Über das Routing

Zunächst zum folgenden Routing

@app.route('/client', methods=['GET'])

Sie müssen ein Capability Token erhalten, das erforderlich ist, um einen Anruf beim Twilio-Client zu tätigen. Drücken Sie / client, um dieses Token zu generieren und mit json zurückzugeben. Es fühlt sich an, als würde die Vorderseite dies verwenden, um einen Anruf zu tätigen.

Weitere Informationen zu Token finden Sie unter TWILIO Client Capability Tokens.

Dann das folgende Routing

@app.route('/voice', methods=['POST'], content_types=['application/x-www-form-urlencoded'], cors=True)

Dieses / voice erhält eine Anfrage vom Twilio-Server einschließlich der Telefonnummer des Verbindungsziels. Da es per POST gesendet wird, müssen Sie für den Inhaltstyp "application / x-www-form-urlencoded" angeben.

Informationen zu Umgebungsvariablen

Der Teil von os.environ ['---'] im Code ist der Ort zum Lesen der Umgebungsvariablen, die in die Chalice-Einstellungsdatei geschrieben ist. Sie wird jedoch nach einmaliger Bereitstellung und Einstellung von Twilio festgelegt.

Bereitstellen

Stellen Sie den obigen Code bereit. Führen Sie den folgenden Befehl im Projektverzeichnis aus.

$ chalice deploy
Updating IAM policy.
Updating lambda function...
Regen deployment package...
Sending changes to lambda.
API Gateway rest API already found.
Deploying to: dev
https://********.execute-api.ap-northeast-1.amazonaws.com/dev/

Wenn Sie es ausführen, sollten Sie ein Ergebnis wie das obige sehen. Notieren Sie sich die letzte Ausgabe-URL, die später in der Ziel-URL des APIGateWay-Anrufs verwendet wird.

Erstellen einer TwiML-App mit Twilio

Konto-SID und Auth-Token

Melden Sie sich bei Twilio an und notieren Sie sich die "ACCOUNT SID" und "AUTH TOKEN" des Console Dash Boards.

Erstellen einer TwiML-App

Erstellen Sie eine neue TwiML-App unter "Telefonnummer" -> "Extras". Geben Sie den App-Namen entsprechend dem Anzeigenamen ein.

Geben Sie die URL + / voice, die Sie notiert haben, als Sie den Kelch bereitgestellt haben, früher in" URL anfordern "von" Sprachanruf "ein und speichern Sie sie. (https: // ********. execute-api.ap-northeast-1.amazonaws.com / dev / voice)

Wenn Sie eine TwiML-App erstellen, wird die App in der Liste angezeigt. Zeigen Sie daher die Details an, überprüfen Sie die "SID" (TwiML App SID) und notieren Sie sie.

Telefonnummer kaufen

Kaufen Sie eine Telefonnummer von "Telefonnummer" mit "Kaufen Sie eine Nummer". Notieren Sie sich Ihre Telefonnummer.

So kaufen Sie eine Telefonnummer [zuvor geschriebener Artikel](http://qiita.com/hidesakai/items/20873fa354cb49911608#twilio%E3%81%A7%E9%9B%BB%E8%A9%B1%E7%95 % AA% E5% 8F% B7% E8% B3% BC% E5% 85% A5% E8% AA% B2% E9% 87% 91). Wenn Sie es also nicht wissen, beziehen Sie sich bitte darauf.

Legen Sie Umgebungsvariablen in der Lambda-Funktion fest

Kehren Sie nach dem Erstellen der TwiML-APP zum Kelchprojekt zurück und bearbeiten Sie die folgenden Dateien.

$ vim .chalice/config.json

Fügen Sie der Datei config.json ein Element mit dem Namen "enviroment_variables" hinzu. Stellen Sie die SID und das Token ein, die Sie zuvor hier notiert haben. Dies ist eine Umgebungsvariable in AWS Lambda.

.....
"app_name": "EmployeeCaller",
//Folgende Elemente wurden hinzugefügt
"environment_variables": {
    "TWILIO_ACCOUNT_SID": "*******************",
    "TWILIO_AUTH_TOKEN": "*******************",
    "TWILIO_TWIML_APP_SID": "*******************",
    "TWILIO_CALLER_ID": "+81********",
    "DEFAULT_CLIENT": "reception"
}

Stellen Sie nach dem Bearbeiten von config.json erneut bereit.

$ chalice deploy

Empfangsbildschirm erstellen, auf S3 hochladen

Erstellen Sie als Nächstes einen Empfangsbildschirm.

Bildschirmerstellung

$ vim employee.html

employee_call.html


<html>
    <head>
        <script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
        <script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
        <script type="text/javascript" src="https://media.twiliocdn.com/sdk/js/client/v1.4/twilio.min.js"></script>
        <script type="text/javascript">
            Twilio.Device.ready(function (device) {
                console.log("Ready");
            });

            Twilio.Device.error(function (error) {
                console.log("Error: " + error.message);
            });

            Twilio.Device.connect(function (conn) {
                console.log("Successfully established call");
            });

            Twilio.Device.disconnect(function (conn) {
                console.log("Call ended");
                $('.employee-hangup').addClass('disabled').prop('disabled', true);
                $('.employee-call').removeClass('disabled').prop('disabled', false);
            });

            Twilio.Device.incoming(function (conn) {
                console.log("Incoming connection from " + conn.parameters.From);
                conn.accept();
            });

            function twilioReadyAsync(phoneNumber) {
                return new Promise(function(resolve){
                    (function ready(){
                        if (Twilio.Device.status() == 'ready') {
                            resolve({"PhoneNumber": phoneNumber});
                        }
                        setTimeout(ready, 1000);
                    })();
                });
            }

            $(function() {
                $('.employee-hangup').addClass('disabled').prop('disabled', true);

                $('.employee-call').click(function(){
                    var employeePhoneNumber = $(this).attr('data-phone-number');

                    $(this).next().removeClass('disabled').prop('disabled', false);
                    $('.employee-call').addClass('disabled').prop('disabled', true);

                    $.ajax({
                        url: 'https://******.execute-api.ap-northeast-1.amazonaws.com/dev/client',
                        dataType: 'jsonp',
                        jsonCallback: 'callback'
                    })
                    .done(function(data) {
                        Twilio.Device.setup(data.token);
                        twilioReadyAsync(employeePhoneNumber).then(Twilio.Device.connect);
                    });
                });

                $('.employee-hangup').click(function(){
                    Twilio.Device.disconnectAll();
                    $(this).addClass('disabled').prop('disabled', true);
                    $('.employee-call').removeClass('disabled').prop('disabled', false);
                });
            });

        </script>
        <style>
            .container {width: auto;}
        </style>
    </head>
    <body>
        <div class="container">
            <h1>Rezeption</h1>
            <div class="card-deck">
                <div class="card text-center" id="employee-1">
                    <img class="card-img-top img-fluid" src="hidesakai.png " alt="Card image cap">
                    <div class="card-block">
                        <h4 class="card-title">hidesakai</h4>
                        <p class="card-text">
                        <p>Development: Engineer</p>
Bitte kontaktieren Sie uns per Erweiterung, wenn Sie es brauchen.
                        </p>
                        <button class="btn btn-primary employee-call" data-phone-number="+8190-****-****">Call</button>
                        <button class="btn btn-danger employee-hangup">Hangup</button>
                    </div>
                </div>
                <div class="card text-center" id="employee-2">
                    <img class="card-img-top img-fluid" src="spam.jpg " alt="Card image cap">
                    <div class="card-block">
                        <h4 class="card-title">Spam</h4>
                        <p class="card-text">
                        <p>Design: Designer</p>
Bitte kontaktieren Sie uns an der Rezeption.
                        </p>
                        <button class="btn btn-primary employee-call" data-phone-number="+8190-****-****">Call</button>
                        <button class="btn btn-danger employee-hangup">Hangup</button>
                    </div>
                </div>
                <div class="card text-center" id="employee-3">
                    <img class="card-img-top img-fluid" src="egg.png " alt="Card image cap">
                    <div class="card-block">
                        <h4 class="card-title">Ei</h4>
                        <p class="card-text">
                        <p>Sales: Marketer</p>
                        </p>
                        <button class="btn btn-primary employee-call" data-phone-number="+8190-****-****">Call</button>
                        <button class="btn btn-danger employee-hangup">Hangup</button>
                    </div>
                </div>
                <div class="card text-center" id="employee-4">
                    <div class="card-block">
                        <h4 class="card-title">Rezeption</h4>
                        <p class="card-text">
Dies ist die Rezeption.
                        </p>
                        <button class="btn btn-primary employee-call" data-phone-number="+8180-****-****">Call</button>
                        <button class="btn btn-danger employee-hangup">Hangup</button>
                    </div>
                </div>
            </div>
        </div>
    </body>
</html>

Die URL der url: 'https: // ******. Execute-api.ap-northeast-1.amazonaws.com / dev / client' der $ .ajax () Wird entsprechend eingegeben.

Geben Sie dann die Telefonnummer beginnend mit der Landesvorwahl (+81) in "Datentelefonnummer" ein.

Auf S3 hochladen

Erstellen Sie einen geeigneten Bucket in S3 und laden Sie die HTML-Datei hoch.

Anruf vom Bildschirm

Gehen Sie nach dem Hochladen auf S3 zur Seite und drücken Sie die Anruftaste. Es ist in Ordnung, wenn Sie an die eingestellte Telefonnummer senden können.

スクリーンショット 2017-05-09 1.50.01.png

Herausforderungen zeigen

Mit dieser Geschwindigkeit können Sie von überall darauf zugreifen und damit spielen.

Danach habe ich die Telefonnummer direkt in den HTML-Code eingegeben, möchte aber die Daten von Lambda wie DynamoDB erhalten.

Recommended Posts

Erstellen wir ein einfaches Empfangssystem mit dem serverlosen Python-Framework Chalice und Twilio
Berühren Sie AWS mit Serverless Framework und Python
[CRUD] [Django] Erstellen Sie eine CRUD-Site mit dem Python-Framework Django ~ 1 ~
Erstellen Sie eine Python-Version der Lambda-Funktion (+ Lambda-Schicht) mit Serverless Framework
Lassen Sie uns eine Todo-App mit dem Django REST-Framework erstellen
Versuchen Sie, ein einfaches Spiel mit Python 3 und iPhone zu erstellen
[CRUD] [Django] Erstellen Sie eine CRUD-Site mit dem Python-Framework Django ~ 2 ~
[CRUD] [Django] Erstellen Sie eine CRUD-Site mit dem Python-Framework Django ~ 3 ~
[CRUD] [Django] Erstellen Sie eine CRUD-Site mit dem Python-Framework Django ~ 4 ~
[CRUD] [Django] Erstellen Sie eine CRUD-Site mit dem Python-Framework Django ~ 5 ~
Mit Python mit Kelch ganz einfach ohne Server
Erstellen Sie ein Verzeichnis mit Python
Wahrscheinlich der einfachste Weg, um mit Python 3 ein PDF zu erstellen
Lassen Sie uns ein PRML-Diagramm mit Python, Numpy und matplotlib erstellen.
Erstellen Sie einen Twitter-BOT mit dem GoogleAppEngine SDK für Python
Erstellen Sie mit python wxpython + openCV ein einfaches Videoanalysetool
Erstellen Sie mit VSCode & Docker Desktop eine einfache Python-Entwicklungsumgebung
Erstellen Sie eine virtuelle Umgebung mit Python!
Erstellen Sie ein Empfehlungssystem mit Python
Erstellen Sie ein universelles Dekorationsframework für Python
Erstellen Sie eine gestreifte Illusion mit Gammakorrektur für Python3 und openCV3
Erstellen Sie mit Python + Qt (PySide) einen Farbwähler für das Farbrad.
Erstellen Sie mit Python und OpenCV ein einfaches OMR (Mark Sheet Reader)
Geben Sie einen Python-Ordner an oder erstellen Sie ihn, und speichern Sie den Screenshot.
Erstellen Sie einen einfachen geplanten Stapel mit Dockers Python Image und parse-crontab
Lösen Sie das Python-Rucksackproblem mit der Branch-and-Bound-Methode
Erstellen Sie eine REST-API, um dynamodb mit dem Django REST Framework zu betreiben
Erstellen Sie eine CP932-CSV-Datei für Excel mit Chalice und geben Sie sie zurück
Erstellen Sie ein Kompatibilitätsbewertungsprogramm mit dem Zufallsmodul von Python.
Erstellen Sie mit Class einen Python-Funktionsdekorator
Erstellen einer einfachen Power-Datei mit Python
Berechnen Sie die kürzeste Route eines Diagramms mit der Dyxtra-Methode und Python
Installieren Sie Python als Framework mit pyenv
[AWS] Erstellen Sie mit CodeStar eine Python Lambda-Umgebung und führen Sie Hello World aus
Erstellen Sie mit Python + PIL ein Dummy-Image.
Erstellen Sie eine einfache GUI-App in Python
[Python] Erstellen Sie mit Anaconda eine virtuelle Umgebung
Erstellen wir mit Python eine kostenlose Gruppe
Ein Memo mit Python2.7 und Python3 in CentOS
Durchsuche das Labyrinth mit dem Python A * -Algorithmus
Erstellen und entschlüsseln Sie Caesar-Code mit Python
Erstellen Sie ein Sternensystem mit Blender 2.80-Skript
Erstellen Sie eine einfache Web-App mit Flasche
Abrufen und Konvertieren der aktuellen Zeit in der lokalen Systemzeitzone mit Python
Erstellen Sie mit Python 3.4 einen Worthäufigkeitszähler
Erstellen Sie mit dem Python-Anforderungsmodul einen Datensatz mit Anhängen in KINTONE
Erstellen Sie ein Webframework mit Python! (1)
Erstellen Sie eine Python3-Umgebung mit pyenv auf einem Mac und zeigen Sie NetworkX-Diagramme an
Erstellen Sie mit Python einen Entscheidungsbaum von 0 und verstehen Sie ihn (5. Information Entropy)
Erstellen Sie ein Webframework mit Python! (2)
Ich habe mit Python einen einfachen Blackjack gemacht
Implementieren Sie eine einfache Anwendung mit Python Full Scratch ohne Verwendung eines Webframeworks.
Testen Sie das Hochladen von Bildern, indem Sie in Python erstellen, ohne Dummy-Bilddateien in Django zu platzieren
Stellen Sie Docker in Windows Home und führen Sie einen einfachen Webserver mit Python aus
Erstellen wir es, indem wir den Protokollpuffer mit Serverless Framework auf die API anwenden.
Verwenden Sie den Befehl [shell], um eine beliebige Datei zu komprimieren, um eine Datei zu erstellen und die Originaldatei zu löschen.
Ich habe versucht, mit Selenium + Python einfach ein vollautomatisches Anwesenheitssystem zu erstellen