Sutto-marvin 0.1.20081115 → 0.1.20081120

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: