sponge 0.2.9 → 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.
data/README.rdoc CHANGED
@@ -1,11 +1,20 @@
1
1
  == Sponge
2
2
 
3
- Sponge is a simple, lightweight IRC library for Ruby.
3
+ Sponge is a simple, lightweight plugin based IRC bot and IRC library for Ruby.
4
+ See the {wiki}[http://wiki.github.com/injekt/sponge] for more information.
4
5
 
5
6
 
6
7
  == Example
8
+
9
+ client = Sponge::IRC::Client.new do
10
+ server "irc.freenode.org"
11
+ nickname "MyNick"
12
+ end
7
13
 
8
- See http://rdoc.injekt.net/sponge/Sponge/IRC/Client.html for a quick example
14
+ client.run
15
+
16
+
17
+ See {Sponge::IRC::Client}[http://rdoc.injekt.net/sponge/Sponge/IRC/Client.html] for more
9
18
 
10
19
 
11
20
  == Notes
@@ -16,7 +25,8 @@ are no specs and it lacks documenation. These will be added soon.
16
25
  == Installation
17
26
 
18
27
  gem install sponge
19
-
28
+
29
+
20
30
  or alternatively you can checkout the latest revision from github
21
31
 
22
32
  git clone git://github.com/injekt/sponge
data/Rakefile CHANGED
@@ -3,11 +3,12 @@ require "rake/clean"
3
3
  require "rake/gempackagetask"
4
4
  require "find"
5
5
  require "rake/rdoctask"
6
+ require 'spec/rake/spectask'
6
7
  require "lib/sponge/version"
7
8
 
8
9
  NAME = 'sponge'
9
10
  VERSION = Sponge::VERSION
10
- TITLE = "Sponge: The simple IRC library"
11
+ TITLE = "Sponge: The simple plugin based IRC bot/library"
11
12
  CLEAN.include ["*.gem", "doc"]
12
13
  RDOC_OPTS = [
13
14
  "-U", "--title", TITLE,
@@ -20,23 +21,28 @@ Rake::RDocTask.new do |rdoc|
20
21
  rdoc.rdoc_files.add %w(README.rdoc lib/**/*.rb)
21
22
  end
22
23
 
24
+ desc "Run all specs"
25
+ Spec::Rake::SpecTask.new('spec') do |t|
26
+ t.spec_files = Dir['spec/**/*.rb']
27
+ end
28
+
23
29
  desc "Package sponge"
24
- task :package=>[:clean] do |p|
30
+ task :package => [:clean] do |p|
25
31
  sh "gem build #{NAME}.gemspec"
26
32
  end
27
33
 
28
34
  desc "Install gem"
29
- task :install=>[:package] do
35
+ task :install => [:package] do
30
36
  sh "sudo gem install ./#{NAME}-#{VERSION} --local"
31
37
  end
32
-
38
+
33
39
  desc "Uninstall gem"
34
- task :uninstall=>[:clean] do
40
+ task :uninstall => [:clean] do
35
41
  sh "sudo gem uninstall #{NAME}"
36
42
  end
37
-
43
+
38
44
  desc "Upload gem to gemcutter"
39
- task :release=>[:package] do
45
+ task :release => [:package] do
40
46
  sh "gem push ./#{NAME}-#{VERSION}.gem"
41
47
  end
42
48
 
@@ -46,8 +52,16 @@ task :version do
46
52
  end
47
53
 
48
54
  desc "Upload rdoc to injekt.net"
49
- task :upload do
55
+ task :upload => [:clean, :rdoc] do
50
56
  sh("scp -rP 2295 doc/* injekt@injekt.net:/var/www/localhost/rdoc.injekt.net/sponge")
51
57
  end
52
58
 
53
- task :default => [:clean, :rdoc, :package]
59
+ desc "Report code statistics (KLOCs, etc) from the application"
60
+ task :stats do
61
+ STATS_DIRECTORIES = [%w(Code lib/), %w(Spec spec)].map{|name, dir| [ name, "./#{dir}" ] }.select { |name, dir| File.directory?(dir)}
62
+ require "extra/stats"
63
+ verbose = true
64
+ CodeStatistics.new(*STATS_DIRECTORIES).to_s
65
+ end
66
+
67
+ task :default => [:spec]
data/bin/sponge ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require 'sponge'
5
+ rescue LoadError
6
+ require 'rubygems'
7
+ require 'sponge'
8
+ end
9
+
10
+ require 'optparse'
11
+ require 'fileutils'
12
+
13
+ # This doesn't really do much at the moment
14
+ # At some point it should handling running bots
15
+ # but until then... bah
16
+ OptionParser.new do |opts|
17
+ opts.banner = "Usage: sponge [options]"
18
+
19
+ opts.separator ""
20
+
21
+ opts.on("--init NAME", "Create a new directory with NAME and copy the default Sponge proto") do |n|
22
+ if File.exists?(n)
23
+ puts "Unable to create proto, file exists.."
24
+ exit
25
+ end
26
+ FileUtils.mkdir(n)
27
+ path = File.expand_path(n)
28
+ proto = File.expand_path(Sponge::BASE + '/proto')
29
+ FileUtils.cp_r Dir[proto + '/**'], path
30
+ end
31
+
32
+ opts.on("-v", "--version", "Return the current version of Sponge") do
33
+ puts Sponge.version
34
+ exit
35
+ end
36
+ end.parse!
37
+
38
+
@@ -0,0 +1,11 @@
1
+ class Help < Sponge::Plugin
2
+
3
+ def reply(m, arg)
4
+ if @bot.plugins.has_plugin?(arg)
5
+ m.reply @bot.plugins.help(arg)
6
+ else
7
+ m.reply "Plugin unknown"
8
+ end
9
+ end
10
+
11
+ end
@@ -0,0 +1,8 @@
1
+ class Log < Sponge::Plugin
2
+ listen_to :privmsg, :join, :part, :quit
3
+
4
+ def listen(message)
5
+ puts "<#{message.channel}/#{message.nick}> #{message.text}"
6
+ end
7
+
8
+ end
@@ -0,0 +1,14 @@
1
+ class Login < Sponge::Plugin
2
+
3
+ def reply(m, arg)
4
+ if @bot.auth.login(m.nick, arg.to_s)
5
+ m.answer "You're logged in"
6
+ else
7
+ m.answer "Unable to log in"
8
+ end
9
+ end
10
+
11
+ def help
12
+ "login <password>"
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ class Logout < Sponge::Plugin
2
+
3
+ def reply(m, arg)
4
+ if @bot.auth.logout(m.nick)
5
+ m.answer "You're now logged out"
6
+ else
7
+ m.answer "Unable to log you out"
8
+ end
9
+ end
10
+
11
+ end
@@ -0,0 +1,11 @@
1
+ class Say < Sponge::Plugin
2
+
3
+ def reply(message, arg)
4
+ message.reply arg
5
+ end
6
+
7
+ def help
8
+ "say <text> - reply in current channel with <text>"
9
+ end
10
+
11
+ end
@@ -0,0 +1,20 @@
1
+ class SeenPlugin < Sponge::Plugin
2
+ listen_to :privmsg
3
+
4
+ def initialize(bot)
5
+ @users = {}
6
+ end
7
+
8
+ def listen(message)
9
+ @users[message.nick] = message
10
+ end
11
+
12
+ def reply(m, arg)
13
+ if @users.include?(arg)
14
+ m.reply "I have seen #{arg}"
15
+ else
16
+ m.reply "I haven't seen #{arg}"
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'sponge'
3
+
4
+ bot = Sponge::Bot.new('irc.yourserver.net',
5
+ :channels => ['#yourchannel'],
6
+ :users => {'foo' => 'bar'},
7
+ )
8
+
9
+ bot.start
data/lib/sponge.rb CHANGED
@@ -9,9 +9,7 @@ module Sponge
9
9
  require 'socket'
10
10
  require 'pp'
11
11
  require 'ostruct'
12
-
13
- # Sponge core
14
- require 'sponge/version'
12
+ require 'set'
15
13
 
16
14
  # IRC library
17
15
  require 'sponge/irc/socket'
@@ -20,4 +18,11 @@ module Sponge
20
18
  require 'sponge/irc/user'
21
19
  require 'sponge/irc/client'
22
20
  require 'sponge/irc/listeners'
21
+
22
+ # Sponge core
23
+ require 'sponge/version'
24
+ require 'sponge/plugins'
25
+ require 'sponge/plugin'
26
+ require 'sponge/auth'
27
+ require 'sponge/bot'
23
28
  end
@@ -0,0 +1,41 @@
1
+ module Sponge
2
+ class Auth
3
+
4
+ def initialize(client, users)
5
+ @client = client
6
+ @users = users
7
+ @logged = []
8
+ end
9
+
10
+ # Log a user in, returns the user if the user has successfully
11
+ # logged in, and nil otherwise
12
+ def login(user, pass)
13
+ return unless @users.key?(user) && @users[user] == pass
14
+ @logged.push(user).uniq!
15
+ user
16
+ end
17
+
18
+ # Log a user out, returns nil if the user isn't logged in
19
+ def logout(user)
20
+ return unless logged_in?(user)
21
+ @logged.delete(user)
22
+ true
23
+ end
24
+
25
+ # Check if a user is logged in
26
+ def logged_in?(user)
27
+ @logged.include?(user)
28
+ end
29
+
30
+ # How many users we have logged in
31
+ def count
32
+ @logged.size
33
+ end
34
+
35
+ # Log all users out
36
+ def clear
37
+ @logged.clear
38
+ end
39
+
40
+ end
41
+ end
data/lib/sponge/bot.rb ADDED
@@ -0,0 +1,64 @@
1
+ module Sponge
2
+ class Bot < IRC::Client
3
+
4
+ attr_reader :plugins
5
+
6
+ attr_reader :auth
7
+
8
+ def initialize(server=nil, options={}, &blk)
9
+ @plugins = Plugins.new(self)
10
+ @auth = Auth.new(self, options[:users] || {})
11
+
12
+ @command_prefix = options[:prefix] || '!'
13
+ @channels = options[:channels] || []
14
+
15
+ setup_plugins
16
+
17
+ super(server, options, &blk)
18
+ init_listeners
19
+ end
20
+
21
+ # This probably isn't a good idea, I generally don't like seeing any
22
+ # eval lines, as it's a nightmare to debug. It'll do for now, though.
23
+ def init_listeners
24
+ path = File.expand_path('../listeners', __FILE__)
25
+ Dir[path + '/*.rb'].each do |listener|
26
+ instance_eval(File.read(listener))
27
+ end
28
+ end
29
+
30
+ # Looks through the 'plugins' directory, require all plugins
31
+ # found, and add them into Sponge::Plugins
32
+ def setup_plugins
33
+ unless File.directory?(@plugins.path)
34
+ raise(LoadError, "No plugins directory found. Did you run `sponge init'?")
35
+ end
36
+
37
+ Dir[@plugins.path + '/*.rb'].each do |plugin|
38
+ require plugin
39
+ end
40
+
41
+ Plugin::LIST.each do |plugin|
42
+ add_plugin(plugin)
43
+ end
44
+ end
45
+
46
+ # Should only be used by #setup_plugins (for now..)
47
+ # Sugar for Sponge::Plugins#add
48
+ def add_plugin(plugin)
49
+ plugins.add(plugin)
50
+ end
51
+
52
+ # Registers an IRC command ready to dispatch to any
53
+ # plugin who are listening
54
+ def register(command, message)
55
+ if Plugin.has_listener?(command)
56
+ Plugin::LISTENERS[command.to_s.downcase].each do |cmd|
57
+ plugins.dispatch_listen(cmd, message)
58
+ end
59
+ end
60
+ end
61
+
62
+ end
63
+ end
64
+
@@ -22,6 +22,8 @@ module Sponge
22
22
  end
23
23
  end
24
24
 
25
+ class ListenerExistsError < RuntimeError; end
26
+
25
27
  # The IRC::Client using this Listener List
26
28
  attr_reader :client
27
29
 
@@ -37,8 +39,8 @@ module Sponge
37
39
  # * See IRC::Client#on
38
40
  def add(*commands, &blk)
39
41
  commands.each do |command|
40
- command = command.to_s
41
- raise "listener for #{command} already exists" if @list.key?(command)
42
+ command = command.to_s.downcase
43
+ raise ListenerExistsError, "listener for #{command} already exists" if @list.key?(command)
42
44
  @list[command] = Listener.new(command, &blk)
43
45
  end
44
46
  commands
@@ -46,7 +48,7 @@ module Sponge
46
48
 
47
49
  # Remove a listener from our list
48
50
  def delete(command)
49
- @list.delete(command)
51
+ @list.delete(command.to_s.downcase)
50
52
  end
51
53
 
52
54
  def [](command)
@@ -54,14 +56,19 @@ module Sponge
54
56
  end
55
57
 
56
58
  def include?(k)
57
- @list.key?(k)
59
+ @list.key?(k.to_s.downcase)
60
+ end
61
+
62
+ def clear
63
+ @list.clear
58
64
  end
59
65
 
60
66
  # Invoke #call on a Listener if it exists passing an IRC::Message
61
67
  def handle(message)
62
68
  raise "Not a IRC::Message" unless message.is_a?(Sponge::IRC::Message)
63
- if @list.key?(message.command)
64
- @list[message.command].call(client.irc, message)
69
+ command = message.command.to_s.downcase
70
+ if @list.key?(command)
71
+ @list[command].call(client.irc, message)
65
72
  end
66
73
  end
67
74
 
@@ -9,6 +9,8 @@ module Sponge
9
9
  # == Synopsis
10
10
  #
11
11
  class Parser
12
+
13
+ class BadMessageFormat < RuntimeError; end
12
14
 
13
15
  # Our IRC::Client instance
14
16
  attr_reader :client
@@ -21,7 +23,7 @@ module Sponge
21
23
  # for you to play with
22
24
  def parse(data)
23
25
  return unless data
24
- raise "Unknown Message" unless matches = data.match(/\A(?:\:(\S+)\s)?([A-Z0-9]+?)\s(.+?)\Z/)
26
+ raise(BadMessageFormat, "Unknown Message") unless matches = data.match(/\A(?:\:(\S+)\s)?([A-Z0-9]+?)\s(.+?)\Z/)
25
27
  prefix, command, params = matches.captures
26
28
 
27
29
  message = IRC::Message.new(client, data, prefix, command, params)
@@ -0,0 +1,5 @@
1
+ on(376) do |irc, message|
2
+ @channels.each do |chan|
3
+ irc.join chan
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ on(:JOIN) do |irc, message|
2
+
3
+ register(:JOIN, message)
4
+ end
@@ -0,0 +1,14 @@
1
+ on(:PRIVMSG) do |irc, message|
2
+
3
+ prefix = Regexp.escape(@command_prefix)
4
+
5
+ if matches = message.text.match(/#{prefix}([a-zA-Z]+?)(\s*\Z|\s(.*))/)
6
+ command = matches[1]
7
+ arg = matches[3]
8
+ if @plugins.has_plugin?(command)
9
+ @plugins.dispatch_reply(command, message, arg)
10
+ end
11
+ end
12
+
13
+ register(:PRIVMSG, message)
14
+ end
@@ -0,0 +1,109 @@
1
+ module Sponge
2
+
3
+ # == Plugin Example
4
+ # class SayPlugin < Sponge::Plugin
5
+ # def reply(m, arg)
6
+ # m.reply arg
7
+ # end
8
+ # end
9
+ #
10
+ # Simple as that, the reply method will get invoked when the say command is used.
11
+ # You can also have plugins 'listen' for stuff, for example if you'd like a plugin
12
+ # to print PRIVMSG's to your terminal you can have a plugin which listens for them.
13
+ #
14
+ # class ShowMessage < Sponge::Plugin
15
+ # listen_to :privmsg
16
+ #
17
+ # def listen(m)
18
+ # if m.public?
19
+ # puts "[#{m.channel}]<#{m.nick}> #{m.text}"
20
+ # end
21
+ # end
22
+ # end
23
+ #
24
+ # And that's it, the listen method will be invoked whenever the bot see's a PRIVMSG
25
+ # and it'll send the Sponge::IRC::Message applicable for this command.
26
+ #
27
+ # All plugins should be placed into a 'plugins' directory. All plugins are loaded on start
28
+ # and cannot be 'unloaded' although im sure this feature will be implemented at some time.
29
+ class Plugin
30
+
31
+ # Our list of plugins
32
+ LIST = []
33
+
34
+ # For plugins which require authentication
35
+ AUTH = []
36
+
37
+ # A hash containing IRC commands as keys whose values are Arrays containing
38
+ # a list of commands who are interested in 'listening' to them
39
+ #
40
+ # :privmsg => ['log', 'memo', 'seen']
41
+ # :join => ['log']
42
+ LISTENERS = {}
43
+
44
+ # Throw our plugin straight into the LIST
45
+ def self.inherited(plugin)
46
+ LIST << plugin
47
+ end
48
+
49
+ # This works ok, but I should probably add a better way of checking
50
+ # at some point.. heh.
51
+ # Returns 'say' from SayPlugin, etc
52
+ def self.command
53
+ name.downcase.sub(/plugin$/, '')
54
+ end
55
+
56
+ # Check if an IRC command has any plugins 'listening' for it
57
+ def self.has_listener?(cmd)
58
+ LISTENERS.key?(cmd.to_s.downcase)
59
+ end
60
+
61
+ # Plugin requires the nick to be authenticated
62
+ def self.requires_auth
63
+ AUTH << command
64
+ p AUTH
65
+ end
66
+
67
+ # Allows a specific plugin to 'listen' to irc messages
68
+ # making the plugins a little more interactive
69
+ def self.listen_to(*commands)
70
+ commands.each do |cmd|
71
+ cmd = cmd.to_s.downcase
72
+ if LISTENERS.key?(cmd)
73
+ LISTENERS[cmd] << command
74
+ else
75
+ LISTENERS[cmd] = [command]
76
+ end
77
+ end
78
+ end
79
+
80
+ # Create a new Plugin instance
81
+ # This is done for *every* command, if you want to reference the Sponge::Bot
82
+ # instance and also want to create add variables in your plugins constructor
83
+ # then make sure you either call super() or assign @bot in your plugins
84
+ #
85
+ # Probably a bad idea to use ::new on every Plugin, perhaps create a 'setup'
86
+ # method for controlling per plugin options and data in the future
87
+ #
88
+ # Need to implement a way of setting plugin specific options through class methods
89
+ # without using constants that just store the plugin name (ie AUTH)
90
+ def initialize(bot)
91
+ @bot = bot
92
+ end
93
+
94
+ # The default help if a specific plugin lacks it
95
+ def help
96
+ "No help for this plugin"
97
+ end
98
+
99
+ # The default usage if a specific plugin lacks it
100
+ def usage
101
+ "No usage for this plugin"
102
+ end
103
+
104
+ def requires_auth?
105
+ AUTH.include? self.class.command
106
+ end
107
+
108
+ end
109
+ end
@@ -0,0 +1,79 @@
1
+ module Sponge
2
+ class Plugins
3
+
4
+ attr_reader :bot
5
+
6
+ # The full path to our plugins directory
7
+ attr_reader :path
8
+
9
+ def initialize(bot)
10
+ @bot = bot
11
+ @path = File.expand_path('plugins')
12
+ @list = {}
13
+ end
14
+
15
+ # Add a plugin, this method invokes Plugin::new and passes our Sponge::Bot instance
16
+ # so we can access it in all of our plugins
17
+ def add(plugin)
18
+ @list[plugin.command] = plugin.new(bot)
19
+ end
20
+
21
+ # Grab a plugin
22
+ def get(plugin)
23
+ @list[plugin]
24
+ end
25
+ alias [] get
26
+
27
+ # Check if a plugin exists
28
+ def include?(command)
29
+ @list.key?(command)
30
+ end
31
+ alias has_plugin? include?
32
+
33
+ # Return a list of our plugin commands
34
+ def commands
35
+ @list.keys
36
+ end
37
+
38
+ def dispatch_listen(command, message)
39
+ if include?(command)
40
+ plugin = get(command)
41
+
42
+ if plugin.respond_to?(:listen)
43
+ plugin.send(:listen, message)
44
+ else
45
+ raise(ArgumentError, "Unable to dispatch to #{command}, does the #{plugin} plugin have a `listen' method?")
46
+ end
47
+ else
48
+ raise(ArgumentError, "Attempting to dispatch to unknown plugin")
49
+ end
50
+ end
51
+
52
+ def dispatch_reply(command, message, args)
53
+ if include?(command)
54
+ plugin = get(command)
55
+
56
+ # We don't raise if a plugin hasn't implemented a reply method
57
+ # as plugins can *just* be listeners
58
+ if plugin.respond_to?(:reply)
59
+ if plugin.requires_auth?
60
+ return unless bot.auth.logged_in?(message.nick)
61
+ end
62
+ plugin.send(:reply, message, args)
63
+ end
64
+ else
65
+ raise(ArgumentError, "Attempting to dispatch to unknown plugin")
66
+ end
67
+ end
68
+ alias :reply :dispatch_reply
69
+
70
+ def help(command)
71
+ if include?(command)
72
+ plugin = get(command)
73
+
74
+ plugin.help
75
+ end
76
+ end
77
+
78
+ end
79
+ end
@@ -1,7 +1,7 @@
1
1
  module Sponge
2
2
  MAJOR = 0
3
- MINOR = 2
4
- TINY = 9
3
+ MINOR = 3
4
+ TINY = 0
5
5
 
6
6
  VERSION = [MAJOR, MINOR, TINY].join('.')
7
7
 
@@ -9,4 +9,4 @@ module Sponge
9
9
  def self.version
10
10
  VERSION
11
11
  end
12
- end
12
+ end
data/spec/helper.rb CHANGED
@@ -1,6 +1,10 @@
1
1
  require File.expand_path('../../lib/sponge.rb', __FILE__)
2
2
  require 'bacon'
3
3
 
4
+ BaseClient = Sponge::IRC::Client.new do
5
+ server 'irc.freenode.org'
6
+ end unless defined?(BaseClient)
7
+
4
8
  class Sponge::IRC::Socket
5
9
  def write(data)
6
10
  nil
@@ -0,0 +1,67 @@
1
+ require File.expand_path('../../../lib/sponge/auth', __FILE__)
2
+
3
+ users = {
4
+ 'injekt' => 'sekret',
5
+ 'foo' => 'bar',
6
+ 'lorem' => 'ipsum',
7
+ }
8
+
9
+ auth = Sponge::Auth.new(nil, users)
10
+
11
+ describe "Sponge::Auth" do
12
+ describe "#login" do
13
+ it "should log a user in" do
14
+ auth.login('injekt', 'sekret')
15
+ auth.logged_in?('injekt').should == true
16
+ end
17
+
18
+ it "should return nil if given wrong credentials" do
19
+ resp = auth.login('injekt', 'wrongpass')
20
+ resp.should == nil
21
+ end
22
+ end
23
+
24
+ describe "#logout" do
25
+ it "should log a user out" do
26
+ auth.logout('injekt')
27
+ auth.logged_in?('injekt').should == false
28
+ end
29
+
30
+ it "should return nil if a user is not logged in" do
31
+ resp = auth.logout('foo')
32
+ resp.should == nil
33
+ end
34
+ end
35
+
36
+ describe "#clear" do
37
+ it "should log all users out" do
38
+ auth.login('injekt', 'sekret')
39
+ auth.login('foo', 'bar')
40
+ auth.count.should == 2
41
+ auth.clear
42
+ auth.count.should == 0
43
+ end
44
+ end
45
+
46
+ describe "#logged_in?" do
47
+ it "should return true if a user is logged in" do
48
+ auth.login('injekt', 'sekret')
49
+ resp = auth.logged_in?('injekt')
50
+ resp.should == true
51
+ end
52
+
53
+ it "should return false if a user is not logged in" do
54
+ auth.clear
55
+ resp = auth.logged_in?('injekt')
56
+ resp.should == false
57
+ end
58
+ end
59
+
60
+ describe "#count" do
61
+ it "should display how many users are currently logged in" do
62
+ auth.login('injekt', 'sekret')
63
+ auth.login('foo', 'bar')
64
+ auth.count.should == 2
65
+ end
66
+ end
67
+ end
@@ -12,6 +12,12 @@ describe "Sponge::IRC::Client" do
12
12
  client.config.nickname.should == 'Sponge'
13
13
  end
14
14
 
15
+ it "should raise if no server is supplied" do
16
+ lambda { Sponge::IRC::Client.new }
17
+ .should.raise(ArgumentError)
18
+ .message.should == "No server supplied"
19
+ end
20
+
15
21
  it "should use the default nickname if no username, hostname, or realname are supplied" do
16
22
  c = Sponge::IRC::Client.new('', :nickname => 'foobot')
17
23
 
@@ -0,0 +1,65 @@
1
+ require File.expand_path('../../../helper', __FILE__)
2
+
3
+ listeners = Sponge::IRC::Listeners.new(nil)
4
+
5
+ describe "Sponge::IRC::Listeners" do
6
+
7
+ it "is not case specific for keys" do
8
+ listeners.add('Case1', 'case2', 'CASE3')
9
+ 3.times do |n|
10
+ str = "CaSe#{n+1}"
11
+ listeners.include?(str.upcase).should == true
12
+ listeners.include?(str.downcase).should == true
13
+ end
14
+ end
15
+
16
+ describe "::new" do
17
+ it "should add the default ping listener" do
18
+ listeners.include?('PING').should == true
19
+ end
20
+ end
21
+
22
+ describe "#add" do
23
+ it "should add a listener" do
24
+ listeners.add('foo')
25
+ listeners.include?('foo').should == true
26
+ end
27
+
28
+ it "should add many listeners" do
29
+ listeners.add('lorem', 'ipsum')
30
+ listeners.include?('lorem').should == true
31
+ listeners.include?('ipsum').should == true
32
+ end
33
+
34
+ it "should convert Integers and Symbols to Strings" do
35
+ listeners.add(:blah)
36
+ listeners.include?('blah').should == true
37
+
38
+ listeners.add(376)
39
+ listeners.include?('376').should == true
40
+ end
41
+
42
+ it "should raise a ListenerExistsError if a listener already exists" do
43
+ lambda { listeners.add(:PING) }
44
+ .should.raise(Sponge::IRC::Listeners::ListenerExistsError)
45
+ .message.should =~ /listener for \w+ already exists/
46
+ end
47
+ end
48
+
49
+ describe "#delete" do
50
+ it "should remove a listener" do
51
+ listeners.add(:deleteme)
52
+ listeners.include?(:deleteme).should == true
53
+ listeners.delete(:deleteme)
54
+ listeners.include?(:deleteme).should == false
55
+ end
56
+ end
57
+
58
+ describe "#clear" do
59
+ it "should remove all listeners" do
60
+ listeners.clear
61
+ listeners.all.empty?.should == true
62
+ end
63
+ end
64
+
65
+ end
@@ -0,0 +1,37 @@
1
+ require File.expand_path '../../../helper', __FILE__
2
+
3
+ lines = {
4
+ :ping => 'PING :1825672507',
5
+ :notice => ':injekt!~injekt@myhostname.com NOTICE Sponge :foo bar',
6
+ :privmsg => ':injekt!~injekt@myhostname.com PRIVMSG Sponge :foo bar',
7
+ :join => ':injekt!~injekt@myhostname.com JOIN #sponge',
8
+ :part => ':injekt!~injekt@myhostname.com PART #sponge :cya!',
9
+ :quit => ':injekt!~injekt@myhostname.com QUIT :bye',
10
+ # more commands
11
+ }
12
+
13
+ badline = "foobar"
14
+
15
+ parser = Sponge::IRC::Parser.new(BaseClient)
16
+
17
+ describe "Sponge::IRC::Parser#parse" do
18
+
19
+ it "should return an IRC::Message" do
20
+ m = parser.parse(lines[:privmsg])
21
+ m.class.should == Sponge::IRC::Message
22
+ end
23
+
24
+ it "should raise BadMessageFormat if string is bad formatting" do
25
+ lambda { parser.parse(badline) }
26
+ .should.raise(Sponge::IRC::Parser::BadMessageFormat)
27
+ .message.should == "Unknown Message"
28
+ end
29
+
30
+ lines.each do |c, d|
31
+ it "should parse a #{c} message" do
32
+ m = parser.parse(d)
33
+ m.command.downcase.should == c.to_s
34
+ end
35
+ end
36
+
37
+ end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 2
8
- - 9
9
- version: 0.2.9
7
+ - 3
8
+ - 0
9
+ version: 0.3.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Lee 'injekt' Jarvis
@@ -14,8 +14,8 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-05 00:00:00 +01:00
18
- default_executable:
17
+ date: 2010-04-07 00:00:00 +01:00
18
+ default_executable: sponge
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: bacon
@@ -31,10 +31,10 @@ dependencies:
31
31
  version: 1.1.0
32
32
  type: :development
33
33
  version_requirements: *id001
34
- description: A simple IRC library
34
+ description: A simple plugin based IRC bot/library
35
35
  email: ljjarvis@gmail.com
36
- executables: []
37
-
36
+ executables:
37
+ - sponge
38
38
  extensions: []
39
39
 
40
40
  extra_rdoc_files:
@@ -42,27 +42,42 @@ extra_rdoc_files:
42
42
  files:
43
43
  - README.rdoc
44
44
  - Rakefile
45
- - examples/client.rb
46
- - examples/socket.rb
45
+ - spec/sponge/auth.rb
46
+ - spec/sponge/irc/listeners.rb
47
47
  - spec/sponge/irc/client.rb
48
+ - spec/sponge/irc/parser.rb
48
49
  - spec/helper.rb
50
+ - lib/proto/plugins/log.rb
51
+ - lib/proto/plugins/logout.rb
52
+ - lib/proto/plugins/login.rb
53
+ - lib/proto/plugins/seen.rb
54
+ - lib/proto/plugins/help.rb
55
+ - lib/proto/plugins/say.rb
56
+ - lib/proto/sponge.rb
49
57
  - lib/sponge/version.rb
58
+ - lib/sponge/plugins.rb
59
+ - lib/sponge/auth.rb
60
+ - lib/sponge/bot.rb
61
+ - lib/sponge/listeners/privmsg.rb
62
+ - lib/sponge/listeners/376.rb
63
+ - lib/sponge/listeners/join.rb
50
64
  - lib/sponge/irc/listeners.rb
51
65
  - lib/sponge/irc/client.rb
52
66
  - lib/sponge/irc/message.rb
53
67
  - lib/sponge/irc/socket.rb
54
68
  - lib/sponge/irc/user.rb
55
69
  - lib/sponge/irc/parser.rb
70
+ - lib/sponge/plugin.rb
56
71
  - lib/sponge.rb
57
72
  has_rdoc: true
58
- homepage: http://rdoc.injekt.net/sponge
73
+ homepage: http://wiki.github.com/injekt/sponge
59
74
  licenses: []
60
75
 
61
76
  post_install_message:
62
77
  rdoc_options:
63
78
  - --quiet
64
79
  - --title
65
- - "Sponge: The Simple IRC library"
80
+ - "Sponge: The Simple plugin based IRC bot/library"
66
81
  - --main
67
82
  - README.rdoc
68
83
  require_paths:
@@ -89,6 +104,6 @@ rubyforge_project:
89
104
  rubygems_version: 1.3.6
90
105
  signing_key:
91
106
  specification_version: 3
92
- summary: A simple IRC library
107
+ summary: A simple plugin based IRC bot/library
93
108
  test_files: []
94
109
 
data/examples/client.rb DELETED
@@ -1,20 +0,0 @@
1
- require 'sponge'
2
-
3
- client = Sponge::IRC::Client.new do
4
- server "irc.freenode.org"
5
- nickname "Sponge"
6
- end
7
-
8
- # 376 is the command for end of motd
9
- client.on "376" do |irc, message|
10
- irc.join "#mychannel"
11
- end
12
-
13
- # Add a callback for when someone (including ourselves) joins a channel
14
- client.on "JOIN" do |irc, message|
15
- unless message.nick == 'Sponge'
16
- message.reply "Hi there #{message.nick}, welcome to #{message.channel}!"
17
- end
18
- end
19
-
20
- client.run
data/examples/socket.rb DELETED
@@ -1,9 +0,0 @@
1
- require 'sponge'
2
-
3
- sock = Sponge::IRC::Socket.open('irc.freenode.org')
4
- sock.nick "SpongeBot"
5
- sock.user "SpongeBot", "sponge", "sponge", "Sponge IRC bot"
6
- sock.join "#mychan"
7
- sock.privmsg "#mychan", "Hello!"
8
- sock.part "#mychan"
9
- sock.quit "Quitting.."