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 +9 -2
- data/config/setup.rb +1 -2
- data/lib/marvin/abstract_client.rb +1 -2
- data/lib/marvin/core_ext.rb +0 -6
- data/lib/marvin/irc/event.rb +3 -2
- data/lib/marvin/loader.rb +13 -0
- data/lib/marvin/logger.rb +2 -1
- data/lib/marvin/parsers/regexp_parser.rb +1 -1
- data/lib/marvin/parsers/simple_parser/default_events.rb +37 -0
- data/lib/marvin/parsers/simple_parser/event_extensions.rb +14 -0
- data/lib/marvin/parsers/simple_parser/prefixes.rb +34 -0
- data/lib/marvin/parsers/simple_parser.rb +101 -0
- data/lib/marvin/parsers.rb +1 -1
- data/lib/marvin/settings.rb +4 -0
- data/lib/marvin.rb +11 -1
- data/script/daemon-runner +12 -0
- data/script/run +3 -2
- metadata +12 -6
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
@@ -23,7 +23,7 @@ module Marvin
|
|
23
23
|
self.class.setup
|
24
24
|
logger.debug "Initializing the current instance"
|
25
25
|
self.channels = []
|
26
|
-
|
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
|
|
data/lib/marvin/core_ext.rb
CHANGED
data/lib/marvin/irc/event.rb
CHANGED
@@ -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.
|
15
|
-
|
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
|
-
|
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)
|
@@ -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
|
data/lib/marvin/parsers.rb
CHANGED
data/lib/marvin/settings.rb
CHANGED
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 '
|
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.
|
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:
|