Sutto-marvin 0.4.0 → 0.8.0.0
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 +22 -156
- data/handlers/keiki_thwopper.rb +21 -0
- data/handlers/tweet_tweet.rb +1 -3
- data/lib/marvin/abstract_client.rb +75 -189
- data/lib/marvin/abstract_parser.rb +9 -11
- data/lib/marvin/base.rb +134 -101
- data/lib/marvin/client/actions.rb +104 -0
- data/lib/marvin/client/default_handlers.rb +97 -0
- data/lib/marvin/command_handler.rb +60 -49
- data/lib/marvin/console.rb +4 -31
- data/lib/marvin/core_commands.rb +30 -12
- data/lib/marvin/distributed/client.rb +225 -0
- data/lib/marvin/distributed/handler.rb +85 -0
- data/lib/marvin/distributed/protocol.rb +88 -0
- data/lib/marvin/distributed/server.rb +154 -0
- data/lib/marvin/distributed.rb +4 -10
- data/lib/marvin/dsl.rb +103 -0
- data/lib/marvin/exception_tracker.rb +7 -4
- data/lib/marvin/irc/client.rb +127 -99
- data/lib/marvin/irc/event.rb +14 -10
- data/lib/marvin/irc.rb +0 -1
- data/lib/marvin/middle_man.rb +1 -1
- data/lib/marvin/parsers/command.rb +10 -8
- data/lib/marvin/parsers/prefixes/host_mask.rb +12 -7
- data/lib/marvin/parsers/prefixes/server.rb +1 -1
- data/lib/marvin/parsers/ragel_parser.rb +59 -52
- data/lib/marvin/parsers/ragel_parser.rl +6 -7
- data/lib/marvin/parsers/simple_parser.rb +4 -9
- data/lib/marvin/parsers.rb +1 -2
- data/lib/marvin/settings.rb +29 -79
- data/lib/marvin/test_client.rb +20 -26
- data/lib/marvin/util.rb +10 -3
- data/lib/marvin.rb +42 -39
- data/templates/boot.erb +3 -0
- data/templates/connections.yml.erb +10 -0
- data/templates/debug_handler.erb +5 -0
- data/templates/hello_world.erb +10 -0
- data/templates/rakefile.erb +15 -0
- data/templates/settings.yml.erb +8 -0
- data/{config/setup.rb → templates/setup.erb} +8 -10
- data/templates/test_helper.erb +17 -0
- data/test/abstract_client_test.rb +63 -0
- data/test/parser_comparison.rb +2 -2
- data/test/parser_test.rb +3 -3
- data/test/test_helper.rb +58 -6
- metadata +51 -83
- data/README.textile +0 -105
- data/TUTORIAL.textile +0 -54
- data/VERSION.yml +0 -4
- data/config/boot.rb +0 -14
- data/config/connections.yml.sample +0 -5
- data/config/settings.yml.sample +0 -13
- data/handlers/logging_handler.rb +0 -89
- data/lib/marvin/core_ext.rb +0 -11
- data/lib/marvin/daemon.rb +0 -71
- data/lib/marvin/data_store.rb +0 -73
- data/lib/marvin/dispatchable.rb +0 -99
- data/lib/marvin/distributed/dispatch_handler.rb +0 -83
- data/lib/marvin/distributed/drb_client.rb +0 -78
- data/lib/marvin/distributed/ring_server.rb +0 -41
- data/lib/marvin/handler.rb +0 -12
- data/lib/marvin/irc/server/abstract_connection.rb +0 -84
- data/lib/marvin/irc/server/base_connection.rb +0 -66
- data/lib/marvin/irc/server/channel.rb +0 -115
- data/lib/marvin/irc/server/named_store.rb +0 -14
- data/lib/marvin/irc/server/remote_interface.rb +0 -77
- data/lib/marvin/irc/server/user/handle_mixin.rb +0 -140
- data/lib/marvin/irc/server/user.rb +0 -5
- data/lib/marvin/irc/server/user_connection.rb +0 -134
- data/lib/marvin/irc/server/virtual_user_connection.rb +0 -80
- data/lib/marvin/irc/server.rb +0 -71
- data/lib/marvin/loader.rb +0 -149
- data/lib/marvin/logger.rb +0 -86
- data/lib/marvin/options.rb +0 -42
- data/lib/marvin/parsers/regexp_parser.rb +0 -93
- data/lib/marvin/status.rb +0 -72
- data/script/client +0 -3
- data/script/console +0 -3
- data/script/distributed_client +0 -3
- data/script/install +0 -1
- data/script/ring_server +0 -4
- data/script/server +0 -4
- data/script/status +0 -3
- data/spec/marvin/abstract_client_test.rb +0 -38
- data/spec/spec_helper.rb +0 -14
data/bin/marvin
CHANGED
@@ -1,167 +1,33 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'rubygems'
|
3
|
-
require
|
4
|
-
require "thor"
|
3
|
+
require File.join(File.dirname(__FILE__), "..", "lib", "marvin")
|
5
4
|
|
6
|
-
|
5
|
+
Marvin::Application.processing(ARGV) do |a|
|
7
6
|
|
8
|
-
|
7
|
+
a.banner = "Marvin v#{Marvin::VERSION} - An IRC Library for Ruby"
|
9
8
|
|
10
|
-
|
9
|
+
a.generator!
|
11
10
|
|
12
|
-
|
13
|
-
|
11
|
+
a.option :development, "Runs the app in development mode (handler reloading)", :shortcut => "D"
|
12
|
+
a.controller! :client, "Starts the actual Marvin client instance"
|
13
|
+
a.controller! :console, "Opens a friendly IRB prompt with Marvin pre-loaded"
|
14
|
+
a.controller! :distributed_client, "Starts a distributed client instance"
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
if File.directory?(@dest)
|
21
|
-
STDOUT.puts "The given directory, \"#{path}\", already exists."
|
22
|
-
exit! 1
|
23
|
-
else
|
24
|
-
say "Creating Marvin app"
|
25
|
-
say " => Making directories"
|
26
|
-
mkdir @dest
|
27
|
-
mkdir source(@dest, "script")
|
28
|
-
mkdir source(@dest, "config")
|
29
|
-
mkdir source(@dest, "handlers")
|
30
|
-
mkdir_p source(@dest, "tmp/pids")
|
31
|
-
mkdir source(@dest, "log")
|
32
|
-
mkdir source(@dest, "lib")
|
33
|
-
say " => Copying files..."
|
34
|
-
copy "config/setup.rb"
|
35
|
-
copy "config/boot.rb"
|
36
|
-
copy "config/connections.yml.sample", "config/connections.yml"
|
37
|
-
copy "config/settings.yml.sample", "config/settings.yml"
|
38
|
-
copy "handlers/hello_world.rb"
|
39
|
-
copy "handlers/debug_handler.rb"
|
40
|
-
%w(client console distributed_client ring_server status).each do |c|
|
41
|
-
copy "script/#{c}"
|
42
|
-
FileUtils.chmod 0755, source(@dest, "script/#{c}")
|
43
|
-
end
|
44
|
-
say "Done!"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
map "cl" => :client, "st" => :status, "rs" => :ring_server,
|
49
|
-
"dc" => :distributed_client, "co" => :console
|
50
|
-
|
51
|
-
desc "start [PATH]", "starts client at the given path"
|
52
|
-
method_options :verbose => :boolean, :daemon => :boolean, :level => :optional, :kill => :boolean
|
53
|
-
def start(path = ".")
|
54
|
-
@dest = File.expand_path(path)
|
55
|
-
start_script(:client)
|
56
|
-
end
|
57
|
-
|
58
|
-
desc "status [PATH]", "shows status of marvin app at a given location"
|
59
|
-
def status(path = ".")
|
60
|
-
@dest = File.expand_path(path)
|
61
|
-
start_script(:status)
|
62
|
-
end
|
63
|
-
|
64
|
-
desc "client [PATH]", "starts a client instance from the given location"
|
65
|
-
method_options :verbose => :boolean, :daemon => :boolean, :level => :optional, :kill => :boolean
|
66
|
-
def client(path = ".")
|
67
|
-
@dest = File.expand_path(path)
|
68
|
-
start_script(:client)
|
69
|
-
end
|
70
|
-
|
71
|
-
desc "server [PATH]", "starts a server instance from the given location"
|
72
|
-
method_options :verbose => :boolean, :daemon => :boolean, :level => :optional, :kill => :boolean
|
73
|
-
def server(path = ".")
|
74
|
-
@dest = File.expand_path(path)
|
75
|
-
start_script(:server)
|
76
|
-
end
|
77
|
-
|
78
|
-
desc "ring_server [PATH]", "starts a ring server from the given location"
|
79
|
-
method_options :verbose => :boolean, :daemon => :boolean, :level => :optional, :kill => :boolean
|
80
|
-
def ring_server(path = ".")
|
81
|
-
@dest = File.expand_path(path)
|
82
|
-
start_script(:ring_server)
|
83
|
-
end
|
84
|
-
|
85
|
-
desc "distributed_client [PATH]", "starts a distributed client from the given location"
|
86
|
-
method_options :verbose => :boolean, :daemon => :boolean, :level => :optional,
|
87
|
-
:kill => :boolean, :nodes => :numeric
|
88
|
-
def distributed_client(path = ".")
|
89
|
-
@dest = File.expand_path(path)
|
90
|
-
start_script(:distributed_client)
|
91
|
-
end
|
92
|
-
|
93
|
-
desc "console [PATH]", "starts a marvin console from the given location"
|
94
|
-
def console(path = ".")
|
95
|
-
@dest = File.expand_path(path)
|
96
|
-
start_script(:console)
|
97
|
-
end
|
98
|
-
|
99
|
-
private
|
100
|
-
|
101
|
-
def source(*args)
|
102
|
-
File.expand_path(File.join(*args))
|
103
|
-
end
|
104
|
-
|
105
|
-
def copy(from, to = from)
|
106
|
-
s, d = source(GEM_ROOT, from), source(@dest, to)
|
107
|
-
say " --> cp #{s.gsub(" ", "\\ ")} #{d.gsub(" ", "\\ ")}" if @verbose
|
108
|
-
FileUtils.cp_r(s, d)
|
109
|
-
end
|
110
|
-
|
111
|
-
def mkdir(path)
|
112
|
-
say " --> mkdir #{path.gsub(" ", "\\ ")}" if @verbose
|
113
|
-
FileUtils.mkdir path
|
114
|
-
end
|
115
|
-
|
116
|
-
def mkdir_p(path)
|
117
|
-
say " --> mkdir #{path.gsub(" ", "\\ ")}" if @verbose
|
118
|
-
FileUtils.mkdir_p path
|
119
|
-
end
|
120
|
-
|
121
|
-
def say(text)
|
122
|
-
STDOUT.puts text
|
123
|
-
end
|
124
|
-
|
125
|
-
def marvin_repo?(path, type = client)
|
126
|
-
File.directory?(source(path, "script")) && File.exist?(source(path, "script/#{type}"))
|
127
|
-
end
|
128
|
-
|
129
|
-
def start_script(name)
|
130
|
-
if marvin_repo?(@dest, name)
|
131
|
-
extra_args = []
|
132
|
-
extra_args << "-k" if options[:kill]
|
133
|
-
extra_args << "-v" if options[:verbose]
|
134
|
-
extra_args << "-d" if options[:daemon]
|
135
|
-
extra_args << "--level=#{options[:level]}" if options[:level]
|
136
|
-
if options[:daemon] && options[:nodes]
|
137
|
-
nodes = options[:nodes]
|
138
|
-
else
|
139
|
-
nodes = 1
|
140
|
-
end
|
141
|
-
Dir.chdir(@dest) do
|
142
|
-
# Lets you start a number of different processes.
|
143
|
-
# uses system if there are more than 1 nodes, exec
|
144
|
-
# otherwise.
|
145
|
-
if nodes > 1
|
146
|
-
nodes.times { system("script/#{name}", *extra_args) }
|
147
|
-
else
|
148
|
-
exec("script/#{name}", *extra_args)
|
149
|
-
end
|
150
|
-
end
|
151
|
-
else
|
152
|
-
STDOUT.puts "Woop! #{@dest.gsub(" ", "\\ ")} isn't a marvin app."
|
16
|
+
a.option :force, "force the creation of the application"
|
17
|
+
a.add "create PATH", "Creates a marvin application at the given location" do |path, options|
|
18
|
+
path = File.expand_path(path)
|
19
|
+
if File.exists?(path) && !options[:force]
|
20
|
+
die! "The path you tried to use, #{path}, already exists. Please try another or use the --force option"
|
153
21
|
end
|
22
|
+
setup_generator(path)
|
23
|
+
folders 'tmp', 'config', 'lib', 'handlers', 'test'
|
24
|
+
template 'boot.erb', 'config/boot.rb'
|
25
|
+
template 'setup.erb', 'config/setup.rb'
|
26
|
+
template 'settings.yml.erb', 'config/settings.yml'
|
27
|
+
template 'connections.yml.erb', 'config/connections.yml'
|
28
|
+
template 'debug_handler.erb', 'handlers/debug_handler.rb'
|
29
|
+
template 'hello_world.erb', 'handlers/hello_world.rb'
|
30
|
+
template 'rakefile.erb', 'Rakefile'
|
154
31
|
end
|
155
32
|
|
156
33
|
end
|
157
|
-
|
158
|
-
STDOUT.puts "Marvin - IRC Library / Framework for Ruby"
|
159
|
-
|
160
|
-
# Check if we have arguments, we run the normal
|
161
|
-
# thor task otherwise we just print the help
|
162
|
-
# message.
|
163
|
-
if ARGV.empty?
|
164
|
-
Marvin.new.help
|
165
|
-
else
|
166
|
-
Marvin.start
|
167
|
-
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class KeikiThwopper < Marvin::Base
|
2
|
+
|
3
|
+
FROM_REGEXP = /^(sutto)/i
|
4
|
+
THWOP_REGEXP = /(t+h+w+o+m*p+|stab|kill)/i
|
5
|
+
|
6
|
+
MESSAGES = [
|
7
|
+
"mwahahahaha",
|
8
|
+
"you totally deserved it",
|
9
|
+
"oi! leave 'em alone!",
|
10
|
+
"say hello to my little friend",
|
11
|
+
"you know, they could have liked that?"
|
12
|
+
]
|
13
|
+
|
14
|
+
on_event :incoming_action, :thwop_back
|
15
|
+
|
16
|
+
def thwop_back
|
17
|
+
return if !from || from !~ FROM_REGEXP || options.message !~ THWOP_REGEXP
|
18
|
+
action "#{$1}s #{from} (#{MESSAGES[rand(MESSAGES.length)]})"
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
data/handlers/tweet_tweet.rb
CHANGED
@@ -1,30 +1,30 @@
|
|
1
|
-
require 'ostruct'
|
2
|
-
require 'active_support'
|
3
1
|
require "marvin/irc/event"
|
4
2
|
|
5
3
|
module Marvin
|
6
4
|
class AbstractClient
|
7
5
|
|
8
|
-
|
6
|
+
is :dispatchable, :loggable
|
9
7
|
|
10
|
-
def initialize(opts
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
8
|
+
def initialize(opts)
|
9
|
+
opts = opts.to_nash if opts.is_a?(Hash)
|
10
|
+
@connection_config = opts.dup # Copy the options so we can use them to reconnect.
|
11
|
+
@server = opts.server
|
12
|
+
@port = opts.port
|
13
|
+
@default_channels = opts.channels
|
14
|
+
@nicks = opts.nicks || []
|
15
|
+
@pass = opts.pass
|
17
16
|
end
|
18
17
|
|
19
|
-
cattr_accessor :events, :configuration, :
|
20
|
-
attr_accessor :channels, :nickname, :server, :port, :nicks, :pass,
|
18
|
+
cattr_accessor :events, :configuration, :is_setup, :connections, :development
|
19
|
+
attr_accessor :channels, :nickname, :server, :port, :nicks, :pass,
|
20
|
+
:disconnect_expected, :connection_config
|
21
21
|
|
22
22
|
# Set the default values for the variables
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
@@events = []
|
24
|
+
@@configuration = Marvin::Nash.new
|
25
|
+
@@connections = []
|
26
|
+
@@development = false
|
27
|
+
|
28
28
|
# Initializes the instance variables used for the
|
29
29
|
# current connection, dispatching a :client_connected event
|
30
30
|
# once it has finished. During this process, it will
|
@@ -32,78 +32,79 @@ module Marvin
|
|
32
32
|
def process_connect
|
33
33
|
self.class.setup
|
34
34
|
logger.info "Initializing the current instance"
|
35
|
-
|
36
|
-
|
35
|
+
@channels = []
|
36
|
+
connections << self
|
37
37
|
logger.info "Setting the client for each handler"
|
38
|
-
|
38
|
+
setup_handlers
|
39
39
|
logger.info "Dispatching the default :client_connected event"
|
40
40
|
dispatch :client_connected
|
41
41
|
end
|
42
42
|
|
43
43
|
def process_disconnect
|
44
|
-
logger.info "Handling disconnect for #{
|
45
|
-
|
44
|
+
logger.info "Handling disconnect for #{host_with_port}"
|
45
|
+
connections.delete(self)
|
46
46
|
dispatch :client_disconnected
|
47
|
-
unless
|
48
|
-
logger.warn "
|
49
|
-
self.class.add_reconnect
|
47
|
+
unless @disconnect_expected
|
48
|
+
logger.warn "Unexpectly lost connection to server; adding reconnect"
|
49
|
+
self.class.add_reconnect @connection_config
|
50
50
|
else
|
51
|
-
Marvin::Loader.stop! if
|
51
|
+
Marvin::Loader.stop! if connections.blank?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def setup_handlers
|
56
|
+
handlers.each { |h| h.client = self if h.respond_to?(:client=) }
|
57
|
+
end
|
58
|
+
|
59
|
+
def process_development
|
60
|
+
if @@development
|
61
|
+
Marvin::Reloading.reload!
|
62
|
+
setup_handlers
|
52
63
|
end
|
53
64
|
end
|
54
65
|
|
66
|
+
def dispatch(*args)
|
67
|
+
process_development
|
68
|
+
super
|
69
|
+
end
|
70
|
+
|
55
71
|
# Sets the current class-wide settings of this IRC Client
|
56
72
|
# to either an OpenStruct or the results of #to_hash on
|
57
73
|
# any other value that is passed in.
|
58
74
|
def self.configuration=(config)
|
59
|
-
|
75
|
+
config = Marvin::Nash.new(config.to_hash) unless config.is_a?(Marvin::Nash)
|
76
|
+
@@configuration = config.normalized
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.setup?
|
80
|
+
@setup ||= false
|
60
81
|
end
|
61
82
|
|
62
|
-
# Initializes class-wide settings and those that
|
63
|
-
# are required such as the logger. by default, it
|
64
|
-
# will convert the channel option of the configuration
|
65
|
-
# to be channels - hence normalising it into a format
|
66
|
-
# that is more widely used throughout the client.
|
67
83
|
def self.setup
|
68
|
-
return if
|
69
|
-
|
70
|
-
|
71
|
-
|
84
|
+
return if setup?
|
85
|
+
configure
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.configure
|
89
|
+
config = Marvin::Nash.new
|
90
|
+
config.merge! Marvin::Settings.configuration
|
91
|
+
if block_given?
|
92
|
+
yield(nash = Marvin::Nash.new)
|
93
|
+
config.merge! nash
|
72
94
|
end
|
73
|
-
|
74
|
-
|
95
|
+
@@configuration = config
|
96
|
+
# Help is only currently available on an instance running
|
97
|
+
# distributed handler.
|
98
|
+
Marvin::CoreCommands.register! unless Marvin::Distributed::Handler.registered?
|
99
|
+
@setup = true
|
75
100
|
end
|
76
101
|
|
77
102
|
## Handling all of the the actual client stuff.
|
78
103
|
|
79
104
|
def receive_line(line)
|
80
105
|
dispatch :incoming_line, :line => line
|
81
|
-
event = Marvin::Settings.
|
82
|
-
dispatch(event.to_incoming_event_name, event.to_hash) unless event.nil?
|
83
|
-
end
|
84
|
-
|
85
|
-
# Default handlers
|
86
|
-
|
87
|
-
# The default handler for all things initialization-related
|
88
|
-
# on the client. Usually, this will send the user command,
|
89
|
-
# set out nick, join all of the channels / rooms we wish
|
90
|
-
# to be in and if a password is specified in the configuration,
|
91
|
-
# it will also attempt to identify us.
|
92
|
-
def handle_client_connected(opts = {})
|
93
|
-
logger.info "About to handle client connected"
|
94
|
-
# If the pass is set
|
95
|
-
unless self.pass.blank?
|
96
|
-
logger.info "Sending pass for connection"
|
97
|
-
command :pass, self.pass
|
98
|
-
end
|
99
|
-
# IRC Connection is establish so we send all the required commands to the server.
|
100
|
-
logger.info "Setting default nickname"
|
101
|
-
default_nickname = self.nicks.shift
|
102
|
-
nick default_nickname
|
103
|
-
logger.info "sending user command"
|
104
|
-
command :user, self.configuration.user, "0", "*", Marvin::Util.last_param(self.configuration.name)
|
105
|
-
rescue Exception => e
|
106
|
-
Marvin::ExceptionTracker.log(e)
|
106
|
+
event = Marvin::Settings.parser.parse(line)
|
107
|
+
dispatch(event.to_incoming_event_name, event.to_hash) unless event.nil?
|
107
108
|
end
|
108
109
|
|
109
110
|
def default_channels
|
@@ -115,145 +116,30 @@ module Marvin
|
|
115
116
|
end
|
116
117
|
|
117
118
|
def host_with_port
|
118
|
-
@host_with_port ||= "#{
|
119
|
+
@host_with_port ||= "#{server}:#{port}"
|
119
120
|
end
|
120
121
|
|
121
122
|
def nicks
|
122
123
|
if @nicks.blank? && !@nicks_loaded
|
123
124
|
logger.info "Setting default nick list"
|
124
125
|
@nicks = []
|
125
|
-
@nicks <<
|
126
|
-
@nicks +=
|
126
|
+
@nicks << configuration.nick if configuration.nick?
|
127
|
+
@nicks += configuration.nicks.to_a if configuration.nicks?
|
127
128
|
@nicks.compact!
|
129
|
+
raise "No initial nicks for #{host_with_port}" if @nicks.blank?
|
128
130
|
@nicks_loaded = true
|
129
131
|
end
|
130
132
|
return @nicks
|
131
133
|
end
|
132
134
|
|
133
|
-
#
|
134
|
-
|
135
|
-
|
136
|
-
logger.info "Received Incoming Ping - Handling with a PONG"
|
137
|
-
pong(opts[:data])
|
138
|
-
end
|
139
|
-
|
140
|
-
# TODO: Get the correct mapping for a given
|
141
|
-
# Code.
|
142
|
-
def handle_incoming_numeric(opts = {})
|
143
|
-
case opts[:code]
|
144
|
-
when Marvin::IRC::Replies[:RPL_WELCOME]
|
145
|
-
handle_welcome
|
146
|
-
when Marvin::IRC::Replies[:ERR_NICKNAMEINUSE]
|
147
|
-
handle_nick_taken
|
148
|
-
end
|
149
|
-
code = opts[:code].to_i
|
150
|
-
args = Marvin::Util.arguments(opts[:data])
|
151
|
-
dispatch :incoming_numeric_processed, :code => code, :data => args
|
152
|
-
end
|
153
|
-
|
154
|
-
def handle_welcome
|
155
|
-
logger.info "Say hello to my little friend - Got welcome"
|
156
|
-
# If a password is specified, we will attempt to message
|
157
|
-
# NickServ to identify ourselves.
|
158
|
-
say ":IDENTIFY #{self.configuration.password}", "NickServ" unless self.configuration.password.blank?
|
159
|
-
# Join the default channels IF they're already set
|
160
|
-
# Note that Marvin::IRC::Client.connect will set them AFTER this stuff is run.
|
161
|
-
self.default_channels.each { |c| self.join(c) }
|
162
|
-
end
|
135
|
+
# Break it down into a couple of different files.
|
136
|
+
require 'marvin/client/default_handlers'
|
137
|
+
require 'marvin/client/actions'
|
163
138
|
|
164
|
-
|
165
|
-
# on the server. It will attempt to get the nicknickname from
|
166
|
-
# the nicknames part of the configuration (if available) and
|
167
|
-
# will then call #nick to change the nickname.
|
168
|
-
def handle_nick_taken
|
169
|
-
logger.info "Nickname '#{self.nickname}' on #{self.server} taken, trying next."
|
170
|
-
logger.info "Available Nicknames: #{self.nicks.empty? ? "None" : self.nicks.join(", ")}"
|
171
|
-
if !self.nicks.empty?
|
172
|
-
logger.info "Getting next nickname to switch"
|
173
|
-
next_nick = self.nicks.shift # Get the next nickname
|
174
|
-
logger.info "Attemping to set nickname to '#{next_nick}'"
|
175
|
-
nick next_nick
|
176
|
-
else
|
177
|
-
logger.fatal "No Nicknames available - QUITTING"
|
178
|
-
quit
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
## General IRC Functions
|
183
|
-
|
184
|
-
# Sends a specified command to the server.
|
185
|
-
# Takes name (e.g. :privmsg) and all of the args.
|
186
|
-
# Very simply formats them as a string correctly
|
187
|
-
# and calls send_data with the results.
|
188
|
-
def command(name, *args)
|
189
|
-
# First, get the appropriate command
|
190
|
-
name = name.to_s.upcase
|
191
|
-
args = args.flatten.compact
|
192
|
-
irc_command = "#{name} #{args.join(" ").strip}\r\n"
|
193
|
-
send_line irc_command
|
194
|
-
end
|
195
|
-
|
196
|
-
def join(channel)
|
197
|
-
channel = Marvin::Util.channel_name(channel)
|
198
|
-
# Record the fact we're entering the room.
|
199
|
-
# TODO: Refactor to only add the channel when we receive confirmation we've joined.
|
200
|
-
self.channels << channel
|
201
|
-
command :JOIN, channel
|
202
|
-
logger.info "Joined channel #{channel}"
|
203
|
-
dispatch :outgoing_join, :target => channel
|
204
|
-
end
|
205
|
-
|
206
|
-
def part(channel, reason = nil)
|
207
|
-
channel = Marvin::Util.channel_name(channel)
|
208
|
-
if self.channels.include?(channel)
|
209
|
-
command :part, channel, Marvin::Util.last_param(reason)
|
210
|
-
dispatch :outgoing_part, :target => channel, :reason => reason
|
211
|
-
logger.info "Parted from room #{channel}#{reason ? " - #{reason}" : ""}"
|
212
|
-
else
|
213
|
-
logger.warn "Tried to disconnect from #{channel} - which you aren't a part of"
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
def quit(reason = nil)
|
218
|
-
self.disconnect_expected = true
|
219
|
-
logger.info "Preparing to part from #{self.channels.size} channels"
|
220
|
-
self.channels.to_a.each do |chan|
|
221
|
-
logger.info "Parting from #{chan}"
|
222
|
-
self.part chan, reason
|
223
|
-
end
|
224
|
-
logger.info "Parted from all channels, quitting"
|
225
|
-
command :quit
|
226
|
-
dispatch :quit
|
227
|
-
# Remove the connections from the pool
|
228
|
-
self.connections.delete(self)
|
229
|
-
logger.info "Quit from server"
|
230
|
-
end
|
231
|
-
|
232
|
-
def msg(target, message)
|
233
|
-
command :privmsg, target, Marvin::Util.last_param(message)
|
234
|
-
logger.info "Message sent to #{target} - #{message}"
|
235
|
-
dispatch :outgoing_message, :target => target, :message => message
|
236
|
-
end
|
237
|
-
|
238
|
-
def action(target, message)
|
239
|
-
action_text = Marvin::Util.last_param "\01ACTION #{message.strip}\01"
|
240
|
-
command :privmsg, target, action_text
|
241
|
-
dispatch :outgoing_action, :target => target, :message => message
|
242
|
-
logger.info "Action sent to #{target} - #{message}"
|
243
|
-
end
|
244
|
-
|
245
|
-
def pong(data)
|
246
|
-
command :pong, data
|
247
|
-
dispatch :outgoing_pong
|
248
|
-
logger.info "PONG sent to #{data}"
|
249
|
-
end
|
139
|
+
protected
|
250
140
|
|
251
|
-
def
|
252
|
-
|
253
|
-
command :nick, new_nick
|
254
|
-
self.nickname = new_nick
|
255
|
-
dispatch :outgoing_nick, :new_nick => new_nick
|
256
|
-
logger.info "Nickname changed to #{new_nick}"
|
141
|
+
def util
|
142
|
+
Marvin::Util
|
257
143
|
end
|
258
144
|
|
259
145
|
end
|
@@ -1,27 +1,25 @@
|
|
1
1
|
module Marvin
|
2
|
-
# An abstract class for an IRC protocol
|
3
|
-
# Parser. Used as a basis for expirimentation.
|
4
2
|
class AbstractParser
|
5
3
|
|
6
|
-
def self.parse(line)
|
7
|
-
return self.new(line.strip).to_event
|
8
|
-
end
|
9
|
-
|
10
4
|
attr_accessor :line, :command, :event
|
11
5
|
|
12
6
|
# Instantiates a parser instance, attempts to
|
13
7
|
# parse it for it's command and it's event.
|
14
8
|
def initialize(line)
|
15
|
-
|
16
|
-
|
17
|
-
|
9
|
+
@line = line
|
10
|
+
@command = self.class.parse!(line)
|
11
|
+
@event = @command.to_event unless @command.blank?
|
18
12
|
end
|
19
13
|
|
20
14
|
def to_event
|
21
|
-
|
15
|
+
@event
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.parse(line)
|
19
|
+
new(line.strip).to_event
|
22
20
|
end
|
23
21
|
|
24
|
-
|
22
|
+
protected
|
25
23
|
|
26
24
|
def self.parse!(line)
|
27
25
|
raise NotImplementedError, "Must be implemented in a subclass"
|