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 = 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() 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 = 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) 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 = 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)) 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 = 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)) 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 = 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 last = List.last(history) {_, active} = Nola.Plugins.Alcoolog.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 = 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 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 # Nola.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 = 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) 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) # {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 = 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) 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, %{}) |> 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 -> # %{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) |> text("invalid value") end else conn |> put_status(:not_found) |> text("not found") end end end