summaryrefslogtreecommitdiff
path: root/lib/plugins/account.ex
blob: c11d07724c2a0121a68161810dfd1331224ffb24 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
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(IRC.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(IRC.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 = IRC.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 = IRC.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
      IRC.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 IRC.Account.get_meta(m.account, "sms-number") do
        IRC.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())
      IRC.Account.put_meta(m.account, "sms-validation-code", code)
      IRC.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())
      IRC.Account.delete_meta(m.account, "telegram-id")
      IRC.Account.put_meta(m.account, "telegram-validation-code", code)
      IRC.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} <- IRC.Account.get_all_meta(m.account) do
            case k do
              "u:"<>key -> "(user) #{key}: #{v}"
              key -> "#{key}: #{v}"
            end
          end
        ["getmeta", key] ->
          value = IRC.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] ->
          IRC.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 = IRC.Account.lookup(m.sender)
      new_account = IRC.Account.get(id)
      if new_account && token == new_account.token do
        case IRC.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