Sutto-marvin 0.1.0.20081014 → 0.1.0.20081016

Sign up to get free protection for your applications and to get access to all the features.
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: