summaryrefslogblamecommitdiff
path: root/lib/plugins/account.ex
blob: 747fbc7f06001ceda227ea26c7428416740f9c5a (plain) (tree)


















                                                                                                
                                                                       





















                                                                                              
                                                                      















                                                                                                 
                                             






                                                                                                                       
                                              









                                                                                                         
                                                     




                                                                                   

                                                          















                                                                                  

                                                                          








                                                                                       


                                                                               















                                                                                                                       
                                                               





                                                
                                                       














                                                                                      
                                                           












                                            

                                                 
                                                     
                                                                          














                                                             
defmodule Nola.Plugins.Account do
    @moduledoc """
    # Account

    * **account** Get current account id and token
    * **auth `<account-id>` `<token>`** Authenticate and link the current nickname to an account
    * **auth** list authentications methods
    * **whoami** list currently authenticated users
    * **web** get a one-time login link to web
    * **enable-telegram** Link a Telegram account
    * **enable-sms** Link a SMS number
    * **enable-untappd** Link a Untappd account
    * **set-name** set account name
    * **setusermeta puppet-nick `<nick>`** Set puppet IRC nickname
    """

    def irc_doc, do: @moduledoc
    def start_link(), do: GenServer.start_link(__MODULE__, [], name: __MODULE__)
    def init(_) do
      {:ok, _} = Registry.register(Nola.PubSub, "messages:private", [])
      {:ok, nil}
    end

    def handle_info({:irc, :text, m = %IRC.Message{account: account, text: "help"}}, state) do
      text = [
        "account: show current account and auth token",
        "auth: show authentications methods",
        "whoami: list authenticated users",
        "set-name <name>: set account name",
        "web: login to web",
        "enable-sms | disable-sms: enable/change or disable sms",
        "enable-telegram: link/change telegram",
        "enable-untappd: link untappd account",
        "getmeta: show meta datas",
        "setusermeta: set user meta",
      ]
      m.replyfun.(text)
      {:noreply, state}
    end

    def handle_info({:irc, :text, m = %IRC.Message{account: account, text: "auth"}}, state) do
      spec = [{{:"$1", :"$2"}, [{:==, :"$2", {:const, account.id}}], [:"$1"]}]
      predicates = :dets.select(Nola.Account.file("predicates"), spec)
      text = for {net, {key, value}} <- predicates, do: "#{net}: #{to_string(key)}: #{value}"
      m.replyfun.(text)
      {:noreply, state}
    end

    def handle_info({:irc, :text, m = %IRC.Message{account: account, text: "whoami"}}, state) do
      users = for user <- IRC.UserTrack.find_by_account(m.account) do
        chans = Enum.map(user.privileges, fn({chan, _}) -> chan end)
                |> Enum.join(" ")
        "#{user.network} - #{user.nick}!#{user.username}@#{user.host} - #{chans}"
      end
      m.replyfun.(users)
      {:noreply, state}
    end

    def handle_info({:irc, :text, m = %IRC.Message{account: account, text: "account"}}, state) do
      account = Nola.Account.lookup(m.sender)
      text = ["Account Id: #{account.id}",
        "Authenticate to this account from another network: \"auth #{account.id} #{account.token}\" to the other bot!"]
      m.replyfun.(text)
      {:noreply, state}
    end

    def handle_info({:irc, :text, m = %IRC.Message{sender: sender, text: "auth"<>_}}, state) do
      #account = Nola.Account.lookup(m.sender)
      case String.split(m.text, " ") do
        ["auth", id, token] ->
          join_account(m, id, token)
        _ ->
          m.replyfun.("Invalid parameters")
      end
      {:noreply, state}
    end

    def handle_info({:irc, :text, m = %IRC.Message{account: account, text: "set-name "<>name}}, state) do
      Nola.Account.update_account_name(account, name)
      m.replyfun.("Name changed: #{name}")
      {:noreply, state}
    end

    def handle_info({:irc, :text, m = %IRC.Message{text: "disable-sms"}}, state) do
      if Nola.Account.get_meta(m.account, "sms-number") do
        Nola.Account.delete_meta(m.account, "sms-number")
        m.replfyun.("SMS disabled.")
      else
        m.replyfun.("SMS already disabled.")
      end
      {:noreply, state}
    end

    def handle_info({:irc, :text, m = %IRC.Message{text: "web"}}, state) do
      auth_url = Untappd.auth_url()
      login_url = Nola.AuthToken.new_url(m.account.id, nil)
      m.replyfun.("-> " <> login_url)
      {:noreply, state}
    end

    def handle_info({:irc, :text, m = %IRC.Message{text: "enable-sms"}}, state) do
      code = String.downcase(EntropyString.small_id())
      Nola.Account.put_meta(m.account, "sms-validation-code", code)
      Nola.Account.put_meta(m.account, "sms-validation-target", m.network)
      number = Nola.IRC.Sms.my_number()
      text = "To enable or change your number for SMS messaging, please send:"
             <> " \"enable #{code}\" to #{number}"
      m.replyfun.(text)
      {:noreply, state}
    end

    def handle_info({:irc, :text, m = %IRC.Message{text: "enable-telegram"}}, state) do
      code = String.downcase(EntropyString.small_id())
      Nola.Account.delete_meta(m.account, "telegram-id")
      Nola.Account.put_meta(m.account, "telegram-validation-code", code)
      Nola.Account.put_meta(m.account, "telegram-validation-target", m.network)
      text = "To enable or change your number for telegram messaging, please open #{Nola.Telegram.my_path()} and send:"
             <> " \"/enable #{code}\""
      m.replyfun.(text)
      {:noreply, state}
    end

    def handle_info({:irc, :text, m = %IRC.Message{text: "enable-untappd"}}, state) do
      auth_url = Untappd.auth_url()
      login_url = Nola.AuthToken.new_url(m.account.id, {:external_redirect, auth_url})
      m.replyfun.(["To link your Untappd account, open this URL:", login_url])
      {:noreply, state}
    end

    def handle_info({:irc, :text, m = %IRC.Message{text: "getmeta"<>_}}, state) do
      result = case String.split(m.text, " ") do
        ["getmeta"] ->
          for {k, v} <- Nola.Account.get_all_meta(m.account) do
            case k do
              "u:"<>key -> "(user) #{key}: #{v}"
              key -> "#{key}: #{v}"
            end
          end
        ["getmeta", key] ->
          value = Nola.Account.get_meta(m.account, key)
          text = if value do
            "#{key}: #{value}"
          else
            "#{key} is not defined"
          end
        _ ->
          "usage: getmeta [key]"
      end
      m.replyfun.(result)
      {:noreply, state}
    end

    def handle_info({:irc, :text, m = %IRC.Message{text: "setusermeta"<>_}}, state) do
      result = case String.split(m.text, " ") do
        ["setusermeta", key, value] ->
          Nola.Account.put_user_meta(m.account, key, value)
          "ok"
        _ ->
          "usage: setusermeta <key> <value>"
      end
      m.replyfun.(result)
      {:noreply, state}
    end

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

    defp join_account(m, id, token) do
      old_account = Nola.Account.lookup(m.sender)
      new_account = Nola.Account.get(id)
      if new_account && token == new_account.token do
        case Nola.Account.merge_account(old_account.id, new_account.id) do
          :ok ->
            if old_account.id == new_account.id do
              m.replyfun.("Already authenticated, but hello")
            else
              m.replyfun.("Accounts merged!")
            end
          _ -> m.replyfun.("Something failed :(")
        end
      else
        m.replyfun.("Invalid token")
      end
    end

  end