collecta-rb 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Jeff Smick
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,44 @@
1
+ Collecta.rb
2
+ ===========
3
+
4
+ A ruby library based on Blather for working with the Collecta XMPP api.
5
+
6
+ Install
7
+ -------
8
+ Gem is hosted on [Gemcutter](http://gemcutter.org/)
9
+
10
+ sudo gem install collecta-rb
11
+
12
+ Example
13
+ -------
14
+
15
+ require 'rubygems'
16
+ require 'collecta-rb'
17
+ require 'pp'
18
+
19
+ client = Collecta::Client.setup '[api-key]'
20
+
21
+ client.subscribe('earthquake') do |result|
22
+ pp({
23
+ :query => result.query,
24
+ :title => result.title,
25
+ :category => result.category,
26
+ :abstract => result.abstract,
27
+ })
28
+ end
29
+
30
+ client.notifications('earthquake') do |notification|
31
+ pp notification
32
+ end
33
+
34
+ client.archive('earthquake') do |result|
35
+ pp result
36
+ end
37
+
38
+ EM.run { client.connect }
39
+
40
+
41
+ Copyright
42
+ ---------
43
+
44
+ Copyright (c) 2009 Jeff Smick. See LICENSE for details.
@@ -0,0 +1,24 @@
1
+ require 'rubygems'
2
+ require 'collecta-rb'
3
+ require 'pp'
4
+
5
+ client = Collecta::Client.setup 'f67a267c6d5c86ed36ae676e70698bdd'
6
+
7
+ client.subscribe('earthquake') do |result|
8
+ pp({
9
+ :query => result.query,
10
+ :title => result.title,
11
+ :category => result.category,
12
+ :abstract => result.abstract,
13
+ })
14
+ end
15
+
16
+ client.notifications('earthquake') do |notification|
17
+ pp notification
18
+ end
19
+
20
+ client.archive('earthquake') do |result|
21
+ pp result
22
+ end
23
+
24
+ EM.run { client.connect }
@@ -0,0 +1,84 @@
1
+ %w[
2
+ blather
3
+ blather/client/client
4
+
5
+ collecta/pubsub
6
+ collecta/archive
7
+ collecta/result
8
+ collecta/subscribe
9
+ ].each { |r| require r }
10
+
11
+ module Collecta
12
+ COLLECTA_JID = 'search.collecta.com'.freeze
13
+ HOST = 'guest.collecta.com'.freeze
14
+ NODE = 'search'.freeze
15
+
16
+ class Client < Blather::Client
17
+ attr_accessor :api_key # :nodoc:
18
+
19
+ # Setup the connection with an API key
20
+ def self.setup(apikey)
21
+ new_client = super "@#{HOST}", nil
22
+ new_client.api_key = apikey
23
+ new_client
24
+ end
25
+
26
+ def initialize # :nodoc:
27
+ super
28
+ @deferred = []
29
+ end
30
+
31
+ # Subscribe to a query
32
+ def subscribe(search, &block)
33
+ return if defer(:subscribe, search, &block)
34
+ self.write Subscribe.new self.api_key, search
35
+ self.register_handler(:pubsub_event, "//ns:headers/ns:header[@name='x-collecta#query' and .='#{search}']", :ns => 'http://jabber.org/protocol/shim') do |evt, _|
36
+ block.call Result.new.inherit(evt)
37
+ end
38
+ end
39
+
40
+ # Subscribe to query notifications
41
+ def notifications(search, &block)
42
+ return if defer(:notifications, search, &block)
43
+ self.write Subscribe.new self.api_key, nil, search
44
+ self.register_handler(:pubsub_event, "//ns:item[@id='#{search}']", :ns => 'http://jabber.org/protocol/pubsub#event') do |evt, item|
45
+ block.call item.first.find('//ns:count', :ns => 'http://api.collecta.com/ns/search-0#notify').first.content.to_i
46
+ end
47
+ end
48
+
49
+ # Retrieve the last set of entries for <tt>search</tt>
50
+ def archive(search, &block)
51
+ return if defer(:archive, search, &block)
52
+ self.write_with_handler Archive.new(self.api_key, search), &block
53
+ end
54
+
55
+ # Collecta doesn't seem to like stanzas with whitespace so clear it out
56
+ def write(stanza) # :nodoc:
57
+ super stanza.to_xml(:indent => 0).gsub(/\n|\r/,'')
58
+ end
59
+
60
+ # Allow users to setup callbacks before the connection is setup
61
+ def defer(*args, &block) # :nodoc:
62
+ if @stream
63
+ false
64
+ else
65
+ @deferred << [args, block]
66
+ true
67
+ end
68
+ end
69
+
70
+ # Run all deferred commands after the connection is established
71
+ def post_init(stream, jid = nil) # :nodoc:
72
+ super
73
+ until @deferred.empty?
74
+ args = @deferred.pop
75
+ self.__send__ *(args[0]), &args[1]
76
+ end
77
+ end
78
+
79
+ def client_post_init # :nodoc:
80
+ # overwrite the default actions to take after a client is setup
81
+ end
82
+ end
83
+
84
+ end
@@ -0,0 +1,12 @@
1
+ module Collecta
2
+ class Archive < Blather::Stanza::PubSub::Items
3
+ include Collecta::Pubsub
4
+ def self.new(apikey, search)
5
+ new_node = super :get, COLLECTA_JID
6
+ new_node.node = NODE
7
+ new_node.apikey = apikey
8
+ new_node.query = search
9
+ new_node
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,54 @@
1
+ module Collecta
2
+ module Pubsub
3
+ DATA_NS = 'jabber:x:data'.freeze
4
+
5
+ def apikey
6
+ self.options.content_from '//ns:field[@var="x-collecta#apikey"]/ns:value', :ns => DATA_NS
7
+ end
8
+
9
+ def apikey=(key)
10
+ self.add_field 'x-collecta#apikey', key
11
+ end
12
+
13
+ def query
14
+ self.options.find('//ns:field[@var="x-collecta#query"]/ns:value', :ns => DATA_NS).map { |n| n.content }
15
+ end
16
+
17
+ def query=(values)
18
+ self.add_field 'x-collecta#query', values
19
+ end
20
+
21
+ def notify
22
+ self.options.find('//ns:field[@var="x-collecta#notify"]/ns:value', :ns => DATA_NS).map { |n| n.content }
23
+ end
24
+
25
+ def notify=(values)
26
+ self.add_field 'x-collecta#notify', values
27
+ end
28
+
29
+ protected
30
+ def options
31
+ x = self.pubsub.find_first('//pubsub_ns:options/ns:x', :pubsub_ns => self.registered_ns, :ns => DATA_NS)
32
+ unless x
33
+ self.pubsub << (o = Blather::XMPPNode.new('options', self.document))
34
+ o << (x = Blather::XMPPNode.new('x', self.document))
35
+ x.namespace = 'jabber:x:data'
36
+ x[:type] = 'submit'
37
+
38
+ field = self.add_field('FORM_TYPE', 'http://jabber.org/protocol/pubsub#subscribe_options')
39
+ field[:type] = 'hidden'
40
+ end
41
+ x
42
+ end
43
+
44
+ def add_field(var, values)
45
+ self.options << (field = Blather::XMPPNode.new('field', self.document))
46
+ field[:var] = var
47
+ [values].flatten.each do |value|
48
+ field << (val = Blather::XMPPNode.new('value', self.document))
49
+ val.content = value
50
+ end
51
+ field
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,23 @@
1
+ module Collecta
2
+ class Result < Blather::Stanza::PubSub::Event
3
+ def query
4
+ content_from('//ns:headers/ns:header[@name="x-collecta#query"]', :ns => 'http://jabber.org/protocol/shim').strip
5
+ end
6
+
7
+ def title
8
+ self.entry.content_from '//ns:title', :ns => 'http://www.w3.org/2005/Atom'
9
+ end
10
+
11
+ def category
12
+ self.entry.content_from '//ns:category', :ns => 'http://api.collecta.com/ns/search-0#results'
13
+ end
14
+
15
+ def abstract
16
+ self.entry.find('//ns:abstract', :ns => 'http://api.collecta.com/ns/search-0#results').first.inner_html.strip
17
+ end
18
+
19
+ def entry
20
+ Blather::XMPPNode.new('event').inherit self.items.first.find_first('//ns:entry', :ns => 'http://www.w3.org/2005/Atom')
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,12 @@
1
+ module Collecta
2
+ class Subscribe < Blather::Stanza::PubSub::Subscribe
3
+ include Collecta::Pubsub
4
+ def self.new(apikey, query = nil, notify = nil)
5
+ new_node = super :set, COLLECTA_JID, NODE
6
+ new_node.apikey = apikey
7
+ new_node.query = query
8
+ new_node.notify = notify if notify
9
+ new_node
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Collecta::Archive do
4
+ it 'can be created with an apikey and a search term' do
5
+ archive = Collecta::Archive.new 'apikey-value', 'search-term'
6
+ archive.must_be_kind_of Blather::Stanza::PubSub::Items
7
+ archive.must_have_apikey 'apikey-value'
8
+ archive.must_have_query 'search-term'
9
+ end
10
+ end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ describe Collecta::Result do
4
+ before do
5
+ @result = Collecta::Result.new.inherit(Blather::XMPPNode.import(Nokogiri::XML.parse(<<-XML).root))
6
+ <message from='search.collecta.com'
7
+ to='tofu@collecta.com/search'>
8
+ <event xmlns='http://jabber.org/protocol/pubsub#event'>
9
+ <items node='search'>
10
+ <item id='1cb57d9c-1c46-11dd-838c-001143d5d5db'>
11
+ <entry xmlns="http://www.w3.org/2005/Atom">
12
+ <source>
13
+ <title>metajack</title>
14
+ <icon>http://identi.ca/avatar/4685-96-20090213165024.jpeg</icon>
15
+ <author>
16
+ <name>metajack</name>
17
+ </author>
18
+ <link href="http://identi.ca/metajack"/>
19
+ <link href="http://identi.ca/metajack" type="application/atom+xml" rel="self"/>
20
+ <link href="http://creativecommons.org/licenses/by/3.0/" rel="license"/>
21
+ </source>
22
+ <link href="http://identi.ca/metajack"/>
23
+ <title>metajack</title>
24
+ <published>2009-04-25T04:03:38+00:00</published>
25
+ <id>http://identi.ca/notice/3694388</id>
26
+ <updated>1970-01-01T00:00:00+00:00</updated>
27
+ <category xmlns="http://api.collecta.com/ns/search-0#results">update</category>
28
+ <abstract xmlns="http://api.collecta.com/ns/search-0#results">
29
+ <p>metajack Great. My first day back in SF and there's an earthquake.</p>
30
+ </abstract>
31
+ <link rel='collecta-abstract-image' href='http://identi.ca/avatar/4685-96-20090213165024.jpeg'/>
32
+ </entry>
33
+ </item>
34
+ </items>
35
+ </event>
36
+ <headers xmlns='http://jabber.org/protocol/shim'>
37
+ <header name='x-collecta#query'>
38
+ earthquake
39
+ </header>
40
+ </headers>
41
+ </message>
42
+ XML
43
+ end
44
+
45
+ it 'has a query' do
46
+ @result.query.must_equal 'earthquake'
47
+ end
48
+
49
+ it 'has a title' do
50
+ @result.title.must_equal 'metajack'
51
+ end
52
+
53
+ it 'has a category' do
54
+ @result.category.must_equal 'update'
55
+ end
56
+
57
+ it 'has an abstract' do
58
+ @result.abstract.must_equal "<p>metajack Great. My first day back in SF and there's an earthquake.</p>"
59
+ end
60
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Collecta::Subscribe do
4
+ it 'can be created with an apikey, a search term and a notify term' do
5
+ subscription = Collecta::Subscribe.new 'apikey-value', 'search-term', 'notify-term'
6
+ subscription.must_be_kind_of Blather::Stanza::PubSub::Subscribe
7
+ subscription.must_have_apikey 'apikey-value'
8
+ subscription.must_have_query 'search-term'
9
+ subscription.must_have_notify 'notify-term'
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ require 'spec_helper'
2
+
3
+
@@ -0,0 +1,43 @@
1
+ require 'rubygems'
2
+ require 'minitest/spec'
3
+
4
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), '..'))
5
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), *%w[.. lib]))
6
+ require 'collecta-rb'
7
+
8
+ MiniTest::Unit.autorun
9
+
10
+ module MiniTest
11
+ require 'pathname' if MINI_DIR =~ %r{^./}
12
+
13
+ module Assertions
14
+ def assert_has_apikey(key, node, msg = nil)
15
+ msg = message(msg) { "Expected #{mu_pp(node)} to have API key #{mu_pp(key)}" }
16
+ assert(node.apikey == key, msg)
17
+ end
18
+
19
+ def assert_has_query(query, node, msg = nil)
20
+ msg = message(msg) { "Expected #{mu_pp(node)} to have query #{mu_pp(query)}" }
21
+ assert(node.query.include?(query), msg)
22
+ end
23
+
24
+ def assert_has_notify(notify, node, msg = nil)
25
+ msg = message(msg) { "Expected #{mu_pp(node)} to have query #{mu_pp(notify)}" }
26
+ assert(node.notify.include?(notify), msg)
27
+ end
28
+ end
29
+ end
30
+
31
+ class Object
32
+ def must_have_apikey *args
33
+ return MiniTest::Spec.current.assert_has_apikey(args.first, self)
34
+ end
35
+
36
+ def must_have_query *args
37
+ return MiniTest::Spec.current.assert_has_query(args.first, self)
38
+ end
39
+
40
+ def must_have_notify *args
41
+ return MiniTest::Spec.current.assert_has_notify(args.first, self)
42
+ end
43
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: collecta-rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jeff Smick
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-02 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: blather
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: minitest
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: yard
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ description: A ruby library based on Blather for working with the Collecta XMPP api.
46
+ email: sprsquish@gmail.com
47
+ executables: []
48
+
49
+ extensions: []
50
+
51
+ extra_rdoc_files:
52
+ - LICENSE
53
+ - README.md
54
+ files:
55
+ - examples/collecta.rb
56
+ - lib/collecta-rb.rb
57
+ - lib/collecta/archive.rb
58
+ - lib/collecta/pubsub.rb
59
+ - lib/collecta/result.rb
60
+ - lib/collecta/subscribe.rb
61
+ - LICENSE
62
+ - README.md
63
+ has_rdoc: true
64
+ homepage: http://github.com/sprsquish/collecta-rb
65
+ licenses: []
66
+
67
+ post_install_message:
68
+ rdoc_options:
69
+ - --charset=UTF-8
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ version:
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: "0"
83
+ version:
84
+ requirements: []
85
+
86
+ rubyforge_project:
87
+ rubygems_version: 1.3.5
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: A ruby library based on Blather for working with the Collecta XMPP api.
91
+ test_files:
92
+ - spec/collecta/archive_spec.rb
93
+ - spec/collecta/result_spec.rb
94
+ - spec/collecta/subscribe_spec.rb
95
+ - spec/collecta_spec.rb
96
+ - spec/spec_helper.rb