xmppbot 0.0.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/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