Current section
Files
Jump to
Current section
Files
lib/client/custom.ex
defmodule Client.Custom do
@moduledoc """
A Microsoft Directline Client
"""
alias Direxion.{Config, Util}
@behaviour Direxion.ClientBehaviour
@doc """
Get the authorization token for bots request
Returns a tuple containing the status of request and the conversation ID
"""
@spec get_authorization_token() :: tuple()
def get_authorization_token() do
url = "https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token"
headers = [{"Content-Type", "application/x-www-form-urlencoded"}]
msa_credentials = Config.get_msa_credentials()
client_id = Map.get(msa_credentials, :client_id)
params =
msa_credentials
|> Map.put("grant_type", "client_credentials")
|> Map.put("scope", "#{client_id}/.default")
|> Map.put("atver", 1)
|> URI.encode_query()
case HTTPoison.post(url, params, headers) do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
access_token =
body
|> Poison.decode!()
|> Map.get("access_token")
{:ok, access_token}
{:ok, _} ->
{:error, "Error Getting Authorization Token"}
{:error, %HTTPoison.Error{reason: reason}} ->
{:error, reason}
end
end
@doc """
Send an activity to a bot
Parameters:
* access_token - Microsoft bot authorization token
* activity - The activity we want reponse to send
Returns the assigned activity id.
"""
@spec send_activity_to_bot(String.t(), map()) :: tuple()
def send_activity_to_bot(access_token, activity) do
request_endpoint = Config.get_bot_request_endpoint()
headers = Util.generate_request_header(access_token)
activity_id = Util.generate_uuid()
modified_activity = Util.modify_activity(activity, activity_id)
case HTTPoison.post(request_endpoint, modified_activity, headers) do
{:ok, %HTTPoison.Response{status_code: 200, body: _}} ->
{:ok, activity_id}
{:ok, _} ->
{:error, "Error Sending Activity"}
{:error, %HTTPoison.Error{reason: reason}} ->
{:error, reason}
end
end
@doc """
Receive the response from a bot response service.
Parameters:
* activity_id - The Activity ID we want reponse to
Returns a Response object.
"""
@spec receive_response(String.t()) :: tuple()
def receive_response(activity_id) do
response_endpoint = Config.get_bot_response_endpoint()
case HTTPoison.get("#{response_endpoint}/activity/#{activity_id}") do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
{:ok, Poison.decode!(body)}
{:ok, _} ->
{:error, "Error Receiving Activities"}
{:error, %HTTPoison.Error{reason: reason}} ->
{:error, reason}
end
end
@doc """
Send an activity through our response handler
the response is the Directline reponse.
Parameters:
* input_token - Directline Token to be used, Will be overridden by `DIRECTLINE_TOKEN` in path if found
* activity - The activity to send
Returns a Directline Response
"""
@spec message(map()) :: map()
def message(activity) do
timeout = Config.get_request_timeout()
with {:ok, access_token} <-
Task.await(
Task.async(fn -> get_authorization_token() end),
timeout
),
response <- message_bot(access_token, activity) do
response
end
end
@doc """
Send an activity to a conversation
and return its the Directline reponse.
Parameters:
* access_token - Microsoft Bot framework access token
* activity - The activity to send
Returns the bot Response
"""
@spec message_bot(String.t(), map()) :: map()
def message_bot(access_token, activity) do
timeout = Config.get_request_timeout()
with {:ok, activity_id} <-
Task.await(
Task.async(fn -> send_activity_to_bot(access_token, activity) end),
timeout
),
_ <- Process.sleep(1000),
{:ok, response} <-
Task.await(
Task.async(fn -> receive_response(activity_id) end),
timeout
) do
response
end
end
end