lib/blather/client/dsl.rb in blather-0.4.7 vs lib/blather/client/dsl.rb in blather-0.4.8

- old
+ new

@@ -1,140 +1,264 @@ require File.join(File.dirname(__FILE__), 'client') module Blather + + # # Blather DSL + # + # The DSL is a set of methods that enables you to write cleaner code. Being a + # module means it can be included in or extend any class you may want to + # create. + # + # Every stanza handler is registered as a method on the DSL. + # + # @example Include the DSL in the top level namespace. + # + # require 'blather/client' + # when_ready { puts "Connected ! send messages to #{jid.stripped}." } + # + # subscription :request? do |s| + # write_to_stream s.approve! + # end + # + # message :chat?, :body => 'exit' do |m| + # say m.from, 'Exiting ...' + # shutdown + # end + # + # message :chat?, :body do |m| + # say m.from, "You sent: #{m.body}" + # end + # + # @example Set the DSL to its own namespace. + # + # require 'blather/client/dsl' + # module Echo + # extend Blather::DSL + # def self.run + # client.run + # end + # + # when_ready { puts "Connected ! send messages to #{jid.stripped}." } + # + # subscription :request? do |s| + # write_to_stream s.approve! + # end + # + # message :chat?, :body => 'exit' do |m| + # say m.from, 'Exiting ...' + # shutdown + # end + # + # message :chat?, :body do |m| + # say m.from, "You sent: #{m.body}" + # end + # end + # + # EM.run { Echo.run } + # + # @example Create a class out of it + # + # require 'blather/client/dsl' + # class Echo + # include Blather::DSL + # end + # + # echo = Echo.new + # echo.when_ready { puts "Connected ! send messages to #{jid.stripped}." } + # + # echo.subscription :request? do |s| + # write_to_stream s.approve! + # end + # + # echo.message :chat?, :body => 'exit' do |m| + # say m.from, 'Exiting ...' + # shutdown + # end + # + # echo.message :chat?, :body do |m| + # say m.from, "You sent: #{m.body}" + # end + # + # EM.run { echo.client.run } module DSL autoload :PubSub, File.expand_path(File.join(File.dirname(__FILE__), *%w[dsl pubsub])) + # The actual client connection + # + # @return [Blather::Client] def client @client ||= Client.new end module_function :client + # A pubsub helper + # + # @return [Blather::PubSub] def pubsub @pubsub ||= PubSub.new client, jid.domain end - ## # Push data to the stream # This works such that it can be chained: - # self << stanza1 << stanza2 << "raw data" + # self << stanza1 << stanza2 << "raw data" + # + # @param [#to_xml, #to_s] stanza data to send down the wire + # @return [self] def <<(stanza) client.write stanza self end - ## # Prepare server settings - # setup [node@domain/resource], [password], [host], [port] - # host and port are optional defaulting to the domain in the JID and 5222 respectively + # + # @param [#to_s] jid the JID to authenticate with + # @param [#to_s] password the password to authenticate with + # @param [String] host (optional) the host to connect to (can be an IP). If + # this is `nil` the domain on the JID will be used + # @param [Fixnum, String] (optional) port the port to connect on def setup(jid, password, host = nil, port = nil) client.setup(jid, password, host, port) end - ## # Shutdown the connection. # Flushes the write buffer then stops EventMachine def shutdown client.close end - ## # Setup a before filter + # + # @param [Symbol] handler (optional) the stanza handler the filter should + # run before + # @param [guards] guards (optional) a set of guards to check the stanza + # against + # @yield [Blather::Stanza] stanza def before(handler = nil, *guards, &block) client.register_filter :before, handler, *guards, &block end - ## # Setup an after filter + # + # @param [Symbol] handler (optional) the stanza handler the filter should + # run after + # @param [guards] guards (optional) a set of guards to check the stanza + # against + # @yield [Blather::Stanza] stanza def after(handler = nil, *guards, &block) client.register_filter :after, handler, *guards, &block end - ## # Set handler for a stanza type - def handle(stanza_type, *guards, &block) - client.register_handler stanza_type, *guards, &block + # + # @param [Symbol] handler the stanza type it should handle + # @param [guards] guards (optional) a set of guards to check the stanza + # against + # @yield [Blather::Stanza] stanza + def handle(handler, *guards, &block) + client.register_handler handler, *guards, &block end - ## # Wrapper for "handle :ready" (just a bit of syntactic sugar) + # + # This is run after the connection has been completely setup def when_ready(&block) handle :ready, &block end - ## # Wrapper for "handle :disconnected" + # + # This is run after the connection has been shut down. + # + # @example Reconnect after a disconnection + # disconnected { client.run } def disconnected(&block) handle :disconnected, &block end - ## # Set current status + # + # @param [Blather::Stanza::Presence::State::VALID_STATES] state the current + # state + # @param [#to_s] msg the status message to use def set_status(state = nil, msg = nil) client.status = state, msg end - ## # Direct access to the roster + # + # @return [Blather::Roster] def my_roster client.roster end - ## # Write data to the stream - # Anything that resonds to #to_s can be paseed to the stream + # + # @param [#to_xml, #to_s] stanza the data to send down the wire. def write_to_stream(stanza) client.write stanza end - ## # Helper method to make sending basic messages easier - # say [jid], [msg] + # + # @param [Blather::JID, #to_s] to the JID of the message recipient + # @param [#to_s] msg the message to send def say(to, msg) client.write Blather::Stanza::Message.new(to, msg) end - ## - # Wrapper to grab the current JID + # The JID according to the server + # + # @return [Blather::JID] def jid client.jid end - ## # Halt the handler chain + # + # Use this to stop the propogation of the stanza though the handler chain. + # + # @example + # Ignore all IQ stanzas + # + # before(:iq) { halt } def halt throw :halt end - ## # Pass responsibility to the next handler + # + # Use this to jump out of the current handler and let the next registered + # handler take care of the stanza + # + # @example + # This is contrive and should be handled with guards, but pass a message + # to the next handler based on the content + # + # message { |s| puts "message caught" } + # message { |s| pass if s.body =~ /pass along/ } def pass throw :pass end - ## # Request items or info from an entity - # discover (items|info), [jid], [node] do |response| - # end + # discover (items|info), [jid], [node] do |response| + # end def discover(what, who, where, &callback) stanza = Blather::Stanza.class_from_registration(:query, "http://jabber.org/protocol/disco##{what}").new stanza.to = who stanza.node = where client.register_tmp_handler stanza.id, &callback client.write stanza end - ## - # Checks to see if the method is part of the handlers list. - # If so it creates a handler, otherwise it'll pass it back - # to Ruby's method_missing handler + # Generate a method for every stanza handler that exists. Blather::Stanza.handler_list.each do |handler_name| module_eval <<-METHOD, __FILE__, __LINE__ def #{handler_name}(*args, &callback) handle :#{handler_name}, *args, &callback end METHOD end - end #DSL -end #Blather + end # DSL +end # Blather