Sutto-marvin 0.1.0.20081014 → 0.1.0.20081016

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.
data/bin/marvin CHANGED
@@ -21,7 +21,7 @@ if ARGV.include?("-h") || ARGV.include?("--help")
21
21
  exit
22
22
  end
23
23
 
24
- if ARGV.length >= 1
24
+ if ARGV.length >= 1 && !["start", "stop", "run", "restart"].include?(ARGV[0])
25
25
  if ARGV[0].to_s.downcase != "create"
26
26
  puts "'#{ARGV[0]}' isn't a valid command. - Please use #{__FILE__} --help"
27
27
  exit(1)
@@ -44,13 +44,20 @@ if ARGV.length >= 1
44
44
 
45
45
  puts "Copying start script - script/run"
46
46
  copy "script/run"
47
+ copy "script/daemon-runner"
47
48
  FileUtils.chmod 0755, j(DEST, "script/run")
49
+ FileUtils.chmod 0755, j(DEST, "script/daemon-runner")
48
50
 
49
51
  puts "Copying example handler"
50
52
  copy "handlers/hello_world.rb"
51
53
 
52
54
  puts "Done!"
53
-
55
+ elsif ARGV.length >= 1
56
+ if !File.exist?("script/daemon-runner")
57
+ puts "Woops! This isn't a marvin directory."
58
+ exit(1)
59
+ end
60
+ exec "script/daemon-runner #{ARGV.map {|a| a.include?(" ") ? "\"#{a}\"" : a }.join(" ")}"
54
61
  else
55
62
  if !File.exist?("script/run")
56
63
  puts "Woops! This isn't a marvin directory."
data/config/setup.rb CHANGED
@@ -9,7 +9,6 @@ Marvin::Loader.before_connecting do
9
9
  # Example Handler use.
10
10
  # LoggingHandler.register! if Marvin::Settings.use_logging
11
11
 
12
- # Register using Marvin::MiddleMan.
13
- #HelloWorld.register!(Marvin::MiddleMan)
12
+ HelloWorld.register!
14
13
 
15
14
  end
@@ -23,7 +23,7 @@ module Marvin
23
23
  self.class.setup
24
24
  logger.debug "Initializing the current instance"
25
25
  self.channels = []
26
- (self.connections ||= []) << self
26
+ self.connections << self
27
27
  logger.debug "Setting the client for each handler"
28
28
  self.handlers.each { |h| h.client = self if h.respond_to?(:client=) }
29
29
  logger.debug "Dispatching the default :client_connected event"
@@ -167,7 +167,6 @@ module Marvin
167
167
  def handle_incoming_numeric(opts = {})
168
168
  code = opts[:code].to_i
169
169
  args = Marvin::Util.arguments(opts[:data])
170
- logger.debug "Dispatching processed numeric - #{code}"
171
170
  dispatch_event :incoming_numeric_processed, {:code => code, :data => args}
172
171
  end
173
172
 
@@ -1,9 +1,3 @@
1
- class String
2
- def /(other)
3
- File.join(self, other)
4
- end
5
- end
6
-
7
1
  class File
8
2
  def self.present_dir
9
3
  File.dirname(__FILE__)
@@ -11,8 +11,9 @@ module Marvin::IRC
11
11
  return {} unless self.raw_arguments
12
12
  results = {}
13
13
  values = self.raw_arguments.to_a
14
- self.keys.each do |key|
15
- results[key] = values.shift
14
+ last_index = self.keys.size - 1
15
+ self.keys.each_with_index do |key, i|
16
+ results[key] = (i == last_index ? values.join(" ").strip : values.shift)
16
17
  end
17
18
  return results
18
19
  end
data/lib/marvin/loader.rb CHANGED
@@ -3,6 +3,9 @@ module Marvin
3
3
 
4
4
  cattr_accessor :setup_block
5
5
 
6
+ cattr_accessor :start_hooks, :stop_hooks
7
+ self.stop_hooks, self.start_hooks = [], []
8
+
6
9
  def self.before_connecting(&blk)
7
10
  self.setup_block = blk
8
11
  end
@@ -11,6 +14,14 @@ module Marvin
11
14
  Marvin::Logger.setup
12
15
  end
13
16
 
17
+ def self.before_run(&blk)
18
+ self.start_hooks << blk unless blk.blank?
19
+ end
20
+
21
+ def self.after_stop(&blk)
22
+ self.stop_hooks << blk unless blk.blank?
23
+ end
24
+
14
25
  def load_handlers
15
26
  handlers = Dir[Marvin::Settings.root / "handlers/**/*.rb"].map { |h| h[0..-4] }
16
27
  handlers.each do |handler|
@@ -35,11 +46,13 @@ module Marvin
35
46
  self.load_settings
36
47
  self.load_handlers
37
48
  self.pre_connect_setup
49
+ self.start_hooks.each { |h| h.call }
38
50
  Marvin::Settings.default_client.run
39
51
  end
40
52
 
41
53
  def stop!
42
54
  Marvin::Settings.default_client.stop
55
+ self.stop_hooks.each { |h| h.call }
43
56
  Marvin::DataStore.dump!
44
57
  end
45
58
 
data/lib/marvin/logger.rb CHANGED
@@ -8,7 +8,8 @@ module Marvin
8
8
  class << self
9
9
 
10
10
  def setup
11
- self.logger ||= ::Logger.new(STDOUT)
11
+ log_path = Marvin::Settings.root / "log/#{Marvin::Settings.environment}.log"
12
+ self.logger ||= ::Logger.new(Marvin::Settings.daemon? ? log_path : STDOUT)
12
13
  end
13
14
 
14
15
  def method_missing(name, *args, &blk)
@@ -88,7 +88,7 @@ module Marvin
88
88
  :nick, :ident, :host, :data
89
89
 
90
90
  register_event :numeric, /^\:(\S+) ([0-9]+) (.*)$/,
91
- :host, :code, :data
91
+ :server, :code, :data
92
92
  end
93
93
  end
94
94
  end
@@ -0,0 +1,37 @@
1
+ class Marvin::Parsers::SimpleParser < Marvin::AbstractParser
2
+ module DefaultEvents
3
+
4
+ def self.included(parent)
5
+ parent.class_eval do
6
+ extend ClassMethods
7
+ # Register the default set of events with commands
8
+ register_event :nick, :NICK, :new_nick
9
+ register_event :quit, :QUIT, :message
10
+ register_event :ping, :PING, :data
11
+ register_event :join, :JOIN, :target
12
+ register_event :invite, :INVITE, :target, :channel
13
+ register_event :message, :PRIVMSG, :target, :message
14
+ register_event :part, :PART, :target, :message
15
+ register_event :mode, :MODE, :target, :mode
16
+ register_event :kick, :KICK, :target, :channel, :reason
17
+ register_event :topic, :TOPIC, :target, :topic
18
+ # Add the default numeric event
19
+ register_event :numeric, :numeric, :code, :data
20
+ # And a few others reserved for special purposed
21
+ register_event :action, :action, :message
22
+ register_event :ctcp, :ctcp, :message
23
+ end
24
+ end
25
+
26
+ module ClassMethods
27
+
28
+ # Register an event from a given name,
29
+ # command as well as a set of arguments.
30
+ def register_event(name, command, *args)
31
+ event = Marvin::Parsers::SimpleParser::EventWithPrefix.new(name, *args)
32
+ self.events[command] = event
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,14 @@
1
+ # An extension to Marvin::IRC::Event which
2
+ # lets a user specify a prefix to use.
3
+ class Marvin::Parsers::SimpleParser < Marvin::AbstractParser
4
+
5
+ class EventWithPrefix < Marvin::IRC::Event
6
+ attr_accessor :prefix
7
+
8
+ def to_hash
9
+ super.merge(prefix.blank? ? {} : prefix.to_hash)
10
+ end
11
+
12
+ end
13
+
14
+ end
@@ -0,0 +1,34 @@
1
+ # A Set of prefixes for a given IRC line
2
+ # as parsed from an incoming line.
3
+ class Marvin::Parsers::SimpleParser < Marvin::AbstractParser
4
+
5
+ class Prefix; end
6
+
7
+ class ServerNamePrefix < Prefix
8
+ attr_accessor :server_name
9
+
10
+ def initialize(name)
11
+ self.server_name = name
12
+ end
13
+
14
+ def to_hash
15
+ {:server => self.server_name}
16
+ end
17
+
18
+ end
19
+
20
+ class UserPrefix < Prefix
21
+ attr_accessor :nick, :ident, :host
22
+
23
+ def initialize(nick, ident = nil, host = nil)
24
+ self.nick = nick
25
+ self.ident = ident
26
+ self.host = host
27
+ end
28
+
29
+ def to_hash
30
+ {:host => self.host, :nick => self.nick, :ident => self.ident}
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,101 @@
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
+ module Marvin
6
+ module Parsers
7
+ class SimpleParser < Marvin::AbstractParser
8
+
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
+ private
29
+
30
+ def parse!
31
+ # Split the message
32
+ line = self.current_line
33
+ if line[0] == ?:
34
+ prefix_text, line = line.split(" ", 2)
35
+ else
36
+ prefix_text = nil
37
+ end
38
+ extract_prefix! prefix_text
39
+
40
+ 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
62
+ end
63
+
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)
90
+ else
91
+ # TODO: Validate the hostname here.
92
+ prefix = ServerNamePrefix.new(prefix.strip)
93
+ end
94
+ self.prefix = prefix
95
+ return prefix
96
+ end
97
+
98
+ include DefaultEvents
99
+ end
100
+ end
101
+ end
@@ -2,6 +2,6 @@ module Marvin
2
2
  module Parsers
3
3
  # Default Parsers
4
4
  autoload :RegexpParser, 'marvin/parsers/regexp_parser'
5
-
5
+ autoload :SimpleParser, 'marvin/parsers/simple_parser'
6
6
  end
7
7
  end
@@ -16,6 +16,10 @@ module Marvin
16
16
  self.setup!(options)
17
17
  end
18
18
 
19
+ def daemon?
20
+ defined?(IS_DAEMON) && IS_DAEMON
21
+ end
22
+
19
23
  def setup!(options = {})
20
24
  self.environment ||= "development"
21
25
  self.configuration = {}
data/lib/marvin.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  $:.unshift File.dirname(__FILE__) # Append the current working dir to the front of the line.
2
2
 
3
3
  require 'rubygems'
4
- require 'active_support'
4
+ require 'extlib'
5
5
  require 'marvin/core_ext'
6
6
 
7
7
  # Make all exceptions available
@@ -30,4 +30,14 @@ module Marvin
30
30
 
31
31
  Settings.setup # Load Settings etc.
32
32
 
33
+ end
34
+
35
+ def p(text)
36
+ res = Marvin::Parsers::SimpleParser.parse(text)
37
+ if res.blank?
38
+ puts "Unrecognized Result"
39
+ else
40
+ STDOUT.puts "Event: #{res.to_incoming_event_name}"
41
+ STDOUT.puts "Args: #{res.to_hash.inspect}"
42
+ end
33
43
  end
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'daemons'
4
+
5
+ DIR = File.join(File.dirname(__FILE__), "..")
6
+
7
+ Daemons.run(File.join(DIR, "script/run --is-daemon"),
8
+ {:mode => :exec,
9
+ :dir => DIR,
10
+ :dir_mode => :normal,
11
+ :log_output => true,
12
+ :app_name => 'marvin'})
data/script/run CHANGED
@@ -1,12 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'rubygems'
3
- # Set the root of Marvin
4
3
 
5
4
  if File.exist?(File.dirname(__FILE__) + "/../lib/marvin.rb")
6
5
  $:.unshift(File.dirname(__FILE__) + "/../lib/")
7
6
  end
8
7
 
9
8
  MARVIN_ROOT = File.join(File.dirname(__FILE__), "..")
9
+ IS_DAEMON = ARGV.include?("--is-daemon")
10
+
10
11
  # And Require Marvin.
11
12
  require 'marvin'
12
13
 
@@ -15,4 +16,4 @@ trap "SIGINT" do
15
16
  exit
16
17
  end
17
18
 
18
- Marvin::Loader.run!
19
+ Marvin::Loader.run!
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.0.20081014
4
+ version: 0.1.0.20081016
5
5
  platform: ruby
6
6
  authors:
7
7
  - Darcy Laycock
@@ -24,6 +24,7 @@ extra_rdoc_files: []
24
24
  files:
25
25
  - lib/marvin
26
26
  - lib/marvin/abstract_client.rb
27
+ - lib/marvin/abstract_parser.rb
27
28
  - lib/marvin/base.rb
28
29
  - lib/marvin/command_handler.rb
29
30
  - lib/marvin/core_ext.rb
@@ -32,6 +33,7 @@ files:
32
33
  - lib/marvin/exception_tracker.rb
33
34
  - lib/marvin/exceptions.rb
34
35
  - lib/marvin/irc
36
+ - lib/marvin/irc/abstract_server.rb
35
37
  - lib/marvin/irc/client.rb
36
38
  - lib/marvin/irc/event.rb
37
39
  - lib/marvin/irc/socket_client.rb
@@ -39,22 +41,26 @@ files:
39
41
  - lib/marvin/loader.rb
40
42
  - lib/marvin/logger.rb
41
43
  - lib/marvin/middle_man.rb
44
+ - lib/marvin/parsers
45
+ - lib/marvin/parsers/regexp_parser.rb
46
+ - lib/marvin/parsers/simple_parser
47
+ - lib/marvin/parsers/simple_parser/default_events.rb
48
+ - lib/marvin/parsers/simple_parser/event_extensions.rb
49
+ - lib/marvin/parsers/simple_parser/prefixes.rb
50
+ - lib/marvin/parsers/simple_parser.rb
51
+ - lib/marvin/parsers.rb
42
52
  - lib/marvin/settings.rb
43
53
  - lib/marvin/test_client.rb
44
54
  - lib/marvin/util.rb
45
55
  - lib/marvin.rb
46
56
  - bin/marvin
47
- - config/settings.yml
48
57
  - config/settings.yml.sample
49
58
  - config/setup.rb
50
59
  - handlers/hello_world.rb
51
60
  - handlers/logging_handler.rb
52
61
  - handlers/tweet_tweet.rb
62
+ - script/daemon-runner
53
63
  - script/run
54
- - lib/marvin/parsers/regexp_parser.rb
55
- - lib/marvin/parsers.rb
56
- - lib/marvin/irc/abstract_server.rb
57
- - lib/marvin/abstract_parser.rb
58
64
  has_rdoc: true
59
65
  homepage: http://github.com/sutto/marvin
60
66
  post_install_message: