PerfectlyNormal-Flexo 0.4.2 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
data/bin/flexo CHANGED
File without changes
@@ -93,7 +93,5 @@ module Flexo
93
93
  end
94
94
  end
95
95
 
96
- if __FILE__ == $0
97
- c = Flexo::ConfigGenerator.new
98
- c.generate_interactive
99
- end
96
+ c = Flexo::ConfigGenerator.new
97
+ c.generate_interactive
@@ -1,10 +1,10 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "Flexo"
3
- s.version = "0.4.2"
4
- s.date = "2008-10-19"
3
+ s.version = "0.4.4"
4
+ s.date = "2008-12-25"
5
5
  s.author = "Per Christian B. Viken"
6
6
  s.email = "perchr@northblue.org"
7
- s.homepage = "http://eastblue.org/dev/flexo/"
7
+ s.homepage = "http://eastblue.org/projects/flexo/"
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.summary = "A simple, extensible IRC bot based on Flux"
10
10
  s.files = ["README",
@@ -56,11 +56,7 @@ module Flexo
56
56
  def parse_hostmask(mask)
57
57
  m = mask.match(/^([^!\s]+)(?:(?:!([^@\s]+))?@(\S+))?$/)
58
58
 
59
- if m
60
- host = Hostmask.new(m[1], m[2], m[3])
61
- return host
62
- end
63
-
59
+ return Hostmask.new(m[1], m[2], m[3]) if m
64
60
  return nil
65
61
  end
66
62
  end
@@ -72,10 +72,12 @@ module Flexo
72
72
  def subscribe(event, &block)
73
73
  if event.is_a?(Symbol) || event.kind_of?(String)
74
74
  if (e = event.to_s) =~ /^(?:RPL|ERR)_/i
75
+ @manager.logger.debug "Subscribing to a ReplyEvent (#{e})"
75
76
  event = Flexo::Events::ReplyEvent[e.upcase]
76
77
  else
77
78
  match = e.match(/^(.+?)(?:_?event)?$/i)
78
79
  event = Flexo::Events.const_get("#{match[1].capitalize}Event")
80
+ @manager.logger.debug "Subscribing to a #{match[1].capitalize}Event (else)"
79
81
  end
80
82
  end
81
83
 
@@ -86,6 +88,7 @@ module Flexo
86
88
  numeric = false
87
89
  end
88
90
 
91
+ @manager.logger.debug "Creating a handler against #{numeric.to_s}"
89
92
  handler = Handler.new(numeric, &block)
90
93
  @manager.mutex do
91
94
  @handlers[event] ||= []
@@ -105,6 +108,24 @@ module Flexo
105
108
 
106
109
  @manager.logger.debug("Handler #{handler} removed")
107
110
  end
111
+
112
+ # Waits for a specified amount of time, which defaults to 60.
113
+ # If the chosen event isn't receieved within that time, a TimeoutError
114
+ # is raised.
115
+ def await(event, opts = {}, &block)
116
+ opts = {:timeout => 60}.merge(opts)
117
+ queue = Queue.new
118
+ handler = subscribe(event) do |e|
119
+ queue << e
120
+ block.call(e) if block_given?
121
+ end
122
+
123
+ begin
124
+ Timeout.timeout(opts[:timeout], Flexo::TimeoutError) { queue.shift }
125
+ ensure
126
+ unsubscribe(handler)
127
+ end
128
+ end
108
129
 
109
130
  # Easy way to add a trigger.
110
131
  # See Flexo::Trigger for documentation
@@ -6,6 +6,10 @@ module Flexo
6
6
  # Raised when the configuration is invalid, and there's no way to recover
7
7
  class InvalidConfigurationException < Error
8
8
  end
9
+
10
+ # Error raised when calls to Dispatcher.await times out
11
+ class TimeoutError < Error
12
+ end
9
13
 
10
14
  # Raised when a plugin is missing a required dependency
11
15
  class PluginDependencyError < Error
@@ -22,8 +22,8 @@ module Flexo
22
22
  end
23
23
 
24
24
  def self.[](reply)
25
- n = (reply =~ /^\d+$/ || reply.kind_of?(Integer)) ? reply.to_i : Numerics.const_get(reply)
26
- Numeric.new(n)
25
+ n = (reply =~ /^\d+$/ || reply.kind_of?(Integer)) ? reply.to_i : Flexo::Numerics.const_get(reply)
26
+ Flexo::Events::ReplyEvent::Numeric.new(n)
27
27
  end
28
28
  end
29
29
 
@@ -22,7 +22,7 @@ module Flexo
22
22
  # aptly named 'call', is called, the block passed
23
23
  # as block when creating this instance, is executed.
24
24
  def call(event)
25
- if !@numeric || event.class == ReplyEvent && @numeric == event.numeric
25
+ if !@numeric || event.class == Flexo::Events::ReplyEvent && @numeric == event.numeric
26
26
  @manager.thread { @block.call(event) }
27
27
  end
28
28
  end
@@ -33,9 +33,6 @@ module Flexo
33
33
 
34
34
  # Create everything
35
35
  def setup
36
- return if @setup == true
37
- @setup = true
38
-
39
36
  @config = Flexo::Config.new
40
37
  raise InvalidConfigurationException unless @config.valid?
41
38
 
@@ -96,9 +93,11 @@ module Flexo
96
93
  end
97
94
  end
98
95
  }
99
-
100
- @logger.debug "Sleeping a while to allow logging into the server"
101
- sleep 15
96
+
97
+ while(!@server.welcomed) do
98
+ @logger.debug "Not welcomed, sleeping"
99
+ sleep 0.5
100
+ end
102
101
 
103
102
  @logger.info "Joining channels"
104
103
  @config['core.channels'].each do |channel|
@@ -62,6 +62,17 @@ module Flexo
62
62
  super
63
63
  end
64
64
 
65
+ # Searches loaded plugins for a method. Used by plugins to see if
66
+ # certain optional functionality is available, instead of adding
67
+ # the plugin providing the function as a requirement.
68
+ def has_method?(method)
69
+ @plugins.each do |name, plugin|
70
+ return true if plugin.respond_to?(method)
71
+ end
72
+
73
+ return false
74
+ end
75
+
65
76
  # Synchronize mutex
66
77
  def mutex
67
78
  @manager.pluginmutex { yield }
@@ -113,6 +113,16 @@ module Flexo
113
113
  klass = @plugins_loaded[plugin]
114
114
  @manager.mutex { @plugins_loaded.delete(plugin) }
115
115
  klass.unload
116
+
117
+ # Every file we load ends up in $". Require checks there, and if it's there,
118
+ # it doesn't reload the file. So to force tthe removal of the plugin,
119
+ # we remove the class from the object space, and from the array
120
+ @plugins_path.each do |p|
121
+ file = File.expand_path(File.join(p, "#{plugin.downcase}.rb"))
122
+ $".delete file
123
+ end
124
+
125
+ Object.send :remove_const, klass.name if klass
116
126
  end
117
127
  end
118
128
  end
@@ -10,11 +10,13 @@ module Flexo
10
10
  attr_reader :thread
11
11
  attr_reader :server
12
12
  attr_reader :nickname
13
+ attr_reader :welcomed
13
14
 
14
15
  def initialize
15
16
  @manager = Flexo::Manager.instance
16
17
  @socket = nil
17
18
  @server = nil
19
+ @welcomed = false
18
20
  end
19
21
 
20
22
  def setup
@@ -126,19 +128,27 @@ module Flexo
126
128
 
127
129
  # First, we add a handler to fix things
128
130
  # if our nickname is taken
129
- nicktaken = @manager.dispatcher.subscribe(Flexo::Events::ReplyEvent) do |event|
130
- if event.numeric == 433
131
- nick = config['core.nick'].shift
132
- quote "NICK #{nick}"
133
- @manager.logger.info("Nickname taken, trying #{nick}")
134
- @manager.nickname = nick
135
- end
131
+ nicktaken = @manager.dispatcher.subscribe(:ERR_NICKNAMEINUSE) do
132
+ nick = config['core.nick'].shift
133
+ quote "NICK #{nick}"
134
+ @manager.logger.info("Nickname taken, trying #{nick}")
135
+ @manager.nickname = nick
136
136
  end
137
137
 
138
138
  nick = config['core.nick'].shift
139
139
  @manager.sender.nick nick
140
140
  @manager.sender.user config['core.username'], 0, config['core.realname']
141
- @manager.nickname = nick
141
+
142
+ @manager.thread do
143
+ @manager.dispatcher.await(:RPL_WELCOME, :timeout => 30) do |reply|
144
+ @manager.mutex do
145
+ @manager.nickname = nick
146
+ @manager.logger.debug "Welcomed!"
147
+ @welcomed = true
148
+ end
149
+ @manager.dispatcher.unsubscribe(nicktaken)
150
+ end
151
+ end
142
152
  end
143
153
 
144
154
  # Disconnects from the server
@@ -22,10 +22,12 @@ module Flexo
22
22
  @default_level = 0
23
23
 
24
24
  add_trigger(/^user register ([a-zA-Z][a-zA-Z0-9_-]*) (\S+)$/, &method(:cmd_register))
25
- add_trigger(/^user addmask ([a-zA-Z][a-zA-Z0-9_-]*) (\S+)$/, &method(:cmd_addmask))
25
+ add_trigger(/^user mask add ([a-zA-Z][a-zA-Z0-9_-]*) (\S+)$/, &method(:cmd_addmask))
26
26
 
27
27
  add_restricted_trigger(/^user change ([a-zA-Z][a-zA-Z0-9_-]*) (\d{1,3})$/, :level => 256, &method(:cmd_changelevel))
28
28
  add_restricted_trigger(/^user remove ([a-zA-Z][a-zA-Z0-9_-]*)$/, :level => 256, &method(:cmd_remove))
29
+ add_restricted_trigger(/^user forceregister ([a-zA-Z][a-zA-Z0-9_-]*) (\S+)$/, :level => 256, &method(:cmd_admin_register))
30
+ add_restricted_trigger(/^user mask forceadd ([a-zA-Z][a-zA-Z0-9_-]*) ([a-zA-Z][a-zA-Z0-9_-]*) (\S+)$/, :level => 256, &method(:cmd_admin_addmask))
29
31
  add_trigger(/^user lookup ([a-zA-Z][a-zA-Z0-9_-]*)$/, &method(:cmd_lookup))
30
32
 
31
33
  @db = pstore_open("#{@manager.config.path}/user.db")
@@ -148,7 +150,7 @@ module Flexo
148
150
  tmpuser = {
149
151
  :username => user,
150
152
  :password => Digest::MD5.hexdigest(pass).to_s,
151
- :hostmasks => [[nick, host]],
153
+ :hostmasks => nick != nil ? [[nick, host]] : [],
152
154
  :level => level.to_i
153
155
  }
154
156
 
@@ -164,6 +166,19 @@ module Flexo
164
166
  end
165
167
  end
166
168
 
169
+ # Triggered when a superuser registers another user
170
+ def cmd_admin_register(privmsg, username, password)
171
+ @manager.logger.debug "AuthPlugin: Going to register #{username} (admin)"
172
+ p = privmsg
173
+ return notify_cannot_register_in_public(p) if privmsg.to_channel?
174
+ return notify_username_taken(p) if username_exists?(username)
175
+
176
+ register(username, password, nil, nil, @default_level.to_i)
177
+
178
+ privmsg.reply("Successfully registered #{username}", false)
179
+ privmsg.reply("No hostmask has been added for that user", false)
180
+ end
181
+
167
182
  # Triggered when a user tries to register via a privmsg
168
183
  def cmd_register(privmsg, username, password)
169
184
  @manager.logger.debug "AuthPlugin: Going to register #{username}"
@@ -180,6 +195,17 @@ module Flexo
180
195
  privmsg.reply("You have been added as a master!", false) if master
181
196
  end
182
197
 
198
+ # Triggered when a superuser adds a hostmask to a user
199
+ def cmd_admin_addmask(privmsg, username, nick, mask)
200
+ @manager.logger.debug "AuthPlugin: Adding a mask to #{username} (admin)"
201
+ p = privmsg
202
+ return notify_incorrect_information(p) if (!username_exists?(username))
203
+ return notify_hostmask_taken(p) if hostmask_exists?(nick, mask)
204
+
205
+ addmask(username, nick, mask)
206
+ privmsg.reply "Successfully added the new mask to #{username}"
207
+ end
208
+
183
209
  # Triggered when a user wants to add a new hostmask to themselves
184
210
  def cmd_addmask(privmsg, username, password)
185
211
  @manager.logger.debug "AuthPlugin: Adding a mask to #{username}"
@@ -224,13 +250,21 @@ module Flexo
224
250
  return notify_user_not_found(privmsg)
225
251
  end
226
252
 
227
- level = 0
253
+ user = nil
228
254
 
229
255
  @db.transaction do |pstore|
230
- level = pstore[:users][username.downcase][:level]
256
+ user = pstore[:users][username.downcase]
231
257
  end
232
258
 
233
- msg(privmsg, "#{username} has a level of #{level.to_s}")
259
+ privmsg.reply "#{username} has a level of #{user[:level].to_s}"
260
+
261
+ srcuser = get_user_from_hostmask(privmsg.sender, privmsg.data.hostmask.hostname)
262
+ if(srcuser && srcuser[:level] > 1)
263
+ privmsg.reply "Registered nick/hostmask-combinations:"
264
+ user[:hostmasks].each do |nick,host|
265
+ privmsg.reply " #{nick}@#{host}"
266
+ end
267
+ end
234
268
  end
235
269
 
236
270
  # Convenience function for errors
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: PerfectlyNormal-Flexo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Per Christian B. Viken
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-10-19 00:00:00 -07:00
12
+ date: 2008-12-25 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -64,7 +64,7 @@ files:
64
64
  - plugins/dbus.rb
65
65
  - plugins/svnlookup.rb
66
66
  has_rdoc: true
67
- homepage: http://eastblue.org/dev/flexo/
67
+ homepage: http://eastblue.org/projects/flexo/
68
68
  post_install_message:
69
69
  rdoc_options: []
70
70