spox-mod_spox 0.3.1
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/CHANGELOG +174 -0
- data/INSTALL +15 -0
- data/LICENSE +674 -0
- data/README.rdoc +73 -0
- data/bin/mod_spox +112 -0
- data/data/mod_spox/extras/AOLSpeak.rb +257 -0
- data/data/mod_spox/extras/AutoKick.rb +152 -0
- data/data/mod_spox/extras/AutoMode.rb +122 -0
- data/data/mod_spox/extras/AutoRejoin.rb +37 -0
- data/data/mod_spox/extras/Bash.rb +55 -0
- data/data/mod_spox/extras/Bouncer.rb +220 -0
- data/data/mod_spox/extras/Bullshit.rb +19 -0
- data/data/mod_spox/extras/Bytes.rb +11 -0
- data/data/mod_spox/extras/Confess.rb +244 -0
- data/data/mod_spox/extras/DCC.rb +182 -0
- data/data/mod_spox/extras/DevWatch.rb +153 -0
- data/data/mod_spox/extras/DownForEveryoneOrJustMe.rb +47 -0
- data/data/mod_spox/extras/EightBall.rb +33 -0
- data/data/mod_spox/extras/FML.rb +35 -0
- data/data/mod_spox/extras/FloodKicker.rb +129 -0
- data/data/mod_spox/extras/Fortune.rb +76 -0
- data/data/mod_spox/extras/GoogleIt.rb +13 -0
- data/data/mod_spox/extras/Headers.rb +59 -0
- data/data/mod_spox/extras/Karma.rb +302 -0
- data/data/mod_spox/extras/Locator.rb +44 -0
- data/data/mod_spox/extras/Logger.rb +182 -0
- data/data/mod_spox/extras/LolSpeak.rb +21 -0
- data/data/mod_spox/extras/NickServ.rb +84 -0
- data/data/mod_spox/extras/PhpCli.rb +308 -0
- data/data/mod_spox/extras/PhpFuncLookup.rb +297 -0
- data/data/mod_spox/extras/Pinger.rb +11 -0
- data/data/mod_spox/extras/Quotes.rb +79 -0
- data/data/mod_spox/extras/RegexTracker.rb +158 -0
- data/data/mod_spox/extras/Roulette.rb +267 -0
- data/data/mod_spox/extras/RubyCli.rb +93 -0
- data/data/mod_spox/extras/Search.rb +49 -0
- data/data/mod_spox/extras/Seen.rb +150 -0
- data/data/mod_spox/extras/Slashdot.rb +35 -0
- data/data/mod_spox/extras/SlashdotHeadlineGenerator.rb +500 -0
- data/data/mod_spox/extras/Talk.rb +32 -0
- data/data/mod_spox/extras/Topten.rb +103 -0
- data/data/mod_spox/extras/TracTicket.rb +66 -0
- data/data/mod_spox/extras/Translate.rb +132 -0
- data/data/mod_spox/extras/Twitter.rb +458 -0
- data/data/mod_spox/extras/UrbanDictionary.rb +55 -0
- data/data/mod_spox/extras/Weather.rb +55 -0
- data/data/mod_spox/plugins/Authenticator.rb +289 -0
- data/data/mod_spox/plugins/Banner.rb +585 -0
- data/data/mod_spox/plugins/BotNick.rb +18 -0
- data/data/mod_spox/plugins/Helper.rb +49 -0
- data/data/mod_spox/plugins/Initializer.rb +35 -0
- data/data/mod_spox/plugins/Joiner.rb +23 -0
- data/data/mod_spox/plugins/Nicker.rb +14 -0
- data/data/mod_spox/plugins/Parter.rb +23 -0
- data/data/mod_spox/plugins/Permissions.rb +60 -0
- data/data/mod_spox/plugins/PluginLoader.rb +180 -0
- data/data/mod_spox/plugins/Ponger.rb +70 -0
- data/data/mod_spox/plugins/PoolConfig.rb +52 -0
- data/data/mod_spox/plugins/Quitter.rb +15 -0
- data/data/mod_spox/plugins/Servers.rb +57 -0
- data/data/mod_spox/plugins/Status.rb +31 -0
- data/data/mod_spox/plugins/Triggers.rb +85 -0
- data/lib/mod_spox/BaseConfig.rb +51 -0
- data/lib/mod_spox/Bot.rb +604 -0
- data/lib/mod_spox/BotConfig.rb +65 -0
- data/lib/mod_spox/ConfigurationWizard.rb +180 -0
- data/lib/mod_spox/Database.rb +51 -0
- data/lib/mod_spox/Exceptions.rb +84 -0
- data/lib/mod_spox/Helpers.rb +122 -0
- data/lib/mod_spox/Loader.rb +60 -0
- data/lib/mod_spox/Logger.rb +37 -0
- data/lib/mod_spox/MessageFactory.rb +112 -0
- data/lib/mod_spox/Pipeline.rb +207 -0
- data/lib/mod_spox/Plugin.rb +97 -0
- data/lib/mod_spox/PluginHolder.rb +22 -0
- data/lib/mod_spox/PluginManager.rb +257 -0
- data/lib/mod_spox/PriorityQueue.rb +69 -0
- data/lib/mod_spox/Socket.rb +201 -0
- data/lib/mod_spox/Sockets.rb +226 -0
- data/lib/mod_spox/Timer.rb +60 -0
- data/lib/mod_spox/Version.rb +14 -0
- data/lib/mod_spox/handlers/BadNick.rb +19 -0
- data/lib/mod_spox/handlers/Bounce.rb +24 -0
- data/lib/mod_spox/handlers/Created.rb +27 -0
- data/lib/mod_spox/handlers/Handler.rb +39 -0
- data/lib/mod_spox/handlers/Invite.rb +28 -0
- data/lib/mod_spox/handlers/Join.rb +38 -0
- data/lib/mod_spox/handlers/Kick.rb +36 -0
- data/lib/mod_spox/handlers/LuserChannels.rb +19 -0
- data/lib/mod_spox/handlers/LuserClient.rb +18 -0
- data/lib/mod_spox/handlers/LuserMe.rb +16 -0
- data/lib/mod_spox/handlers/LuserOp.rb +19 -0
- data/lib/mod_spox/handlers/LuserUnknown.rb +19 -0
- data/lib/mod_spox/handlers/Mode.rb +62 -0
- data/lib/mod_spox/handlers/Motd.rb +38 -0
- data/lib/mod_spox/handlers/MyInfo.rb +24 -0
- data/lib/mod_spox/handlers/Names.rb +86 -0
- data/lib/mod_spox/handlers/Nick.rb +50 -0
- data/lib/mod_spox/handlers/NickInUse.rb +19 -0
- data/lib/mod_spox/handlers/Notice.rb +35 -0
- data/lib/mod_spox/handlers/Part.rb +39 -0
- data/lib/mod_spox/handlers/Ping.rb +25 -0
- data/lib/mod_spox/handlers/Pong.rb +23 -0
- data/lib/mod_spox/handlers/Privmsg.rb +39 -0
- data/lib/mod_spox/handlers/Quit.rb +29 -0
- data/lib/mod_spox/handlers/Topic.rb +38 -0
- data/lib/mod_spox/handlers/Welcome.rb +30 -0
- data/lib/mod_spox/handlers/Who.rb +83 -0
- data/lib/mod_spox/handlers/Whois.rb +117 -0
- data/lib/mod_spox/handlers/YourHost.rb +20 -0
- data/lib/mod_spox/messages/Messages.rb +6 -0
- data/lib/mod_spox/messages/incoming/BadNick.rb +16 -0
- data/lib/mod_spox/messages/incoming/Bounce.rb +18 -0
- data/lib/mod_spox/messages/incoming/Created.rb +15 -0
- data/lib/mod_spox/messages/incoming/Invite.rb +21 -0
- data/lib/mod_spox/messages/incoming/Join.rb +19 -0
- data/lib/mod_spox/messages/incoming/Kick.rb +26 -0
- data/lib/mod_spox/messages/incoming/LuserChannels.rb +15 -0
- data/lib/mod_spox/messages/incoming/LuserClient.rb +24 -0
- data/lib/mod_spox/messages/incoming/LuserMe.rb +18 -0
- data/lib/mod_spox/messages/incoming/LuserOp.rb +15 -0
- data/lib/mod_spox/messages/incoming/LuserUnknown.rb +15 -0
- data/lib/mod_spox/messages/incoming/Message.rb +22 -0
- data/lib/mod_spox/messages/incoming/Mode.rb +42 -0
- data/lib/mod_spox/messages/incoming/Motd.rb +18 -0
- data/lib/mod_spox/messages/incoming/MyInfo.rb +24 -0
- data/lib/mod_spox/messages/incoming/Names.rb +24 -0
- data/lib/mod_spox/messages/incoming/Nick.rb +26 -0
- data/lib/mod_spox/messages/incoming/NickInUse.rb +15 -0
- data/lib/mod_spox/messages/incoming/Notice.rb +9 -0
- data/lib/mod_spox/messages/incoming/Part.rb +21 -0
- data/lib/mod_spox/messages/incoming/Ping.rb +18 -0
- data/lib/mod_spox/messages/incoming/Pong.rb +9 -0
- data/lib/mod_spox/messages/incoming/Privmsg.rb +90 -0
- data/lib/mod_spox/messages/incoming/Quit.rb +18 -0
- data/lib/mod_spox/messages/incoming/Topic.rb +21 -0
- data/lib/mod_spox/messages/incoming/TopicInfo.rb +21 -0
- data/lib/mod_spox/messages/incoming/Welcome.rb +27 -0
- data/lib/mod_spox/messages/incoming/Who.rb +18 -0
- data/lib/mod_spox/messages/incoming/Whois.rb +49 -0
- data/lib/mod_spox/messages/incoming/YourHost.rb +18 -0
- data/lib/mod_spox/messages/internal/BotInitialized.rb +11 -0
- data/lib/mod_spox/messages/internal/ChangeNick.rb +15 -0
- data/lib/mod_spox/messages/internal/Connected.rb +20 -0
- data/lib/mod_spox/messages/internal/ConnectionFailed.rb +23 -0
- data/lib/mod_spox/messages/internal/DCCListener.rb +12 -0
- data/lib/mod_spox/messages/internal/DCCRequest.rb +12 -0
- data/lib/mod_spox/messages/internal/DCCSocket.rb +19 -0
- data/lib/mod_spox/messages/internal/Disconnected.rb +8 -0
- data/lib/mod_spox/messages/internal/Disconnecting.rb +8 -0
- data/lib/mod_spox/messages/internal/EstablishConnection.rb +22 -0
- data/lib/mod_spox/messages/internal/HaltBot.rb +8 -0
- data/lib/mod_spox/messages/internal/NickRequest.rb +9 -0
- data/lib/mod_spox/messages/internal/NickResponse.rb +15 -0
- data/lib/mod_spox/messages/internal/PluginLoadRequest.rb +21 -0
- data/lib/mod_spox/messages/internal/PluginLoadResponse.rb +17 -0
- data/lib/mod_spox/messages/internal/PluginModuleRequest.rb +14 -0
- data/lib/mod_spox/messages/internal/PluginModuleResponse.rb +18 -0
- data/lib/mod_spox/messages/internal/PluginReload.rb +18 -0
- data/lib/mod_spox/messages/internal/PluginRequest.rb +18 -0
- data/lib/mod_spox/messages/internal/PluginResponse.rb +21 -0
- data/lib/mod_spox/messages/internal/PluginUnloadRequest.rb +9 -0
- data/lib/mod_spox/messages/internal/PluginUnloadResponse.rb +9 -0
- data/lib/mod_spox/messages/internal/PluginsReady.rb +10 -0
- data/lib/mod_spox/messages/internal/QueueSocket.rb +8 -0
- data/lib/mod_spox/messages/internal/Reconnect.rb +8 -0
- data/lib/mod_spox/messages/internal/Request.rb +15 -0
- data/lib/mod_spox/messages/internal/Response.rb +15 -0
- data/lib/mod_spox/messages/internal/Shutdown.rb +8 -0
- data/lib/mod_spox/messages/internal/SignaturesUpdate.rb +8 -0
- data/lib/mod_spox/messages/internal/StatusRequest.rb +10 -0
- data/lib/mod_spox/messages/internal/StatusResponse.rb +18 -0
- data/lib/mod_spox/messages/internal/TimerAdd.rb +36 -0
- data/lib/mod_spox/messages/internal/TimerClear.rb +16 -0
- data/lib/mod_spox/messages/internal/TimerRemove.rb +23 -0
- data/lib/mod_spox/messages/internal/TimerResponse.rb +34 -0
- data/lib/mod_spox/messages/internal/TriggersUpdate.rb +8 -0
- data/lib/mod_spox/messages/internal/UnqueueSocket.rb +8 -0
- data/lib/mod_spox/messages/outgoing/Admin.rb +15 -0
- data/lib/mod_spox/messages/outgoing/Away.rb +11 -0
- data/lib/mod_spox/messages/outgoing/ChannelMode.rb +25 -0
- data/lib/mod_spox/messages/outgoing/Connect.rb +24 -0
- data/lib/mod_spox/messages/outgoing/Die.rb +9 -0
- data/lib/mod_spox/messages/outgoing/Info.rb +15 -0
- data/lib/mod_spox/messages/outgoing/Invite.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Ison.rb +15 -0
- data/lib/mod_spox/messages/outgoing/Join.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Kick.rb +23 -0
- data/lib/mod_spox/messages/outgoing/Kill.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Links.rb +19 -0
- data/lib/mod_spox/messages/outgoing/List.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Lusers.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Motd.rb +16 -0
- data/lib/mod_spox/messages/outgoing/Names.rb +20 -0
- data/lib/mod_spox/messages/outgoing/Nick.rb +16 -0
- data/lib/mod_spox/messages/outgoing/Notice.rb +12 -0
- data/lib/mod_spox/messages/outgoing/Oper.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Part.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Pass.rb +16 -0
- data/lib/mod_spox/messages/outgoing/Ping.rb +11 -0
- data/lib/mod_spox/messages/outgoing/Pong.rb +17 -0
- data/lib/mod_spox/messages/outgoing/Privmsg.rb +43 -0
- data/lib/mod_spox/messages/outgoing/Quit.rb +11 -0
- data/lib/mod_spox/messages/outgoing/Raw.rb +16 -0
- data/lib/mod_spox/messages/outgoing/Rehash.rb +9 -0
- data/lib/mod_spox/messages/outgoing/Restart.rb +9 -0
- data/lib/mod_spox/messages/outgoing/ServList.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Simple.rb +12 -0
- data/lib/mod_spox/messages/outgoing/Squery.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Squit.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Stats.rb +18 -0
- data/lib/mod_spox/messages/outgoing/Summon.rb +23 -0
- data/lib/mod_spox/messages/outgoing/Time.rb +15 -0
- data/lib/mod_spox/messages/outgoing/Topic.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Trace.rb +15 -0
- data/lib/mod_spox/messages/outgoing/Unaway.rb +9 -0
- data/lib/mod_spox/messages/outgoing/User.rb +23 -0
- data/lib/mod_spox/messages/outgoing/UserHost.rb +15 -0
- data/lib/mod_spox/messages/outgoing/UserMode.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Users.rb +15 -0
- data/lib/mod_spox/messages/outgoing/Version.rb +16 -0
- data/lib/mod_spox/messages/outgoing/Who.rb +23 -0
- data/lib/mod_spox/messages/outgoing/WhoWas.rb +23 -0
- data/lib/mod_spox/messages/outgoing/Whois.rb +19 -0
- data/lib/mod_spox/migrations/001_initialize_models.rb +115 -0
- data/lib/mod_spox/migrations/002_persistent_sigs.rb +14 -0
- data/lib/mod_spox/migrations/003_auth_restructure.rb +31 -0
- data/lib/mod_spox/migrations/004_mode_index_fix.rb +18 -0
- data/lib/mod_spox/migrations/005_nick_mode_nopark.rb +18 -0
- data/lib/mod_spox/models/Auth.rb +65 -0
- data/lib/mod_spox/models/AuthMask.rb +13 -0
- data/lib/mod_spox/models/Channel.rb +89 -0
- data/lib/mod_spox/models/Config.rb +30 -0
- data/lib/mod_spox/models/Group.rb +30 -0
- data/lib/mod_spox/models/Models.rb +4 -0
- data/lib/mod_spox/models/Nick.rb +195 -0
- data/lib/mod_spox/models/NickMode.rb +32 -0
- data/lib/mod_spox/models/Server.rb +27 -0
- data/lib/mod_spox/models/Setting.rb +52 -0
- data/lib/mod_spox/models/Signature.rb +52 -0
- data/lib/mod_spox/models/Trigger.rb +9 -0
- data/lib/mod_spox/rfc2812.rb +49 -0
- data/populate_gemspec.rb +15 -0
- data/tests/BotHolder.rb +24 -0
- data/tests/handlers/tc_BadNick.rb +21 -0
- data/tests/handlers/tc_Created.rb +24 -0
- data/tests/handlers/tc_Invite.rb +50 -0
- data/tests/handlers/tc_Join.rb +33 -0
- data/tests/handlers/tc_Kick.rb +32 -0
- data/tests/handlers/tc_Mode.rb +85 -0
- data/tests/handlers/tc_Names.rb +35 -0
- data/tests/handlers/tc_Nick.rb +55 -0
- data/tests/handlers/tc_Part.rb +44 -0
- data/tests/handlers/tc_Ping.rb +40 -0
- data/tests/handlers/tc_Pong.rb +28 -0
- data/tests/handlers/tc_Privmsg.rb +85 -0
- data/tests/handlers/tc_Quit.rb +40 -0
- data/tests/handlers/tc_Who.rb +50 -0
- data/tests/handlers/tc_Whois.rb +61 -0
- data/tests/models/tc_Auth.rb +39 -0
- data/tests/models/tc_Channel.rb +52 -0
- data/tests/models/tc_Config.rb +19 -0
- data/tests/models/tc_Nick.rb +144 -0
- data/tests/models/tc_NickMode.rb +40 -0
- data/tests/models/tc_Setting.rb +21 -0
- data/tests/models/tc_Signature.rb +14 -0
- data/tests/run_tests.rb +6 -0
- metadata +362 -0
@@ -0,0 +1,180 @@
|
|
1
|
+
['etc',
|
2
|
+
'mod_spox/Database',
|
3
|
+
'mod_spox/BotConfig',
|
4
|
+
'mod_spox/BaseConfig'].each{|f|require f}
|
5
|
+
|
6
|
+
|
7
|
+
module ModSpox
|
8
|
+
|
9
|
+
class ConfigurationWizard
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@echo = nil
|
13
|
+
@config = Array.new
|
14
|
+
@config_db = Hash.new
|
15
|
+
@stuck_visible = true
|
16
|
+
begin
|
17
|
+
require 'termios'
|
18
|
+
@stuck_visible = false
|
19
|
+
rescue Object => boom
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Run the configuration wizard
|
24
|
+
def run
|
25
|
+
config = {}
|
26
|
+
puts "*********************************"
|
27
|
+
puts "* mod_spox Configuration Wizard *"
|
28
|
+
puts "*********************************"
|
29
|
+
puts ""
|
30
|
+
config[:irc_server] = get_input('IRC Server: ', '.+', nil)
|
31
|
+
config[:irc_port] = get_input('IRC Port: ', '\d+', '6667')
|
32
|
+
config[:reconnect_wait] = get_input('Reconnect wait time: ', '\d+', 10)
|
33
|
+
config[:bot_nick] = get_input('IRC Nick: ', '[a-zA-Z].*', 'mod_spox')
|
34
|
+
config[:bot_password] = get_input('IRC Nick Password (for nickserv): ', '.*', nil)
|
35
|
+
config[:bot_username] = get_input('IRC Username: ', '.+', 'mod_spox')
|
36
|
+
config[:bot_realname] = get_input('IRC Real Name: ', '.+', 'mod_spox IRC bot')
|
37
|
+
config[:socket_burst] = get_input('Socket burst rate (lines): ', '\d+', '3')
|
38
|
+
config[:socket_burst_in] = get_input('Socket burst time: ', '\d+', '2')
|
39
|
+
config[:socket_burst_delay] = get_input('Socket burst delay: ', '\d+', '2')
|
40
|
+
config[:admin_nick] = get_input('Administator nick: ', '[a-zA-Z].*', nil)
|
41
|
+
config[:admin_password] = get_input('Administrator password: ', '.+', nil)
|
42
|
+
config[:plugin_directory] = get_input('Plugin temp data driectory (bot needs write permission): ', '.+', '/tmp')
|
43
|
+
config[:trigger] = get_input('Default trigger: ', '.+', '!')
|
44
|
+
config[:memcache] = get_input('Use memcache (EXPERIMENTAL): ', '(yes|no)', 'no')
|
45
|
+
valid_connection = false
|
46
|
+
until valid_connection do
|
47
|
+
config[:db_adapter] = get_input('Database type (pgsql|sqlite|mysql): ', '(pgsql|sqlite|mysql)', 'sqlite')
|
48
|
+
unless(config[:db_adapter] == 'sqlite')
|
49
|
+
config[:db_username] = get_input('Database username: ', '.+', 'mod_spox')
|
50
|
+
config[:db_password] = get_input('Database password: ', '.*', nil)
|
51
|
+
config[:db_host] = get_input('Database host: ', '.*', '127.0.0.1')
|
52
|
+
config[:db_database] = get_input('Database name: ', '.+', 'mod_spox')
|
53
|
+
end
|
54
|
+
begin
|
55
|
+
print 'Testing database connection... '
|
56
|
+
config[:db_adapter] == 'sqlite' ? test_connection(config[:db_adapter]) : test_connection(config[:db_adapter], config[:db_username], config[:db_password], config[:db_host], config[:db_database])
|
57
|
+
puts 'OK'
|
58
|
+
valid_connection = true
|
59
|
+
rescue Sequel::DatabaseError, URI::InvalidURIError => boom
|
60
|
+
puts 'Failed'
|
61
|
+
puts 'Error: Connection to database failed'
|
62
|
+
puts "Info: #{boom}"
|
63
|
+
rescue Object => boom
|
64
|
+
puts 'Failed'
|
65
|
+
puts 'Error: Unexpected error encountered.'
|
66
|
+
puts "Info: #{boom}"
|
67
|
+
ensure
|
68
|
+
$stdout.flush
|
69
|
+
end
|
70
|
+
end
|
71
|
+
print "Storing configuration values... "
|
72
|
+
begin
|
73
|
+
save_configuration(config)
|
74
|
+
puts 'OK'
|
75
|
+
puts 'mod_spox is now configured and ready for use'
|
76
|
+
rescue Object => boom
|
77
|
+
puts 'Failed'
|
78
|
+
puts "Error: #{boom}"
|
79
|
+
puts 'Please try running the configuration again'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def update
|
84
|
+
run
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def test_connection(type, username=nil, password=nil, host=nil, name=nil)
|
90
|
+
case type
|
91
|
+
when 'mysql'
|
92
|
+
c = Sequel.mysql(name, :user => username, :password => password, :host => host)
|
93
|
+
c.test_connection
|
94
|
+
when 'pgsql'
|
95
|
+
c = Sequel.connect("#{ModSpox.jdbc ? 'jdbc:' : ''}postgres://#{username}:#{password}@#{host}/#{name}")
|
96
|
+
c.test_connection
|
97
|
+
when 'sqlite'
|
98
|
+
return true
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Save our configuration values
|
103
|
+
def save_configuration(uconfig)
|
104
|
+
config = BaseConfig.new(BotConfig[:userconfigpath])
|
105
|
+
uconfig.each_pair do |key,value|
|
106
|
+
config[key] = value if key.to_s =~ /^(db|memcache)/
|
107
|
+
end
|
108
|
+
config.write_configuration
|
109
|
+
ModSpox.initialize_bot
|
110
|
+
require 'mod_spox/models/Models'
|
111
|
+
require 'mod_spox/Helpers'
|
112
|
+
Sequel::Migrator.apply(Database.db, BotConfig[:libpath] + '/migrations')
|
113
|
+
uconfig.each_pair do |key,value|
|
114
|
+
unless key.to_s =~ /^(db|irc|admin|trigger)/
|
115
|
+
m = Models::Config.find_or_create(:name => key.to_s)
|
116
|
+
m.value = value
|
117
|
+
m.save
|
118
|
+
end
|
119
|
+
end
|
120
|
+
s = Models::Server.find_or_create(:host => uconfig[:irc_server], :port => uconfig[:irc_port])
|
121
|
+
n = Models::Nick.find_or_create(:nick => uconfig[:admin_nick])
|
122
|
+
a = Models::Auth.find_or_create(:nick_id => n.pk)
|
123
|
+
g = Models::Group.find_or_create(:name => 'admin')
|
124
|
+
a.add_group(g)
|
125
|
+
a.password = uconfig[:admin_password]
|
126
|
+
a.save
|
127
|
+
t = Models::Trigger.find_or_create(:trigger => uconfig[:trigger])
|
128
|
+
t.active = true
|
129
|
+
t.save
|
130
|
+
end
|
131
|
+
|
132
|
+
# echo:: echo user input
|
133
|
+
# Turns echoing of user input on or off
|
134
|
+
def input_echo(echo=true)
|
135
|
+
return if echo == @echo || @stuck_visible
|
136
|
+
term = Termios::getattr($stdin)
|
137
|
+
term.c_lflag |= Termios::ECHO if echo
|
138
|
+
term.c_lflag &= ~Termios::ECHO unless echo
|
139
|
+
Termios::setattr($stdin, Termios::TCSANOW, term)
|
140
|
+
@echo = echo
|
141
|
+
end
|
142
|
+
|
143
|
+
# pattern:: regex response must match
|
144
|
+
# default:: default value if response is empty
|
145
|
+
# echo:: echo user's input
|
146
|
+
# Reads users input
|
147
|
+
def read_input(pattern=nil, default=nil)
|
148
|
+
#input_echo(echo)
|
149
|
+
response = $stdin.readline
|
150
|
+
response.strip!
|
151
|
+
set = response.length > 0
|
152
|
+
unless(pattern.nil?)
|
153
|
+
response = nil unless response =~ /^#{pattern}$/
|
154
|
+
end
|
155
|
+
if(default && !set)
|
156
|
+
response = default
|
157
|
+
end
|
158
|
+
#input_echo(true) unless echo
|
159
|
+
#puts "" unless echo
|
160
|
+
return response
|
161
|
+
end
|
162
|
+
|
163
|
+
# output:: to send before user input
|
164
|
+
# regex:: pattern user input must match (^ and $ not needed. applied automatically)
|
165
|
+
# echo:: echo user's input
|
166
|
+
# default:: default value if no value is entered
|
167
|
+
def get_input(output, regex, default=nil)
|
168
|
+
response = nil
|
169
|
+
until(response) do
|
170
|
+
print output
|
171
|
+
print "[#{default}]: " unless default.nil?
|
172
|
+
$stdout.flush
|
173
|
+
response = read_input(regex, default)
|
174
|
+
end
|
175
|
+
return response
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module ModSpox
|
2
|
+
|
3
|
+
class Database
|
4
|
+
|
5
|
+
def Database.db=(database)
|
6
|
+
@@db = nil
|
7
|
+
@@db = database
|
8
|
+
end
|
9
|
+
|
10
|
+
def Database.type=(type)
|
11
|
+
@@type = nil
|
12
|
+
@@type = type
|
13
|
+
end
|
14
|
+
|
15
|
+
def Database.cache=(cache)
|
16
|
+
@@cache = nil
|
17
|
+
@@cache = cache
|
18
|
+
end
|
19
|
+
|
20
|
+
def Database.cache
|
21
|
+
return Database.class_variable_defined?(:@@cache) ? @@cache : nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def Database.type
|
25
|
+
return Database.class_variable_defined?(:@@type) ? @@type : nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def Database.db
|
29
|
+
return Database.class_variable_defined?(:@@db) ? @@db : nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def Database.reset_connections
|
33
|
+
@@db.disconnect
|
34
|
+
end
|
35
|
+
|
36
|
+
def Database.reconnect
|
37
|
+
begin
|
38
|
+
@@db.test_connection
|
39
|
+
Logger.warn('Database connection appears to be active. Closing.')
|
40
|
+
@@db.disconnect
|
41
|
+
rescue Object => boom
|
42
|
+
Logger.warn('Database connection does not appear to be active.')
|
43
|
+
ensure
|
44
|
+
Logger.warn('Reconnecting to database.')
|
45
|
+
ModSpox.setup_adapter
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module ModSpox
|
2
|
+
module Exceptions
|
3
|
+
|
4
|
+
class BotException < Exception
|
5
|
+
end
|
6
|
+
|
7
|
+
class GeneralException < Exception
|
8
|
+
attr_reader :original
|
9
|
+
def initialize(o)
|
10
|
+
@original = o
|
11
|
+
end
|
12
|
+
def to_s
|
13
|
+
@original.to_s
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class NotImplemented < BotException
|
18
|
+
end
|
19
|
+
|
20
|
+
class InvalidType < BotException
|
21
|
+
end
|
22
|
+
|
23
|
+
class InvalidValue < BotException
|
24
|
+
end
|
25
|
+
|
26
|
+
class AlreadyRunning < BotException
|
27
|
+
end
|
28
|
+
|
29
|
+
class NotRunning < BotException
|
30
|
+
end
|
31
|
+
|
32
|
+
class UnknownKey < BotException
|
33
|
+
end
|
34
|
+
|
35
|
+
class InstallationError < BotException
|
36
|
+
end
|
37
|
+
|
38
|
+
class LockedObject < BotException
|
39
|
+
end
|
40
|
+
|
41
|
+
class TimerInUse < BotException
|
42
|
+
end
|
43
|
+
|
44
|
+
class EmptyQueue < BotException
|
45
|
+
end
|
46
|
+
|
47
|
+
class Disconnected < BotException
|
48
|
+
end
|
49
|
+
|
50
|
+
class HandlerNotFound < BotException
|
51
|
+
attr_reader :message_type
|
52
|
+
def initialize(type)
|
53
|
+
@message_type = type
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class NotInChannel < BotException
|
58
|
+
attr_reader :channel
|
59
|
+
def initialize(channel)
|
60
|
+
@channel = channel
|
61
|
+
end
|
62
|
+
def to_s
|
63
|
+
"Bot is not currently in channel: #{@channel}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class QuietChannel < BotException
|
68
|
+
attr_reader :channel
|
69
|
+
def initialize(channel)
|
70
|
+
@channel = channel
|
71
|
+
end
|
72
|
+
def to_s
|
73
|
+
"Bot is not allowed to speak in channel: #{@channel}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class PluginMissing < BotException
|
78
|
+
end
|
79
|
+
|
80
|
+
class PluginFileNotFound < BotException
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
['timeout',
|
2
|
+
'net/http',
|
3
|
+
'mod_spox/models/Nick',
|
4
|
+
'mod_spox/models/Channel',
|
5
|
+
'mod_spox/models/Server',
|
6
|
+
'mod_spox/models/Models',
|
7
|
+
'mod_spox/Logger'].each{|f|require f}
|
8
|
+
|
9
|
+
module ModSpox
|
10
|
+
module Helpers
|
11
|
+
# secs:: number of seconds
|
12
|
+
# Converts seconds into a human readable string
|
13
|
+
def Helpers.format_seconds(secs)
|
14
|
+
arg = {:year => 29030400,
|
15
|
+
:month => 2419200,
|
16
|
+
:week => 604800,
|
17
|
+
:day => 86400,
|
18
|
+
:hour => 3600,
|
19
|
+
:minute => 60,
|
20
|
+
:second => 1}
|
21
|
+
res = ''
|
22
|
+
arg.each_pair do |k,v|
|
23
|
+
z = (secs / v).to_i
|
24
|
+
next unless z > 0
|
25
|
+
res += " #{z} #{k}#{z == 1 ? '':'s'}"
|
26
|
+
secs = secs % v
|
27
|
+
end
|
28
|
+
res = '0 seconds' if res.empty?
|
29
|
+
return res.strip
|
30
|
+
end
|
31
|
+
|
32
|
+
# bytes:: number of bytes
|
33
|
+
# Converts bytes into easy human readable form
|
34
|
+
# O(1) version by Ryan "pizza_milkshake" Flynn
|
35
|
+
Suff = [
|
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
|
+
]
|
46
|
+
def Helpers.format_size(bytes)
|
47
|
+
mag = (Math.log(bytes) / Math.log(1024)).floor
|
48
|
+
mag = [ Suff.length - 1, mag ].min
|
49
|
+
val = bytes.to_f / (1024 ** mag)
|
50
|
+
"%7.3f %sbyte%s" % [ val, Suff[mag], val == 1 ? "" : "s" ]
|
51
|
+
end
|
52
|
+
|
53
|
+
# command:: command to execute
|
54
|
+
# timeout:: maximum number of seconds to run
|
55
|
+
# Execute a system command (use with care)
|
56
|
+
def Helpers.safe_exec(command, timeout=10)
|
57
|
+
begin
|
58
|
+
Timeout::timeout(timeout) do
|
59
|
+
result = `#{command}`
|
60
|
+
end
|
61
|
+
rescue Timeout::Error => boom
|
62
|
+
Logger.warn("Command execution exceeded allowed time (command: #{command} | timeout: #{timeout})")
|
63
|
+
raise boom
|
64
|
+
rescue Object => boom
|
65
|
+
Logger.warn("Command generated an exception (command: #{command} | error: #{boom})")
|
66
|
+
raise boom
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# url:: URL to shorten
|
71
|
+
# Gets a tinyurl for given URL
|
72
|
+
def Helpers.tinyurl(url)
|
73
|
+
begin
|
74
|
+
connection = Net::HTTP.new('tinyurl.com', 80)
|
75
|
+
resp, data = connection.get("/api-create.php?url=#{url}")
|
76
|
+
if(resp.code !~ /^200$/)
|
77
|
+
raise "Failed to make the URL small."
|
78
|
+
end
|
79
|
+
return data.strip
|
80
|
+
rescue Object => boom
|
81
|
+
raise "Failed to process URL. #{boom}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# string:: name of target
|
86
|
+
# Locates target model and returns it. String can be a nick
|
87
|
+
# or channel name. If the string given does not match the required
|
88
|
+
# pattern for a channel or nick, the string is returned.
|
89
|
+
def Helpers.find_model(string, create=true)
|
90
|
+
result = nil
|
91
|
+
if(string =~ /^[A-Za-z\|\\\{\}\[\]\^\`~\_\-]+[A-Za-z0-9\|\\\{\}\[\]\^\`~\_\-]*$/)
|
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
|
97
|
+
else
|
98
|
+
Logger.warn("Failed to match string to model: #{string} -> No match")
|
99
|
+
end
|
100
|
+
return result
|
101
|
+
end
|
102
|
+
|
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
|
113
|
+
end
|
114
|
+
|
115
|
+
# kind:: (:internal|:incoming|:outgoing)
|
116
|
+
# type:: message type (Example: :Privmsg)
|
117
|
+
# Easy loader for messages
|
118
|
+
def load_message(kind, type)
|
119
|
+
require "mod_spox/messages/#{kind}/#{type}"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
['mod_spox/Exceptions',
|
2
|
+
'mod_spox/BotConfig',
|
3
|
+
'mod_spox/BaseConfig',
|
4
|
+
'mod_spox/Database',
|
5
|
+
'logger'].each{|f|require f}
|
6
|
+
|
7
|
+
module ModSpox
|
8
|
+
|
9
|
+
# Loads all files needed by the bot
|
10
|
+
def self.initialize_bot(db=nil)
|
11
|
+
setup_adapter(db)
|
12
|
+
check_upgrade
|
13
|
+
end
|
14
|
+
|
15
|
+
# Setup the DataMapper adapter
|
16
|
+
def self.setup_adapter(db=nil)
|
17
|
+
memcache = false
|
18
|
+
config = BaseConfig.new(BotConfig[:userconfigpath])
|
19
|
+
if(config[:memcache] == 'on')
|
20
|
+
begin
|
21
|
+
require 'memcache'
|
22
|
+
memcache = true
|
23
|
+
Database.cache = MemCache.new('localhost:11211', :namespace => 'modspox')
|
24
|
+
rescue Object => boom
|
25
|
+
puts "FAILED TO LOAD MEMCACHE SUPPORT: #{boom}"
|
26
|
+
# do nothing #
|
27
|
+
end
|
28
|
+
end
|
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
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# check if the bot has been upgraded
|
48
|
+
def self.check_upgrade
|
49
|
+
Sequel::Migrator.apply(Database.db, BotConfig[:libpath] + '/migrations')
|
50
|
+
config = BaseConfig.new(BotConfig[:userconfigpath])
|
51
|
+
config[:plugin_upgrade] = 'no'
|
52
|
+
begin
|
53
|
+
config[:plugin_upgrade] = 'yes' if config[:last_version] != ModSpox.botversion
|
54
|
+
rescue Exceptions::UnknownKey => boom
|
55
|
+
config[:plugin_upgrade] = 'yes'
|
56
|
+
end
|
57
|
+
config[:last_version] = ModSpox.botversion
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'logger'
|
2
|
+
module ModSpox
|
3
|
+
|
4
|
+
class Logger
|
5
|
+
|
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]
|
10
|
+
end
|
11
|
+
|
12
|
+
def Logger.warn(s)
|
13
|
+
@@log.warn(s) if Logger.log?
|
14
|
+
end
|
15
|
+
|
16
|
+
def Logger.info(s)
|
17
|
+
@@log.info(s) if Logger.log?
|
18
|
+
end
|
19
|
+
|
20
|
+
def Logger.fatal(s)
|
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
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
['mod_spox/handlers/Handler',
|
2
|
+
'mod_spox/Logger',
|
3
|
+
'mod_spox/Pipeline'].each{|f|require f}
|
4
|
+
|
5
|
+
module ModSpox
|
6
|
+
|
7
|
+
class MessageFactory
|
8
|
+
|
9
|
+
# access to handlers. (only really needed for testing)
|
10
|
+
attr_reader :handlers
|
11
|
+
|
12
|
+
# pipeline:: Message pipeline
|
13
|
+
# Create a new MessageFactory
|
14
|
+
def initialize(pipeline, pool)
|
15
|
+
@pipeline = pipeline
|
16
|
+
@pool = pool
|
17
|
+
@sync_pool = ActionPool::Pool.new(1, 1, nil, 2, Logger.raw)
|
18
|
+
@handlers = Hash.new
|
19
|
+
@available = {}
|
20
|
+
RFC.each_pair{|k,v| @available[v[:value]] = v[:handlers]}
|
21
|
+
@sync = [:RPL_MOTDSTART, :RPL_MOTD, :RPL_ENDOFMOTD, :RPL_WHOREPLY, :RPL_ENDOFWHO,
|
22
|
+
:RPL_NAMREPLY, :RPL_ENDOFNAMES, :RPL_WHOISUSER, :RPL_WHOISSERVER, :RPL_WHOISOPERATOR,
|
23
|
+
:RPL_WHOISIDLE, :RPL_WHOISCHANNELS, :RPL_WHOISIDENTIFIED, :RPL_ENDOFWHOIS].map{|s| RFC[s][:value]}
|
24
|
+
end
|
25
|
+
|
26
|
+
# string:: server message to be parsed
|
27
|
+
# Parses messages from server. This is placed in a queue to
|
28
|
+
# be processed thus there is now wait for processing to be
|
29
|
+
# completed.
|
30
|
+
def <<(string)
|
31
|
+
@pool.process{ parse_message(string) }
|
32
|
+
end
|
33
|
+
|
34
|
+
# s:: string from server
|
35
|
+
# determine type of message from server
|
36
|
+
def find_key(s)
|
37
|
+
s = s.dup
|
38
|
+
begin
|
39
|
+
key = nil
|
40
|
+
if(s[0].chr == ':')
|
41
|
+
s.slice!(0..s.index(' '))
|
42
|
+
key = s.slice!(0..s.index(' ')-1)
|
43
|
+
else
|
44
|
+
key = s.slice(0..s.index(' ')-1)
|
45
|
+
end
|
46
|
+
key.strip!
|
47
|
+
key = key.to_sym if key.to_i == 0
|
48
|
+
return key
|
49
|
+
rescue Object
|
50
|
+
Logger.info("Failed to find key for message: #{s}")
|
51
|
+
raise Exceptions::UnknownKey.new
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
# message:: server message
|
58
|
+
# Parses the server message and passes it to the proper handler
|
59
|
+
def parse_message(message)
|
60
|
+
Logger.info("Processing message: #{message}")
|
61
|
+
loaded = false
|
62
|
+
begin
|
63
|
+
key = find_key(message)
|
64
|
+
if(@handlers.has_key?(key))
|
65
|
+
Logger.info("Message of type #{key} is now being handled by #{@handlers[key]}")
|
66
|
+
if(@sync.include?(key))
|
67
|
+
Logger.info("Message of type #{key} requires synchronized processing")
|
68
|
+
@sync_pool.process do
|
69
|
+
message = @handlers[key].process(message)
|
70
|
+
@pipeline << message unless message.nil?
|
71
|
+
end
|
72
|
+
else
|
73
|
+
@pool.process do
|
74
|
+
message = @handlers[key].process(message)
|
75
|
+
@pipeline << message unless message.nil?
|
76
|
+
end
|
77
|
+
end
|
78
|
+
else
|
79
|
+
Logger.error("No handler was found to process message of type: #{key} Message: #{message}")
|
80
|
+
raise Exceptions::HandlerNotFound.new(key)
|
81
|
+
end
|
82
|
+
rescue Exceptions::HandlerNotFound => boom
|
83
|
+
unless(loaded)
|
84
|
+
if(@available[boom.message_type])
|
85
|
+
@available[boom.message_type].each do|f|
|
86
|
+
require "mod_spox/handlers/#{f}"
|
87
|
+
klass = ModSpox::Handlers.const_get(f)
|
88
|
+
if(klass.nil?)
|
89
|
+
Logger.error("File name does not seem to match class name. Now what? #{boom}")
|
90
|
+
else
|
91
|
+
klass.new(@handlers)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
Logger.info("Loaded handler for message type: #{boom.message_type}. Reprocessing message")
|
95
|
+
loaded = true
|
96
|
+
retry
|
97
|
+
end
|
98
|
+
end
|
99
|
+
raise boom
|
100
|
+
rescue Object => boom
|
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
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|