summaryrefslogblamecommitdiff
path: root/lib/lsg_web/controllers/alcoolog_controller.ex
blob: 6542f15a38ebc88d0d02965fe2c6e53b9a587c98 (plain) (tree)
1
2
3
4
5
6
7
8
9
10



                                      





                                                                                        







                                                                       































































































































































                                                                                                                                                    























                                                                                                  
                         
                            








                                                 

                                                                                             
                                             
    
                                     


              
                                                                  


                                                                                                               
                                                           


                                                                                                                                    
 
                                                                                    
 
                                                                                            
                                              




                                                          



                                                                                                       

     












































































                                                                                                                                                       
   
defmodule LSGWeb.AlcoologController do
  use LSGWeb, :controller
  require Logger

  plug LSGWeb.ContextPlug when action not in [:token]
  plug LSGWeb.ContextPlug, [restrict: :public] when action in [:token]

  def token(conn, %{"token" => token}) do
    case LSG.Token.lookup(token) do
      {:ok, {:alcoolog, :index, network, channel}} -> index(conn, nil, network, channel)
      err ->
        Logger.debug("AlcoologControler: token #{inspect err} invalid")
        conn
        |> 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 = LSG.IRC.AlcoologPlugin.get_full_statistics(profile_account.id)
      history = for {{nick, ts}, points, active, cl, deg, type, descr, meta} <- LSG.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 = LSG.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 = LSG.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 = LSG.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} <- LSG.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} = LSG.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} <- LSG.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, LSGWeb.reformat_chan(channel))
  end

  def index(conn = %{assigns: %{account: account}}, _) do
    index(conn, account, nil, nil)
  end

  #def index(conn, params) do
  #  network = Map.get(params, "network")
  #  chan = if c = Map.get(params, "chan") do
  #    LSGWeb.reformat_chan(c)
  #  end
  #  irc_conn = if network do
  #    IRC.Connection.get_network(network, chan)
  #  end
  #  bot = if(irc_conn, do: irc_conn.nick)#
  #
  #  conn
  #  |> put_status(403)
  #  |> render("auth.html", network: network, channel: chan, irc_conn: conn, bot: bot)
  #end

  def index(conn, account, network, channel) do
    aday = ((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(LSG.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 = LSG.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 = LSGWeb.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(LSG.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 = LSG.IRC.AlcoologPlugin.data_state()
      meta = LSG.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)
          LSG.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