podcast_feed_generator 0.2.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.
- checksums.yaml +7 -0
- data/.coveralls.yml +2 -0
- data/.gitignore +9 -0
- data/.travis.yml +7 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +55 -0
- data/LICENSE.txt +21 -0
- data/README.md +111 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/podcast_feed_generator.rb +197 -0
- data/lib/podcast_feed_generator/version.rb +3 -0
- data/podcast_feed_generator.gemspec +30 -0
- metadata +100 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2b263b6ecc78fa2eccf6bf647de3149f8f253fa12ac9055131ad08c83e41a646
|
4
|
+
data.tar.gz: f4e213071fd65c16ac144704162523a44bf850081c85d4cc21f1f224e82edc2b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b83117c6734c19663a84b4f0302571573bb68b54968bd16ae64c48ca0c3ca94463fe6049ba996a7c204c941919ba6898f2d72189d591ebed17d571d582dfa791
|
7
|
+
data.tar.gz: 82178f7ae70067c127ffb599e11eb1935eb16c53a5e702cea4f6e99247349ad5fbf9caaf5a79902f8c1c984e1f364f8700fec191a2ac9fe04f91fff341cd8c55
|
data/.coveralls.yml
ADDED
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
podcast_feed_generator (0.2.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
ansi (1.5.0)
|
10
|
+
builder (3.2.4)
|
11
|
+
coveralls (0.8.23)
|
12
|
+
json (>= 1.8, < 3)
|
13
|
+
simplecov (~> 0.16.1)
|
14
|
+
term-ansicolor (~> 1.3)
|
15
|
+
thor (>= 0.19.4, < 2.0)
|
16
|
+
tins (~> 1.6)
|
17
|
+
docile (1.3.4)
|
18
|
+
json (2.5.1)
|
19
|
+
minitest (5.14.2)
|
20
|
+
minitest-reporters (1.4.2)
|
21
|
+
ansi
|
22
|
+
builder
|
23
|
+
minitest (>= 5.0)
|
24
|
+
ruby-progressbar
|
25
|
+
nokogiri (1.11.0-x86_64-darwin)
|
26
|
+
racc (~> 1.4)
|
27
|
+
racc (1.5.2)
|
28
|
+
rake (10.5.0)
|
29
|
+
ruby-progressbar (1.11.0)
|
30
|
+
simplecov (0.16.1)
|
31
|
+
docile (~> 1.1)
|
32
|
+
json (>= 1.8, < 3)
|
33
|
+
simplecov-html (~> 0.10.0)
|
34
|
+
simplecov-html (0.10.2)
|
35
|
+
sync (0.5.0)
|
36
|
+
term-ansicolor (1.7.1)
|
37
|
+
tins (~> 1.0)
|
38
|
+
thor (1.0.1)
|
39
|
+
tins (1.26.0)
|
40
|
+
sync
|
41
|
+
|
42
|
+
PLATFORMS
|
43
|
+
x86_64-darwin-18
|
44
|
+
|
45
|
+
DEPENDENCIES
|
46
|
+
bundler (~> 2.0)
|
47
|
+
coveralls
|
48
|
+
minitest (~> 5.0)
|
49
|
+
minitest-reporters
|
50
|
+
nokogiri
|
51
|
+
podcast_feed_generator!
|
52
|
+
rake (~> 10.0)
|
53
|
+
|
54
|
+
BUNDLED WITH
|
55
|
+
2.2.4
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2019 Michoel Samuels
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
# PodcastFeedGenerator
|
2
|
+
|
3
|
+
[](https://travis-ci.org/AnalyzePlatypus/PodcastFeedGenerator)
|
4
|
+
[](https://coveralls.io/github/AnalyzePlatypus/PodcastFeedGenerator?branch=master)
|
5
|
+
[](https://img.shields.io/badge/license-MIT-blue.svg)
|
6
|
+
|
7
|
+
Easily generate industry-standard podcast RSS feeds.
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
require "podcast_feed_generator"
|
11
|
+
|
12
|
+
json = JSON.parse(File.open("feed.json").read) # A JSON file containing all of your podcast's info
|
13
|
+
|
14
|
+
rss_feed = PodcastFeedGenerator::Generator.new.generate json
|
15
|
+
```
|
16
|
+
|
17
|
+
## Installation
|
18
|
+
|
19
|
+
```shell
|
20
|
+
$ gem install podcast_feed_generator
|
21
|
+
```
|
22
|
+
|
23
|
+
Or add this line to your application's Gemfile:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
gem 'podcast_feed_generator'
|
27
|
+
```
|
28
|
+
|
29
|
+
## Build
|
30
|
+
|
31
|
+
```shell
|
32
|
+
$ cd PodcastFeedGenerator/
|
33
|
+
$ gem build podcast_feed_generator.gemspec
|
34
|
+
$ gem install podcast_feed_generator
|
35
|
+
```
|
36
|
+
|
37
|
+
## Usage
|
38
|
+
|
39
|
+
`PodcastFeedGenerator` has exactly one public method: `generate`, which expects a Ruby hash with the following shape:
|
40
|
+
|
41
|
+
```javascript
|
42
|
+
{
|
43
|
+
"podcast": {
|
44
|
+
"title": "Podcast Title",
|
45
|
+
"description": "Podcast Description",
|
46
|
+
"link": "link/to/show",
|
47
|
+
"author": "Podcast author",
|
48
|
+
"ownerName": "Podcast owner",
|
49
|
+
"ownerEmail": "podcast@email.io",
|
50
|
+
"podcastArtworkUrl": "link/to/feedImage",
|
51
|
+
"categories": [ // Add up to three of the official iTunes categories: https://castos.com/itunes-podcast-category-list/
|
52
|
+
"Category 1",
|
53
|
+
"Category 2",
|
54
|
+
"Category 3"
|
55
|
+
],
|
56
|
+
|
57
|
+
// Optional
|
58
|
+
"lastBuildDate": "2019-06-23", // Defaults to current date
|
59
|
+
"generator": "PodcastFeedGenerator gem", // Defaults to "PodcastFeedGenerator"
|
60
|
+
"subtitle": "Podcast subtitle", // Defaults to value of `description`
|
61
|
+
"summary": "Podcast summary", // Defaults to value of `description`
|
62
|
+
"explicit": "no", // Can be one of `yes` | `no` | `explicit`. Defaults to "no"
|
63
|
+
"language": "en-US", // Defaults to `en-US`
|
64
|
+
"podcastType": "Episodic", // `Episodic` or `Serial`. `Episodic` causes iTunes to list newest first; `Serial`, oldest first
|
65
|
+
"copyright": "(c) Podcast Copyright Notice" // Empty by default
|
66
|
+
},
|
67
|
+
"episodes": [
|
68
|
+
{
|
69
|
+
"title": "Episode Title",
|
70
|
+
"pubDate": "2019-05-01",
|
71
|
+
"link": "link/to/episode",
|
72
|
+
"description": "Episode description",
|
73
|
+
"mediaFileUrl": "https://my-site.io/podcast/1",
|
74
|
+
"duration": "00:33:12",
|
75
|
+
"mediaFileSizeBytes": "34540230",
|
76
|
+
|
77
|
+
// Optional
|
78
|
+
"author": "Episode Author", // Defaults to the `author` field above
|
79
|
+
"creator": "Episode Creator", // Defaults to the `author` field above
|
80
|
+
"subtitle": "Episode subtitle", // Defaults to the episode `description`
|
81
|
+
"summary": "Episode summary", // Defaults to the episode `description`
|
82
|
+
"explicit": "no", // Can be one of `yes` | `no` | `explicit`. Defaults to "no"
|
83
|
+
"episodeArtUrl": "path/to/episodeImage", // Defaults to the podcast artwork url
|
84
|
+
"itunesTitle": "Episode iTunes title", // Special title to show in iTunes. Defaults to episode `title`
|
85
|
+
"episodeNumber": "42", // Automatically generated if not specified.
|
86
|
+
"seasonNumber": "2", // Defaults to ""
|
87
|
+
"episodeType": "Full", // `full` | `trailer` | `bonus`. Defaults to `Full`. See the documentation for <itunes:episodeType> on https://help.apple.com/itc/podcasts_connect/#/itcb54353390
|
88
|
+
"mediaMimeType": "audio/mpeg", // Any media mime type. Defaults to "audio/mpeg"
|
89
|
+
"mediaIsDefault": "true", // Defaults to true
|
90
|
+
"medium": "audio" // `audio` | `video`. Defaults to `audio`
|
91
|
+
"htmlDescription": "<div></div>", // Defaults to the episode `description`
|
92
|
+
"guid": "my.site/episodes/hjhkhl7829hs986", // Defaults to a 32-character random string. Can alternatvely be a URL.
|
93
|
+
"guidIsPermalink": "false", // `false` by default. Set to `true` if your `guid` is a permalink url
|
94
|
+
}
|
95
|
+
]
|
96
|
+
}
|
97
|
+
```
|
98
|
+
|
99
|
+
## See Also
|
100
|
+
|
101
|
+
* [Apple Podcasts Feed Guidelines](https://help.apple.com/itc/podcasts_connect/#/itc2b3780e76)
|
102
|
+
* [Apple Podcasts RSS Explained](https://help.apple.com/itc/podcasts_connect/#/itcb54353390)
|
103
|
+
* [Apple Podcasts Categories](https://help.apple.com/itc/podcasts_connect/#/itc9267a2f12)
|
104
|
+
|
105
|
+
## Contributing
|
106
|
+
|
107
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/podcast_feed_generator.
|
108
|
+
|
109
|
+
## License
|
110
|
+
|
111
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "podcast_feed_generator"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
require "podcast_feed_generator/version"
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'uri'
|
5
|
+
require 'time'
|
6
|
+
require 'nokogiri'
|
7
|
+
|
8
|
+
# Constants
|
9
|
+
|
10
|
+
DEFAULT_GENERATOR_STRING = "Ruby PodcastFeedGenerator (https://github.com/AnalyzePlatypus/PodcastFeedGenerator)"
|
11
|
+
|
12
|
+
# Warning Strings
|
13
|
+
|
14
|
+
NO_ARTWORK_WARNING = "❗️ Warning: No podcast artwork has been set. The iTunes podcast directory will not accept podcasts the lack channel art.\n"
|
15
|
+
NO_DURATION_WARNING = "❗️ Warning: Episode #%{episode_number}: '%{episode_title}' is missing a duration. Some podcast players may reject your feed.\n"
|
16
|
+
NO_CATEGORIES_WARNING = "❗️ Warning: Your feed has no categories defined.\nThe iTunes podcast directory requires 3 categories to be present in your feed.\n"
|
17
|
+
NO_MEDIA_URL_WARNING = "❗️ Warning: Episode #%{episode_number}: '%{episode_title}' has no audio url defined.\nGot: %{url}\nThe episode will be unplayable and some podcast players may reject your feed.\n"
|
18
|
+
INVALID_URL_WARNING = "❗️ Warning: url `mediaFileUrl` appears to be invalid: %{url}.\nFound in Episode #%{episode_number}: '%{episode_title}'\nThe episode will be unplayable and some podcast players may reject your feed.\n"
|
19
|
+
MISSING_FILE_SIZE_WARNING = "❗️ Warning: Episode #%{episode_number}: '%{episode_title}' is missing media file size (Got: %{fileSize}). (Missing key: `mediaFileSizeBytes`)\n. Some podcast players may reject your feed."
|
20
|
+
DUPLICATE_GUID_WARNING = "❗️ Warning: Multiple episodes are using the same GUID: `%{guid}`.\nGUIDS should be unique.\nSome podcast players may reject your feed."
|
21
|
+
|
22
|
+
# Helpers
|
23
|
+
|
24
|
+
def url_valid? url
|
25
|
+
URI.parse(url).kind_of?(URI::HTTP)
|
26
|
+
end
|
27
|
+
|
28
|
+
def detect_duplicate_guids episodes
|
29
|
+
episode_guids = episodes.map{|e| e["guid"]}
|
30
|
+
length_before_uniq = episode_guids.length
|
31
|
+
length_after_uniq = episode_guids.uniq.length
|
32
|
+
|
33
|
+
id = episode_guids.group_by{|e| e}.keep_if{|_, e| e.length > 1}
|
34
|
+
|
35
|
+
if length_after_uniq < length_before_uniq
|
36
|
+
STDERR.puts DUPLICATE_GUID_WARNING % {
|
37
|
+
guid: id
|
38
|
+
}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def verifyHasArtwork channel_details
|
43
|
+
STDERR.puts NO_ARTWORK_WARNING if channel_details["podcastArtworkUrl"].nil? || channel_details["podcastArtworkUrl"].empty?
|
44
|
+
end
|
45
|
+
|
46
|
+
def verifyHasCategories channel_details
|
47
|
+
if channel_details["categories"].nil? || channel_details["categories"].empty?
|
48
|
+
STDERR.puts NO_CATEGORIES_WARNING
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def verifyHasDuration episode
|
53
|
+
if episode["duration"].nil?
|
54
|
+
STDERR.puts NO_DURATION_WARNING % {
|
55
|
+
episode_number: episode["episodeNumber"],
|
56
|
+
episode_title: episode["title"]
|
57
|
+
}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def verifyMediaFileUrl episode
|
62
|
+
if episode["mediaFileUrl"].nil? || episode["mediaFileUrl"].empty?
|
63
|
+
STDERR.puts NO_MEDIA_URL_WARNING % {
|
64
|
+
url: episode["mediaFileUrl"],
|
65
|
+
episode_number: episode["episodeNumber"],
|
66
|
+
episode_title: episode["title"]
|
67
|
+
}
|
68
|
+
else
|
69
|
+
unless url_valid? episode["mediaFileUrl"]
|
70
|
+
STDERR.puts INVALID_URL_WARNING % {
|
71
|
+
url: episode["mediaFileUrl"],
|
72
|
+
episode_number: episode["episodeNumber"],
|
73
|
+
episode_title: episode["title"]
|
74
|
+
}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def verifyMediaFileBytes episode
|
80
|
+
if episode["mediaFileSizeBytes"].nil? || episode["mediaFileSizeBytes"].empty?
|
81
|
+
STDERR.puts MISSING_FILE_SIZE_WARNING % {
|
82
|
+
fileSize: episode["mediaFileSizeBytes"],
|
83
|
+
episode_number: episode["episodeNumber"] || feed_info["episodes"].length - index,
|
84
|
+
episode_title: episode["title"]
|
85
|
+
}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
module PodcastFeedGenerator
|
90
|
+
|
91
|
+
class Generator
|
92
|
+
def generate feed_info
|
93
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
94
|
+
|
95
|
+
detect_duplicate_guids feed_info["episodes"]
|
96
|
+
verifyHasArtwork feed_info["podcast"]
|
97
|
+
verifyHasCategories feed_info["podcast"]
|
98
|
+
|
99
|
+
xml.rss('xmlns:content' => "http://purl.org/rss/1.0/modules/content/", "xmlns:wfw" => "http://wellformedweb.org/CommentAPI/", "xmlns:itunes" => "http://www.itunes.com/dtds/podcast-1.0.dtd", "xmlns:dc" => "http://purl.org/dc/elements/1.1/", "xmlns:media" => "http://search.yahoo.com/mrss/", "version" => "2.0") {
|
100
|
+
channel_details = feed_info["podcast"]
|
101
|
+
xml.channel {
|
102
|
+
|
103
|
+
xml.title channel_details["title"]
|
104
|
+
xml.description channel_details["description"]
|
105
|
+
xml.link channel_details["link"]
|
106
|
+
xml.lastBuildDate channel_details["lastBuildDate"] || Time.now.rfc2822
|
107
|
+
xml.generator channel_details["generator"] || DEFAULT_GENERATOR_STRING
|
108
|
+
xml.language channel_details["language"] || "en-US"
|
109
|
+
xml.copyright channel_details["copyright"]
|
110
|
+
|
111
|
+
xml['itunes'].author channel_details["author"] || channel_details["author"]
|
112
|
+
xml['itunes'].subtitle channel_details["subtitle"] || channel_details["description"]
|
113
|
+
xml['itunes'].summary channel_details["summary"] || channel_details["description"]
|
114
|
+
xml['itunes'].explicit channel_details["explicit"] || "no"
|
115
|
+
xml['itunes'].type channel_details["podcastType"] || "episodic"
|
116
|
+
|
117
|
+
xml['itunes'].owner {
|
118
|
+
xml['itunes'].name channel_details["ownerName"]
|
119
|
+
xml['itunes'].email channel_details["ownerEmail"]
|
120
|
+
}
|
121
|
+
|
122
|
+
xml['itunes'].image("href" => channel_details["podcastArtworkUrl"] )
|
123
|
+
|
124
|
+
unless channel_details["categories"].nil?
|
125
|
+
channel_details["categories"].each do |category_name|
|
126
|
+
xml['itunes'].category("text" => category_name)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
episodes = feed_info["episodes"].each_with_index do |episode, index|
|
132
|
+
episode["episodeNumber"] = episode["episodeNumber"] || (feed_info["episodes"].length - index)
|
133
|
+
end
|
134
|
+
|
135
|
+
feed_info["episodes"].each_with_index do |episode, index|
|
136
|
+
|
137
|
+
verifyHasDuration episode
|
138
|
+
verifyMediaFileUrl episode
|
139
|
+
verifyMediaFileBytes episode
|
140
|
+
|
141
|
+
xml.item {
|
142
|
+
xml.title episode["title"]
|
143
|
+
xml['dc'].creator episode["creator"] || channel_details["author"]
|
144
|
+
xml.author episode["creator"] || channel_details["author"]
|
145
|
+
xml.pubDate episode["pubDate"]
|
146
|
+
xml.link episode["link"]
|
147
|
+
xml.guid("isPermalink": episode["guidIsPermalink"]){
|
148
|
+
xml.text episode["guid"] || (0...32).map { (65 + rand(26)).chr }.join
|
149
|
+
}
|
150
|
+
|
151
|
+
xml.description episode["description"]
|
152
|
+
xml["content"].encoded {
|
153
|
+
xml.text "<![CDATA[#{episode["htmlDescription"]} ]]>"
|
154
|
+
}
|
155
|
+
xml['itunes'].author episode["author"]
|
156
|
+
xml['itunes'].subtitle episode["subtitle"] || episode["description"]
|
157
|
+
xml['itunes'].summary episode["summary"] || episode["description"]
|
158
|
+
|
159
|
+
|
160
|
+
xml['itunes'].explicit episode["explicit"] || 'no'
|
161
|
+
xml['itunes'].duration episode["duration"]
|
162
|
+
xml['itunes'].image("href"=> episode["episodeArtUrl"] || channel_details["podcastArtworkUrl"])
|
163
|
+
|
164
|
+
|
165
|
+
xml['itunes'].episode episode["episodeNumber"]
|
166
|
+
xml['itunes'].season episode["seasonNumber"]
|
167
|
+
|
168
|
+
xml['itunes'].title episode["itunesTitle"] || episode["title"]
|
169
|
+
xml['itunes'].episodeType episode["episodeType"] || "full"
|
170
|
+
|
171
|
+
xml.enclosure(
|
172
|
+
"url" => episode["mediaFileUrl"],
|
173
|
+
"type" => episode["mediaMimeType"] || "audio/mpeg",
|
174
|
+
"length" => episode["mediaFileSizeBytes"]
|
175
|
+
)
|
176
|
+
|
177
|
+
xml['media'].content(
|
178
|
+
"url"=> episode["mediaFileUrl"],
|
179
|
+
"type" => episode["mediaMimeType"] || "audio/mpeg",
|
180
|
+
"length" => episode["mediaFileSizeBytes"],
|
181
|
+
"isDefault" => episode["mediaIsDefault"] || "true",
|
182
|
+
"medium" => episode["medium"] || "audio"
|
183
|
+
) {
|
184
|
+
xml['media'].title("type" => "plain") {
|
185
|
+
xml.text episode["title"]
|
186
|
+
}
|
187
|
+
}
|
188
|
+
}
|
189
|
+
end
|
190
|
+
}
|
191
|
+
}
|
192
|
+
end
|
193
|
+
|
194
|
+
builder.to_xml
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "podcast_feed_generator/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "podcast_feed_generator"
|
8
|
+
spec.version = PodcastFeedGenerator::VERSION
|
9
|
+
spec.authors = ["Michoel Samuels"]
|
10
|
+
spec.email = ["k2co3@icloud.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{🎙 Easily generate RSS podcast feeds from a simple JSON object.}
|
13
|
+
spec.description = %q{🎙 Easily generate RSS podcast feeds from a simple JSON object (100% test coverage, compatible with every major podcast player)}
|
14
|
+
spec.homepage = "https://github.com/AnalyzePlatypus/PodcastFeedGenerator"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
|
18
|
+
# Specify which files should be added to the gem when it is released.
|
19
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
20
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
21
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
22
|
+
end
|
23
|
+
spec.bindir = "exe"
|
24
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
25
|
+
spec.require_paths = ["lib"]
|
26
|
+
|
27
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
28
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
29
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: podcast_feed_generator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michoel Samuels
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-01-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.0'
|
55
|
+
description: "\U0001F399 Easily generate RSS podcast feeds from a simple JSON object
|
56
|
+
(100% test coverage, compatible with every major podcast player)"
|
57
|
+
email:
|
58
|
+
- k2co3@icloud.com
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- ".coveralls.yml"
|
64
|
+
- ".gitignore"
|
65
|
+
- ".travis.yml"
|
66
|
+
- Gemfile
|
67
|
+
- Gemfile.lock
|
68
|
+
- LICENSE.txt
|
69
|
+
- README.md
|
70
|
+
- Rakefile
|
71
|
+
- bin/console
|
72
|
+
- bin/setup
|
73
|
+
- lib/podcast_feed_generator.rb
|
74
|
+
- lib/podcast_feed_generator/version.rb
|
75
|
+
- podcast_feed_generator.gemspec
|
76
|
+
homepage: https://github.com/AnalyzePlatypus/PodcastFeedGenerator
|
77
|
+
licenses:
|
78
|
+
- MIT
|
79
|
+
metadata: {}
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
requirements: []
|
95
|
+
rubyforge_project:
|
96
|
+
rubygems_version: 2.7.9
|
97
|
+
signing_key:
|
98
|
+
specification_version: 4
|
99
|
+
summary: "\U0001F399 Easily generate RSS podcast feeds from a simple JSON object."
|
100
|
+
test_files: []
|