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.
@@ -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.4"
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 "Run RSpec and Rcov"
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
@@ -1 +1,6 @@
1
- %w{ client folder location subscription }.each { |x| require "wondercroc/#{x}" }
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}" }
@@ -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
- # +config_obj+ is a hash consisting of the keys
27
- # +:name+, +:password+, and +:location+, if you do
28
- # not want WonderCroc auto-generating a location name.
29
- def initialize config_obj
30
- @config = config_obj
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
- self.clear_locations
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 ui = nil
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[:user], @config[:password])
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
- @response = @request.send type, BULLETIN_TOKEN.merge(headers)
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}="
@@ -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 :id, :name, :unread_count
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
- @id = id
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
- folders = []
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 = [ Folder.new(e.attributes['title'], e.attributes['ng:id']) ]
38
- dir << subfolders(e)
39
- folders << dir.compact
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 folders.compact
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
- folders << Folder.new(e.attributes['title'], e.attributes['ng:id'])
49
- folders << subfolders(e)
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
@@ -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
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-01 00:00:00 -07:00
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