PerfectlyNormal-Flexo 0.4.2 → 0.4.4

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/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