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 +20 -0
- data/README.md +44 -0
- data/examples/collecta.rb +24 -0
- data/lib/collecta-rb.rb +84 -0
- data/lib/collecta/archive.rb +12 -0
- data/lib/collecta/pubsub.rb +54 -0
- data/lib/collecta/result.rb +23 -0
- data/lib/collecta/subscribe.rb +12 -0
- data/spec/collecta/archive_spec.rb +10 -0
- data/spec/collecta/result_spec.rb +60 -0
- data/spec/collecta/subscribe_spec.rb +11 -0
- data/spec/collecta_spec.rb +3 -0
- data/spec/spec_helper.rb +43 -0
- metadata +96 -0
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.
|
data/README.md
ADDED
@@ -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 }
|
data/lib/collecta-rb.rb
ADDED
@@ -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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|