diff options
Diffstat (limited to 'lib/nola_web/controllers')
-rw-r--r-- | lib/nola_web/controllers/alcoolog_controller.ex | 323 | ||||
-rw-r--r-- | lib/nola_web/controllers/gpt_controller.ex | 33 | ||||
-rw-r--r-- | lib/nola_web/controllers/icecast_see_controller.ex | 41 | ||||
-rw-r--r-- | lib/nola_web/controllers/irc_auth_sse_controller.ex | 66 | ||||
-rw-r--r-- | lib/nola_web/controllers/irc_controller.ex | 101 | ||||
-rw-r--r-- | lib/nola_web/controllers/network_controller.ex | 11 | ||||
-rw-r--r-- | lib/nola_web/controllers/open_id_controller.ex | 64 | ||||
-rw-r--r-- | lib/nola_web/controllers/page_controller.ex | 53 | ||||
-rw-r--r-- | lib/nola_web/controllers/sms_controller.ex | 10 | ||||
-rw-r--r-- | lib/nola_web/controllers/untappd_controller.ex | 18 |
10 files changed, 720 insertions, 0 deletions
diff --git a/lib/nola_web/controllers/alcoolog_controller.ex b/lib/nola_web/controllers/alcoolog_controller.ex new file mode 100644 index 0000000..3081762 --- /dev/null +++ b/lib/nola_web/controllers/alcoolog_controller.ex @@ -0,0 +1,323 @@ +defmodule NolaWeb.AlcoologController do + use NolaWeb, :controller + require Logger + + plug NolaWeb.ContextPlug when action not in [:token] + plug NolaWeb.ContextPlug, [restrict: :public] when action in [:token] + + def token(conn, %{"token" => token}) do + case Nola.Token.lookup(token) do + {:ok, {:alcoolog, :index, network, channel}} -> index(conn, nil, network, channel) + err -> + Logger.debug("AlcoologControler: token #{inspect err} invalid") + conn + |> put_status(404) + |> text("Page not found") + end + end + + def nick(conn = %{assigns: %{account: account}}, params = %{"network" => network, "nick" => nick}) do + profile_account = IRC.Account.find_always_by_nick(network, nick, nick) + days = String.to_integer(Map.get(params, "days", "180")) + friend? = Enum.member?(IRC.Membership.friends(account), profile_account.id) + if friend? do + stats = Nola.IRC.AlcoologPlugin.get_full_statistics(profile_account.id) + history = for {{nick, ts}, points, active, cl, deg, type, descr, meta} <- Nola.IRC.AlcoologPlugin.nick_history(profile_account) do + %{ + at: ts |> DateTime.from_unix!(:millisecond), + points: points, + active: active, + cl: cl, + deg: deg, + type: type, + description: descr, + meta: meta + } + end + history = Enum.sort(history, &(DateTime.compare(&1.at, &2.at) != :lt)) + |> IO.inspect() + conn + |> assign(:title, "alcoolog #{nick}") + |> render("user.html", network: network, profile: profile_account, days: days, nick: nick, history: history, stats: stats) + else + conn + |> put_status(404) + |> text("Page not found") + end + end + + def nick_stats_json(conn = %{assigns: %{account: account}}, params = %{"network" => network, "nick" => nick}) do + profile_account = IRC.Account.find_always_by_nick(network, nick, nick) + friend? = Enum.member?(IRC.Membership.friends(account), profile_account.id) + if friend? do + stats = Nola.IRC.AlcoologPlugin.get_full_statistics(profile_account.id) + + conn + |> put_resp_content_type("application/json") + |> text(Jason.encode!(stats)) + else + conn + |> put_status(404) + |> json([]) + end + end + + def nick_gls_json(conn = %{assigns: %{account: account}}, params = %{"network" => network, "nick" => nick}) do + profile_account = IRC.Account.find_always_by_nick(network, nick, nick) + friend? = Enum.member?(IRC.Membership.friends(account), profile_account.id) + count = String.to_integer(Map.get(params, "days", "180")) + if friend? do + data = Nola.IRC.AlcoologPlugin.user_over_time_gl(profile_account, count) + delay = count*((24 * 60)*60) + now = DateTime.utc_now() + start_date = DateTime.utc_now() + |> DateTime.shift_zone!("Europe/Paris", Tzdata.TimeZoneDatabase) + |> DateTime.add(-delay, :second, Tzdata.TimeZoneDatabase) + |> DateTime.to_date() + |> Date.to_erl() + filled = (:calendar.date_to_gregorian_days(start_date) .. :calendar.date_to_gregorian_days(DateTime.utc_now |> DateTime.to_date() |> Date.to_erl)) + |> Enum.to_list + |> Enum.map(&(:calendar.gregorian_days_to_date(&1))) + |> Enum.map(&Date.from_erl!(&1)) + |> Enum.map(fn(date) -> + %{date: date, gls: Map.get(data, date, 0)} + end) + |> Enum.sort(&(Date.compare(&1.date, &2.date) != :gt)) + + conn + |> put_resp_content_type("application/json") + |> text(Jason.encode!(filled)) + else + conn + |> put_status(404) + |> json([]) + end + end + + + + def nick_volumes_json(conn = %{assigns: %{account: account}}, params = %{"network" => network, "nick" => nick}) do + profile_account = IRC.Account.find_always_by_nick(network, nick, nick) + friend? = Enum.member?(IRC.Membership.friends(account), profile_account.id) + count = String.to_integer(Map.get(params, "days", "180")) + if friend? do + data = Nola.IRC.AlcoologPlugin.user_over_time(profile_account, count) + delay = count*((24 * 60)*60) + now = DateTime.utc_now() + start_date = DateTime.utc_now() + |> DateTime.shift_zone!("Europe/Paris", Tzdata.TimeZoneDatabase) + |> DateTime.add(-delay, :second, Tzdata.TimeZoneDatabase) + |> DateTime.to_date() + |> Date.to_erl() + filled = (:calendar.date_to_gregorian_days(start_date) .. :calendar.date_to_gregorian_days(DateTime.utc_now |> DateTime.to_date() |> Date.to_erl)) + |> Enum.to_list + |> Enum.map(&(:calendar.gregorian_days_to_date(&1))) + |> Enum.map(&Date.from_erl!(&1)) + |> Enum.map(fn(date) -> + %{date: date, volumes: Map.get(data, date, 0)} + end) + |> Enum.sort(&(Date.compare(&1.date, &2.date) != :gt)) + + conn + |> put_resp_content_type("application/json") + |> text(Jason.encode!(filled)) + else + conn + |> put_status(404) + |> json([]) + end + end + + def nick_log_json(conn = %{assigns: %{account: account}}, %{"network" => network, "nick" => nick}) do + profile_account = IRC.Account.find_always_by_nick(network, nick, nick) + friend? = Enum.member?(IRC.Membership.friends(account), profile_account.id) + if friend? do + history = for {{nick, ts}, points, active, cl, deg, type, descr, meta} <- Nola.IRC.AlcoologPlugin.nick_history(profile_account) do + %{ + at: ts |> DateTime.from_unix!(:millisecond) |> DateTime.to_iso8601(), + points: points, + active: active, + cl: cl, + deg: deg, + type: type, + description: descr, + meta: meta + } + end + last = List.last(history) + {_, active} = Nola.IRC.AlcoologPlugin.user_stats(profile_account) + last = %{last | active: active, at: DateTime.utc_now() |> DateTime.to_iso8601()} + history = history ++ [last] + + conn + |> put_resp_content_type("application/json") + |> text(Jason.encode!(history)) + else + conn + |> put_status(404) + |> json([]) + end + end + + def nick_history_json(conn = %{assigns: %{account: account}}, %{"network" => network, "nick" => nick}) do + profile_account = IRC.Account.find_always_by_nick(network, nick, nick) + friend? = Enum.member?(IRC.Membership.friends(account), profile_account.id) + if friend? do + history = for {_, date, value} <- Nola.IRC.AlcoologAnnouncerPlugin.log(profile_account) do + %{date: DateTime.to_iso8601(date), value: value} + end + conn + |> put_resp_content_type("application/json") + |> text(Jason.encode!(history)) + else + conn + |> put_status(404) + |> json([]) + end + end + + def index(conn = %{assigns: %{account: account}}, %{"network" => network, "chan" => channel}) do + index(conn, account, network, NolaWeb.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 + # NolaWeb.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 = ((24 * 60)*60) + now = DateTime.utc_now() + before7 = now + |> DateTime.add(-(7*aday), :second) + |> DateTime.to_unix(:millisecond) + before15 = now + |> DateTime.add(-(15*aday), :second) + |> DateTime.to_unix(:millisecond) + before31 = now + |> DateTime.add(-(31*aday), :second) + |> DateTime.to_unix(:millisecond) + #match = :ets.fun2ms(fn(obj = {{^nick, date}, _, _, _, _}) when date > before -> obj end) + match = [ + {{{:_, :"$1"}, :_, :_, :_, :_, :_, :_, :_}, + [ + {:>, :"$1", {:const, before15}}, + ], [:"$_"]} + ] + + # 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(Nola.IRC.AlcoologPlugin.ETS, match) + |> Enum.filter(fn({{account, _}, _vol, _cur, _cl, _deg, _name, _cmt, _meta}) -> 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 = Nola.IRC.AlcoologPlugin.get_channel_statistics(account, network, channel) + + 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} + # + conn + |> assign(:title, "alcoolog") + |> render("index.html", network: network, channel: channel, drinks: drinks, top: top, stats: stats) + end + + def index_gls_json(conn = %{assigns: %{account: account}}, %{"network" => network, "chan" => channel}) do + count = 30 + channel = NolaWeb.reformat_chan(channel) + 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) + delay = count*((24 * 60)*60) + now = DateTime.utc_now() + start_date = DateTime.utc_now() + |> DateTime.shift_zone!("Europe/Paris", Tzdata.TimeZoneDatabase) + |> DateTime.add(-delay, :second, Tzdata.TimeZoneDatabase) + |> DateTime.to_date() + |> Date.to_erl() + filled = (:calendar.date_to_gregorian_days(start_date) .. :calendar.date_to_gregorian_days(DateTime.utc_now |> DateTime.to_date() |> Date.to_erl)) + |> Enum.to_list + |> Enum.map(&(:calendar.gregorian_days_to_date(&1))) + |> Enum.map(&Date.from_erl!(&1)) + |> Enum.map(fn(date) -> + {date, (for {a, _, _} <- members, into: Map.new, do: {Map.get(member_names, a.id, a.id), 0})} + end) + |> Enum.into(Map.new) + + gls = Enum.reduce(members, filled, fn({account, _, _}, gls) -> + Enum.reduce(Nola.IRC.AlcoologPlugin.user_over_time_gl(account, count), gls, fn({date, gl}, gls) -> + u = Map.get(gls, date, %{}) + |> Map.put(Map.get(member_names, account.id, account.id), gl) + Map.put(gls, date, u) + end) + end) + + dates = (:calendar.date_to_gregorian_days(start_date) .. :calendar.date_to_gregorian_days(DateTime.utc_now |> DateTime.to_date() |> Date.to_erl)) + |> Enum.to_list + |> Enum.map(&(:calendar.gregorian_days_to_date(&1))) + |> Enum.map(&Date.from_erl!(&1)) + + filled2 = Enum.map(member_names, fn({_, name}) -> + history = (:calendar.date_to_gregorian_days(start_date) .. :calendar.date_to_gregorian_days(DateTime.utc_now |> DateTime.to_date() |> Date.to_erl)) + |> Enum.to_list + |> Enum.map(&(:calendar.gregorian_days_to_date(&1))) + |> Enum.map(&Date.from_erl!(&1)) + |> Enum.map(fn(date) -> + get_in(gls, [date, name]) #%{date: date, gl: get_in(gls, [date, name])} + end) + if Enum.all?(history, fn(x) -> x == 0 end) do + nil + else + %{name: name, history: history} + end + end) + |> Enum.filter(fn(x) -> x end) + + conn + |> put_resp_content_type("application/json") + |> text(Jason.encode!(%{labels: dates, data: filled2})) + end + + def minisync(conn, %{"user_id" => user_id, "key" => key, "value" => value}) do + account = IRC.Account.get(user_id) + if account do + ds = Nola.IRC.AlcoologPlugin.data_state() + meta = Nola.IRC.AlcoologPlugin.get_user_meta(ds, account.id) + case Float.parse(value) do + {val, _} -> + new_meta = Map.put(meta, String.to_existing_atom(key), val) + Nola.IRC.AlcoologPlugin.put_user_meta(ds, account.id, new_meta) + _ -> + conn + |> put_status(:unprocessable_entity) + |> text("invalid value") + end + else + conn + |> put_status(:not_found) + |> text("not found") + end + end + +end diff --git a/lib/nola_web/controllers/gpt_controller.ex b/lib/nola_web/controllers/gpt_controller.ex new file mode 100644 index 0000000..038b235 --- /dev/null +++ b/lib/nola_web/controllers/gpt_controller.ex @@ -0,0 +1,33 @@ +defmodule NolaWeb.GptController do + use NolaWeb, :controller + require Logger + + plug NolaWeb.ContextPlug + + def result(conn, params = %{"id" => result_id}) do + case Nola.IRC.GptPlugin.get_result(result_id) do + {:ok, result} -> + network = Map.get(params, "network") + channel = if c = Map.get(params, "chan"), do: NolaWeb.reformat_chan(c) + render(conn, "result.html", network: network, channel: channel, result: result) + {:error, :not_found} -> + conn + |> put_status(404) + |> text("Page not found") + end + end + + def prompt(conn, params = %{"id" => prompt_id}) do + case Nola.IRC.GptPlugin.get_prompt(prompt_id) do + {:ok, prompt} -> + network = Map.get(params, "network") + channel = if c = Map.get(params, "chan"), do: NolaWeb.reformat_chan(c) + render(conn, "prompt.html", network: network, channel: channel, prompt: prompt) + {:error, :not_found} -> + conn + |> put_status(404) + |> text("Page not found") + end + end + +end diff --git a/lib/nola_web/controllers/icecast_see_controller.ex b/lib/nola_web/controllers/icecast_see_controller.ex new file mode 100644 index 0000000..877ad4e --- /dev/null +++ b/lib/nola_web/controllers/icecast_see_controller.ex @@ -0,0 +1,41 @@ +defmodule NolaWeb.IcecastSseController do + use NolaWeb, :controller + require Logger + + @ping_interval 20_000 + + def sse(conn, _params) do + conn + |> put_resp_header("X-Accel-Buffering", "no") + |> put_resp_header("content-type", "text/event-stream") + |> send_chunked(200) + |> subscribe + |> send_sse_message("ping", "ping") + |> send_sse_message("icecast", Nola.IcecastAgent.get) + |> sse_loop + end + + def subscribe(conn) do + :timer.send_interval(@ping_interval, {:event, :ping}) + {:ok, _} = Registry.register(Nola.BroadcastRegistry, "icecast", []) + conn + end + + def sse_loop(conn) do + {type, event} = receive do + {:event, :ping} -> {"ping", "ping"} + {:icecast, stats} -> {"icecast", stats} + end + + conn + |> send_sse_message(type, event) + |> sse_loop() + end + + defp send_sse_message(conn, type, data) do + json = Jason.encode!(%{type => data}) + {:ok, conn} = chunk(conn, "event: #{type}\ndata: #{json}\n\n") + conn + end + +end diff --git a/lib/nola_web/controllers/irc_auth_sse_controller.ex b/lib/nola_web/controllers/irc_auth_sse_controller.ex new file mode 100644 index 0000000..62ee2b5 --- /dev/null +++ b/lib/nola_web/controllers/irc_auth_sse_controller.ex @@ -0,0 +1,66 @@ +defmodule NolaWeb.IrcAuthSseController do + use NolaWeb, :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, "messages: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 = Nola.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/nola_web/controllers/irc_controller.ex b/lib/nola_web/controllers/irc_controller.ex new file mode 100644 index 0000000..c617e78 --- /dev/null +++ b/lib/nola_web/controllers/irc_controller.ex @@ -0,0 +1,101 @@ +defmodule NolaWeb.IrcController do + use NolaWeb, :controller + + plug NolaWeb.ContextPlug + + def index(conn, params) do + network = Map.get(params, "network") + channel = if c = Map.get(params, "chan"), do: NolaWeb.reformat_chan(c) + commands = for mod <- Enum.uniq([IRC.Account.AccountPlugin] ++ IRC.Plugin.enabled()) do + if is_atom(mod) do + identifier = Module.split(mod) |> List.last |> String.replace("Plugin", "") |> Macro.underscore + {identifier, mod.irc_doc()} + end + end + |> Enum.filter(& &1) + |> Enum.filter(fn({_, doc}) -> doc end) + members = cond do + network && channel -> Enum.map(IRC.UserTrack.channel(network, channel), fn(tuple) -> IRC.UserTrack.User.from_tuple(tuple) end) + 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 + if String.contains?(name, ".txt") do + name = String.replace(name, ".txt", "") + data = data() + if Map.has_key?(data, name) do + lines = Enum.join(data[name], "\n") + text(conn, lines) + else + conn + |> put_status(404) + |> text("Not found") + end + else + do_txt(conn, name) + end + end + def txt(conn, _), do: do_txt(conn, nil) + + + defp do_txt(conn, nil) do + doc = Nola.IRC.TxtPlugin.irc_doc() + data = data() + main = Enum.filter(data, fn({trigger, _}) -> !String.contains?(trigger, ".") end) |> Enum.into(Map.new) + system = Enum.filter(data, fn({trigger, _}) -> String.contains?(trigger, ".") end) |> Enum.into(Map.new) + lines = Enum.reduce(main, 0, fn({_, lines}, acc) -> acc + Enum.count(lines) end) + conn + |> assign(:title, "txt") + |> render("txts.html", data: main, doc: doc, files: Enum.count(main), lines: lines, system: system) + end + + defp do_txt(conn, txt) do + data = data() + base_url = cond do + conn.assigns[:chan] -> "/#{conn.assigns.network}/#{NolaWeb.format_chan(conn.assigns.chan)}" + true -> "/-" + end + if lines = Map.get(data, txt) do + lines = Enum.map(lines, fn(line) -> + line + |> String.split("\\\\") + |> Enum.intersperse(Phoenix.HTML.Tag.tag(:br)) + end) + conn + |> assign(:breadcrumbs, [{"txt", "#{base_url}/txt"}]) + |> assign(:title, "#{txt}.txt") + |> render("txt.html", name: txt, data: lines, doc: nil) + else + conn + |> put_status(404) + |> text("Not found") + end + end + + defp data() do + dir = Application.get_env(:nola, :data_path) <> "/irc.txt/" + Path.wildcard(dir <> "/*.txt") + |> Enum.reduce(%{}, fn(path, m) -> + path = String.split(path, "/") + file = List.last(path) + key = String.replace(file, ".txt", "") + data = dir <> file + |> File.read! + |> String.split("\n") + |> Enum.reject(fn(line) -> + cond do + line == "" -> true + !line -> true + true -> false + end + end) + Map.put(m, key, data) + end) + |> Enum.sort + |> Enum.into(Map.new) + end + +end diff --git a/lib/nola_web/controllers/network_controller.ex b/lib/nola_web/controllers/network_controller.ex new file mode 100644 index 0000000..800294f --- /dev/null +++ b/lib/nola_web/controllers/network_controller.ex @@ -0,0 +1,11 @@ +defmodule NolaWeb.NetworkController do + use NolaWeb, :controller + plug NolaWeb.ContextPlug + + def index(conn, %{"network" => network}) do + conn + |> assign(:title, network) + |> render("index.html") + end + +end diff --git a/lib/nola_web/controllers/open_id_controller.ex b/lib/nola_web/controllers/open_id_controller.ex new file mode 100644 index 0000000..d3fef5d --- /dev/null +++ b/lib/nola_web/controllers/open_id_controller.ex @@ -0,0 +1,64 @@ +defmodule NolaWeb.OpenIdController do + use NolaWeb, :controller + plug NolaWeb.ContextPlug, restrict: :public + require Logger + + def login(conn, _) do + url = OAuth2.Client.authorize_url!(new_client(), scope: "openid", state: Base.url_encode64(:crypto.strong_rand_bytes(32), padding: false)) + redirect(conn, external: url) + end + + def callback(conn, %{"error" => error_code, "error_description" => error}) do + Logger.warn("OpenId error: #{error_code} #{error}") + render(conn, "error.html", error: error) + end + + def callback(conn, %{"code" => code, "state" => state}) do + with \ + client = %{token: %OAuth2.AccessToken{access_token: json}} = OAuth2.Client.get_token!(new_client(), state: state, code: code), + {:ok, %{"access_token" => token}} <- Jason.decode(json), + client = %OAuth2.Client{client | token: %OAuth2.AccessToken{access_token: token}}, + {:ok, %OAuth2.Response{body: body}} <- OAuth2.Client.get(client, "/userinfo"), + {:ok, %{"sub" => id, "preferred_username" => username}} <- Jason.decode(body) + do + if account = conn.assigns.account do + if !IRC.Account.get_meta(account, "identity-id") do # XXX: And oidc id not linked yet + IRC.Account.put_meta(account, "identity-id", id) + end + IRC.Account.put_meta(account, "identity-username", username) + conn + else + conn + end + + conn + |> put_session(:oidc_id, id) + |> put_flash(:info, "Logged in!") + |> redirect(to: Routes.path(conn, "/")) + else + {:error, %OAuth2.Response{status_code: 401}} -> + Logger.error("OpenID: Unauthorized token") + render(conn, "error.html", error: "The token is invalid.") + {:error, %OAuth2.Error{reason: reason}} -> + Logger.error("Error: #{inspect reason}") + render(conn, "error.html", error: reason) + end + end + + def callback(conn, _params) do + render(conn, "error.html", error: "Unspecified error.") + end + + defp new_client() do + config = Application.get_env(:nola, :oidc) + OAuth2.Client.new([ + strategy: OAuth2.Strategy.AuthCode, + client_id: config[:client_id], + client_secret: config[:client_secret], + site: config[:base_url], + authorize_url: config[:authorize_url], + token_url: config[:token_url], + redirect_uri: Routes.open_id_url(NolaWeb.Endpoint, :callback) + ]) + end +end diff --git a/lib/nola_web/controllers/page_controller.ex b/lib/nola_web/controllers/page_controller.ex new file mode 100644 index 0000000..2ac4d0a --- /dev/null +++ b/lib/nola_web/controllers/page_controller.ex @@ -0,0 +1,53 @@ +defmodule NolaWeb.PageController do + use NolaWeb, :controller + + plug NolaWeb.ContextPlug when action not in [:token] + plug NolaWeb.ContextPlug, [restrict: :public] when action in [:token] + + def token(conn, %{"token" => token}) do + with \ + {:ok, account, perks} <- Nola.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 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 + bot_helps = for mod <- Nola.IRC.env(:handlers) do + mod.irc_doc() + end + render conn, "irc.html", bot_helps: bot_helps + end + + 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/nola_web/controllers/sms_controller.ex b/lib/nola_web/controllers/sms_controller.ex new file mode 100644 index 0000000..575655c --- /dev/null +++ b/lib/nola_web/controllers/sms_controller.ex @@ -0,0 +1,10 @@ +defmodule NolaWeb.SmsController do + use NolaWeb, :controller + require Logger + + def ovh_callback(conn, %{"senderid" => from, "message" => message}) do + spawn(fn() -> Nola.IRC.SmsPlugin.incoming(from, String.trim(message)) end) + text(conn, "") + end + +end diff --git a/lib/nola_web/controllers/untappd_controller.ex b/lib/nola_web/controllers/untappd_controller.ex new file mode 100644 index 0000000..d3a540d --- /dev/null +++ b/lib/nola_web/controllers/untappd_controller.ex @@ -0,0 +1,18 @@ +defmodule NolaWeb.UntappdController do + use NolaWeb, :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 |