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.
Files changed (44) hide show
  1. data/README.textile +70 -50
  2. data/VERSION.yml +1 -1
  3. data/bin/marvin +10 -6
  4. data/config/connections.yml.sample +5 -0
  5. data/config/settings.yml.sample +2 -7
  6. data/config/setup.rb +1 -0
  7. data/handlers/debug_handler.rb +5 -0
  8. data/handlers/hello_world.rb +1 -1
  9. data/lib/marvin.rb +1 -0
  10. data/lib/marvin/abstract_client.rb +79 -42
  11. data/lib/marvin/abstract_parser.rb +14 -2
  12. data/lib/marvin/base.rb +44 -6
  13. data/lib/marvin/dispatchable.rb +9 -4
  14. data/lib/marvin/drb_handler.rb +7 -2
  15. data/lib/marvin/exceptions.rb +3 -0
  16. data/lib/marvin/irc.rb +1 -1
  17. data/lib/marvin/irc/client.rb +31 -7
  18. data/lib/marvin/irc/event.rb +9 -4
  19. data/lib/marvin/irc/replies.rb +154 -0
  20. data/lib/marvin/loader.rb +1 -0
  21. data/lib/marvin/logger.rb +66 -3
  22. data/lib/marvin/options.rb +33 -0
  23. data/lib/marvin/parsers.rb +3 -0
  24. data/lib/marvin/parsers/command.rb +73 -0
  25. data/lib/marvin/parsers/prefixes.rb +8 -0
  26. data/lib/marvin/parsers/prefixes/host_mask.rb +30 -0
  27. data/lib/marvin/parsers/prefixes/server.rb +24 -0
  28. data/lib/marvin/parsers/ragel_parser.rb +713 -0
  29. data/lib/marvin/parsers/ragel_parser.rl +144 -0
  30. data/lib/marvin/parsers/regexp_parser.rb +0 -3
  31. data/lib/marvin/parsers/simple_parser.rb +20 -81
  32. data/lib/marvin/settings.rb +8 -8
  33. data/lib/marvin/util.rb +2 -2
  34. data/script/{run → client} +0 -0
  35. data/script/daemon-runner +1 -1
  36. data/script/install +3 -0
  37. data/test/parser_comparison.rb +36 -0
  38. data/test/parser_test.rb +20 -0
  39. data/test/test_helper.rb +10 -0
  40. metadata +19 -9
  41. data/lib/marvin/irc/socket_client.rb +0 -69
  42. data/lib/marvin/parsers/simple_parser/default_events.rb +0 -37
  43. data/lib/marvin/parsers/simple_parser/event_extensions.rb +0 -14
  44. 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
- def parse!
31
- # Split the message
32
- line = self.current_line
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
- extract_prefix! prefix_text
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
- self.parts = head.split(" ")
42
- self.parts << tail
43
- command = self.parts.shift.upcase.to_sym
44
- if command.to_s =~ /^[0-9]{3}$/
45
- # Other Command
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
- def mutate_event!
65
- # Do nothing by default
66
- name, contents = self.event.name, self.event.raw_arguments.last
67
- # mutate for ctcp and actions
68
- if name == :message && contents[0..0] == "\001" && contents[-1..-1] == "\001"
69
- if message.index("ACTION: ") == 1
70
- message = message[9..-2]
71
- new_event = :action
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
- # TODO: Validate the hostname here.
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
@@ -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, :handler_folder, :default_parser
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 ||= begin
27
- require 'eventmachine'
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, *ending = input.split(":")
13
+ prefix, ending = input.split(":", 2)
14
14
  prefix = prefix.split(" ")
15
- prefix << ending.join(":").strip
15
+ prefix << ending unless ending.blank?
16
16
  return prefix
17
17
  end
18
18
 
File without changes
data/script/daemon-runner CHANGED
@@ -4,7 +4,7 @@ require 'daemons'
4
4
 
5
5
  DIR = File.join(File.dirname(__FILE__), "..")
6
6
 
7
- Daemons.run(File.join(DIR, "script/run --is-daemon"),
7
+ Daemons.run(File.join(DIR, "script/client"),
8
8
  {:mode => :exec,
9
9
  :dir => DIR,
10
10
  :dir_mode => :normal,
data/script/install ADDED
@@ -0,0 +1,3 @@
1
+ gem uninstall marvin --quiet
2
+ gem build marvin.gemspec
3
+ gem install marvin-0.1.*.gem
@@ -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
@@ -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
@@ -0,0 +1,10 @@
1
+ BASE_DIR = File.expand_path(File.join(File.dirname(__FILE__), "..")
2
+
3
+ require 'rubygems'
4
+ require 'shoulda'
5
+ require 'test/unit'
6
+ require File.join(BASE_DIR, "lib/marvin")
7
+
8
+ class Test::Unit::TestCase
9
+ # Any extra helpers go here
10
+ end
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.20081115
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-15 00:00:00 -08:00
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/socket_client.rb
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/run
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: