cerberus 0.6 → 0.7
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/Authors.txt +4 -0
- data/Changelog.txt +11 -0
- data/Copyright.txt +16 -0
- data/Rakefile +16 -25
- data/Readme.markdown +1 -3
- data/bin/cerberus +5 -0
- data/lib/cerberus/builder/bjam.rb +1 -3
- data/lib/cerberus/builder/maven2.rb +0 -1
- data/lib/cerberus/builder/rake.rb +1 -1
- data/lib/cerberus/builder/rspec.rb +0 -1
- data/lib/cerberus/builder/ruby_base.rb +0 -1
- data/lib/cerberus/component_lazy_loader.rb +6 -2
- data/lib/cerberus/config.example.yml +1 -0
- data/lib/cerberus/constants.rb +2 -2
- data/lib/cerberus/manager.rb +7 -1
- data/lib/cerberus/publisher/mail.rb +4 -4
- data/lib/cerberus/publisher/twitter.rb +0 -1
- data/lib/cerberus/scm/base.rb +19 -0
- data/lib/cerberus/scm/bzr.rb +62 -0
- data/lib/cerberus/scm/cvs.rb +2 -7
- data/lib/cerberus/scm/darcs.rb +2 -11
- data/lib/cerberus/scm/git.rb +6 -14
- data/lib/cerberus/scm/perforce.rb +4 -4
- data/lib/cerberus/scm/svn.rb +2 -7
- data/lib/cerberus/utils.rb +5 -0
- data/lib/vendor/irc/README +23 -0
- data/lib/vendor/irc/lib/IRC.rb +164 -0
- data/lib/vendor/irc/lib/IRCChannel.rb +33 -0
- data/lib/vendor/irc/lib/IRCConnection.rb +134 -0
- data/lib/vendor/irc/lib/IRCEvent.rb +91 -0
- data/lib/vendor/irc/lib/IRCUser.rb +23 -0
- data/lib/vendor/irc/lib/IRCUtil.rb +49 -0
- data/lib/vendor/irc/lib/eventmap.yml +247 -0
- data/lib/vendor/twitter/CHANGES +129 -0
- data/lib/vendor/twitter/MIT-LICENSE +20 -0
- data/lib/vendor/twitter/README +37 -0
- data/lib/vendor/twitter/TODO +7 -0
- data/lib/vendor/twitter/lib/twitter.rb +34 -0
- data/lib/vendor/twitter/lib/twitter/client.rb +24 -0
- data/lib/vendor/twitter/lib/twitter/client/account.rb +24 -0
- data/lib/vendor/twitter/lib/twitter/client/auth.rb +27 -0
- data/lib/vendor/twitter/lib/twitter/client/base.rb +93 -0
- data/lib/vendor/twitter/lib/twitter/client/blocks.rb +35 -0
- data/lib/vendor/twitter/lib/twitter/client/favorites.rb +53 -0
- data/lib/vendor/twitter/lib/twitter/client/friendship.rb +35 -0
- data/lib/vendor/twitter/lib/twitter/client/graph.rb +37 -0
- data/lib/vendor/twitter/lib/twitter/client/messaging.rb +79 -0
- data/lib/vendor/twitter/lib/twitter/client/profile.rb +29 -0
- data/lib/vendor/twitter/lib/twitter/client/search.rb +27 -0
- data/lib/vendor/twitter/lib/twitter/client/status.rb +51 -0
- data/lib/vendor/twitter/lib/twitter/client/timeline.rb +72 -0
- data/lib/vendor/twitter/lib/twitter/client/user.rb +65 -0
- data/lib/vendor/twitter/lib/twitter/config.rb +77 -0
- data/lib/vendor/twitter/lib/twitter/console.rb +31 -0
- data/lib/vendor/twitter/lib/twitter/core.rb +137 -0
- data/lib/vendor/twitter/lib/twitter/ext.rb +2 -0
- data/lib/vendor/twitter/lib/twitter/ext/stdlib.rb +52 -0
- data/lib/vendor/twitter/lib/twitter/extras.rb +39 -0
- data/lib/vendor/twitter/lib/twitter/meta.rb +56 -0
- data/lib/vendor/twitter/lib/twitter/model.rb +360 -0
- data/lib/vendor/twitter/lib/twitter/version.rb +19 -0
- data/lib/vendor/twitter/spec/twitter/client/account_spec.rb +28 -0
- data/lib/vendor/twitter/spec/twitter/client/auth_spec.rb +34 -0
- data/lib/vendor/twitter/spec/twitter/client/base_spec.rb +242 -0
- data/lib/vendor/twitter/spec/twitter/client/blocks_spec.rb +76 -0
- data/lib/vendor/twitter/spec/twitter/client/favorites_spec.rb +183 -0
- data/lib/vendor/twitter/spec/twitter/client/friendship_spec.rb +76 -0
- data/lib/vendor/twitter/spec/twitter/client/graph_spec.rb +67 -0
- data/lib/vendor/twitter/spec/twitter/client/messaging_spec.rb +135 -0
- data/lib/vendor/twitter/spec/twitter/client/profile_spec.rb +91 -0
- data/lib/vendor/twitter/spec/twitter/client/search_spec.rb +68 -0
- data/lib/vendor/twitter/spec/twitter/client/status_spec.rb +119 -0
- data/lib/vendor/twitter/spec/twitter/client/timeline_spec.rb +79 -0
- data/lib/vendor/twitter/spec/twitter/client/user_spec.rb +203 -0
- data/lib/vendor/twitter/spec/twitter/client_spec.rb +2 -0
- data/lib/vendor/twitter/spec/twitter/config_spec.rb +86 -0
- data/lib/vendor/twitter/spec/twitter/console_spec.rb +15 -0
- data/lib/vendor/twitter/spec/twitter/core_spec.rb +127 -0
- data/lib/vendor/twitter/spec/twitter/ext/stdlib_spec.rb +59 -0
- data/lib/vendor/twitter/spec/twitter/extras_spec.rb +46 -0
- data/lib/vendor/twitter/spec/twitter/meta_spec.rb +90 -0
- data/lib/vendor/twitter/spec/twitter/model_spec.rb +508 -0
- data/lib/vendor/twitter/spec/twitter/version_spec.rb +19 -0
- data/lib/vendor/xmpp4r/CHANGELOG +83 -0
- data/lib/vendor/xmpp4r/COPYING +340 -0
- data/lib/vendor/xmpp4r/LICENSE +59 -0
- data/lib/vendor/xmpp4r/README.rdoc +110 -0
- data/lib/vendor/xmpp4r/README_ruby19.txt +43 -0
- data/lib/vendor/xmpp4r/Rakefile +262 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/adventure/README +56 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/adventure/adventure.rb +23 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/adventure/adventuremuc.rb +136 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/adventure/cube.xml +15 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/adventure/tower.xml +69 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/adventure/world.rb +424 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/fileserve.conf +11 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/fileserve.rb +346 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/getonline.rb +56 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/gtkmucclient.rb +315 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/migrate.rb +88 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/minimuc.rb +266 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/pep-aggregator/index.xsl +235 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/pep-aggregator/pep-aggregator.rb +147 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/recvfile.rb +84 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/rosterdiscovery.rb +129 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/sendfile.conf +10 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/sendfile.rb +72 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/shellmgr/shellmgr.rb +51 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/shellmgr/shellmgr_jabber.rb +43 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/shellmgr/shellmgr_test.rb +10 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/versionpoll.rb +90 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/xmpping.rb +146 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/advanced/xmppingrc.sample +14 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/change_password.rb +41 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/client.rb +70 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/component.rb +11 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/echo.rb +37 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/jabbersend.rb +41 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/mass_sender.rb +68 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/muc_owner_config.rb +12 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/mucinfo.rb +41 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/mucsimplebot.rb +82 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/register.rb +42 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/remove_registration.rb +18 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/roster.rb +44 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/rosterprint.rb +50 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/rosterrename.rb +34 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/rosterwatch.rb +171 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/send_vcard.rb +67 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/tune_client.rb +56 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/tune_server.rb +58 -0
- data/lib/vendor/xmpp4r/data/doc/xmpp4r/examples/basic/versionbot.rb +75 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r.rb +116 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/base64.rb +32 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams.rb +15 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/helper/filetransfer.rb +319 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/helper/ibb/base.rb +257 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/helper/ibb/initiator.rb +31 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/helper/ibb/target.rb +47 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb +152 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/helper/socks5bytestreams/initiator.rb +86 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb +198 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/helper/socks5bytestreams/socks5.rb +65 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.rb +73 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.rb.orig +62 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/iq/bytestreams.rb +170 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/bytestreams/iq/si.rb +206 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/callbacks.rb +124 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/caps.rb +1 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/caps/c.rb +53 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/caps/helper/generator.rb +160 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/caps/helper/helper.rb +87 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/client.rb +317 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/command/helper/responder.rb +53 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/command/iq/command.rb +154 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/component.rb +103 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/connection.rb +219 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/dataforms.rb +5 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/dataforms/x/data.rb +297 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/debuglog.rb +42 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/delay.rb +5 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/delay/x/delay.rb +99 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/discovery.rb +7 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/discovery/helper/responder.rb +165 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/discovery/iq/discoinfo.rb +211 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/discovery/iq/discoitems.rb +147 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/errors.rb +281 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/feature_negotiation.rb +5 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/feature_negotiation/iq/feature.rb +28 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/framework/base.rb +55 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/framework/bot.rb +148 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/httpbinding.rb +5 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/httpbinding/client.rb +285 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/idgenerator.rb +37 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/iq.rb +221 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/jid.rb +167 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/message.rb +148 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/muc.rb +14 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/muc/helper/mucbrowser.rb +92 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/muc/helper/mucclient.rb +462 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/muc/helper/simplemucclient.rb +332 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/muc/iq/mucadmin.rb +23 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/muc/iq/mucadminitem.rb +20 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/muc/iq/mucowner.rb +15 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/muc/item.rb +143 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/muc/x/muc.rb +70 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/muc/x/mucuserinvite.rb +60 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/muc/x/mucuseritem.rb +36 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/presence.rb +232 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub.rb +8 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/children/configuration.rb +86 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/children/event.rb +49 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/children/item.rb +35 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/children/items.rb +44 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/children/node_config.rb +48 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/children/publish.rb +24 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/children/subscription.rb +62 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/children/subscription_config.rb +67 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/children/unsubscribe.rb +48 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/helper/nodebrowser.rb +130 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/helper/nodehelper.rb +156 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/helper/servicehelper.rb +417 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/pubsub/iq/pubsub.rb +19 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/query.rb +15 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/rexmladdons.rb +151 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/roster.rb +7 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/roster/helper/roster.rb +519 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/roster/iq/roster.rb +215 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/roster/x/roster.rb +138 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/rpc.rb +2 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/rpc/helper/client.rb +123 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/rpc/helper/server.rb +74 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/rpc/helper/xmlrpcaddons.rb +67 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/rpc/iq/rpc.rb +23 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/sasl.rb +237 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/semaphore.rb +38 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/stream.rb +497 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/streamparser.rb +77 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/tune.rb +2 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/tune/helper/helper.rb +58 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/tune/tune.rb +113 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/vcard.rb +6 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/vcard/helper/vcard.rb +84 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/vcard/iq/vcard.rb +109 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/version.rb +7 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/version/helper/responder.rb +72 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/version/helper/simpleresponder.rb +44 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/version/iq/version.rb +105 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/x.rb +37 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/xhtml.rb +1 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/xhtml/html.rb +115 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/xmpp4r.rb +18 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/xmppelement.rb +168 -0
- data/lib/vendor/xmpp4r/lib/xmpp4r/xmppstanza.rb +162 -0
- data/lib/vendor/xmpp4r/setup.rb +1586 -0
- data/lib/vendor/xmpp4r/test/bytestreams/tc_ibb.rb +186 -0
- data/lib/vendor/xmpp4r/test/bytestreams/tc_socks5bytestreams.rb +113 -0
- data/lib/vendor/xmpp4r/test/caps/tc_helper.rb +156 -0
- data/lib/vendor/xmpp4r/test/dataforms/tc_data.rb +81 -0
- data/lib/vendor/xmpp4r/test/delay/tc_xdelay.rb +51 -0
- data/lib/vendor/xmpp4r/test/discovery/tc_responder.rb +91 -0
- data/lib/vendor/xmpp4r/test/lib/assert_equal_xml.rb +14 -0
- data/lib/vendor/xmpp4r/test/lib/clienttester.rb +120 -0
- data/lib/vendor/xmpp4r/test/muc/tc_muc_mucclient.rb +830 -0
- data/lib/vendor/xmpp4r/test/muc/tc_muc_simplemucclient.rb +114 -0
- data/lib/vendor/xmpp4r/test/muc/tc_mucowner.rb +50 -0
- data/lib/vendor/xmpp4r/test/pubsub/tc_helper.rb +662 -0
- data/lib/vendor/xmpp4r/test/pubsub/tc_nodeconfig.rb +54 -0
- data/lib/vendor/xmpp4r/test/pubsub/tc_subscriptionconfig.rb +41 -0
- data/lib/vendor/xmpp4r/test/roster/tc_helper.rb +514 -0
- data/lib/vendor/xmpp4r/test/roster/tc_iqqueryroster.rb +173 -0
- data/lib/vendor/xmpp4r/test/roster/tc_xroster.rb +73 -0
- data/lib/vendor/xmpp4r/test/rpc/tc_helper.rb +96 -0
- data/lib/vendor/xmpp4r/test/tc_callbacks.rb +129 -0
- data/lib/vendor/xmpp4r/test/tc_class_names.rb +146 -0
- data/lib/vendor/xmpp4r/test/tc_client.rb +30 -0
- data/lib/vendor/xmpp4r/test/tc_errors.rb +146 -0
- data/lib/vendor/xmpp4r/test/tc_idgenerator.rb +30 -0
- data/lib/vendor/xmpp4r/test/tc_iq.rb +113 -0
- data/lib/vendor/xmpp4r/test/tc_iqquery.rb +31 -0
- data/lib/vendor/xmpp4r/test/tc_jid.rb +204 -0
- data/lib/vendor/xmpp4r/test/tc_message.rb +116 -0
- data/lib/vendor/xmpp4r/test/tc_presence.rb +150 -0
- data/lib/vendor/xmpp4r/test/tc_rexml.rb +139 -0
- data/lib/vendor/xmpp4r/test/tc_stream.rb +229 -0
- data/lib/vendor/xmpp4r/test/tc_streamComponent.rb +95 -0
- data/lib/vendor/xmpp4r/test/tc_streamError.rb +131 -0
- data/lib/vendor/xmpp4r/test/tc_streamSend.rb +59 -0
- data/lib/vendor/xmpp4r/test/tc_streamparser.rb +112 -0
- data/lib/vendor/xmpp4r/test/tc_xmppstanza.rb +135 -0
- data/lib/vendor/xmpp4r/test/ts_xmpp4r.rb +53 -0
- data/lib/vendor/xmpp4r/test/tune/tc_helper_recv.rb +84 -0
- data/lib/vendor/xmpp4r/test/tune/tc_helper_send.rb +74 -0
- data/lib/vendor/xmpp4r/test/tune/tc_tune.rb +79 -0
- data/lib/vendor/xmpp4r/test/vcard/tc_helper.rb +49 -0
- data/lib/vendor/xmpp4r/test/vcard/tc_iqvcard.rb +62 -0
- data/lib/vendor/xmpp4r/test/version/tc_helper.rb +60 -0
- data/lib/vendor/xmpp4r/test/version/tc_iqqueryversion.rb +97 -0
- data/lib/vendor/xmpp4r/test/xhtml/tc_html.rb +41 -0
- data/lib/vendor/xmpp4r/tools/gen_requires.bash +31 -0
- data/lib/vendor/xmpp4r/tools/xmpp4r-gemspec-test.rb +11 -0
- data/lib/vendor/xmpp4r/xmpp4r.gemspec +291 -0
- data/test/jabber_publisher_test.rb +1 -1
- data/test/mail_publisher_test.rb +2 -2
- data/test/mock/twitter.rb +0 -1
- data/test/rspec_builder_test.rb +39 -2
- data/test/rss_publisher_test.rb +1 -1
- data/test/twitter_publisher_test.rb +1 -1
- metadata +268 -53
- data/lib/cerberus/publisher/gmailer.rb +0 -17
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# =XMPP4R - XMPP Library for Ruby
|
|
2
|
+
# License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
|
|
3
|
+
# Website::http://home.gna.org/xmpp4r/
|
|
4
|
+
|
|
5
|
+
module Jabber
|
|
6
|
+
##
|
|
7
|
+
# The JID class represents a Jabber Identifier as described by
|
|
8
|
+
# RFC3920 section 3.1.
|
|
9
|
+
#
|
|
10
|
+
# Note that you can use JIDs also for Sorting, Hash keys, ...
|
|
11
|
+
class JID
|
|
12
|
+
include Comparable
|
|
13
|
+
|
|
14
|
+
PATTERN = /^(?:([^@]*)@)??([^@\/]*)(?:\/(.*?))?$/
|
|
15
|
+
|
|
16
|
+
begin
|
|
17
|
+
require 'idn'
|
|
18
|
+
USE_STRINGPREP = true
|
|
19
|
+
rescue LoadError
|
|
20
|
+
USE_STRINGPREP = false
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
##
|
|
24
|
+
# Create a new JID. If called as new('a@b/c'), parse the string and
|
|
25
|
+
# split (node, domain, resource)
|
|
26
|
+
def initialize(node = "", domain = nil, resource = nil)
|
|
27
|
+
@resource = resource
|
|
28
|
+
@domain = domain
|
|
29
|
+
@node = node
|
|
30
|
+
if @domain.nil? and @resource.nil? and @node
|
|
31
|
+
@node, @domain, @resource = @node.to_s.scan(PATTERN).first
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
if USE_STRINGPREP
|
|
35
|
+
@node = IDN::Stringprep.nodeprep(@node) if @node
|
|
36
|
+
@domain = IDN::Stringprep.nameprep(@domain) if @domain
|
|
37
|
+
@resource = IDN::Stringprep.resourceprep(@resource) if @resource
|
|
38
|
+
else
|
|
39
|
+
@node.downcase! if @node
|
|
40
|
+
@domain.downcase! if @domain
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
raise ArgumentError, 'Node too long' if (@node || '').length > 1023
|
|
44
|
+
raise ArgumentError, 'Domain too long' if (@domain || '').length > 1023
|
|
45
|
+
raise ArgumentError, 'Resource too long' if (@resource || '').length > 1023
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
##
|
|
49
|
+
# Returns a string representation of the JID
|
|
50
|
+
# * ""
|
|
51
|
+
# * "domain"
|
|
52
|
+
# * "node@domain"
|
|
53
|
+
# * "domain/resource"
|
|
54
|
+
# * "node@domain/resource"
|
|
55
|
+
def to_s
|
|
56
|
+
s = @domain
|
|
57
|
+
s = "#{@node}@#{s}" if @node
|
|
58
|
+
s += "/#{@resource}" if @resource
|
|
59
|
+
return s
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
##
|
|
63
|
+
# Returns a new JID with resource removed.
|
|
64
|
+
# return:: [JID]
|
|
65
|
+
def strip
|
|
66
|
+
JID.new(@node, @domain)
|
|
67
|
+
end
|
|
68
|
+
alias_method :bare, :strip
|
|
69
|
+
|
|
70
|
+
##
|
|
71
|
+
# Removes the resource (sets it to nil)
|
|
72
|
+
# return:: [JID] self
|
|
73
|
+
def strip!
|
|
74
|
+
@resource = nil
|
|
75
|
+
self
|
|
76
|
+
end
|
|
77
|
+
alias_method :bare!, :strip!
|
|
78
|
+
|
|
79
|
+
##
|
|
80
|
+
# Returns a hash value of the String representation
|
|
81
|
+
# (see JID#to_s)
|
|
82
|
+
def hash
|
|
83
|
+
return to_s.hash
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
##
|
|
87
|
+
# Ccompare to another JID
|
|
88
|
+
#
|
|
89
|
+
# String representations are compared, see JID#to_s
|
|
90
|
+
def eql?(o)
|
|
91
|
+
to_s.eql?(o.to_s)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
##
|
|
95
|
+
# Ccompare to another JID
|
|
96
|
+
#
|
|
97
|
+
# String representations are compared, see JID#to_s
|
|
98
|
+
def ==(o)
|
|
99
|
+
to_s == o.to_s
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
##
|
|
103
|
+
# Compare two JIDs,
|
|
104
|
+
# helpful for sorting etc.
|
|
105
|
+
#
|
|
106
|
+
# String representations are compared, see JID#to_s
|
|
107
|
+
def <=>(o)
|
|
108
|
+
to_s <=> o.to_s
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Get the JID's node
|
|
112
|
+
def node
|
|
113
|
+
@node
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Set the JID's node
|
|
117
|
+
def node=(v)
|
|
118
|
+
@node = v.to_s
|
|
119
|
+
if USE_STRINGPREP
|
|
120
|
+
@node = IDN::Stringprep.nodeprep(@node) if @node
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Get the JID's domain
|
|
125
|
+
def domain
|
|
126
|
+
return nil if @domain.empty?
|
|
127
|
+
@domain
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Set the JID's domain
|
|
131
|
+
def domain=(v)
|
|
132
|
+
@domain = v.to_s
|
|
133
|
+
if USE_STRINGPREP
|
|
134
|
+
@domain = IDN::Stringprep.nodeprep(@domain)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Get the JID's resource
|
|
139
|
+
def resource
|
|
140
|
+
@resource
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Set the JID's resource
|
|
144
|
+
def resource=(v)
|
|
145
|
+
@resource = v.to_s
|
|
146
|
+
if USE_STRINGPREP
|
|
147
|
+
@resource = IDN::Stringprep.nodeprep(@resource)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Escape JID
|
|
152
|
+
def JID::escape(jid)
|
|
153
|
+
return jid.to_s.gsub('@', '%')
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Test if jid is empty
|
|
157
|
+
def empty?
|
|
158
|
+
to_s.empty?
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Test id jid is strepped
|
|
162
|
+
def stripped?
|
|
163
|
+
@resource.nil?
|
|
164
|
+
end
|
|
165
|
+
alias_method :bared?, :stripped?
|
|
166
|
+
end
|
|
167
|
+
end
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# =XMPP4R - XMPP Library for Ruby
|
|
2
|
+
# License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
|
|
3
|
+
# Website::http://home.gna.org/xmpp4r/
|
|
4
|
+
|
|
5
|
+
require 'xmpp4r/xmppstanza'
|
|
6
|
+
require 'xmpp4r/x'
|
|
7
|
+
|
|
8
|
+
module Jabber
|
|
9
|
+
##
|
|
10
|
+
# The Message class manages the <message/> stanzas,
|
|
11
|
+
# which is used for all messaging communication.
|
|
12
|
+
class Message < XMPPStanza
|
|
13
|
+
|
|
14
|
+
name_xmlns 'message', 'jabber:client'
|
|
15
|
+
force_xmlns true
|
|
16
|
+
|
|
17
|
+
include XParent
|
|
18
|
+
|
|
19
|
+
##
|
|
20
|
+
# Create a new message
|
|
21
|
+
# >to:: a JID or a String object to send the message to.
|
|
22
|
+
# >body:: the message's body
|
|
23
|
+
def initialize(to = nil, body = nil)
|
|
24
|
+
super()
|
|
25
|
+
if not to.nil?
|
|
26
|
+
set_to(to)
|
|
27
|
+
end
|
|
28
|
+
if !body.nil?
|
|
29
|
+
add_element(REXML::Element.new("body").add_text(body))
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
##
|
|
34
|
+
# Get the type of the Message stanza
|
|
35
|
+
#
|
|
36
|
+
# The following Symbols are allowed:
|
|
37
|
+
# * :chat
|
|
38
|
+
# * :error
|
|
39
|
+
# * :groupchat
|
|
40
|
+
# * :headline
|
|
41
|
+
# * :normal
|
|
42
|
+
# result:: [Symbol] or nil
|
|
43
|
+
def type
|
|
44
|
+
case super
|
|
45
|
+
when 'chat' then :chat
|
|
46
|
+
when 'error' then :error
|
|
47
|
+
when 'groupchat' then :groupchat
|
|
48
|
+
when 'headline' then :headline
|
|
49
|
+
when 'normal' then :normal
|
|
50
|
+
else nil
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
##
|
|
55
|
+
# Set the type of the Message stanza (see Message#type for details)
|
|
56
|
+
# v:: [Symbol] or nil
|
|
57
|
+
def type=(v)
|
|
58
|
+
case v
|
|
59
|
+
when :chat then super('chat')
|
|
60
|
+
when :error then super('error')
|
|
61
|
+
when :groupchat then super('groupchat')
|
|
62
|
+
when :headline then super('headline')
|
|
63
|
+
when :normal then super('normal')
|
|
64
|
+
else super(nil)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
##
|
|
69
|
+
# Set the type of the Message stanza (chaining-friendly)
|
|
70
|
+
# v:: [Symbol] or nil
|
|
71
|
+
def set_type(v)
|
|
72
|
+
self.type = v
|
|
73
|
+
self
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
##
|
|
77
|
+
# Returns the message's body, or nil.
|
|
78
|
+
# This is the message's plain-text content.
|
|
79
|
+
def body
|
|
80
|
+
first_element_text('body')
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
##
|
|
84
|
+
# Sets the message's body
|
|
85
|
+
#
|
|
86
|
+
# b:: [String] body to set
|
|
87
|
+
def body=(b)
|
|
88
|
+
replace_element_text('body', b)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
##
|
|
92
|
+
# Sets the message's body
|
|
93
|
+
#
|
|
94
|
+
# b:: [String] body to set
|
|
95
|
+
# return:: [REXML::Element] self for chaining
|
|
96
|
+
def set_body(b)
|
|
97
|
+
self.body = b
|
|
98
|
+
self
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
##
|
|
102
|
+
# sets the message's subject
|
|
103
|
+
#
|
|
104
|
+
# s:: [String] subject to set
|
|
105
|
+
def subject=(s)
|
|
106
|
+
replace_element_text('subject', s)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
##
|
|
110
|
+
# sets the message's subject
|
|
111
|
+
#
|
|
112
|
+
# s:: [String] subject to set
|
|
113
|
+
# return:: [REXML::Element] self for chaining
|
|
114
|
+
def set_subject(s)
|
|
115
|
+
self.subject = s
|
|
116
|
+
self
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
##
|
|
120
|
+
# Returns the message's subject, or nil
|
|
121
|
+
def subject
|
|
122
|
+
first_element_text('subject')
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
##
|
|
126
|
+
# sets the message's thread
|
|
127
|
+
# s:: [String] thread to set
|
|
128
|
+
def thread=(s)
|
|
129
|
+
delete_elements('thread')
|
|
130
|
+
replace_element_text('thread', s) unless s.nil?
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
##
|
|
134
|
+
# gets the message's thread (chaining-friendly)
|
|
135
|
+
# Please note that this are not [Thread] but a [String]-Identifier to track conversations
|
|
136
|
+
# s:: [String] thread to set
|
|
137
|
+
def set_thread(s)
|
|
138
|
+
self.thread = s
|
|
139
|
+
self
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
##
|
|
143
|
+
# Returns the message's thread, or nil
|
|
144
|
+
def thread
|
|
145
|
+
first_element_text('thread')
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# =XMPP4R - XMPP Library for Ruby
|
|
2
|
+
# License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
|
|
3
|
+
# Website::http://home.gna.org/xmpp4r/
|
|
4
|
+
|
|
5
|
+
require 'xmpp4r/dataforms'
|
|
6
|
+
require 'xmpp4r/muc/x/muc'
|
|
7
|
+
require 'xmpp4r/muc/x/mucuserinvite'
|
|
8
|
+
require 'xmpp4r/muc/x/mucuseritem'
|
|
9
|
+
require 'xmpp4r/muc/iq/mucowner'
|
|
10
|
+
require 'xmpp4r/muc/iq/mucadmin'
|
|
11
|
+
require 'xmpp4r/muc/iq/mucadminitem'
|
|
12
|
+
require 'xmpp4r/muc/helper/mucbrowser'
|
|
13
|
+
require 'xmpp4r/muc/helper/mucclient'
|
|
14
|
+
require 'xmpp4r/muc/helper/simplemucclient'
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# =XMPP4R - XMPP Library for Ruby
|
|
2
|
+
# License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
|
|
3
|
+
# Website::http://home.gna.org/xmpp4r/
|
|
4
|
+
|
|
5
|
+
require 'xmpp4r/discovery'
|
|
6
|
+
|
|
7
|
+
module Jabber
|
|
8
|
+
module MUC
|
|
9
|
+
##
|
|
10
|
+
# The MUCBrowser helper can be used to discover
|
|
11
|
+
# Multi-User-Chat components via Service Discovery
|
|
12
|
+
#
|
|
13
|
+
# See JEP 0045 sections 6.1. and 6.2.
|
|
14
|
+
#
|
|
15
|
+
# Usage of its functions should be threaded as
|
|
16
|
+
# responses can take a while
|
|
17
|
+
class MUCBrowser
|
|
18
|
+
##
|
|
19
|
+
# Initialize a new MUCBrowser helper
|
|
20
|
+
def initialize(stream)
|
|
21
|
+
@stream = stream
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
##
|
|
25
|
+
# Retrieve the name of a MUC component,
|
|
26
|
+
# depending upon whether the target entity supports
|
|
27
|
+
# the MUC protocol.
|
|
28
|
+
#
|
|
29
|
+
# A return-value of nil does *not* mean that the entity
|
|
30
|
+
# does not exist or does not support Service Discovery!
|
|
31
|
+
# nil just means that this is not a MUC-compliant service.
|
|
32
|
+
#
|
|
33
|
+
# Throws an ServerError when receiving
|
|
34
|
+
# <tt><iq type='error'/></tt>
|
|
35
|
+
# jid:: [JID] Target entity (set only domain!)
|
|
36
|
+
# return:: [String] or [nil]
|
|
37
|
+
def muc_name(jid)
|
|
38
|
+
iq = Iq.new(:get, jid)
|
|
39
|
+
iq.from = @stream.jid # Enable components to use this
|
|
40
|
+
iq.add(Discovery::IqQueryDiscoInfo.new)
|
|
41
|
+
|
|
42
|
+
res = nil
|
|
43
|
+
|
|
44
|
+
@stream.send_with_id(iq) do |answer|
|
|
45
|
+
if answer.type == :result
|
|
46
|
+
answer.query.each_element('feature') { |feature|
|
|
47
|
+
# Look if the component has a MUC or Groupchat feature
|
|
48
|
+
if feature.var == 'http://jabber.org/protocol/muc' or feature.var == 'gc-1.0'
|
|
49
|
+
# If so, get the identity
|
|
50
|
+
if answer.query.first_element('identity')
|
|
51
|
+
res = answer.query.first_element('identity').iname
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
}
|
|
55
|
+
true
|
|
56
|
+
else
|
|
57
|
+
false
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
res
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
##
|
|
65
|
+
# Retrieve the existing rooms of a MUC component
|
|
66
|
+
#
|
|
67
|
+
# The resulting Hash contains pairs of room JID and room name
|
|
68
|
+
#
|
|
69
|
+
# Usage:
|
|
70
|
+
# my_mucbrowse_helper.muc_rooms('conference.jabber.org').each { |jid,name| ... }
|
|
71
|
+
#
|
|
72
|
+
# Throws an exception when receiving <tt><iq type='error'/></tt>
|
|
73
|
+
# jid:: [JID] Target entity (set only domain!)
|
|
74
|
+
# return:: [Hash]
|
|
75
|
+
def muc_rooms(jid)
|
|
76
|
+
iq = Iq.new(:get, jid)
|
|
77
|
+
iq.from = @stream.jid # Enable components to use this
|
|
78
|
+
iq.add(Discovery::IqQueryDiscoItems.new)
|
|
79
|
+
|
|
80
|
+
rooms = {}
|
|
81
|
+
|
|
82
|
+
@stream.send_with_id(iq) do |answer|
|
|
83
|
+
answer.query.each_element('item') { |item|
|
|
84
|
+
rooms[item.jid] = item.iname
|
|
85
|
+
}
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
rooms
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
# =XMPP4R - XMPP Library for Ruby
|
|
2
|
+
# License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
|
|
3
|
+
# Website::http://home.gna.org/xmpp4r/
|
|
4
|
+
|
|
5
|
+
require 'xmpp4r/muc/x/muc'
|
|
6
|
+
require 'xmpp4r/muc/iq/mucowner'
|
|
7
|
+
require 'xmpp4r/muc/iq/mucadmin'
|
|
8
|
+
require 'xmpp4r/dataforms'
|
|
9
|
+
|
|
10
|
+
module Jabber
|
|
11
|
+
module MUC
|
|
12
|
+
##
|
|
13
|
+
# The MUCClient Helper handles low-level stuff of the
|
|
14
|
+
# Multi-User Chat (JEP 0045).
|
|
15
|
+
#
|
|
16
|
+
# Use one instance per room.
|
|
17
|
+
#
|
|
18
|
+
# Note that one client cannot join a single room multiple
|
|
19
|
+
# times. At least the clients' resources must be different.
|
|
20
|
+
# This is a protocol design issue. But don't consider it as
|
|
21
|
+
# a bug, it is just a clone-preventing feature.
|
|
22
|
+
class MUCClient
|
|
23
|
+
##
|
|
24
|
+
# Sender JID, set this to use MUCClient from Components
|
|
25
|
+
# my_jid:: [JID] Defaults to nil
|
|
26
|
+
attr_accessor :my_jid
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
# MUC room roster
|
|
30
|
+
# roster:: [Hash] of [String] Nick => [Presence]
|
|
31
|
+
attr_reader :roster
|
|
32
|
+
|
|
33
|
+
##
|
|
34
|
+
# MUC JID
|
|
35
|
+
# jid:: [JID] room@component/nick
|
|
36
|
+
attr_reader :jid
|
|
37
|
+
|
|
38
|
+
##
|
|
39
|
+
# Initialize a MUCClient
|
|
40
|
+
#
|
|
41
|
+
# Call MUCClient#join *after* you have registered your
|
|
42
|
+
# callbacks to avoid reception of stanzas after joining
|
|
43
|
+
# and before registration of callbacks.
|
|
44
|
+
# stream:: [Stream] to operate on
|
|
45
|
+
def initialize(stream)
|
|
46
|
+
# Attributes initialization
|
|
47
|
+
@stream = stream
|
|
48
|
+
@my_jid = nil
|
|
49
|
+
@jid = nil
|
|
50
|
+
@roster = {}
|
|
51
|
+
@roster_lock = Mutex.new
|
|
52
|
+
|
|
53
|
+
@active = false
|
|
54
|
+
|
|
55
|
+
@join_cbs = CallbackList.new
|
|
56
|
+
@leave_cbs = CallbackList.new
|
|
57
|
+
@presence_cbs = CallbackList.new
|
|
58
|
+
@message_cbs = CallbackList.new
|
|
59
|
+
@private_message_cbs = CallbackList.new
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
##
|
|
63
|
+
# Join a room
|
|
64
|
+
#
|
|
65
|
+
# This registers its own callbacks on the stream
|
|
66
|
+
# provided to initialize and sends initial presence
|
|
67
|
+
# to the room. May throw ServerError if joining
|
|
68
|
+
# fails.
|
|
69
|
+
# jid:: [JID] room@component/nick
|
|
70
|
+
# password:: [String] Optional password
|
|
71
|
+
# return:: [MUCClient] self (chain-able)
|
|
72
|
+
def join(jid, password=nil)
|
|
73
|
+
if active?
|
|
74
|
+
raise "MUCClient already active"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
@jid = (jid.kind_of?(JID) ? jid : JID.new(jid))
|
|
78
|
+
activate
|
|
79
|
+
|
|
80
|
+
# Joining
|
|
81
|
+
pres = Presence.new
|
|
82
|
+
pres.to = @jid
|
|
83
|
+
pres.from = @my_jid
|
|
84
|
+
xmuc = XMUC.new
|
|
85
|
+
xmuc.password = password
|
|
86
|
+
pres.add(xmuc)
|
|
87
|
+
|
|
88
|
+
# We don't use Stream#send_with_id here as it's unknown
|
|
89
|
+
# if the MUC component *always* uses our stanza id.
|
|
90
|
+
error = nil
|
|
91
|
+
@stream.send(pres) { |r|
|
|
92
|
+
if from_room?(r.from) and r.kind_of?(Presence) and r.type == :error
|
|
93
|
+
# Error from room
|
|
94
|
+
error = r.error
|
|
95
|
+
true
|
|
96
|
+
# type='unavailable' may occur when the MUC kills our previous instance,
|
|
97
|
+
# but all join-failures should be type='error'
|
|
98
|
+
elsif r.from == jid and r.kind_of?(Presence) and r.type != :unavailable
|
|
99
|
+
# Our own presence reflected back - success
|
|
100
|
+
if r.x(XMUCUser) and (i = r.x(XMUCUser).items.first)
|
|
101
|
+
@affiliation = i.affiliation # we're interested in if it's :owner
|
|
102
|
+
@role = i.role # :moderator ?
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
handle_presence(r, false)
|
|
106
|
+
true
|
|
107
|
+
else
|
|
108
|
+
# Everything else
|
|
109
|
+
false
|
|
110
|
+
end
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if error
|
|
114
|
+
deactivate
|
|
115
|
+
raise ServerError.new(error)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
self
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
##
|
|
122
|
+
# Exit the room
|
|
123
|
+
#
|
|
124
|
+
# * Sends presence with type='unavailable' with an optional
|
|
125
|
+
# reason in <tt><status/></tt>,
|
|
126
|
+
# * then waits for a reply from the MUC component (will be
|
|
127
|
+
# processed by leave-callbacks),
|
|
128
|
+
# * then deletes callbacks from the stream.
|
|
129
|
+
# reason:: [String] Optional custom exit message
|
|
130
|
+
def exit(reason=nil)
|
|
131
|
+
unless active?
|
|
132
|
+
raise "MUCClient hasn't yet joined"
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
pres = Presence.new
|
|
136
|
+
pres.type = :unavailable
|
|
137
|
+
pres.to = jid
|
|
138
|
+
pres.from = @my_jid
|
|
139
|
+
pres.status = reason if reason
|
|
140
|
+
@stream.send(pres) { |r|
|
|
141
|
+
Jabber::debuglog "exit: #{r.to_s.inspect}"
|
|
142
|
+
if r.kind_of?(Presence) and r.type == :unavailable and r.from == jid
|
|
143
|
+
@leave_cbs.process(r)
|
|
144
|
+
true
|
|
145
|
+
else
|
|
146
|
+
false
|
|
147
|
+
end
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
deactivate
|
|
151
|
+
|
|
152
|
+
self
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
##
|
|
156
|
+
# Is the MUC client active?
|
|
157
|
+
#
|
|
158
|
+
# This is false after initialization,
|
|
159
|
+
# true after joining and
|
|
160
|
+
# false after exit/kick
|
|
161
|
+
def active?
|
|
162
|
+
@active
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
##
|
|
166
|
+
# The MUCClient's own nick
|
|
167
|
+
# (= resource)
|
|
168
|
+
# result:: [String] Nickname
|
|
169
|
+
def nick
|
|
170
|
+
@jid ? @jid.resource : nil
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
##
|
|
174
|
+
# Change nick
|
|
175
|
+
#
|
|
176
|
+
# Threading is, again, suggested. This method waits for two
|
|
177
|
+
# <presence/> stanzas, one indicating unavailabilty of the old
|
|
178
|
+
# transient JID, one indicating availability of the new
|
|
179
|
+
# transient JID.
|
|
180
|
+
#
|
|
181
|
+
# If the service denies nick-change, ServerError will be raised.
|
|
182
|
+
def nick=(new_nick)
|
|
183
|
+
unless active?
|
|
184
|
+
raise "MUCClient not active"
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
new_jid = JID.new(@jid.node, @jid.domain, new_nick)
|
|
188
|
+
|
|
189
|
+
# Joining
|
|
190
|
+
pres = Presence.new
|
|
191
|
+
pres.to = new_jid
|
|
192
|
+
pres.from = @my_jid
|
|
193
|
+
|
|
194
|
+
error = nil
|
|
195
|
+
# Keeping track of the two stanzas enables us to process stanzas
|
|
196
|
+
# which don't arrive in the order specified by JEP-0045
|
|
197
|
+
presence_unavailable = false
|
|
198
|
+
presence_available = false
|
|
199
|
+
# We don't use Stream#send_with_id here as it's unknown
|
|
200
|
+
# if the MUC component *always* uses our stanza id.
|
|
201
|
+
@stream.send(pres) { |r|
|
|
202
|
+
if from_room?(r.from) and r.kind_of?(Presence) and r.type == :error
|
|
203
|
+
# Error from room
|
|
204
|
+
error = r.error
|
|
205
|
+
elsif r.from == @jid and r.kind_of?(Presence) and r.type == :unavailable and
|
|
206
|
+
r.x and r.x.kind_of?(XMUCUser) and r.x.status_code == 303
|
|
207
|
+
# Old JID is offline, but wait for the new JID and let stanza be handled
|
|
208
|
+
# by the standard callback
|
|
209
|
+
presence_unavailable = true
|
|
210
|
+
handle_presence(r)
|
|
211
|
+
elsif r.from == new_jid and r.kind_of?(Presence) and r.type != :unavailable
|
|
212
|
+
# Our own presence reflected back - success
|
|
213
|
+
presence_available = true
|
|
214
|
+
handle_presence(r)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
if error or (presence_available and presence_unavailable)
|
|
218
|
+
true
|
|
219
|
+
else
|
|
220
|
+
false
|
|
221
|
+
end
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if error
|
|
225
|
+
raise ServerError.new(error)
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# Apply new JID
|
|
229
|
+
@jid = new_jid
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
##
|
|
233
|
+
# The room name
|
|
234
|
+
# (= node)
|
|
235
|
+
# result:: [String] Room name
|
|
236
|
+
def room
|
|
237
|
+
@jid ? @jid.node : nil
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
##
|
|
241
|
+
# Send a stanza to the room
|
|
242
|
+
#
|
|
243
|
+
# If stanza is a Jabber::Message, <tt>stanza.type</tt> will be
|
|
244
|
+
# automatically set to :groupchat if directed to room or :chat
|
|
245
|
+
# if directed to participant.
|
|
246
|
+
# stanza:: [XMPPStanza] to send
|
|
247
|
+
# to:: [String] Stanza destination recipient, or room if +nil+
|
|
248
|
+
def send(stanza, to=nil)
|
|
249
|
+
if stanza.kind_of? Message
|
|
250
|
+
stanza.type = to ? :chat : :groupchat
|
|
251
|
+
end
|
|
252
|
+
stanza.from = @my_jid
|
|
253
|
+
stanza.to = JID.new(jid.node, jid.domain, to)
|
|
254
|
+
@stream.send(stanza)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
##
|
|
258
|
+
# Add a callback for <presence/> stanzas indicating availability
|
|
259
|
+
# of a MUC participant
|
|
260
|
+
#
|
|
261
|
+
# This callback will *not* be called for initial presences when
|
|
262
|
+
# a client joins a room, but only for the presences afterwards.
|
|
263
|
+
#
|
|
264
|
+
# The callback will be called from MUCClient#handle_presence with
|
|
265
|
+
# one argument: the <presence/> stanza.
|
|
266
|
+
# Note that this stanza will have been already inserted into
|
|
267
|
+
# MUCClient#roster.
|
|
268
|
+
def add_join_callback(prio = 0, ref = nil, &block)
|
|
269
|
+
@join_cbs.add(prio, ref, block)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
##
|
|
273
|
+
# Add a callback for <presence/> stanzas indicating unavailability
|
|
274
|
+
# of a MUC participant
|
|
275
|
+
#
|
|
276
|
+
# The callback will be called with one argument: the <presence/> stanza.
|
|
277
|
+
#
|
|
278
|
+
# Note that this is called just *before* the stanza is removed from
|
|
279
|
+
# MUCClient#roster, so it is still possible to see the last presence
|
|
280
|
+
# in the given block.
|
|
281
|
+
#
|
|
282
|
+
# If the presence's origin is your MUC JID, the MUCClient will be
|
|
283
|
+
# deactivated *afterwards*.
|
|
284
|
+
def add_leave_callback(prio = 0, ref = nil, &block)
|
|
285
|
+
@leave_cbs.add(prio, ref, block)
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
##
|
|
289
|
+
# Add a callback for a <presence/> stanza which is neither a join
|
|
290
|
+
# nor a leave. This will be called when a room participant simply
|
|
291
|
+
# changes his status.
|
|
292
|
+
def add_presence_callback(prio = 0, ref = nil, &block)
|
|
293
|
+
@presence_cbs.add(prio, ref, block)
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
##
|
|
297
|
+
# Add a callback for <message/> stanza directed to the whole room.
|
|
298
|
+
#
|
|
299
|
+
# See MUCClient#add_private_message_callback for private messages
|
|
300
|
+
# between MUC participants.
|
|
301
|
+
def add_message_callback(prio = 0, ref = nil, &block)
|
|
302
|
+
@message_cbs.add(prio, ref, block)
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
##
|
|
306
|
+
# Add a callback for <message/> stanza with type='chat'.
|
|
307
|
+
#
|
|
308
|
+
# These stanza are normally not broadcasted to all room occupants
|
|
309
|
+
# but are some sort of private messaging.
|
|
310
|
+
def add_private_message_callback(prio = 0, ref = nil, &block)
|
|
311
|
+
@private_message_cbs.add(prio, ref, block)
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
##
|
|
315
|
+
# Does this JID belong to that room?
|
|
316
|
+
# jid:: [JID]
|
|
317
|
+
# result:: [true] or [false]
|
|
318
|
+
def from_room?(jid)
|
|
319
|
+
@jid.strip == jid.strip
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
private
|
|
323
|
+
|
|
324
|
+
##
|
|
325
|
+
# call_join_cbs:: [Bool] Do not call them if we receive initial presences from room
|
|
326
|
+
def handle_presence(pres, call_join_cbs=true) # :nodoc:
|
|
327
|
+
if pres.type == :unavailable or pres.type == :error
|
|
328
|
+
@leave_cbs.process(pres)
|
|
329
|
+
@roster_lock.synchronize {
|
|
330
|
+
@roster.delete(pres.from.resource)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if pres.from == jid and !(pres.x and pres.x.kind_of?(XMUCUser) and pres.x.status_code == 303)
|
|
334
|
+
deactivate
|
|
335
|
+
end
|
|
336
|
+
else
|
|
337
|
+
is_join = ! @roster.has_key?(pres.from.resource)
|
|
338
|
+
@roster_lock.synchronize {
|
|
339
|
+
@roster[pres.from.resource] = pres
|
|
340
|
+
}
|
|
341
|
+
if is_join
|
|
342
|
+
@join_cbs.process(pres) if call_join_cbs
|
|
343
|
+
else
|
|
344
|
+
@presence_cbs.process(pres)
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def handle_message(msg) # :nodoc:
|
|
350
|
+
if msg.type == :chat
|
|
351
|
+
@private_message_cbs.process(msg)
|
|
352
|
+
else # type == :groupchat or anything else
|
|
353
|
+
@message_cbs.process(msg)
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
def activate # :nodoc:
|
|
358
|
+
@active = true
|
|
359
|
+
|
|
360
|
+
# Callbacks
|
|
361
|
+
@stream.add_presence_callback(150, self) { |presence|
|
|
362
|
+
if from_room?(presence.from)
|
|
363
|
+
handle_presence(presence)
|
|
364
|
+
true
|
|
365
|
+
else
|
|
366
|
+
false
|
|
367
|
+
end
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
@stream.add_message_callback(150, self) { |message|
|
|
371
|
+
if from_room?(message.from)
|
|
372
|
+
handle_message(message)
|
|
373
|
+
true
|
|
374
|
+
else
|
|
375
|
+
false
|
|
376
|
+
end
|
|
377
|
+
}
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
def deactivate # :nodoc:
|
|
381
|
+
@active = false
|
|
382
|
+
@jid = nil
|
|
383
|
+
|
|
384
|
+
# Callbacks
|
|
385
|
+
@stream.delete_presence_callback(self)
|
|
386
|
+
@stream.delete_message_callback(self)
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
public
|
|
390
|
+
def owner?
|
|
391
|
+
@affiliation == :owner
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
##
|
|
395
|
+
# Use this method to configure a MUC room of which you are the owner.
|
|
396
|
+
#
|
|
397
|
+
# options:: [Hash] where keys are the features of the room you wish
|
|
398
|
+
# to configure. See http://www.xmpp.org/extensions/xep-0045.html#registrar-formtype-owner
|
|
399
|
+
def configure(options={})
|
|
400
|
+
get_room_configuration
|
|
401
|
+
submit_room_configuration(options)
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
def get_room_configuration
|
|
405
|
+
raise 'You are not the owner' unless owner?
|
|
406
|
+
|
|
407
|
+
iq = Iq.new(:get, jid.strip)
|
|
408
|
+
iq.from = my_jid
|
|
409
|
+
iq.add(IqQueryMUCOwner.new)
|
|
410
|
+
|
|
411
|
+
fields = []
|
|
412
|
+
|
|
413
|
+
@stream.send_with_id(iq) do |answer|
|
|
414
|
+
raise "Configuration not possible for this room" unless answer.query && answer.query.x(Dataforms::XData)
|
|
415
|
+
|
|
416
|
+
answer.query.x(Dataforms::XData).fields.each do |field|
|
|
417
|
+
if (var = field.attributes['var'])
|
|
418
|
+
fields << var
|
|
419
|
+
end
|
|
420
|
+
end
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
fields
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
def submit_room_configuration(options)
|
|
427
|
+
# fill out the reply form
|
|
428
|
+
iq = Iq.new(:set, jid.strip)
|
|
429
|
+
iq.from = my_jid
|
|
430
|
+
query = IqQueryMUCOwner.new
|
|
431
|
+
form = Dataforms::XData.new
|
|
432
|
+
form.type = :submit
|
|
433
|
+
options.each do |var, values|
|
|
434
|
+
field = Dataforms::XDataField.new
|
|
435
|
+
values = [values] unless values.is_a?(Array)
|
|
436
|
+
field.var, field.values = var, values
|
|
437
|
+
form.add(field)
|
|
438
|
+
end
|
|
439
|
+
query.add(form)
|
|
440
|
+
iq.add(query)
|
|
441
|
+
|
|
442
|
+
@stream.send_with_id(iq)
|
|
443
|
+
end
|
|
444
|
+
|
|
445
|
+
##
|
|
446
|
+
# Push a list of new affiliations to the room
|
|
447
|
+
# items:: [Array] of, or single [IqQueryMUCAdminItem]
|
|
448
|
+
def send_affiliations(items)
|
|
449
|
+
iq = Iq.new(:set, jid.strip)
|
|
450
|
+
iq.from = my_jid
|
|
451
|
+
iq.add(IqQueryMUCAdmin.new)
|
|
452
|
+
|
|
453
|
+
items = [item] unless items.kind_of? Array
|
|
454
|
+
items.each { |item|
|
|
455
|
+
iq.query.add(item)
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
@stream.send_with_id(iq)
|
|
459
|
+
end
|
|
460
|
+
end
|
|
461
|
+
end
|
|
462
|
+
end
|