diff options
author | Jordan Bracco <href@random.sh> | 2025-06-25 19:22:59 +0200 |
---|---|---|
committer | Jordan Bracco <href@random.sh> | 2025-06-25 19:22:59 +0200 |
commit | c934e79e5852e05f714b2d542cc2678e287c49b8 (patch) | |
tree | 55779a0168260fce03e4775eacdd613ffc945588 /lib/web | |
parent | updates (diff) |
format.
Diffstat (limited to '')
23 files changed, 715 insertions, 468 deletions
@@ -25,22 +25,24 @@ defmodule NolaWeb do "♯" end - def format_chan("#"<>chan) do + def format_chan("#" <> chan) do chan end - def format_chan(chan = "!"<>_), do: chan + def format_chan(chan = "!" <> _), do: chan def reformat_chan("♯") do "#" end + def reformat_chan("♯♯") do "##" end - def reformat_chan(chan = "!"<>_), do: chan + + def reformat_chan(chan = "!" <> _), do: chan def reformat_chan(chan) do - "#"<>chan + "#" <> chan end def controller do @@ -55,8 +57,9 @@ defmodule NolaWeb do def view do quote do - use Phoenix.View, root: "lib/web/templates", - namespace: NolaWeb + use Phoenix.View, + root: "lib/web/templates", + namespace: NolaWeb # Import convenience functions from controllers import Phoenix.Controller, only: [get_flash: 2, view_module: 1] diff --git a/lib/web/channels/user_socket.ex b/lib/web/channels/user_socket.ex index eadd4e0..a910ffe 100644 --- a/lib/web/channels/user_socket.ex +++ b/lib/web/channels/user_socket.ex @@ -5,7 +5,7 @@ defmodule NolaWeb.UserSocket do # channel "room:*", NolaWeb.RoomChannel ## Transports - #transport :websocket, Phoenix.Transports.WebSocket + # transport :websocket, Phoenix.Transports.WebSocket # transport :longpoll, Phoenix.Transports.LongPoll # Socket params are passed from the client and can diff --git a/lib/web/components/component.ex b/lib/web/components/component.ex index fff8263..5894536 100644 --- a/lib/web/components/component.ex +++ b/lib/web/components/component.ex @@ -9,6 +9,7 @@ defmodule NolaWeb.Component do def naive_date_time_utc(assigns = %{format: format}) do assigns = assign(assigns, :format, Map.get(@date_time_formats, format, format)) + ~H""" <time class="component" id={"time-#{:erlang.phash2(@datetime)}"} @@ -19,9 +20,11 @@ defmodule NolaWeb.Component do </time> """ end + def naive_date_time_utc(assigns) do naive_date_time_utc(assign(assigns, :format, "%F %H:%M")) end + def get_luxon_format("%H:%M:%S"), do: "TIME_24_WITH_SECONDS" def nick(assigns = %{self: false}) do @@ -39,6 +42,4 @@ defmodule NolaWeb.Component do </span> """ end - - end diff --git a/lib/web/components/event_component.ex b/lib/web/components/event_component.ex index 8af3c67..32af856 100644 --- a/lib/web/components/event_component.ex +++ b/lib/web/components/event_component.ex @@ -38,6 +38,4 @@ defmodule NolaWeb.EventComponent do joined """ end - - end diff --git a/lib/web/components/message_component.ex b/lib/web/components/message_component.ex index 5d0386b..7f9bac7 100644 --- a/lib/web/components/message_component.ex +++ b/lib/web/components/message_component.ex @@ -8,5 +8,4 @@ defmodule NolaWeb.MessageComponent do <div class="inline-block flex-grow cursor-default"><%= @text %></div> """ end - end diff --git a/lib/web/context_plug.ex b/lib/web/context_plug.ex index 0a16340..aca0431 100644 --- a/lib/web/context_plug.ex +++ b/lib/web/context_plug.ex @@ -8,21 +8,27 @@ defmodule NolaWeb.ContextPlug do def get_account(conn) do cond do - get_session(conn, :account) -> get_session(conn, :account) - get_session(conn, :oidc_id) -> if account = Nola.Account.find_meta_account("identity-id", get_session(conn, :oidc_id)), do: account.id - true -> nil + get_session(conn, :account) -> + get_session(conn, :account) + + get_session(conn, :oidc_id) -> + if account = Nola.Account.find_meta_account("identity-id", get_session(conn, :oidc_id)), + do: account.id + + true -> + nil end end def call(conn, opts) do - account = with \ - {:account, account_id} when is_binary(account_id) <- {:account, get_account(conn)}, - {:account, account} when not is_nil(account) <- {:account, Nola.Account.get(account_id)} - do - account - else - _ -> nil - end + account = + with {:account, account_id} when is_binary(account_id) <- {:account, get_account(conn)}, + {:account, account} when not is_nil(account) <- + {:account, Nola.Account.get(account_id)} do + account + else + _ -> nil + end network = Map.get(conn.params, "network") network = if network == "-", do: nil, else: network @@ -30,32 +36,46 @@ defmodule NolaWeb.ContextPlug do oidc_account = Nola.Account.find_meta_account("identity-id", get_session(conn, :oidc_id)) conns = Nola.Irc.Connection.get_network(network) - chan = if c = Map.get(conn.params, "chan") do - NolaWeb.reformat_chan(c) - end + + chan = + if c = Map.get(conn.params, "chan") do + NolaWeb.reformat_chan(c) + end + chan_conn = Nola.Irc.Connection.get_network(network, chan) - memberships = if account do - Nola.Membership.of_account(account) - end + memberships = + if account do + Nola.Membership.of_account(account) + end - auth_required = cond do - Keyword.get(opts, :restrict) == :public -> false - account == nil -> true - network == nil -> false - Keyword.get(opts, :restrict) == :logged_in -> false - network && chan -> - !Enum.member?(memberships, {network, chan}) - network -> - !Enum.any?(memberships, fn({n, _}) -> n == network end) - end + auth_required = + cond do + Keyword.get(opts, :restrict) == :public -> + false - bot = cond do - network && chan && chan_conn -> chan_conn.nick - network && conns -> conns.nick - true -> nil - end + account == nil -> + true + network == nil -> + false + + Keyword.get(opts, :restrict) == :logged_in -> + false + + network && chan -> + !Enum.member?(memberships, {network, chan}) + + network -> + !Enum.any?(memberships, fn {n, _} -> n == network end) + end + + bot = + cond do + network && chan && chan_conn -> chan_conn.nick + network && conns -> conns.nick + true -> nil + end cond do account && auth_required -> @@ -63,30 +83,34 @@ defmodule NolaWeb.ContextPlug do |> put_status(404) |> text("Page not found") |> halt() + auth_required -> conn |> put_status(403) |> render(NolaWeb.AlcoologView, "auth.html", bot: bot, no_header: true, network: network) |> halt() - (network && !conns) -> + + network && !conns -> conn |> put_status(404) |> text("Page not found") |> halt() - (chan && !chan_conn) -> + + chan && !chan_conn -> conn |> put_status(404) |> text("Page not found") |> halt() + true -> - conn = conn - |> assign(:network, network) - |> assign(:chan, chan) - |> assign(:bot, bot) - |> assign(:account, account) - |> assign(:oidc_account, oidc_account) - |> assign(:memberships, memberships) + conn = + conn + |> assign(:network, network) + |> assign(:chan, chan) + |> assign(:bot, bot) + |> assign(:account, account) + |> assign(:oidc_account, oidc_account) + |> assign(:memberships, memberships) end end - end diff --git a/lib/web/controllers/alcoolog_controller.ex b/lib/web/controllers/alcoolog_controller.ex index 8d7fc11..57fc16a 100644 --- a/lib/web/controllers/alcoolog_controller.ex +++ b/lib/web/controllers/alcoolog_controller.ex @@ -2,43 +2,63 @@ 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] + 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) + {:ok, {:alcoolog, :index, network, channel}} -> + index(conn, nil, network, channel) + err -> - Logger.debug("AlcoologControler: token #{inspect err} invalid") + 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 + def nick( + conn = %{assigns: %{account: account}}, + params = %{"network" => network, "nick" => nick} + ) do profile_account = Nola.Account.find_always_by_nick(network, nick, nick) days = String.to_integer(Map.get(params, "days", "180")) friend? = Enum.member?(Nola.Membership.friends(account), profile_account.id) + if friend? do stats = Nola.Plugins.Alcoolog.get_full_statistics(profile_account.id) - history = for {{nick, ts}, points, active, cl, deg, type, descr, meta} <- Nola.Plugins.Alcoolog.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() + + history = + for {{nick, ts}, points, active, cl, deg, type, descr, meta} <- + Nola.Plugins.Alcoolog.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) + |> render("user.html", + network: network, + profile: profile_account, + days: days, + nick: nick, + history: history, + stats: stats + ) else conn |> put_status(404) @@ -46,9 +66,13 @@ defmodule NolaWeb.AlcoologController do end end - def nick_stats_json(conn = %{assigns: %{account: account}}, params = %{"network" => network, "nick" => nick}) do + def nick_stats_json( + conn = %{assigns: %{account: account}}, + params = %{"network" => network, "nick" => nick} + ) do profile_account = Nola.Account.find_always_by_nick(network, nick, nick) friend? = Enum.member?(Nola.Membership.friends(account), profile_account.id) + if friend? do stats = Nola.Plugins.Alcoolog.get_full_statistics(profile_account.id) @@ -62,27 +86,39 @@ defmodule NolaWeb.AlcoologController do end end - def nick_gls_json(conn = %{assigns: %{account: account}}, params = %{"network" => network, "nick" => nick}) do + def nick_gls_json( + conn = %{assigns: %{account: account}}, + params = %{"network" => network, "nick" => nick} + ) do profile_account = Nola.Account.find_always_by_nick(network, nick, nick) friend? = Enum.member?(Nola.Membership.friends(account), profile_account.id) count = String.to_integer(Map.get(params, "days", "180")) + if friend? do data = Nola.Plugins.Alcoolog.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)) + 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") @@ -94,29 +130,39 @@ defmodule NolaWeb.AlcoologController do end end - - - def nick_volumes_json(conn = %{assigns: %{account: account}}, params = %{"network" => network, "nick" => nick}) do + def nick_volumes_json( + conn = %{assigns: %{account: account}}, + params = %{"network" => network, "nick" => nick} + ) do profile_account = Nola.Account.find_always_by_nick(network, nick, nick) friend? = Enum.member?(Nola.Membership.friends(account), profile_account.id) count = String.to_integer(Map.get(params, "days", "180")) + if friend? do data = Nola.Plugins.Alcoolog.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)) + 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") @@ -128,22 +174,29 @@ defmodule NolaWeb.AlcoologController do end end - def nick_log_json(conn = %{assigns: %{account: account}}, %{"network" => network, "nick" => nick}) do + def nick_log_json(conn = %{assigns: %{account: account}}, %{ + "network" => network, + "nick" => nick + }) do profile_account = Nola.Account.find_always_by_nick(network, nick, nick) friend? = Enum.member?(Nola.Membership.friends(account), profile_account.id) + if friend? do - history = for {{nick, ts}, points, active, cl, deg, type, descr, meta} <- Nola.Plugins.Alcoolog.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 + history = + for {{nick, ts}, points, active, cl, deg, type, descr, meta} <- + Nola.Plugins.Alcoolog.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.Plugins.Alcoolog.user_stats(profile_account) last = %{last | active: active, at: DateTime.utc_now() |> DateTime.to_iso8601()} @@ -159,13 +212,19 @@ defmodule NolaWeb.AlcoologController do end end - def nick_history_json(conn = %{assigns: %{account: account}}, %{"network" => network, "nick" => nick}) do + def nick_history_json(conn = %{assigns: %{account: account}}, %{ + "network" => network, + "nick" => nick + }) do profile_account = Nola.Account.find_always_by_nick(network, nick, nick) friend? = Enum.member?(Nola.Membership.friends(account), profile_account.id) + if friend? do - history = for {_, date, value} <- Nola.Plugins.AlcoologAnnouncer.log(profile_account) do - %{date: DateTime.to_iso8601(date), value: value} - end + history = + for {_, date, value} <- Nola.Plugins.AlcoologAnnouncer.log(profile_account) do + %{date: DateTime.to_iso8601(date), value: value} + end + conn |> put_resp_content_type("application/json") |> text(Jason.encode!(history)) @@ -184,7 +243,7 @@ defmodule NolaWeb.AlcoologController do index(conn, account, nil, nil) end - #def index(conn, params) do + # def index(conn, params) do # network = Map.get(params, "network") # chan = if c = Map.get(params, "chan") do # NolaWeb.reformat_chan(c) @@ -197,117 +256,175 @@ defmodule NolaWeb.AlcoologController do # conn # |> put_status(403) # |> render("auth.html", network: network, channel: chan, irc_conn: conn, bot: bot) - #end + # end def index(conn, account, network, channel) do - aday = ((24 * 60)*60) + 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) + + 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}}, - ], [:"$_"]} + {{{:_, :"$1"}, :_, :_, :_, :_, :_, :_, :_}, + [ + {:>, :"$1", {:const, before15}} + ], [:"$_"]} ] - # tuple ets: {{nick, date}, volumes, current, nom, commentaire} + # tuple ets: {{nick, date}, volumes, current, nom, commentaire} members = Nola.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.Plugins.Alcoolog.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) + 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.Plugins.Alcoolog.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.Plugins.Alcoolog.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) + 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) + |> 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 + def index_gls_json(conn = %{assigns: %{account: account}}, %{ + "network" => network, + "chan" => channel + }) do count = 30 channel = NolaWeb.reformat_chan(channel) members = Nola.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) + 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.Plugins.Alcoolog.user_over_time_gl(account, count), gls, fn({date, gl}, gls) -> - u = Map.get(gls, date, %{}) + + 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.Plugins.Alcoolog.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) + + Map.put(gls, date, u) + end) 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})) + 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 -> + # %{date: date, gl: get_in(gls, [date, name])} + 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 = Nola.Account.get(user_id) + if account do ds = Nola.Plugins.Alcoolog.data_state() meta = Nola.Plugins.Alcoolog.get_user_meta(ds, account.id) + case Float.parse(value) do {val, _} -> new_meta = Map.put(meta, String.to_existing_atom(key), val) Nola.Plugins.Alcoolog.put_user_meta(ds, account.id, new_meta) + _ -> conn |> put_status(:unprocessable_entity) @@ -319,5 +436,4 @@ defmodule NolaWeb.AlcoologController do |> text("not found") end end - end diff --git a/lib/web/controllers/icecast_see_controller.ex b/lib/web/controllers/icecast_see_controller.ex index 877ad4e..ca8fb2d 100644 --- a/lib/web/controllers/icecast_see_controller.ex +++ b/lib/web/controllers/icecast_see_controller.ex @@ -11,7 +11,7 @@ defmodule NolaWeb.IcecastSseController do |> send_chunked(200) |> subscribe |> send_sse_message("ping", "ping") - |> send_sse_message("icecast", Nola.IcecastAgent.get) + |> send_sse_message("icecast", Nola.IcecastAgent.get()) |> sse_loop end @@ -22,10 +22,11 @@ defmodule NolaWeb.IcecastSseController do end def sse_loop(conn) do - {type, event} = receive do - {:event, :ping} -> {"ping", "ping"} - {:icecast, stats} -> {"icecast", stats} - end + {type, event} = + receive do + {:event, :ping} -> {"ping", "ping"} + {:icecast, stats} -> {"icecast", stats} + end conn |> send_sse_message(type, event) @@ -37,5 +38,4 @@ defmodule NolaWeb.IcecastSseController do {:ok, conn} = chunk(conn, "event: #{type}\ndata: #{json}\n\n") conn end - end diff --git a/lib/web/controllers/irc_auth_sse_controller.ex b/lib/web/controllers/irc_auth_sse_controller.ex index 01c840b..f67a77f 100644 --- a/lib/web/controllers/irc_auth_sse_controller.ex +++ b/lib/web/controllers/irc_auth_sse_controller.ex @@ -6,12 +6,15 @@ defmodule NolaWeb.IrcAuthSseController do @expire_delay :timer.minutes(3) def sse(conn, params) do - perks = if uri = Map.get(params, "redirect_to") do - {:redirect, uri} - else - nil - end + 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) @@ -31,25 +34,33 @@ defmodule NolaWeb.IrcAuthSseController do 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 + {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 - _ -> {nil, nil, false} - end + end - conn = if type do - send_sse_message(conn, type, event) - else - conn - end + conn = + if type do + send_sse_message(conn, type, event) + else + conn + end if exit do conn @@ -62,5 +73,4 @@ defmodule NolaWeb.IrcAuthSseController do {:ok, conn} = chunk(conn, "event: #{type}\ndata: #{data}\n\n") conn end - end diff --git a/lib/web/controllers/irc_controller.ex b/lib/web/controllers/irc_controller.ex index a78582e..9de807b 100644 --- a/lib/web/controllers/irc_controller.ex +++ b/lib/web/controllers/irc_controller.ex @@ -1,31 +1,46 @@ defmodule NolaWeb.IrcController do use NolaWeb, :controller - plug NolaWeb.ContextPlug + 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([Nola.Plugins.Account] ++ Nola.Plugins.enabled()) do - if is_atom(mod) do - identifier = Module.split(mod) |> List.last |> Macro.underscore - if Kernel.function_exported?(mod, :irc_doc, 0), do: {identifier, mod.irc_doc()} + + commands = + for mod <- Enum.uniq([Nola.Plugins.Account] ++ Nola.Plugins.enabled()) do + if is_atom(mod) do + identifier = Module.split(mod) |> List.last() |> Macro.underscore() + if Kernel.function_exported?(mod, :irc_doc, 0), do: {identifier, mod.irc_doc()} + end end - end - |> Enum.filter(& &1) - |> Enum.filter(fn({_, doc}) -> doc end) - members = cond do - network && channel -> Enum.map(Nola.UserTrack.channel(network, channel), fn(tuple) -> Nola.UserTrack.User.from_tuple(tuple) end) - true -> - Nola.Membership.of_account(conn.assigns.account) - end - render conn, "index.html", network: network, commands: commands, channel: channel, members: members + |> Enum.filter(& &1) + |> Enum.filter(fn {_, doc} -> doc end) + + members = + cond do + network && channel -> + Enum.map(Nola.UserTrack.channel(network, channel), fn tuple -> + Nola.UserTrack.User.from_tuple(tuple) + end) + + true -> + Nola.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) @@ -38,32 +53,54 @@ defmodule NolaWeb.IrcController do do_txt(conn, name) end end - def txt(conn, _), do: do_txt(conn, nil) + def txt(conn, _), do: do_txt(conn, nil) defp do_txt(conn, nil) do doc = Nola.Plugins.Txt.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) + + 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) + |> 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 + + 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) + 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") @@ -77,25 +114,28 @@ defmodule NolaWeb.IrcController do defp data() do dir = Application.get_env(:nola, :data_path) <> "/irc.txt/" + Path.wildcard(dir <> "/*.txt") - |> Enum.reduce(%{}, fn(path, m) -> + |> 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) + + 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) + |> Enum.sort() + |> Enum.into(Map.new()) end - end diff --git a/lib/web/controllers/network_controller.ex b/lib/web/controllers/network_controller.ex index 800294f..07cc291 100644 --- a/lib/web/controllers/network_controller.ex +++ b/lib/web/controllers/network_controller.ex @@ -1,11 +1,10 @@ defmodule NolaWeb.NetworkController do use NolaWeb, :controller - plug NolaWeb.ContextPlug + plug(NolaWeb.ContextPlug) def index(conn, %{"network" => network}) do conn |> assign(:title, network) |> render("index.html") end - end diff --git a/lib/web/controllers/open_id_controller.ex b/lib/web/controllers/open_id_controller.ex index 24dc1a5..b8ea505 100644 --- a/lib/web/controllers/open_id_controller.ex +++ b/lib/web/controllers/open_id_controller.ex @@ -1,10 +1,15 @@ defmodule NolaWeb.OpenIdController do use NolaWeb, :controller - plug NolaWeb.ContextPlug, restrict: :public + 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)) + 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 @@ -14,19 +19,21 @@ defmodule NolaWeb.OpenIdController do 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), + 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}}, + 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 + {:ok, %{"sub" => id, "preferred_username" => username}} <- Jason.decode(body) do if account = conn.assigns.account do - if !Nola.Account.get_meta(account, "identity-id") do # XXX: And oidc id not linked yet - Nola.Account.put_meta(account, "identity-id", id) - end - Nola.Account.put_meta(account, "identity-username", username) - conn + # XXX: And oidc id not linked yet + if !Nola.Account.get_meta(account, "identity-id") do + Nola.Account.put_meta(account, "identity-id", id) + end + + Nola.Account.put_meta(account, "identity-username", username) + conn else conn end @@ -39,8 +46,9 @@ defmodule NolaWeb.OpenIdController do {: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}") + Logger.error("Error: #{inspect(reason)}") render(conn, "error.html", error: reason) end end @@ -51,7 +59,8 @@ defmodule NolaWeb.OpenIdController do defp new_client() do config = Application.get_env(:nola, :oidc) - OAuth2.Client.new([ + + OAuth2.Client.new( strategy: OAuth2.Strategy.AuthCode, client_id: config[:client_id], client_secret: config[:client_secret], @@ -59,6 +68,6 @@ defmodule NolaWeb.OpenIdController do 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/web/controllers/page_controller.ex b/lib/web/controllers/page_controller.ex index cb46b8f..4f3c44e 100644 --- a/lib/web/controllers/page_controller.ex +++ b/lib/web/controllers/page_controller.ex @@ -1,15 +1,14 @@ defmodule NolaWeb.PageController do use NolaWeb, :controller - plug NolaWeb.ContextPlug when action not in [:token] - plug NolaWeb.ContextPlug, [restrict: :public] when action in [:token] + 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}") + 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) @@ -27,27 +26,33 @@ defmodule NolaWeb.PageController do users = Nola.UserTrack.find_by_account(account) metas = Nola.Account.get_all_meta(account) predicates = Nola.Account.get_predicates(account) + conn |> assign(:title, account.name) - |> render("user.html", users: users, memberships: memberships, metas: metas, predicates: predicates) + |> 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 + 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, Nola.Account.get(account_id)} - do + with {:account, account_id} when is_binary(account_id) <- + {:account, get_session(conn, :account)}, + {:account, account} when not is_nil(account) <- {:account, Nola.Account.get(account_id)} do assign(conn, :account, account) else _ -> conn end end - end diff --git a/lib/web/controllers/sms_controller.ex b/lib/web/controllers/sms_controller.ex index 0fffa23..20a58bd 100644 --- a/lib/web/controllers/sms_controller.ex +++ b/lib/web/controllers/sms_controller.ex @@ -3,8 +3,7 @@ defmodule NolaWeb.SmsController do require Logger def ovh_callback(conn, %{"senderid" => from, "message" => message}) do - spawn(fn() -> Nola.Plugins.Sms.incoming(from, String.trim(message)) end) + spawn(fn -> Nola.Plugins.Sms.incoming(from, String.trim(message)) end) text(conn, "") end - end diff --git a/lib/web/controllers/untappd_controller.ex b/lib/web/controllers/untappd_controller.ex index e2e1596..f47f526 100644 --- a/lib/web/controllers/untappd_controller.ex +++ b/lib/web/controllers/untappd_controller.ex @@ -2,11 +2,10 @@ 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)}, + with {:account, account_id} when is_binary(account_id) <- + {:account, get_session(conn, :account)}, {:account, account} when not is_nil(account) <- {:account, Nola.Account.get(account_id)}, - {:ok, auth_token} <- Untappd.auth_callback(code) - do + {:ok, auth_token} <- Untappd.auth_callback(code) do Nola.Account.put_meta(account, "untappd-token", auth_token) text(conn, "OK!") else @@ -14,5 +13,4 @@ defmodule NolaWeb.UntappdController do :error -> text(conn, "Error: untappd authentication failed") end end - end diff --git a/lib/web/live/chat_live.ex b/lib/web/live/chat_live.ex index 6902250..0d45428 100644 --- a/lib/web/live/chat_live.ex +++ b/lib/web/live/chat_live.ex @@ -8,37 +8,46 @@ defmodule NolaWeb.ChatLive do connection = Nola.Irc.Connection.get_network(network, chan) account = Nola.Account.get(account_id) membership = Nola.Membership.of_account(Nola.Account.get(account.id)) + if account && connection && Enum.member?(membership, {connection.network, chan}) do - {:ok, _} = Registry.register(Nola.PubSub, "#{connection.network}:events", plugin: __MODULE__) + {:ok, _} = + Registry.register(Nola.PubSub, "#{connection.network}:events", plugin: __MODULE__) + for t <- ["messages", "triggers", "outputs", "events"] do - {:ok, _} = Registry.register(Nola.PubSub, "#{connection.network}/#{chan}:#{t}", plugin: __MODULE__) + {:ok, _} = + Registry.register(Nola.PubSub, "#{connection.network}/#{chan}:#{t}", plugin: __MODULE__) end Nola.Irc.PuppetConnection.start(account, connection) - users = Nola.UserTrack.channel(connection.network, chan) - |> Enum.map(fn(tuple) -> Nola.UserTrack.User.from_tuple(tuple) end) - |> Enum.reduce(Map.new, fn(user = %{id: id}, acc) -> - Map.put(acc, id, user) - end) - - backlog = case Nola.Plugins.Buffer.select_buffer(connection.network, chan) do - {backlog, _} -> - {backlog, _} = Enum.reduce(backlog, {backlog, nil}, &reduce_contextual_event/2) - Enum.reverse(backlog) - _ -> [] - end - - socket = socket - |> assign(:connection_id, connection.id) - |> assign(:network, connection.network) - |> assign(:chan, chan) - |> assign(:title, "live") - |> assign(:channel, chan) - |> assign(:account_id, account.id) - |> assign(:backlog, backlog) - |> assign(:users, users) - |> assign(:counter, 0) + users = + Nola.UserTrack.channel(connection.network, chan) + |> Enum.map(fn tuple -> Nola.UserTrack.User.from_tuple(tuple) end) + |> Enum.reduce(Map.new(), fn user = %{id: id}, acc -> + Map.put(acc, id, user) + end) + + backlog = + case Nola.Plugins.Buffer.select_buffer(connection.network, chan) do + {backlog, _} -> + {backlog, _} = Enum.reduce(backlog, {backlog, nil}, &reduce_contextual_event/2) + Enum.reverse(backlog) + + _ -> + [] + end + + socket = + socket + |> assign(:connection_id, connection.id) + |> assign(:network, connection.network) + |> assign(:chan, chan) + |> assign(:title, "live") + |> assign(:channel, chan) + |> assign(:account_id, account.id) + |> assign(:backlog, backlog) + |> assign(:users, users) + |> assign(:counter, 0) {:ok, socket} else @@ -54,9 +63,11 @@ defmodule NolaWeb.ChatLive do def handle_info({:irc, :event, event = %{type: :join, user_id: id}}, socket) do if user = Nola.UserTrack.lookup(id) do - socket = socket - |> assign(:users, Map.put(socket.assigns.users, id, user)) - |> append_to_backlog(event) + socket = + socket + |> assign(:users, Map.put(socket.assigns.users, id, user)) + |> append_to_backlog(event) + {:noreply, socket} else {:noreply, socket} @@ -64,23 +75,29 @@ defmodule NolaWeb.ChatLive do end def handle_info({:irc, :event, event = %{type: :nick, user_id: id, nick: nick}}, socket) do - socket = socket - |> assign(:users, update_in(socket.assigns.users, [id, :nick], nick)) - |> append_to_backlog(event) + socket = + socket + |> assign(:users, update_in(socket.assigns.users, [id, :nick], nick)) + |> append_to_backlog(event) + {:noreply, socket} end def handle_info({:irc, :event, event = %{type: :quit, user_id: id}}, socket) do - socket = socket - |> assign(:users, Map.delete(socket.assigns.users, id)) - |> append_to_backlog(event) + socket = + socket + |> assign(:users, Map.delete(socket.assigns.users, id)) + |> append_to_backlog(event) + {:noreply, socket} end def handle_info({:irc, :event, event = %{type: :part, user_id: id}}, socket) do - socket = socket - |> assign(:users, Map.delete(socket.assigns.users, id)) - |> append_to_backlog(event) + socket = + socket + |> assign(:users, Map.delete(socket.assigns.users, id)) + |> append_to_backlog(event) + {:noreply, socket} end @@ -91,13 +108,16 @@ defmodule NolaWeb.ChatLive do # type is text, out, or nil if it's self? def handle_info({:irc, type, message = %Nola.Message{}}, socket) do IO.inspect({:live_message, type, message}) - socket = socket - |> append_to_backlog(message) + + socket = + socket + |> append_to_backlog(message) + {:noreply, socket} end def handle_info(info, socket) do - Logger.debug("Unhandled info: #{inspect info}") + Logger.debug("Unhandled info: #{inspect(info)}") {:noreply, socket} end @@ -109,13 +129,12 @@ defmodule NolaWeb.ChatLive do defp reduce_contextual_event(line, {acc, nil}) do {[line | acc], line} end + defp reduce_contextual_event(line, {acc, last}) do if NaiveDateTime.to_date(last.at) != NaiveDateTime.to_date(line.at) do {[%{type: :day_changed, date: NaiveDateTime.to_date(line.at), at: nil}, line | acc], line} - else - {[line | acc], line} - end - + else + {[line | acc], line} + end end - end diff --git a/lib/web/router.ex b/lib/web/router.ex index fb0df63..18509ac 100644 --- a/lib/web/router.ex +++ b/lib/web/router.ex @@ -2,88 +2,86 @@ defmodule NolaWeb.Router do use NolaWeb, :router pipeline :browser do - plug :accepts, ["html", "txt"] - plug :fetch_session - plug :fetch_flash - plug :fetch_live_flash - plug :protect_from_forgery - plug :put_secure_browser_headers - plug :put_root_layout, {NolaWeb.LayoutView, :root} + plug(:accepts, ["html", "txt"]) + plug(:fetch_session) + plug(:fetch_flash) + plug(:fetch_live_flash) + plug(:protect_from_forgery) + plug(:put_secure_browser_headers) + plug(:put_root_layout, {NolaWeb.LayoutView, :root}) end pipeline :api do - plug :accepts, ["json", "sse"] + plug(:accepts, ["json", "sse"]) end pipeline :matrix_app_service do - plug :accepts, ["json"] - plug Nola.Matrix.Plug.Auth - plug Nola.Matrix.Plug.SetConfig + plug(:accepts, ["json"]) + plug(Nola.Matrix.Plug.Auth) + plug(Nola.Matrix.Plug.SetConfig) end scope "/api", NolaWeb do - pipe_through :api - get "/irc-auth.sse", IrcAuthSseController, :sse - post "/sms/callback/Ovh", SmsController, :ovh_callback, as: :sms + pipe_through(:api) + get("/irc-auth.sse", IrcAuthSseController, :sse) + post("/sms/callback/Ovh", SmsController, :ovh_callback, as: :sms) end scope "/", NolaWeb do - pipe_through :browser - get "/", PageController, :index + pipe_through(:browser) + get("/", PageController, :index) - get "/login/irc/:token", PageController, :token, as: :login - get "/login/oidc", OpenIdController, :login - get "/login/oidc/callback", OpenIdController, :callback + get("/login/irc/:token", PageController, :token, as: :login) + get("/login/oidc", OpenIdController, :login) + get("/login/oidc/callback", OpenIdController, :callback) - get "/api/untappd/callback", UntappdController, :callback, as: :untappd_callback + get("/api/untappd/callback", UntappdController, :callback, as: :untappd_callback) - get "/-", IrcController, :index - get "/-/txt", IrcController, :txt - get "/-/txt/:name", IrcController, :txt + get("/-", IrcController, :index) + get("/-/txt", IrcController, :txt) + get("/-/txt/:name", IrcController, :txt) - get "/-/gpt", GptController, :index - get "/-/gpt/p/:id", GptController, :task - get "/-/gpt/r/:id", GptController, :result + get("/-/gpt", GptController, :index) + get("/-/gpt/p/:id", GptController, :task) + get("/-/gpt/r/:id", GptController, :result) - get "/-/alcoolog", AlcoologController, :index - get "/-/alcoolog/~/:account_name", AlcoologController, :index + get("/-/alcoolog", AlcoologController, :index) + get("/-/alcoolog/~/:account_name", AlcoologController, :index) - get "/:network", NetworkController, :index + get("/:network", NetworkController, :index) - get "/:network/~:nick/alcoolog", AlcoologController, :nick - get "/:network/~:nick/alcoolog/log.json", AlcoologController, :nick_log_json - get "/:network/~:nick/alcoolog/gls.json", AlcoologController, :nick_gls_json - get "/:network/~:nick/alcoolog/volumes.json", AlcoologController, :nick_volumes_json - get "/:network/~:nick/alcoolog/history.json", AlcoologController, :nick_history_json - get "/:network/~:nick/alcoolog/stats.json", AlcoologController, :nick_stats_json + get("/:network/~:nick/alcoolog", AlcoologController, :nick) + get("/:network/~:nick/alcoolog/log.json", AlcoologController, :nick_log_json) + get("/:network/~:nick/alcoolog/gls.json", AlcoologController, :nick_gls_json) + get("/:network/~:nick/alcoolog/volumes.json", AlcoologController, :nick_volumes_json) + get("/:network/~:nick/alcoolog/history.json", AlcoologController, :nick_history_json) + get("/:network/~:nick/alcoolog/stats.json", AlcoologController, :nick_stats_json) - get "/:network/:chan/alcoolog", AlcoologController, :index - get "/:network/:chan/alcoolog/gls.json", AlcoologController, :index_gls_json + get("/:network/:chan/alcoolog", AlcoologController, :index) + get("/:network/:chan/alcoolog/gls.json", AlcoologController, :index_gls_json) - put "/api/alcoolog/minisync/:user_id/meta/:key", AlcoologController, :minisync_put_meta + put("/api/alcoolog/minisync/:user_id/meta/:key", AlcoologController, :minisync_put_meta) - get "/:network/:chan", IrcController, :index - live "/:network/:chan/live", ChatLive - get "/:network/:chan/txt", IrcController, :txt - get "/:network/:chan/txt/:name", IrcController, :txt - get "/:network/:channel/preums", IrcController, :preums - get "/:network/:chan/alcoolog/t/:token", AlcoologController, :token + get("/:network/:chan", IrcController, :index) + live("/:network/:chan/live", ChatLive) + get("/:network/:chan/txt", IrcController, :txt) + get("/:network/:chan/txt/:name", IrcController, :txt) + get("/:network/:channel/preums", IrcController, :preums) + get("/:network/:chan/alcoolog/t/:token", AlcoologController, :token) end scope "/_matrix/:appservice", MatrixAppServiceWeb.V1, as: :matrix do - pipe_through :matrix_app_service + pipe_through(:matrix_app_service) - put "/transactions/:txn_id", TransactionController, :push + put("/transactions/:txn_id", TransactionController, :push) - get "/users/:user_id", UserController, :query - get "/rooms/*room_alias", RoomController, :query + get("/users/:user_id", UserController, :query) + get("/rooms/*room_alias", RoomController, :query) - get "/thirdparty/protocol/:protocol", ThirdPartyController, :query_protocol - get "/thirdparty/user/:protocol", ThirdPartyController, :query_users - get "/thirdparty/location/:protocol", ThirdPartyController, :query_locations - get "/thirdparty/location", ThirdPartyController, :query_location_by_alias - get "/thirdparty/user", ThirdPartyController, :query_user_by_id + get("/thirdparty/protocol/:protocol", ThirdPartyController, :query_protocol) + get("/thirdparty/user/:protocol", ThirdPartyController, :query_users) + get("/thirdparty/location/:protocol", ThirdPartyController, :query_locations) + get("/thirdparty/location", ThirdPartyController, :query_location_by_alias) + get("/thirdparty/user", ThirdPartyController, :query_user_by_id) end - - end diff --git a/lib/web/views/alcoolog_view.ex b/lib/web/views/alcoolog_view.ex index ad52472..3a86038 100644 --- a/lib/web/views/alcoolog_view.ex +++ b/lib/web/views/alcoolog_view.ex @@ -1,6 +1,4 @@ defmodule NolaWeb.AlcoologView do use NolaWeb, :view require Integer - end - diff --git a/lib/web/views/error_helpers.ex b/lib/web/views/error_helpers.ex index 25214bd..156b801 100644 --- a/lib/web/views/error_helpers.ex +++ b/lib/web/views/error_helpers.ex @@ -9,8 +9,8 @@ defmodule NolaWeb.ErrorHelpers do Generates tag for inlined form input errors. """ def error_tag(form, field) do - Enum.map(Keyword.get_values(form.errors, field), fn (error) -> - content_tag :span, translate_error(error), class: "help-block" + Enum.map(Keyword.get_values(form.errors, field), fn error -> + content_tag(:span, translate_error(error), class: "help-block") end) end diff --git a/lib/web/views/error_view.ex b/lib/web/views/error_view.ex index 5cad939..5acd333 100644 --- a/lib/web/views/error_view.ex +++ b/lib/web/views/error_view.ex @@ -12,6 +12,6 @@ defmodule NolaWeb.ErrorView do # In case no render clause matches or no # template is found, let's render it as 500 def template_not_found(_template, assigns) do - render "500.html", assigns + render("500.html", assigns) end end diff --git a/lib/web/views/layout_view.ex b/lib/web/views/layout_view.ex index 663eccf..747740f 100644 --- a/lib/web/views/layout_view.ex +++ b/lib/web/views/layout_view.ex @@ -2,17 +2,27 @@ defmodule NolaWeb.LayoutView do use NolaWeb, :view def liquid_markdown(conn, text) do - context_path = cond do - conn.assigns[:chan] -> "/#{conn.assigns[:network]}/#{NolaWeb.format_chan(conn.assigns[:chan])}" - conn.assigns[:network] -> "/#{conn.assigns[:network]}/-" - true -> "/-" - end + context_path = + cond do + conn.assigns[:chan] -> + "/#{conn.assigns[:network]}/#{NolaWeb.format_chan(conn.assigns[:chan])}" + + conn.assigns[:network] -> + "/#{conn.assigns[:network]}/-" + + true -> + "/-" + end {:ok, ast} = Liquex.parse(text) - context = Liquex.Context.new(%{ - "context_path" => context_path - }) + + context = + Liquex.Context.new(%{ + "context_path" => context_path + }) + {content, _} = Liquex.render(ast, context) + content |> to_string() |> Earmark.as_html!() @@ -20,21 +30,28 @@ defmodule NolaWeb.LayoutView do end def page_title(conn) do - target = cond do - conn.assigns[:chan] -> - "#{conn.assigns.chan} @ #{conn.assigns.network}" - conn.assigns[:network] -> conn.assigns.network - true -> Nola.name() - end - - breadcrumb_title = Enum.map(Map.get(conn.assigns, :breadcrumbs)||[], fn({title, _href}) -> title end) - - title = [conn.assigns[:title], breadcrumb_title, target] - |> List.flatten() - |> Enum.uniq() - |> Enum.filter(fn(x) -> x end) - |> Enum.intersperse(" / ") - |> Enum.join() + target = + cond do + conn.assigns[:chan] -> + "#{conn.assigns.chan} @ #{conn.assigns.network}" + + conn.assigns[:network] -> + conn.assigns.network + + true -> + Nola.name() + end + + breadcrumb_title = + Enum.map(Map.get(conn.assigns, :breadcrumbs) || [], fn {title, _href} -> title end) + + title = + [conn.assigns[:title], breadcrumb_title, target] + |> List.flatten() + |> Enum.uniq() + |> Enum.filter(fn x -> x end) + |> Enum.intersperse(" / ") + |> Enum.join() content_tag(:title, title) end @@ -42,14 +59,16 @@ defmodule NolaWeb.LayoutView do def format_time(date, with_relative \\ true) do alias Timex.Format.DateTime.Formatters alias Timex.Timezone - date = if is_integer(date) do - date - |> DateTime.from_unix!(:millisecond) - |> DateTime.shift_zone!("Europe/Paris", Tzdata.TimeZoneDatabase) - else - date - |> DateTime.shift_zone!("Europe/Paris", Tzdata.TimeZoneDatabase) - end + + date = + if is_integer(date) do + date + |> DateTime.from_unix!(:millisecond) + |> DateTime.shift_zone!("Europe/Paris", Tzdata.TimeZoneDatabase) + else + date + |> DateTime.shift_zone!("Europe/Paris", Tzdata.TimeZoneDatabase) + end now = DateTime.now!("Europe/Paris", Tzdata.TimeZoneDatabase) @@ -57,25 +76,39 @@ defmodule NolaWeb.LayoutView do date_week = Timex.iso_week(date) {y, w} = now_week - now_last_week = {y, w-1} - now_last_roll = 7-Timex.days_to_beginning_of_week(now) + now_last_week = {y, w - 1} + now_last_roll = 7 - Timex.days_to_beginning_of_week(now) date_date = DateTime.to_date(date) now_date = DateTime.to_date(date) - format = cond do - date.year != now.year -> "{D}/{M}/{YYYY} {h24}:{m}" - date_date == now_date -> "{h24}:{m}" - (now_week == date_week) || (date_week == now_last_week && (Date.day_of_week(date) >= now_last_roll)) -> "{WDfull} {h24}:{m}" - (now.year == date.year && now.month == date.month) -> "{WDfull} {D} {h24}:{m}" - true -> "{WDfull} {D} {M} {h24}:{m}" - end + format = + cond do + date.year != now.year -> + "{D}/{M}/{YYYY} {h24}:{m}" - {:ok, relative} = Formatters.Relative.relative_to(date, Timex.now("Europe/Paris"), "{relative}", "fr") - {:ok, full} = Formatters.Default.lformat(date, "{WDfull} {D} {YYYY} {h24}:{m}", "fr") #"{h24}:{m} {WDfull} {D}", "fr") - {:ok, detail} = Formatters.Default.lformat(date, format, "fr") #"{h24}:{m} {WDfull} {D}", "fr") + date_date == now_date -> + "{h24}:{m}" - content_tag(:time, if(with_relative, do: relative, else: detail), [title: full]) - end + now_week == date_week || + (date_week == now_last_week && Date.day_of_week(date) >= now_last_roll) -> + "{WDfull} {h24}:{m}" + + now.year == date.year && now.month == date.month -> + "{WDfull} {D} {h24}:{m}" + true -> + "{WDfull} {D} {M} {h24}:{m}" + end + + {:ok, relative} = + Formatters.Relative.relative_to(date, Timex.now("Europe/Paris"), "{relative}", "fr") + + # "{h24}:{m} {WDfull} {D}", "fr") + {:ok, full} = Formatters.Default.lformat(date, "{WDfull} {D} {YYYY} {h24}:{m}", "fr") + # "{h24}:{m} {WDfull} {D}", "fr") + {:ok, detail} = Formatters.Default.lformat(date, format, "fr") + + content_tag(:time, if(with_relative, do: relative, else: detail), title: full) + end end diff --git a/lib/web/views/network_view.ex b/lib/web/views/network_view.ex index 7a24db1..58b0e55 100644 --- a/lib/web/views/network_view.ex +++ b/lib/web/views/network_view.ex @@ -1,4 +1,3 @@ defmodule NolaWeb.NetworkView do use NolaWeb, :view - end diff --git a/lib/web/views/open_id_view.ex b/lib/web/views/open_id_view.ex index bd8089b..b847202 100644 --- a/lib/web/views/open_id_view.ex +++ b/lib/web/views/open_id_view.ex @@ -1,4 +1,3 @@ defmodule NolaWeb.OpenIdView do use NolaWeb, :view - end |