sponge 0.2.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,30 @@
1
+ == Sponge
2
+
3
+ Sponge is a simple, lightweight IRC library for Ruby.
4
+
5
+
6
+ == Example
7
+
8
+ See http://rdoc.injekt.net/sponge/Sponge/IRC/Client.html for a quick example
9
+
10
+
11
+ == Notes
12
+
13
+ Please note that this is an early release. Though the code should work fine, there
14
+ are no specs and it lacks documenation. These will be added soon.
15
+
16
+ == Installation
17
+
18
+ gem install sponge
19
+
20
+ or alternatively you can checkout the latest revision from github
21
+
22
+ git clone git://github.com/injekt/sponge
23
+
24
+
25
+ == TODO
26
+
27
+ * Finish this README
28
+ * Create specs
29
+ * Complete documentation
30
+ * Create more rake tasks
@@ -0,0 +1,54 @@
1
+ require "rake"
2
+ require "rake/clean"
3
+ require "rake/gempackagetask"
4
+ require "find"
5
+ require "rake/rdoctask"
6
+ require "lib/sponge/version"
7
+
8
+ NAME = 'sponge'
9
+ VERSION = Sponge::VERSION
10
+ TITLE = "Sponge: The simple IRC library"
11
+ CLEAN.include ["*.gem", ".config", "rdoc"]
12
+ RDOC_OPTS = [
13
+ "--line-numbers", "--inline-source",
14
+ "--title", TITLE,
15
+ "--main", "README.rdoc"
16
+ ]
17
+
18
+ Rake::RDocTask.new do |rdoc|
19
+ rdoc.rdoc_dir = "rdoc"
20
+ rdoc.options += RDOC_OPTS
21
+ rdoc.rdoc_files.add %w(README.rdoc lib/**/*.rb)
22
+ end
23
+
24
+ desc "Package sponge"
25
+ task :package=>[:clean] do |p|
26
+ sh "gem build #{NAME}.gemspec"
27
+ end
28
+
29
+ desc "Install gem"
30
+ task :install=>[:package] do
31
+ sh "sudo gem install ./#{NAME}-#{VERSION} --local"
32
+ end
33
+
34
+ desc "Uninstall gem"
35
+ task :uninstall=>[:clean] do
36
+ sh "sudo gem uninstall #{NAME}"
37
+ end
38
+
39
+ desc "Upload gem to gemcutter"
40
+ task :release=>[:package] do
41
+ sh "gem push ./#{NAME}-#{VERSION}.gem"
42
+ end
43
+
44
+ desc "Print latest #{NAME} version"
45
+ task :version do
46
+ puts VERSION
47
+ end
48
+
49
+ desc "Upload rdoc to injekt.net"
50
+ task :upload do
51
+ sh("scp -rP 2295 rdoc/ injekt@injekt.net:/var/www/localhost/rdoc.injekt.net/sponge")
52
+ end
53
+
54
+ task :default => [:rdoc, :package]
@@ -0,0 +1,20 @@
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
@@ -0,0 +1,9 @@
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.."
@@ -0,0 +1,23 @@
1
+ # Copyright (c) 2010 Lee 'injekt' Jarvis <ljjarvis@gmail.com>
2
+ # All files in this distribution are subject to the terms of the Ruby license.
3
+
4
+ module Sponge
5
+ BASE = File.expand_path(File.dirname(__FILE__))
6
+ $LOAD_PATH.unshift(BASE)
7
+
8
+ # Stdlib
9
+ require 'socket'
10
+ require 'pp'
11
+ require 'ostruct'
12
+
13
+ # Sponge core
14
+ require 'sponge/version'
15
+
16
+ # IRC library
17
+ require 'sponge/irc/socket'
18
+ require 'sponge/irc/parser'
19
+ require 'sponge/irc/message'
20
+ require 'sponge/irc/user'
21
+ require 'sponge/irc/client'
22
+ require 'sponge/irc/listeners'
23
+ end
@@ -0,0 +1,158 @@
1
+ module Sponge
2
+ module IRC
3
+
4
+ # == Author
5
+ # * Lee Jarvis - ljjarvis@gmail.com
6
+ #
7
+ # == Description
8
+ # TODO
9
+ #
10
+ # == Usage
11
+ #
12
+ # === Minimal Example
13
+ # client = Sponge::IRC::Client.new do
14
+ # server "irc.freenode.org"
15
+ # nickname "MyNick"
16
+ # end
17
+ #
18
+ # client.run
19
+ #
20
+ # === Mapping a Listener
21
+ # client = Sponge::IRC::Client.new do
22
+ # server "irc.freenode.org"
23
+ # nickname "MyNick"
24
+ # realname "Mr Sponge Bot"
25
+ # end
26
+ #
27
+ # # Join a channel once we've seen end of MOTD
28
+ # client.on(376) do |irc, message|
29
+ # irc.join "#mychan"
30
+ # end
31
+ #
32
+ # client.on(:JOIN) do |irc, message|
33
+ # message.reply "Hi #{message.nick}. Welcome to #{message.channel}!"
34
+ # end
35
+ #
36
+ # client.run
37
+ class Client
38
+ # The current IRC::Socket this Client is using
39
+ attr_reader :irc
40
+
41
+ # Client configuration options
42
+ attr_reader :config
43
+
44
+ def initialize(server=nil, opts={}, &blk)
45
+ @config = OpenStruct.new(opts.merge(OptionsDSL.new(server, &blk).options))
46
+ @config.port ||= 6667
47
+
48
+ @irc = IRC::Socket.new(config.server, config.port)
49
+ @irc.client = self
50
+ @parser = IRC::Parser.new(self)
51
+ @listeners = IRC::Listeners.new(self)
52
+
53
+ setup_username
54
+ end
55
+
56
+ # Start our connection
57
+ def connect
58
+ puts "Connecting to #{irc.server} on #{irc.port}"
59
+ irc.connect unless irc.connected?
60
+
61
+ irc.nick(config.nickname)
62
+ irc.user(config.username, config.hostname, "*", config.realname)
63
+
64
+ puts "Connected" if irc.connected?
65
+ end
66
+
67
+ # Map listeners to an IRC command. For example:
68
+ #
69
+ # client.on("376") do |irc, message|
70
+ # irc.join "#mychan"
71
+ # end
72
+ #
73
+ # client.on(:JOIN) do |irc, message|
74
+ # message.reply "Hi, #{message.nick}. Welcome to #{message.channel}"
75
+ # end
76
+ #
77
+ # * +irc+ - The Clients Sponge::IRC::Socket
78
+ # * +message+ - The current Sponge::IRC::Message
79
+ def on(*commands, &blk)
80
+ @listeners.add(*commands, &blk)
81
+ end
82
+
83
+ # Change clients nickname
84
+ def set_nick(new)
85
+ config.nickname = new
86
+ @irc.nick(new)
87
+ end
88
+
89
+ # Sugar for IRC::Parser#parse
90
+ def process(data)
91
+ message = @parser.parse(data)
92
+ @listeners.handle(message) if message
93
+ end
94
+
95
+ # Reads the next line from the IRC server whilst we're connected.
96
+ # Sends the line to #process
97
+ def run
98
+ connect unless irc.connected?
99
+ process(irc.read) while irc.connected?
100
+ end
101
+
102
+ # Quit our IRC socket and exit the Client
103
+ def quit
104
+ @irc.quit
105
+ exit
106
+ end
107
+
108
+ private
109
+
110
+ def setup_username
111
+ raise "You must set a nickname" unless nick = config.nickname
112
+ config.username ||= nick
113
+ config.hostname ||= nick
114
+ config.realname ||= nick
115
+ end
116
+
117
+ # == Author
118
+ # * Lee Jarvis - ljjarvis@gmail.com
119
+ #
120
+ # == Description
121
+ # TODO
122
+ class OptionsDSL
123
+ attr_reader :options
124
+
125
+ def initialize(server=nil, &blk)
126
+ @options = {}
127
+ server(server) if server
128
+ instance_eval(&blk)
129
+ end
130
+
131
+ def server(val)
132
+ @options[:server] = val
133
+ end
134
+
135
+ def port(val)
136
+ @options[:port] = val
137
+ end
138
+
139
+ def nickname(val)
140
+ @options[:nickname] = val
141
+ end
142
+
143
+ def username(val)
144
+ @options[:username] = val
145
+ end
146
+
147
+ def hostname(val)
148
+ @options[:hostname] = val
149
+ end
150
+
151
+ def realname(val)
152
+ @options[:realname] = val
153
+ end
154
+ end
155
+
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,69 @@
1
+ module Sponge
2
+ module IRC
3
+
4
+ # == Author
5
+ # * Lee Jarvis
6
+ #
7
+ #
8
+ #
9
+ class Listeners
10
+
11
+ # == Author
12
+ # * Lee Jarvis
13
+ #
14
+ #
15
+ class Listener
16
+ def initialize(command, &blk)
17
+ @callback = blk
18
+ end
19
+
20
+ def call(*args)
21
+ @callback.call(args)
22
+ end
23
+ end
24
+
25
+ # The IRC::Client using this Listener List
26
+ attr_reader :client
27
+
28
+ def initialize(client)
29
+ @client = client
30
+ @list = {}
31
+
32
+ # Add the default PING reply
33
+ add(:PING) {|i, m| i.pong(m.text) }
34
+ end
35
+
36
+ # Add a new Listener to the Listener List
37
+ # * See IRC::Client#on
38
+ def add(*commands, &blk)
39
+ commands.each do |command|
40
+ command = command.to_s
41
+ raise "listener for #{command} already exists" if @list.key?(command)
42
+ @list[command] = Listener.new(command, &blk)
43
+ end
44
+ end
45
+
46
+ # Remove a listener from our list
47
+ def delete(command)
48
+ @list.delete(command)
49
+ end
50
+
51
+ def [](command)
52
+ @list[command]
53
+ end
54
+
55
+ # Invoke #call on a Listener if it exists passing an IRC::Message
56
+ def handle(message)
57
+ raise "Not a IRC::Message" unless message.is_a?(Sponge::IRC::Message)
58
+ if @list.key?(message.command)
59
+ @list[message.command].call(client.irc, message)
60
+ end
61
+ end
62
+
63
+ def all
64
+ @list
65
+ end
66
+
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,90 @@
1
+ module Sponge
2
+ module IRC
3
+
4
+ # == Author
5
+ # * Lee Jarvis
6
+ #
7
+ # == Description
8
+ # This class should *only* be used by IRC::Parser
9
+ #
10
+ # == Synopsis
11
+ #
12
+ #
13
+ class Message
14
+
15
+ # Our IRC::Client
16
+ attr_reader :client
17
+
18
+ # Our IRC::Socket instance
19
+ attr_reader :irc
20
+
21
+ # The raw IRC string received from the server
22
+ attr_reader :raw
23
+
24
+ # The message prefix passed from IRC::Parser
25
+ attr_reader :prefix
26
+
27
+ # The IRC Command (PRIVMSG, MODE, 376, 372, etc)
28
+ attr_reader :command
29
+
30
+ # Channel the message is for
31
+ attr_accessor :channel
32
+
33
+ # The channel or the client name (if it's a private message)
34
+ attr_reader :for
35
+
36
+ # The IRC::User this message is from
37
+ attr_accessor :from
38
+
39
+ # The nick the message is from (sugar for IRC::User#nick)
40
+ attr_accessor :nick
41
+
42
+ # Message text
43
+ attr_accessor :text
44
+
45
+ # All params
46
+ attr_reader :params
47
+
48
+ def initialize(client, raw, prefix, command, params)
49
+ @client = client
50
+ @irc = client.irc
51
+ @raw = raw
52
+ @prefix = prefix
53
+ @command = command
54
+ @params = []
55
+ params.scan(/(?!:)(\S+)|:(.*)/) { @params << ($1 || $2) } if params
56
+
57
+ @channel = nil
58
+ @for = nil
59
+ @from = nil
60
+ @nick = nil
61
+ end
62
+
63
+ def for=(who)
64
+ @for = who
65
+ @channel = who if who =~ /^[\#&]+/
66
+ end
67
+
68
+ def private?
69
+ @channel
70
+ end
71
+
72
+ def public?
73
+ !@channel
74
+ end
75
+
76
+ # Reply to a message with a PRIVMSG back to the sender (channel or nick)
77
+ def reply(message)
78
+ who = channel || from
79
+ @irc.privmsg(who, message)
80
+ end
81
+
82
+ # Reply to a user with their nickname prefix'd
83
+ def answer(message)
84
+ return unless nick && channel
85
+ @irc.privmsg(channel, [nick, message].join(': '))
86
+ end
87
+
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,41 @@
1
+ module Sponge
2
+ module IRC
3
+
4
+ # == Author
5
+ # * Lee Jarvis - ljjarvis@gmail.com
6
+ #
7
+ # == Description
8
+ #
9
+ # == Synopsis
10
+ #
11
+ class Parser
12
+
13
+ # Our IRC::Client instance
14
+ attr_reader :client
15
+
16
+ def initialize(client)
17
+ @client = client
18
+ end
19
+
20
+ # Parses a raw IRC server message and returns a nicely encapsulated IRC::Message
21
+ # for you to play with
22
+ def parse(data)
23
+ return unless data
24
+ raise "Unknown Message" unless matches = data.match(/\A(?:\:(\S+)\s)?([A-Z0-9]+?)\s(.+?)\Z/)
25
+ prefix, command, params = matches.captures
26
+
27
+ message = IRC::Message.new(client, data, prefix, command, params)
28
+ message.for = message.params.first
29
+ message.text = message.params.last
30
+
31
+ if prefix && usermatch = prefix.match(/^(\S+?)!(\S+?)@(\S+?)$/)
32
+ message.from = IRC::User.new(client, *usermatch.captures)
33
+ message.nick = message.from.nick
34
+ end
35
+
36
+ message
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,165 @@
1
+ module Sponge
2
+ module IRC
3
+
4
+ # == Author
5
+ # * Lee Jarvis - ljjarvis@gmail.com
6
+ #
7
+ # == Description
8
+ # Sponge::IRC::Socket is a simple wrapper around TCPSocket. It provides simple
9
+ # functionality to interact with IRC servers.
10
+ #
11
+ # Note that when creating a new IRC::Socket, I generally assign the instance to a
12
+ # variable named <em>irc</em> throughout the documentation.
13
+ #
14
+ # == Synopsis
15
+ # irc = Sponge::IRC::Socket.open('irc.2600.net')
16
+ # irc.nick "SpongeBot"
17
+ # irc.user "SpongeBot", "sponge", "sponge", "Sponge IRC bot"
18
+ # irc.join "#mychan"
19
+ # irc.privmsg "#mychan", "Hello!"
20
+ # irc.part "#mychan"
21
+ # irc.quit "Quitting.."
22
+ #
23
+ class Socket
24
+
25
+ # The Client using this Socket (if one at all)
26
+ attr_accessor :client
27
+
28
+ # The server address we're connected to
29
+ attr_reader :server
30
+
31
+ # The port our socket is connected on
32
+ attr_reader :port
33
+
34
+ # Create a new IRC::Socket and connect to it
35
+ def self.open(server, port=6667)
36
+ sock = new(server, port)
37
+ sock.connect
38
+ sock
39
+ end
40
+
41
+ # Creates a new IRC::Socket. This doesn't automatically connect.
42
+ # If you want to do that use IRC::Socket.open
43
+ def initialize(server, port=6667)
44
+ @server = server
45
+ @port = port
46
+
47
+ @client = nil
48
+ @connected = false
49
+ end
50
+
51
+ # Connect to our IRC server if we haven't already connected
52
+ def connect
53
+ return if connected?
54
+
55
+ @socket = TCPSocket.new(server, port)
56
+ rescue Interrupt
57
+ raise
58
+ rescue Exception
59
+ raise
60
+ else
61
+ @connected = true
62
+ end
63
+
64
+ # Check if our Socket is currently connected to a server
65
+ def connected?
66
+ @connected
67
+ end
68
+
69
+ # Send a message to our server, appending CR-LF
70
+ def write(data)
71
+ @socket.print(data + "\r\n")
72
+ rescue IOError
73
+ raise
74
+ end
75
+
76
+ # Read the next line from the server. Chomps the trailing CR-LF
77
+ # Returns nil if there are issues with reading from the Socket.
78
+ # This method also safely shuts down our IRC::Socket by sending
79
+ # the QUIT command before exiting, it then closes the socket and exits
80
+ # the program.
81
+ def read
82
+ if data = @socket.gets
83
+ data.chomp("\r\n")
84
+ else
85
+ @connected = false
86
+ nil
87
+ end
88
+ rescue Interrupt
89
+ puts "\nInterrupted. Shutting down safely."
90
+ if connected?
91
+ quit("Client Interrupted")
92
+ close
93
+ exit 1
94
+ end
95
+ rescue IOError
96
+ @connected = false
97
+ nil
98
+ end
99
+
100
+ # Close our socket
101
+ def close
102
+ @socket.close
103
+ rescue IOError
104
+ end
105
+
106
+ # Send the USER command, usually to log into the server
107
+ def user(user, host, server, real)
108
+ write("USER #{user} #{host} #{server} :#{real}")
109
+ end
110
+
111
+ # Change our nickname
112
+ def nick(nick)
113
+ write("NICK #{nick}")
114
+ end
115
+
116
+ # Send a PRIVMSG to a specific user or channel
117
+ def privmsg(recipient, message)
118
+ write("PRIVMSG #{recipient} :#{message}")
119
+ end
120
+
121
+ # Send a NOTICE to a specific user or channel
122
+ def notice(recipient, message)
123
+ write("NOTICE #{recipient} :#{message}")
124
+ end
125
+
126
+ # Join a channel, using a password is necessary
127
+ def join(channel, password=nil)
128
+ write("JOIN #{channel}#{password ? password : ''}")
129
+ end
130
+
131
+ # Part a channel(s)
132
+ def part(*channels)
133
+ write("PART #{channels.join(',')}")
134
+ end
135
+
136
+ # Set the topic on a given channel
137
+ def topic(channel, topic)
138
+ write("TOPIC #{channel} :#{topic}")
139
+ end
140
+
141
+ # Kick nick from channel
142
+ def kick(channel, nick, reason="")
143
+ write("KICK #{channel} #{nick} :#{reason}")
144
+ end
145
+
146
+ # Send a PONG command
147
+ def pong(server)
148
+ write("PONG #{server}")
149
+ end
150
+
151
+ # Set ourselves as being away, (or not-away if a message is not given)
152
+ def away(message=nil)
153
+ write("AWAY#{message ? ':'+message : ''}")
154
+ end
155
+
156
+ # Send the QUIT command to our IRC server
157
+ # This also closes our IRC::Socket
158
+ def quit(reason="Cya!")
159
+ write("QUIT :#{reason}")
160
+ close
161
+ end
162
+
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,35 @@
1
+ module Sponge
2
+ module IRC
3
+ class User
4
+
5
+ # Our IRC::Client
6
+ attr_reader :client
7
+
8
+ # The nickname of this User
9
+ attr_reader :nick
10
+
11
+ # The username of this User
12
+ attr_reader :user
13
+
14
+ # The hostname of this User
15
+ attr_reader :host
16
+
17
+ def initialize(client, nick, user, host)
18
+ @client = client
19
+ @nick = nick
20
+ @user = user
21
+ @host = host
22
+ end
23
+
24
+ # Check if the User is us
25
+ def me?
26
+ client.config.nickname == nick
27
+ end
28
+
29
+ def to_s
30
+ @nick
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,12 @@
1
+ module Sponge
2
+ MAJOR = 0
3
+ MINOR = 2
4
+ TINY = 8
5
+
6
+ VERSION = [MAJOR, MINOR, TINY].join('.')
7
+
8
+ # The current Version of Sponge you're using
9
+ def self.version
10
+ VERSION
11
+ end
12
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sponge
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 2
8
+ - 8
9
+ version: 0.2.8
10
+ platform: ruby
11
+ authors:
12
+ - Lee 'injekt' Jarvis
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-04-05 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: A simple IRC library
22
+ email: ljjarvis@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files:
28
+ - README.rdoc
29
+ files:
30
+ - README.rdoc
31
+ - Rakefile
32
+ - examples/client.rb
33
+ - examples/socket.rb
34
+ - lib/sponge/version.rb
35
+ - lib/sponge/irc/listeners.rb
36
+ - lib/sponge/irc/client.rb
37
+ - lib/sponge/irc/message.rb
38
+ - lib/sponge/irc/socket.rb
39
+ - lib/sponge/irc/user.rb
40
+ - lib/sponge/irc/parser.rb
41
+ - lib/sponge.rb
42
+ has_rdoc: true
43
+ homepage: http://rdoc.injekt.net/sponge
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options:
48
+ - --quiet
49
+ - --line-numbers
50
+ - --inline-source
51
+ - --title
52
+ - "Sponge: The Simple IRC library"
53
+ - --main
54
+ - README.rdoc
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ segments:
62
+ - 1
63
+ - 8
64
+ - 4
65
+ version: 1.8.4
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ requirements: []
74
+
75
+ rubyforge_project:
76
+ rubygems_version: 1.3.6
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: A simple IRC library
80
+ test_files: []
81
+