Sutto-marvin 0.1.20081115 → 0.1.20081120
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +70 -50
- data/VERSION.yml +1 -1
- data/bin/marvin +10 -6
- data/config/connections.yml.sample +5 -0
- data/config/settings.yml.sample +2 -7
- data/config/setup.rb +1 -0
- data/handlers/debug_handler.rb +5 -0
- data/handlers/hello_world.rb +1 -1
- data/lib/marvin.rb +1 -0
- data/lib/marvin/abstract_client.rb +79 -42
- data/lib/marvin/abstract_parser.rb +14 -2
- data/lib/marvin/base.rb +44 -6
- data/lib/marvin/dispatchable.rb +9 -4
- data/lib/marvin/drb_handler.rb +7 -2
- data/lib/marvin/exceptions.rb +3 -0
- data/lib/marvin/irc.rb +1 -1
- data/lib/marvin/irc/client.rb +31 -7
- data/lib/marvin/irc/event.rb +9 -4
- data/lib/marvin/irc/replies.rb +154 -0
- data/lib/marvin/loader.rb +1 -0
- data/lib/marvin/logger.rb +66 -3
- data/lib/marvin/options.rb +33 -0
- data/lib/marvin/parsers.rb +3 -0
- data/lib/marvin/parsers/command.rb +73 -0
- data/lib/marvin/parsers/prefixes.rb +8 -0
- data/lib/marvin/parsers/prefixes/host_mask.rb +30 -0
- data/lib/marvin/parsers/prefixes/server.rb +24 -0
- data/lib/marvin/parsers/ragel_parser.rb +713 -0
- data/lib/marvin/parsers/ragel_parser.rl +144 -0
- data/lib/marvin/parsers/regexp_parser.rb +0 -3
- data/lib/marvin/parsers/simple_parser.rb +20 -81
- data/lib/marvin/settings.rb +8 -8
- data/lib/marvin/util.rb +2 -2
- data/script/{run → client} +0 -0
- data/script/daemon-runner +1 -1
- data/script/install +3 -0
- data/test/parser_comparison.rb +36 -0
- data/test/parser_test.rb +20 -0
- data/test/test_helper.rb +10 -0
- metadata +19 -9
- data/lib/marvin/irc/socket_client.rb +0 -69
- data/lib/marvin/parsers/simple_parser/default_events.rb +0 -37
- data/lib/marvin/parsers/simple_parser/event_extensions.rb +0 -14
- data/lib/marvin/parsers/simple_parser/prefixes.rb +0 -34
@@ -0,0 +1,144 @@
|
|
1
|
+
# Ragel Parser comes from the Arrbot Guys -
|
2
|
+
# Kudos to Halogrium and Epitron.
|
3
|
+
|
4
|
+
%%{
|
5
|
+
machine irc;
|
6
|
+
|
7
|
+
action prefix_servername_start {
|
8
|
+
server = Marvin::Parsers::Prefixes::Server.new
|
9
|
+
}
|
10
|
+
|
11
|
+
action prefix_servername {
|
12
|
+
server.name << fc
|
13
|
+
}
|
14
|
+
|
15
|
+
action prefix_servername_finish {
|
16
|
+
command.prefix = server
|
17
|
+
}
|
18
|
+
|
19
|
+
action prefix_hostmask_start {
|
20
|
+
hostmask = Marvin::Parsers::Prefixes::HostMask.new
|
21
|
+
}
|
22
|
+
|
23
|
+
action hostmask_nickname {
|
24
|
+
hostmask.nickname << fc
|
25
|
+
}
|
26
|
+
|
27
|
+
action hostmask_user {
|
28
|
+
hostmask.user << fc
|
29
|
+
}
|
30
|
+
|
31
|
+
action hostmask_host {
|
32
|
+
hostmask.host << fc
|
33
|
+
}
|
34
|
+
|
35
|
+
action prefix_hostmask_finish {
|
36
|
+
command.prefix = hostmask
|
37
|
+
}
|
38
|
+
|
39
|
+
action message_code_start {
|
40
|
+
code = ""
|
41
|
+
}
|
42
|
+
|
43
|
+
action message_code {
|
44
|
+
code << fc
|
45
|
+
}
|
46
|
+
|
47
|
+
action message_code_finish {
|
48
|
+
command.code = code
|
49
|
+
}
|
50
|
+
|
51
|
+
action params_start {
|
52
|
+
params_1 = []
|
53
|
+
params_2 = []
|
54
|
+
}
|
55
|
+
|
56
|
+
action params {
|
57
|
+
}
|
58
|
+
|
59
|
+
action params_1_start {
|
60
|
+
params_1 << ""
|
61
|
+
}
|
62
|
+
|
63
|
+
action params_2_start {
|
64
|
+
params_2 << ""
|
65
|
+
}
|
66
|
+
|
67
|
+
action params_1 {
|
68
|
+
params_1.last << fc
|
69
|
+
}
|
70
|
+
|
71
|
+
action params_2 {
|
72
|
+
params_2.last << fc
|
73
|
+
}
|
74
|
+
|
75
|
+
action params_1_finish {
|
76
|
+
command.params = params_1
|
77
|
+
}
|
78
|
+
|
79
|
+
action params_2_finish {
|
80
|
+
command.params = params_2
|
81
|
+
}
|
82
|
+
|
83
|
+
SPACE = " ";
|
84
|
+
special = "[" | "\\" | "]" | "^" | "_" | "`" | "{" | "|" | "}" | "+";
|
85
|
+
nospcrlfcl = extend - ( 0 | SPACE | '\r' | '\n' | ':' );
|
86
|
+
crlf = "\r\n";
|
87
|
+
shortname = ( alnum ( alnum | "-" )* alnum* ) | "*";
|
88
|
+
multihostname = shortname ( ( "." | "/" ) shortname )*;
|
89
|
+
singlehostname = shortname ( "." | "/" );
|
90
|
+
hostname = multihostname | singlehostname;
|
91
|
+
servername = hostname;
|
92
|
+
nickname = ( alpha | special ) ( alnum | special | "-" ){,15};
|
93
|
+
user = (extend - ( 0 | "\n" | "\r" | SPACE | "@" ))+;
|
94
|
+
ip4addr = digit{1,3} "." digit{1,3} "." digit{1,3} "." digit{1,3};
|
95
|
+
ip6addr = ( xdigit+ ( ":" xdigit+ ){7} ) | ( "0:0:0:0:0:" ( "0" | "FFFF"i ) ":" ip4addr );
|
96
|
+
hostaddr = ip4addr | ip6addr;
|
97
|
+
host = hostname | hostaddr;
|
98
|
+
hostmask = nickname $ hostmask_nickname ( ( "!" user $ hostmask_user )? "@" host $ hostmask_host )?;
|
99
|
+
prefix = ( servername $ prefix_servername > prefix_servername_start % prefix_servername_finish ) | ( hostmask > prefix_hostmask_start % prefix_hostmask_finish );
|
100
|
+
code = alpha+ | digit{3};
|
101
|
+
middle = nospcrlfcl ( ":" | nospcrlfcl )*;
|
102
|
+
trailing = ( ":" | " " | nospcrlfcl )*;
|
103
|
+
params_1 = ( SPACE middle $ params_1 > params_1_start ){,14} ( SPACE ":" trailing $ params_1 > params_1_start )?;
|
104
|
+
params_2 = ( SPACE middle $ params_2 > params_2_start ){14} ( SPACE ":"? trailing $ params_2 > params_2_start )?;
|
105
|
+
params = ( params_1 % params_1_finish | params_2 % params_2_finish ) $ params > params_start;
|
106
|
+
message = ( ":" prefix SPACE )? ( code $ message_code > message_code_start % message_code_finish ) params? crlf;
|
107
|
+
|
108
|
+
main := message;
|
109
|
+
|
110
|
+
}%%
|
111
|
+
|
112
|
+
module Marvin
|
113
|
+
module Parsers
|
114
|
+
class RagelParser < Marvin::AbstractParser
|
115
|
+
|
116
|
+
%% write data;
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
def self.parse!(line)
|
121
|
+
data = "#{line.strip}\r\n"
|
122
|
+
|
123
|
+
p = 0;
|
124
|
+
pe = data.length
|
125
|
+
cs = 0
|
126
|
+
|
127
|
+
hostmask = nil
|
128
|
+
server = nil
|
129
|
+
code = nil
|
130
|
+
command = Marvin::Parsers::Command.new(data)
|
131
|
+
|
132
|
+
%% write init;
|
133
|
+
%% write exec;
|
134
|
+
|
135
|
+
if cs >= irc_first_final
|
136
|
+
command
|
137
|
+
else
|
138
|
+
raise UnparseableMessage, "Failed to parse the message: #{input.inspect}"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -81,9 +81,6 @@ module Marvin
|
|
81
81
|
register_event :quit, /^\:(.+)\!\~?(.+)\@(.+) QUIT :?(.+?)$/i,
|
82
82
|
:nick, :ident, :host, :message
|
83
83
|
|
84
|
-
register_event :nick_taken, /^\:(\S+) 433 \* (\w+) :(.+)$/,
|
85
|
-
:server, :target, :message
|
86
|
-
|
87
84
|
register_event :ping, /^\:(.+)\!\~?(.+)\@(.+) PING (.*)$/,
|
88
85
|
:nick, :ident, :host, :data
|
89
86
|
|
@@ -1,101 +1,40 @@
|
|
1
|
-
require File.dirname(__FILE__) / "simple_parser/prefixes"
|
2
|
-
require File.dirname(__FILE__) / "simple_parser/event_extensions"
|
3
|
-
require File.dirname(__FILE__) / "simple_parser/default_events"
|
4
|
-
|
5
1
|
module Marvin
|
6
2
|
module Parsers
|
7
3
|
class SimpleParser < Marvin::AbstractParser
|
8
4
|
|
9
|
-
cattr_accessor :events
|
10
|
-
self.events ||= {}
|
11
|
-
|
12
|
-
attr_accessor :arguments, :prefix, :current_line, :parts, :event
|
13
|
-
|
14
|
-
def initialize(line)
|
15
|
-
self.current_line = line
|
16
|
-
parse!
|
17
|
-
end
|
18
|
-
|
19
|
-
def to_event
|
20
|
-
if self.event.blank?
|
21
|
-
parse!
|
22
|
-
return nil
|
23
|
-
else
|
24
|
-
return self.event
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
5
|
private
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
6
|
+
|
7
|
+
# Parses an incoming message by using string
|
8
|
+
# Manipulation.
|
9
|
+
def self.parse!(line)
|
33
10
|
if line[0] == ?:
|
34
11
|
prefix_text, line = line.split(" ", 2)
|
35
12
|
else
|
36
13
|
prefix_text = nil
|
37
14
|
end
|
38
|
-
|
39
|
-
|
15
|
+
command = Marvin::Parsers::Command.new(line + "\r\n")
|
16
|
+
command.prefix = self.extract_prefix(prefix_text)
|
40
17
|
head, tail = line.split(":", 2)
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
self.parts.unshift(command.to_s) # Reappend the command
|
47
|
-
process_event self.events[:numeric]
|
48
|
-
elsif self.events.has_key? command
|
49
|
-
# Registered Command
|
50
|
-
process_event self.events[command]
|
51
|
-
else
|
52
|
-
# Unknown Command
|
53
|
-
self.event = nil
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def process_event(prototype, skip_mutation = false)
|
58
|
-
self.event = prototype.dup
|
59
|
-
self.event.prefix = self.prefix
|
60
|
-
self.event.raw_arguments = self.parts
|
61
|
-
mutate_event! unless skip_mutation
|
18
|
+
parts = head.split(" ")
|
19
|
+
command.code = parts.shift
|
20
|
+
parts << tail unless tail.nil?
|
21
|
+
command.params = parts
|
22
|
+
return command
|
62
23
|
end
|
63
24
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
else
|
73
|
-
message = message[1..-2]
|
74
|
-
new_event = :ctcp
|
75
|
-
end
|
76
|
-
self.parts = [message]
|
77
|
-
process_event self.events[new_event], true
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def extract_prefix!(text)
|
82
|
-
return if text.blank?
|
83
|
-
full_prefix = text[1..-1]
|
84
|
-
prefix = full_prefix
|
85
|
-
# Ugly regexp for nick!ident@host format
|
86
|
-
# Officially this should be less-terse, but hey
|
87
|
-
# it's a simple parser.
|
88
|
-
if full_prefix =~ /^([^@!]+)\!\~?([^@]+)@(.*)$/
|
89
|
-
prefix = UserPrefix.new($1, $2, $3)
|
25
|
+
# From a given string, attempts to get the correct
|
26
|
+
# type of prefix (be it a HostMask or a Server name).
|
27
|
+
def self.extract_prefix(prefix_text)
|
28
|
+
return if prefix_text.blank?
|
29
|
+
prefix_text = prefix_text[1..-1] # Remove the leading :
|
30
|
+
# I think I just vomitted in my mouth a little...
|
31
|
+
if prefix_text =~ /^([A-Za-z0-9\-\[\]\\\`\^\{\}]+)(\!\~?([^@]+))?(@(.*))?$/
|
32
|
+
prefix = Prefixes::HostMask.new($1, $3, $5)
|
90
33
|
else
|
91
|
-
|
92
|
-
prefix = ServerNamePrefix.new(prefix.strip)
|
34
|
+
prefix = Prefixes::Server.new(prefix_text.strip)
|
93
35
|
end
|
94
|
-
self.prefix = prefix
|
95
36
|
return prefix
|
96
37
|
end
|
97
|
-
|
98
|
-
include DefaultEvents
|
99
38
|
end
|
100
39
|
end
|
101
40
|
end
|
data/lib/marvin/settings.rb
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
require 'yaml'
|
2
|
+
require 'eventmachine'
|
2
3
|
|
3
4
|
module Marvin
|
4
5
|
class Settings
|
5
6
|
|
6
|
-
cattr_accessor :environment, :configuration, :is_setup, :default_client,
|
7
|
+
cattr_accessor :environment, :configuration, :is_setup, :default_client,
|
8
|
+
:handler_folder, :default_parser, :log_level, :verbose
|
9
|
+
|
10
|
+
self.verbose = false
|
11
|
+
self.log_level = :info
|
7
12
|
|
8
13
|
class << self
|
9
14
|
|
@@ -23,13 +28,8 @@ module Marvin
|
|
23
28
|
def setup!(options = {})
|
24
29
|
self.environment ||= "development"
|
25
30
|
self.configuration = {}
|
26
|
-
self.default_client ||=
|
27
|
-
|
28
|
-
Marvin::IRC::Client
|
29
|
-
rescue LoadError
|
30
|
-
Marvin::IRC::SocketClient
|
31
|
-
end
|
32
|
-
self.default_parser ||= Marvin::Parsers::RegexpParser
|
31
|
+
self.default_client ||= Marvin::IRC::Client
|
32
|
+
self.default_parser ||= Marvin::Parsers::SimpleParser
|
33
33
|
loaded_yaml = YAML.load_file(root / "config/settings.yml")
|
34
34
|
loaded_options = loaded_yaml["default"].
|
35
35
|
merge(loaded_yaml[self.environment]).
|
data/lib/marvin/util.rb
CHANGED
@@ -10,9 +10,9 @@ module Marvin
|
|
10
10
|
alias chan channel_name
|
11
11
|
|
12
12
|
def arguments(input)
|
13
|
-
prefix,
|
13
|
+
prefix, ending = input.split(":", 2)
|
14
14
|
prefix = prefix.split(" ")
|
15
|
-
prefix << ending.
|
15
|
+
prefix << ending unless ending.blank?
|
16
16
|
return prefix
|
17
17
|
end
|
18
18
|
|
data/script/{run → client}
RENAMED
File without changes
|
data/script/daemon-runner
CHANGED
data/script/install
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require File.join(File.dirname(__FILE__),'../lib/marvin')
|
3
|
+
|
4
|
+
LINES = [
|
5
|
+
":irc.darth.vpn.spork.in 366 testbot #testing :End of NAMES list",
|
6
|
+
":Helsinki.FI.EU.Undernet.org PONG Helsinki.FI.EU.Undernet.org :Helsinki.FI.EU.Undernet.org",
|
7
|
+
":testnick USER guest tolmoon tolsun :Ronnie Reagan",
|
8
|
+
"LIST #twilight_zone,#42",
|
9
|
+
":WiZ LINKS *.bu.edu *.edu",
|
10
|
+
":Angel PRIVMSG Wiz :Hello are you receiving this message ?",
|
11
|
+
":RelayBot!n=MarvinBo@203.161.81.201.static.amnet.net.au JOIN :#relayrelay",
|
12
|
+
":SuttoL!n=SuttoL@li6-47.members.linode.com PRIVMSG #relayrelay :testing...",
|
13
|
+
":wolfe.freenode.net 004 MarvinBot3000 wolfe.freenode.net hyperion-1.0.2b aAbBcCdDeEfFGhHiIjkKlLmMnNopPQrRsStTuUvVwWxXyYzZ01234569*@ bcdefFhiIklmnoPqstv"
|
14
|
+
]
|
15
|
+
PARSERS = [Marvin::Parsers::RagelParser, Marvin::Parsers::SimpleParser, Marvin::Parsers::RegexpParser]
|
16
|
+
|
17
|
+
LINES.each do |line|
|
18
|
+
|
19
|
+
puts "Processing: #{line}"
|
20
|
+
puts ""
|
21
|
+
cmd = []
|
22
|
+
|
23
|
+
PARSERS.each do |p|
|
24
|
+
parser = p.new(line)
|
25
|
+
ev = parser.to_event
|
26
|
+
puts "Parser: #{p.name}"
|
27
|
+
if ev.nil?
|
28
|
+
puts "Unknown Event"
|
29
|
+
else
|
30
|
+
puts ev.to_hash.inspect
|
31
|
+
end
|
32
|
+
puts ""
|
33
|
+
end
|
34
|
+
puts ""
|
35
|
+
|
36
|
+
end
|
data/test/parser_test.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
class ParserTest < Test::Unit::TestCase
|
2
|
+
@@parser = nil
|
3
|
+
def self.parser_is(p)
|
4
|
+
@@parser = p
|
5
|
+
end
|
6
|
+
|
7
|
+
context "When parsing a PONG" do
|
8
|
+
end
|
9
|
+
|
10
|
+
context "When parsing a PING" do
|
11
|
+
end
|
12
|
+
|
13
|
+
context "When parsing a PRIVMSG" do
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
["Regexp", "Simple"].each do |parser_name|
|
19
|
+
eval("class #{parser_name}ParserTest < ParserTest; parser_is #{parser_is}Parser; end")
|
20
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: Sutto-marvin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.20081120
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Darcy Laycock
|
@@ -9,8 +9,8 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-11-
|
13
|
-
default_executable:
|
12
|
+
date: 2008-11-22 00:00:00 -08:00
|
13
|
+
default_executable: marvin
|
14
14
|
dependencies: []
|
15
15
|
|
16
16
|
description: Marvin is a Ruby IRC library / framework for ultimate awesomeness and with an evented design.
|
@@ -42,33 +42,43 @@ files:
|
|
42
42
|
- lib/marvin/irc/base_server.rb
|
43
43
|
- lib/marvin/irc/client.rb
|
44
44
|
- lib/marvin/irc/event.rb
|
45
|
-
- lib/marvin/irc/
|
45
|
+
- lib/marvin/irc/replies.rb
|
46
46
|
- lib/marvin/irc.rb
|
47
47
|
- lib/marvin/loader.rb
|
48
48
|
- lib/marvin/logger.rb
|
49
49
|
- lib/marvin/middle_man.rb
|
50
|
+
- lib/marvin/options.rb
|
50
51
|
- lib/marvin/parsers
|
52
|
+
- lib/marvin/parsers/command.rb
|
53
|
+
- lib/marvin/parsers/prefixes
|
54
|
+
- lib/marvin/parsers/prefixes/host_mask.rb
|
55
|
+
- lib/marvin/parsers/prefixes/server.rb
|
56
|
+
- lib/marvin/parsers/prefixes.rb
|
57
|
+
- lib/marvin/parsers/ragel_parser.rb
|
58
|
+
- lib/marvin/parsers/ragel_parser.rl
|
51
59
|
- lib/marvin/parsers/regexp_parser.rb
|
52
|
-
- lib/marvin/parsers/simple_parser
|
53
|
-
- lib/marvin/parsers/simple_parser/default_events.rb
|
54
|
-
- lib/marvin/parsers/simple_parser/event_extensions.rb
|
55
|
-
- lib/marvin/parsers/simple_parser/prefixes.rb
|
56
60
|
- lib/marvin/parsers/simple_parser.rb
|
57
61
|
- lib/marvin/parsers.rb
|
58
62
|
- lib/marvin/settings.rb
|
59
63
|
- lib/marvin/test_client.rb
|
60
64
|
- lib/marvin/util.rb
|
61
65
|
- lib/marvin.rb
|
66
|
+
- test/parser_comparison.rb
|
67
|
+
- test/parser_test.rb
|
68
|
+
- test/test_helper.rb
|
62
69
|
- spec/marvin
|
63
70
|
- spec/marvin/abstract_client_test.rb
|
64
71
|
- spec/spec_helper.rb
|
72
|
+
- script/client
|
65
73
|
- script/daemon-runner
|
66
|
-
- script/
|
74
|
+
- script/install
|
75
|
+
- handlers/debug_handler.rb
|
67
76
|
- handlers/hello_world.rb
|
68
77
|
- handlers/logging_handler.rb
|
69
78
|
- handlers/tweet_tweet.rb
|
70
79
|
- config/setup.rb
|
71
80
|
- config/settings.yml.sample
|
81
|
+
- config/connections.yml.sample
|
72
82
|
has_rdoc: false
|
73
83
|
homepage: http://blog.ninjahideout.com/
|
74
84
|
post_install_message:
|