A DSL for routing parsed LINE webhook events (ExLine.Webhook structs) to
handlers.
Routes are declared with macros and matched against the event struct plus an
event_assigns map you control. Parse the raw payload with ExLine.Webhook.parse/1
first, then route each event.
Example
defmodule MyApp.LineRouter do
use ExLine.EventRouter
# Routes can also match on the assigns set by before_action/2 (e.g. the
# loaded current_user) — declare the more specific route first.
text "menu", %{current_user: %{role: :admin}}, MyApp.AdminHandler, :menu
text "menu", MyApp.MenuHandler, :menu
message :image, MyApp.MediaHandler, :on_image # any image message
postback "buy", MyApp.ShopHandler, :buy
follow MyApp.OnboardHandler, :welcome
unfollow MyApp.OnboardHandler, :goodbye
default MyApp.FallbackHandler, :unknown # REQUIRED: also catches Event.Unknown
# Preprocess every event before it is matched: load the current user from
# the event's source and stash the messaging client for handlers to use.
@impl true
def before_action(event, assigns) do
user =
case event.source do
%ExLine.Webhook.Source{user_id: id} when is_binary(id) ->
MyApp.Accounts.get_by_line_id(id)
_ ->
nil
end
{event, assigns |> Map.put(:current_user, user) |> Map.put(:client, MyApp.client())}
end
end
# In your webhook controller (after ExLine.Webhook.Signature has verified it):
params["events"] |> ExLine.Webhook.parse() |> Enum.each(&MyApp.LineRouter.call/1)Because LINE adds event types without notice (and unknown types become
ExLine.Webhook.Event.Unknown), always declare a default/2 route so unmatched
events never raise.
Ref: https://developers.line.biz/en/reference/messaging-api/#webhook-event-objects
Summary
Callbacks
Invoked before an event is matched; preprocess the event and assigns here.
Invoked just before the handler is called; lets you tweak the dispatch.
Functions
Routes an account-link event.
Routes a module-channel activated event.
Routes a beacon event.
Routes a bot-resumed event.
Routes a bot-suspended event.
Routes a module-channel deactivated event.
Catch-all route for any unmatched event (also catches UnknownEvent).
Routes a follow event.
Routes a join event.
Routes a leave event.
Routes a member-joined event.
Routes a member-left event.
Routes a membership event.
Routes any message event of the given content kind
(:text | :image | :video | :audio | :file | :location | :sticker).
Routes a module-channel event.
Routes a PNP (LINE notification message) delivery-completion event.
Routes a postback event whose data equals data.
Routes a text message event whose text equals text.
Routes an unfollow event.
Routes an unsend event.
Routes a video-play-complete event.
Callbacks
@callback before_action(event :: struct(), event_assigns :: map()) :: {event :: struct(), event_assigns :: map()}
Invoked before an event is matched; preprocess the event and assigns here.
@callback before_handler_call( handler :: atom(), action :: atom(), event :: struct(), event_assigns :: map() ) :: {atom(), atom(), struct(), map()}
Invoked just before the handler is called; lets you tweak the dispatch.
Functions
Routes an account-link event.
Routes a module-channel activated event.
Routes a beacon event.
Routes a bot-resumed event.
Routes a bot-suspended event.
Routes a module-channel deactivated event.
Catch-all route for any unmatched event (also catches UnknownEvent).
Routes a follow event.
Routes a join event.
Routes a leave event.
Routes a member-joined event.
Routes a member-left event.
Routes a membership event.
Routes any message event of the given content kind
(:text | :image | :video | :audio | :file | :location | :sticker).
Routes a module-channel event.
Routes a PNP (LINE notification message) delivery-completion event.
Routes a postback event whose data equals data.
Routes a text message event whose text equals text.
Routes an unfollow event.
Routes an unsend event.
Routes a video-play-complete event.