rubyhexagon 0.4.3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/rubyhexagon.rb +36 -28
- data/lib/rubyhexagon/artist.rb +92 -0
- data/lib/rubyhexagon/error.rb +21 -0
- data/lib/rubyhexagon/helper/api.rb +93 -0
- data/lib/rubyhexagon/image.rb +112 -0
- data/lib/rubyhexagon/level.rb +56 -0
- data/lib/rubyhexagon/post.rb +256 -0
- data/lib/rubyhexagon/search/posts.rb +99 -0
- data/lib/rubyhexagon/search/tags.rb +65 -0
- data/lib/rubyhexagon/tag.rb +89 -0
- data/lib/rubyhexagon/type.rb +70 -0
- data/lib/rubyhexagon/user.rb +78 -0
- metadata +34 -21
- data/lib/api.rb +0 -79
- data/lib/container.rb +0 -45
- data/lib/pool.rb +0 -71
- data/lib/post.rb +0 -50
- data/lib/search.rb +0 -100
- data/lib/set.rb +0 -59
- data/lib/standard/error.rb +0 -24
- data/lib/standard/hash.rb +0 -29
- data/lib/standard/http.rb +0 -92
- data/lib/standard/int.rb +0 -36
- data/lib/standard/string.rb +0 -91
- data/lib/standard/time.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1920d433c32360d24b4091fa37a7132f9fac4ccf36b400e034b2491679bee5b0
|
4
|
+
data.tar.gz: 7abdf32fcfaf560525b03697b7c68e63faff335bb6677c3569631b6d6b71b69e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a682ee7cba26e33eed44ddc234d41ea8ea31fd8e1dc06d9838ad2096aecc0fb97bcd47721dfb4731181ee02f675c283d4948a98a73957636239d8a1b5b639b5
|
7
|
+
data.tar.gz: 23b285239417e638de6b8873d8023b0840cb2039fb778382f367d7c9e8542da653737ea002108307fc9bfcbf6dd0790d72fc5b387ab62e6365e2aa4eeb73000c
|
data/lib/rubyhexagon.rb
CHANGED
@@ -1,33 +1,41 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# Copyright 2014-2018 Maxine Michalski <maxine@furfind.net>
|
2
|
+
#
|
3
|
+
# This file is part of rubyhexagon.
|
4
|
+
#
|
5
|
+
# rubyhexagon is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# rubyhexagon is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with rubyhexagon. If not, see <http://www.gnu.org/licenses/>.
|
3
17
|
|
4
|
-
|
18
|
+
require 'open-uri'
|
19
|
+
require 'uri'
|
20
|
+
require 'json'
|
21
|
+
require 'digest/md5'
|
5
22
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
along with rubyhexagon. If not, see <http://www.gnu.org/licenses/>.
|
18
|
-
=end
|
19
|
-
|
20
|
-
require "standard/string"
|
21
|
-
require "standard/int"
|
22
|
-
require "standard/error"
|
23
|
-
require "standard/time"
|
24
|
-
|
25
|
-
require "api"
|
26
|
-
require "container"
|
27
|
-
require "search"
|
28
|
-
require "pool"
|
23
|
+
require 'rubyhexagon/helper/api'
|
24
|
+
require 'rubyhexagon/error'
|
25
|
+
require 'rubyhexagon/user'
|
26
|
+
require 'rubyhexagon/tag'
|
27
|
+
require 'rubyhexagon/artist'
|
28
|
+
require 'rubyhexagon/type'
|
29
|
+
require 'rubyhexagon/image'
|
30
|
+
require 'rubyhexagon/level'
|
31
|
+
require 'rubyhexagon/post'
|
32
|
+
require 'rubyhexagon/search/posts'
|
33
|
+
require 'rubyhexagon/search/tags'
|
29
34
|
|
35
|
+
# Namespace for all classes in this gem.
|
36
|
+
# @author Maxine Michalski
|
37
|
+
# @since 0.4.3
|
30
38
|
module E621
|
31
|
-
|
32
|
-
|
39
|
+
NAME = 'rubyhexagon'.freeze
|
40
|
+
VERSION = '1.0.0'.freeze
|
33
41
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# Copyright 2014-2018 Maxine Michalski <maxine@furfind.net>
|
2
|
+
#
|
3
|
+
# This file is part of rubyhexagon.
|
4
|
+
#
|
5
|
+
# rubyhexagon is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# rubyhexagon is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with rubyhexagon. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
module E621
|
18
|
+
# Class to hold information about an artist on e621
|
19
|
+
#
|
20
|
+
# @author Maxine Michalski
|
21
|
+
# @since 1.0.0
|
22
|
+
class Artist
|
23
|
+
# @return [Integer] id of artist
|
24
|
+
attr_reader :id
|
25
|
+
|
26
|
+
# @return [String] name of artist
|
27
|
+
attr_reader :name
|
28
|
+
|
29
|
+
# @return [Array<String>] alternative names for artist
|
30
|
+
attr_reader :alternative_names
|
31
|
+
|
32
|
+
# @return [Array<URI>] links to find artist
|
33
|
+
attr_reader :urls
|
34
|
+
|
35
|
+
# @author Maxine Michalski
|
36
|
+
#
|
37
|
+
# Initializer for Artist.
|
38
|
+
#
|
39
|
+
# @param artist [Hash] artist data, fetched from e621
|
40
|
+
#
|
41
|
+
# @return the object
|
42
|
+
def initialize(artist)
|
43
|
+
@name = artist
|
44
|
+
end
|
45
|
+
|
46
|
+
# @author Maxine Michalski
|
47
|
+
#
|
48
|
+
# Fills this object with additional artist data
|
49
|
+
def show!
|
50
|
+
artist = API.new.fetch('artist', 'index', name: @name).first
|
51
|
+
@id = artist[:id].to_i
|
52
|
+
@alternative_names = artist[:other_names].split(/,\s+/)
|
53
|
+
@urls = artist[:urls].map { |u| URI(u) }
|
54
|
+
@active = artist[:is_active]
|
55
|
+
end
|
56
|
+
|
57
|
+
# @author Maxine Michalski
|
58
|
+
#
|
59
|
+
# Returns a filled Artist object
|
60
|
+
#
|
61
|
+
# @return [Artist] filled out artist object
|
62
|
+
def show
|
63
|
+
artist = Artist.new(@name)
|
64
|
+
artist.show!
|
65
|
+
artist
|
66
|
+
end
|
67
|
+
|
68
|
+
# @author Maxine Michalski
|
69
|
+
#
|
70
|
+
# Comparison method for artists
|
71
|
+
#
|
72
|
+
# @return [TrueClass, FalseClass]
|
73
|
+
def ==(other)
|
74
|
+
return false unless other.is_a?(Artist)
|
75
|
+
if @id && other.id
|
76
|
+
@id == other.id && @name == other.name
|
77
|
+
else
|
78
|
+
@name == other.name
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# @author Maxine Michalski
|
83
|
+
#
|
84
|
+
# Check if this artist is active
|
85
|
+
#
|
86
|
+
# @return [TrueClass] artist is active
|
87
|
+
# @return [FalseClass] artist is not active
|
88
|
+
def active?
|
89
|
+
@active
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Copyright 2014-2018 Maxine Michalski <maxine@furfind.net>
|
2
|
+
#
|
3
|
+
# This file is part of rubyhexagon.
|
4
|
+
#
|
5
|
+
# rubyhexagon is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# rubyhexagon is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with rubyhexagon. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
# Error class to show an ID is out of range or not an Integer
|
18
|
+
#
|
19
|
+
# @author Maxine Michalski
|
20
|
+
# @since 1.0.0
|
21
|
+
class InvalidIDError < StandardError; end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# Copyright 2014-2018 Maxine Michalski <maxine@furfind.net>
|
2
|
+
#
|
3
|
+
# This file is part of rubyhexagon.
|
4
|
+
#
|
5
|
+
# rubyhexagon is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# rubyhexagon is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with rubyhexagon. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
module E621
|
19
|
+
# An interface class, to unify calls from other code to e621 [dot] net.
|
20
|
+
# This class handles rate limiting, as well as provides a more uniform
|
21
|
+
# approach in making requests.
|
22
|
+
# It also ensures that a proper user agent is sent, as required by the e621
|
23
|
+
# API.
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
# @author Maxine Michalski
|
27
|
+
# @since 0.4.3
|
28
|
+
class API
|
29
|
+
# User agent, used to identify this gem against e621.
|
30
|
+
#
|
31
|
+
# @return [Hash] hash that can be used with open-uri
|
32
|
+
attr_reader :user_agent
|
33
|
+
|
34
|
+
# @author Maxine Michalski
|
35
|
+
#
|
36
|
+
# Initializer for API. All methods are instance methods.
|
37
|
+
#
|
38
|
+
# @return the object
|
39
|
+
def initialize(rspec = false)
|
40
|
+
@user_agent = { 'User-Agent' =>
|
41
|
+
"#{E621::NAME}/#{E621::VERSION} (by maxine_red on e621" }
|
42
|
+
@base = 'https://e621.net'
|
43
|
+
lock_path = '/tmp/rubyhexagon.lock'
|
44
|
+
@lock_file = File.open(lock_path, 'a')
|
45
|
+
@rspec = rspec
|
46
|
+
end
|
47
|
+
|
48
|
+
# @author Maxine Michalski
|
49
|
+
#
|
50
|
+
# @param noun [String] the e621 noun (post, tag, user, artist, etc.)
|
51
|
+
# @param action [String] action to be performed on noun (list, show, etc.)
|
52
|
+
# @param query [Hash] a hash with extra information, which is dependent on
|
53
|
+
# noun and action
|
54
|
+
#
|
55
|
+
# Fetches information from e621 and returns data to caller. This also takes
|
56
|
+
# into account rate limiting.
|
57
|
+
#
|
58
|
+
# @return [Hash] JSON parsed response.
|
59
|
+
def fetch(noun, action, query)
|
60
|
+
query = query.to_a.map { |q| "#{q.first}=#{q.last}" }.join('&')
|
61
|
+
lock do
|
62
|
+
if @rspec || !defined? RSpec
|
63
|
+
JSON.parse(open("#{@base}/#{noun}/#{action}.json?#{query}",
|
64
|
+
@user_agent).read, symbolize_names: true)
|
65
|
+
else # In RSpec environment?
|
66
|
+
JSON.parse(open("spec/data/#{noun}/#{action}.json?#{query}")
|
67
|
+
.read, symbolize_names: true)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
# @author Maxine Michalski
|
75
|
+
#
|
76
|
+
# (see #fetch)
|
77
|
+
# A wrapper for actual requests, to minimize method length.
|
78
|
+
def lock
|
79
|
+
@lock_file.flock(File::LOCK_EX)
|
80
|
+
@lock_file.truncate(0)
|
81
|
+
@lock_file.print $PROCESS_ID
|
82
|
+
begin
|
83
|
+
data = yield
|
84
|
+
# There is a hard limit of 2 requests per second, but to be nice we wait
|
85
|
+
# a whole second between requests.
|
86
|
+
sleep 1 if @rspec || !defined? RSpec
|
87
|
+
ensure
|
88
|
+
@lock_file.flock(File::LOCK_UN)
|
89
|
+
end
|
90
|
+
data
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# Copyright 2014-2018 Maxine Michalski <maxine@furfind.net>
|
2
|
+
#
|
3
|
+
# This file is part of rubyhexagon.
|
4
|
+
#
|
5
|
+
# rubyhexagon is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# rubyhexagon is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with rubyhexagon. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
module E621
|
18
|
+
# Class for post file data. This is mostly an abstraction to have data
|
19
|
+
# structures in a more Ruby like nature.
|
20
|
+
#
|
21
|
+
# @api private
|
22
|
+
# @author Maxine Michalski
|
23
|
+
# @since 1.0.0
|
24
|
+
class Image
|
25
|
+
# @return [URI] url of file
|
26
|
+
attr_reader :url
|
27
|
+
|
28
|
+
# @return [String] extension of file
|
29
|
+
attr_reader :ext
|
30
|
+
|
31
|
+
# @return [Integer] image/video width
|
32
|
+
attr_reader :width
|
33
|
+
|
34
|
+
# @return [Integer] image/video height
|
35
|
+
attr_reader :height
|
36
|
+
|
37
|
+
# @return [String] MD5 hash sum
|
38
|
+
attr_reader :md5
|
39
|
+
|
40
|
+
# @author Maxine Michalski
|
41
|
+
#
|
42
|
+
# Initializer for a File. This is not a Ruby file class, but an abstraction
|
43
|
+
# of e621 file information.
|
44
|
+
#
|
45
|
+
# @param file [Hash] file information
|
46
|
+
#
|
47
|
+
# @return the object
|
48
|
+
def initialize(file)
|
49
|
+
@url = URI(file[:url])
|
50
|
+
@md5 = File.basename(file[:url]).sub(/\.\w{3,4}$/, '')
|
51
|
+
@ext = file[:ext]
|
52
|
+
@width = file[:width].to_i
|
53
|
+
@height = file[:height].to_i
|
54
|
+
@user_agent = { 'User-Agent' =>
|
55
|
+
"#{E621::NAME}/#{E621::VERSION} (by maxine_red on e621" }
|
56
|
+
end
|
57
|
+
|
58
|
+
# @author Maxine Michalski
|
59
|
+
#
|
60
|
+
# Comparison method to comapre two Image objects (and sub class objects)
|
61
|
+
#
|
62
|
+
# @return [TrueClass, FalseClass]
|
63
|
+
def ==(other)
|
64
|
+
other.is_a?(Image) && @md5 == other.md5
|
65
|
+
end
|
66
|
+
|
67
|
+
# @author Maxine Michalski
|
68
|
+
#
|
69
|
+
# Retrieve data from e621 and save it to file.
|
70
|
+
#
|
71
|
+
# @param dirname [String] path where to save. This needs be an existing
|
72
|
+
# directory. This overwrites existing files.
|
73
|
+
# @raise [ArgumentError] Argument given is not an existing directory
|
74
|
+
def save!(dirname = './')
|
75
|
+
raise ArgumentError, 'Not a directory!' unless File.directory?(dirname)
|
76
|
+
loop do
|
77
|
+
stream = open(@url, @user_agent).read
|
78
|
+
File.open("#{dirname}/#{File.basename(@url.path)}", 'w') do |f|
|
79
|
+
f.print stream
|
80
|
+
end
|
81
|
+
break if Digest::MD5.hexdigest(stream) == @md5
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
class Sample < Image; end
|
86
|
+
|
87
|
+
# Class for post file data. This is mostly an abstraction to have data
|
88
|
+
# structures in a more Ruby like nature.
|
89
|
+
# This class just holds an adapted version of #save!, to handle the case of
|
90
|
+
# preview images having a different MD5 hash sum attribute than they actually
|
91
|
+
# should have.
|
92
|
+
# That is an e621 issue though.
|
93
|
+
#
|
94
|
+
# @api private
|
95
|
+
# @author Maxine Michalski
|
96
|
+
# @since 1.0.0
|
97
|
+
class Preview < Image
|
98
|
+
# @author Maxine Michalski
|
99
|
+
#
|
100
|
+
# Retrieve data from e621 and save it to file.
|
101
|
+
#
|
102
|
+
# @param dirname [String] path where to save. This needs be an existing
|
103
|
+
# directory. This overwrites existing files.
|
104
|
+
# @raise [ArgumentError] Argument given is not an existing directory
|
105
|
+
def save!(dirname = './')
|
106
|
+
raise ArgumentError, 'Not a directory!' unless File.directory?(dirname)
|
107
|
+
File.open("#{dirname}/#{File.basename(@url.path)}", 'w') do |f|
|
108
|
+
f.print open(@url, @user_agent).read
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# Copyright 2014-2018 Maxine Michalski <maxine@furfind.net>
|
2
|
+
#
|
3
|
+
# This file is part of rubyhexagon.
|
4
|
+
#
|
5
|
+
# rubyhexagon is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# rubyhexagon is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with rubyhexagon. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
module E621
|
18
|
+
# Class to hold level information.
|
19
|
+
#
|
20
|
+
# @api private
|
21
|
+
# @author Maxine Michalski
|
22
|
+
# @since 1.0.0
|
23
|
+
class Level
|
24
|
+
# @return [Integer] id of level
|
25
|
+
attr_reader :id
|
26
|
+
|
27
|
+
# @return [String] name of level
|
28
|
+
attr_reader :name
|
29
|
+
|
30
|
+
# @author Maxine Michalski
|
31
|
+
#
|
32
|
+
# Initializer for Level a user can have. This is just to have a more Ruby
|
33
|
+
# like interface to it.
|
34
|
+
#
|
35
|
+
# @param level [Hash] level a user can have.
|
36
|
+
#
|
37
|
+
# @return the object
|
38
|
+
def initialize(level)
|
39
|
+
@id = level
|
40
|
+
@name = if @id.between?(31, 39)
|
41
|
+
[nil, nil, :contributor, :'former staff', :janotor][@id - 30]
|
42
|
+
else
|
43
|
+
%i[unactivated blocked member privileged mod admin][@id / 10]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# @author Maxine Michalski
|
48
|
+
#
|
49
|
+
# Comparison method for Level objects
|
50
|
+
#
|
51
|
+
# @return [TrueClass, FalseClass]
|
52
|
+
def ==(other)
|
53
|
+
other.is_a?(Level) && @id == other.id && @name == other.name
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|