https://a.storyblok.com/f/270183/84753/346046837b/azure-functions-python_1200x675.jpg

Como usar o Azure Functions com Python

Publicado em November 9, 2020

Tempo de leitura: 19 minutos

Aqui na Vonage, procuramos tornar nossas APIs o mais simples possível de usar. No entanto, uma dificuldade que não conseguimos evitar é que muitas de nossas APIs, como a Voice API da Vonage, precisam perguntar ao seu aplicativo o que fazer durante uma chamada. Isso significa que você precisa executar seu próprio servidor. Ou será que não?

Adotando a arquitetura sem servidor com o Azure Functions

A Microsoft oferece o Azure Functions para Python, e isso é ótimo! Há muito suporte disponível para ajudar você a começar a trabalhar rapidamente, e ele funciona com padrões de projeto padrão do Python, como requirements.txt. Ele permite que você escreva pequenas funções independentes em Python e, em seguida, as implante facilmente na nuvem do Azure.

Existe um plano gratuito que oferece um milhão execuções de funções por mês. Isso deve ser suficiente para um pequeno aplicativo de demonstração ou até mesmo para um pequeno aplicativo de produção!

Vamos nos exercitar

Vou mostrar a vocês como criar um aplicativo simples da Vonage com dois webhooks hospedados no Azure Functions. A ideia é que o usuário ligue para um número da Vonage (o que acionará o primeiro webhook) e seja recebido por uma voz robótica. Será solicitado que ele informe seu estado de espírito. Ele digitará 1 para “feliz”, 2 para “infeliz” e quaisquer outras opções que você desejar. Nesse momento, o segundo endpoint será chamado com a entrada, e isso gerará uma resposta apropriada.

Vou descrever todas as etapas para criar todo o código e a configuração de que você vai precisar, mas se quiser ver o resultado final, o código está hospedado no GitHub

Requisitos

Como você pode ver abaixo, há alguns algumas coisas que você precisará configurar ou instalar, mas acredite, vale a pena.

  • Um conta gratuita do Azure para que você possa publicar suas Azure Functions.

  • Instale a ferramenta CLI da Vonage e leia esta breve postagem no blog sobre como começar a usá-la.

    Isso fornece a você o vonage no seu console, o que permite criar Applications de voz da Vonage, comprar números virtuais e vincular os dois.

  • Instalar o Ngrok

    Isso fornece o ngrok comando no seu console, que encaminhará as solicitações para sua máquina de desenvolvimento, permitindo que a Vonage envie webhooks para o seu servidor de desenvolvimento.

  • Instale o Azure Functions Core Tools

    Isso fornece o func comando no seu console, que permite inicializar seu projeto do Azure Functions e executá-lo localmente para desenvolvimento e testes.

  • Instale o CLI do Azure.

    Isso fornece o az comando no seu console. Isso permitirá que você crie vários objetos no Azure e publique suas funções do Azure!

Criando sua primeira função

Depois de instalar todos os pré-requisitos acima, abra o console. Você criará um código padrão para dar início à criação de suas funções do Azure.

Primeiro, vamos criar um novo projeto do Azure Functions usando o comando do Azure Functions Core Tools, func. Execute func init para criar um projeto vazio do Azure Functions:

func init enter-your-mood Select a worker runtime: 1. dotnet 2. node 3. python 4. powershell (preview) Choose option: 3 python Writing .gitignore Writing host.json Writing local.settings.json Writing /Users/mark/Documents/Development/nexmo/azure_webhooks/enter-your-mood/.vscode/extensions.json

Agora, acesse o diretório do novo projeto e use func new para criar uma nova função do Azure para atender uma chamada recebida. Quando for perguntado que tipo de função você deseja criar, selecione “5”, gatilho HTTP. Esse é o tipo de função do Azure que responde a solicitações HTTP. Quando for perguntado como nomear a função, digite answer_inbound , pois o endpoint será usado para atender chamadas telefônicas recebidas.

cd enter-your-mood func new Select a template: 1. Azure Blob Storage trigger 2. Azure Cosmos DB trigger 3. Azure Event Grid trigger 4. Azure Event Hub trigger 5. HTTP trigger 6. Azure Queue Storage trigger 7. Azure Service Bus Queue trigger 8. Azure Service Bus Topic trigger 9. Timer trigger Choose option: 5 HTTP trigger Function name: [HttpTrigger] answer_inbound Writing /Users/mark/Documents/Development/nexmo/azure_webhooks/enter-your-mood/answer_inbound/__init__.py Writing /Users/mark/Documents/Development/nexmo/azure_webhooks/enter-your-mood/answer_inbound/function.json The function "answer_inbound" was created successfully from the "HTTP trigger" template.

Você pode ver na saída acima que func foi criado um arquivo Python, __init__.py e um arquivo de configuração, function.json.

Editar function.json e defina “authlevel” como “anonymous”. Isso permitirá que a Vonage faça a chamada sem nenhuma autenticação adicional.

{
    "scriptFile": "__init__.py",
    "bindings": [
    {
        "authLevel": "anonymous",
        "type": "httpTrigger",
        ...

Execute a função padrão em Python, usando o func host comando:

# Run the functions locally: func host start

Se você acessar o seguinte URL no seu navegador http://localhost:7071/api/answer_inbound?name=bob , você deverá ver “Hello bob!”. Muito bem! Você “escreveu” sua primeira função do Azure!

Da Função do Azure à chamada telefônica

É recomendável que sua função gere algumas ações NCCO, para que a Vonage saiba o que fazer quando alguém ligar para o seu número. Para isso, você precisará substituir o código da função pelo seguinte:

def main(req: func.HttpRequest) -> func.HttpResponse:
    return func.HttpResponse(json.dumps([
        {
            'action': 'talk',
            'text': 'Welcome to the mood reporting hotline. Please enter 1 if you are happy, or 2 if you are unhappy.',
            'bargeIn': True,
        },
        {
            'action': 'input',
            'eventUrl': [ f'https://{req.headers["host"]}/api/mood_feedback' ],
            'maxDigits': 1,
            'timeOut': 10,
        },
    ]), mimetype='application/json')

O código acima retorna uma resposta JSON, contendo duas ações NCCO. Uma ação NCCO é uma instrução para a Vonage, indicando como lidar com a chamada telefônica. Neste caso, temos duas ações:

  • A talk ação instrui a Vonage a ler uma mensagem para quem está ligando.

  • A input ação indica à Vonage que o usuário deve digitar um dígito, que será então enviado para a URL especificada em eventURL

Como definimos bargeIn para true na talk ação, se o chamador digitar um dígito antes de a input ação ter começado, a Vonage presumirá que se trata apenas de impaciência e executará a seguinte input instrução.

Se você executar func host start novamente, ao acessar seu navegador em http://localhost:7071/api/answer_inbound?name=bob você deverá ver vários dados em JSON contendo as ações descritas acima.

Crie um túnel para o seu servidor de desenvolvimento

Enquanto você ainda estiver desenvolvendo, vai ser necessário que a Vonage tenha acesso às suas funções, para que você possa testá-las. Recomendo seguir as instruções do meu colega Aaron Bassett escreveu para conectar seu servidor de desenvolvimento local à API da Vonage usando um túnel Ngrok.

Supondo que você já saiba como o Ngrok funciona, em um terminal , execute:

ngrok http 7071

Verifique se você ainda está executando func host start na outra janela do console e carregue a URL do Ngrok que foi exibida, seguida de /api/answer_inbound. Deve ficar mais ou menos assim https://r4nd0m.ngrok.io/api/answer_inbound (mas com seu próprio prefixo aleatório no lugar de r4nd0m!).

Se isso funcionar, é hora de informar à Vonage como entrar em contato com o seu servidor de desenvolvimento!

Conecte o Vonage ao seu servidor de desenvolvimento

Caso ainda não tenha feito isso, você precisará configurar a CLI da Vonage, após a instalação, com sua chave de API e seu segredo.

vonage config:set --apiKey=XXXXXX --apiSecret=XXXXXX

Crie um novo aplicativo de voz da Vonage executando vonage apps:create e nomeie-o como “Enter Your Mood” quando solicitado. Siga as demais instruções da linha de comando para criar seu aplicativo.

vonage apps:create

Isso cria um aplicativo chamado “Enter Your Mood” no Painel da API da Vonage. Quando for detectada uma chamada recebida em qualquer número de telefone vinculado a esse aplicativo, ele acionará o webhook em https://r4nd0m.ngrok.io/api/answer_inbound, enviando os detalhes da chamada recebida. Espera-se que a Função do Azure nesse endpoint responda com Ações NCCO... soa familiar? Também foi salva uma chave privada, que não usaremos por enquanto, em um arquivo chamado “private.key”

Agora você precisa comprar um número virtual e vinculá-lo ao aplicativo da Vonage. Portanto, anote o ID do aplicativo que acabou de ser criado (neste caso, é “4f33ff5e-dbbc-11e9-8656-6bdabe7b8258”).

Compre um número virtual, caso ainda não tenha um. Recomendo comprá-lo usando o Painel da API da Vonage, mas você também também pesquisar números e comprá-los usando a ferramenta CLI da Vonage. Assim que tiver um número, vincule-o ao aplicativo com o seguinte comando, substituindo o número de telefone pelo que você acabou de comprar e o ID do aplicativo pelo que você anotou acima:

vonage apps:link [APPLICATION_ID] --number=number

Agora, com seu celular, ligue para o número que você acabou de vincular.

O que deveria acontecer: Uma voz deve responder com a mensagem acima. Se você digitar um número no teclado do seu celular, a ligação provavelmente emitirá um bipe e, em seguida, será interrompida. Isso ocorre porque o segundo URL, em /api/mood_feedback ainda não existe!

Tratamento de entradas

Para isso, siga passos semelhantes aos descritos acima:

  • Executar func new, selecione HTTP trigger e digite “mood_feedback” como nome da função.

  • Modifique o function.json arquivo e defina authLevel para anonymous.

Agora, abra __init__.py e substitua o código da função pelo seguinte:

def main(req: func.HttpRequest) -> func.HttpResponse:
    try:
        req_body = req.get_json()
        return func.HttpResponse(json.dumps([
            {
                'action': 'talk',
                'text': 'Thank you for telling us how you feel.',
            },
        ]), mimetype='application/json')
    except ValueError:
        return func.HttpResponse(
            "Could not parse request body.",
            status_code=400
        )

Tem um pouquinho de código a mais aqui, que vai servir para extrair os dados enviados pela ligação, mas, por enquanto, você já deve conseguir ligar para o número de novo e desta vez, , ao digitar um número durante a ligação, você deverá ouvir a mensagem “obrigado por nos contar como você está se sentindo”.

Torne a resposta dinâmica

Se isso funcionar, vamos garantir que a resposta à chamada seja um pouco mais amigável. Acima da função, adicione as seguintes variáveis globais:

RESPONSES = {
    "1": "It's great that you're so happy!",
    "2": "I'm sorry that you're unhappy.",
}
UNEXPECTED_RESPONSE = "I'm sorry, I don't understand that feedback."

Agora, no NCCO ao qual você está retornando, substitua a string por RESPONSES.get(req_body['dtmf'], UNEXPECTED_RESPONSE). Essa expressão extrai o código DTMF da solicitação (req_body['dtmf']), tenta encontrar a resposta associada em RESPONSESe, se essa chave não existir, recorre a UNEXPECTED_RESPONSE. Ligue para o seu número e teste!

Criação de um Function App no Azure

O que você fez até agora é ótimo — desde que sua máquina de desenvolvimento esteja ligada e você tenha janelas de console abertas executando func host & ngrok. Mas isso é pouco prático, então agora vou mostrar como implantar o código que você escreveu no Azure Functions, para que a Microsoft possa hospedá-lo para você!

Para interagir com os servidores do Azure, usaremos o comando da CLI do Azure, az.

Primeiro, você precisa fazer login na sua conta do Azure executando az login. O navegador será aberto e você será solicitado a fazer login na sua conta do Azure. Se ainda não se cadastrou no Azure, pode fazer isso agora.

# Connect `az` to your Azure account: az login

Agora, você vai executar os três az comandos abaixo — adicionei um comentário a cada um deles, para que você possa ver o que eles fazem. A única coisa que você precisará alterar é substituir MYVONAGEFUNCTIONSTORE por algo globalmente único. O nome específico que você escolher não importa — é apenas um local para armazenar os dados das suas funções em execução e não será visível aos usuários. Você também precisará alterar moodfeedbackapp por algo globalmente único.

# Create a resource group. (This is analagous to a Vonage 'Application'): az group create --name myResourceGroup --location westeurope # Create a storage account for storing your function data: az storage account create --name "MYVONAGEFUNCTIONSTORE" \ --location westeurope --resource-group myResourceGroup \ --sku Standard_LRS # Create a function app for grouping your functions together: az functionapp create --resource-group myResourceGroup --os-type Linux \ --consumption-plan-location westeurope --runtime python \ --name "moodfeedbackapp" --storage-account "MYVONAGEFUNCTIONSTORE"

Publique sua função no Azure

func azure functionapp publish moodfeedback --build remote Getting site publishing info... Creating archive for current directory... Perform remote build for functions project (--build remote). Uploading 6.08 KB [##################################################################] Remote build in progress, please wait... Updating submodules. Preparing deployment for commit id '5bfe469a6e'. Running oryx build... Writing the artifacts to a Squashfs file Parallel mksquashfs: Using 1 processor Creating 4.0 filesystem on /home/site/deployments/20190919110956.squashfs, block size 131072. ... Remote build succeeded! Syncing triggers... Functions in moodfeedback: answer_inbound - [httpTrigger] Invoke url: https://moodfeedback.azurewebsites.net/api/answer_inbound mood_feedback - [httpTrigger] Invoke url: https://moodfeedback.azurewebsites.net/api/mood_feedback

Você pode verificar se suas funções foram implantadas corretamente acessando https://moodfeedback.azurewebsites.net/api/answer_inbound (você precisará substituir “moodfeedback” pelo nome do seu próprio aplicativo de função, escolhido acima) no navegador e conferindo se a saída JSON do NCCO está sendo gerada.

Atualize seu aplicativo da Vonage

A Vonage ainda acredita que deve ligar para o seu servidor de desenvolvimento quando alguém liga para o seu número virtual! Para corrigir isso, atualize seu aplicativo da Vonage para que ele aponte para a nova URL. Execute o comando a seguir, substituindo o ID do aplicativo pelo seu e substituindo “moodfeedbackapp” pelo nome do seu próprio aplicativo de função.

nexmo app:update 4f33ff5e-dbbc-11e9-8656-6bdabe7b8258 "Mood Feedback" "https://moodfeedbackapp.azurewebsites.net/api/answer_inbound" "https://api.example.org/events" --answer_method POST

Próximos passos

O objetivo deste tutorial foi mostrar como criar manipuladores de webhook para chamadas da Voice API Vonage usando o Azure Functions. Embora este exemplo não faça muita coisa, você poderá criar exemplos muito mais interessantes e práticos com a ajuda do armazenamento do Azure e de outras APIs.

Se você quiser incorporar funcionalidades interessantes ao seu aplicativo, pode:

  • Enviar os resultados do feedback a um pesquisador, por meio da SMS API da Vonage.

  • Integre uma API de conversão de fala em texto para processar entradas de voz, em vez de códigos numéricos.

  • Armazene o feedback de cada pessoa que ligar em um banco de dados, para analisar as tendências ao longo do tempo.

Outros recursos

Compartilhar:

https://a.storyblok.com/f/270183/150x150/a3d03a85fd/placeholder.svg
Mark SmithEx-funcionários da Vonage

Mark era o responsável nominal pelas bibliotecas de clientes da Nexmo (embora ele só desenvolva as bibliotecas em Python e Java). Ele começou como desenvolvedor Java, já trabalha com Python há 18 anos e vem se aventurando cada vez mais com Go e Rust. Ele gosta de levar as linguagens de programação ao limite e, depois, ensinar essas técnicas a outros programadores. Ele tem um chapéu de viking, mas não é um viking, e no Twitter usa o nome Judy2k por motivos que prefere não revelar.