Current section
Files
Jump to
Current section
Files
src/telega@reactions.erl
-module(telega@reactions).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/telega/reactions.gleam").
-export([emoji/1, custom_emoji/1, paid/0, react/2, react_emoji/2, react_many/2, react_big/2, clear_reaction/1, react_to_message/3, react_to_chat_message/4, reaction_equals/2, get_changes/1, get_emoji/1, was_added/2, was_removed/2, has_added/1, has_removed/1, get_counts/1, get_total_count/1, get_emoji_count/2, get_top_reactions/2, get_custom_emoji_id/1, is_paid/1, is_emoji/1, is_custom_emoji/1, matches_emoji/2]).
-export_type([reaction_changes/0, reaction_count_info/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" `reactions` provides convenient helpers for working with Telegram reactions.\n"
"\n"
" ## Sending reactions\n"
"\n"
" ```gleam\n"
" import telega/reactions\n"
"\n"
" // React to current message with emoji\n"
" reactions.react(ctx, reactions.thumbs_up)\n"
"\n"
" // React with custom emoji string\n"
" reactions.react_emoji(ctx, \"👍\")\n"
"\n"
" // React with big animation\n"
" reactions.react_big(ctx, reactions.heart)\n"
" ```\n"
"\n"
" ## Handling reaction updates\n"
"\n"
" ```gleam\n"
" import telega/router\n"
" import telega/reactions\n"
"\n"
" router.new()\n"
" |> router.on_reaction(fn(ctx, update) {\n"
" let changes = reactions.get_changes(update)\n"
" // Process added/removed reactions\n"
" Ok(ctx)\n"
" })\n"
" ```\n"
).
-type reaction_changes() :: {reaction_changes,
list(telega@model@types:reaction_type()),
list(telega@model@types:reaction_type()),
list(telega@model@types:reaction_type())}.
-type reaction_count_info() :: {reaction_count_info,
telega@model@types:reaction_type(),
integer()}.
-file("src/telega/reactions.gleam", 52).
?DOC(" Create an emoji reaction\n").
-spec emoji(binary()) -> telega@model@types:reaction_type().
emoji(Emoji_str) ->
{reaction_type_emoji_reaction_type,
{reaction_type_emoji, <<"emoji"/utf8>>, Emoji_str}}.
-file("src/telega/reactions.gleam", 60).
?DOC(" Create a custom emoji reaction\n").
-spec custom_emoji(binary()) -> telega@model@types:reaction_type().
custom_emoji(Custom_emoji_id) ->
{reaction_type_custom_emoji_reaction_type,
{reaction_type_custom_emoji, <<"custom_emoji"/utf8>>, Custom_emoji_id}}.
-file("src/telega/reactions.gleam", 68).
?DOC(" Create a paid reaction (stars)\n").
-spec paid() -> telega@model@types:reaction_type().
paid() ->
{reaction_type_paid_reaction_type, {reaction_type_paid, <<"paid"/utf8>>}}.
-file("src/telega/reactions.gleam", 480).
-spec set_reaction(
telega@bot:context(any(), any(), any()),
integer(),
integer(),
gleam@option:option(list(telega@model@types:reaction_type())),
gleam@option:option(boolean())
) -> {ok, boolean()} | {error, telega@error:telega_error()}.
set_reaction(Ctx, Chat_id, Message_id, Reaction, Is_big) ->
telega@api:set_message_reaction(
erlang:element(5, erlang:element(4, Ctx)),
{set_message_reaction_parameters,
{int, Chat_id},
Message_id,
Reaction,
Is_big}
).
-file("src/telega/reactions.gleam", 498).
-spec get_message_id(telega@update:update()) -> gleam@option:option(integer()).
get_message_id(Update) ->
case Update of
{text_update, _, _, _, Message, _} ->
{some, erlang:element(2, Message)};
{command_update, _, _, _, Message@1, _} ->
{some, erlang:element(2, Message@1)};
{photo_update, _, _, _, Message@2, _} ->
{some, erlang:element(2, Message@2)};
{video_update, _, _, _, Message@3, _} ->
{some, erlang:element(2, Message@3)};
{audio_update, _, _, _, Message@4, _} ->
{some, erlang:element(2, Message@4)};
{voice_update, _, _, _, Message@5, _} ->
{some, erlang:element(2, Message@5)};
{media_group_update, _, _, _, _, _} ->
none;
{web_app_update, _, _, _, Message@6, _} ->
{some, erlang:element(2, Message@6)};
{message_update, _, _, Message@7, _} ->
{some, erlang:element(2, Message@7)};
{channel_post_update, _, _, Post, _} ->
{some, erlang:element(2, Post)};
{edited_message_update, _, _, Message@8, _} ->
{some, erlang:element(2, Message@8)};
{edited_channel_post_update, _, _, Post@1, _} ->
{some, erlang:element(2, Post@1)};
{business_message_update, _, _, Message@9, _} ->
{some, erlang:element(2, Message@9)};
{edited_business_message_update, _, _, Message@10, _} ->
{some, erlang:element(2, Message@10)};
{message_reaction_update, _, _, Message_reaction_updated, _} ->
{some, erlang:element(3, Message_reaction_updated)};
{message_reaction_count_update, _, _, Message_reaction_count_updated, _} ->
{some, erlang:element(3, Message_reaction_count_updated)};
{callback_query_update, _, _, Query, _} ->
case erlang:element(4, Query) of
{some, {message_maybe_inaccessible_message, Msg}} ->
{some, erlang:element(2, Msg)};
{some, {inaccessible_message_maybe_inaccessible_message, Msg@1}} ->
{some, erlang:element(3, Msg@1)};
none ->
none
end;
{business_connection_update, _, _, _, _} ->
none;
{deleted_business_message_update, _, _, _, _} ->
none;
{inline_query_update, _, _, _, _} ->
none;
{chosen_inline_result_update, _, _, _, _} ->
none;
{shipping_query_update, _, _, _, _} ->
none;
{pre_checkout_query_update, _, _, _, _} ->
none;
{paid_media_purchase_update, _, _, _, _} ->
none;
{poll_update, _, _, _, _} ->
none;
{poll_answer_update, _, _, _, _} ->
none;
{my_chat_member_update, _, _, _, _} ->
none;
{chat_member_update, _, _, _, _} ->
none;
{chat_join_request_update, _, _, _, _} ->
none;
{removed_chat_boost, _, _, _, _} ->
none;
{managed_bot_update, _, _, _, _} ->
none;
{guest_message_update, _, _, Message@11, _} ->
{some, erlang:element(2, Message@11)};
{subscription_update, _, _, _, _} ->
none
end.
-file("src/telega/reactions.gleam", 146).
?DOC(
" React to the current message with a reaction\n"
"\n"
" ## Example\n"
" ```gleam\n"
" reactions.react(ctx, reactions.thumbs_up)\n"
" ```\n"
).
-spec react(
telega@bot:context(any(), any(), any()),
telega@model@types:reaction_type()
) -> {ok, boolean()} | {error, telega@error:telega_error()}.
react(Ctx, Reaction) ->
case get_message_id(erlang:element(3, Ctx)) of
{some, Message_id} ->
set_reaction(
Ctx,
erlang:element(3, erlang:element(3, Ctx)),
Message_id,
{some, [Reaction]},
none
);
none ->
{error,
{router_error,
<<"No message_id available in current update"/utf8>>}}
end.
-file("src/telega/reactions.gleam", 164).
?DOC(
" React to the current message with an emoji string\n"
"\n"
" ## Example\n"
" ```gleam\n"
" reactions.react_emoji(ctx, \"👍\")\n"
" ```\n"
).
-spec react_emoji(telega@bot:context(any(), any(), any()), binary()) -> {ok,
boolean()} |
{error, telega@error:telega_error()}.
react_emoji(Ctx, Emoji_str) ->
react(Ctx, emoji(Emoji_str)).
-file("src/telega/reactions.gleam", 177).
?DOC(
" React to the current message with multiple reactions\n"
"\n"
" ## Example\n"
" ```gleam\n"
" reactions.react_many(ctx, [reactions.thumbs_up, reactions.heart])\n"
" ```\n"
).
-spec react_many(
telega@bot:context(any(), any(), any()),
list(telega@model@types:reaction_type())
) -> {ok, boolean()} | {error, telega@error:telega_error()}.
react_many(Ctx, Reactions) ->
case get_message_id(erlang:element(3, Ctx)) of
{some, Message_id} ->
set_reaction(
Ctx,
erlang:element(3, erlang:element(3, Ctx)),
Message_id,
{some, Reactions},
none
);
none ->
{error,
{router_error,
<<"No message_id available in current update"/utf8>>}}
end.
-file("src/telega/reactions.gleam", 195).
?DOC(
" React to the current message with a big animation\n"
"\n"
" ## Example\n"
" ```gleam\n"
" reactions.react_big(ctx, reactions.party)\n"
" ```\n"
).
-spec react_big(
telega@bot:context(any(), any(), any()),
telega@model@types:reaction_type()
) -> {ok, boolean()} | {error, telega@error:telega_error()}.
react_big(Ctx, Reaction) ->
case get_message_id(erlang:element(3, Ctx)) of
{some, Message_id} ->
set_reaction(
Ctx,
erlang:element(3, erlang:element(3, Ctx)),
Message_id,
{some, [Reaction]},
{some, true}
);
none ->
{error,
{router_error,
<<"No message_id available in current update"/utf8>>}}
end.
-file("src/telega/reactions.gleam", 219).
?DOC(
" Clear all bot's reactions from the current message\n"
"\n"
" ## Example\n"
" ```gleam\n"
" reactions.clear_reaction(ctx)\n"
" ```\n"
).
-spec clear_reaction(telega@bot:context(any(), any(), any())) -> {ok, boolean()} |
{error, telega@error:telega_error()}.
clear_reaction(Ctx) ->
case get_message_id(erlang:element(3, Ctx)) of
{some, Message_id} ->
set_reaction(
Ctx,
erlang:element(3, erlang:element(3, Ctx)),
Message_id,
{some, []},
none
);
none ->
{error,
{router_error,
<<"No message_id available in current update"/utf8>>}}
end.
-file("src/telega/reactions.gleam", 236).
?DOC(
" React to a specific message by ID\n"
"\n"
" ## Example\n"
" ```gleam\n"
" reactions.react_to_message(ctx, message_id: 123, reaction: reactions.heart)\n"
" ```\n"
).
-spec react_to_message(
telega@bot:context(any(), any(), any()),
integer(),
telega@model@types:reaction_type()
) -> {ok, boolean()} | {error, telega@error:telega_error()}.
react_to_message(Ctx, Message_id, Reaction) ->
set_reaction(
Ctx,
erlang:element(3, erlang:element(3, Ctx)),
Message_id,
{some, [Reaction]},
none
).
-file("src/telega/reactions.gleam", 250).
?DOC(
" React to a specific message in a specific chat\n"
"\n"
" ## Example\n"
" ```gleam\n"
" reactions.react_to_chat_message(ctx, chat_id: -100123, message_id: 456, reaction: reactions.fire)\n"
" ```\n"
).
-spec react_to_chat_message(
telega@bot:context(any(), any(), any()),
integer(),
integer(),
telega@model@types:reaction_type()
) -> {ok, boolean()} | {error, telega@error:telega_error()}.
react_to_chat_message(Ctx, Chat_id, Message_id, Reaction) ->
set_reaction(Ctx, Chat_id, Message_id, {some, [Reaction]}, none).
-file("src/telega/reactions.gleam", 455).
?DOC(" Check if two reactions are equal\n").
-spec reaction_equals(
telega@model@types:reaction_type(),
telega@model@types:reaction_type()
) -> boolean().
reaction_equals(A, B) ->
case {A, B} of
{{reaction_type_emoji_reaction_type, A_inner},
{reaction_type_emoji_reaction_type, B_inner}} ->
erlang:element(3, A_inner) =:= erlang:element(3, B_inner);
{{reaction_type_custom_emoji_reaction_type, A_inner@1},
{reaction_type_custom_emoji_reaction_type, B_inner@1}} ->
erlang:element(3, A_inner@1) =:= erlang:element(3, B_inner@1);
{{reaction_type_paid_reaction_type, _},
{reaction_type_paid_reaction_type, _}} ->
true;
{_, _} ->
false
end.
-file("src/telega/reactions.gleam", 287).
?DOC(
" Get detailed information about reaction changes\n"
"\n"
" ## Example\n"
" ```gleam\n"
" let changes = reactions.get_changes(update)\n"
" list.each(changes.added, fn(r) {\n"
" case reactions.get_emoji(r) {\n"
" Some(e) -> io.println(\"Added: \" <> e)\n"
" None -> Nil\n"
" }\n"
" })\n"
" ```\n"
).
-spec get_changes(telega@model@types:message_reaction_updated()) -> reaction_changes().
get_changes(Update) ->
Old = erlang:element(7, Update),
New = erlang:element(8, Update),
Added = gleam@list:filter(
New,
fun(R) ->
not gleam@list:any(Old, fun(O) -> reaction_equals(R, O) end)
end
),
Removed = gleam@list:filter(
Old,
fun(R@1) ->
not gleam@list:any(New, fun(N) -> reaction_equals(R@1, N) end)
end
),
Kept = gleam@list:filter(
New,
fun(R@2) ->
gleam@list:any(Old, fun(O@1) -> reaction_equals(R@2, O@1) end)
end
),
{reaction_changes, Added, Removed, Kept}.
-file("src/telega/reactions.gleam", 415).
?DOC(
" Get emoji string from a ReactionType (if it's an emoji reaction)\n"
"\n"
" ## Example\n"
" ```gleam\n"
" case reactions.get_emoji(reaction) {\n"
" Some(emoji) -> io.println(\"Emoji: \" <> emoji)\n"
" None -> io.println(\"Not an emoji reaction\")\n"
" }\n"
" ```\n"
).
-spec get_emoji(telega@model@types:reaction_type()) -> gleam@option:option(binary()).
get_emoji(Reaction) ->
case Reaction of
{reaction_type_emoji_reaction_type, Inner} ->
{some, erlang:element(3, Inner)};
_ ->
none
end.
-file("src/telega/reactions.gleam", 311).
?DOC(
" Check if a specific emoji was added\n"
"\n"
" ## Example\n"
" ```gleam\n"
" if reactions.was_added(update, \"👍\") {\n"
" // Handle like\n"
" }\n"
" ```\n"
).
-spec was_added(telega@model@types:message_reaction_updated(), binary()) -> boolean().
was_added(Update, Emoji_str) ->
Changes = get_changes(Update),
gleam@list:any(erlang:element(2, Changes), fun(R) -> case get_emoji(R) of
{some, E} ->
E =:= Emoji_str;
none ->
false
end end).
-file("src/telega/reactions.gleam", 329).
?DOC(
" Check if a specific emoji was removed\n"
"\n"
" ## Example\n"
" ```gleam\n"
" if reactions.was_removed(update, \"👍\") {\n"
" // Handle unlike\n"
" }\n"
" ```\n"
).
-spec was_removed(telega@model@types:message_reaction_updated(), binary()) -> boolean().
was_removed(Update, Emoji_str) ->
Changes = get_changes(Update),
gleam@list:any(erlang:element(3, Changes), fun(R) -> case get_emoji(R) of
{some, E} ->
E =:= Emoji_str;
none ->
false
end end).
-file("src/telega/reactions.gleam", 340).
?DOC(" Check if there are any added reactions\n").
-spec has_added(telega@model@types:message_reaction_updated()) -> boolean().
has_added(Update) ->
Changes = get_changes(Update),
not gleam@list:is_empty(erlang:element(2, Changes)).
-file("src/telega/reactions.gleam", 346).
?DOC(" Check if there are any removed reactions\n").
-spec has_removed(telega@model@types:message_reaction_updated()) -> boolean().
has_removed(Update) ->
Changes = get_changes(Update),
not gleam@list:is_empty(erlang:element(3, Changes)).
-file("src/telega/reactions.gleam", 361).
?DOC(" Get all reaction counts from a MessageReactionCountUpdated\n").
-spec get_counts(telega@model@types:message_reaction_count_updated()) -> list(reaction_count_info()).
get_counts(Update) ->
gleam@list:map(
erlang:element(5, Update),
fun(Rc) ->
{reaction_count_info, erlang:element(2, Rc), erlang:element(3, Rc)}
end
).
-file("src/telega/reactions.gleam", 370).
?DOC(" Get total count across all reactions\n").
-spec get_total_count(telega@model@types:message_reaction_count_updated()) -> integer().
get_total_count(Update) ->
gleam@list:fold(
erlang:element(5, Update),
0,
fun(Acc, Rc) -> Acc + erlang:element(3, Rc) end
).
-file("src/telega/reactions.gleam", 377).
?DOC(" Get count for a specific emoji\n").
-spec get_emoji_count(
telega@model@types:message_reaction_count_updated(),
binary()
) -> integer().
get_emoji_count(Update, Emoji_str) ->
gleam@list:fold(
erlang:element(5, Update),
0,
fun(Acc, Rc) -> case get_emoji(erlang:element(2, Rc)) of
{some, E} when E =:= Emoji_str ->
Acc + erlang:element(3, Rc);
_ ->
Acc
end end
).
-file("src/telega/reactions.gleam", 390).
?DOC(" Get top reactions sorted by count\n").
-spec get_top_reactions(
telega@model@types:message_reaction_count_updated(),
integer()
) -> list(reaction_count_info()).
get_top_reactions(Update, Limit) ->
_pipe = erlang:element(5, Update),
_pipe@1 = gleam@list:map(
_pipe,
fun(Rc) ->
{reaction_count_info, erlang:element(2, Rc), erlang:element(3, Rc)}
end
),
_pipe@2 = gleam@list:sort(
_pipe@1,
fun(A, B) ->
gleam@int:compare(erlang:element(3, B), erlang:element(3, A))
end
),
gleam@list:take(_pipe@2, Limit).
-file("src/telega/reactions.gleam", 423).
?DOC(" Get custom emoji ID from a ReactionType (if it's a custom emoji reaction)\n").
-spec get_custom_emoji_id(telega@model@types:reaction_type()) -> gleam@option:option(binary()).
get_custom_emoji_id(Reaction) ->
case Reaction of
{reaction_type_custom_emoji_reaction_type, Inner} ->
{some, erlang:element(3, Inner)};
_ ->
none
end.
-file("src/telega/reactions.gleam", 431).
?DOC(" Check if a reaction is a paid reaction (stars)\n").
-spec is_paid(telega@model@types:reaction_type()) -> boolean().
is_paid(Reaction) ->
case Reaction of
{reaction_type_paid_reaction_type, _} ->
true;
_ ->
false
end.
-file("src/telega/reactions.gleam", 439).
?DOC(" Check if a reaction is an emoji reaction\n").
-spec is_emoji(telega@model@types:reaction_type()) -> boolean().
is_emoji(Reaction) ->
case Reaction of
{reaction_type_emoji_reaction_type, _} ->
true;
_ ->
false
end.
-file("src/telega/reactions.gleam", 447).
?DOC(" Check if a reaction is a custom emoji reaction\n").
-spec is_custom_emoji(telega@model@types:reaction_type()) -> boolean().
is_custom_emoji(Reaction) ->
case Reaction of
{reaction_type_custom_emoji_reaction_type, _} ->
true;
_ ->
false
end.
-file("src/telega/reactions.gleam", 469).
?DOC(" Check if a reaction matches a specific emoji\n").
-spec matches_emoji(telega@model@types:reaction_type(), binary()) -> boolean().
matches_emoji(Reaction, Emoji_str) ->
case get_emoji(Reaction) of
{some, E} ->
E =:= Emoji_str;
none ->
false
end.