summaryrefslogblamecommitdiff
path: root/lib/lsg_irc/quatre_cent_vingt_plugin.ex
blob: fff7e4f5d1552d03d8bb3786aa0d5d9751417d3e (plain) (tree)
1
2
3
4
5
6
7
8






                                          
                                                                                              



















                                                                                                                                                                        
                           


                             
                                                                            


                           
                                                                                            
       
                                                                             

                                                                                 
               
           




                                                                                                                            
                                                                 



                                                                 
                                                       












                                                                                                                       



























                                                                     
       

                    


















                                                                     













                                                                                                          

                                               















                                                                  
defmodule LSG.IRC.QuatreCentVingtPlugin do
  require Logger

  @moduledoc """
  # 420

  * **!420**: recorde un nouveau 420.
  * **!420*x**: recorde un nouveau 420*x (*2 = 840, ...) (à vous de faire la multiplication).
  * **!420 pseudo**: stats du pseudo.
  """

  @achievements %{
    1    => ["[le premier… il faut bien commencer un jour]"],
    10   => ["T'en es seulement à 10 ? ╭∩╮(Ο_Ο)╭∩╮"],
    42   => ["Bravo, et est-ce que autant de pétards t'on aidés à trouver la Réponse ? ٩(- ̮̮̃-̃)۶ [42]"],
    100  => ["°º¤ø,¸¸,ø¤º°`°º¤ø,¸,ø¤°º¤ø,¸¸,ø¤º°`°º¤ø,¸ 100 °º¤ø,¸¸,ø¤º°`°º¤ø,¸,ø¤°º¤ø,¸¸,ø¤º°`°º¤ø,¸"],
    115  => [" ۜ\(סּںסּَ` )/ۜ 115!!"]
  }

  @emojis [
    "\\o/",
    "~o~",
    "~~o∞~~",
    "*\\o/*",
    "**\\o/**",
    "*ô*",
  ]

  @coeffs Range.new(1, 100)

  def irc_doc, do: @moduledoc

  def start_link, do: GenServer.start_link(__MODULE__, [], name: __MODULE__)

  def init(_) do
    for coeff <- @coeffs do
      {:ok, _} = Registry.register(IRC.PubSub, "trigger:#{420*coeff}", [plugin: __MODULE__])
    end
    {:ok, _} = Registry.register(IRC.PubSub, "account", [plugin: __MODULE__])
    dets_filename = (LSG.data_path() <> "/420.dets") |> String.to_charlist
    {:ok, dets} = :dets.open_file(dets_filename, [{:type,:bag},{:repair,:force}])
    {:ok, dets}
    :ignore
  end

  for coeff <- @coeffs do
    qvc = to_string(420 * coeff)
    def handle_info({:irc, :trigger, unquote(qvc), m = %IRC.Message{trigger: %IRC.Trigger{args: [], type: :bang}}}, dets) do
      {count, last} = get_statistics_for_nick(dets, m.account.id)
      count = count + unquote(coeff)
      text = achievement_text(count)
      now = DateTime.to_unix(DateTime.utc_now())-1 # this is ugly
      for i <- Range.new(1, unquote(coeff)) do
        :ok = :dets.insert(dets, {m.account.id, now+i})
      end
      last_s = if last do
        last_s = format_relative_timestamp(last)
        " (le dernier était #{last_s})"
      else
        ""
      end
      m.replyfun.("#{m.sender.nick} 420 +#{unquote(coeff)} #{text}#{last_s}")
      {:noreply, dets}
    end
  end

  def handle_info({:irc, :trigger, "420", m = %IRC.Message{trigger: %IRC.Trigger{args: [nick], type: :bang}}}, dets) do
    account = IRC.Account.find_by_nick(m.network, nick)
    if account do
      text = case get_statistics_for_nick(dets, m.account.id) do
        {0, _} -> "#{nick} n'a jamais !420 ... honte à lui."
        {count, last} ->
          last_s = format_relative_timestamp(last)
          "#{nick} 420: total #{count}, le dernier #{last_s}"
      end
      m.replyfun.(text)
    else
      m.replyfun.("je connais pas de #{nick}")
    end
    {:noreply, dets}
  end

  # Account
  def handle_info({:account_change, old_id, new_id}, dets) do
    spec = [{{:"$1", :_}, [{:==, :"$1", {:const, old_id}}], [:"$_"]}]
    Util.ets_mutate_select_each(:dets, dets, spec, fn(table, obj) ->
      rename_object_owner(table, obj, new_id)
    end)
    {:noreply, dets}
  end

  # Account: move from nick to account id
  def handle_info({:accounts, accounts}, dets) do
    for x={:account, _net, _chan, _nick, _account_id} <- accounts do
      handle_info(x, dets)
    end
    {:noreply, dets}
  end
  def handle_info({:account, _net, _chan, nick, account_id}, dets) do
    nick = String.downcase(nick)
    spec = [{{:"$1", :_}, [{:==, :"$1", {:const, nick}}], [:"$_"]}]
    Util.ets_mutate_select_each(:dets, dets, spec, fn(table, obj) ->
      Logger.debug("account:: merging #{nick} -> #{account_id}")
      rename_object_owner(table, obj, account_id)
    end)
    {:noreply, dets}
  end

  def handle_info(_, dets) do
    {:noreply, dets}
  end

  defp rename_object_owner(table, object = {_, at}, account_id) do
    :dets.delete_object(table, object)
    :dets.insert(table, {account_id, at})
  end


  defp format_relative_timestamp(timestamp) do
    alias Timex.Format.DateTime.Formatters
    alias Timex.Timezone
    date = timestamp
    |> DateTime.from_unix!
    |> Timezone.convert("Europe/Paris")

    {:ok, relative} = Formatters.Relative.relative_to(date, Timex.now("Europe/Paris"), "{relative}", "fr")
    {:ok, detail} = Formatters.Default.lformat(date, " ({h24}:{m})", "fr")

    relative <> detail
  end

  defp get_statistics_for_nick(dets, acct) do
    qvc = :dets.lookup(dets, acct) |> Enum.sort
    count = Enum.reduce(qvc, 0, fn(_, acc) -> acc + 1 end)
    {_, last} = List.last(qvc) || {nil, nil}
    {count, last}
  end

  @achievements_keys Map.keys(@achievements)
  defp achievement_text(count) when count in @achievements_keys do
    Enum.random(Map.get(@achievements, count))
  end

  defp achievement_text(count) do
    emoji = Enum.random(@emojis)
    "#{emoji} [#{count}]"
  end

end