ardekantur-wondercroc 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +31 -1
- data/Rakefile +8 -3
- data/lib/wondercroc.rb +6 -1
- data/lib/wondercroc/client.rb +43 -23
- data/lib/wondercroc/folder.rb +43 -12
- data/lib/wondercroc/location.rb +0 -11
- metadata +3 -2
data/README.rdoc
CHANGED
@@ -1,3 +1,33 @@
|
|
1
1
|
= wondercroc
|
2
2
|
|
3
|
-
A gem that provides
|
3
|
+
A gem that provides functionality for interfacing with the NewsGator online feed reading service.
|
4
|
+
|
5
|
+
= simple to use
|
6
|
+
|
7
|
+
c = WonderCroc::Client.new :user => 'newsgator_user', :password => 'newsgator_pass', :location => 'newsgator_location'
|
8
|
+
|
9
|
+
Or, if you have a YAML file like this:
|
10
|
+
|
11
|
+
user: newsgator_user
|
12
|
+
password: newsgator_password
|
13
|
+
location: newsgator_location
|
14
|
+
|
15
|
+
You can pass it in like this:
|
16
|
+
|
17
|
+
c = WonderCroc::Client.new :file => '/path/to/config.yml'
|
18
|
+
|
19
|
+
If you don't specify a location anywhere, it will default to the name of the library, a hyphen, and the name of your machine (in all caps), like thus:
|
20
|
+
|
21
|
+
wondercroc-MY_IMAC
|
22
|
+
|
23
|
+
= folders
|
24
|
+
|
25
|
+
Folders are a tree of the folders you have at the location you specified previously.
|
26
|
+
|
27
|
+
c.get_folders
|
28
|
+
|
29
|
+
= subscriptions
|
30
|
+
|
31
|
+
c.get_subscriptions_from_location
|
32
|
+
|
33
|
+
That's kind of where I am right now, poke around in irb to get a better feel for what you can do from there.
|
data/Rakefile
CHANGED
@@ -8,7 +8,7 @@ require 'spec/rake/verify_rcov'
|
|
8
8
|
|
9
9
|
|
10
10
|
GEM = "wondercroc"
|
11
|
-
GEM_VERSION = "0.0.
|
11
|
+
GEM_VERSION = "0.0.5"
|
12
12
|
AUTHOR = "Ardekantur"
|
13
13
|
EMAIL = "greystone@ardekantur.com"
|
14
14
|
HOMEPAGE = "http://github.com/ardekantur/wondercroc"
|
@@ -59,10 +59,15 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
59
59
|
rdoc.rdoc_dir = 'doc' # rdoc output folder
|
60
60
|
end
|
61
61
|
|
62
|
-
desc "
|
62
|
+
desc "run specs"
|
63
|
+
Spec::Rake::SpecTask.new("spec") do |t|
|
64
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
65
|
+
end
|
66
|
+
|
67
|
+
desc "run rspec + rcov"
|
63
68
|
Spec::Rake::SpecTask.new("spec:rcov") do |t|
|
64
69
|
t.spec_files = FileList['spec/**/*_spec.rb']
|
65
|
-
t.rcov_opts = ['--exclude', "spec/,rcov.rb,rspec.rb,spec*"]
|
70
|
+
t.rcov_opts = ['--exclude', "spec/,rcov.rb,rspec.rb,spec*,gems*"]
|
66
71
|
t.rcov = true
|
67
72
|
t.rcov_dir = 'doc/coverage'
|
68
73
|
end
|
data/lib/wondercroc.rb
CHANGED
@@ -1 +1,6 @@
|
|
1
|
-
|
1
|
+
|
2
|
+
# WonderCroc is a library for retrieving subscriptions from a NewsGator online RSS feed reading account.
|
3
|
+
# Please see the README for more information.
|
4
|
+
module WonderCroc; end;
|
5
|
+
|
6
|
+
%w{ config client folder location subscription }.each { |x| require "wondercroc/#{x}" }
|
data/lib/wondercroc/client.rb
CHANGED
@@ -2,20 +2,18 @@ require 'rubygems'
|
|
2
2
|
require 'rest_client'
|
3
3
|
require 'rexml/document'
|
4
4
|
require 'rss/2.0'
|
5
|
-
|
6
|
-
# NewsGator is a Ruby layer for interacting with the
|
7
|
-
# NewsGator API.
|
8
5
|
|
9
6
|
module WonderCroc
|
10
7
|
|
8
|
+
VERSION = [ 0, 0, 5 ].join '.'
|
9
|
+
|
11
10
|
class Client
|
12
11
|
|
13
|
-
VERSION = [ 0, 0, 4 ].join '.'
|
14
12
|
SERVICE = "http://services.newsgator.com/ngws/svc"
|
15
13
|
|
16
14
|
BULLETIN_TOKEN = {
|
17
15
|
"X-NGAPITOKEN" => "A8BBE03745F2439287D9425AB4BFFC30",
|
18
|
-
"User-Agent" => "wondercroc/#{VERSION}",
|
16
|
+
"User-Agent" => "wondercroc/#{WonderCroc::VERSION}",
|
19
17
|
"Accept-Encoding" => "compress,gzip"
|
20
18
|
}
|
21
19
|
|
@@ -23,13 +21,22 @@ module WonderCroc
|
|
23
21
|
attr_accessor :folders
|
24
22
|
|
25
23
|
# Initializes an instance of a NewsGator Client.
|
26
|
-
# +
|
27
|
-
#
|
28
|
-
#
|
29
|
-
|
30
|
-
|
24
|
+
# +config_options+ is a hash consisting of either all the informatio
|
25
|
+
# required to start a NewsGator connection (:user, :password, and :location),
|
26
|
+
# or the name of a file that has all those values in a YAML file (:file).
|
27
|
+
#
|
28
|
+
# We then set the location from the configuration hash passed through
|
29
|
+
# at the instantsiation of the Client object. If a +:location+
|
30
|
+
# key was not passed with that has, the location name is generated
|
31
|
+
# like so: 'newsgator_account_name-MACHINE_HOSTNAME'.
|
32
|
+
def initialize config_options
|
33
|
+
@config = WonderCroc::Configuration.new config_options
|
31
34
|
@folder_unread_counts = {}
|
32
|
-
|
35
|
+
|
36
|
+
get_locations
|
37
|
+
@location = @locations.find { |l| l[:title] == @config.location }
|
38
|
+
raise "no location found for name #{@config.location}" unless @location
|
39
|
+
|
33
40
|
end
|
34
41
|
|
35
42
|
def get_feed id, unread = true
|
@@ -37,19 +44,13 @@ module WonderCroc
|
|
37
44
|
send_request :get
|
38
45
|
end
|
39
46
|
|
40
|
-
def get_random_feed
|
41
|
-
raise "no feeds" unless @subscriptions
|
42
|
-
get_feed @subscriptions[(rand * @subscriptions.length).floor].id, false
|
43
|
-
end
|
44
|
-
|
45
47
|
def parse_stories
|
46
48
|
p = RSS::Parser.new @response
|
47
49
|
p.do_validate = false
|
48
50
|
p.parse
|
49
51
|
end
|
50
52
|
|
51
|
-
def get_unread_counts
|
52
|
-
ui.update_status 'Getting subscription counts...' if ui
|
53
|
+
def get_unread_counts
|
53
54
|
new_connection_to "/Subscription.aspx/#{@location[:id]}/subscriptionCounts"
|
54
55
|
send_request :get
|
55
56
|
doc = REXML::Document.new @response
|
@@ -57,26 +58,46 @@ module WonderCroc
|
|
57
58
|
@folder_unread_counts[e.attributes['ng:folderId']] = @folder_unread_counts.fetch(e.attributes['ng:folderId'], 0) + e.attributes['ng:unreadCount'].to_i
|
58
59
|
end
|
59
60
|
@folders.flatten.each { |f| f.unread_count = @folder_unread_counts.fetch(f.id, 0) }
|
60
|
-
ui.update_status ''
|
61
61
|
end
|
62
62
|
|
63
63
|
private
|
64
64
|
|
65
65
|
def new_connection_to url
|
66
|
-
@request = RestClient::Resource.new(SERVICE + url, @config
|
66
|
+
@request = RestClient::Resource.new(SERVICE + url, @config.user, @config.password)
|
67
67
|
end
|
68
68
|
|
69
69
|
def send_request type, headers = {}
|
70
70
|
raise ArgumentError, "invalid send request type #{type}" unless [ :get, :delete ].include? type
|
71
|
-
|
71
|
+
|
72
|
+
begin
|
73
|
+
@response = @request.send type, BULLETIN_TOKEN.merge(headers)
|
74
|
+
rescue RestClient::Unauthorized
|
75
|
+
raise IncorrectLoginError, "#{@config.user} was not able to login"
|
76
|
+
end
|
77
|
+
|
78
|
+
log_request_and_response
|
72
79
|
end
|
73
80
|
|
74
81
|
def send_data type, payload, headers = {}
|
75
82
|
raise ArgumentError, "invalid send data request type #{type}" unless [ :put, :post ].include? type
|
76
83
|
@response = @request.send type, payload, BULLETIN_TOKEN.merge(headers)
|
84
|
+
|
85
|
+
log_request_and_response
|
86
|
+
end
|
87
|
+
|
88
|
+
def log_request_and_response
|
89
|
+
File.open(File.join(ENV['HOME'], 'wondercroc_logs'), 'a') do |f|
|
90
|
+
f.write "REQUEST TO: #{@request.inspect}\n"
|
91
|
+
f.write "RESPONSE: #{@response}"
|
92
|
+
f.write "\n\n\n"
|
93
|
+
end
|
77
94
|
end
|
78
95
|
|
79
96
|
end
|
97
|
+
|
98
|
+
class IncorrectLoginError < RuntimeError
|
99
|
+
end
|
100
|
+
|
80
101
|
end
|
81
102
|
|
82
103
|
class RSS::Rss::Channel::Item
|
@@ -86,8 +107,7 @@ class RSS::Rss::Channel::Item
|
|
86
107
|
["postId", :integer ],
|
87
108
|
["avgRating", :float ],
|
88
109
|
["clipped", :boolean ],
|
89
|
-
["token", :text ]
|
90
|
-
["folderId", :text ]
|
110
|
+
["token", :text ]
|
91
111
|
].each do |elem, type|
|
92
112
|
install_text_element "ng:#{elem}", "http://newsgator.com/schema/extensions", '?', "#{elem}", type, "ng:#{elem}"
|
93
113
|
RSS::BaseListener.install_get_text_element "http://newsgator.com/schema/extensions", "#{elem}", "#{elem}="
|
data/lib/wondercroc/folder.rb
CHANGED
@@ -1,15 +1,28 @@
|
|
1
|
-
# A folder is a folder that resides in a NewsGator location.
|
2
|
-
# It can contain subscriptions and other folders.
|
3
1
|
|
4
2
|
module WonderCroc
|
3
|
+
|
4
|
+
class Client
|
5
|
+
|
6
|
+
def find_folder_by_id folder_id
|
7
|
+
@subfolders.each { |subfolder| return subfolder if subfolder and subfolder.find_by_id folder_id}
|
8
|
+
return nil
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
# A folder is a folder that resides in a NewsGator location.
|
14
|
+
# It can contain subscriptions and other folders.
|
5
15
|
class Folder
|
6
16
|
|
7
|
-
attr_accessor :
|
17
|
+
attr_accessor :folder_id, :name
|
18
|
+
attr_reader :unread_count
|
8
19
|
|
9
20
|
def initialize name, id
|
21
|
+
raise ArgumentException unless name
|
10
22
|
@name = name
|
11
|
-
@
|
23
|
+
@folder_id = id
|
12
24
|
@unread_count = 0
|
25
|
+
@subfolders = []
|
13
26
|
end
|
14
27
|
|
15
28
|
def to_str
|
@@ -17,6 +30,23 @@ class Folder
|
|
17
30
|
return "#{@name} (#{@unread_count})"
|
18
31
|
end
|
19
32
|
|
33
|
+
def subfolders
|
34
|
+
return @subfolders
|
35
|
+
end
|
36
|
+
|
37
|
+
def << subfolder
|
38
|
+
@subfolders << subfolder
|
39
|
+
end
|
40
|
+
|
41
|
+
def merge array
|
42
|
+
@subfolders += array if array
|
43
|
+
end
|
44
|
+
|
45
|
+
def find_by_id id
|
46
|
+
return self if @folder_id == id
|
47
|
+
@subfolders.each { |subfolder| return subfolder if subfolder.find_by_id id}
|
48
|
+
end
|
49
|
+
|
20
50
|
end
|
21
51
|
|
22
52
|
class Client
|
@@ -25,28 +55,29 @@ class Client
|
|
25
55
|
def get_folders
|
26
56
|
new_connection_to "/Folder.aspx"
|
27
57
|
send_request :get
|
28
|
-
@folders = folders_from_xml(@response)
|
58
|
+
@folders = folders_from_xml(@response).subfolders
|
29
59
|
end
|
30
60
|
|
31
61
|
private
|
32
62
|
|
33
63
|
def folders_from_xml xml
|
34
|
-
|
64
|
+
root_folder = Folder.new 'Root', -1
|
35
65
|
doc = REXML::Document.new xml
|
36
66
|
doc.elements.each('opml/body/outline') do |e|
|
37
|
-
dir =
|
38
|
-
dir
|
39
|
-
|
67
|
+
dir = Folder.new e.attributes['title'], e.attributes['ng:id']
|
68
|
+
dir.merge subfolders(e)
|
69
|
+
root_folder << dir
|
40
70
|
end
|
41
|
-
return
|
71
|
+
return root_folder
|
42
72
|
end
|
43
73
|
|
44
74
|
def subfolders element
|
45
75
|
return nil if element.elements.size == 0
|
46
76
|
folders = []
|
47
77
|
element.each do |e|
|
48
|
-
|
49
|
-
|
78
|
+
folder = Folder.new(e.attributes['title'], e.attributes['ng:id'])
|
79
|
+
folder.merge subfolders(e)
|
80
|
+
folders << folder
|
50
81
|
end
|
51
82
|
|
52
83
|
return folders.compact
|
data/lib/wondercroc/location.rb
CHANGED
@@ -7,17 +7,6 @@ class Client
|
|
7
7
|
@locations = []
|
8
8
|
end
|
9
9
|
|
10
|
-
# Sets the location from the configuration hash passed through
|
11
|
-
# at the instantsiation of the Client object. If a +:location+
|
12
|
-
# key was not passed with that has, the location name is generated
|
13
|
-
# like so: 'newsgator_account_name-MACHINE_HOSTNAME'.
|
14
|
-
def set_location_from_config
|
15
|
-
get_locations
|
16
|
-
@config[:location] ||= "#{@config[:user]}-#{`hostname`.strip.upcase}"
|
17
|
-
@location = @locations.find { |l| l[:title] == @config[:location] }
|
18
|
-
raise "no location found for name #{@config.location}" unless @location
|
19
|
-
end
|
20
|
-
|
21
10
|
# Retrieves a list of all the locations that the logged in user
|
22
11
|
# has available.
|
23
12
|
def get_locations
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ardekantur-wondercroc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ardekantur
|
@@ -9,7 +9,7 @@ autorequire: wondercroc
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-07-
|
12
|
+
date: 2008-07-06 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -30,6 +30,7 @@ files:
|
|
30
30
|
- TODO
|
31
31
|
- lib/wondercroc
|
32
32
|
- lib/wondercroc/client.rb
|
33
|
+
- lib/wondercroc/config.rb
|
33
34
|
- lib/wondercroc/folder.rb
|
34
35
|
- lib/wondercroc/location.rb
|
35
36
|
- lib/wondercroc/subscription.rb
|