I’m trying to build a telegram bot with Nadia
, and I thought that would be a good idea, to wrap some functionalities with macros, for studying purposes!
Here’re my macros:
#router.ex
defmodule Lovelace.Router
[...]
defp generate_command(command, handler) do
quote do
def do_match_message(
%{
message: %{
text: "/" <> unquote(command)
}
} = var!(update)
) do
handle_message(unquote(handler), [var!(update)])
end
def do_match_message(
%{
message: %{
text: "/" <> unquote(command) <> " " <> _
}
} = var!(update)
) do
handle_message(unquote(handler), [var!(update)])
end
def do_match_message(
%{
message: %{
text: "/" <> unquote(command) <> "@" <> unquote(@bot_name)
}
} = var!(update)
) do
handle_message(unquote(handler), [var!(update)])
end
def do_match_message(
%{
message: %{
text: "/" <> unquote(command) <> "@" <> unquote(@bot_name) <> " " <> _
}
} = var!(update)
) do
handle_message(unquote(handler), [var!(update)])
end
end
end
# Helpers
def handle_message({module, function}, update)
when is_atom(function) and is_list(update) do
Task.start(fn ->
apply(module, function, [hd(update)])
end)
end
def handle_message({module, function}, update)
when is_atom(function) do
Task.start(fn ->
apply(module, function, [update])
end)
end
def handle_message(function, _update)
when is_function(function) do
Task.start(fn ->
function.()
end)
end
def handle_message(_, _), do: nil
## Command
defmacro command(commands, do: function)
when is_list(commands) do
Enum.map(commands, fn command ->
generate_command(command, function)
end)
end
defmacro command(command, do: function) do
generate_command(command, function)
end
defmacro command(commands, module, function)
when is_list(commands) do
Enum.map(commands, fn command ->
generate_command(command, {module, function})
end)
end
defmacro command(command, module, function) do
generate_command(command, {module, function})
end
[...]
end
And I’m using as:
#commands.ex
defmodule Lovelace.Commands do
@moduledoc """
Define all bot's commands
"""
use Lovelace.Router
use Lovelace.Commander
import Lovelace.Helpers
alias Lovelace.Commands.Outside
command "welcome" do
Logger.log(:info, "Command /welcome")
~s(Seja bem vindo ao grupo de Ciência da Computação! )
|> Kernel.<>(
~s|Leia as regras do grupo no pinado e visite nosso GitHub(https://github.com/cciuenf) |
)
|> Kernel.<>(~s(Digite /ajuda para ver mais comandos!))
|> send_message()
end
end
However, when compiling, I’m geeting:
Compiling 2 files (.ex)
== Compilation error in file lib/lovelace/commands.ex ==
** (ArgumentError) expected binary argument in <> operator but got: nil
(elixir 1.11.3) lib/kernel.ex:1821: Kernel.wrap_concatenation/3
(elixir 1.11.3) lib/kernel.ex:1812: Kernel.extract_concatenations/2
(elixir 1.11.3) lib/kernel.ex:1808: Kernel.extract_concatenations/2
(elixir 1.11.3) expanding macro: Kernel.<>/2
lib/lovelace/commands.ex:13: Lovelace.Commands.do_match_message/1
The Error is thrown on
command "welcome"...
in the commands.ex file!
But I ain’t finding where is the error… Could you help me?