dropcaster 0.0.6 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gemnasium.yml +1 -0
- data/.gitignore +12 -14
- data/.rubocop.yml +34 -0
- data/.ruby-version +1 -0
- data/.travis.yml +20 -5
- data/CONTRIBUTING.md +18 -0
- data/Dockerfile +4 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +309 -65
- data/Guardfile +8 -6
- data/LICENSE.txt +1 -1
- data/README.markdown +43 -37
- data/Rakefile +46 -2
- data/{TODO → TODO.markdown} +0 -0
- data/VISION.markdown +52 -18
- data/Vagrantfile +10 -0
- data/bin/dropcaster +57 -53
- data/bin/lstags +29 -28
- data/dropcaster.gemspec +31 -20
- data/lib/dropcaster.rb +2 -15
- data/lib/dropcaster/channel.rb +54 -43
- data/lib/dropcaster/channel_file_locator.rb +8 -5
- data/lib/dropcaster/contributors.rb +39 -0
- data/lib/dropcaster/errors.rb +6 -4
- data/lib/dropcaster/item.rb +20 -14
- data/lib/dropcaster/log_formatter.rb +10 -0
- data/lib/dropcaster/logging.rb +13 -0
- data/lib/dropcaster/version.rb +3 -1
- data/templates/channel.html.erb +3 -6
- data/templates/channel.rss.erb +6 -5
- data/test/Vagrantfile +3 -1
- data/test/bin/vagrant-status +37 -31
- data/test/extensions/windows.rb +3 -1
- data/test/fixtures/extension.MP3 +0 -0
- data/test/fixtures/special &.mp3 +0 -0
- data/test/fixtures/test_template.json.erb +3 -4
- data/test/helper.rb +4 -1
- data/test/unit/test_app.rb +29 -24
- data/test/unit/test_channel.rb +9 -5
- data/test/unit/test_channel_locator.rb +8 -5
- data/test/unit/test_channel_xml.rb +29 -9
- data/test/unit/{test_item.rb → test_itunes_item.rb} +5 -6
- data/website/.gitignore +2 -0
- data/website/README.markdown +8 -0
- data/website/_config.yml +14 -0
- data/website/_front_matter/contributing.yaml +5 -0
- data/website/_front_matter/index.yaml +3 -0
- data/website/_front_matter/vision.yaml +5 -0
- data/website/_includes/footer.html +55 -0
- data/website/_includes/head.html +11 -0
- data/website/_includes/header.html +27 -0
- data/website/_layouts/default.html +20 -0
- data/website/_layouts/page.html +14 -0
- data/website/_layouts/post.html +15 -0
- data/website/_sass/_base.scss +204 -0
- data/website/_sass/_layout.scss +236 -0
- data/website/_sass/_syntax-highlighting.scss +67 -0
- data/website/css/main.scss +49 -0
- data/website/deploy.sh +23 -0
- data/website/feed.xml +30 -0
- metadata +150 -23
data/Guardfile
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
guard 'bundler' do
|
2
4
|
watch('Gemfile')
|
3
|
-
watch(
|
5
|
+
watch(/^.*\.gemspec/)
|
4
6
|
end
|
5
7
|
|
6
8
|
guard 'minitest' do
|
7
|
-
watch(%r
|
8
|
-
watch(%r
|
9
|
-
watch(%r
|
10
|
-
watch(%r{^lib/.*/([^/]+)\.rb$}){|m| "test/unit/test_#{m[1]}.rb"}
|
11
|
-
watch(%r
|
9
|
+
watch(%r{^test/unit/test_(.*)\.rb})
|
10
|
+
watch(%r{^lib/*\.rb}) { 'test/unit' }
|
11
|
+
watch(%r{^lib/.*/*\.rb}) { 'test/unit' }
|
12
|
+
watch(%r{^lib/.*/([^/]+)\.rb$}) { |m| "test/unit/test_#{m[1]}.rb" }
|
13
|
+
watch(%r{^test/helper\.rb}) { 'test/unit' }
|
12
14
|
end
|
data/LICENSE.txt
CHANGED
data/README.markdown
CHANGED
@@ -2,13 +2,13 @@
|
|
2
2
|
|
3
3
|
[![Build Status](https://travis-ci.org/nerab/dropcaster.png?branch=master)](https://travis-ci.org/nerab/dropcaster)
|
4
4
|
|
5
|
-
_This project is developed with the [readme-driven development](http://tom.preston-werner.com/2010/08/23/readme-driven-development.html) method. This file describes the functionality that is actually implemented, whereas the [
|
5
|
+
_This project is developed with the [readme-driven development](http://tom.preston-werner.com/2010/08/23/readme-driven-development.html) method. This file describes the functionality that is actually implemented, whereas the [vision](VISION.markdown) reflects where the tool should go._
|
6
6
|
|
7
|
-
[Dropcaster](http://
|
7
|
+
[Dropcaster](http://nerab.github.io/dropcaster/) is a podcast feed generator for the command line. It is most simple to use with Dropbox, but works equally well with any other (static file) web hoster.
|
8
8
|
|
9
9
|
Author: Nicolas E. Rabenau <nerab@gmx.at>
|
10
10
|
|
11
|
-
# What is the problem Dropcaster is trying to solve?
|
11
|
+
# What is the problem that Dropcaster is trying to solve?
|
12
12
|
|
13
13
|
You have a number of podcast episodes that you would like to publish as a feed. Nothing else - no fancy website, no stats, nothing but the pure podcast.
|
14
14
|
|
@@ -24,17 +24,27 @@ To get started, use RubyGems to install Dropcaster:
|
|
24
24
|
|
25
25
|
Once installed, you can use the `dropcaster` command to generate a new podcast feed document.
|
26
26
|
|
27
|
+
## Troubleshooting
|
28
|
+
|
29
|
+
`libxml-ruby` is a frequent offender with installation problems. As usual, [Stack Overflow](https://stackoverflow.com/questions/38129330/libxml-ruby-failed-to-build-gem-native-extension#comment98572516_55162900) has the answer (at least for macOS with Homebrew):
|
30
|
+
|
31
|
+
```
|
32
|
+
$ gem install --no-document libxml-ruby -- --with-xml2-config="$(brew --prefix libxml2)/bin/xml2-config"
|
33
|
+
```
|
34
|
+
|
35
|
+
For Ruby 2.5, add `-v '3.1.0'`.
|
36
|
+
|
27
37
|
# Basic Usage
|
28
38
|
|
29
39
|
Once Dropcaster is installed, the only two other things you will need are a channel definition and one or more mp3 files to publish.
|
30
40
|
|
31
|
-
Let's start with the channel definition. It is a simple [YAML](http://yaml.org/) file that holds the general information about your podcast channel. According to the [RSS 2.0 spec](http://
|
41
|
+
Let's start with the channel definition. It is a simple [YAML](http://yaml.org/) file that holds the general information about your podcast channel. According to the [RSS 2.0 spec](http://blogs.law.harvard.edu/tech/rss#requiredChannelElements), the only mandatory information that your channel absolutely needs are a title, a description and a link to a web site where the channel belongs to.
|
32
42
|
|
33
43
|
The simplest channel file looks like this:
|
34
44
|
|
35
|
-
|
36
|
-
|
37
|
-
|
45
|
+
:title: 'All About Everything'
|
46
|
+
:description: 'A show about everything'
|
47
|
+
:url: 'http://www.example.com/podcasts/everything/index.html'
|
38
48
|
|
39
49
|
Store this file as channel.yml in the same directory where the mp3 files of your podcast reside. The channel definition is expected to be present in the same directory as your mp3 files, but this can be overridden using a command line switch. You can find a [more elaborate example](http://github.com/nerab/dropcaster/blob/master/doc/sample-channel.yml) for the channel definition in the doc folder of the Dropcaster gem. You can find it by running `gem open dropcaster`.
|
40
50
|
|
@@ -45,21 +55,21 @@ With all required pieces in place, we could generate the podcast feed. Just befo
|
|
45
55
|
$ cd ~/Dropbox/Public
|
46
56
|
$ dropcaster
|
47
57
|
|
48
|
-
(The above lines assume that you are using Dropbox, and that there is at least one mp3 file in
|
58
|
+
(The above lines assume that you are using Dropbox, and that there is at least one mp3 file in `~/Dropbox/Public`).
|
49
59
|
|
50
60
|
Dropcaster will print the feed to standard-out, without writing it to disk. When you are happy with the results, call Dropcaster again, but redirect the output to a file, this time:
|
51
61
|
|
52
62
|
$ dropcaster > index.rss
|
53
63
|
|
54
|
-
If all went well, you will now have a valid podcast feed in your Dropbox, listing all mp3 files as podcast episodes. Please see the section [Publish Your Feed] for details on how to find the public URL of your feed.
|
64
|
+
If all went well, you will now have a valid podcast feed in your Dropbox, listing all mp3 files as podcast episodes. Please see the section [Publish Your Feed](#publish-your-feed) for details on how to find the public URL of your feed.
|
55
65
|
|
56
66
|
# Use Cases
|
57
67
|
|
58
68
|
## Publish a New Episode
|
59
69
|
|
60
|
-
1. Drop the mp3 file into the Dropbox Public folder (e.g.
|
70
|
+
1. Drop the mp3 file into the Dropbox Public folder (e.g. `~/Dropbox/Public`), and then run the following command in the directory where the mp3 files reside:
|
61
71
|
|
62
|
-
|
72
|
+
$ dropcaster > index.rss
|
63
73
|
|
64
74
|
1. Dropbox will sync the updated index.rss file to its web server and any podcast client will download the new episode as soon as it has loaded the updated index.rss.
|
65
75
|
|
@@ -67,19 +77,19 @@ If all went well, you will now have a valid podcast feed in your Dropbox, listin
|
|
67
77
|
|
68
78
|
Remove the mp3 you want to delete from the Dropbox Public folder, and then run the following command in the directory where the remaining mp3 files reside:
|
69
79
|
|
70
|
-
|
80
|
+
$ dropcaster > index.rss
|
71
81
|
|
72
82
|
## Replace an Episode With an Updated File
|
73
83
|
|
74
84
|
In the Dropbox Public folder, replace the mp3 you want to update with a new version, and then run the following command in the directory where the mp3 files reside:
|
75
85
|
|
76
|
-
|
86
|
+
$ dropcaster > index.rss
|
77
87
|
|
78
88
|
## Publish Your Feed
|
79
89
|
|
80
90
|
1. Re-generate the feed to make sure the it is up to date (see above):
|
81
91
|
|
82
|
-
|
92
|
+
$ dropcaster > index.rss
|
83
93
|
|
84
94
|
1. In your Dropbox Public folder, right-click the index.rss and select "Dropbox / Copy public link". This copies the public, HTTP-addressable link to your podcast into the clipboard.
|
85
95
|
1. Publish this link and tell people to subscribe to it.
|
@@ -94,19 +104,19 @@ For example, in order to generate a feed that only publishes MP3 files where the
|
|
94
104
|
|
95
105
|
## Publish More than One Feed
|
96
106
|
|
97
|
-
|
98
|
-
|
107
|
+
$ dropcaster project1 > project1.rss
|
108
|
+
$ dropcaster project2 > project2.rss
|
99
109
|
|
100
110
|
or
|
101
111
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
112
|
+
$ cd project1
|
113
|
+
$ dropcaster > index.rss
|
114
|
+
$ cd ../project2
|
115
|
+
$ dropcaster > index.rss
|
106
116
|
|
107
117
|
## Include Episodes From Two Subdirectories Into a Single Feed
|
108
118
|
|
109
|
-
|
119
|
+
$ dropcaster project1 project2 > index.rss
|
110
120
|
|
111
121
|
# Advanced features
|
112
122
|
|
@@ -118,7 +128,7 @@ However, it is still possible to override Dropcaster's behavior in many ways. Yo
|
|
118
128
|
|
119
129
|
In order to find out about all the options, simply run
|
120
130
|
|
121
|
-
|
131
|
+
$ dropcaster --help
|
122
132
|
|
123
133
|
## Using custom channel templates
|
124
134
|
|
@@ -130,11 +140,11 @@ It is also possible to customize the channel by supplying an alternative channel
|
|
130
140
|
|
131
141
|
Besides generating an RSS feed, dropcaster can also generate HTML that can be used as a home page for your podcast. The template directory contains a sample template that can be used to get started:
|
132
142
|
|
133
|
-
|
143
|
+
$ dropcaster --channel-template templates/channel.html.erb
|
134
144
|
|
135
145
|
As discussed above, the output of this command can be written to a file, too:
|
136
146
|
|
137
|
-
|
147
|
+
$ dropcaster --channel-template templates/channel.html.erb > ~/Dropbox/Public/allabouteverything.html
|
138
148
|
|
139
149
|
Dropcaster works exactly the same, whether it generates an RSS feed or a HTML page. Therefore, all options discussed before also apply when generating HTML.
|
140
150
|
|
@@ -146,12 +156,16 @@ The generated XML file contains all elements required for iTunes. However, Dropc
|
|
146
156
|
|
147
157
|
The whole concept of Dropcaster works perfectly fine without Dropbox. Just run the Dropcaster script in a directory of mp3 files and upload the files as well as the generated index.rss to a web server. Leave the relative position of the index and mp3 files as is, otherwise the path to the mp3 files in index.rss will become invalid.
|
148
158
|
|
159
|
+
## Using Dropcaster With S3 or Digital Ocean Spaces
|
160
|
+
|
161
|
+
If you set up an S3 bucket or Digital Ocean Space (or any other s3 compatible static asset host), you can easily sync your local podcast directory using a command line tool like [s3cmd](https://github.com/s3tools/s3cmd).
|
162
|
+
|
163
|
+
After installing s3cmd, make sure you have the right credentials to write to your bucket/space. Add your mp3 files to your folder, run `dropcaster > index.rss` and then `s3cmd sync ./ s3://$your-bucket-name --acl public-read`. S3cmd will now upload any new or changed files to your bucket.
|
164
|
+
|
149
165
|
## Episode Identifier (uuid)
|
150
166
|
|
151
167
|
Dropcaster uses a rather simple approach to uniquely identify the episodes. It simply generates a SHA1 hash of the mp3 file. If it changes, for whatever reason (even if only a tag was changed), the episode will get a new UUID, and any podcatcher will fetch the episode again (which is what you want, in most cases).
|
152
168
|
|
153
|
-
Modifying the sidecar file does not change the UUID, because it only affects the feed and not the episode itself.
|
154
|
-
|
155
169
|
## I Don't Like the Output Format that Dropcaster produces
|
156
170
|
|
157
171
|
Dropcaster uses an ERB template to generate the XML feed. The template was written so that it is easy to understand, but not necessarily in a way that would make the output rather nice-looking. That should not be an issue, as long as the XML is correct.
|
@@ -164,18 +178,10 @@ For writing the output to a file, just redirect the ouput of the above command:
|
|
164
178
|
|
165
179
|
dropcaster | xmllint --format - > index.rss
|
166
180
|
|
167
|
-
#
|
168
|
-
|
169
|
-
Dropcaster is hosted at [Github](http://github.com/nerab/dropcaster):
|
181
|
+
# Web site
|
170
182
|
|
171
|
-
|
172
|
-
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
173
|
-
* Fork the project
|
174
|
-
* Start a feature/bugfix branch
|
175
|
-
* Commit and push until you are happy with your contribution
|
176
|
-
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
177
|
-
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
183
|
+
Dropcaster uses Steve Klabnik's [approach](https://github.com/steveklabnik/automatically_update_github_pages_with_travis_example) for publishing the site with [Travis CI](http://travis-ci.org/).
|
178
184
|
|
179
185
|
# Copyright
|
180
186
|
|
181
|
-
Copyright (c) 2011-
|
187
|
+
Copyright (c) 2011-2015 Nicolas E. Rabenau. See [LICENSE.txt](https://raw.github.com/nerab/dropcaster/master/LICENSE.txt) for further details.
|
data/Rakefile
CHANGED
@@ -1,11 +1,55 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'bundler/gem_tasks'
|
4
4
|
require 'rake/testtask'
|
5
|
+
require 'rake/clean'
|
6
|
+
require 'rubocop/rake_task'
|
7
|
+
require 'dropcaster'
|
8
|
+
|
9
|
+
RuboCop::RakeTask.new
|
5
10
|
|
6
11
|
Rake::TestTask.new(:test) do |test|
|
7
12
|
test.libs << 'test'
|
8
13
|
test.pattern = 'test/**/test_*.rb'
|
9
14
|
end
|
10
15
|
|
11
|
-
task :
|
16
|
+
task default: %i[rubocop test]
|
17
|
+
|
18
|
+
namespace :web do
|
19
|
+
file 'website/index.markdown' do |f|
|
20
|
+
concat 'website/_front_matter/index.yaml', 'README.markdown', f
|
21
|
+
end
|
22
|
+
CLOBBER << 'website/index.markdown'
|
23
|
+
|
24
|
+
file 'website/vision.markdown' do |f|
|
25
|
+
concat 'website/_front_matter/vision.yaml', 'VISION.markdown', f
|
26
|
+
end
|
27
|
+
CLOBBER << 'website/vision.markdown'
|
28
|
+
|
29
|
+
file 'website/contributors.markdown' do
|
30
|
+
require 'dropcaster/contributors'
|
31
|
+
File.write('website/contributors.markdown', Dropcaster.contributors)
|
32
|
+
end
|
33
|
+
CLOBBER << 'website/contributors.markdown'
|
34
|
+
|
35
|
+
file 'website/contributing.md' => 'website/contributors.markdown' do |f|
|
36
|
+
concat 'website/_front_matter/contributing.yaml', 'CONTRIBUTING.md', f
|
37
|
+
concat 'website/contributors.markdown', f
|
38
|
+
end
|
39
|
+
CLOBBER << 'website/contributing.md'
|
40
|
+
|
41
|
+
desc 'Generate web page'
|
42
|
+
task generate: ['website/index.markdown', 'website/vision.markdown', 'website/contributing.md'] do
|
43
|
+
cd 'website' do
|
44
|
+
`bundle exec jekyll build`
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def concat(*files)
|
50
|
+
File.open(files.pop.to_s, 'a') do |f|
|
51
|
+
files.each do |src|
|
52
|
+
f << File.read(src)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/{TODO → TODO.markdown}
RENAMED
File without changes
|
data/VISION.markdown
CHANGED
@@ -2,13 +2,13 @@
|
|
2
2
|
|
3
3
|
[![Build Status](https://travis-ci.org/nerab/dropcaster.png?branch=master)](https://travis-ci.org/nerab/dropcaster)
|
4
4
|
|
5
|
-
_This project is developed with the [readme-driven development](http://tom.preston-werner.com/2010/08/23/readme-driven-development.html) method. This file contains the vision, whereas the [README](README.
|
5
|
+
_This project is developed with the [readme-driven development](http://tom.preston-werner.com/2010/08/23/readme-driven-development.html) method. This file contains the vision, whereas the [README](README.markdown) reflects the functionality that is actually implemented._
|
6
6
|
|
7
|
-
[Dropcaster](http://
|
7
|
+
[Dropcaster](http://nerab.github.io/dropcaster/) is a podcast feed generator for the command line. It is most simple to use with Dropbox, but works equally well with any other (static file) web hoster.
|
8
8
|
|
9
9
|
Author: Nicolas E. Rabenau <nerab@gmx.at>
|
10
10
|
|
11
|
-
# What is the problem Dropcaster is trying to solve?
|
11
|
+
# What is the problem that Dropcaster is trying to solve?
|
12
12
|
|
13
13
|
You have a number of podcast episodes that you would like to publish as a feed. Nothing else - no fancy website, no stats, nothing but the pure podcast.
|
14
14
|
|
@@ -28,7 +28,7 @@ Once installed, you can use the `dropcaster` command to generate a new podcast f
|
|
28
28
|
|
29
29
|
Once Dropcaster is installed, the only two other things you will need are a channel definition and one or more mp3 files to publish.
|
30
30
|
|
31
|
-
Let's start with the channel definition. It is a simple [YAML](http://yaml.org/) file that holds the general information about your podcast channel. According to the [RSS 2.0 spec](http://
|
31
|
+
Let's start with the channel definition. It is a simple [YAML](http://yaml.org/) file that holds the general information about your podcast channel. According to the [RSS 2.0 spec](http://blogs.law.harvard.edu/tech/rss#requiredChannelElements), the only mandatory information that your channel absolutely needs are a title, a description and a link to a web site where the channel belongs to.
|
32
32
|
|
33
33
|
The simplest channel file looks like this:
|
34
34
|
|
@@ -45,19 +45,19 @@ With all required pieces in place, we could generate the podcast feed. Just befo
|
|
45
45
|
$ cd ~/Dropbox/Public
|
46
46
|
$ dropcaster
|
47
47
|
|
48
|
-
(The above lines assume that you are using Dropbox, and that there is at least one mp3 file in
|
48
|
+
(The above lines assume that you are using Dropbox, and that there is at least one mp3 file in `~/Dropbox/Public`).
|
49
49
|
|
50
50
|
Dropcaster will print the feed to standard-out, without writing it to disk. When you are happy with the results, call Dropcaster again, but redirect the output to a file, this time:
|
51
51
|
|
52
52
|
$ dropcaster > index.rss
|
53
53
|
|
54
|
-
If all went well, you will now have a valid podcast feed in your Dropbox, listing all mp3 files as podcast episodes. Please see the section [Publish Your Feed] for details on how to find the public URL of your feed.
|
54
|
+
If all went well, you will now have a valid podcast feed in your Dropbox, listing all mp3 files as podcast episodes. Please see the section [Publish Your Feed](#publish-your-feed) for details on how to find the public URL of your feed.
|
55
55
|
|
56
56
|
# Use Cases
|
57
57
|
|
58
58
|
## Publish a New Episode
|
59
59
|
|
60
|
-
1. Drop the mp3 file into the Dropbox Public folder (e.g.
|
60
|
+
1. Drop the mp3 file into the Dropbox Public folder (e.g. `~/Dropbox/Public`), and then run the following command in the directory where the mp3 files reside:
|
61
61
|
|
62
62
|
$ dropcaster > index.rss
|
63
63
|
|
@@ -138,6 +138,48 @@ As discussed above, the output of this command can be written to a file, too:
|
|
138
138
|
|
139
139
|
Dropcaster works exactly the same, whether it generates an RSS feed or a HTML page. Therefore, all options discussed before also apply when generating HTML.
|
140
140
|
|
141
|
+
## Generate a HTML page for each episode
|
142
|
+
|
143
|
+
If the `--episode-pages` switch is present, dropcaster will generate a separate page for each episode. The result will not appear on STDOUT, but will be written to files that are named like he episode files, but with a file extension of `.html`.
|
144
|
+
|
145
|
+
For example, let's assume the following directory structure:
|
146
|
+
|
147
|
+
channel.yml
|
148
|
+
episodes/episode1/AAE001 Hello World.mp3
|
149
|
+
episodes/episode2/AAE002 Getting started.mp3
|
150
|
+
episodes/episode3/AAE003 Advanced Topics.mp3
|
151
|
+
|
152
|
+
With this directory structure, Dropcaster would typically be called like this:
|
153
|
+
|
154
|
+
dropcaster episodes/episode* --channel channel.yml
|
155
|
+
|
156
|
+
In order to generate episode pages, the command would need to be modified to look as follows:
|
157
|
+
|
158
|
+
dropcaster episodes/episode* --channel channel.yml --episode-pages
|
159
|
+
|
160
|
+
If any of the files to be generated already exist, Dropcaster will not overwrite them. Adding the `--force` option forces dropcaster to overwrite existing files.
|
161
|
+
|
162
|
+
The index.html page could be written with the same command by redirecting dropcaster's output to a file:
|
163
|
+
|
164
|
+
dropcaster episodes/episode* --channel channel.yml --episode-pages --channel-template hannel.html.erb > index.html
|
165
|
+
|
166
|
+
As a result, each episode will get an HTML page next to the MP3 file. The default HTML channel template will write links pointing to each episode. After calling the example command above, the esulting directory structure would look like this:
|
167
|
+
|
168
|
+
channel.yml
|
169
|
+
index.html
|
170
|
+
episodes/episode1/AAE001 Hello World.mp3
|
171
|
+
episodes/episode1/AAE001 Hello World.html
|
172
|
+
episodes/episode2/AAE002 Getting started.mp3
|
173
|
+
episodes/episode2/AAE002 Getting started.html
|
174
|
+
episodes/episode3/AAE003 Advanced Topics.mp3
|
175
|
+
episodes/episode3/AAE003 Advanced Topics.html
|
176
|
+
|
177
|
+
Please note that the example above only deals with HTML pages. The RSS feed would still have to be generated with a second call to dropcaster (see the earlier sections of this page).
|
178
|
+
|
179
|
+
Dropcaster will use its default template for generating the episode pages. It is also possible to specify a custom episode template with the `--episode-template=FILE` switch, passing the name of a custom episode template file (similar to a custom channel template).
|
180
|
+
|
181
|
+
The major difference between the channel and episode HTML templates is that the episodes write out lyrics. For podcasts, lyrics are used for an in-depth description of the episode. Any text is treated as [Markdown](http://daringfireball.net/projects/markdown/) and converted to HTML.
|
182
|
+
|
141
183
|
## Sidecar files
|
142
184
|
|
143
185
|
You may override the meta data for any episode by providing a YAML file with the same name as the mp3 file, but with an extension of yml or yaml (ususally refered to as [sidecar file](http://en.wikipedia.org/wiki/Sidecar_file)). Any attributes specified in this file override the ID tags in the mp3 file.
|
@@ -172,18 +214,10 @@ For writing the output to a file, just redirect the ouput of the above command:
|
|
172
214
|
|
173
215
|
dropcaster | xmllint --format - > index.rss
|
174
216
|
|
175
|
-
#
|
176
|
-
|
177
|
-
Dropcaster is hosted at [Github](http://github.com/nerab/dropcaster):
|
217
|
+
# Web site
|
178
218
|
|
179
|
-
|
180
|
-
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
181
|
-
* Fork the project
|
182
|
-
* Start a feature/bugfix branch
|
183
|
-
* Commit and push until you are happy with your contribution
|
184
|
-
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
185
|
-
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
219
|
+
Dropcaster uses Steve Klabnik's [approach](https://github.com/steveklabnik/automatically_update_github_pages_with_travis_example) for publishing the site with [Travis CI](http://travis-ci.org/).
|
186
220
|
|
187
221
|
# Copyright
|
188
222
|
|
189
|
-
Copyright (c) 2011-
|
223
|
+
Copyright (c) 2011-2015 Nicolas E. Rabenau. See [LICENSE.txt](https://raw.github.com/nerab/dropcaster/master/LICENSE.txt) for further details.
|
data/Vagrantfile
ADDED
data/bin/dropcaster
CHANGED
@@ -1,22 +1,24 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
|
4
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
4
5
|
|
5
6
|
require 'yaml'
|
7
|
+
require 'English'
|
6
8
|
|
7
|
-
help =
|
8
|
-
Dropcaster is a podcast feed generator for the command line.
|
9
|
+
help = <<~HELP
|
10
|
+
Dropcaster is a podcast feed generator for the command line.
|
9
11
|
|
10
|
-
Author: Nicolas E. Rabenau nerab@gmx.at
|
11
|
-
Homepage: http://
|
12
|
+
Author: Nicolas E. Rabenau nerab@gmx.at
|
13
|
+
Homepage: http://nerab.github.io/dropcaster/
|
12
14
|
|
13
|
-
Basic Usage:
|
15
|
+
Basic Usage:
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
dropcaster Prints a podcast feed document for the mp3 files in the current directory.
|
18
|
+
dropcaster [FILE]... Prints a podcast feed document for FILES
|
19
|
+
dropcaster [DIR]... Prints a podcast feed document for the mp3 files in DIR
|
18
20
|
|
19
|
-
Options:
|
21
|
+
Options:
|
20
22
|
HELP
|
21
23
|
|
22
24
|
def usage
|
@@ -25,105 +27,107 @@ end
|
|
25
27
|
|
26
28
|
require 'optparse'
|
27
29
|
require 'dropcaster'
|
30
|
+
require 'dropcaster/log_formatter'
|
28
31
|
|
29
|
-
options =
|
32
|
+
options = {}
|
30
33
|
options[:auto_detect_channel_file] = true
|
31
34
|
|
32
|
-
|
35
|
+
logger = Logger.new($stderr).tap do |l|
|
36
|
+
l.level = Logger::WARN
|
37
|
+
l.formatter = Dropcaster::LogFormatter.new
|
38
|
+
end
|
39
|
+
|
40
|
+
# rubocop:disable Metrics/BlockLength
|
41
|
+
OptionParser.new do |opts|
|
33
42
|
opts.banner = help
|
34
43
|
|
35
|
-
opts.on(
|
36
|
-
|
37
|
-
Dropcaster.logger.formatter = Dropcaster::LogFormatter.new
|
38
|
-
Dropcaster.logger.level = Logger::INFO
|
44
|
+
opts.on('--verbose', 'Verbose mode - displays additional diagnostic information') do
|
45
|
+
logger.level = Logger::INFO
|
39
46
|
end
|
40
47
|
|
41
|
-
opts.on(
|
42
|
-
|
43
|
-
Dropcaster.logger.formatter = Dropcaster::LogFormatter.new
|
44
|
-
Dropcaster.logger.level = Logger::DEBUG
|
48
|
+
opts.on('--trace', 'Verbose mode - displays additional diagnostic information') do
|
49
|
+
logger.level = Logger::DEBUG
|
45
50
|
end
|
46
51
|
|
47
|
-
opts.on(
|
52
|
+
opts.on('--channel FILE', 'Read the channel definition from FILE instead of channel.yml in the current directory.') do |file|
|
53
|
+
logger.info "Reading channel definition from #{file}"
|
48
54
|
begin
|
49
|
-
Dropcaster.logger.info "Reading channel definition from #{file}"
|
50
55
|
options = YAML.load_file(file).merge(options)
|
51
56
|
options[:auto_detect_channel_file] = false
|
52
|
-
rescue
|
53
|
-
|
54
|
-
|
57
|
+
rescue StandardError
|
58
|
+
logger.error "Could not load channel definition. #{$ERROR_INFO.message}"
|
59
|
+
logger.info $ERROR_INFO.backtrace
|
55
60
|
exit(1)
|
56
61
|
end
|
57
62
|
end
|
58
63
|
|
59
|
-
opts.on(
|
60
|
-
|
64
|
+
opts.on('--title STRING', "Use STRING as the channel's title. Overrides settings read from channel definition file.") do |title|
|
65
|
+
logger.info "Setting channel title to '#{title}' via command line"
|
61
66
|
options[:title] = title
|
62
67
|
end
|
63
68
|
|
64
|
-
opts.on(
|
65
|
-
|
69
|
+
opts.on('--subtitle STRING', "Use STRING as the channel's subtitle. Overrides settings read from channel definition file.") do |subtitle|
|
70
|
+
logger.info "Setting channel subtitle to '#{subtitle}' via command line"
|
66
71
|
options[:subtitle] = subtitle
|
67
72
|
end
|
68
73
|
|
69
|
-
opts.on(
|
70
|
-
|
74
|
+
opts.on('--url URL', "Use URL as the channel's url. Overrides settings read from channel definition file.") do |url|
|
75
|
+
logger.info "Setting channel URL to '#{url}' via command line"
|
71
76
|
options[:url] = url
|
72
77
|
end
|
73
78
|
|
74
|
-
opts.on(
|
75
|
-
|
79
|
+
opts.on('--description STRING', "Use STRING as the channel's description. Overrides settings read from channel definition file.") do |description|
|
80
|
+
logger.info "Setting channel description to '#{description}' via command line"
|
76
81
|
options[:description] = description
|
77
82
|
end
|
78
83
|
|
79
|
-
opts.on(
|
80
|
-
|
84
|
+
opts.on('--enclosures URL', "Use URL as the base URL for the channel's enclosures. Overrides settings read from channel definition file.") do |enclosures_url|
|
85
|
+
logger.info "Setting enclosures base URL to '#{enclosures_url}' via command line"
|
81
86
|
options[:enclosures_url] = enclosures_url
|
82
87
|
end
|
83
88
|
|
84
|
-
opts.on(
|
85
|
-
|
89
|
+
opts.on('--image URL', "Use URL as the channel's image URL. Overrides settings read from channel definition file.") do |image_url|
|
90
|
+
logger.info "Setting image URL to '#{image_url}' via command line"
|
86
91
|
options[:image_url] = image_url
|
87
92
|
end
|
88
93
|
|
89
|
-
opts.on(
|
90
|
-
|
94
|
+
opts.on('--channel-template FILE', 'Use FILE as template for generating the channel feed. Overrides the default that comes with Dropcaster.') do |file|
|
95
|
+
logger.info "Using'#{file}' as channel template file"
|
91
96
|
options[:channel_template] = file
|
92
97
|
end
|
93
98
|
|
94
|
-
opts.on(
|
99
|
+
opts.on('--version', 'Display current version') do
|
95
100
|
puts "#{File.basename(__FILE__)} " + Dropcaster::VERSION
|
96
101
|
exit 0
|
97
102
|
end
|
98
|
-
end
|
103
|
+
end.parse!
|
104
|
+
# rubocop:enable Metrics/BlockLength
|
99
105
|
|
100
|
-
opts.parse!
|
101
106
|
sources = ARGV.blank? ? '.' : ARGV
|
102
107
|
|
103
108
|
if options[:auto_detect_channel_file]
|
104
109
|
# There was no channel file specified, so we try to load channel.yml from sources dir
|
105
110
|
channel_file = Dropcaster::ChannelFileLocator.locate(sources)
|
106
111
|
|
107
|
-
if File.
|
108
|
-
|
112
|
+
if File.exist?(channel_file)
|
113
|
+
logger.info "Auto-detected channel file at #{channel_file}"
|
109
114
|
options_from_yaml = YAML.load_file(channel_file)
|
110
115
|
options = options_from_yaml.merge(options)
|
111
116
|
else
|
112
|
-
|
113
|
-
|
117
|
+
logger.error "No channel file found at #{channel_file})"
|
118
|
+
logger.info usage
|
114
119
|
exit(1) # No way to continue without a channel definition
|
115
120
|
end
|
116
121
|
end
|
117
122
|
|
118
|
-
|
119
|
-
|
123
|
+
logger.info "Generating the channel with these options: #{options.inspect}"
|
120
124
|
begin
|
121
125
|
puts Dropcaster::Channel.new(sources, options).to_rss
|
122
|
-
rescue
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
+
rescue StandardError
|
127
|
+
logger.error $ERROR_INFO.message
|
128
|
+
$ERROR_INFO.backtrace.each do |line|
|
129
|
+
logger.debug(line)
|
126
130
|
end
|
127
|
-
|
131
|
+
logger.info usage
|
128
132
|
exit(1)
|
129
133
|
end
|