irc_parser 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +21 -0
- data/README.md +105 -0
- data/Rakefile +155 -0
- data/extra/benchmark.rb +41 -0
- data/irc_parser.gemspec +98 -0
- data/lib/irc_parser.rb +25 -0
- data/lib/irc_parser/factory.erb +53 -0
- data/lib/irc_parser/helper.rb +71 -0
- data/lib/irc_parser/messages.rb +96 -0
- data/lib/irc_parser/messages/commands.rb +274 -0
- data/lib/irc_parser/messages/errors.rb +51 -0
- data/lib/irc_parser/messages/replies.rb +212 -0
- data/lib/irc_parser/parser.rb +557 -0
- data/lib/irc_parser/parser.rl +89 -0
- data/spec/fixtures/from_weechat.rb +24 -0
- data/spec/fixtures/inbound.log +3959 -0
- data/spec/irc_parser/helper_spec.rb +32 -0
- data/spec/irc_parser/irc_parser_spec.rb +12 -0
- data/spec/irc_parser/messages_spec.rb +195 -0
- data/spec/irc_parser/parser_spec.rb +9 -0
- data/spec/irc_parser/rfc1459/4_1_connection_registration/4_1_1_password_message_spec.rb +28 -0
- data/spec/irc_parser/rfc1459/4_1_connection_registration/4_1_2_nick_message_spec.rb +35 -0
- data/spec/irc_parser/rfc1459/4_1_connection_registration/4_1_3_user_message_spec.rb +47 -0
- data/spec/irc_parser/rfc1459/4_1_connection_registration/4_1_4_server_message_spec.rb +33 -0
- data/spec/irc_parser/rfc1459/4_1_connection_registration/4_1_5_oper_spec.rb +17 -0
- data/spec/irc_parser/rfc1459/4_1_connection_registration/4_1_6_quit_spec.rb +17 -0
- data/spec/irc_parser/rfc1459/4_1_connection_registration/4_1_7_server_quit_message_spec.rb +32 -0
- data/spec/irc_parser/rfc1459/4_2_channel_operations/4_2_1_join_message_spec.rb +65 -0
- data/spec/irc_parser/rfc1459/4_2_channel_operations/4_2_2_part_message_spec.rb +23 -0
- data/spec/irc_parser/rfc1459/4_2_channel_operations/4_2_3_1_channel_modes_spec.rb +159 -0
- data/spec/irc_parser/rfc1459/4_2_channel_operations/4_2_3_2_user_modes_spec.rb +55 -0
- data/spec/irc_parser/rfc1459/4_2_channel_operations/4_2_4_topic_message_spec.rb +36 -0
- data/spec/irc_parser/rfc1459/4_2_channel_operations/4_2_5_names_message_spec.rb +25 -0
- data/spec/irc_parser/rfc1459/4_2_channel_operations/4_2_6_list_message_spec.rb +23 -0
- data/spec/irc_parser/rfc1459/4_2_channel_operations/4_2_7_invite_message_spec.rb +31 -0
- data/spec/irc_parser/rfc1459/4_2_channel_operations/4_2_8_kick_command_spec.rb +56 -0
- data/spec/irc_parser/rfc1459/4_3_server_queries_and_commands/4_3_1_version_message_spec.rb +30 -0
- data/spec/irc_parser/rfc1459/4_3_server_queries_and_commands/4_3_2_stats_message_spec.rb +32 -0
- data/spec/irc_parser/rfc1459/4_3_server_queries_and_commands/4_3_3_links_message_spec.rb +31 -0
- data/spec/irc_parser/rfc1459/4_3_server_queries_and_commands/4_3_4_time_message_spec.rb +34 -0
- data/spec/irc_parser/rfc1459/4_3_server_queries_and_commands/4_3_5_connect_message_spec.rb +32 -0
- data/spec/irc_parser/rfc1459/4_3_server_queries_and_commands/4_3_6_trace_message_spec.rb +28 -0
- data/spec/irc_parser/rfc1459/4_3_server_queries_and_commands/4_3_7_admin_command_spec.rb +28 -0
- data/spec/irc_parser/rfc1459/4_3_server_queries_and_commands/4_3_8_info_command_spec.rb +38 -0
- data/spec/irc_parser/rfc1459/4_4_sending_messages/4_4_1_private_messages_spec.rb +63 -0
- data/spec/irc_parser/rfc1459/4_4_sending_messages/4_4_2_notice_spec.rb +63 -0
- data/spec/irc_parser/rfc1459/4_5_user_based_queries/4_5_1_who_query_spec.rb +27 -0
- data/spec/irc_parser/rfc1459/4_5_user_based_queries/4_5_2_whois_query_spec.rb +27 -0
- data/spec/irc_parser/rfc1459/4_5_user_based_queries/4_5_3_whowas_spec.rb +40 -0
- data/spec/irc_parser/rfc1459/4_6_miscellaneous_messages/4_6_1_kill_message_spec.rb +20 -0
- data/spec/irc_parser/rfc1459/4_6_miscellaneous_messages/4_6_2_ping_message_spec.rb +35 -0
- data/spec/irc_parser/rfc1459/4_6_miscellaneous_messages/4_6_3_pong_message_spec.rb +26 -0
- data/spec/irc_parser/rfc1459/4_6_miscellaneous_messages/4_6_4_error_spec.rb +26 -0
- data/spec/irc_parser/rfc1459/5_0_optionals/5_1_0_away_spec.rb +25 -0
- data/spec/irc_parser/rfc1459/5_0_optionals/5_2_0_rehash_message_spec.rb +14 -0
- data/spec/irc_parser/rfc1459/5_0_optionals/5_3_0_restart_message_spec.rb +14 -0
- data/spec/irc_parser/rfc1459/5_0_optionals/5_4_0_summon_message_spec.rb +28 -0
- data/spec/irc_parser/rfc1459/5_0_optionals/5_5_0_users_spec.rb +27 -0
- data/spec/irc_parser/rfc1459/5_0_optionals/5_6_0_operwall_message_spec.rb +17 -0
- data/spec/irc_parser/rfc1459/5_0_optionals/5_7_0_userhost_message_spec.rb +16 -0
- data/spec/irc_parser/rfc1459/5_0_optionals/5_8_0_ison_message_spec.rb +16 -0
- data/spec/irc_parser/rfc1459/6_0_replies/6_1_error_parsing_spec.rb +488 -0
- data/spec/irc_parser/rfc1459/6_0_replies/6_2_command_responses_generation_spec.rb +934 -0
- data/spec/irc_parser/rfc2812/5_1_command_responses/5_1_command_responses_spec.rb +63 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/messages_helper.rb +24 -0
- data/spec/support/simplecov.rb +12 -0
- metadata +185 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
#class Struct::<%= name %>
|
2
|
+
|
3
|
+
def initialize(prefix = nil, arguments = nil)
|
4
|
+
arguments ? super(prefix, *arguments) : super(prefix)
|
5
|
+
|
6
|
+
<% if @postfix_format %>
|
7
|
+
self.postfix ||= <%= @postfix_format.inspect %>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<% csv_arguments.each do |argument| %>
|
11
|
+
self[<%=argument[:name].inspect%>] = Array(self[<%=argument[:name].inspect%>]).join(<%=argument[:csv].inspect%>)
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
yield self if block_given?
|
15
|
+
end
|
16
|
+
|
17
|
+
def format_postfix(hash)
|
18
|
+
self.postfix = <%= @postfix_format.inspect %> % hash
|
19
|
+
end
|
20
|
+
|
21
|
+
EMPTY_STRING = "".freeze
|
22
|
+
|
23
|
+
# Generates the IRC message. It will have the form:
|
24
|
+
# ':prefix IDENTIFIER param1 param2 :postfix thay may have spaces\r\n'
|
25
|
+
def to_s
|
26
|
+
result = "#{prefix && prefix != EMPTY_STRING ? ":#{prefix} " : nil}<%= @identifier %>"
|
27
|
+
|
28
|
+
<% arguments.each_with_index do |argument, index| %>
|
29
|
+
part = self[<%= argument[:name].inspect %>]
|
30
|
+
<% if argument.member?(:default) %>
|
31
|
+
result << " " << ((part && part != EMPTY_STRING) ? part.to_s : <%= argument[:default].inspect %>)
|
32
|
+
<% else %>
|
33
|
+
result << " " << part.to_s if (part && part != EMPTY_STRING)
|
34
|
+
<% end %>
|
35
|
+
<% end %>
|
36
|
+
|
37
|
+
result << " :#{postfix}" if postfix && postfix != EMPTY_STRING
|
38
|
+
result << "\r\n"
|
39
|
+
end
|
40
|
+
alias_method :to_str, :to_s
|
41
|
+
|
42
|
+
<% csv_arguments.each do |argument| %>
|
43
|
+
def <%=argument[:name]%>
|
44
|
+
self[<%=argument[:name].inspect%>].split(<%=argument[:csv].inspect%>)
|
45
|
+
end
|
46
|
+
|
47
|
+
def <%=argument[:name]%>=(val)
|
48
|
+
self[<%=argument[:name].inspect%>] = Array(val).join(<%=argument[:csv].inspect%>)
|
49
|
+
end
|
50
|
+
<% end %>
|
51
|
+
|
52
|
+
#end
|
53
|
+
# vim: set ft=ruby ts=8 sw=2 tw=0 :
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module IRCParser
|
2
|
+
module Helper
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def underscore(string)
|
6
|
+
string.to_s.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').gsub(/([a-z\d])([A-Z])/,'\1_\2').downcase
|
7
|
+
end
|
8
|
+
|
9
|
+
def parse_regexp(text)
|
10
|
+
/#{ text.to_s.split(".").join("\\.").gsub(/\*|\?/, ".*") }/
|
11
|
+
end
|
12
|
+
|
13
|
+
# http://tools.ietf.org/html/rfc1459#section-4.3.2
|
14
|
+
# c - returns a list of servers which the server may connect to or allow connections from;
|
15
|
+
# h - returns a list of servers which are either forced to be treated as leaves or allowed to act as hubs;
|
16
|
+
# i - returns a list of hosts which the server allows a client to connect from;
|
17
|
+
# k - returns a list of banned username/hostname combinations for that server;
|
18
|
+
# l - returns a list of the server's connections, showing how long each connection has been established and the traffic
|
19
|
+
# over that connection in bytes and messages for each direction;
|
20
|
+
# m - returns a list of commands supported by the server and the usage count for each if the usage count is non zero;
|
21
|
+
# o - returns a list of hosts from which normal clients may become operators;
|
22
|
+
# y - show Y (Class) lines from server's configuration file;
|
23
|
+
# u - returns a string showing how long the server has been up.
|
24
|
+
STATS_MODES = %w|c h i k l m o y u|
|
25
|
+
|
26
|
+
NICK_REGEXP = /^[a-zA-Z]+[a-zA-Z0-9]*/
|
27
|
+
|
28
|
+
def valid_nick?(nick)
|
29
|
+
nick =~ NICK_REGEXP
|
30
|
+
end
|
31
|
+
|
32
|
+
def invalid_nick?(nick)
|
33
|
+
not valid_nick?(nick)
|
34
|
+
end
|
35
|
+
|
36
|
+
module NicknameHelpers
|
37
|
+
%w|valid_nick? invalid_nick?|.each do |meth|
|
38
|
+
define_method(meth) { IRCParser::Helper.send(meth, self) }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
CHANNEL_PREFIXES = {
|
43
|
+
:normal => "#",
|
44
|
+
:local => "&",
|
45
|
+
:modeless => "+",
|
46
|
+
:safe => "!"
|
47
|
+
}
|
48
|
+
|
49
|
+
CHANNEL_REGEXP = /^[#{CHANNEL_PREFIXES.values.join("|")}][a-zA-Z0-9]+/
|
50
|
+
|
51
|
+
def valid_channel_name?(name)
|
52
|
+
name.to_s =~ CHANNEL_REGEXP
|
53
|
+
end
|
54
|
+
|
55
|
+
def invalid_channel_name?(name)
|
56
|
+
not valid_channel_name?(name)
|
57
|
+
end
|
58
|
+
|
59
|
+
CHANNEL_PREFIXES.each do |channel_mode, prefix|
|
60
|
+
define_method("#{channel_mode}_channel?") do |name|
|
61
|
+
name.to_s[0, 1] == prefix
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
module Channel
|
66
|
+
(CHANNEL_PREFIXES.keys.map {|mode| "#{mode}_channel?" } + %w|valid_channel_name? invalid_channel_name?|).each do |meth|
|
67
|
+
define_method(meth) { IRCParser::Helper.send(meth, self) }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module IRCParser
|
4
|
+
module Messages
|
5
|
+
# Store all known message classes under convenient keys so they are easy to find.
|
6
|
+
ALL = Hash.new
|
7
|
+
|
8
|
+
# Create a Message class and save it on the IRCParser::Messages::ALL hash
|
9
|
+
# for easy retrieval with different names.
|
10
|
+
def self.define_message(name, *arguments, &block)
|
11
|
+
klass = message_class(name, *arguments, &block)
|
12
|
+
[klass.name.to_s, klass.name.to_s.upcase, klass.to_sym.to_s, klass.to_sym.to_s.upcase, klass.identifier.to_s].uniq.each do |key|
|
13
|
+
IRCParser::Messages::ALL[key] = klass
|
14
|
+
IRCParser::Messages::ALL[key.to_sym] = klass
|
15
|
+
end
|
16
|
+
IRCParser::Messages::ALL[klass.identifier.to_s.to_i] = klass if klass.identifier.to_s =~ /^\d+$/
|
17
|
+
const_set(name, klass)
|
18
|
+
end
|
19
|
+
|
20
|
+
IMPLEMENTATION_PATH = File.expand_path(File.join(File.dirname(__FILE__), "factory.erb"))
|
21
|
+
IMPLEMENTATION = File.read(IMPLEMENTATION_PATH)
|
22
|
+
|
23
|
+
# Creates a message class, which inherits from a ruby Struct to save the different message params.
|
24
|
+
def self.message_class(name, *arguments, &block)
|
25
|
+
# # #
|
26
|
+
# Prepare information needed to generate the classes
|
27
|
+
# # #
|
28
|
+
|
29
|
+
# klass.to_sym is convenient name for storing the class in the ALL hash. E.g.: AWAY -> :away
|
30
|
+
to_sym = IRCParser::Helper.underscore(name).to_sym
|
31
|
+
identifier = (arguments.first.is_a?(String) ? arguments.shift : name).to_s.upcase.to_sym
|
32
|
+
postfix_format = arguments.pop if arguments.last.is_a?(String)
|
33
|
+
postfix_alias = arguments.pop.keys.first if arguments.last.is_a?(Hash) && arguments.last.values.first == :postfix
|
34
|
+
|
35
|
+
placeholders = 0 # used to give name to placeholder arguments.
|
36
|
+
|
37
|
+
# normalize the parameter information so it is easy to work with.
|
38
|
+
arguments.map! do |arg|
|
39
|
+
if arg.is_a?(Hash) then {:name => arg.keys.first}.merge(arg.values.first)
|
40
|
+
elsif arg.is_a?(String) then {:name => "placeholder_#{placeholders += 1}", :default => arg}
|
41
|
+
else {:name => arg}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# we will generate accessors to move from and to char separated values (char can be a comma, a space, etc..)
|
46
|
+
csv_arguments = arguments.select { |arg| arg.has_key?(:csv) }
|
47
|
+
|
48
|
+
# # #
|
49
|
+
# Generate the class, inhereting from Struct, and generate its methods.
|
50
|
+
# # #
|
51
|
+
|
52
|
+
klass = Struct.new("IRC#{name}", *([:prefix] + (arguments.map { |arg| arg[:name] } + [:postfix]))) do
|
53
|
+
@name, @to_sym, @identifier, @postfix_format = name, to_sym, identifier, postfix_format
|
54
|
+
|
55
|
+
extend ClassMethods
|
56
|
+
|
57
|
+
# It would be trivial to rewrite the code on factory.erb using define_methods,
|
58
|
+
# but the code generated using eval runs about 10% faster, with the only caveat
|
59
|
+
# *sometimes* is a little harder to follow backtraces when errors occur.
|
60
|
+
class_eval(ERB.new(IMPLEMENTATION).result(binding), IMPLEMENTATION_PATH)
|
61
|
+
|
62
|
+
[postfix_alias, :body, :message].compact.uniq.each do |attr|
|
63
|
+
alias_method attr, :postfix
|
64
|
+
alias_method "#{attr}=", :postfix=
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# # #
|
69
|
+
# Evaluate any additional configuration block passed to this method, and return the resulting class.
|
70
|
+
# # #
|
71
|
+
|
72
|
+
klass.class_eval(&block) if block
|
73
|
+
klass
|
74
|
+
end
|
75
|
+
|
76
|
+
module ClassMethods
|
77
|
+
attr_reader :name, :to_sym, :identifier, :postfix_format
|
78
|
+
|
79
|
+
def is_error?
|
80
|
+
!(@name !~ /^Err[A-Z]/)
|
81
|
+
end
|
82
|
+
|
83
|
+
def is_reply?
|
84
|
+
!(@name !~ /^Rpl[A-Z]/)
|
85
|
+
end
|
86
|
+
|
87
|
+
def is_command?
|
88
|
+
!(@name =~ /^(Rpl|Err)[A-Z]/)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
require 'irc_parser/messages/commands'
|
93
|
+
require 'irc_parser/messages/errors'
|
94
|
+
require 'irc_parser/messages/replies'
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,274 @@
|
|
1
|
+
module IRCParser::Messages
|
2
|
+
define_message :Admin , :target
|
3
|
+
define_message :Away , :away_message => :postfix
|
4
|
+
define_message :Connect , :target_server, :port, :remote_server
|
5
|
+
define_message :Info , :target
|
6
|
+
define_message :Invite , :to_nick, :channel
|
7
|
+
define_message :Join , {:channels => {:csv => ","}}, {:keys => {:csv => ","}}
|
8
|
+
define_message :Kick , {:channels => {:csv => ","}}, {:users => {:csv => ","}}, :kick_message => :postfix
|
9
|
+
define_message :Kill , :nick, :kill_message => :postfix
|
10
|
+
define_message :Links , :remote_server, :server_mask
|
11
|
+
define_message :List , :channels => {:csv => ","}
|
12
|
+
define_message :Names , :channels => {:csv => ","}
|
13
|
+
define_message :Oper , :user, :password
|
14
|
+
define_message :Part , {:channels => {:csv => ","}}, :part_message
|
15
|
+
define_message :Pass , :password
|
16
|
+
define_message :Ping , :target, :final_target
|
17
|
+
define_message :Pong , :server, :target
|
18
|
+
define_message :Quit , :quit_message => :postfix
|
19
|
+
define_message :Rehash
|
20
|
+
define_message :Restart
|
21
|
+
define_message :SQuit , :server, :reason => :postfix
|
22
|
+
define_message :Stats , :mode, :server
|
23
|
+
define_message :Time , :for_server
|
24
|
+
define_message :Topic , :channel, :topic => :postfix
|
25
|
+
define_message :Trace , :target
|
26
|
+
define_message :User , :user, {:mode => { :default => "*" }}, {:servername => { :default => "*" }}, :realname => :postfix
|
27
|
+
define_message :Users , :target
|
28
|
+
define_message :Version , :server
|
29
|
+
define_message :WallOps , :wall_message => :postfix
|
30
|
+
|
31
|
+
define_message :Mode, :target, :flags, :limit, :user, :ban_mask do
|
32
|
+
|
33
|
+
# Channel Parameters: <channel> {[+|-]|o|p|s|i|t|n|b|v} [<limit>] [<user>] [<ban mask>]
|
34
|
+
# User Parameters: <nickname> {[+|-]|i|w|s|o}
|
35
|
+
def initialize(prefix, params = [], &block)
|
36
|
+
super(prefix, *params)
|
37
|
+
|
38
|
+
return if params == nil || params.length <= 1
|
39
|
+
|
40
|
+
if params.length != 5 && params.length != 2
|
41
|
+
self.target = params[0]
|
42
|
+
self.flags = params[1]
|
43
|
+
|
44
|
+
if remaining = params[2..-1]
|
45
|
+
if remaining.first =~ /\d+/ || self.flags =~ /\+k/
|
46
|
+
self.limit = remaining.shift
|
47
|
+
elsif self.flags =~ /\+b/
|
48
|
+
self.ban_mask = remaining.first
|
49
|
+
else
|
50
|
+
self.user, self.ban_mask = *remaining
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
self.flags = self.flags.downcase if self.flags
|
56
|
+
end
|
57
|
+
|
58
|
+
def for_channel?
|
59
|
+
IRCParser::Helper.valid_channel_name?(target)
|
60
|
+
end
|
61
|
+
|
62
|
+
def for_user?
|
63
|
+
IRCParser::Helper.valid_nick?(target)
|
64
|
+
end
|
65
|
+
|
66
|
+
CHANNEL_MODES = {
|
67
|
+
:invitation => "I", # set/remove an invitation mask to automatically override the invite-only flag;
|
68
|
+
:exception => "e", # set/remove an exception mask to override a ban mask;
|
69
|
+
:quiet => "q", # toggle the quiet channel flag;
|
70
|
+
:reop => "r", # toggle the server reop channel flag;
|
71
|
+
:anonymous => "a", # toggle the anonymous channel flag;
|
72
|
+
:ban_mask => "b", # set a ban mask to keep users out;
|
73
|
+
:creator => "O", # give "channel creator" status;
|
74
|
+
:invite_only => "i", # invite-only channel flag;
|
75
|
+
:moderated => "m", # moderated channel;
|
76
|
+
:no_foreign_messages => "n", # no messages to channel from clients on the outside;
|
77
|
+
:operator => "o", # give/take channel operator privileges;
|
78
|
+
:password => "k", # set a channel key (password).
|
79
|
+
:private => "p", # private channel flag;
|
80
|
+
:secret => "s", # secret channel flag;
|
81
|
+
:speaker => "v", # give/take the ability to speak on a moderated channel;
|
82
|
+
:topic_by_op_only => "t", # topic settable by channel operator only flag;
|
83
|
+
:users_limit => "l" # set the user limit to channel;
|
84
|
+
}
|
85
|
+
|
86
|
+
def negative_flags?
|
87
|
+
flags && ( flags[0,1] == "-" )
|
88
|
+
end
|
89
|
+
|
90
|
+
def positive_flags?
|
91
|
+
not negative_flags?
|
92
|
+
end
|
93
|
+
|
94
|
+
def negative_flags!
|
95
|
+
self.flags ||= ""
|
96
|
+
|
97
|
+
case flags[0,1]
|
98
|
+
when "-" then # Do nothing
|
99
|
+
when "+" then self.flags[0] = "-"
|
100
|
+
else
|
101
|
+
self.flags.insert(0, "-") # Should not happen. Anyway.
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def positive_flags!
|
106
|
+
self.flags ||= ""
|
107
|
+
|
108
|
+
case flags[0,1]
|
109
|
+
when "+" then # Do nothing
|
110
|
+
when "-" then self.flags[0] = "+"
|
111
|
+
else
|
112
|
+
self.flags.insert(0, "+") # Should not happen. Anyway.
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
CHANNEL_MODES.each do |name, flag|
|
117
|
+
define_method("chan_flags_include_#{name}?") do
|
118
|
+
flags && for_channel? && flags.include?(flag)
|
119
|
+
end
|
120
|
+
|
121
|
+
define_method("chan_#{name}?") do
|
122
|
+
flags && for_channel? && flags.include?(flag) && positive_flags?
|
123
|
+
end
|
124
|
+
|
125
|
+
define_method("chan_#{name}!") do
|
126
|
+
self.flags ||= ""
|
127
|
+
self.flags = flags + flag unless flags.include?(flag)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
USER_MODES = {
|
132
|
+
:invisible => "i", # marks a users as invisible;
|
133
|
+
:server_receptor => "s", # marks a user for receipt of server notices;
|
134
|
+
:wallops_receptor => "w", # user receives wallops;
|
135
|
+
:operator => "o", # operator flag.
|
136
|
+
:away => "a", # user is flagged as away;
|
137
|
+
:restricted => "r", # restricted user connection;
|
138
|
+
:local_operator => "O" # local operator flag;
|
139
|
+
}
|
140
|
+
|
141
|
+
USER_MODES.each do |name, flag|
|
142
|
+
define_method("user_flags_include_#{name}?") do
|
143
|
+
flags && for_user? && flags.include?(flag)
|
144
|
+
end
|
145
|
+
|
146
|
+
define_method("user_#{name}?") do
|
147
|
+
flags && for_user? && flags.include?(flag) && positive_flags?
|
148
|
+
end
|
149
|
+
|
150
|
+
define_method("user_#{name}!") do
|
151
|
+
self.flags ||= ""
|
152
|
+
self.flags = flags + flag unless self.flags.include?(flag)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# hopcount: removed in RFC 2812
|
158
|
+
define_message :Nick, :nick, :hopcount do
|
159
|
+
def invalid_nick?
|
160
|
+
IRCParser::Helper.invalid_nick?(nick)
|
161
|
+
end
|
162
|
+
|
163
|
+
def changing?
|
164
|
+
prefix.to_s =~ /\S/
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
define_message :Server, :server, :hopcount, :info => :postfix do
|
169
|
+
def hopcount
|
170
|
+
self[:hopcount].to_i
|
171
|
+
end
|
172
|
+
|
173
|
+
# not sure about this one, from RFC 2813
|
174
|
+
# http://tools.ietf.org/html/rfc2813#section-4.1.2
|
175
|
+
def token
|
176
|
+
info
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
module MesageMan
|
181
|
+
def for_channel?
|
182
|
+
IRCParser::Helper.valid_channel_name?(target.to_s)
|
183
|
+
end
|
184
|
+
|
185
|
+
def for_user?
|
186
|
+
IRCParser::Helper.valid_nick?(target.to_s)
|
187
|
+
end
|
188
|
+
|
189
|
+
def for_server_pattern?
|
190
|
+
target.to_s =~ /^\$/
|
191
|
+
end
|
192
|
+
|
193
|
+
def for_host_pattern?
|
194
|
+
target.to_s =~ /^\#/
|
195
|
+
end
|
196
|
+
|
197
|
+
def server_pattern
|
198
|
+
for_server_pattern? && IRCParser::Helper::parse_regexp(target[1..-1])
|
199
|
+
end
|
200
|
+
|
201
|
+
def host_pattern
|
202
|
+
for_host_pattern? && IRCParser::Helper::parse_regexp(target[1..-1])
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
define_message :PrivMsg, :target, :body => :postfix do
|
207
|
+
include MesageMan
|
208
|
+
end
|
209
|
+
|
210
|
+
define_message :Notice, :target, :body => :postfix do
|
211
|
+
include MesageMan
|
212
|
+
end
|
213
|
+
|
214
|
+
define_message :Who, :pattern, :operator do
|
215
|
+
alias_method :operator?, :operator
|
216
|
+
|
217
|
+
def for_channel?
|
218
|
+
IRCParser::Helper.valid_channel_name?(pattern)
|
219
|
+
end
|
220
|
+
|
221
|
+
def operator!(true_or_false = true)
|
222
|
+
self.operator = true_or_false ? "o" : ""
|
223
|
+
end
|
224
|
+
|
225
|
+
def regexp
|
226
|
+
IRCParser::Helper.parse_regexp(pattern)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
define_message :WhoIs, :target, :pattern do
|
231
|
+
def initialize(prefix, params = [], &block)
|
232
|
+
super(prefix, *params)
|
233
|
+
self.target, self.pattern = nil, self.target if params && params.length == 1
|
234
|
+
end
|
235
|
+
|
236
|
+
def regexp
|
237
|
+
IRCParser::Helper.parse_regexp(pattern)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
define_message :WhoWas, :nick, :count, :server do
|
242
|
+
def count
|
243
|
+
self[:count].to_i
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
define_message :Error, :nick, :error_message => :postfix do
|
248
|
+
def initialize(prefix, params = [], &block)
|
249
|
+
super(prefix, *params)
|
250
|
+
|
251
|
+
if params
|
252
|
+
if params.length == 2
|
253
|
+
self.nick, self.error_message = *params
|
254
|
+
else
|
255
|
+
self.error_message = params.first
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
define_message :Summon, :nick, :server
|
262
|
+
|
263
|
+
define_message :UserHost, :nicks => { :csv => " " } do
|
264
|
+
def initialize(prefix = nil, *nicks)
|
265
|
+
super(prefix, nicks.join(" "))
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
define_message :IsOn, :nicks => { :csv => " " } do
|
270
|
+
def initialize(prefix = nil, *nicks)
|
271
|
+
super(prefix, nicks.join(" "))
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|