xmppbot 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2008-12-05
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/Manifest.txt ADDED
@@ -0,0 +1,15 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.rdoc
5
+ Rakefile
6
+ lib/xmppbot.rb
7
+ lib/xmppbot/bot.rb
8
+ lib/xmppbot/message.rb
9
+ lib/xmppbot/other.rb
10
+ lib/xmppbot/presence.rb
11
+ script/console
12
+ script/destroy
13
+ script/generate
14
+ test/test_helper.rb
15
+ test/test_xmppbot.rb
data/PostInstall.txt ADDED
@@ -0,0 +1,56 @@
1
+ Example of use :
2
+
3
+ require 'xmppbot'
4
+
5
+ class Johnny5 < XMPPBot::Bot
6
+ def connect
7
+ super do |status|
8
+ if status == XMPPBot::ConnectionEvents::CONNECT
9
+ announce_presence
10
+ register_callbacks
11
+ else
12
+ disconnect
13
+ end
14
+ end
15
+ end
16
+
17
+ def register_callbacks
18
+ on_presence_received do |pres|
19
+ puts "#{pres.from} is now #{pres.to_s}" unless pres.to_s.strip ==
20
+ ""
21
+ end
22
+
23
+ on_message_received do |msg|
24
+ if msg.body == "exit"
25
+ disconnect
26
+ else
27
+ stanza=XMPPBot::Message.new
28
+ stanza.to=msg.from
29
+ stanza.body="You said : #{msg.body}"
30
+ send(stanza)
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ @bot = Johnny5.new
37
+ @bot.jid = "cripes@jaim.at"
38
+ @bot.password = "cripes"
39
+ @bot.log_level = XMPPBot::Logging::INFO
40
+ @bot.auto_accept_subscriptions = true
41
+
42
+ @bot.connect
43
+
44
+ #We pause the execution of the current thread to prevent the program
45
+ from exiting
46
+ Thread.stop
47
+
48
+ #Once the parsing thread exits, execution resumes here
49
+ puts "Connection terminated"
50
+
51
+
52
+
53
+
54
+
55
+
56
+ For more information on xmppbot, see http://xmppbot.rubyforge.org
data/README.rdoc ADDED
@@ -0,0 +1,90 @@
1
+ = xmppbot
2
+
3
+ == DESCRIPTION:
4
+
5
+ Simple implementation on top of StropheRuby(http://github.com/flamontagne/strophe_ruby/).
6
+ It's for those who want to build simple xmpp bots quickly. It features only the essential :
7
+ - auto accept subscriptions
8
+ - callback for received messages
9
+ - callback for received presences
10
+ - a method to send messages and presences
11
+ - That's it
12
+
13
+ Warning : StropheRuby is very experimental at the moment. It is definitely NOT ready for production!
14
+
15
+ == FEATURES/PROBLEMS:
16
+
17
+ - Only tested under Debian
18
+ - No TLS support for now. It will work once TLS with OpenSSL is working in Strophe (http://code.stanziq.com/strophe)
19
+
20
+
21
+ == SYNOPSIS:
22
+
23
+ How to use it :
24
+
25
+ require 'xmppbot'
26
+ def register_callbacks
27
+ @bot.on_presence_received do |pres|
28
+ puts "#{pres.from} is now #{pres.to_s}"
29
+ end
30
+
31
+ @bot.on_message_received do |msg|
32
+ if msg.body == "exit"
33
+ @bot.disconnect
34
+ else
35
+ stanza=XMPPBot::Message.new
36
+ stanza.to=msg.from
37
+ stanza.body="You said : #{msg.body}"
38
+ @bot.send(stanza)
39
+ end
40
+ end
41
+ end
42
+
43
+
44
+ @bot=XMPPBot::Bot.new
45
+ @bot.jid="bot@example.com"
46
+ @bot.password="secret"
47
+ @bot.log_level = XMPPBot::Logging::DEBUG
48
+ @bot.auto_accept_subscriptions = true
49
+
50
+ @bot.connect do |status|
51
+ if status == XMPPBot::ConnectionEvents::CONNECT
52
+ @bot.announce_presence
53
+ register_callbacks
54
+ else
55
+ @bot.disconnect
56
+ end
57
+ end
58
+
59
+ == REQUIREMENTS:
60
+
61
+ * Compile and install StropheRuby (http://github.com/flamontagne/stropheruby)
62
+
63
+ == INSTALL:
64
+
65
+ * For now you can install the GEM in the pkg directory. Remember that you need StropheRuby to use XMPPBot ()
66
+
67
+ == LICENSE:
68
+
69
+ (The MIT License)
70
+
71
+ Copyright (c) 2008 FIXME full name
72
+
73
+ Permission is hereby granted, free of charge, to any person obtaining
74
+ a copy of this software and associated documentation files (the
75
+ 'Software'), to deal in the Software without restriction, including
76
+ without limitation the rights to use, copy, modify, merge, publish,
77
+ distribute, sublicense, and/or sell copies of the Software, and to
78
+ permit persons to whom the Software is furnished to do so, subject to
79
+ the following conditions:
80
+
81
+ The above copyright notice and this permission notice shall be
82
+ included in all copies or substantial portions of the Software.
83
+
84
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
85
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
86
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
87
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
88
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
89
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
90
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
2
+ #require File.dirname(__FILE__) + '/lib/xmppbot'
3
+
4
+ # Generate all the Rake tasks
5
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
+ $hoe = Hoe.new('xmppbot', '0.0.1') do |p|
7
+ p.developer('François Lamontagne', 'flamontagne@gmail.com')
8
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
9
+ p.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
10
+ p.rubyforge_name = p.name # TODO this is default value
11
+ p.extra_deps = [
12
+ ['strophe_ruby','>= 0.0.1'],
13
+ ]
14
+ p.extra_dev_deps = [
15
+ ['newgem', ">= #{::Newgem::VERSION}"]
16
+ ]
17
+
18
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
19
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
20
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
21
+ p.rsync_args = '-av --delete --ignore-errors'
22
+ end
23
+
24
+ require 'newgem/tasks' # load /tasks/*.rake
25
+ Dir['tasks/**/*.rake'].each { |t| load t }
26
+
27
+ # TODO - want other tests/tasks run by default? Add them to the list
28
+ # task :default => [:spec, :features]
@@ -0,0 +1,147 @@
1
+ ############################################################
2
+ # XMPPBot::Bot
3
+ # Really simple implementation of StropheRuby to ease the devleopment process of a XMPP bot
4
+ # Author : Francois Lamontagne
5
+ ############################################################
6
+
7
+ module XMPPBot
8
+ class Bot
9
+ attr_accessor :jid, :password, :log_level, :auto_accept_subscriptions
10
+ #connect, authenticate and start event loop
11
+ def connect
12
+ StropheRuby::EventLoop.prepare
13
+
14
+ @ctx=StropheRuby::Context.new(@log_level)
15
+ @conn=StropheRuby::Connection.new(@ctx)
16
+ @conn.jid = @jid
17
+ @conn.password= @password
18
+
19
+ @conn.connect do |status|
20
+ if status == StropheRuby::ConnectionEvents::CONNECT
21
+ accept_subscriptions if auto_accept_subscriptions
22
+ keep_alive
23
+ end
24
+ yield(status)
25
+ end
26
+
27
+ main_thread = Thread.current
28
+
29
+ #start the event loop in a separate thread
30
+ Thread.new do
31
+ Thread.current.abort_on_exception = true
32
+
33
+ @ctx.loop_status=1
34
+ while @ctx.loop_status == 1
35
+ StropheRuby::EventLoop.run_once(@ctx,1)
36
+ end
37
+
38
+ #shutdown down strophe and wake up the calling thread
39
+ StropheRuby::EventLoop.shutdown
40
+ main_thread.wakeup
41
+ end
42
+ end
43
+
44
+ #accept subscription request from the user then send a subscription request to that same user.
45
+ def accept_subscriptions
46
+ on_presence_received do |pres|
47
+ if pres.type == "subscribe"
48
+ accept_subscription_from(pres.from)
49
+ subscribe_to(pres.from)
50
+ end
51
+ end
52
+ end
53
+
54
+ def accept_subscription_from(jid)
55
+ p = Presence.new
56
+ p.type = "subscribed"
57
+ p.to=jid.scrap_resource
58
+ self.send(p)
59
+ end
60
+
61
+ def subscribe_to(jid)
62
+ p = Presence.new
63
+ p.type = "subscribe"
64
+ p.to = jid.scrap_resource
65
+ self.send(p)
66
+ end
67
+
68
+ def unsubscribe_from(jid)
69
+ iq = StropheRuby::Stanza.new
70
+ iq.name="iq"
71
+ iq.type="set"
72
+
73
+ query = StropheRuby::Stanza.new
74
+ query.name="query"
75
+ query.ns="jabber:iq:roster"
76
+
77
+ item = StropheRuby::Stanza.new
78
+ item.name="item"
79
+ item.set_attribute("jid",jid.scrap_resource)
80
+ item.set_attribute("subscription","remove")
81
+
82
+ query.add_child(item)
83
+ iq.add_child(query)
84
+ send_stanza(iq)
85
+ end
86
+
87
+ #Stop the event loop
88
+ def disconnect
89
+ StropheRuby::EventLoop.stop(@ctx)
90
+ end
91
+
92
+ #Send a message or presence object to the stream
93
+ def send(obj)
94
+ if obj.respond_to?(:stanza)
95
+ send_stanza(obj.stanza)
96
+ else
97
+ raise("Error: StropheRuby::Stanza object has not been set")
98
+ end
99
+ end
100
+
101
+ #You have to call this after a successful connection to notify everyone that you are online.
102
+ #This is called the "initial presence" (see 5.1.1 at http://xmpp.org/rfcs/rfc3921.html)
103
+ def announce_presence
104
+ presence = StropheRuby::Stanza.new
105
+ presence.name="presence"
106
+ presence.set_attribute("show", "available")
107
+ send_stanza(presence)
108
+ end
109
+
110
+ #callback for message stanzas. The parameter sent in the code block is the received Message object.
111
+ def on_message_received
112
+ @conn.add_handler("message") do |stanza|
113
+ yield(Message.new(stanza)) if Message.new(stanza).body
114
+ end
115
+ end
116
+
117
+ #callback for presence stanzas. The parameter sent in the code block is the received Presence object.
118
+ def on_presence_received
119
+ @conn.add_handler("presence") do |stanza|
120
+ yield(Presence.new(stanza))
121
+ end
122
+ end
123
+
124
+ private
125
+ #Internal method that send the actual StropheRuby::Stanza object to the stream
126
+ def send_stanza(stanza)
127
+ @conn.send(stanza)
128
+ @last_send=Time.now
129
+ end
130
+
131
+ #Signals to the xmpp server that we are still connected every X seconds
132
+ #TODO: Investigate if it really helps keeping the connection alive
133
+ def keep_alive
134
+ Thread.new do
135
+ loop do
136
+ difference = (@last_send || Time.now) + 90 - Time.now
137
+ if difference <= 0
138
+ announce_presence
139
+ sleep(90)
140
+ else
141
+ sleep(difference)
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,61 @@
1
+ ############################################################
2
+ # XMPPBot::Presence
3
+ # Simple wrapper for a StropheRuby::Stanza of type 'presence'
4
+ # Author : Francois Lamontagne
5
+ ############################################################
6
+
7
+ module XMPPBot
8
+ class Message
9
+ attr_reader :stanza
10
+ def initialize(stanza=nil)
11
+ if stanza
12
+ @stanza=stanza
13
+ else
14
+ @stanza=StropheRuby::Stanza.new
15
+ @stanza.name="message"
16
+ @stanza.type="chat"
17
+ end
18
+ end
19
+
20
+ def from
21
+ self.stanza.attribute("from") rescue nil
22
+ end
23
+
24
+ def from=(value)
25
+ self.stanza.set_attribute("from",value.to_s)
26
+ end
27
+
28
+ def type
29
+ self.stanza.type
30
+ end
31
+
32
+ def type=(type)
33
+ self.stanza.type=type
34
+ end
35
+
36
+ def body
37
+ self.stanza.child_by_name("body").text rescue nil
38
+ end
39
+
40
+ def body=(str)
41
+ children = self.stanza.children
42
+
43
+ if children
44
+ children.children.text = str
45
+ else
46
+ body_stanza = StropheRuby::Stanza.new
47
+ body_stanza.name="body"
48
+
49
+ text_stanza = StropheRuby::Stanza.new
50
+ text_stanza.text=str
51
+
52
+ body_stanza.add_child(text_stanza)
53
+ self.stanza.add_child(body_stanza)
54
+ end
55
+ end
56
+
57
+ def to=(to)
58
+ self.stanza.set_attribute("to",to)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,33 @@
1
+ #############################################################
2
+ # Some other StropheRuby wrappers
3
+ # Author : Francois Lamontagne
4
+ ############################################################
5
+
6
+ module XMPPBot
7
+ class ConnectionEvents
8
+ CONNECT = StropheRuby::ConnectionEvents::CONNECT
9
+ DISCONNECT = StropheRuby::ConnectionEvents::DISCONNECT
10
+ FAIL = StropheRuby::ConnectionEvents::FAIL
11
+ end
12
+
13
+ class Logging
14
+ INFO = StropheRuby::Logging::INFO
15
+ WARN = StropheRuby::Logging::WARN
16
+ ERROR = StropheRuby::Logging::ERROR
17
+ DEBUG = StropheRuby::Logging::DEBUG
18
+ end
19
+ end
20
+
21
+ class String
22
+ def scrap_resource
23
+ self.match(/[^\/]*/i).to_s
24
+ end
25
+
26
+ def resource
27
+ self.match(/\/.*/i).to_s.delete("/")
28
+ end
29
+
30
+ def node
31
+ self.match(/[^\@]*/i).to_s
32
+ end
33
+ end
@@ -0,0 +1,52 @@
1
+ ############################################################
2
+ # XMPPBot::Presence
3
+ # Simple wrapper for a StropheRuby::Stanza of type 'presence'
4
+ # Author : Francois Lamontagne
5
+ ############################################################
6
+
7
+ module XMPPBot
8
+ class Presence
9
+ attr_reader :stanza
10
+
11
+ def initialize(stanza=nil)
12
+ if stanza
13
+ @stanza=stanza
14
+ else
15
+ @stanza = StropheRuby::Stanza.new
16
+ @stanza.name = "presence"
17
+ end
18
+ end
19
+
20
+ def from
21
+ self.stanza.attribute("from")
22
+ end
23
+
24
+ def to
25
+ self.stanza.attribute("to")
26
+ end
27
+
28
+ def to=(to)
29
+ self.stanza.set_attribute("to",to)
30
+ end
31
+
32
+ def type
33
+ self.stanza.type
34
+ end
35
+
36
+ def type=(type)
37
+ self.stanza.type=type
38
+ end
39
+
40
+ def show
41
+ s=self.stanza.child_by_name("show")
42
+ s ? s.text : nil
43
+ end
44
+
45
+ #returns the show (away, dnd, chat,xa). if there is none, returns the type which can be : unavailable
46
+ #subscribe,subscribed,unsubscribe,unsubscribed,probe or error.
47
+ def to_s
48
+ res = self.show
49
+ res ? res : self.type.to_s
50
+ end
51
+ end
52
+ end
data/lib/xmppbot.rb ADDED
@@ -0,0 +1,11 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'strophe_ruby'
5
+ require 'xmppbot/bot'
6
+ require 'xmppbot/message'
7
+ require 'xmppbot/presence'
8
+ require 'xmppbot/other'
9
+ module XMPPBot
10
+ VERSION = '0.0.1'
11
+ end
data/script/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/xmppbot.rb'}"
9
+ puts "Loading xmppbot gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,3 @@
1
+ require 'stringio'
2
+ require 'test/unit'
3
+ require File.dirname(__FILE__) + '/../lib/xmppbot'
@@ -0,0 +1,11 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestXmppbot < Test::Unit::TestCase
4
+
5
+ def setup
6
+ end
7
+
8
+ def test_truth
9
+ assert true
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xmppbot
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - "Fran\xC3\xA7ois Lamontagne"
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-12-12 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: strophe_ruby
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.1
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: newgem
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.2.0
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: hoe
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.8.0
44
+ version:
45
+ description: "Simple implementation on top of StropheRuby(http://github.com/flamontagne/strophe_ruby/). It's for those who want to build simple xmpp bots quickly. It features only the essential : - auto accept subscriptions - callback for received messages - callback for received presences - a method to send messages and presences - That's it Warning : StropheRuby is very experimental at the moment. It is definitely NOT ready for production!"
46
+ email:
47
+ - flamontagne@gmail.com
48
+ executables: []
49
+
50
+ extensions: []
51
+
52
+ extra_rdoc_files:
53
+ - History.txt
54
+ - Manifest.txt
55
+ - PostInstall.txt
56
+ - README.rdoc
57
+ files:
58
+ - History.txt
59
+ - Manifest.txt
60
+ - PostInstall.txt
61
+ - README.rdoc
62
+ - Rakefile
63
+ - lib/xmppbot.rb
64
+ - lib/xmppbot/bot.rb
65
+ - lib/xmppbot/message.rb
66
+ - lib/xmppbot/other.rb
67
+ - lib/xmppbot/presence.rb
68
+ - script/console
69
+ - script/destroy
70
+ - script/generate
71
+ - test/test_helper.rb
72
+ - test/test_xmppbot.rb
73
+ has_rdoc: true
74
+ homepage:
75
+ post_install_message: PostInstall.txt
76
+ rdoc_options:
77
+ - --main
78
+ - README.rdoc
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: "0"
86
+ version:
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: "0"
92
+ version:
93
+ requirements: []
94
+
95
+ rubyforge_project: xmppbot
96
+ rubygems_version: 1.3.1
97
+ signing_key:
98
+ specification_version: 2
99
+ summary: Simple implementation on top of StropheRuby(http://github.com/flamontagne/strophe_ruby/)
100
+ test_files:
101
+ - test/test_helper.rb
102
+ - test/test_xmppbot.rb