wallhavened 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 36794ae7b739307ea0af71ef74ebceef6aec55ae0bd6d1f14f676fbd2e58912e
4
+ data.tar.gz: 2fc86626f4990b814676b017ddf03e9faacf070b695d11e7c3f75bfcf49cb938
5
+ SHA512:
6
+ metadata.gz: 458d9f2ee3598475a65f5d1e1b0e821948a3f4a3c1ea71634fed1ac5a3cdfe5a30c0711a7e4c71543dc4404240430204acfa94247d21cf8a677e2a3fef6d5fa6
7
+ data.tar.gz: cbdf3247db9b370fb8168faee95c3020367b72fb34460812992be41f55de16858f3efb991486bee9324f46d77aacbc421f84237000b382fc95a62a96fb3b9872
data/.envrc ADDED
@@ -0,0 +1 @@
1
+ use nix
data/.rubocop.yml ADDED
@@ -0,0 +1,13 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.6
3
+
4
+ Style/StringLiterals:
5
+ Enabled: true
6
+ EnforcedStyle: double_quotes
7
+
8
+ Style/StringLiteralsInInterpolation:
9
+ Enabled: true
10
+ EnforcedStyle: double_quotes
11
+
12
+ Layout/LineLength:
13
+ Max: 120
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Wallhavened
2
+
3
+ TODO: Delete this and the text below, and describe your gem
4
+
5
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/wallhavened`. To experiment with that code, run `bin/console` for an interactive prompt.
6
+
7
+ ## Installation
8
+
9
+ TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
10
+
11
+ Install the gem and add to the application's Gemfile by executing:
12
+
13
+ $ bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
14
+
15
+ If bundler is not being used to manage dependencies, install the gem by executing:
16
+
17
+ $ gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Development
24
+
25
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
26
+
27
+ 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 the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
28
+
29
+ ## Contributing
30
+
31
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/wallhavened.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "minitest/test_task"
5
+
6
+ Minitest::TestTask.create
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[test rubocop]
data/exe/wallhavened ADDED
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env ruby
2
+ require "bundler/setup"
3
+
4
+ require_relative "../lib/wallhavened"
5
+
6
+ require "thor"
7
+ require "cli/ui"
8
+
9
+ class App < Thor
10
+ package_name "wallhavened"
11
+
12
+ def self.exit_on_failure?
13
+ true
14
+ end
15
+
16
+ desc "download_all_collections USERNAME API_KEY DIRECTORY", "Download wallpapers from all user collections"
17
+ method_options username: :string, api_key: :string, directory: :string
18
+ def download_all_collections(username, api_key, directory)
19
+ driver = WallhavenAuth.new(username, api_key)
20
+
21
+ CLI::UI::Spinner.spin("Collecting collection data...") do |spinner|
22
+ walls = driver.scrape_all_user_collections
23
+ walls.each_with_index do |wall, i|
24
+ spinner.update_title("Downloading wallpapers... [#{i + 1}/#{walls.count}]")
25
+ wall.download(directory)
26
+ end
27
+ end
28
+ puts "Wallpapers available in #{directory}"
29
+ end
30
+
31
+ desc "download_collection USERNAME API_KEY DIRECTORY", "Download wallpapers from a user collection"
32
+ method_options username: :string, api_key: :string, directory: :string
33
+ def download_collection(username, api_key, directory)
34
+ driver = WallhavenAuth.new(username, api_key)
35
+
36
+ collection = CLI::UI::Prompt.ask("Which collection to download?") do |handler|
37
+ driver.user_collections do |collection|
38
+ handler.option(collection.label) { collection }
39
+ end
40
+ end
41
+
42
+ CLI::UI::Spinner.spin("Collecting collection data...") do |spinner|
43
+ walls = driver.scrape_collection(collection.id)
44
+ walls.each_with_index do |wall, i|
45
+ spinner.update_title("Downloading wallpapers... [#{i + 1}/#{walls.count}]")
46
+ wall.download(directory)
47
+ end
48
+ end
49
+ puts "Wallpapers available in #{directory}"
50
+ end
51
+ end
52
+
53
+ CLI::UI::StdoutRouter.enable
54
+ App.start
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Wallhavened
4
+ VERSION = "0.0.1"
5
+ end
@@ -0,0 +1,82 @@
1
+ require_relative "wallhaven_wallpaper"
2
+
3
+ require "open-uri"
4
+ require "nokogiri"
5
+ require "json"
6
+
7
+ class RequestSender
8
+ def get_json(url)
9
+ begin
10
+ json = JSON.parse(URI.parse(url).open.read)
11
+ rescue OpenURI::HTTPError => e
12
+ raise e unless e.to_s.include?("429")
13
+ puts("Delaying for 10s")
14
+ sleep(10)
15
+ retry
16
+ end
17
+ json
18
+ end
19
+ end
20
+
21
+ class Wallhaven
22
+ SITE_URL = "https://wallhaven.cc".freeze
23
+ SITE_API = "#{SITE_URL}/api/v1".freeze
24
+
25
+ def initialize
26
+ @request_sender = RequestSender.new
27
+ end
28
+ end
29
+
30
+ class Collection
31
+ attr_reader :id, :label
32
+
33
+ def initialize(id, label)
34
+ @id = id
35
+ @label = label
36
+ end
37
+ end
38
+
39
+ class WallhavenAuth < Wallhaven
40
+ def initialize(username, api_key)
41
+ @username = username
42
+ @api_key = api_key
43
+ super()
44
+ end
45
+
46
+ def scrape_all_user_collections
47
+ user_collections.flat_map { |collection| scrape_collection(collection.id) }
48
+ end
49
+
50
+ def user_collections
51
+ url = "#{SITE_API}/collections?apikey=#{@api_key}"
52
+ collections = []
53
+ @request_sender.get_json(url)["data"].each do |collection|
54
+ collection = Collection.new(collection["id"], collection["label"])
55
+ yield collection if block_given?
56
+ collections << collection
57
+ end
58
+ collections
59
+ end
60
+
61
+ def scrape_collection(id)
62
+ max_page = collection_pages_count(id)
63
+ walls = []
64
+ (1..max_page).each do |page|
65
+ walls += scrape_collection_page(id, page)
66
+ sleep 1.4
67
+ end
68
+ walls
69
+ end
70
+
71
+ def collection_pages_count(id)
72
+ url = "#{SITE_API}/collections/#{@username}/#{id}?page=1"
73
+ json = @request_sender.get_json(url)
74
+ json["meta"]["last_page"]
75
+ end
76
+
77
+ def scrape_collection_page(id, page)
78
+ url = "#{SITE_API}/collections/#{@username}/#{id}?page=#{page}"
79
+ json = @request_sender.get_json(url)
80
+ json["data"].map { |wallpaper| WallhavenWallpaper.new(wallpaper["path"], wallpaper["id"]) }
81
+ end
82
+ end
@@ -0,0 +1,18 @@
1
+ class WallhavenWallpaper
2
+ SITE_URL = "https://wallhaven.cc".freeze
3
+ attr_reader :url
4
+
5
+ def initialize(img_url, id)
6
+ @img_url = img_url
7
+ @id = id
8
+ @filename = img_url.split("/")[-1]
9
+ puts @filename
10
+ end
11
+
12
+ def download(path)
13
+ output_path = "#{path}/#{@filename}"
14
+ URI.parse(@img_url).open do |image|
15
+ File.binwrite(output_path, image.read)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "wallhavened/version"
4
+ require_relative "wallhavened/wallhaven"
5
+
6
+ module Wallhavened
7
+ class Error < StandardError; end
8
+ # Your code goes here...
9
+ end
@@ -0,0 +1,4 @@
1
+ module Wallhavened
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/wallhavened/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "wallhavened"
7
+ spec.version = Wallhavened::VERSION
8
+ spec.authors = ["Remigiusz Micielski"]
9
+ spec.email = ["rmicielski@purelymail.com"]
10
+ spec.summary = "Scrapes wallhaven"
11
+
12
+ # spec.description = "TODO: Write a longer description or delete this line."
13
+ # spec.homepage = "TODO: Put your gem's website or public repo "
14
+ spec.required_ruby_version = ">= 2.6.0"
15
+
16
+ # spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
17
+
18
+ # spec.metadata["homepage_uri"] = spec.homepage
19
+ # spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
20
+ # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(__dir__) do
25
+ `git ls-files -z`.split("\x0").reject do |f|
26
+ (File.expand_path(f) == __FILE__) ||
27
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git appveyor Gemfile])
28
+ end
29
+ end
30
+ spec.bindir = "exe"
31
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
32
+ spec.require_paths = ["lib"]
33
+
34
+ # Uncomment to register a new dependency of your gem
35
+ # spec.add_dependency "wallhavaned", "~> 1.0"
36
+ spec.add_runtime_dependency "rake", "~> 13.0"
37
+ spec.add_runtime_dependency "minitest", "~> 5.16"
38
+ spec.add_runtime_dependency "open-uri"
39
+ spec.add_runtime_dependency "nokogiri"
40
+ spec.add_runtime_dependency "rdoc"
41
+ spec.add_runtime_dependency "thor"
42
+ spec.add_runtime_dependency "cli-ui"
43
+
44
+ # For more information and examples about making a new gem, check out our
45
+ # guide at: https://bundler.io/guides/creating_gem.html
46
+ end
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wallhavened
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Remigiusz Micielski
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-06-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '13.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '13.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.16'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.16'
41
+ - !ruby/object:Gem::Dependency
42
+ name: open-uri
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: nokogiri
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rdoc
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: thor
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: cli-ui
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description:
112
+ email:
113
+ - rmicielski@purelymail.com
114
+ executables:
115
+ - wallhavened
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".envrc"
120
+ - ".rubocop.yml"
121
+ - README.md
122
+ - Rakefile
123
+ - exe/wallhavened
124
+ - lib/wallhavened.rb
125
+ - lib/wallhavened/version.rb
126
+ - lib/wallhavened/wallhaven.rb
127
+ - lib/wallhavened/wallhaven_wallpaper.rb
128
+ - sig/wallhavened.rbs
129
+ - wallhavened.gemspec
130
+ homepage:
131
+ licenses: []
132
+ metadata: {}
133
+ post_install_message:
134
+ rdoc_options: []
135
+ require_paths:
136
+ - lib
137
+ required_ruby_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: 2.6.0
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ requirements: []
148
+ rubygems_version: 3.4.22
149
+ signing_key:
150
+ specification_version: 4
151
+ summary: Scrapes wallhaven
152
+ test_files: []