podrick 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|