diff options
Diffstat (limited to 'lib/telegram.ex')
-rw-r--r-- | lib/telegram.ex | 307 |
1 files changed, 209 insertions, 98 deletions
diff --git a/lib/telegram.ex b/lib/telegram.ex index b161b63..289b913 100644 --- a/lib/telegram.ex +++ b/lib/telegram.ex @@ -34,42 +34,62 @@ defmodule Nola.Telegram do {:ok, %{room_state: room_state}} end - def handle_update(%{"message" => m = %{"chat" => %{"type" => "private"}, "text" => text = "/start"<>_}}, _token, state) do - text = "*Welcome to beautte!*\n\nQuery the bot on IRC and say \"enable-telegram\" to continue." + def handle_update( + %{"message" => m = %{"chat" => %{"type" => "private"}, "text" => text = "/start" <> _}}, + _token, + state + ) do + text = + "*Welcome to beautte!*\n\nQuery the bot on IRC and say \"enable-telegram\" to continue." + send_message(m["chat"]["id"], text) {:ok, %{account: nil}} end - def handle_update(%{"message" => m = %{"chat" => %{"type" => "private"}, "text" => text = "/enable"<>_}}, _token, state) do - key = case String.split(text, " ") do - ["/enable", key | _] -> key - _ -> "nil" - end + def handle_update( + %{"message" => m = %{"chat" => %{"type" => "private"}, "text" => text = "/enable" <> _}}, + _token, + state + ) do + key = + case String.split(text, " ") do + ["/enable", key | _] -> key + _ -> "nil" + end - #Handled message "1247435154:AAGnSSCnySn0RuVxy_SUcDEoOX_rbF6vdq0" %{"message" => + # Handled message "1247435154:AAGnSSCnySn0RuVxy_SUcDEoOX_rbF6vdq0" %{"message" => # %{"chat" => %{"first_name" => "J", "id" => 2075406, "type" => "private", "username" => "ahref"}, # "date" => 1591027272, "entities" => # [%{"length" => 7, "offset" => 0, "type" => "bot_command"}], # "from" => %{"first_name" => "J", "id" => 2075406, "is_bot" => false, "language_code" => "en", "username" => "ahref"}, # "message_id" => 11, "text" => "/enable salope"}, "update_id" => 764148578} account = Nola.Account.find_meta_account("telegram-validation-code", String.downcase(key)) - text = if account do - net = Nola.Account.get_meta(account, "telegram-validation-target") - Nola.Account.put_meta(account, "telegram-id", m["chat"]["id"]) - Nola.Account.put_meta(account, "telegram-username", m["chat"]["username"]) - Nola.Account.put_meta(account, "telegram-username", m["chat"]["username"]) - Nola.Account.delete_meta(account, "telegram-validation-code") - Nola.Account.delete_meta(account, "telegram-validation-target") - Nola.Irc.Connection.broadcast_message(net, account, "Telegram #{m["chat"]["username"]} account added!") - "Yay! Linked to account **#{account.name}**." - else - "Token invalid" - end + + text = + if account do + net = Nola.Account.get_meta(account, "telegram-validation-target") + Nola.Account.put_meta(account, "telegram-id", m["chat"]["id"]) + Nola.Account.put_meta(account, "telegram-username", m["chat"]["username"]) + Nola.Account.put_meta(account, "telegram-username", m["chat"]["username"]) + Nola.Account.delete_meta(account, "telegram-validation-code") + Nola.Account.delete_meta(account, "telegram-validation-target") + + Nola.Irc.Connection.broadcast_message( + net, + account, + "Telegram #{m["chat"]["username"]} account added!" + ) + + "Yay! Linked to account **#{account.name}**." + else + "Token invalid" + end + send_message(m["chat"]["id"], text) {:ok, %{account: account.id}} end - #[debug] Unhandled update: %{"message" => + # [debug] Unhandled update: %{"message" => # %{"chat" => %{"first_name" => "J", "id" => 2075406, "type" => "private", "username" => "ahref"}, # "date" => 1591096015, # "from" => %{"first_name" => "J", "id" => 2075406, "is_bot" => false, "language_code" => "en", "username" => "ahref"}, @@ -87,7 +107,7 @@ defmodule Nola.Telegram do end end - #[debug] Unhandled update: %{"callback_query" => + # [debug] Unhandled update: %{"callback_query" => # %{ # "chat_instance" => "-7948978714441865930", "data" => "evolu.net/#dmz", # "from" => %{"first_name" => "J", "id" => 2075406, "is_bot" => false, "language_code" => "en", "username" => "ahref"}, @@ -101,79 +121,139 @@ defmodule Nola.Telegram do # } # , "update_id" => 218161568} - #def handle_update(t, %{"callback_query" => cb = %{"data" => "resend", "id" => id, "message" => m = %{"message_id" => m_id, "chat" => %{"id" => chat_id}, "reply_to_message" => op}}}) do - #end + # def handle_update(t, %{"callback_query" => cb = %{"data" => "resend", "id" => id, "message" => m = %{"message_id" => m_id, "chat" => %{"id" => chat_id}, "reply_to_message" => op}}}) do + # end - def handle_update(%{"callback_query" => cb = %{"data" => "start-upload:"<>target, "id" => id, "message" => m = %{"message_id" => m_id, "chat" => %{"id" => chat_id}, "reply_to_message" => op}}}, t, state) do + def handle_update( + %{ + "callback_query" => + cb = %{ + "data" => "start-upload:" <> target, + "id" => id, + "message" => + m = %{ + "message_id" => m_id, + "chat" => %{"id" => chat_id}, + "reply_to_message" => op + } + } + }, + t, + state + ) do account = Nola.Account.find_meta_account("telegram-id", chat_id) + if account do - target = case String.split(target, "/") do - ["everywhere"] -> Nola.Membership.of_account(account) - [net, chan] -> [{net, chan}] - end - Telegram.Api.request(t, "editMessageText", chat_id: chat_id, message_id: m_id, text: "Processing...", reply_markup: %{}) - - {content, type} = cond do - op["photo"] -> {op["photo"], ""} - op["voice"] -> {op["voice"], " a voice message"} - op["video"] -> {op["video"], ""} - op["document"] -> {op["document"], ""} - op["animation"] -> {op["animation"], ""} - end + target = + case String.split(target, "/") do + ["everywhere"] -> Nola.Membership.of_account(account) + [net, chan] -> [{net, chan}] + end + + Telegram.Api.request(t, "editMessageText", + chat_id: chat_id, + message_id: m_id, + text: "Processing...", + reply_markup: %{} + ) + + {content, type} = + cond do + op["photo"] -> {op["photo"], ""} + op["voice"] -> {op["voice"], " a voice message"} + op["video"] -> {op["video"], ""} + op["document"] -> {op["document"], ""} + op["animation"] -> {op["animation"], ""} + end + + file = + if is_list(content) && Enum.count(content) > 1 do + Enum.sort_by(content, fn p -> p["file_size"] end, &>=/2) + |> List.first() + else + content + end - file = if is_list(content) && Enum.count(content) > 1 do - Enum.sort_by(content, fn(p) -> p["file_size"] end, &>=/2) - |> List.first() - else - content - end file_id = file["file_id"] file_unique_id = file["file_unique_id"] - text = if(op["caption"], do: ": "<> op["caption"] <> "", else: "") - resend = %{"inline_keyboard" => [ [%{"text" => "re-share", "callback_data" => "resend"}] ]} - spawn(fn() -> - with \ - {:ok, file} <- Telegram.Api.request(t, "getFile", file_id: file_id), - path = "https://api.telegram.org/file/bot#{t}/#{file["file_path"]}", - {:ok, %HTTPoison.Response{status_code: 200, body: body}} <- HTTPoison.get(path), - <<smol_body::binary-size(20), _::binary>> = body, - {:ok, magic} <- GenMagic.Pool.perform(Nola.GenMagic, {:bytes, smol_body}), - bucket = Application.get_env(:nola, :s3, []) |> Keyword.get(:bucket), - ext = Path.extname(file["file_path"]), - s3path = "#{account.id}/#{file_unique_id}#{ext}", - Telegram.Api.request(t, "editMessageText", chat_id: chat_id, message_id: m_id, text: "*Uploading...*", reply_markup: %{}, parse_mode: "MarkdownV2"), - s3req = ExAws.S3.put_object(bucket, s3path, body, acl: :public_read, content_type: magic.mime_type), - {:ok, _} <- ExAws.request(s3req) - do + text = if(op["caption"], do: ": " <> op["caption"] <> "", else: "") + resend = %{"inline_keyboard" => [[%{"text" => "re-share", "callback_data" => "resend"}]]} + + spawn(fn -> + with {:ok, file} <- Telegram.Api.request(t, "getFile", file_id: file_id), + path = "https://api.telegram.org/file/bot#{t}/#{file["file_path"]}", + {:ok, %HTTPoison.Response{status_code: 200, body: body}} <- HTTPoison.get(path), + <<smol_body::binary-size(20), _::binary>> = body, + {:ok, magic} <- GenMagic.Pool.perform(Nola.GenMagic, {:bytes, smol_body}), + bucket = Application.get_env(:nola, :s3, []) |> Keyword.get(:bucket), + ext = Path.extname(file["file_path"]), + s3path = "#{account.id}/#{file_unique_id}#{ext}", + Telegram.Api.request(t, "editMessageText", + chat_id: chat_id, + message_id: m_id, + text: "*Uploading...*", + reply_markup: %{}, + parse_mode: "MarkdownV2" + ), + s3req = + ExAws.S3.put_object(bucket, s3path, body, + acl: :public_read, + content_type: magic.mime_type + ), + {:ok, _} <- ExAws.request(s3req) do path = NolaWeb.Router.Helpers.url(NolaWeb.Endpoint) <> "/files/#{s3path}" - sent = for {net, chan} <- target do - txt = "sent#{type}#{text} #{path}" - Nola.Irc.send_message_as(account, net, chan, txt) - "#{net}/#{chan}" - end + + sent = + for {net, chan} <- target do + txt = "sent#{type}#{text} #{path}" + Nola.Irc.send_message_as(account, net, chan, txt) + "#{net}/#{chan}" + end + if caption = op["caption"], do: as_irc_message(chat_id, caption, account) text = "Sent on " <> Enum.join(sent, ", ") <> " !" - Telegram.Api.request(t, "editMessageText", chat_id: chat_id, message_id: m_id, text: "_Sent!_", reply_markup: %{}, parse_mode: "MarkdownV2") + + Telegram.Api.request(t, "editMessageText", + chat_id: chat_id, + message_id: m_id, + text: "_Sent!_", + reply_markup: %{}, + parse_mode: "MarkdownV2" + ) else error -> - Telegram.Api.request(t, "editMessageText", chat_id: chat_id, message_id: m_id, text: "Something failed.", reply_markup: %{}, parse_mode: "MarkdownV2") - Logger.error("Failed upload from Telegram: #{inspect error}") + Telegram.Api.request(t, "editMessageText", + chat_id: chat_id, + message_id: m_id, + text: "Something failed.", + reply_markup: %{}, + parse_mode: "MarkdownV2" + ) + + Logger.error("Failed upload from Telegram: #{inspect(error)}") end end) end + {:ok, state} end - def handle_update(%{"message" => m = %{"chat" => %{"id" => id, "type" => "private"}, "text" => text}}, _, state) do + def handle_update( + %{"message" => m = %{"chat" => %{"id" => id, "type" => "private"}, "text" => text}}, + _, + state + ) do account = Nola.Account.find_meta_account("telegram-id", id) + if account do as_irc_message(id, text, account) end + {:ok, state} end def handle_update(m, _, state) do - Logger.debug("Unhandled update: #{inspect m}") + Logger.debug("Unhandled update: #{inspect(m)}") {:ok, state} end @@ -188,49 +268,80 @@ defmodule Nola.Telegram do end defp as_irc_message(id, text, account) do - reply_fun = fn(text) -> send_message(id, text) end - trigger_text = cond do - String.starts_with?(text, "/") -> - "/"<>text = text - "!"<>text - Enum.any?(Nola.Irc.Connection.triggers(), fn({trigger, _}) -> String.starts_with?(text, trigger) end) -> - text - true -> - "!"<>text - end - message = %Nola.Message{ - id: FlakeId.get(), - transport: :telegram, + reply_fun = fn text -> send_message(id, text) end + + trigger_text = + cond do + String.starts_with?(text, "/") -> + "/" <> text = text + "!" <> text + + Enum.any?(Nola.Irc.Connection.triggers(), fn {trigger, _} -> + String.starts_with?(text, trigger) + end) -> + text + + true -> + "!" <> text + end + + message = %Nola.Message{ + id: FlakeId.get(), + transport: :telegram, network: "telegram", channel: nil, text: text, account: account, sender: %ExIRC.SenderInfo{nick: account.name}, replyfun: reply_fun, - trigger: Nola.Irc.Connection.extract_trigger(trigger_text), - at: nil + trigger: Nola.Irc.Connection.extract_trigger(trigger_text), + at: nil } - Nola.Irc.Connection.publish(message, ["messages:private", "messages:telegram", "telegram/#{account.id}:messages"]) + + Nola.Irc.Connection.publish(message, [ + "messages:private", + "messages:telegram", + "telegram/#{account.id}:messages" + ]) + message end - defp start_upload(_type, %{"message" => m = %{"chat" => %{"id" => id, "type" => "private"}}}, token, state) do + defp start_upload( + _type, + %{"message" => m = %{"chat" => %{"id" => id, "type" => "private"}}}, + token, + state + ) do account = Nola.Account.find_meta_account("telegram-id", id) + if account do text = if(m["text"], do: m["text"], else: nil) - targets = Nola.Membership.of_account(account) - |> Enum.map(fn({net, chan}) -> "#{net}/#{chan}" end) - |> Enum.map(fn(i) -> %{"text" => i, "callback_data" => "start-upload:#{i}"} end) - kb = if Enum.count(targets) > 1 do - [%{"text" => "everywhere", "callback_data" => "start-upload:everywhere"}] ++ targets - else - targets - end - |> Enum.chunk_every(2) + + targets = + Nola.Membership.of_account(account) + |> Enum.map(fn {net, chan} -> "#{net}/#{chan}" end) + |> Enum.map(fn i -> %{"text" => i, "callback_data" => "start-upload:#{i}"} end) + + kb = + if Enum.count(targets) > 1 do + [%{"text" => "everywhere", "callback_data" => "start-upload:everywhere"}] ++ targets + else + targets + end + |> Enum.chunk_every(2) + keyboard = %{"inline_keyboard" => kb} - Telegram.Api.request(token, "sendMessage", chat_id: id, text: "Where should I send this file?", reply_markup: keyboard, reply_to_message_id: m["message_id"], parse_mode: "MarkdownV2") + + Telegram.Api.request(token, "sendMessage", + chat_id: id, + text: "Where should I send this file?", + reply_markup: keyboard, + reply_to_message_id: m["message_id"], + parse_mode: "MarkdownV2" + ) end + {:ok, state} end - end |