diff options
Diffstat (limited to 'lib/lsg_web/controllers')
-rw-r--r-- | lib/lsg_web/controllers/alcoolog_controller.ex | 56 | ||||
-rw-r--r-- | lib/lsg_web/controllers/irc_auth_sse_controller.ex | 66 | ||||
-rw-r--r-- | lib/lsg_web/controllers/irc_controller.ex | 27 | ||||
-rw-r--r-- | lib/lsg_web/controllers/network_controller.ex | 11 | ||||
-rw-r--r-- | lib/lsg_web/controllers/page_controller.ex | 50 | ||||
-rw-r--r-- | lib/lsg_web/controllers/sms_controller.ex | 10 | ||||
-rw-r--r-- | lib/lsg_web/controllers/untappd_controller.ex | 18 |
7 files changed, 207 insertions, 31 deletions
diff --git a/lib/lsg_web/controllers/alcoolog_controller.ex b/lib/lsg_web/controllers/alcoolog_controller.ex index 9d5d9d9..b88faa3 100644 --- a/lib/lsg_web/controllers/alcoolog_controller.ex +++ b/lib/lsg_web/controllers/alcoolog_controller.ex @@ -2,9 +2,12 @@ defmodule LSGWeb.AlcoologController do use LSGWeb, :controller require Logger - def index(conn, %{"channel" => channel}) do - case LSG.Token.lookup(channel) do - {:ok, obj} -> index(conn, obj) + plug LSGWeb.ContextPlug when action not in [:token] + plug LSGWeb.ContextPlug, [restrict: :public] when action in [:token] + + def token(conn, %{"token" => token}) do + case LSG.Token.lookup(token) do + {:ok, {:alcoolog, :index, network, channel}} -> index(conn, nil, network, channel) err -> Logger.debug("AlcoologControler: token #{inspect err} invalid") conn @@ -13,8 +16,31 @@ defmodule LSGWeb.AlcoologController do end end - def index(conn, {:alcoolog, :index, channel}) do - aday = 7*((24 * 60)*60) + def index(conn = %{assigns: %{account: account}}, %{"network" => network, "chan" => channel}) do + index(conn, account, network, LSGWeb.reformat_chan(channel)) + end + + def index(conn = %{assigns: %{account: account}}, _) do + index(conn, account, nil, nil) + end + + #def index(conn, params) do + # network = Map.get(params, "network") + # chan = if c = Map.get(params, "chan") do + # LSGWeb.reformat_chan(c) + # end + # irc_conn = if network do + # IRC.Connection.get_network(network, chan) + # end + # bot = if(irc_conn, do: irc_conn.nick)# + # + # conn + # |> put_status(403) + # |> render("auth.html", network: network, channel: chan, irc_conn: conn, bot: bot) + #end + + def index(conn, account, network, channel) do + aday = 18*((24 * 60)*60) now = DateTime.utc_now() before = now |> DateTime.add(-aday, :second) @@ -27,22 +53,28 @@ defmodule LSGWeb.AlcoologController do ], [:"$_"]} ] - nicks_in_channel = IRC.UserTrack.channel(channel) - |> Enum.map(fn({_, nick, _, _, _, _, _}) -> String.downcase(nick) end) # tuple ets: {{nick, date}, volumes, current, nom, commentaire} + members = IRC.Membership.expanded_members_or_friends(account, network, channel) + members_ids = Enum.map(members, fn({account, _, nick}) -> account.id end) + member_names = Enum.reduce(members, %{}, fn({account, _, nick}, acc) -> Map.put(acc, account.id, nick) end) drinks = :ets.select(LSG.IRC.AlcoologPlugin.ETS, match) - #|> Enum.filter(fn({{nick, _}, _, _, _, _}) -> Enum.member?(nicks_in_channel, nick) end) - |> Enum.sort_by(fn({{_, ts}, _, _, _, _}) -> ts end, &>/2) + |> Enum.filter(fn({{account, _}, _, _, _, _}) -> Enum.member?(members_ids, account) end) + |> Enum.map(fn({{account, _}, _, _, _, _} = object) -> {object, Map.get(member_names, account)} end) + |> Enum.sort_by(fn({{{_, ts}, _, _, _, _}, _}) -> ts end, &>/2) - stats = LSG.IRC.AlcoologPlugin.get_channel_statistics(channel) + stats = LSG.IRC.AlcoologPlugin.get_channel_statistics(account, network, channel) - top = Enum.reduce(drinks, %{}, fn({{nick, _}, vol, _, _, _}, acc) -> + top = Enum.reduce(drinks, %{}, fn({{{account_id, _}, vol, _, _, _}, _}, acc) -> + nick = Map.get(member_names, account_id) all = Map.get(acc, nick, 0) Map.put(acc, nick, all + vol) end) |> Enum.sort_by(fn({_nick, count}) -> count end, &>/2) # {date, single_peak} - render(conn, "index.html", channel: channel, drinks: drinks, top: top, stats: stats) + # + conn + |> assign(:title, "alcoolog") + |> render("index.html", network: network, channel: channel, drinks: drinks, top: top, stats: stats) end end diff --git a/lib/lsg_web/controllers/irc_auth_sse_controller.ex b/lib/lsg_web/controllers/irc_auth_sse_controller.ex new file mode 100644 index 0000000..c39a866 --- /dev/null +++ b/lib/lsg_web/controllers/irc_auth_sse_controller.ex @@ -0,0 +1,66 @@ +defmodule LSGWeb.IrcAuthSseController do + use LSGWeb, :controller + require Logger + + @ping_interval 20_000 + @expire_delay :timer.minutes(3) + + def sse(conn, params) do + perks = if uri = Map.get(params, "redirect_to") do + {:redirect, uri} + else + nil + end + token = String.downcase(EntropyString.random_string(65)) + conn + |> assign(:token, token) + |> assign(:perks, perks) + |> put_resp_header("X-Accel-Buffering", "no") + |> put_resp_header("content-type", "text/event-stream") + |> send_chunked(200) + |> subscribe() + |> send_sse_message("token", token) + |> sse_loop + end + + def subscribe(conn) do + :timer.send_interval(@ping_interval, {:event, :ping}) + :timer.send_after(@expire_delay, {:event, :expire}) + {:ok, _} = Registry.register(IRC.PubSub, "message:private", []) + conn + end + + def sse_loop(conn) do + {type, event, exit} = receive do + {:event, :ping} -> {"ping", "ping", false} + {:event, :expire} -> {"expire", "expire", true} + {:irc, :text, %{account: account, text: token} = m} -> + if String.downcase(String.trim(token)) == conn.assigns.token do + path = LSG.AuthToken.new_path(account.id, conn.assigns.perks) + m.replyfun.("ok!") + {"authenticated", path, true} + else + {nil, nil, false} + end + _ -> {nil, nil, false} + end + + conn = if type do + send_sse_message(conn, type, event) + else + conn + end + + if exit do + conn + else + sse_loop(conn) + end + end + + defp send_sse_message(conn, type, data) do + {:ok, conn} = chunk(conn, "event: #{type}\ndata: #{data}\n\n") + conn + end + +end diff --git a/lib/lsg_web/controllers/irc_controller.ex b/lib/lsg_web/controllers/irc_controller.ex index 022807d..e0bf24d 100644 --- a/lib/lsg_web/controllers/irc_controller.ex +++ b/lib/lsg_web/controllers/irc_controller.ex @@ -1,13 +1,21 @@ defmodule LSGWeb.IrcController do use LSGWeb, :controller - def index(conn, _) do - commands = for mod <- (Application.get_env(:lsg, :irc)[:plugins] ++ Application.get_env(:lsg, :irc)[:handlers]) do + plug LSGWeb.ContextPlug + + def index(conn, params) do + network = Map.get(params, "network") + channel = if c = Map.get(params, "channel"), do: LSGWeb.reformat_chan(c) + commands = for mod <- ([IRC.Account.AccountPlugin] ++ Application.get_env(:lsg, :irc)[:plugins] ++ Application.get_env(:lsg, :irc)[:handlers]) do identifier = Module.split(mod) |> List.last |> String.replace("Plugin", "") |> Macro.underscore {identifier, mod.irc_doc()} end |> Enum.reject(fn({_, i}) -> i == nil end) - render conn, "index.html", commands: commands + members = cond do + network -> IRC.Membership.expanded_members_or_friends(conn.assigns.account, network, channel) + true -> IRC.Membership.of_account(conn.assigns.account) + end + render conn, "index.html", network: network, commands: commands, channel: channel, members: members end def txt(conn, %{"name" => name}) do @@ -33,13 +41,22 @@ defmodule LSGWeb.IrcController do doc = LSG.IRC.TxtPlugin.irc_doc() data = data() lines = Enum.reduce(data, 0, fn({_, lines}, acc) -> acc + Enum.count(lines) end) - render conn, "txts.html", data: data, doc: doc, files: Enum.count(data), lines: lines + conn + |> assign(:title, "txt") + |> render("txts.html", data: data, doc: doc, files: Enum.count(data), lines: lines) end defp do_txt(conn, txt) do data = data() + base_url = cond do + conn.assigns[:chan] -> "/#{conn.assigns.network}/#{LSGWeb.format_chan(conn.assigns.chan)}" + true -> "/-" + end if Map.has_key?(data, txt) do - render(conn, "txt.html", name: txt, data: data[txt], doc: nil) + conn + |> assign(:breadcrumbs, [{"txt", "#{base_url}/txt"}]) + |> assign(:title, "#{txt}.txt") + |> render("txt.html", name: txt, data: data[txt], doc: nil) else conn |> put_status(404) diff --git a/lib/lsg_web/controllers/network_controller.ex b/lib/lsg_web/controllers/network_controller.ex new file mode 100644 index 0000000..537c2f6 --- /dev/null +++ b/lib/lsg_web/controllers/network_controller.ex @@ -0,0 +1,11 @@ +defmodule LSGWeb.NetworkController do + use LSGWeb, :controller + plug LSGWeb.ContextPlug + + def index(conn, %{"network" => network}) do + conn + |> assign(:title, network) + |> render("index.html") + end + +end diff --git a/lib/lsg_web/controllers/page_controller.ex b/lib/lsg_web/controllers/page_controller.ex index b356b9c..a87cf1d 100644 --- a/lib/lsg_web/controllers/page_controller.ex +++ b/lib/lsg_web/controllers/page_controller.ex @@ -1,12 +1,35 @@ defmodule LSGWeb.PageController do use LSGWeb, :controller - def index(conn, _params) do - render conn, "index.html" + plug LSGWeb.ContextPlug when action not in [:token] + plug LSGWeb.ContextPlug, [restrict: :public] when action in [:token] + + def token(conn, %{"token" => token}) do + with \ + {:ok, account, perks} <- LSG.AuthToken.lookup(token) + do + IO.puts("Authenticated account #{inspect account}") + conn = put_session(conn, :account, account) + case perks do + nil -> redirect(conn, to: "/") + {:redirect, path} -> redirect(conn, to: path) + {:external_redirect, url} -> redirect(conn, external: url) + end + else + z -> + IO.inspect(z) + text(conn, "Error: invalid or expired token") + end end - def api(conn, _params) do - render conn, "api.html" + def index(conn = %{assigns: %{account: account}}, _) do + memberships = IRC.Membership.of_account(account) + users = IRC.UserTrack.find_by_account(account) + metas = IRC.Account.get_all_meta(account) + predicates = IRC.Account.get_predicates(account) + conn + |> assign(:title, account.name) + |> render("user.html", users: users, memberships: memberships, metas: metas, predicates: predicates) end def irc(conn, _) do @@ -16,16 +39,15 @@ defmodule LSGWeb.PageController do render conn, "irc.html", bot_helps: bot_helps end - def icecast(conn, _params) do - conn - |> json(LSG.IcecastAgent.get) - end - - def widget(conn, options) do - icecast = LSG.IcecastAgent.get - conn - |> put_layout(false) - |> render("widget.html", icecast: icecast) + def authenticate(conn, _) do + with \ + {:account, account_id} when is_binary(account_id) <- {:account, get_session(conn, :account)}, + {:account, account} when not is_nil(account) <- {:account, IRC.Account.get(account_id)} + do + assign(conn, :account, account) + else + _ -> conn + end end end diff --git a/lib/lsg_web/controllers/sms_controller.ex b/lib/lsg_web/controllers/sms_controller.ex new file mode 100644 index 0000000..00c6352 --- /dev/null +++ b/lib/lsg_web/controllers/sms_controller.ex @@ -0,0 +1,10 @@ +defmodule LSGWeb.SmsController do + use LSGWeb, :controller + require Logger + + def ovh_callback(conn, %{"senderid" => from, "message" => message}) do + spawn(fn() -> LSG.IRC.SmsPlugin.incoming(from, String.trim(message)) end) + text(conn, "") + end + +end diff --git a/lib/lsg_web/controllers/untappd_controller.ex b/lib/lsg_web/controllers/untappd_controller.ex new file mode 100644 index 0000000..1c3ceb1 --- /dev/null +++ b/lib/lsg_web/controllers/untappd_controller.ex @@ -0,0 +1,18 @@ +defmodule LSGWeb.UntappdController do + use LSGWeb, :controller + + def callback(conn, %{"code" => code}) do + with \ + {:account, account_id} when is_binary(account_id) <- {:account, get_session(conn, :account)}, + {:account, account} when not is_nil(account) <- {:account, IRC.Account.get(account_id)}, + {:ok, auth_token} <- Untappd.auth_callback(code) + do + IRC.Account.put_meta(account, "untappd-token", auth_token) + text(conn, "OK!") + else + {:account, _} -> text(conn, "Error: account not found") + :error -> text(conn, "Error: untappd authentication failed") + end + end + +end |