diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/exirc/channels.ex | 10 | ||||
| -rw-r--r-- | lib/exirc/client.ex | 90 | ||||
| -rw-r--r-- | lib/exirc/commands.ex | 25 | ||||
| -rw-r--r-- | lib/exirc/logger.ex | 6 | ||||
| -rw-r--r-- | lib/exirc/utils.ex | 14 | ||||
| -rw-r--r-- | lib/exirc/whois.ex | 18 | 
6 files changed, 141 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 c86f58d..4c49106 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,16 @@ defmodule ExIrc.Client do    def names(client, channel) do      GenServer.call(client, {:names, channel}, :infinity)    end + +  @doc """ +  Ask the server for the user's informations. +  """ +  @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 +341,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 +408,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 +568,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 +578,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 +606,65 @@ 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_whoiscertfp, args: [_sender, nickname, "has client certificate fingerprint "<> fingerprint]}, state) do +    {:noreply, %ClientState{state|whois_buffers: put_in(state.whois_buffers, [nickname, :certfp], fingerprint)}} +  end + +  def handle_data(%IrcMessage{cmd: @rpl_whoisregnick, args: [_sender, nickname, _message]}, state) do +    {:noreply, %ClientState{state|whois_buffers: put_in(state.whois_buffers, [nickname, :registered_nick?], true)}} +  end + +  def handle_data(%IrcMessage{cmd: @rpl_whoishelpop, args: [_sender, nickname, _message]}, state) do +    {:noreply, %ClientState{state|whois_buffers: put_in(state.whois_buffers, [nickname, :helpop?], true)}} +  end + +  def handle_data(%IrcMessage{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(%IrcMessage{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) +    {:noreply, %ClientState{state|whois_buffers: new_buffer}} +  end + +  def handle_data(%IrcMessage{cmd: @rpl_whoisoperator, args: [_sender, nickname, _message]}, state) do +    {:noreply, %ClientState{state|whois_buffers: put_in(state.whois_buffers, [nickname, :ircop?], true)}} +  end + +  def handle_data(%IrcMessage{cmd: @rpl_whoisaccount, args: [_sender, nickname, account_name, _message]}, state) do +    {:noreply, %ClientState{state|whois_buffers: put_in(state.whois_buffers, [nickname, :account_name], account_name)}} +  end + +  def handle_data(%IrcMessage{cmd: @rpl_whoissecure, args: [_sender, nickname, _message]}, state) do +    {:noreply, %ClientState{state|whois_buffers: put_in(state.whois_buffers, [nickname, :tls?], true)}} +  end + +  def handle_data(%IrcMessage{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) +    {:noreply, %ClientState{state|whois_buffers: new_buffer}} +  end + +  def handle_data(%IrcMessage{cmd: @rpl_endofwhois, args: [_sender, nickname, _message]}, state) do +    buffer = struct(Irc.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(%IrcMessage{cmd: @rpl_notopic, args: [channel]}, state) do      if state.debug? do        debug "INITIAL TOPIC MSG" @@ -645,7 +721,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 +731,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 +805,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..0d959c0 100644 --- a/lib/exirc/commands.ex +++ b/lib/exirc/commands.ex @@ -49,6 +49,16 @@ defmodule Irc.Commands do        #one of two replies is sent. If the topic is set, RPL_TOPIC is sent back else        #RPL_NOTOPIC.        #""" +      @rpl_whoiscertfp "276" +      @rpl_whoisregnick "307" +      @rpl_whoishelpop "310" +      @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 +87,8 @@ defmodule Irc.Commands do        @rpl_motd "372"        @rpl_motdstart "375"        @rpl_endofmotd "376" +      @rpl_whoishost "378" +      @rpl_whoismodes "379"        ################        # Error Codes @@ -150,6 +162,8 @@ defmodule Irc.Commands do        #"""        @err_restricted "484" +      @rpl_whoissecure "671" +        ###############        # Code groups        ############### @@ -158,6 +172,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 +203,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 diff --git a/lib/exirc/whois.ex b/lib/exirc/whois.ex new file mode 100644 index 0000000..fb14e63 --- /dev/null +++ b/lib/exirc/whois.ex @@ -0,0 +1,18 @@ +defmodule Irc.Whois do +  defstruct [account_name: nil, +             channels: [], +             helpop?: false, +             hostname: nil, +             idling_time: 0, +             ircop?: false, +             nickname: nil, +             realname: nil, +             registered_nick?: false, +             server_address: nil, +             server_name: nil, +             signon_time: 0, +             tls?: false, +             username: nil, +            ] +end +  | 
