times_wire 0.5.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/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Rakefile +9 -0
- data/lib/times_wire/base.rb +71 -0
- data/lib/times_wire/item.rb +54 -0
- data/lib/times_wire/version.rb +3 -0
- data/lib/times_wire.rb +3 -0
- data/test/test_helper.rb +15 -0
- data/test/times_wire/test_item.rb +63 -0
- data/times_wire.gemspec +23 -0
- metadata +91 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'open-uri'
|
3
|
+
require 'json'
|
4
|
+
require 'date'
|
5
|
+
|
6
|
+
module TimesWire
|
7
|
+
class Base
|
8
|
+
API_SERVER = 'api.nytimes.com'
|
9
|
+
API_VERSION = 'v3'
|
10
|
+
API_NAME = 'news'
|
11
|
+
API_BASE = "/svc/#{API_NAME}/#{API_VERSION}/content"
|
12
|
+
|
13
|
+
@@api_key = nil
|
14
|
+
@@debug = false
|
15
|
+
@@copyright = nil
|
16
|
+
|
17
|
+
# The copyright footer to be placed at the bottom of any data from the New York Times. Note this is only set after an API call.
|
18
|
+
def copyright
|
19
|
+
@@copyright
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# Set the API key used for operations. This needs to be called before any requests against the API. To obtain an API key, go to http://developer.nytimes.com/
|
24
|
+
def self.api_key=(key)
|
25
|
+
@@api_key = key
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.api_key
|
29
|
+
@@api_key
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.date_parser(date)
|
33
|
+
date ? Date.parse(date) : nil
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# Builds a request URI to call the API server
|
38
|
+
def self.build_request_url(path, params)
|
39
|
+
URI::HTTP.build :host => API_SERVER, :path => "#{API_BASE}/#{path}.json", :query => params.map {|k,v| "#{k}=#{v}"}.join('&')
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.invoke(path, params={})
|
43
|
+
begin
|
44
|
+
if @@api_key.nil?
|
45
|
+
raise "You must initialize the API key before you run any API queries"
|
46
|
+
end
|
47
|
+
|
48
|
+
full_params = params.merge 'api-key' => @@api_key
|
49
|
+
|
50
|
+
uri = build_request_url(path, full_params)
|
51
|
+
|
52
|
+
reply = uri.read
|
53
|
+
parsed_reply = JSON.parse reply
|
54
|
+
|
55
|
+
if parsed_reply.nil?
|
56
|
+
raise "Empty reply returned from API"
|
57
|
+
end
|
58
|
+
|
59
|
+
@@copyright = parsed_reply['copyright']
|
60
|
+
|
61
|
+
parsed_reply
|
62
|
+
rescue OpenURI::HTTPError => e
|
63
|
+
if e.message =~ /^404/
|
64
|
+
return nil
|
65
|
+
end
|
66
|
+
|
67
|
+
raise "Error connecting to URL #{uri} #{e}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module TimesWire
|
2
|
+
class Item < Base
|
3
|
+
|
4
|
+
attr_reader :section, :title, :abstract, :url, :byline, :item_type, :source, :updated_date, :created_date,
|
5
|
+
:published_date, :material_type_facet, :kicker, :subheadline, :multimedia, :des_facets, :org_facets,
|
6
|
+
:per_facets, :geo_facets, :related_urls
|
7
|
+
|
8
|
+
def initialize(params={})
|
9
|
+
params.each_pair do |k,v|
|
10
|
+
instance_variable_set("@#{k}", v)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.create_from_api(params={})
|
15
|
+
self.new :section => params['section'],
|
16
|
+
:title => params['title'],
|
17
|
+
:abstract => params['abstract'],
|
18
|
+
:url => params['url'],
|
19
|
+
:byline => params['byline'],
|
20
|
+
:item_type => params['item_type'],
|
21
|
+
:source => params['source'],
|
22
|
+
:updated_date => date_parser(params['updated_date']),
|
23
|
+
:created_date => date_parser(params['created_date']),
|
24
|
+
:published_date => date_parser(params['published_date']),
|
25
|
+
:material_type_facet => params['material_type_facet'],
|
26
|
+
:kicker => params['kicker'],
|
27
|
+
:subheadline => params['subheadline'],
|
28
|
+
:multimedia => params['multimedia'],
|
29
|
+
:des_facets => params['des_facet'],
|
30
|
+
:org_facets => params['org_facet'],
|
31
|
+
:per_facets => params['per_facet'],
|
32
|
+
:geo_facets => params['geo_facet'],
|
33
|
+
:related_urls => params['related_urls']
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.latest(source="nyt", limit=20)
|
37
|
+
reply = Base.invoke("#{source}/all", {"limit" => limit})
|
38
|
+
results = reply['results']
|
39
|
+
@items = results.map {|r| Item.create_from_api(r)}
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.section(source='nyt', section=section, limit=20)
|
43
|
+
reply = Base.invoke("#{source}/#{section}/", {"limit" => limit})
|
44
|
+
results = reply['results']
|
45
|
+
@items = results.map {|r| Item.create_from_api(r)}
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.blog_name(source='nyt', section=section, blog=blog, limit=20)
|
49
|
+
reply = Base.invoke("#{source}/#{section}/", {"limit" => limit})
|
50
|
+
results = reply['results'].select{|i| i['blog_name'] == blog}
|
51
|
+
@items = results.map {|r| Item.create_from_api(r)}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/times_wire.rb
ADDED
data/test/test_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'shoulda'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
%w(base item).each do |f|
|
7
|
+
require File.join(File.dirname(__FILE__), '../lib/times_wire', f)
|
8
|
+
end
|
9
|
+
|
10
|
+
# set your NYT Times Newswire API key as an environment variable to run the tests
|
11
|
+
API_KEY = ENV['NYT_TIMESWIRE_API_KEY']
|
12
|
+
TimesWire::Base.api_key = API_KEY
|
13
|
+
|
14
|
+
module TestTimesWire
|
15
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
class TestTimesWire::TestItem < Test::Unit::TestCase
|
2
|
+
include TimesWire
|
3
|
+
|
4
|
+
context "create single Item" do
|
5
|
+
setup do
|
6
|
+
reply = Base.invoke('', {"url" => "http://www.nytimes.com/2010/12/17/world/asia/17sanger.html"})
|
7
|
+
@result = reply['results'].first
|
8
|
+
@item = Item.create_from_api(@result)
|
9
|
+
end
|
10
|
+
|
11
|
+
should "return an object of the Item type" do
|
12
|
+
assert_kind_of(Item, @item)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "create list of items from NYT only" do
|
17
|
+
setup do
|
18
|
+
@items = Item.latest('nyt')
|
19
|
+
end
|
20
|
+
|
21
|
+
should "return an array of 20 objects of the Item type from the NYT alone" do
|
22
|
+
assert_equal(20, @items.size)
|
23
|
+
assert_kind_of(Item, @items.first)
|
24
|
+
assert_equal(["The New York Times"], @items.map {|i| i.source}.uniq)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "create list of 15 items from IHT only" do
|
29
|
+
setup do
|
30
|
+
@items = Item.latest('iht', 15)
|
31
|
+
end
|
32
|
+
|
33
|
+
should "return an array of 15 objects of the Item type from the IHT alone" do
|
34
|
+
assert_equal(15, @items.size)
|
35
|
+
assert_kind_of(Item, @items.first)
|
36
|
+
assert_equal(["International Herald Tribune"], @items.map {|i| i.source}.uniq)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "create list of 20 items from the World section of NYT" do
|
41
|
+
setup do
|
42
|
+
@items = Item.section('nyt', 'World', 20)
|
43
|
+
end
|
44
|
+
|
45
|
+
should "return an array of 20 objects of the Item type from the NYT World section" do
|
46
|
+
assert_equal(20, @items.size)
|
47
|
+
assert_kind_of(Item, @items.first)
|
48
|
+
assert_equal(["World"], @items.map {|i| i.section}.uniq)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "create list of items from The Caucus blog" do
|
53
|
+
setup do
|
54
|
+
@items = Item.blog_name('nyt', 'U.S.', 'The Caucus')
|
55
|
+
end
|
56
|
+
|
57
|
+
should "return an array of objects of the Item type from the NYT U.S. section and Caucus blog" do
|
58
|
+
assert_kind_of(Item, @items.first)
|
59
|
+
assert_equal(["The Caucus"], @items.map {|i| i.kicker}.uniq)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
data/times_wire.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "times_wire/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "times_wire"
|
7
|
+
s.version = TimesWire::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Derek Willis"]
|
10
|
+
s.email = ["dwillis@gmail.com"]
|
11
|
+
s.homepage = "http://rubygems.org/gems/times_wire"
|
12
|
+
s.summary = %q{A thin client for The New York Times Newswire API}
|
13
|
+
s.description = %q{A Ruby library for parsing stories and blog posts from The New York Times Newswire API}
|
14
|
+
|
15
|
+
s.rubyforge_project = "times_wire"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_development_dependency "shoulda"
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: times_wire
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 11
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 5
|
9
|
+
- 0
|
10
|
+
version: 0.5.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Derek Willis
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-12-13 00:00:00 -05:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: shoulda
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
description: A Ruby library for parsing stories and blog posts from The New York Times Newswire API
|
36
|
+
email:
|
37
|
+
- dwillis@gmail.com
|
38
|
+
executables: []
|
39
|
+
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files: []
|
43
|
+
|
44
|
+
files:
|
45
|
+
- .gitignore
|
46
|
+
- Gemfile
|
47
|
+
- Rakefile
|
48
|
+
- lib/times_wire.rb
|
49
|
+
- lib/times_wire/base.rb
|
50
|
+
- lib/times_wire/item.rb
|
51
|
+
- lib/times_wire/version.rb
|
52
|
+
- test/test_helper.rb
|
53
|
+
- test/times_wire/test_item.rb
|
54
|
+
- times_wire.gemspec
|
55
|
+
has_rdoc: true
|
56
|
+
homepage: http://rubygems.org/gems/times_wire
|
57
|
+
licenses: []
|
58
|
+
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
hash: 3
|
70
|
+
segments:
|
71
|
+
- 0
|
72
|
+
version: "0"
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
hash: 3
|
79
|
+
segments:
|
80
|
+
- 0
|
81
|
+
version: "0"
|
82
|
+
requirements: []
|
83
|
+
|
84
|
+
rubyforge_project: times_wire
|
85
|
+
rubygems_version: 1.6.2
|
86
|
+
signing_key:
|
87
|
+
specification_version: 3
|
88
|
+
summary: A thin client for The New York Times Newswire API
|
89
|
+
test_files:
|
90
|
+
- test/test_helper.rb
|
91
|
+
- test/times_wire/test_item.rb
|