summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThéophile Choutri <theophile@choutri.eu>2018-01-19 15:08:01 +0100
committerGitHub <noreply@github.com>2018-01-19 15:08:01 +0100
commit77f8aab44fe39b0bc8c8da3c5cd399bb79cead3d (patch)
treecc522f7997834352709fdc8cdade0893b32ac038
parentFix namespaces and improve internal consistency (diff)
Add WHO query (#78)
Support the WHO query
-rw-r--r--lib/exirc/client.ex58
-rw-r--r--lib/exirc/commands.ex5
-rw-r--r--lib/exirc/who.ex17
-rw-r--r--lib/exirc/whois.ex2
4 files changed, 71 insertions, 11 deletions
diff --git a/lib/exirc/client.ex b/lib/exirc/client.ex
index 4dd4d25..f84a1d2 100644
--- a/lib/exirc/client.ex
+++ b/lib/exirc/client.ex
@@ -34,7 +34,8 @@ defmodule ExIRC.Client do
retries: 0,
inet: :inet,
owner: nil,
- whois_buffers: %{}
+ whois_buffers: %{},
+ who_buffers: %{}
end
#################
@@ -177,6 +178,13 @@ defmodule ExIRC.Client do
GenServer.call(client, {:whois, user}, :infinity)
end
+ @doc """
+ Ask the server for the channel's users
+ """
+ @spec who(client :: pid, channel :: binary) :: :ok | {:error, atom()}
+ def who(client, channel) do
+ GenServer.call(client, {:who, channel}, :infinity)
+ end
@doc """
Change mode for a user or channel
@@ -414,6 +422,11 @@ defmodule ExIRC.Client do
{:reply, :ok, state}
end
+ def handle_call({:who, channel}, _from, state) do
+ Transport.send(state, who!(channel))
+ {:reply, :ok, state}
+ end
+
# Handles a call to change mode for a user or channel
def handle_call({:mode, channel_or_nick, flags, args}, _from, state) do
Transport.send(state, mode!(channel_or_nick, flags, args))
@@ -611,10 +624,7 @@ defmodule ExIRC.Client do
## WHOIS
-
-
def handle_data(%ExIRC.Message{cmd: @rpl_whoisuser, args: [_sender, nickname, username, hostname, _, realname]}, state) do
-
user = %{nickname: nickname, username: username, hostname: hostname, realname: realname}
{:noreply, %ClientState{state|whois_buffers: Map.put(state.whois_buffers, nickname, user)}}
end
@@ -632,14 +642,12 @@ defmodule ExIRC.Client do
end
def handle_data(%ExIRC.Message{cmd: @rpl_whoischannels, args: [_sender, nickname, channels]}, state) do
-
chans = String.split(channels, " ")
{:noreply, %ClientState{state|whois_buffers: put_in(state.whois_buffers, [nickname, :channels], chans)}}
end
def handle_data(%ExIRC.Message{cmd: @rpl_whoisserver, args: [_sender, nickname, server_addr, server_name]}, state) do
-
new_buffer = state.whois_buffers
|> put_in([nickname, :server_name], server_name)
|> put_in([nickname, :server_address], server_addr)
@@ -655,11 +663,10 @@ defmodule ExIRC.Client do
end
def handle_data(%ExIRC.Message{cmd: @rpl_whoissecure, args: [_sender, nickname, _message]}, state) do
- {:noreply, %ClientState{state|whois_buffers: put_in(state.whois_buffers, [nickname, :tls?], true)}}
+ {:noreply, %ClientState{state|whois_buffers: put_in(state.whois_buffers, [nickname, :ssl?], true)}}
end
def handle_data(%ExIRC.Message{cmd: @rpl_whoisidle, args: [_sender, nickname, idling_time, signon_time, _message]}, state) do
-
new_buffer = state.whois_buffers
|> put_in([nickname, :idling_time], idling_time)
|> put_in([nickname, :signon_time], signon_time)
@@ -668,13 +675,44 @@ defmodule ExIRC.Client do
def handle_data(%ExIRC.Message{cmd: @rpl_endofwhois, args: [_sender, nickname, _message]}, state) do
buffer = struct(ExIRC.Whois, state.whois_buffers[nickname])
-
send_event {:whois, buffer}, state
{:noreply, %ClientState{state|whois_buffers: Map.delete(state.whois_buffers, nickname)}}
end
- def handle_data(%ExIRC.Message{cmd: @rpl_notopic, args: [channel]}, state) do
+ ## WHO
+
+ def handle_data(%ExIRC.Message{:cmd => "352", :args => [_, channel, user, host, server, nick, mode, hop_and_realn]}, state) do
+ [hop, name] = String.split(hop_and_realn, " ", parts: 2)
+ :binary.compile_pattern(["@", "&", "+"])
+ admin? = String.contains?(mode, "&")
+ away? = String.contains?(mode, "G")
+ founder? = String.contains?(mode, "~")
+ half_operator? = String.contains?(mode, "%")
+ operator? = founder? || admin? || String.contains?(mode, "@")
+ server_operator? = String.contains?(mode, "*")
+ voiced? = String.contains?(mode, "+")
+
+ nick = %{nick: nick, user: user, name: name, server: server, hops: hop, admin?: admin?,
+ away?: away?, founder?: founder?, half_operator?: half_operator?,
+ operator?: operator?, server_operator?: server_operator?, voiced?: voiced?
+ }
+
+ buffer = Map.get(state.who_buffers, channel, [])
+ {:noreply, %ClientState{state | who_buffers: Map.put(state.who_buffers, channel, [nick|buffer])}}
+ end
+
+ def handle_data(%ExIRC.Message{:cmd => "315", :args => [_, channel, _]}, state) do
+ buffer = state
+ |> Map.get(:who_buffers)
+ |> Map.get(channel)
+ |> Enum.map(fn user -> struct(ExIRC.Who, user) end)
+
+ send_event {:who, channel, buffer}, state
+ {:noreply, %ClientState{state | who_buffers: Map.delete(state.who_buffers, channel)}}
+ end
+
+ def handle_data(%ExIRC.Message{cmd: @rpl_notopic, args: [channel]}, state) do
if state.debug? do
debug "INITIAL TOPIC MSG"
debug "1. NO TOPIC SET FOR #{channel}}"
diff --git a/lib/exirc/commands.ex b/lib/exirc/commands.ex
index c4833d5..7f7a130 100644
--- a/lib/exirc/commands.ex
+++ b/lib/exirc/commands.ex
@@ -208,6 +208,11 @@ defmodule ExIRC.Commands do
def whois!(user), do: command! ['WHOIS ', user]
@doc """
+ Send a WHO request about a channel
+ """
+ def who!(channel), do: command! ['WHO ', channel]
+
+ @doc """
Send password to server
"""
def pass!(pwd), do: command! ['PASS ', pwd]
diff --git a/lib/exirc/who.ex b/lib/exirc/who.ex
new file mode 100644
index 0000000..583717f
--- /dev/null
+++ b/lib/exirc/who.ex
@@ -0,0 +1,17 @@
+defmodule ExIRC.Who do
+
+ defstruct [
+ admin?: nil,
+ away?: nil,
+ founder?: nil,
+ half_operator?: nil,
+ hops: nil,
+ name: nil,
+ nickname: nil,
+ operator?: nil,
+ server: nil,
+ server_operator?: nil,
+ user: nil,
+ voiced?: nil
+ ]
+end
diff --git a/lib/exirc/whois.ex b/lib/exirc/whois.ex
index 3970214..8b9d987 100644
--- a/lib/exirc/whois.ex
+++ b/lib/exirc/whois.ex
@@ -12,7 +12,7 @@ defmodule ExIRC.Whois do
server_address: nil,
server_name: nil,
signon_time: 0,
- tls?: false,
+ ssl?: false,
username: nil,
]
end