dropcaster 0.0.6 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +5 -5
  2. data/.gemnasium.yml +1 -0
  3. data/.gitignore +12 -14
  4. data/.rubocop.yml +34 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +20 -5
  7. data/CONTRIBUTING.md +18 -0
  8. data/Dockerfile +4 -0
  9. data/Gemfile +2 -0
  10. data/Gemfile.lock +309 -65
  11. data/Guardfile +8 -6
  12. data/LICENSE.txt +1 -1
  13. data/README.markdown +43 -37
  14. data/Rakefile +46 -2
  15. data/{TODO → TODO.markdown} +0 -0
  16. data/VISION.markdown +52 -18
  17. data/Vagrantfile +10 -0
  18. data/bin/dropcaster +57 -53
  19. data/bin/lstags +29 -28
  20. data/dropcaster.gemspec +31 -20
  21. data/lib/dropcaster.rb +2 -15
  22. data/lib/dropcaster/channel.rb +54 -43
  23. data/lib/dropcaster/channel_file_locator.rb +8 -5
  24. data/lib/dropcaster/contributors.rb +39 -0
  25. data/lib/dropcaster/errors.rb +6 -4
  26. data/lib/dropcaster/item.rb +20 -14
  27. data/lib/dropcaster/log_formatter.rb +10 -0
  28. data/lib/dropcaster/logging.rb +13 -0
  29. data/lib/dropcaster/version.rb +3 -1
  30. data/templates/channel.html.erb +3 -6
  31. data/templates/channel.rss.erb +6 -5
  32. data/test/Vagrantfile +3 -1
  33. data/test/bin/vagrant-status +37 -31
  34. data/test/extensions/windows.rb +3 -1
  35. data/test/fixtures/extension.MP3 +0 -0
  36. data/test/fixtures/special &.mp3 +0 -0
  37. data/test/fixtures/test_template.json.erb +3 -4
  38. data/test/helper.rb +4 -1
  39. data/test/unit/test_app.rb +29 -24
  40. data/test/unit/test_channel.rb +9 -5
  41. data/test/unit/test_channel_locator.rb +8 -5
  42. data/test/unit/test_channel_xml.rb +29 -9
  43. data/test/unit/{test_item.rb → test_itunes_item.rb} +5 -6
  44. data/website/.gitignore +2 -0
  45. data/website/README.markdown +8 -0
  46. data/website/_config.yml +14 -0
  47. data/website/_front_matter/contributing.yaml +5 -0
  48. data/website/_front_matter/index.yaml +3 -0
  49. data/website/_front_matter/vision.yaml +5 -0
  50. data/website/_includes/footer.html +55 -0
  51. data/website/_includes/head.html +11 -0
  52. data/website/_includes/header.html +27 -0
  53. data/website/_layouts/default.html +20 -0
  54. data/website/_layouts/page.html +14 -0
  55. data/website/_layouts/post.html +15 -0
  56. data/website/_sass/_base.scss +204 -0
  57. data/website/_sass/_layout.scss +236 -0
  58. data/website/_sass/_syntax-highlighting.scss +67 -0
  59. data/website/css/main.scss +49 -0
  60. data/website/deploy.sh +23 -0
  61. data/website/feed.xml +30 -0
  62. 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(%r|^.*\.gemspec|)
5
+ watch(/^.*\.gemspec/)
4
6
  end
5
7
 
6
8
  guard 'minitest' do
7
- watch(%r|^test/unit/test_(.*)\.rb|)
8
- watch(%r|^lib/*\.rb|){'test/unit'}
9
- watch(%r|^lib/.*/*\.rb|){'test/unit'}
10
- watch(%r{^lib/.*/([^/]+)\.rb$}){|m| "test/unit/test_#{m[1]}.rb"}
11
- watch(%r|^test/helper\.rb|){'test/unit'}
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
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011-2014 Nicolas E. Rabenau
1
+ Copyright (c) 2011-2015 Nicolas E. Rabenau
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
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 [VISION](VISION.md) reflects the vision where the tool should go._
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://rubydoc.info/gems/dropcaster/file/README.md) is a podcast feed generator for the command line. It is most simple to use with Dropbox, but works equally well with any other hoster.
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://feedvalidator.org/docs/rss2.html#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.
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
- :title: 'All About Everything'
36
- :subtitle: 'A show about everything'
37
- :url: 'http://www.example.com/podcasts/everything/index.html'
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 ~/Dropbox/Public).
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. ~/Dropbox/Public), and then run the following command in the directory where the mp3 files reside:
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
- $ dropcaster > index.rss
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
- $ dropcaster > index.rss
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
- $ dropcaster > index.rss
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
- $ dropcaster > index.rss
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
- $ dropcaster project1 > project1.rss
98
- $ dropcaster project2 > project2.rss
107
+ $ dropcaster project1 > project1.rss
108
+ $ dropcaster project2 > project2.rss
99
109
 
100
110
  or
101
111
 
102
- $ cd project1
103
- $ dropcaster > index.rss
104
- $ cd ../project2
105
- $ dropcaster > index.rss
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
- $ dropcaster project1 project2 > index.rss
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
- $ dropcaster --help
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
- $ dropcaster --channel-template templates/channel.html.erb
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
- $ dropcaster --channel-template templates/channel.html.erb > ~/Dropbox/Public/allabouteverything.html
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
- # Contributing to Dropcaster
168
-
169
- Dropcaster is hosted at [Github](http://github.com/nerab/dropcaster):
181
+ # Web site
170
182
 
171
- * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
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-2014 Nicolas E. Rabenau. See [LICENSE.txt](https://raw.github.com/nerab/dropcaster/master/LICENSE.txt) for further details.
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
- # encoding: utf-8
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 :default => :test
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
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.md) reflects the functionality that is actually implemented._
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://rubydoc.info/gems/dropcaster/file/README.md) is a podcast feed generator for the command line. It is most simple to use with Dropbox, but works equally well with any other hoster.
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://feedvalidator.org/docs/rss2.html#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.
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 ~/Dropbox/Public).
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. ~/Dropbox/Public), and then run the following command in the directory where the mp3 files reside:
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
- # Contributing to Dropcaster
176
-
177
- Dropcaster is hosted at [Github](http://github.com/nerab/dropcaster):
217
+ # Web site
178
218
 
179
- * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
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-2014 Nicolas E. Rabenau. See [LICENSE.txt](https://raw.github.com/nerab/dropcaster/master/LICENSE.txt) for further details.
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
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # -*- mode: ruby -*-
4
+ # vi: set ft=ruby :
5
+
6
+ Vagrant.configure(2) do |config|
7
+ config.vm.provider 'docker' do |d|
8
+ d.build_dir = '.'
9
+ end
10
+ end
data/bin/dropcaster CHANGED
@@ -1,22 +1,24 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
4
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
5
 
5
6
  require 'yaml'
7
+ require 'English'
6
8
 
7
- help = <<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://rubydoc.info/gems/dropcaster/file/README.md
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
- dropcaster Prints a podcast feed document for the mp3 files in the current directory.
16
- dropcaster [FILE]... Prints a podcast feed document for FILES
17
- dropcaster [DIR]... Prints a podcast feed document for the mp3 files in DIR
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 = Hash.new
32
+ options = {}
30
33
  options[:auto_detect_channel_file] = true
31
34
 
32
- opts = OptionParser.new do |opts|
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("--verbose", "Verbose mode - displays additional diagnostic information") do |file|
36
- Dropcaster.logger = Logger.new(STDERR)
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("--trace", "Verbose mode - displays additional diagnostic information") do |file|
42
- Dropcaster.logger = Logger.new(STDERR)
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("--channel FILE", "Read the channel definition from FILE instead of channel.yml in the current directory.") do |file|
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
- Dropcaster.logger.error "Could not load channel definition. #{$!.message}"
54
- Dropcaster.logger.info $!.backtrace
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("--title STRING", "Use STRING as the channel's title. Overrides settings read from channel definition file.") do |title|
60
- Dropcaster.logger.info "Setting channel title to '#{title}' via command line"
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("--subtitle STRING", "Use STRING as the channel's subtitle. Overrides settings read from channel definition file.") do |subtitle|
65
- Dropcaster.logger.info "Setting channel subtitle to '#{subtitle}' via command line"
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("--url URL", "Use URL as the channel's url. Overrides settings read from channel definition file.") do |url|
70
- Dropcaster.logger.info "Setting channel URL to '#{url}' via command line"
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("--description STRING", "Use STRING as the channel's description. Overrides settings read from channel definition file.") do |description|
75
- Dropcaster.logger.info "Setting channel description to '#{description}' via command line"
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("--enclosures URL", "Use URL as the base URL for the channel's enclosures. Overrides settings read from channel definition file.") do |enclosures_url|
80
- Dropcaster.logger.info "Setting enclosures base URL to '#{enclosures_url}' via command line"
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("--image URL", "Use URL as the channel's image URL. Overrides settings read from channel definition file.") do |image_url|
85
- Dropcaster.logger.info "Setting image URL to '#{image_url}' via command line"
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("--channel-template FILE", "Use FILE as template for generating the channel feed. Overrides the default that comes with Dropcaster.") do |file|
90
- Dropcaster.logger.info "Using'#{file}' as channel template file"
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("--version", "Display current version") do
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.exists?(channel_file)
108
- Dropcaster.logger.info "Auto-detected channel file at #{channel_file}"
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
- Dropcaster.logger.error "No channel file found at #{channel_file})"
113
- Dropcaster.logger.info usage
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
- Dropcaster.logger.info "Generating the channel with these options: #{options.inspect}"
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
- Dropcaster.logger.error $!.message
124
- $!.backtrace.each do |line|
125
- Dropcaster.logger.debug(line)
126
+ rescue StandardError
127
+ logger.error $ERROR_INFO.message
128
+ $ERROR_INFO.backtrace.each do |line|
129
+ logger.debug(line)
126
130
  end
127
- Dropcaster.logger.info usage
131
+ logger.info usage
128
132
  exit(1)
129
133
  end