mod_spox 0.2.0 → 0.3.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.
Files changed (145) hide show
  1. data/CHANGELOG +31 -1
  2. data/LICENSE +674 -0
  3. data/README.rdoc +73 -0
  4. data/bin/mod_spox +28 -28
  5. data/data/mod_spox/extras/AOLSpeak.rb +2 -3
  6. data/data/mod_spox/extras/AutoKick.rb +10 -23
  7. data/data/mod_spox/extras/AutoMode.rb +12 -23
  8. data/data/mod_spox/extras/Bash.rb +55 -0
  9. data/data/mod_spox/extras/Bouncer.rb +85 -57
  10. data/data/mod_spox/extras/Bullshit.rb +1 -1
  11. data/data/mod_spox/extras/Bytes.rb +1 -2
  12. data/data/mod_spox/extras/Confess.rb +27 -29
  13. data/data/mod_spox/extras/DCC.rb +11 -20
  14. data/data/mod_spox/extras/DevWatch.rb +21 -23
  15. data/data/mod_spox/extras/DownForEveryoneOrJustMe.rb +47 -0
  16. data/data/mod_spox/extras/EightBall.rb +1 -1
  17. data/data/mod_spox/extras/FML.rb +35 -0
  18. data/data/mod_spox/extras/Headers.rb +31 -50
  19. data/data/mod_spox/extras/Karma.rb +81 -29
  20. data/data/mod_spox/extras/Logger.rb +2 -2
  21. data/data/mod_spox/extras/LolSpeak.rb +1 -2
  22. data/data/mod_spox/extras/PhpCli.rb +138 -8
  23. data/data/mod_spox/extras/PhpFuncLookup.rb +20 -23
  24. data/data/mod_spox/extras/Pinger.rb +1 -1
  25. data/data/mod_spox/extras/Quotes.rb +8 -10
  26. data/data/mod_spox/extras/RegexTracker.rb +2 -4
  27. data/data/mod_spox/extras/Roulette.rb +20 -27
  28. data/data/mod_spox/extras/RubyCli.rb +93 -0
  29. data/data/mod_spox/extras/Search.rb +17 -3
  30. data/data/mod_spox/extras/Seen.rb +150 -0
  31. data/data/mod_spox/extras/SlashdotHeadlineGenerator.rb +500 -0
  32. data/data/mod_spox/extras/Talk.rb +2 -4
  33. data/data/mod_spox/extras/Topten.rb +10 -12
  34. data/data/mod_spox/extras/TracTicket.rb +3 -5
  35. data/data/mod_spox/extras/Translate.rb +20 -22
  36. data/data/mod_spox/extras/Twitter.rb +118 -33
  37. data/data/mod_spox/extras/UrbanDictionary.rb +8 -17
  38. data/data/mod_spox/extras/Weather.rb +1 -2
  39. data/data/mod_spox/plugins/Authenticator.rb +93 -98
  40. data/data/mod_spox/plugins/Banner.rb +26 -56
  41. data/data/mod_spox/plugins/Helper.rb +5 -6
  42. data/data/mod_spox/plugins/Initializer.rb +4 -14
  43. data/data/mod_spox/plugins/Joiner.rb +1 -1
  44. data/data/mod_spox/plugins/Nicker.rb +13 -0
  45. data/data/mod_spox/plugins/Parter.rb +2 -2
  46. data/data/mod_spox/plugins/Permissions.rb +60 -0
  47. data/data/mod_spox/plugins/PluginLoader.rb +7 -12
  48. data/data/mod_spox/plugins/Ponger.rb +51 -0
  49. data/data/mod_spox/plugins/Quitter.rb +1 -2
  50. data/data/mod_spox/plugins/Servers.rb +57 -0
  51. data/data/mod_spox/plugins/Status.rb +3 -2
  52. data/data/mod_spox/plugins/Triggers.rb +9 -9
  53. data/lib/mod_spox/Bot.rb +109 -33
  54. data/lib/mod_spox/BotConfig.rb +2 -2
  55. data/lib/mod_spox/ConfigurationWizard.rb +12 -12
  56. data/lib/mod_spox/Database.rb +1 -4
  57. data/lib/mod_spox/Exceptions.rb +26 -0
  58. data/lib/mod_spox/Helpers.rb +29 -68
  59. data/lib/mod_spox/Loader.rb +23 -24
  60. data/lib/mod_spox/Logger.rb +19 -17
  61. data/lib/mod_spox/MessageFactory.rb +50 -24
  62. data/lib/mod_spox/Pipeline.rb +21 -7
  63. data/lib/mod_spox/Plugin.rb +27 -3
  64. data/lib/mod_spox/PluginManager.rb +28 -15
  65. data/lib/mod_spox/PriorityQueue.rb +69 -0
  66. data/lib/mod_spox/Socket.rb +93 -51
  67. data/lib/mod_spox/Sockets.rb +76 -63
  68. data/lib/mod_spox/Timer.rb +21 -141
  69. data/lib/mod_spox/Version.rb +14 -0
  70. data/lib/mod_spox/handlers/BadNick.rb +1 -1
  71. data/lib/mod_spox/handlers/Bounce.rb +5 -5
  72. data/lib/mod_spox/handlers/Created.rb +13 -5
  73. data/lib/mod_spox/handlers/Handler.rb +12 -3
  74. data/lib/mod_spox/handlers/Invite.rb +14 -8
  75. data/lib/mod_spox/handlers/Join.rb +24 -20
  76. data/lib/mod_spox/handlers/Kick.rb +22 -13
  77. data/lib/mod_spox/handlers/Mode.rb +42 -36
  78. data/lib/mod_spox/handlers/Motd.rb +4 -0
  79. data/lib/mod_spox/handlers/Names.rb +66 -39
  80. data/lib/mod_spox/handlers/Nick.rb +20 -14
  81. data/lib/mod_spox/handlers/Part.rb +25 -8
  82. data/lib/mod_spox/handlers/Ping.rb +11 -5
  83. data/lib/mod_spox/handlers/Pong.rb +9 -5
  84. data/lib/mod_spox/handlers/Privmsg.rb +25 -17
  85. data/lib/mod_spox/handlers/Quit.rb +13 -8
  86. data/lib/mod_spox/handlers/Topic.rb +4 -0
  87. data/lib/mod_spox/handlers/Welcome.rb +16 -24
  88. data/lib/mod_spox/handlers/Who.rb +64 -48
  89. data/lib/mod_spox/handlers/Whois.rb +92 -60
  90. data/lib/mod_spox/messages/incoming/Nick.rb +2 -2
  91. data/lib/mod_spox/messages/incoming/Privmsg.rb +1 -1
  92. data/lib/mod_spox/messages/incoming/Whois.rb +1 -0
  93. data/lib/mod_spox/messages/internal/EstablishConnection.rb +1 -1
  94. data/lib/mod_spox/messages/internal/PluginsReady.rb +10 -0
  95. data/lib/mod_spox/messages/internal/QueueSocket.rb +8 -0
  96. data/lib/mod_spox/messages/internal/Reconnect.rb +8 -0
  97. data/lib/mod_spox/messages/internal/UnqueueSocket.rb +8 -0
  98. data/lib/mod_spox/migrations/002_persistent_sigs.rb +14 -0
  99. data/lib/mod_spox/migrations/003_auth_restructure.rb +31 -0
  100. data/lib/mod_spox/migrations/004_mode_index_fix.rb +18 -0
  101. data/lib/mod_spox/migrations/005_nick_mode_nopark.rb +18 -0
  102. data/lib/mod_spox/models/Auth.rb +16 -46
  103. data/lib/mod_spox/models/AuthMask.rb +13 -0
  104. data/lib/mod_spox/models/Channel.rb +46 -27
  105. data/lib/mod_spox/models/Config.rb +10 -19
  106. data/lib/mod_spox/models/Group.rb +20 -8
  107. data/lib/mod_spox/models/Models.rb +1 -1
  108. data/lib/mod_spox/models/Nick.rb +105 -113
  109. data/lib/mod_spox/models/NickMode.rb +23 -9
  110. data/lib/mod_spox/models/Server.rb +12 -1
  111. data/lib/mod_spox/models/Setting.rb +12 -16
  112. data/lib/mod_spox/models/Signature.rb +28 -8
  113. data/tests/BotHolder.rb +24 -0
  114. data/tests/handlers/tc_BadNick.rb +21 -0
  115. data/tests/handlers/tc_Created.rb +24 -0
  116. data/tests/handlers/tc_Invite.rb +50 -0
  117. data/tests/handlers/tc_Join.rb +33 -0
  118. data/tests/handlers/tc_Kick.rb +32 -0
  119. data/tests/handlers/tc_Mode.rb +85 -0
  120. data/tests/handlers/tc_Names.rb +35 -0
  121. data/tests/handlers/tc_Nick.rb +55 -0
  122. data/tests/handlers/tc_Part.rb +44 -0
  123. data/tests/handlers/tc_Ping.rb +40 -0
  124. data/tests/handlers/tc_Pong.rb +28 -0
  125. data/tests/handlers/tc_Privmsg.rb +85 -0
  126. data/tests/handlers/tc_Quit.rb +40 -0
  127. data/tests/handlers/tc_Who.rb +50 -0
  128. data/tests/handlers/tc_Whois.rb +61 -0
  129. data/tests/models/tc_Auth.rb +34 -0
  130. data/tests/models/tc_Channel.rb +52 -0
  131. data/tests/models/tc_Config.rb +19 -0
  132. data/tests/models/tc_Nick.rb +142 -0
  133. data/tests/models/tc_NickMode.rb +40 -0
  134. data/tests/models/tc_Setting.rb +21 -0
  135. data/tests/models/tc_Signature.rb +14 -0
  136. data/tests/run_tests.rb +4 -0
  137. metadata +284 -212
  138. data/README +0 -36
  139. data/lib/mod_spox/Cache.rb +0 -57
  140. data/lib/mod_spox/Monitors.rb +0 -84
  141. data/lib/mod_spox/Pool.rb +0 -164
  142. data/lib/mod_spox/models/AuthGroup.rb +0 -16
  143. data/lib/mod_spox/models/ChannelMode.rb +0 -14
  144. data/lib/mod_spox/models/NickChannel.rb +0 -45
  145. data/lib/mod_spox/models/NickGroup.rb +0 -16
@@ -20,11 +20,11 @@ module ModSpox
20
20
  # :userconfigpath => path to the user configuration file
21
21
  def BotConfig.populate(createdir=true)
22
22
  gemname, gem = Gem.source_index.find{|name, spec|
23
- spec.name == 'mod_spox' && spec.version.version = $BOTVERSION
23
+ spec.name == 'mod_spox' && spec.version.version = ModSpox.botversion
24
24
  }
25
25
  if(gem)
26
26
  p = gem.full_gem_path
27
- up = $MOD_SPOX_PATH.nil? ? Etc.getpwnam(Etc.getlogin).dir : $MOD_SPOX_PATH
27
+ up = ModSpox.mod_spox_path.nil? ? Etc.getpwnam(Etc.getlogin).dir : ModSpox.mod_spox.path
28
28
  @@config = {:basepath => p,
29
29
  :libpath => "#{p}/lib/mod_spox",
30
30
  :datapath => "#{p}/data/mod_spox",
@@ -44,7 +44,7 @@ module ModSpox
44
44
  config[:memcache] = get_input('Use memcache (EXPERIMENTAL): ', '(yes|no)', 'no')
45
45
  valid_connection = false
46
46
  until valid_connection do
47
- config[:db_adapter] = get_input('Database type (pgsql): ', '(pgsql)', 'pgsql')
47
+ config[:db_adapter] = get_input('Database type (pgsql|sqlite|mysql): ', '(pgsql|sqlite|mysql)', 'sqlite')
48
48
  unless(config[:db_adapter] == 'sqlite')
49
49
  config[:db_username] = get_input('Database username: ', '.+', 'mod_spox')
50
50
  config[:db_password] = get_input('Database password: ', '.*', nil)
@@ -63,8 +63,7 @@ module ModSpox
63
63
  rescue Object => boom
64
64
  puts 'Failed'
65
65
  puts 'Error: Unexpected error encountered.'
66
- puts "Info: #{boom.class} #{boom}\n#{boom.backtrace.join("\n")}"
67
- exit 1
66
+ puts "Info: #{boom}"
68
67
  ensure
69
68
  $stdout.flush
70
69
  end
@@ -76,7 +75,7 @@ module ModSpox
76
75
  puts 'mod_spox is now configured and ready for use'
77
76
  rescue Object => boom
78
77
  puts 'Failed'
79
- puts "Error: #{boom}\n#{boom.backtrace.join("\n")}"
78
+ puts "Error: #{boom}"
80
79
  puts 'Please try running the configuration again'
81
80
  end
82
81
  end
@@ -89,11 +88,11 @@ module ModSpox
89
88
 
90
89
  def test_connection(type, username=nil, password=nil, host=nil, name=nil)
91
90
  case type
92
- # when 'mysql'
93
- # c = Sequel.mysql(name, :user => username, :password => password, :host => host)
94
- # c.test_connection
91
+ when 'mysql'
92
+ c = Sequel.mysql(name, :user => username, :password => password, :host => host)
93
+ c.test_connection
95
94
  when 'pgsql'
96
- c = Sequel.connect("#{$JDBC ? 'jdbc:' : ''}postgres://#{username}:#{password}@#{host}/#{name}")
95
+ c = Sequel.connect("#{ModSpox.jdbc ? 'jdbc:' : ''}postgres://#{username}:#{password}@#{host}/#{name}")
97
96
  c.test_connection
98
97
  when 'sqlite'
99
98
  return true
@@ -107,7 +106,7 @@ module ModSpox
107
106
  config[key] = value if key.to_s =~ /^(db|memcache)/
108
107
  end
109
108
  config.write_configuration
110
- initialize_bot
109
+ ModSpox.initialize_bot
111
110
  require 'mod_spox/models/Models'
112
111
  require 'mod_spox/Helpers'
113
112
  Sequel::Migrator.apply(Database.db, BotConfig[:libpath] + '/migrations')
@@ -121,11 +120,12 @@ module ModSpox
121
120
  s = Models::Server.find_or_create(:host => uconfig[:irc_server], :port => uconfig[:irc_port])
122
121
  n = Models::Nick.find_or_create(:nick => uconfig[:admin_nick])
123
122
  a = Models::Auth.find_or_create(:nick_id => n.pk)
124
- a.group = Models::Group.find_or_create(:name => 'admin')
123
+ g = Models::Group.find_or_create(:name => 'admin')
124
+ a.add_group(g)
125
125
  a.password = uconfig[:admin_password]
126
126
  a.save
127
127
  t = Models::Trigger.find_or_create(:trigger => uconfig[:trigger])
128
- t.update_with_params(:active => true)
128
+ t.active = true
129
129
  t.save
130
130
  end
131
131
 
@@ -177,4 +177,4 @@ module ModSpox
177
177
 
178
178
  end
179
179
 
180
- end
180
+ end
@@ -30,10 +30,7 @@ module ModSpox
30
30
  end
31
31
 
32
32
  def Database.reset_connections
33
- Logger.warn('Resetting database connections. Any active connections are being closed.')
34
- Database.db.pool.allocated.each_pair do |thread, connection|
35
- thread.kill
36
- end
33
+ @@db.disconnect
37
34
  end
38
35
 
39
36
  def Database.reconnect
@@ -30,6 +30,32 @@ module ModSpox
30
30
 
31
31
  class TimerInUse < BotException
32
32
  end
33
+
34
+ class EmptyQueue < BotException
35
+ end
36
+
37
+ class Disconnected < BotException
38
+ end
39
+
40
+ class NotInChannel < BotException
41
+ attr_reader :channel
42
+ def initialize(channel)
43
+ @channel = channel
44
+ end
45
+ def to_s
46
+ "Bot is not currently in channel: #{@channel}"
47
+ end
48
+ end
49
+
50
+ class QuietChannel < BotException
51
+ attr_reader :channel
52
+ def initialize(channel)
53
+ @channel = channel
54
+ end
55
+ def to_s
56
+ "Bot is not allowed to speak in channel: #{@channel}"
57
+ end
58
+ end
33
59
 
34
60
  end
35
61
  end
@@ -3,7 +3,7 @@
3
3
  'mod_spox/models/Nick',
4
4
  'mod_spox/models/Channel',
5
5
  'mod_spox/models/Server',
6
- 'mod_spox/Cache',
6
+ 'mod_spox/models/Models',
7
7
  'mod_spox/Logger'].each{|f|require f}
8
8
 
9
9
  module ModSpox
@@ -33,20 +33,20 @@ module ModSpox
33
33
  # Converts bytes into easy human readable form
34
34
  # O(1) version by Ryan "pizza_milkshake" Flynn
35
35
  Suff = [
36
- "", # 1000^0
37
- "Kilo", # 1000^1
38
- "Mega", # 1000^2
39
- "Giga", # 1000^3
40
- "Tera", # 1000^4
41
- "Peta", # 1000^5
42
- "Exa", # 1000^6
43
- "Zetta", # 1000^7
44
- "Yotta" # 1000^8
36
+ "", # 1024^0
37
+ "Kilo", # 1024^1
38
+ "Mega", # 1024^2
39
+ "Giga", # 1024^3
40
+ "Tera", # 1024^4
41
+ "Peta", # 1024^5
42
+ "Exa", # 1024^6
43
+ "Zetta", # 1024^7
44
+ "Yotta" # 1024^8
45
45
  ]
46
46
  def Helpers.format_size(bytes)
47
- mag = (Math.log(bytes) / Math.log(1000)).floor
47
+ mag = (Math.log(bytes) / Math.log(1024)).floor
48
48
  mag = [ Suff.length - 1, mag ].min
49
- val = bytes.to_f / (1000 ** mag)
49
+ val = bytes.to_f / (1024 ** mag)
50
50
  "%7.3f %sbyte%s" % [ val, Suff[mag], val == 1 ? "" : "s" ]
51
51
  end
52
52
 
@@ -87,68 +87,29 @@ module ModSpox
87
87
  # or channel name. If the string given does not match the required
88
88
  # pattern for a channel or nick, the string is returned.
89
89
  def Helpers.find_model(string, create=true)
90
- Helpers.initialize_caches
90
+ result = nil
91
91
  if(string =~ /^[A-Za-z\|\\\{\}\[\]\^\`~\_\-]+[A-Za-z0-9\|\\\{\}\[\]\^\`~\_\-]*$/)
92
- nick = nil
93
- if(@@nick_cache.has_key?(string.downcase.to_sym))
94
- begin
95
- nick = Models::Nick[@@nick_cache[string.downcase.to_sym]]
96
- if(nick.nick.downcase != string.downcase)
97
- Logger.warn("Nick returned from cache invalid. Expecting #{string} but got #{nick.nick}")
98
- nick = nil
99
- end
100
- rescue Object => boom
101
- Logger.info("Failed to grab cached nick: #{boom}")
102
- end
103
- end
104
- unless(nick)
105
- begin
106
- nick = Models::Nick.locate(string, create)
107
- if(nick.nil?)
108
- Database.reconnect
109
- return string
110
- end
111
- rescue Object => boom
112
- Logger.warn("Caught an error. Assuming the database barfed: #{boom}")
113
- Database.reconnect
114
- end
115
- @@nick_cache[string.downcase.to_sym] = nick.pk if nick.is_a?(Models::Nick)
116
- Logger.info('Nick was retrieved from database')
117
- end
118
- return nick
119
- elsif(string =~ /^[&#+!]/)
120
- if(@@channel_cache.has_key?(string.downcase.to_sym))
121
- begin
122
- channel = Models::Channel[@@channel_cache[string.downcase.to_sym]]
123
- if(string.downcase != channel.name.downcase)
124
- Logger.warn("Channel returned from cache invalid. Expecting #{string} but got #{channel.name}")
125
- channel = nil
126
- end
127
- rescue Object => boom
128
- Logger.info("Failed to grab cached channel: #{boom}")
129
- end
130
- end
131
- unless(channel)
132
- channel = Models::Channel.locate(string, create)
133
- if(channel.nil?)
134
- Database.reconnect
135
- return string
136
- end
137
- @@channel_cache[string.downcase.to_sym] = channel.pk if channel.is_a?(Models::Channel)
138
- Logger.info('Channel was retrieved from database')
139
- end
140
- return channel
141
- elsif(model = Models::Server.filter(:host => string, :connected => true).first)
142
- return model
92
+ result = Models::Nick.find_or_create(:nick => string.downcase)
93
+ elsif(['&', '#', '+', '!'].include?(string[0]))
94
+ result = Models::Channel.find_or_create(:name => string.downcase)
95
+ elsif(Models::Server.filter(:host => string, :connected => true).count > 0)
96
+ result = Models::Server.filter(:host => string, :connected => true).first
143
97
  else
144
98
  Logger.warn("Failed to match string to model: #{string} -> No match")
145
- return string
146
99
  end
100
+ return result
147
101
  end
148
102
 
149
- def Helpers.initialize_caches
150
- @@nick_cache = Cache.new(20) unless Helpers.class_variable_defined?(:@@nick_cache)
151
- @@channel_cache = Cache.new(5) unless Helpers.class_variable_defined?(:@@channel_cache)
103
+ # string:: string to convert
104
+ # Converts HTML entities found in a string
105
+ def Helpers.convert_entities(string)
106
+ begin
107
+ require 'htmlentities'
108
+ @@coder = HTMLEntities.new unless Helpers.class_variable_defined?(:@@coder)
109
+ return @@coder.decode(string)
110
+ rescue Object
111
+ return string
112
+ end
152
113
  end
153
114
  end
154
115
  end
@@ -7,13 +7,13 @@
7
7
  module ModSpox
8
8
 
9
9
  # Loads all files needed by the bot
10
- def initialize_bot
11
- setup_adapter
10
+ def self.initialize_bot(db=nil)
11
+ setup_adapter(db)
12
12
  check_upgrade
13
13
  end
14
14
 
15
15
  # Setup the DataMapper adapter
16
- def setup_adapter
16
+ def self.setup_adapter(db=nil)
17
17
  memcache = false
18
18
  config = BaseConfig.new(BotConfig[:userconfigpath])
19
19
  if(config[:memcache] == 'on')
@@ -26,36 +26,35 @@ module ModSpox
26
26
  # do nothing #
27
27
  end
28
28
  end
29
- case config[:db_adapter]
30
- when 'mysql'
31
- Database.db = Sequel.mysql(config[:db_database], :user => config[:db_username],
32
- :password => config[:db_password], :host => config[:db_host], :max_connections => 20)
33
- Database.type = :mysql
34
- when 'pgsql'
35
- Database.db = Sequel.connect("#{$JDBC ? 'jdbc:' : ''}postgres://#{config[:db_username]}:#{config[:db_password]}@#{config[:db_host]}/#{config[:db_database]}")
36
- Database.type = :pgsql
37
- when 'sqlite'
38
- Database.db = Sequel.sqlite("#{BotConfig[:userpath]}/mod_spox.db")
39
- Database.type = :sqlite
29
+ unless(db.nil?)
30
+ Database.db = db
31
+ else
32
+ case config[:db_adapter]
33
+ when 'mysql'
34
+ Database.db = Sequel.mysql(config[:db_database], :user => config[:db_username],
35
+ :password => config[:db_password], :host => config[:db_host], :max_connections => 20)
36
+ Database.type = :mysql
37
+ when 'pgsql'
38
+ Database.db = Sequel.connect("#{ModSpox.jdbc ? 'jdbc:' : ''}postgres://#{config[:db_username]}:#{config[:db_password]}@#{config[:db_host]}/#{config[:db_database]}")
39
+ Database.type = :pgsql
40
+ when 'sqlite'
41
+ Database.db = Sequel.sqlite("#{BotConfig[:userpath]}/mod_spox.db", :pool_timeout => 20, :timeout => 5000)
42
+ Database.type = :sqlite
43
+ end
40
44
  end
41
45
  end
42
46
 
43
47
  # check if the bot has been upgraded
44
- def check_upgrade
48
+ def self.check_upgrade
49
+ Sequel::Migrator.apply(Database.db, BotConfig[:libpath] + '/migrations')
45
50
  config = BaseConfig.new(BotConfig[:userconfigpath])
46
51
  config[:plugin_upgrade] = 'no'
47
52
  begin
48
- do_upgrade(config) if config[:last_version] != $BOTVERSION
53
+ config[:plugin_upgrade] = 'yes' if config[:last_version] != ModSpox.botversion
49
54
  rescue Exceptions::UnknownKey => boom
50
- do_upgrade(config)
55
+ config[:plugin_upgrade] = 'yes'
51
56
  end
52
- config[:last_version] = $BOTVERSION
53
- end
54
-
55
- # perform upgrade tasks
56
- def do_upgrade(config)
57
- Sequel::Migrator.apply(Database.db, BotConfig[:libpath] + '/migrations')
58
- config[:plugin_upgrade] = 'yes'
57
+ config[:last_version] = ModSpox.botversion
59
58
  end
60
59
 
61
60
  end
@@ -3,32 +3,34 @@ module ModSpox
3
3
 
4
4
  class Logger
5
5
 
6
- def Logger.initialize(output=nil, level=:fatal)
7
- if(output.nil?)
8
- @@log = nil
9
- else
10
- levels = {:info => Object::Logger::INFO, :warn => Object::Logger::WARN, :fatal => Object::Logger::FATAL}
11
- @@log = Object::Logger.new(output)
12
- @@log.level = levels.has_key?(level) ? levels[level] : Object::Logger::WARN
13
- end
6
+ def Logger.initialize(logger, level)
7
+ l = {:info => ::Logger::INFO, :error => ::Logger::ERROR, :warn => ::Logger::WARN, :fatal => ::Logger::FATAL}
8
+ @@log = logger.is_a?(::Logger) ? logger : nil
9
+ @@log.level = l[level]
14
10
  end
15
11
 
16
12
  def Logger.warn(s)
17
- unless @@log.nil?
18
- Pool << lambda{@@log.warn(s)}
19
- end
13
+ @@log.warn(s) if Logger.log?
20
14
  end
21
15
 
22
16
  def Logger.info(s)
23
- unless @@log.nil?
24
- Pool << lambda{@@log.info(s)}
25
- end
17
+ @@log.info(s) if Logger.log?
26
18
  end
27
19
 
28
20
  def Logger.fatal(s)
29
- unless @@log.nil?
30
- Pool << lambda{@@log.fatal(s)}
31
- end
21
+ @@log.fatal(s) if Logger.log?
22
+ end
23
+
24
+ def Logger.error(s)
25
+ @@log.error(s) if Logger.log?
26
+ end
27
+
28
+ def Logger.log?
29
+ Logger.class_variable_defined?(:@@log)
30
+ end
31
+
32
+ def Logger.raw
33
+ Logger.log? ? @@log : nil
32
34
  end
33
35
 
34
36
  end
@@ -1,18 +1,21 @@
1
1
  ['mod_spox/handlers/Handler',
2
2
  'mod_spox/Logger',
3
- 'mod_spox/Pipeline',
4
- 'mod_spox/Pool'].each{|f|require f}
3
+ 'mod_spox/Pipeline'].each{|f|require f}
5
4
 
6
5
  module ModSpox
7
6
 
8
7
  class MessageFactory
9
8
 
9
+ # access to handlers. (only really needed for testing)
10
+ attr_reader :handlers
11
+
10
12
  # pipeline:: Message pipeline
11
13
  # Create a new MessageFactory
12
- def initialize(pipeline)
14
+ def initialize(pipeline, pool)
13
15
  @pipeline = pipeline
16
+ @pool = pool
17
+ @sync_pool = ActionPool::Pool.new(1, 1, nil, 2, Logger.raw)
14
18
  @handlers = Hash.new
15
- @lock = Mutex.new
16
19
  build_handlers
17
20
  @sync = [RPL_MOTDSTART, RPL_MOTD, RPL_ENDOFMOTD, RPL_WHOREPLY, RPL_ENDOFWHO,
18
21
  RPL_NAMREPLY, RPL_ENDOFNAMES, RPL_WHOISUSER, RPL_WHOISSERVER, RPL_WHOISOPERATOR,
@@ -24,7 +27,28 @@ module ModSpox
24
27
  # be processed thus there is now wait for processing to be
25
28
  # completed.
26
29
  def <<(string)
27
- Pool << lambda{ parse_message(string) }
30
+ @pool.process{ parse_message(string) }
31
+ end
32
+
33
+ # s:: string from server
34
+ # determine type of message from server
35
+ def find_key(s)
36
+ s = s.dup
37
+ begin
38
+ key = nil
39
+ if(s[0].chr == ':')
40
+ s.slice!(0..s.index(' '))
41
+ key = s.slice!(0..s.index(' ')-1)
42
+ else
43
+ key = s.slice(0..s.index(' ')-1)
44
+ end
45
+ key.strip!
46
+ key = key.to_sym if key.to_i == 0
47
+ return key
48
+ rescue Object
49
+ Logger.info("Failed to find key for message: #{s}")
50
+ raise Exceptions::UnknownKey.new
51
+ end
28
52
  end
29
53
 
30
54
  private
@@ -55,29 +79,31 @@ module ModSpox
55
79
  def parse_message(message)
56
80
  Logger.info("Processing message: #{message}")
57
81
  begin
58
- if(message =~ /^:\S+ (\S+)/ || message =~ /^([A-Za-z0-9]+)\s/)
59
- key = $1
60
- key = key.to_sym unless key[0].chr =~ /\d/
61
- if(@handlers.has_key?(key))
62
- Logger.info("Message of type #{key} is now being handled by #{@handlers[key]}")
63
- if(@sync.include?(key))
64
- Logger.info("Message of type #{key} requires synchronized processing")
65
- Pool << lambda do
66
- @lock.synchronize do
67
- message = @handlers[key].process(message)
68
- @pipeline << message unless message.nil?
69
- end
70
- end
71
- else
72
- Pool << lambda do
73
- message = @handlers[key].process(message)
74
- @pipeline << message unless message.nil?
75
- end
82
+ key = find_key(message)
83
+ if(@handlers.has_key?(key))
84
+ Logger.info("Message of type #{key} is now being handled by #{@handlers[key]}")
85
+ if(@sync.include?(key))
86
+ Logger.info("Message of type #{key} requires synchronized processing")
87
+ @sync_pool.process do
88
+ message = @handlers[key].process(message)
89
+ @pipeline << message unless message.nil?
90
+ end
91
+ else
92
+ @pool.process do
93
+ message = @handlers[key].process(message)
94
+ @pipeline << message unless message.nil?
76
95
  end
77
96
  end
97
+ else
98
+ Logger.error("No handler was found to process message of type: #{key} Message: #{message}")
78
99
  end
79
100
  rescue Object => boom
80
- Logger.warn("Failed to parse message from server: #{boom}\n#{boom.backtrace.join("\n")}")
101
+ if(boom.class.to_s == 'SQLite3::BusyException' || boom.class.to_s == 'PGError')
102
+ Database.reset_connections
103
+ retry
104
+ else
105
+ Logger.warn("Failed to parse message from server: #{boom}\n#{boom.backtrace.join("\n")}")
106
+ end
81
107
  end
82
108
  end
83
109