collecta-rb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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