podrick 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/Gemfile +1 -2
- data/Gemfile.lock +1 -1
- data/lib/podrick/episode.rb +118 -0
- data/lib/podrick/podcast.rb +85 -0
- data/lib/podrick/version.rb +3 -0
- data/lib/podrick.rb +3 -0
- data/podrick.gemspec +22 -0
- metadata +10 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 536e37c7db0e1838aa7724b073196ae93d6cb766
|
|
4
|
+
data.tar.gz: 11e8dd2d9cb41eef89adba3d5bbe169aaff6a92d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4229d70b08d51da6d6968ada268b1984a75404820d4a4984d543124e07f7fd115c70d655b7849b0328dbc70f22184fa2f472c4fb212939a0da711bc784581af6
|
|
7
|
+
data.tar.gz: 2be72c8b86c1de2132258456be1780b761e2d407e2883d5ea2f88f6c8282790096898297a5f1d95c2ad6612bbffb0f2c99537a94b7dc0565ef1358149c360fb6
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
module Podrick
|
|
2
|
+
class Episode
|
|
3
|
+
attr_reader :xml_doc, :images
|
|
4
|
+
|
|
5
|
+
def initialize xml_doc
|
|
6
|
+
@xml_doc = xml_doc
|
|
7
|
+
@images = []
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
%w[title link guid author].each do |method|
|
|
11
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
12
|
+
def #{method}
|
|
13
|
+
instance_variable_get("@#{method}") || instance_variable_set("@#{method}", xml_content_at("#{method}"))
|
|
14
|
+
end
|
|
15
|
+
RUBY
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def description
|
|
19
|
+
@description ||= load_without_images("description")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def published_date
|
|
23
|
+
@published_date ||= Time.parse(xml_doc.at_xpath("pubDate").content)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
alias pubDate published_date
|
|
27
|
+
|
|
28
|
+
def content
|
|
29
|
+
@content ||= content_without_images
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def enclosure
|
|
33
|
+
@enclosure ||= begin
|
|
34
|
+
enclosure_struct = Struct.new(:url, :length, :type)
|
|
35
|
+
enclosure = xml_doc.at_xpath("enclosure")
|
|
36
|
+
if enclosure
|
|
37
|
+
enclosure_struct.new(
|
|
38
|
+
enclosure["url"],
|
|
39
|
+
enclosure["length"],
|
|
40
|
+
enclosure["type"]
|
|
41
|
+
)
|
|
42
|
+
else
|
|
43
|
+
enclosure_struct.new(nil, nil, nil)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def itunes
|
|
49
|
+
@itunes ||= begin
|
|
50
|
+
image = Struct.new(:href)
|
|
51
|
+
itunes = Struct.new(:author, :duration, :subtitle, :summary, :keywords, :image)
|
|
52
|
+
image_href = (node = xml_node_at("itunes:image")) ? node["href"] : nil
|
|
53
|
+
|
|
54
|
+
itunes.new(
|
|
55
|
+
xml_content_at("itunes:author"),
|
|
56
|
+
xml_content_at("itunes:duration"),
|
|
57
|
+
xml_content_at("itunes:subtitle"),
|
|
58
|
+
xml_content_at("itunes:summary"),
|
|
59
|
+
xml_content_at("itunes:keywords"),
|
|
60
|
+
image.new(image_href)
|
|
61
|
+
)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def add_image url, width = nil, height = nil
|
|
66
|
+
image_struct = Struct.new(:url, :width, :height)
|
|
67
|
+
|
|
68
|
+
@images << image_struct.new(url, width, height)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def xml_content_at string
|
|
72
|
+
begin
|
|
73
|
+
if node = xml_doc.at_xpath(string)
|
|
74
|
+
node.content
|
|
75
|
+
end
|
|
76
|
+
rescue Nokogiri::XML::XPath::SyntaxError
|
|
77
|
+
nil
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def xml_node_at string
|
|
82
|
+
if node = xml_doc.at_xpath(string)
|
|
83
|
+
node
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
private
|
|
88
|
+
|
|
89
|
+
def content_without_images
|
|
90
|
+
begin
|
|
91
|
+
load_without_images("content:encoded")
|
|
92
|
+
rescue Nokogiri::XML::XPath::SyntaxError
|
|
93
|
+
nil
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def load_without_images node_name
|
|
98
|
+
node = xml_node_at(node_name)
|
|
99
|
+
|
|
100
|
+
return nil if node.nil?
|
|
101
|
+
|
|
102
|
+
html = Nokogiri::HTML(node.content)
|
|
103
|
+
html.xpath("//img").each do |img|
|
|
104
|
+
if img.key?("src")
|
|
105
|
+
url = img["src"]
|
|
106
|
+
height = img["height"]
|
|
107
|
+
width = img["width"]
|
|
108
|
+
|
|
109
|
+
add_image(url, width, height)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
img.remove
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
html.to_html
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
require 'faraday'
|
|
2
|
+
require 'nokogiri'
|
|
3
|
+
|
|
4
|
+
module Podrick
|
|
5
|
+
class Podcast
|
|
6
|
+
attr_reader :etag
|
|
7
|
+
|
|
8
|
+
def initialize xml_string, etag = nil
|
|
9
|
+
@xml = xml_string
|
|
10
|
+
@etag = etag
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.from_xml xml_string, etag = nil
|
|
14
|
+
new(xml_string, etag)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.from_url url, etag = nil
|
|
18
|
+
headers = {}
|
|
19
|
+
|
|
20
|
+
if etag
|
|
21
|
+
headers['If-None-Match'] = etag
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
response = Faraday.get(url, {}, headers)
|
|
25
|
+
|
|
26
|
+
if response.status == 304
|
|
27
|
+
nil
|
|
28
|
+
else
|
|
29
|
+
new(response.body, response.headers['ETag'])
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def xml_doc
|
|
34
|
+
@xml_doc ||= Nokogiri::XML(@xml)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def xml_metadata
|
|
38
|
+
@xml_metadata ||= xml_doc.xpath('/rss/channel/*[not(self::item)]')
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
%w[link title description language].each do |method|
|
|
42
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
43
|
+
def #{method}
|
|
44
|
+
instance_variable_get("@#{method}") || instance_variable_set("@#{method}", xml_content_at("//#{method}"))
|
|
45
|
+
end
|
|
46
|
+
RUBY
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def itunes
|
|
50
|
+
@itunes ||= begin
|
|
51
|
+
image = Struct.new(:href)
|
|
52
|
+
owner = Struct.new(:name, :email)
|
|
53
|
+
itunes = Struct.new(:subtitle, :author, :summary, :keywords, :explicit, :category, :subcategories, :image, :owner)
|
|
54
|
+
|
|
55
|
+
itunes.new(
|
|
56
|
+
xml_content_at("//itunes:subtitle"),
|
|
57
|
+
xml_content_at("//itunes:author"),
|
|
58
|
+
xml_content_at("//itunes:summary"),
|
|
59
|
+
xml_content_at("//itunes:keywords"),
|
|
60
|
+
xml_content_at("//itunes:explicit"),
|
|
61
|
+
xml_node_at("//itunes:category")["text"],
|
|
62
|
+
xml_doc.xpath("//itunes:category//itunes:category").map { |category| category["text"] },
|
|
63
|
+
image.new(xml_node_at("//itunes:image")["href"]),
|
|
64
|
+
owner.new(xml_content_at("//itunes:owner//itunes:name"), xml_content_at("//itunes:owner//itunes:email"))
|
|
65
|
+
)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def xml_content_at string
|
|
70
|
+
if node = xml_metadata.at_xpath(string)
|
|
71
|
+
node.content
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def xml_node_at string
|
|
76
|
+
if node = xml_metadata.at_xpath(string)
|
|
77
|
+
node
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def episodes
|
|
82
|
+
@episodes ||= xml_doc.xpath('//item').map { |item_xml| Episode.new(item_xml) }
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
data/lib/podrick.rb
ADDED
data/podrick.gemspec
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
require File.expand_path('../lib/podrick/version', __FILE__)
|
|
3
|
+
|
|
4
|
+
Gem::Specification.new do |gem|
|
|
5
|
+
gem.name = "podrick"
|
|
6
|
+
gem.author = "Scott Bader"
|
|
7
|
+
gem.email = "sbader2@gmail.com"
|
|
8
|
+
gem.summary = "A simple library to work with podcasts"
|
|
9
|
+
gem.description = "Podrick is a library that allows you to quickly, and easily work with a podcast feed. You can parse a feed, see the newest episodes, and download files"
|
|
10
|
+
gem.homepage = "http://sbader.github.com/castpod"
|
|
11
|
+
gem.license = "MIT"
|
|
12
|
+
|
|
13
|
+
gem.version = Podrick::VERSION
|
|
14
|
+
|
|
15
|
+
gem.files = `git ls-files`.split("\n")
|
|
16
|
+
gem.test_files = `git ls-files -- test/*`.split("\n")
|
|
17
|
+
|
|
18
|
+
gem.add_dependency 'faraday', '~> 0.8.8'
|
|
19
|
+
gem.add_dependency 'nokogiri', '~> 1.6.0'
|
|
20
|
+
gem.add_development_dependency 'minitest', '~> 4'
|
|
21
|
+
gem.add_development_dependency 'webmock', '~> 1.9'
|
|
22
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: podrick
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Scott Bader
|
|
@@ -16,28 +16,28 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - ~>
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.8.
|
|
19
|
+
version: 0.8.8
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - ~>
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.8.
|
|
26
|
+
version: 0.8.8
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: nokogiri
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - ~>
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 1.
|
|
33
|
+
version: 1.6.0
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - ~>
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 1.
|
|
40
|
+
version: 1.6.0
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: minitest
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -81,6 +81,11 @@ files:
|
|
|
81
81
|
- bin/coderay
|
|
82
82
|
- bin/nokogiri
|
|
83
83
|
- bin/pry
|
|
84
|
+
- lib/podrick.rb
|
|
85
|
+
- lib/podrick/episode.rb
|
|
86
|
+
- lib/podrick/podcast.rb
|
|
87
|
+
- lib/podrick/version.rb
|
|
88
|
+
- podrick.gemspec
|
|
84
89
|
- test/assets/back_to_work.xml
|
|
85
90
|
- test/assets/by_the_way.xml
|
|
86
91
|
- test/assets/radio_lab.xml
|