dash-bees 0.19 → 0.20
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/CHANGELOG +2 -0
- data/Gemfile +1 -1
- data/dash-bees.gemspec +2 -1
- data/lib/dash-fu/bee.rb +6 -6
- data/lib/dash-fu/bees/feed.rb +104 -0
- data/lib/dash-fu/bees/feed.yml +7 -0
- data/lib/dash-fu/bees/github.rb +0 -8
- data/lib/dash-fu/bees/github_issues.rb +0 -9
- data/test/cassettes/feed.yml +83 -0
- data/test/feed_test.rb +132 -0
- data/test/helpers/source.rb +2 -2
- data/test/test.log +76 -0
- metadata +24 -7
data/CHANGELOG
CHANGED
data/Gemfile
CHANGED
data/dash-bees.gemspec
CHANGED
@@ -18,8 +18,9 @@ Gem::Specification.new do |spec|
|
|
18
18
|
|
19
19
|
spec.required_ruby_version = '>= 1.8.7'
|
20
20
|
spec.add_dependency "activesupport"
|
21
|
+
spec.add_dependency "i18n"
|
21
22
|
spec.add_dependency "json"
|
22
23
|
spec.add_dependency "nokogiri"
|
23
24
|
spec.add_dependency "rack"
|
24
|
-
spec.add_dependency "
|
25
|
+
spec.add_dependency "sanitize"
|
25
26
|
end
|
data/lib/dash-fu/bee.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
require "active_support"
|
2
1
|
require "json"
|
3
2
|
require "net/http"
|
4
|
-
require "rack"
|
5
3
|
require "uri"
|
4
|
+
require "open-uri"
|
5
|
+
require "rack"
|
6
6
|
|
7
7
|
# See http://dash-fu.com
|
8
8
|
module DashFu
|
@@ -10,7 +10,7 @@ module DashFu
|
|
10
10
|
# The README covers it all.
|
11
11
|
module Bee
|
12
12
|
|
13
|
-
VERSION = "0.
|
13
|
+
VERSION = "0.20"
|
14
14
|
|
15
15
|
class << self
|
16
16
|
attr_accessor :logger
|
@@ -146,15 +146,15 @@ module DashFu
|
|
146
146
|
# three arguments: status code, response body and response headers. The
|
147
147
|
# block may be called asynchronoulsy.
|
148
148
|
def get(path, headers = {}, &block)
|
149
|
-
response = @http.request(get_request(path, headers))
|
150
|
-
yield response.code, response.body, {}
|
149
|
+
response = @http.request(get_request(path, headers || {}))
|
150
|
+
yield response.code.to_i, response.body, {}
|
151
151
|
end
|
152
152
|
|
153
153
|
# Make a GET request and yield response to the block. If the response
|
154
154
|
# status is 200 the second argument is the response JSON object. The block
|
155
155
|
# may be called asynchronously.
|
156
156
|
def get_json(path, headers = {}, &block)
|
157
|
-
response = @http.request(get_request(path, headers))
|
157
|
+
response = @http.request(get_request(path, headers || {}))
|
158
158
|
if Net::HTTPOK === response
|
159
159
|
json = JSON.parse(response.body) rescue nil
|
160
160
|
if json
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require "sanitize"
|
2
|
+
require "nokogiri"
|
3
|
+
|
4
|
+
module DashFu::Bee
|
5
|
+
# Track Web feed (Atom or RSS).
|
6
|
+
class Feed
|
7
|
+
include DashFu::Bee
|
8
|
+
|
9
|
+
def setup(source, params)
|
10
|
+
source["url"] = params["url"].strip
|
11
|
+
source["source.name"] = "Web feed"
|
12
|
+
end
|
13
|
+
|
14
|
+
def validate(source)
|
15
|
+
uri = URI.parse(source["url"]) rescue nil
|
16
|
+
raise "Not a valid URL" unless uri && uri.absolute?
|
17
|
+
raise "Only HTTP/S URLs supported" unless uri.scheme == "http" || uri.scheme == "https"
|
18
|
+
begin
|
19
|
+
uri.open read_timeout: 3, redirect: true do |io|
|
20
|
+
code = io.status.first
|
21
|
+
raise "Cannot read this feed, got status code #{code}" unless code == "200"
|
22
|
+
feed = (Nokogiri::XML(io.read)>"feed").first
|
23
|
+
source["title"] = get_text(feed>"title").strip
|
24
|
+
source["source.name"] = source["title"] if source["title"].length > 2
|
25
|
+
permalink = (feed>"link[rel=alternate]").first
|
26
|
+
source["permalink"] = permalink["href"] if permalink
|
27
|
+
source["logo"] = (feed>"logo").text
|
28
|
+
end
|
29
|
+
rescue
|
30
|
+
raise "Cannot read this feed: is it down for you or just for us?"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def update(source, callback)
|
35
|
+
uri = URI.parse(source["url"])
|
36
|
+
session uri.host, uri.port do |http|
|
37
|
+
headers = { username: uri.user, password: uri.password } unless uri.user.blank? && uri.password.blank?
|
38
|
+
http.get uri.request_uri, headers do |status, body|
|
39
|
+
begin
|
40
|
+
case status
|
41
|
+
when 200
|
42
|
+
feed = (Nokogiri::XML(body)>"feed").first
|
43
|
+
updated = Time.iso8601((feed>"updated").text) rescue Time.now
|
44
|
+
if source["updated"].nil? || updated > source["updated"]
|
45
|
+
(feed>"entry").each do |entry|
|
46
|
+
published = Time.iso8601((entry>"published").text) rescue Time.now
|
47
|
+
break unless source["updated"].nil? || updated >= published
|
48
|
+
if author = (entry>"author").first
|
49
|
+
person = { fullname: (author>"name").text, email: (author>"email").text,
|
50
|
+
identities: (author>"uri").map(&:text) }
|
51
|
+
end
|
52
|
+
title = get_text(entry>"title")
|
53
|
+
url = (entry>"link[rel=alternate]").first["href"] rescue nil
|
54
|
+
if content = get_html(entry.css("summary,content"))
|
55
|
+
html = "posted <a href=\"#{h url}\">#{h title}</a>:\n<blockquote>#{content}</blockquote>"
|
56
|
+
else
|
57
|
+
html = "posted a link <a href=\"#{h url}\">#{h title}</a>"
|
58
|
+
end
|
59
|
+
callback.activity! uid: (entry>"id").text, url: url, html: html, timestamp: published, person: person
|
60
|
+
end
|
61
|
+
end
|
62
|
+
source["updated"] = updated
|
63
|
+
when 401
|
64
|
+
callback.error! "You are not authorized to access this feed"
|
65
|
+
when 404
|
66
|
+
callback.error! "Could not find the feed #{source["url"]}"
|
67
|
+
else
|
68
|
+
callback.error! "Last request didn't go as expected, trying again later"
|
69
|
+
end
|
70
|
+
rescue
|
71
|
+
logger.error $!
|
72
|
+
callback.error! "Last request didn't go as expected, trying again later"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def meta(source)
|
79
|
+
meta = []
|
80
|
+
meta << { title: "Source", text: source["title"], url: source["permalink"] }
|
81
|
+
meta
|
82
|
+
end
|
83
|
+
|
84
|
+
def get_text(elements)
|
85
|
+
element = elements.first
|
86
|
+
case element["type"]
|
87
|
+
when "html" ; Nokogiri::HTML(element.text).text.strip
|
88
|
+
when "xhtml", "text", nil ; element.text.strip
|
89
|
+
else ""
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def get_html(elements)
|
94
|
+
element = elements.first
|
95
|
+
return unless element
|
96
|
+
case element["type"]
|
97
|
+
when "html" ; Sanitize.clean(element.text, Sanitize::Config::BASIC).strip
|
98
|
+
when "xhtml" ; Sanitize.clean(element.to_xhtml, Sanitize::Config::BASIC).strip
|
99
|
+
when "text"; element.text.strip
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
data/lib/dash-fu/bees/github.rb
CHANGED
@@ -92,13 +92,5 @@ module DashFu::Bee
|
|
92
92
|
meta
|
93
93
|
end
|
94
94
|
|
95
|
-
protected
|
96
|
-
|
97
|
-
def http_request(http, source, path)
|
98
|
-
get = Net::HTTP::Get.new(path.gsub(":repo", URI.escape(source["repo"])).gsub(":branch", URI.escape(source["branch"])))
|
99
|
-
get.basic_auth "#{source["username"]}/token", source["api_token"] unless source["username"].blank? && source["api_token"].blank?
|
100
|
-
http.request(get)
|
101
|
-
end
|
102
|
-
|
103
95
|
end
|
104
96
|
end
|
@@ -78,14 +78,5 @@ closed <a href="#{url}">issue #{issue["number"]}</a> on #{source["repo"]}:
|
|
78
78
|
[ { title: "On GitHub", url: "http://github.com/#{source["repo"]}/issues" } ]
|
79
79
|
end
|
80
80
|
|
81
|
-
protected
|
82
|
-
|
83
|
-
def http_request(http, source, state)
|
84
|
-
path = "/api/v2/json/issues/list/#{URI.escape source["repo"]}/#{state}"
|
85
|
-
get = Net::HTTP::Get.new(path)
|
86
|
-
get.basic_auth "#{source["username"]}/token", source["api_token"] unless source["username"].blank? && source["api_token"].blank?
|
87
|
-
http.request(get)
|
88
|
-
end
|
89
|
-
|
90
81
|
end
|
91
82
|
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
---
|
2
|
+
- !ruby/struct:VCR::HTTPInteraction
|
3
|
+
request: !ruby/struct:VCR::Request
|
4
|
+
method: :get
|
5
|
+
uri: http://example.org:80/feed.xml
|
6
|
+
response: !ruby/struct:VCR::Response
|
7
|
+
status: !ruby/struct:VCR::ResponseStatus
|
8
|
+
code: 200
|
9
|
+
message: OK
|
10
|
+
body: |-
|
11
|
+
<?xml version="1.0" encoding="utf-8"?>
|
12
|
+
<feed xmlns="http://www.w3.org/2005/Atom">
|
13
|
+
<title type="text">dive into mark</title>
|
14
|
+
<subtitle type="html">
|
15
|
+
A <em>lot</em> of effort
|
16
|
+
went into making this effortless
|
17
|
+
</subtitle>
|
18
|
+
<updated>2005-07-31T12:29:29Z</updated>
|
19
|
+
<id>tag:example.org,2003:3</id>
|
20
|
+
<link rel="alternate" type="text/html"
|
21
|
+
hreflang="en" href="http://example.org/"/>
|
22
|
+
<link rel="self" type="application/atom+xml"
|
23
|
+
href="http://example.org/feed.atom"/>
|
24
|
+
<rights>Copyright (c) 2003, Mark Pilgrim</rights>
|
25
|
+
<generator uri="http://www.example.com/" version="1.0">
|
26
|
+
Example Toolkit
|
27
|
+
</generator>
|
28
|
+
<entry>
|
29
|
+
<title>Atom draft-07 snapshot</title>
|
30
|
+
<link rel="alternate" type="text/html"
|
31
|
+
href="http://example.org/2005/04/02/atom"/>
|
32
|
+
<link rel="enclosure" type="audio/mpeg" length="1337"
|
33
|
+
href="http://example.org/audio/ph34r_my_podcast.mp3"/>
|
34
|
+
<id>tag:example.org,2003:3.2397</id>
|
35
|
+
<updated>2005-07-31T12:29:29Z</updated>
|
36
|
+
<published>2003-12-13T08:29:29-04:00</published>
|
37
|
+
<author>
|
38
|
+
<name>Mark Pilgrim</name>
|
39
|
+
<uri>http://example.org/</uri>
|
40
|
+
<email>f8dy@example.com</email>
|
41
|
+
</author>
|
42
|
+
<contributor>
|
43
|
+
<name>Sam Ruby</name>
|
44
|
+
</contributor>
|
45
|
+
<contributor>
|
46
|
+
<name>Joe Gregorio</name>
|
47
|
+
</contributor>
|
48
|
+
<content type="xhtml" xml:lang="en"
|
49
|
+
xml:base="http://diveintomark.org/">
|
50
|
+
<div xmlns="http://www.w3.org/1999/xhtml">
|
51
|
+
<p><i>[Update: The Atom draft is finished.]</i></p>
|
52
|
+
</div>
|
53
|
+
</content>
|
54
|
+
</entry>
|
55
|
+
</feed>
|
56
|
+
- !ruby/struct:VCR::HTTPInteraction
|
57
|
+
request: !ruby/struct:VCR::Request
|
58
|
+
method: :get
|
59
|
+
uri: http://example.org:80/summary.xml
|
60
|
+
response: !ruby/struct:VCR::Response
|
61
|
+
status: !ruby/struct:VCR::ResponseStatus
|
62
|
+
code: 200
|
63
|
+
message: OK
|
64
|
+
body: |-
|
65
|
+
<?xml version="1.0" encoding="utf-8"?>
|
66
|
+
<feed xmlns="http://www.w3.org/2005/Atom">
|
67
|
+
<title type="text">dive into mark</title>
|
68
|
+
<updated>2005-07-31T12:29:29Z</updated>
|
69
|
+
<entry>
|
70
|
+
<title>Atom draft-07 snapshot</title>
|
71
|
+
<id>tag:example.org,2003:3.2397</id>
|
72
|
+
<published>2003-12-13T08:29:29-04:00</published>
|
73
|
+
<link rel="alternate" type="text/html"
|
74
|
+
href="http://example.org/2005/04/02/atom"/>
|
75
|
+
<summary type="html"><q>Quickly stated</></summary>
|
76
|
+
<content type="xhtml" xml:lang="en"
|
77
|
+
xml:base="http://diveintomark.org/">
|
78
|
+
<div xmlns="http://www.w3.org/1999/xhtml">
|
79
|
+
<p><i>[Update: The Atom draft is finished.]</i></p>
|
80
|
+
</div>
|
81
|
+
</content>
|
82
|
+
</entry>
|
83
|
+
</feed>
|
data/test/feed_test.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
require_relative "setup"
|
2
|
+
|
3
|
+
test DashFu::Bee::Feed do
|
4
|
+
context "setup" do
|
5
|
+
subject { source.setup "url"=>"http://example.org/feed.xml" }
|
6
|
+
end
|
7
|
+
|
8
|
+
context "validation" do
|
9
|
+
should "fail if URL is invalid" do
|
10
|
+
assert_raises(RuntimeError) { source.setup("url"=>"/feed.xml") }
|
11
|
+
end
|
12
|
+
|
13
|
+
should "fail if URL is not HTTP" do
|
14
|
+
assert_raises(RuntimeError) { source.setup("url"=>"ftp://example.org/feed.xml") }
|
15
|
+
end
|
16
|
+
|
17
|
+
should "fail if URL is not accessible" do
|
18
|
+
stub_request(:get, "http://example.org/feed.xml").to_timeout
|
19
|
+
assert_raises(RuntimeError) { source.setup("url"=>"http://example.org/feed.xml") }
|
20
|
+
end
|
21
|
+
|
22
|
+
should "fail if status is not 200" do
|
23
|
+
stub_request(:get, "http://example.org/feed.xml").to_return status: 400
|
24
|
+
assert_raises(RuntimeError) { source.setup("url"=>"http://example.org/feed.xml") }
|
25
|
+
end
|
26
|
+
|
27
|
+
should "fail if document is not a feed" do
|
28
|
+
stub_request(:get, "http://example.org/feed.xml").to_return body: { not: "feed" }.to_json
|
29
|
+
assert_raises(RuntimeError) { source.setup("url"=>"http://example.org/feed.xml") }
|
30
|
+
end
|
31
|
+
|
32
|
+
should "set source name from feed title" do
|
33
|
+
stub_request(:get, "http://example.org/feed.xml").to_return body: { title: "The Awesome Feed" }.to_xml(root: "feed")
|
34
|
+
source.setup "url"=>"http://example.org/feed.xml"
|
35
|
+
assert_equal "The Awesome Feed", source.name
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "update" do
|
40
|
+
setup { source.setup "url"=>"http://example.org/feed.xml" }
|
41
|
+
|
42
|
+
should "handle 401" do
|
43
|
+
stub_request(:get, interactions.first.uri).to_return :status=>404
|
44
|
+
source.update
|
45
|
+
assert_equal "Could not find the feed http://example.org/feed.xml", source.last_error
|
46
|
+
end
|
47
|
+
|
48
|
+
should "handle 401" do
|
49
|
+
stub_request(:get, interactions.first.uri).to_return :status=>401
|
50
|
+
source.update
|
51
|
+
assert_equal "You are not authorized to access this feed", source.last_error
|
52
|
+
end
|
53
|
+
|
54
|
+
should "handle other error" do
|
55
|
+
stub_request(:get, interactions.first.uri).to_return :status=>500
|
56
|
+
source.update
|
57
|
+
assert_equal "Last request didn't go as expected, trying again later", source.last_error
|
58
|
+
end
|
59
|
+
|
60
|
+
should "handle invlid document entity" do
|
61
|
+
stub_request(:get, interactions.first.uri).to_return :body=>"Not a feed"
|
62
|
+
source.update
|
63
|
+
assert_equal "Last request didn't go as expected, trying again later", source.last_error
|
64
|
+
end
|
65
|
+
|
66
|
+
context "activity" do
|
67
|
+
setup { source.update }
|
68
|
+
subject { source.activity }
|
69
|
+
|
70
|
+
should "capture entry id" do
|
71
|
+
assert_equal "tag:example.org,2003:3.2397", subject.uid
|
72
|
+
end
|
73
|
+
|
74
|
+
should "capture published date" do
|
75
|
+
assert_equal Time.parse("2003-12-13T08:29:29-04:00"), subject.timestamp
|
76
|
+
end
|
77
|
+
|
78
|
+
should "capture URL" do
|
79
|
+
assert_equal "http://example.org/2005/04/02/atom", subject.url
|
80
|
+
end
|
81
|
+
|
82
|
+
should "capture title and content" do
|
83
|
+
assert_equal <<-HTML.strip, subject.html
|
84
|
+
posted <a href=\"http://example.org/2005/04/02/atom\">Atom draft-07 snapshot</a>:
|
85
|
+
<blockquote><p><i>[Update: The Atom draft is finished.]</i></p></blockquote>
|
86
|
+
HTML
|
87
|
+
end
|
88
|
+
|
89
|
+
context "person" do
|
90
|
+
subject { source.activity.person }
|
91
|
+
|
92
|
+
should "capture full name" do
|
93
|
+
assert_equal "Mark Pilgrim", subject.fullname
|
94
|
+
end
|
95
|
+
|
96
|
+
should "capture email" do
|
97
|
+
assert_equal "f8dy@example.com", subject.email
|
98
|
+
end
|
99
|
+
|
100
|
+
should "capture identity" do
|
101
|
+
assert_contains subject.identities, "http://example.org/"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
context "with summary" do
|
108
|
+
setup do
|
109
|
+
source.setup "url"=>"http://example.org/summary.xml"
|
110
|
+
source.update
|
111
|
+
end
|
112
|
+
subject { source.activity }
|
113
|
+
|
114
|
+
should "capture title and summary" do
|
115
|
+
assert_equal <<-HTML.strip, subject.html
|
116
|
+
posted <a href=\"http://example.org/2005/04/02/atom\">Atom draft-07 snapshot</a>:
|
117
|
+
<blockquote><q>Quickly stated</q></blockquote>
|
118
|
+
HTML
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
context "meta" do
|
125
|
+
setup { source.setup "url"=>"http://example.org/feed.xml" }
|
126
|
+
subject { source.meta }
|
127
|
+
|
128
|
+
should "link to site" do
|
129
|
+
assert_contains subject, :title=>"Source", :text=>"dive into mark", :url=>"http://example.org/"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
data/test/helpers/source.rb
CHANGED
@@ -16,17 +16,17 @@ class Source
|
|
16
16
|
# setup { source.setup "gem_name"=>"vanity" }
|
17
17
|
def setup(params = {})
|
18
18
|
bee.setup state, params
|
19
|
+
bee.validate state
|
19
20
|
self.name = state.delete("source.name")
|
20
21
|
@metric = Metric.new(:name=>name, :columns=>state.delete("metric.columns"), :totals=>!!state.delete("metric.totals")) if state["metric.columns"]
|
21
22
|
validate
|
22
23
|
end
|
23
24
|
|
24
25
|
def validate
|
26
|
+
metric.validate if metric
|
25
27
|
raise "Must be named" if name.blank?
|
26
28
|
raise "Name must be 3 characters of longer" if name.length < 3
|
27
29
|
raise "State fields can only use alphanumeric/underscore in their names" unless state.keys.all? { |k| k =~ /^\w+$/ }
|
28
|
-
bee.validate state
|
29
|
-
metric.validate if metric
|
30
30
|
end
|
31
31
|
|
32
32
|
def valid?
|
data/test/test.log
CHANGED
@@ -932,3 +932,79 @@ RubyGems: 200
|
|
932
932
|
RubyGems: 500
|
933
933
|
RubyGems: 200
|
934
934
|
RubyGems: 500
|
935
|
+
#<Timeout::Error: execution expired>
|
936
|
+
#<NameError: undefined local variable or method `body' for #<DashFu::Bee::Feed:0x00000101b4f670>>
|
937
|
+
#<OpenURI::HTTPError: 400 >
|
938
|
+
#<WebMock::NetConnectNotAllowedError: Real HTTP connections are disabled. Unregistered request: GET http://example.org/feed.xml with headers {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}>
|
939
|
+
#<Timeout::Error: execution expired>
|
940
|
+
#<NameError: undefined local variable or method `body' for #<DashFu::Bee::Feed:0x000001014b6430>>
|
941
|
+
#<OpenURI::HTTPError: 400 >
|
942
|
+
#<WebMock::NetConnectNotAllowedError: Real HTTP connections are disabled. Unregistered request: GET http://example.org/feed.xml with headers {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}>
|
943
|
+
#<NameError: undefined local variable or method `io' for #<DashFu::Bee::Feed:0x000001015d9650>>
|
944
|
+
#<NameError: undefined local variable or method `io' for #<DashFu::Bee::Feed:0x00000101727188>>
|
945
|
+
#<NameError: undefined local variable or method `io' for #<DashFu::Bee::Feed:0x00000100e870c8>>
|
946
|
+
#<NameError: undefined local variable or method `io' for #<DashFu::Bee::Feed:0x000001013110f8>>
|
947
|
+
#<NameError: undefined local variable or method `io' for #<DashFu::Bee::Feed:0x0000010114e1f8>>
|
948
|
+
#<NameError: undefined local variable or method `io' for #<DashFu::Bee::Feed:0x00000101577a90>>
|
949
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
950
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
951
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
952
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
953
|
+
#<NameError: uninitialized constant DashFu::Bee::Rack>
|
954
|
+
#<NameError: uninitialized constant DashFu::Bee::Rack>
|
955
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
956
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
957
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
958
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
959
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
960
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
961
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
962
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
963
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
964
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
965
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
966
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
967
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
968
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
969
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
970
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
971
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
972
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
973
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
974
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
975
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
976
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
977
|
+
#<NoMethodError: undefined method `[]' for nil:NilClass>
|
978
|
+
#<NameError: uninitialized constant DashFu::Bee::Feed::Sanitize>
|
979
|
+
#<NameError: uninitialized constant DashFu::Bee::Feed::Sanitize>
|
980
|
+
#<NameError: uninitialized constant DashFu::Bee::Feed::Sanitize>
|
981
|
+
#<NameError: uninitialized constant DashFu::Bee::Feed::Sanitize>
|
982
|
+
#<NameError: uninitialized constant DashFu::Bee::Feed::Sanitize>
|
983
|
+
#<NameError: uninitialized constant DashFu::Bee::Feed::Sanitize>
|
984
|
+
#<NameError: uninitialized constant DashFu::Bee::Feed::Sanitize>
|
985
|
+
#<NoMethodError: undefined method `namespaces' for nil:NilClass>
|
986
|
+
#<NoMethodError: undefined method `namespaces' for nil:NilClass>
|
987
|
+
#<NoMethodError: undefined method `namespaces' for nil:NilClass>
|
988
|
+
#<NoMethodError: undefined method `namespaces' for nil:NilClass>
|
989
|
+
#<NoMethodError: undefined method `namespaces' for nil:NilClass>
|
990
|
+
#<NoMethodError: undefined method `namespaces' for nil:NilClass>
|
991
|
+
#<NoMethodError: undefined method `namespaces' for nil:NilClass>
|
992
|
+
#<NoMethodError: undefined method `namespaces' for nil:NilClass>
|
993
|
+
#<Nokogiri::XML::XPath::SyntaxError: Undefined namespace prefix: ./content:summary>
|
994
|
+
#<Nokogiri::XML::XPath::SyntaxError: Undefined namespace prefix: ./content:summary>
|
995
|
+
#<Nokogiri::XML::XPath::SyntaxError: Undefined namespace prefix: ./content:summary>
|
996
|
+
#<Nokogiri::XML::XPath::SyntaxError: Undefined namespace prefix: ./content:summary>
|
997
|
+
#<Nokogiri::XML::XPath::SyntaxError: Undefined namespace prefix: ./content:summary>
|
998
|
+
#<Nokogiri::XML::XPath::SyntaxError: Undefined namespace prefix: ./content:summary>
|
999
|
+
#<Nokogiri::XML::XPath::SyntaxError: Undefined namespace prefix: ./content:summary>
|
1000
|
+
#<Nokogiri::XML::XPath::SyntaxError: Undefined namespace prefix: ./content:summary>
|
1001
|
+
#<NoMethodError: undefined method `namespaces' for nil:NilClass>
|
1002
|
+
#<NoMethodError: undefined method `namespaces' for nil:NilClass>
|
1003
|
+
#<NoMethodError: undefined method `namespaces' for nil:NilClass>
|
1004
|
+
#<NoMethodError: undefined method `namespaces' for nil:NilClass>
|
1005
|
+
#<NoMethodError: undefined method `namespaces' for nil:NilClass>
|
1006
|
+
#<NoMethodError: undefined method `namespaces' for nil:NilClass>
|
1007
|
+
#<NoMethodError: undefined method `namespaces' for nil:NilClass>
|
1008
|
+
#<NoMethodError: undefined method `namespaces' for nil:NilClass>
|
1009
|
+
#<NoMethodError: undefined method `namespaces' for nil:NilClass>
|
1010
|
+
#<NoMethodError: undefined method `namespaces' for nil:NilClass>
|
metadata
CHANGED
@@ -4,8 +4,8 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
version: "0.
|
7
|
+
- 20
|
8
|
+
version: "0.20"
|
9
9
|
platform: ruby
|
10
10
|
authors:
|
11
11
|
- Assaf Arkin
|
@@ -30,7 +30,7 @@ dependencies:
|
|
30
30
|
type: :runtime
|
31
31
|
version_requirements: *id001
|
32
32
|
- !ruby/object:Gem::Dependency
|
33
|
-
name:
|
33
|
+
name: i18n
|
34
34
|
prerelease: false
|
35
35
|
requirement: &id002 !ruby/object:Gem::Requirement
|
36
36
|
none: false
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
type: :runtime
|
44
44
|
version_requirements: *id002
|
45
45
|
- !ruby/object:Gem::Dependency
|
46
|
-
name:
|
46
|
+
name: json
|
47
47
|
prerelease: false
|
48
48
|
requirement: &id003 !ruby/object:Gem::Requirement
|
49
49
|
none: false
|
@@ -56,7 +56,7 @@ dependencies:
|
|
56
56
|
type: :runtime
|
57
57
|
version_requirements: *id003
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
|
-
name:
|
59
|
+
name: nokogiri
|
60
60
|
prerelease: false
|
61
61
|
requirement: &id004 !ruby/object:Gem::Requirement
|
62
62
|
none: false
|
@@ -69,7 +69,7 @@ dependencies:
|
|
69
69
|
type: :runtime
|
70
70
|
version_requirements: *id004
|
71
71
|
- !ruby/object:Gem::Dependency
|
72
|
-
name:
|
72
|
+
name: rack
|
73
73
|
prerelease: false
|
74
74
|
requirement: &id005 !ruby/object:Gem::Requirement
|
75
75
|
none: false
|
@@ -81,6 +81,19 @@ dependencies:
|
|
81
81
|
version: "0"
|
82
82
|
type: :runtime
|
83
83
|
version_requirements: *id005
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: sanitize
|
86
|
+
prerelease: false
|
87
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
segments:
|
93
|
+
- 0
|
94
|
+
version: "0"
|
95
|
+
type: :runtime
|
96
|
+
version_requirements: *id006
|
84
97
|
description:
|
85
98
|
email: assaf@labnotes.org
|
86
99
|
executables: []
|
@@ -94,6 +107,8 @@ files:
|
|
94
107
|
- lib/dash-fu/bee.rb
|
95
108
|
- lib/dash-fu/bees/backtweets.rb
|
96
109
|
- lib/dash-fu/bees/backtweets.yml
|
110
|
+
- lib/dash-fu/bees/feed.rb
|
111
|
+
- lib/dash-fu/bees/feed.yml
|
97
112
|
- lib/dash-fu/bees/github.rb
|
98
113
|
- lib/dash-fu/bees/github.yml
|
99
114
|
- lib/dash-fu/bees/github_issues.rb
|
@@ -103,9 +118,11 @@ files:
|
|
103
118
|
- test/api_keys.yml
|
104
119
|
- test/backtweets_test.rb
|
105
120
|
- test/cassettes/backtweets.yml
|
121
|
+
- test/cassettes/feed.yml
|
106
122
|
- test/cassettes/github.yml
|
107
123
|
- test/cassettes/github_issues.yml
|
108
124
|
- test/cassettes/ruby_gems.yml
|
125
|
+
- test/feed_test.rb
|
109
126
|
- test/github_issues_test.rb
|
110
127
|
- test/github_test.rb
|
111
128
|
- test/helpers/activity.rb
|
@@ -129,7 +146,7 @@ licenses: []
|
|
129
146
|
post_install_message:
|
130
147
|
rdoc_options:
|
131
148
|
- --title
|
132
|
-
- DashFu::Bee 0.
|
149
|
+
- DashFu::Bee 0.20
|
133
150
|
- --main
|
134
151
|
- README.rdoc
|
135
152
|
- --webcvs
|