Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F73744
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
7 KB
Subscribers
None
View Options
diff --git a/lib/lsg_telegram/room.ex b/lib/lsg_telegram/room.ex
index f7e42c6..db3308e 100644
--- a/lib/lsg_telegram/room.ex
+++ b/lib/lsg_telegram/room.ex
@@ -1,130 +1,166 @@
defmodule LSG.TelegramRoom do
require Logger
@behaviour Telegram.ChatBot
alias Telegram.Api
- def dets() do
- (LSG.data_path() <> "/telegram-rooms.dets") |> String.to_charlist()
+ @couch "bot-telegram-rooms"
+
+ def rooms(), do: rooms(:with_docs)
+
+ @spec rooms(:with_docs | :ids) :: [Map.t | integer( )]
+ def rooms(:with_docs) do
+ case Couch.get(@couch, :all_docs, include_docs: true) do
+ {:ok, %{"rows" => rows}} -> {:ok, for(%{"doc" => doc} <- rows, do: doc)}
+ error = {:error, _} -> error
+ end
+ end
+
+ def rooms(:ids) do
+ case Couch.get(@couch, :all_docs) do
+ {:ok, %{"rows" => rows}} -> {:ok, for(%{"id" => id} <- rows, do: id)}
+ error = {:error, _} -> error
+ end
+ end
+
+ def room(id, opts \\ []) do
+ Couch.get(@couch, id, opts)
end
+ # TODO: Create couch
def setup() do
- {:ok, _} = :dets.open_file(dets(), [])
:ok
end
def after_start() do
- rooms = :dets.foldl(fn({id, _, _}, acc) -> [id | acc] end, [], dets())
- for id <- rooms, do: Telegram.Bot.ChatBot.Chat.Session.Supervisor.start_child(LSG.Telegram, id)
+ for id <- room_ids(), do: Telegram.Bot.ChatBot.Chat.Session.Supervisor.start_child(LSG.Telegram, Integer.parse(id) |> elem(0))
end
@impl Telegram.ChatBot
- def init(id) do
+ def init(id) when is_integer(id) and id < 0 do
+ Logger.metadata(transport: :telegram, id: id, telegram_room_id: id)
+ tg_room = case room(id) do
+ {:ok, tg_room = %{"network" => _net, "channel" => _chan}} -> tg_room
+ {:error, :not_found} ->
+ [net, chan] = String.split(chat["title"], "/", parts: 2)
+ {net, chan} = case IRC.Connection.get_network(net, chan) do
+ %IRC.Connection{} -> {net, chan}
+ _ -> {nil, nil}
+ end
+ {:ok, _id, _rev} = Couch.post(@couch, %{"_id" => id, "network" => net, "channel" => nil})
+ {:ok, tg_room} = room(id)
+ tg_room
+ end
token = Keyword.get(Application.get_env(:lsg, :telegram, []), :key)
+ %{"network" => net, "channel" => chan} = tg_room
+ Logger.info("Starting ChatBot for room #{id} \"#{chat["title"]}\" #{inspect tg_room}")
{:ok, chat} = Api.request(token, "getChat", chat_id: id)
- Logger.debug("Starting ChatBot for room #{id} \"#{chat["title"]}\"")
- [net, chan] = String.split(chat["title"], "/", parts: 2)
- case IRC.Connection.get_network(net, chan) do
- %IRC.Connection{} ->
+ irc_plumbed = if net && chan do
{:ok, _} = Registry.register(IRC.PubSub, "#{net}/#{chan}:messages", plugin: __MODULE__)
{:ok, _} = Registry.register(IRC.PubSub, "#{net}/#{chan}:triggers", plugin: __MODULE__)
{:ok, _} = Registry.register(IRC.PubSub, "#{net}/#{chan}:outputs", plugin: __MODULE__)
- err ->
- Logger.warn("Did not found telegram match for #{id} \"#{chat["title"]}\"")
+ true
+ else
+ Logger.warn("Did not found telegram match for #{id} \"#{chat["title"]}\"")
+ false
end
- :dets.insert(dets(), {id, net, chan})
- {:ok, %{id: id, net: net, chan: chan}}
+ {:ok, %{id: id, net: net, chan: chan, irc: irc_plumbed}}
+ end
+
+ def init(id) do
+ Logger.error("telegram_room: bad id (not room id)", transport: :telegram, id: id, telegram_room_id: id)
+ :ignoree
end
def handle_update(%{"message" => %{"from" => %{"id" => user_id}, "text" => text}}, _token, state) do
account = IRC.Account.find_meta_account("telegram-id", user_id)
connection = IRC.Connection.get_network(state.net)
IRC.send_message_as(account, state.net, state.chan, text, true)
{:ok, state}
end
def handle_update(data = %{"message" => %{"from" => %{"id" => user_id}, "location" => %{"latitude" => lat, "longitude" => lon}}}, _token, state) do
account = IRC.Account.find_meta_account("telegram-id", user_id)
connection = IRC.Connection.get_network(state.net)
IRC.send_message_as(account, state.net, state.chan, "@ #{lat}, #{lon}", true)
{:ok, state}
end
for type <- ~w(photo voice video document animation) do
def handle_update(data = %{"message" => %{unquote(type) => _}}, token, state) do
upload(unquote(type), data, token, state)
end
end
def handle_update(update, token, state) do
{:ok, state}
end
def handle_info({:irc, _, _, message}, state) do
handle_info({:irc, nil, message}, state)
end
def handle_info({:irc, _, message = %IRC.Message{sender: %{nick: nick}, text: text}}, state) do
if Map.get(message.meta, :from) == self() do
else
body = if Map.get(message.meta, :self), do: text, else: "<#{nick}> #{text}"
LSG.Telegram.send_message(state.id, body)
end
{:ok, state}
end
def handle_info(info, state) do
Logger.info("UNhandled #{inspect info}")
{:ok, state}
end
defp upload(_type, %{"message" => m = %{"chat" => %{"id" => chat_id}, "from" => %{"id" => user_id}}}, token, state) do
account = IRC.Account.find_meta_account("telegram-id", user_id)
if account do
{content, type} = cond do
m["photo"] -> {m["photo"], "photo"}
m["voice"] -> {m["voice"], "voice message"}
m["video"] -> {m["video"], "video"}
m["document"] -> {m["document"], "file"}
m["animation"] -> {m["animation"], "gif"}
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(m["caption"], do: m["caption"] <> " ", else: "")
spawn(fn() ->
with \
{:ok, file} <- Telegram.Api.request(token, "getFile", file_id: file_id),
path = "https://api.telegram.org/file/bot#{token}/#{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(LSG.GenMagic, {:bytes, smol_body}),
bucket = Application.get_env(:lsg, :s3, []) |> Keyword.get(:bucket),
ext = Path.extname(file["file_path"]),
s3path = "#{account.id}/#{file_unique_id}#{ext}",
s3req = ExAws.S3.put_object(bucket, s3path, body, acl: :public_read, content_type: magic.mime_type),
{:ok, _} <- ExAws.request(s3req)
do
path = LSGWeb.Router.Helpers.url(LSGWeb.Endpoint) <> "/files/#{s3path}"
txt = "#{type}: #{text}#{path}"
connection = IRC.Connection.get_network(state.net)
IRC.send_message_as(account, state.net, state.chan, txt, true)
else
error ->
Telegram.Api.request(token, "sendMessage", chat_id: chat_id, text: "File upload failed, sorry.")
Logger.error("Failed upload from Telegram: #{inspect error}")
end
end)
{:ok, state}
end
end
end
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Jun 9, 4:27 AM (1 d, 3 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
47628
Default Alt Text
(7 KB)
Attached To
rNOLA Nola
Event Timeline
Log In to Comment