reddit_image_downloader 0.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in reddit_image_downloader.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Brendan Loudermilk
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,109 @@
1
+ # RedditImageDownloader
2
+
3
+ RedditImageDownloader is a command line tool written in Ruby for downloading
4
+ images from any subreddit on reddit.com.
5
+
6
+ ## Installation
7
+
8
+ The tool is available on RubyGems:
9
+
10
+ $ gem install reddit_image_downloader
11
+
12
+ ## Usage
13
+
14
+ Use the `reddit_image_downloader` command to download images. Specify one or
15
+ more of the options below to customize your query.
16
+
17
+ $ reddit_image_downloader [options]
18
+
19
+ ### Specifying subreddit(s)
20
+
21
+ You must use `--subreddits` (shorthand `-r`) to specify one or more subreddits
22
+ as a comma-separated list. The following example will download the top images
23
+ [/r/EarthPorn][earthporn] and [/r/awww][awww].
24
+
25
+ $ reddit_image_downloader -r EarthPorn,awww
26
+
27
+ ### Downloading to a specific path
28
+
29
+ By default, the command will download all images into the current working
30
+ directory of your shell. You can override this behavior with the
31
+ `--destination` (shorthand `-d`) option. The following example will download
32
+ images from [/r/Earthporn][earthporn] to your desktop.
33
+
34
+ $ reddit_image_downloader -r EarthPorn -d ~/Desktop
35
+
36
+ ### Requiring minimum dimensions
37
+
38
+ You may choose to only download images which meet minimum width and height
39
+ requirements with the `--min-width` (shorthand `-x`) and `--min-height`
40
+ (shorthand `-y`) options respectively. The following example will download
41
+ images from [/r/EarthPorn][earthporn] *only* if they are 1920x1080.
42
+
43
+ $ reddit_image_downloader -r EarthPorn -x 1920 -y 1080
44
+
45
+ You may choose to only specify one dimension, as well.
46
+
47
+ $ reddit_image_downloader -r EarthPorn -y 1080
48
+
49
+ ### Choosing a page
50
+
51
+ You may choose to download images from either one the of "top" (default),
52
+ "new", or "controversial" pages with the `--page` (shorthand `-p`) option. The
53
+ following example will download new images from [/r/awww][awww].
54
+
55
+ $ reddit_image_downloader -r awww -p new
56
+
57
+ ### Purging old images
58
+
59
+ The initial use case for this tool was to manage a folder for wallpaper
60
+ images. The `--max-age` (shorthand `-a`) option can be used to purge images
61
+ older than a specified number of days. The following example will download
62
+ images from [/r/awww][awww] then delete any images that were downloaded more
63
+ than 14 days ago.
64
+
65
+ $ reddit_image_downloader -r awww -a 14
66
+
67
+ ### Need help?
68
+
69
+ You can use the `--help` (shorthand `-h`) option to see a list of all the
70
+ available options and a short description of each. The following example shows
71
+ the help message:
72
+
73
+ $ reddit_image_downloader -h
74
+
75
+ ## Contributing
76
+
77
+ 1. Fork it
78
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
79
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
80
+ 4. Push to the branch (`git push origin my-new-feature`)
81
+ 5. Create new Pull Request
82
+
83
+ [earthporn]: http://reddit.com/r/EarthPorn
84
+ [awww]: http://reddit.com/r/awww
85
+
86
+ ## License
87
+
88
+ Copyright (c) 2013 Brendan Loudermilk
89
+
90
+ MIT License
91
+
92
+ Permission is hereby granted, free of charge, to any person obtaining
93
+ a copy of this software and associated documentation files (the
94
+ "Software"), to deal in the Software without restriction, including
95
+ without limitation the rights to use, copy, modify, merge, publish,
96
+ distribute, sublicense, and/or sell copies of the Software, and to
97
+ permit persons to whom the Software is furnished to do so, subject to
98
+ the following conditions:
99
+
100
+ The above copyright notice and this permission notice shall be
101
+ included in all copies or substantial portions of the Software.
102
+
103
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
104
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
105
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
106
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
107
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
108
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
109
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "reddit_image_downloader"
4
+
5
+ RedditImageDownloader::Processor.process!(
6
+ RedditImageDownloader::OptionParser.parse(ARGV)
7
+ )
@@ -0,0 +1,21 @@
1
+ # Stdlib
2
+ require "optparse"
3
+ require "ostruct"
4
+
5
+ # Gems
6
+ require "snoo"
7
+ require "mechanize"
8
+ require "dimensions"
9
+
10
+ # Development Gems
11
+ if ENV["DEV"]
12
+ require "pry"
13
+ end
14
+
15
+ # Self
16
+ require "reddit_image_downloader/version"
17
+ require "reddit_image_downloader/option_parser"
18
+ require "reddit_image_downloader/processor"
19
+
20
+ module RedditImageDownloader
21
+ end
@@ -0,0 +1,78 @@
1
+ module RedditImageDownloader
2
+ module OptionParser
3
+ PAGES = %W[top new controversial]
4
+
5
+ DEFAULT_OPTIONS = {
6
+ show_help: false,
7
+ subreddits: [],
8
+ min_width: 0,
9
+ min_height: 0,
10
+ destination: Dir.pwd,
11
+ max_age: nil,
12
+ page: :top,
13
+ }
14
+
15
+ BANNER = "Usage: reddit_image_downloader [options]"
16
+
17
+ SUBREDDIT_FORMATS = %W[-r --subreddits=SUB1,SUB2]
18
+ SUBREDDIT_DESC = "List of subreddits to download from"
19
+
20
+ PATH_FORMATS = %W[-d --destination=PATH]
21
+ PATH_DESC = "Path to download images to (defaults to current directory)"
22
+
23
+ WIDTH_FORMATS = %W[-x --min-width=WIDTH]
24
+ WIDTH_DESC = "Only download images at least WIDTH wide"
25
+
26
+ HEIGHT_FORMATS = %W[-y --min-height=HEIGHT]
27
+ HEIGHT_DESC = "Only download images at least HEIGHT tall"
28
+
29
+ PAGE_FORMATS = %W[-p --page=PAGE]
30
+ PAGE_DESC = "Page to download (top [default], new, controversial)"
31
+
32
+ DAYS_FORMATS = %W[-a --max-age=DAYS]
33
+ DAYS_DESC = "Purge files in destination folder older than DAYS days"
34
+
35
+ HELP_FORMATS = %W[-h --help]
36
+ HELP_DESC = "Show this message"
37
+
38
+ def self.parse(args)
39
+ options = DEFAULT_OPTIONS.dup
40
+
41
+ parser = ::OptionParser.new do |parser|
42
+ parser.banner = BANNER
43
+
44
+ parser.on(*SUBREDDIT_FORMATS, Array, SUBREDDIT_DESC) do |subreddits|
45
+ options[:subreddits] += subreddits
46
+ end
47
+
48
+ parser.on(*PATH_FORMATS, PATH_DESC) do |destination|
49
+ options[:destination] = destination
50
+ end
51
+
52
+ parser.on(*WIDTH_FORMATS, Integer, WIDTH_DESC) do |min_width|
53
+ options[:min_width] = min_width
54
+ end
55
+
56
+ parser.on(*HEIGHT_FORMATS, Integer, HEIGHT_DESC) do |min_height|
57
+ options[:min_height] = min_height
58
+ end
59
+
60
+ parser.on(*PAGE_FORMATS, PAGES, PAGE_DESC) do |page|
61
+ options[:page] = page
62
+ end
63
+
64
+ parser.on(*DAYS_FORMATS, Integer, DAYS_DESC) do |days|
65
+ options[:max_age] = days
66
+ end
67
+
68
+ parser.on_tail(*HELP_FORMATS, HELP_DESC) do
69
+ options[:show_help] = true
70
+ end
71
+ end
72
+
73
+ parser.parse!(args)
74
+
75
+ options
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,59 @@
1
+ module RedditImageDownloader
2
+ class Processor < Struct.new(:options)
3
+ def self.process!(options)
4
+ new(options).process!
5
+ end
6
+
7
+ def process!
8
+ listings.each do |listing|
9
+ download = agent.get(listing["url"])
10
+
11
+ if download.is_a?(Mechanize::Image)
12
+ reader = Dimensions::Reader.new
13
+
14
+ reader << download.body
15
+
16
+ if reader.width > options[:min_width] && reader.height > options[:min_height]
17
+ filename = "#{listing["id"]}.#{reader.type}"
18
+ destination = File.join(options[:destination], filename)
19
+
20
+ unless File.exists?(destination)
21
+ download.save(destination)
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ if options[:max_age]
28
+ file_query = File.join(options[:destination], "*")
29
+
30
+ Dir[file_query].each do |file|
31
+ age = Time.now - File.ctime(file)
32
+ days_old = age / (24 * 3600)
33
+
34
+ if days_old > options[:max_age]
35
+ File.delete(file)
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def listings
44
+ options[:subreddits].map do |subreddit|
45
+ client.get_listing(subreddit: subreddit, page: options[:page]).parsed_response["data"]["children"]
46
+ end.flatten.map do |listing|
47
+ listing["data"]
48
+ end
49
+ end
50
+
51
+ def client
52
+ @client ||= Snoo::Client.new
53
+ end
54
+
55
+ def agent
56
+ @agent ||= Mechanize.new
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,3 @@
1
+ module RedditImageDownloader
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'reddit_image_downloader/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "reddit_image_downloader"
8
+ spec.version = RedditImageDownloader::VERSION
9
+ spec.authors = ["Brendan Loudermilk"]
10
+ spec.email = ["brendan@gophilosophie.com"]
11
+ spec.description = %q{Download images from Reddit}
12
+ spec.summary = %q{Download images from Reddit}
13
+ spec.homepage = "https://github.com/bloudermilk/reddit_image_downloader"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "pry", "~> 0.9.12.2"
24
+
25
+ spec.add_dependency "snoo", "~> 0.1.2"
26
+ spec.add_dependency "mechanize", "~> 2.7.2"
27
+ spec.add_dependency "dimensions", "~> 1.2.0"
28
+ end
metadata ADDED
@@ -0,0 +1,154 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: reddit_image_downloader
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Brendan Loudermilk
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-10-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ prerelease: false
16
+ version_requirements: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: '1.3'
21
+ none: false
22
+ type: :development
23
+ name: bundler
24
+ requirement: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ version: '1.3'
29
+ none: false
30
+ - !ruby/object:Gem::Dependency
31
+ prerelease: false
32
+ version_requirements: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ! '>='
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
37
+ none: false
38
+ type: :development
39
+ name: rake
40
+ requirement: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ none: false
46
+ - !ruby/object:Gem::Dependency
47
+ prerelease: false
48
+ version_requirements: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ~>
51
+ - !ruby/object:Gem::Version
52
+ version: 0.9.12.2
53
+ none: false
54
+ type: :development
55
+ name: pry
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ version: 0.9.12.2
61
+ none: false
62
+ - !ruby/object:Gem::Dependency
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 0.1.2
69
+ none: false
70
+ type: :runtime
71
+ name: snoo
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: 0.1.2
77
+ none: false
78
+ - !ruby/object:Gem::Dependency
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ~>
83
+ - !ruby/object:Gem::Version
84
+ version: 2.7.2
85
+ none: false
86
+ type: :runtime
87
+ name: mechanize
88
+ requirement: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ~>
91
+ - !ruby/object:Gem::Version
92
+ version: 2.7.2
93
+ none: false
94
+ - !ruby/object:Gem::Dependency
95
+ prerelease: false
96
+ version_requirements: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ~>
99
+ - !ruby/object:Gem::Version
100
+ version: 1.2.0
101
+ none: false
102
+ type: :runtime
103
+ name: dimensions
104
+ requirement: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ~>
107
+ - !ruby/object:Gem::Version
108
+ version: 1.2.0
109
+ none: false
110
+ description: Download images from Reddit
111
+ email:
112
+ - brendan@gophilosophie.com
113
+ executables:
114
+ - reddit_image_downloader
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - .gitignore
119
+ - Gemfile
120
+ - LICENSE.txt
121
+ - README.md
122
+ - Rakefile
123
+ - bin/reddit_image_downloader
124
+ - lib/reddit_image_downloader.rb
125
+ - lib/reddit_image_downloader/option_parser.rb
126
+ - lib/reddit_image_downloader/processor.rb
127
+ - lib/reddit_image_downloader/version.rb
128
+ - reddit_image_downloader.gemspec
129
+ homepage: https://github.com/bloudermilk/reddit_image_downloader
130
+ licenses:
131
+ - MIT
132
+ post_install_message:
133
+ rdoc_options: []
134
+ require_paths:
135
+ - lib
136
+ required_ruby_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ! '>='
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ none: false
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ! '>='
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ none: false
148
+ requirements: []
149
+ rubyforge_project:
150
+ rubygems_version: 1.8.25
151
+ signing_key:
152
+ specification_version: 3
153
+ summary: Download images from Reddit
154
+ test_files: []