freakonomics 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ 2.2.2
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
4
+ before_install: gem install bundler -v 1.10.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in freakonomics.gemspec
4
+ gemspec
@@ -0,0 +1,28 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ freakonomics (0.1.0)
5
+ nokogiri (~> 1.6.6.0)
6
+ progressbar (~> 0.6)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ mini_portile (0.6.2)
12
+ minitest (5.8.2)
13
+ nokogiri (1.6.6.2)
14
+ mini_portile (~> 0.6.0)
15
+ progressbar (0.21.0)
16
+ rake (10.4.2)
17
+
18
+ PLATFORMS
19
+ ruby
20
+
21
+ DEPENDENCIES
22
+ bundler (~> 1.10)
23
+ freakonomics!
24
+ minitest (~> 5.8)
25
+ rake (~> 10.0)
26
+
27
+ BUNDLED WITH
28
+ 1.10.6
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Ile Eftimov
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 all
13
+ 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 THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,97 @@
1
+ # Freakonomics
2
+
3
+ [![Code Climate](https://codeclimate.com/github/fteem/freakonomics/badges/gpa.svg)](https://codeclimate.com/github/fteem/freakonomics)
4
+ [![Test Coverage](https://codeclimate.com/github/fteem/freakonomics/badges/coverage.svg)](https://codeclimate.com/github/fteem/freakonomics/coverage)
5
+ [![Build Status](https://travis-ci.org/fteem/freakonomics.svg)](https://travis-ci.org/fteem/freakonomics)
6
+
7
+ Freakonomics is a CLI app built with Ruby. It's purpose is to download episodes of
8
+ one of my favourite podcasts - [Freakonomics](http://freakonomics.com).
9
+
10
+ ## Installation
11
+
12
+ Install it yourself as:
13
+
14
+ $ gem install freakonomics
15
+
16
+ ## Usage
17
+
18
+ ### Download latest episode
19
+
20
+ You can download the latest episode via:
21
+
22
+ ```ruby
23
+ freak latest
24
+ ```
25
+
26
+ You can also specify a download path:
27
+
28
+ ```ruby
29
+ freak latest -p/--path "freakonomics_episodes/new"
30
+ ```
31
+
32
+ ### Download all episodes
33
+
34
+ You can download all episodes via:
35
+
36
+ ```ruby
37
+ freak all
38
+ ```
39
+
40
+ You can also specify a download path:
41
+
42
+ ```ruby
43
+ freak all -p/--path path_to_all_episodes
44
+ ```
45
+
46
+ Note: The directory will be created if it does not exist.
47
+
48
+ ### Download single episode
49
+
50
+ By name:
51
+
52
+ ```ruby
53
+ freak episode --name "Do More Expensive Wines Taste Better?"
54
+ ```
55
+
56
+ By release date:
57
+
58
+ ```ruby
59
+ freak episode --date "01 Dec 2010"
60
+ ```
61
+
62
+ Also, works with path:
63
+
64
+ ```ruby
65
+ freak episode --date "01 Dec 2010" --path path_to_episodes
66
+ ```
67
+
68
+ ```ruby
69
+ freak episode --name "Do More Expensive Wines Taste Better?" --path path_to_episodes
70
+ ```
71
+
72
+ ## To do
73
+
74
+ - [x] Download latest
75
+ - [x] Download latest with path
76
+ - [x] Download all
77
+ - [x] Download all with path
78
+ - [x] Download single episode by name
79
+ - [x] Download single episode by release date
80
+ - [x] Download single episode by name with path
81
+ - [x] Download single episode by release date with path
82
+ - [ ] Test coverage!
83
+
84
+
85
+ ## Development
86
+
87
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
88
+
89
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
90
+
91
+ ## Contributing
92
+
93
+ Bug reports and pull requests are welcome on GitHub at https://github.com/fteem/freakonomics.
94
+
95
+ ## License
96
+
97
+ See [LICENSE](https://github.com/fteem/freakonomics/blob/master/LICENSE).
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ task :default => :test
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << "test"
8
+ t.test_files = FileList['test/**/*_test.rb']
9
+ t.verbose = true
10
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "freakonomics"
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
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
4
+
5
+ require "freakonomics"
6
+ require "optparse"
7
+
8
+ options = {}
9
+
10
+ base = OptionParser.new do |opts|
11
+ opts.banner = "Usage: freak COMMAND [options] [subject]"
12
+
13
+ opts.separator ""
14
+ opts.separator <<HELP
15
+ Commonly used command are:
16
+ latest : Download the latest Freakonomics episode.
17
+ episode: Download a single Freakonomics episode.
18
+ all : Download all Freakonomics episodes.
19
+ See 'fn-salesforce COMMAND --help' for more information on a specific command.
20
+ HELP
21
+
22
+ end
23
+
24
+ commands = {
25
+ latest: OptionParser.new { |opts|
26
+ opts.banner = "Usage: freak latest --path path-to-save-episode"
27
+ opts.on("-p PATH", "--path PATH", "PATH where to save the episode. If PATH does not exist, it will be created.") do |p|
28
+ options[:path] = p.strip
29
+ end
30
+ },
31
+ episode: OptionParser.new { |opts|
32
+ opts.banner = "Usage: freak episode [options]"
33
+
34
+ opts.on("-p PATH", "--path PATH", "PATH where to save the episodes.") do |p|
35
+ options[:path] = p.strip
36
+ end
37
+ opts.on("-n NAME", "--name NAME", "The name of the episode.") do |n|
38
+ options[:name] = n.strip
39
+ end
40
+ opts.on("-d PUBLISH_DATE", "--date PUBLISH_DATE", "The publish date of the episode.") do |d|
41
+ options[:publish_date] = d.strip
42
+ end
43
+ },
44
+ all: OptionParser.new { |opts|
45
+ opts.banner = "Usage: freak all [options]"
46
+
47
+ opts.on("-p PATH", "--path PATH", "PATH where to save the episodes.") do |p|
48
+ options[:path] = p.strip
49
+ end
50
+ }
51
+ }
52
+
53
+ command_key = (ARGV.shift || "").to_sym
54
+ command = commands[command_key] || base
55
+
56
+ command.parse!
57
+
58
+ case command_key
59
+ when :latest
60
+ Freakonomics::CLI.latest(options)
61
+ when :episode
62
+ Freakonomics::CLI.episode(options)
63
+ when :all
64
+ Freakonomics::CLI.all(options)
65
+ else
66
+ puts command
67
+ end
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'freakonomics/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "freakonomics"
8
+ spec.version = Freakonomics::VERSION
9
+ spec.authors = ["Ile Eftimov"]
10
+ spec.email = ["ileeftimov@gmail.com"]
11
+ spec.licenses = ['MIT']
12
+ spec.summary = %q{Freakonomics Radio CLI downloader}
13
+ spec.description = %q{Freakonomics is a CLI app built with Ruby. It's purpose is to download episodes of Freakonomics Radio via the command line.}
14
+ spec.homepage = "https://github.com/fteem/freakonomics"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib", "bin"]
20
+
21
+ spec.add_dependency "nokogiri", "~> 1.6.6.0"
22
+ spec.add_dependency "progressbar", "~> 0.6"
23
+ spec.add_development_dependency "bundler", "~> 1.10"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "minitest", "~> 5.8"
26
+ end
@@ -0,0 +1,12 @@
1
+ require "freakonomics/version"
2
+ require "freakonomics/downloader"
3
+ require "freakonomics/fetcher"
4
+ require "freakonomics/parser"
5
+ require "freakonomics/reporter"
6
+ require "freakonomics/cli"
7
+ require "freakonomics/file_saver"
8
+ require "open-uri"
9
+ require "progressbar"
10
+
11
+ module Freakonomics
12
+ end
@@ -0,0 +1,36 @@
1
+ class Freakonomics::CLI
2
+ def self.latest opts
3
+ raw_feed = Freakonomics::Fetcher.fetch_feed
4
+ metadata = Freakonomics::Parser.parse(raw_feed).first
5
+ Freakonomics::Reporter.download(metadata[:name])
6
+ episode = Freakonomics::Downloader.download(metadata[:name], metadata[:url])
7
+ Freakonomics::FileSaver.save!(metadata[:name], episode, opts[:path])
8
+ end
9
+
10
+ def self.episode opts
11
+ raw_feed = Freakonomics::Fetcher.fetch_feed
12
+ metadata = Freakonomics::Parser.parse(raw_feed)
13
+ if opts[:name]
14
+ episode_metadata = metadata.detect {|meta| meta[:name] == opts[:name] }
15
+ abort("No episode found with name: #{opts[:name]}") unless episode_metadata
16
+ end
17
+ if opts[:publish_date]
18
+ episode_metadata = metadata.detect {|meta| meta[:publish_date] == opts[:publish_date] }
19
+ abort("No episode found with release date: #{opts[:publish_date]}") unless episode_metadata
20
+ end
21
+ Freakonomics::Reporter.download(episode_metadata[:name])
22
+ episode = Freakonomics::Downloader.download(episode_metadata[:name], episode_metadata[:url])
23
+ Freakonomics::FileSaver.save!(episode_metadata[:name], episode, opts[:path])
24
+ end
25
+
26
+ def self.all opts
27
+ raw_feed = Freakonomics::Fetcher.fetch_feed
28
+ metadata = Freakonomics::Parser.parse(raw_feed)
29
+ metadata.each do |episode_metadata|
30
+ Freakonomics::Reporter.download(episode_metadata[:name])
31
+ episode = Freakonomics::Downloader.download(episode_metadata[:name], episode_metadata[:url])
32
+ Freakonomics::FileSaver.save!(episode_metadata[:name], episode, opts[:path])
33
+ Freakonomics::Reporter.downloaded(episode_metadata[:name])
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,25 @@
1
+ class Freakonomics::Downloader
2
+ def self.download name, url
3
+ new.download(name, url)
4
+ end
5
+
6
+ def download name, url
7
+ download_episode(name, url)
8
+ end
9
+
10
+ private
11
+
12
+ def download_episode name, url, path = nil
13
+ progress_bar = nil
14
+
15
+ download = open(url,
16
+ content_length_proc: proc { |total|
17
+ progress_bar = ProgressBar.new("Download", total)
18
+ },
19
+ progress_proc: proc { |step|
20
+ progress_bar.set(step)
21
+ }
22
+ )
23
+
24
+ end
25
+ end
@@ -0,0 +1,7 @@
1
+ class Freakonomics::Fetcher
2
+ FEED_URL = "http://feeds.feedburner.com/freakonomicsradio?format=xml"
3
+
4
+ def self.fetch_feed
5
+ open(FEED_URL).read
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ class Freakonomics::FileSaver
2
+ def self.save!(episode_name, episode_file, path = "./")
3
+ full_path = path + "/" + episode_name + ".mp3"
4
+ if File.directory?(path)
5
+ IO.copy_stream(episode_file, full_path)
6
+ else
7
+ Dir.mkdir(path)
8
+ IO.copy_stream(episode_file, full_path)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,35 @@
1
+ require 'nokogiri'
2
+
3
+ class Freakonomics::Parser
4
+ DATE_REGEX = /\d\d [a-zA-Z]+ \d\d\d\d/
5
+
6
+ def self.parse feed
7
+ new.parse(feed)
8
+ end
9
+
10
+ def parse feed
11
+ doc = Nokogiri::XML feed
12
+ episodes = doc.css("item")
13
+ episodes.inject([]) do |store, episode|
14
+ store << {
15
+ name: extract_episode_title(episode),
16
+ url: extract_episode_url(episode),
17
+ publish_date: extract_episode_release_date(episode)
18
+ }
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def extract_episode_title episode
25
+ episode.css("title").children.first.text.strip
26
+ end
27
+
28
+ def extract_episode_url episode
29
+ episode.xpath("//feedburner:origEnclosureLink").children.first.text.gsub("www.podtrac.com/pts/redirect.mp3/","")
30
+ end
31
+
32
+ def extract_episode_release_date episode
33
+ episode.css("pubDate").children.first.text.strip[DATE_REGEX]
34
+ end
35
+ end
@@ -0,0 +1,17 @@
1
+ class Freakonomics::Reporter
2
+ def self.download file_name
3
+ STDOUT.puts "Downloading Episode: \"#{file_name}\"..."
4
+ end
5
+
6
+ def self.downloaded file_name
7
+ STDOUT.puts "Episode: \"#{file_name}\" downloaded."
8
+ end
9
+
10
+ def self.all
11
+ STDOUT.puts "Downloading ALL Episodes..."
12
+ end
13
+
14
+ def self.not_found
15
+ STDOUT.puts "Episode not found."
16
+ end
17
+ end