summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThéophile Choutri <theophile@choutri.eu>2017-12-09 00:13:23 +0100
committerThéophile Choutri <theophile@choutri.eu>2017-12-11 22:14:07 +0100
commita4fd0858575918acc2ea5de1e03742b01256c0c2 (patch)
tree2fb1680638eb9f3aef9d520f844de205e3092bc4
parentMerge pull request #70 from w1gz/master (diff)
testing this, now
-rw-r--r--lib/exirc/channels.ex10
-rw-r--r--lib/exirc/client.ex69
-rw-r--r--lib/exirc/commands.ex23
-rw-r--r--lib/exirc/logger.ex6
-rw-r--r--lib/exirc/utils.ex14
5 files changed, 100 insertions, 22 deletions
diff --git a/lib/exirc/channels.ex b/lib/exirc/channels.ex
index b108de9..f274ef1 100644
--- a/lib/exirc/channels.ex
+++ b/lib/exirc/channels.ex
@@ -72,7 +72,7 @@ defmodule ExIrc.Channels do
Update the type of a tracked channel when it changes
"""
def set_type(channel_tree, channel_name, channel_type) when is_binary(channel_type) do
- set_type(channel_tree, channel_name, String.to_char_list(channel_type))
+ set_type(channel_tree, channel_name, String.to_charlist(channel_type))
end
def set_type(channel_tree, channel_name, channel_type) do
name = downcase(channel_name)
@@ -104,7 +104,7 @@ defmodule ExIrc.Channels do
Add multiple users to a tracked channel (used primarily in conjunction with the NAMES command)
"""
def users_join(channel_tree, channel_name, nicks) do
- pnicks = strip_rank(nicks)
+ pnicks = trim_rank(nicks)
manipfn = fn(channel_nicks) -> :lists.usort(channel_nicks ++ pnicks) end
users_manip(channel_tree, channel_name, manipfn)
end
@@ -113,13 +113,13 @@ defmodule ExIrc.Channels do
Remove a user from a tracked channel when they leave
"""
def user_part(channel_tree, channel_name, nick) do
- pnick = strip_rank([nick])
+ pnick = trim_rank([nick])
manipfn = fn(channel_nicks) -> :lists.usort(channel_nicks -- pnick) end
users_manip(channel_tree, channel_name, manipfn)
end
def user_quit(channel_tree, nick) do
- pnick = strip_rank([nick])
+ pnick = trim_rank([nick])
manipfn = fn(channel_nicks) -> :lists.usort(channel_nicks -- pnick) end
foldl = fn(channel_name, new_channel_tree) ->
name = downcase(channel_name)
@@ -217,7 +217,7 @@ defmodule ExIrc.Channels do
end
end
- defp strip_rank(nicks) do
+ defp trim_rank(nicks) do
nicks |> Enum.map(fn(n) -> case n do
<< "@", nick :: binary >> -> nick
<< "+", nick :: binary >> -> nick
diff --git a/lib/exirc/client.ex b/lib/exirc/client.ex
index 9d6905b..36cb87d 100644
--- a/lib/exirc/client.ex
+++ b/lib/exirc/client.ex
@@ -33,7 +33,8 @@ defmodule ExIrc.Client do
debug?: false,
retries: 0,
inet: :inet,
- owner: nil
+ owner: nil,
+ whois_buffers: %{}
end
#################
@@ -167,6 +168,13 @@ defmodule ExIrc.Client do
def names(client, channel) do
GenServer.call(client, {:names, channel}, :infinity)
end
+
+ @spec whois(client :: pid, user :: binary) :: :ok | {:error, atom()}
+ def whois(client, user) do
+ GenServer.call(client, {:whois, user}, :infinity)
+ end
+
+
@doc """
Change mode for a user or channel
"""
@@ -330,7 +338,7 @@ defmodule ExIrc.Client do
# Set SSL mode
state = %{state | ssl?: ssl}
# Open a new connection
- case Transport.connect(state, String.to_char_list(server), port, [:list, {:packet, :line}, {:keepalive, true}] ++ options) do
+ case Transport.connect(state, String.to_charlist(server), port, [:list, {:packet, :line}, {:keepalive, true}] ++ options) do
{:ok, socket} ->
send_event {:connected, server, port}, state
{:reply, :ok, %{state | connected?: true, server: server, port: port, socket: socket}}
@@ -397,6 +405,12 @@ defmodule ExIrc.Client do
Transport.send(state, names!(channel))
{:reply, :ok, state}
end
+
+ def handle_call({:whois, user}, _from, state) do
+ Transport.send(state, whois!(user))
+ {: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))
@@ -551,7 +565,7 @@ defmodule ExIrc.Client do
end
# Called when the client enters a channel
def handle_data(%IrcMessage{nick: nick, cmd: "JOIN"} = msg, %ClientState{nick: nick} = state) do
- channel = msg.args |> List.first |> String.strip
+ channel = msg.args |> List.first |> String.trim
if state.debug?, do: debug "JOINED A CHANNEL #{channel}"
channels = Channels.join(state.channels, channel)
new_state = %{state | channels: channels}
@@ -561,7 +575,7 @@ defmodule ExIrc.Client do
# Called when another user joins a channel the client is in
def handle_data(%IrcMessage{nick: user_nick, cmd: "JOIN", host: host, user: user} = msg, state) do
sender = %SenderInfo{nick: user_nick, host: host, user: user}
- channel = msg.args |> List.first |> String.strip
+ channel = msg.args |> List.first |> String.trim
if state.debug?, do: debug "ANOTHER USER JOINED A CHANNEL: #{channel} - #{user_nick}"
channels = Channels.user_join(state.channels, channel, user_nick)
new_state = %{state | channels: channels}
@@ -589,6 +603,47 @@ defmodule ExIrc.Client do
send_event {:topic_changed, channel, topic}, new_state
{:noreply, new_state}
end
+
+
+ ## WHOIS
+
+ def handle_data(%IrcMessage{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
+
+ def handle_data(%IrcMessage{cmd: @rpl_whoischannels, args: [_sender, nickname, channels]}, state) do
+ {:noreply, %ClientState{state|whois_buffers: Map.merge(state.whois_buffers[nickname], %{channels: channels})}}
+ end
+
+ def handle_data(%IrcMessage{cmd: @rpl_whoisserver, args: [_sender, nickname, server_addr, server_name]}, state) do
+ {:noreply, %ClientState{state|whois_buffers: Map.merge(state.whois_buffers[nickname], %{server: %{name: server_name, address: server_addr}})}}
+ end
+
+ def handle_data(%IrcMessage{cmd: @rpl_whoisoperator, args: [_sender, nickname, _msg]}, state) do
+ {:noreply, %ClientState{state|whois_buffers: Map.merge(state.whois_buffers[nickname], %{is_ircop?: true})}}
+ end
+
+ def handle_data(%IrcMessage{cmd: @rpl_whoisaccount, args: [_sender, nickname, account_name]}, state) do
+ {:noreply, %ClientState{state|whois_buffers: Map.merge(state.whois_buffers[nickname], %{account_name: account_name})}}
+ end
+
+ def handle_data(%IrcMessage{cmd: @rpl_whoissecure, args: [_sender, nickname, "is using a secure connection"]}, state) do
+ {:noreply, %ClientState{state|whois_buffers: Map.merge(state.whois_buffers[nickname], %{use_tls?: true})}}
+ end
+
+ def handle_data(%IrcMessage{cmd: @rpl_whoisidle, args: [_sender, nickname, idling_time, signon_time, "seconds idle, signon time"]}, state) do
+ {:noreply, %ClientState{state|whois_buffers: Map.merge(state.whois_buffers[nickname], %{idling_time: idling_time, signon_time: signon_time})}}
+ end
+
+ def handle_data(%IrcMessage{cmd: @rpl_endofwhois, args: [_sender, nickname, "End of /WHOIS list."]}, state) do
+ buffer = state.whois_buffers[nickname]
+ send_event {:whois, buffer}, state
+ {:noreply, %ClientState{state|whois_buffers: Map.delete(state.whois_buffers, nickname)}}
+ end
+
+
+
def handle_data(%IrcMessage{cmd: @rpl_notopic, args: [channel]}, state) do
if state.debug? do
debug "INITIAL TOPIC MSG"
@@ -645,7 +700,7 @@ defmodule ExIrc.Client do
end
# Called when we leave a channel
def handle_data(%IrcMessage{cmd: "PART", nick: nick} = msg, %ClientState{nick: nick} = state) do
- channel = msg.args |> List.first |> String.strip
+ channel = msg.args |> List.first |> String.trim
if state.debug?, do: debug "WE LEFT A CHANNEL: #{channel}"
channels = Channels.part(state.channels, channel)
new_state = %{state | channels: channels}
@@ -655,7 +710,7 @@ defmodule ExIrc.Client do
# Called when someone else in our channel leaves
def handle_data(%IrcMessage{cmd: "PART", nick: from, host: host, user: user} = msg, state) do
sender = %SenderInfo{nick: from, host: host, user: user}
- channel = msg.args |> List.first |> String.strip
+ channel = msg.args |> List.first |> String.trim
if state.debug?, do: debug "#{from} LEFT A CHANNEL: #{channel}"
channels = Channels.user_part(state.channels, channel, from)
new_state = %{state | channels: channels}
@@ -729,7 +784,7 @@ defmodule ExIrc.Client do
{:noreply, state}
end
# Called when a NOTICE is received by the client.
- def handle_data(%IrcMessage{nick: from, cmd: "NOTICE", args: [target, message], host: host, user: user} = _msg, state) do
+ def handle_data(%IrcMessage{nick: from, cmd: "NOTICE", args: [_target, message], host: host, user: user} = _msg, state) do
sender = %SenderInfo{nick: from,
host: host,
user: user}
diff --git a/lib/exirc/commands.ex b/lib/exirc/commands.ex
index 9f52b75..60cd779 100644
--- a/lib/exirc/commands.ex
+++ b/lib/exirc/commands.ex
@@ -49,6 +49,14 @@ defmodule Irc.Commands do
#one of two replies is sent. If the topic is set, RPL_TOPIC is sent back else
#RPL_NOTOPIC.
#"""
+ @rpl_whoiregnick "307"
+ @rpl_whoisuser "311"
+ @rpl_whoisserver "312"
+ @rpl_whoisoperator "313"
+ @rpl_whoisidle "317"
+ @rpl_endofwhois "318"
+ @rpl_whoischannels "319"
+ @rpl_whoisaccount "330"
@rpl_notopic "331"
@rpl_topic "332"
#@doc """
@@ -77,6 +85,8 @@ defmodule Irc.Commands do
@rpl_motd "372"
@rpl_motdstart "375"
@rpl_endofmotd "376"
+ @rpl_whoishost "378"
+ @rpl_whoismodes "379"
################
# Error Codes
@@ -150,6 +160,8 @@ defmodule Irc.Commands do
#"""
@err_restricted "484"
+ @rpl_whoissecure "671"
+
###############
# Code groups
###############
@@ -158,6 +170,12 @@ defmodule Irc.Commands do
@err_nickname_in_use, @err_nick_collision,
@err_unavail_resource, @err_need_more_params,
@err_already_registered, @err_restricted ]
+
+ @whois_rpls [ @rpl_whoisuser, @rpl_whoishost,
+ @rpl_whoishost, @rpl_whoisserver,
+ @rpl_whoismodes, @rpl_whoisidle,
+ @rpl_endofwhois
+ ]
end
end
@@ -183,6 +201,11 @@ defmodule Irc.Commands do
# IRC Commands
@doc """
+ Send a WHOIS request about a user
+ """
+ def whois!(user), do: command! ['WHOIS', user]
+
+ @doc """
Send password to server
"""
def pass!(pwd), do: command! ['PASS ', pwd]
diff --git a/lib/exirc/logger.ex b/lib/exirc/logger.ex
index 6055221..65ae980 100644
--- a/lib/exirc/logger.ex
+++ b/lib/exirc/logger.ex
@@ -8,7 +8,7 @@ defmodule ExIrc.Logger do
"""
@spec info(binary) :: :ok
def info(msg) do
- :error_logger.info_report String.to_char_list(msg)
+ :error_logger.info_report String.to_charlist(msg)
end
@doc """
@@ -16,7 +16,7 @@ defmodule ExIrc.Logger do
"""
@spec warning(binary) :: :ok
def warning(msg) do
- :error_logger.warning_report String.to_char_list("#{IO.ANSI.yellow()}#{msg}#{IO.ANSI.reset()}")
+ :error_logger.warning_report String.to_charlist("#{IO.ANSI.yellow()}#{msg}#{IO.ANSI.reset()}")
end
@doc """
@@ -24,6 +24,6 @@ defmodule ExIrc.Logger do
"""
@spec error(binary) :: :ok
def error(msg) do
- :error_logger.error_report String.to_char_list("#{IO.ANSI.red()}#{msg}#{IO.ANSI.reset()}")
+ :error_logger.error_report String.to_charlist("#{IO.ANSI.red()}#{msg}#{IO.ANSI.reset()}")
end
end \ No newline at end of file
diff --git a/lib/exirc/utils.ex b/lib/exirc/utils.ex
index 46cba11..d79b326 100644
--- a/lib/exirc/utils.ex
+++ b/lib/exirc/utils.ex
@@ -13,7 +13,7 @@ defmodule ExIrc.Utils do
message = ExIrc.Utils.parse data
assert "irc.example.org" = message.server
"""
- @spec parse(raw_data :: char_list) :: IrcMessage.t
+ @spec parse(raw_data :: charlist) :: IrcMessage.t
def parse(raw_data) do
data = :string.substr(raw_data, 1, length(raw_data))
case data do
@@ -137,7 +137,7 @@ defmodule ExIrc.Utils do
end
defp isup_param("PREFIX=" <> user_prefixes, state) do
prefixes = Regex.run(~r/\((.*)\)(.*)/, user_prefixes, capture: :all_but_first)
- |> Enum.map(&String.to_char_list/1)
+ |> Enum.map(&String.to_charlist/1)
|> List.zip
%{state | user_prefixes: prefixes}
end
@@ -167,15 +167,15 @@ defmodule ExIrc.Utils do
' ',
:lists.nth(m, @months_of_year),
' ',
- :io_lib.format("~2..0s", [Integer.to_char_list(d)]),
+ :io_lib.format("~2..0s", [Integer.to_charlist(d)]),
' ',
- :io_lib.format("~2..0s", [Integer.to_char_list(h)]),
+ :io_lib.format("~2..0s", [Integer.to_charlist(h)]),
':',
- :io_lib.format("~2..0s", [Integer.to_char_list(n)]),
+ :io_lib.format("~2..0s", [Integer.to_charlist(n)]),
':',
- :io_lib.format("~2..0s", [Integer.to_char_list(s)]),
+ :io_lib.format("~2..0s", [Integer.to_charlist(s)]),
' ',
- Integer.to_char_list(y)] |> List.flatten |> List.to_string
+ Integer.to_charlist(y)] |> List.flatten |> List.to_string
end
defp trim_crlf(charlist) do