defmodule ExGram.Updates.Polling do
@moduledoc """
Updates implementation that uses polling method
"""
use GenServer
require Logger
@polling_timeout 100
def start_link({:bot, pid, :token, token}) do
# Logger.debug "START WORKER"
GenServer.start_link(__MODULE__, {:ok, pid, token})
end
def init({:ok, pid, token}) do
# Clean webhook
ExGram.delete_webhook(token: token)
Process.send_after(self(), {:fetch, :update_id}, @polling_timeout)
{:ok, {pid, token, -1}}
end
def handle_cast({:fetch, :update_id} = m, state), do: handle_info(m, state)
def handle_info(:timeout, state), do: handle_info({:fetch, :update_id}, state)
def handle_info({:fetch, :update_id}, {pid, token, uid}) do
updates = get_updates(token, uid)
send_updates(updates, pid)
nid = next_pid(uid, updates)
{:noreply, {pid, token, nid}, @polling_timeout}
end
def handle_info(unknown_message, state) do
Logger.debug("Polling updates received an unknown message #{inspect(unknown_message)}")
{:noreply, state, @polling_timeout}
end
@default_opts [limit: 100, timeout: 50]
defp get_updates(token, uid, opts \\ []) do
opts =
@default_opts
|> Keyword.merge(opts)
|> Keyword.put(:offset, uid)
|> Keyword.put(:token, token)
try do
ExGram.get_updates!(opts)
rescue
ExGram.Error -> []
end
end
defp send_updates(updates, pid) do
Enum.map(updates, &GenServer.call(pid, {:update, &1}))
end
defp next_pid(actual, []), do: actual
defp next_pid(actual, updates) do
updates
|> Stream.map(&(&1.update_id + 1))
|> Enum.reduce(actual, &max(&1, &2))
end
end