rubyhexagon 0.4.3 → 1.0.0
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 +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
@@ -0,0 +1,256 @@
|
|
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
|
+
# This class holds post information, fetched from e621, and gives access in a
|
19
|
+
# more Ruby like manner.
|
20
|
+
#
|
21
|
+
# @author Maxine Michalski
|
22
|
+
# @since 1.0.0
|
23
|
+
class Post
|
24
|
+
# @return [Integer] id of post information
|
25
|
+
attr_reader :id
|
26
|
+
|
27
|
+
# @return [User] user object of who uploaded this post
|
28
|
+
attr_reader :author
|
29
|
+
|
30
|
+
# @return [Time] creation time of post
|
31
|
+
attr_reader :created_at
|
32
|
+
|
33
|
+
# @return [Symbol] status of post, can be :active, :flagged, :pending or
|
34
|
+
# :deleted
|
35
|
+
attr_reader :status
|
36
|
+
|
37
|
+
# @return [Array<String>] array of sources. This can contain URI in string
|
38
|
+
# form
|
39
|
+
attr_reader :sources
|
40
|
+
|
41
|
+
# @return [Array<Artist>] array of artists, that work on the image in this
|
42
|
+
# post
|
43
|
+
attr_reader :artists
|
44
|
+
|
45
|
+
# @return [String] description that's associated with this post
|
46
|
+
attr_reader :description
|
47
|
+
|
48
|
+
# @return [Integer] number of people, who favorited this post
|
49
|
+
attr_reader :favorites
|
50
|
+
|
51
|
+
# @return [Integer] vote score this post holds
|
52
|
+
attr_reader :score
|
53
|
+
|
54
|
+
# @return [Symbol] rating of this post. Can be one of :safe,
|
55
|
+
# :questionable, :explicit
|
56
|
+
attr_reader :rating
|
57
|
+
|
58
|
+
# @return [Post] parent of this post
|
59
|
+
# @return [NilClass]
|
60
|
+
attr_reader :parent
|
61
|
+
|
62
|
+
# @return [Array<Post>] Array of child posts
|
63
|
+
attr_reader :children
|
64
|
+
|
65
|
+
# @return [String] MD5 checksum associated with this post
|
66
|
+
attr_reader :md5
|
67
|
+
|
68
|
+
# @return [E621::Image] file content of this post
|
69
|
+
attr_reader :image
|
70
|
+
|
71
|
+
# @return [E621::Sample] sample data in E621::Sample format
|
72
|
+
attr_reader :sample
|
73
|
+
|
74
|
+
# @return [E621::Preview] preview data in E621::Preview format
|
75
|
+
attr_reader :preview
|
76
|
+
|
77
|
+
# @author Maxine Michalski
|
78
|
+
#
|
79
|
+
# Initializer for Post.
|
80
|
+
#
|
81
|
+
# @param id [Integer] post id on e621
|
82
|
+
#
|
83
|
+
# @return the object
|
84
|
+
def initialize(id)
|
85
|
+
id = id.to_i
|
86
|
+
unless id.is_a?(Integer) && id > 0
|
87
|
+
raise InvalidIDError, "ID out of range: #{id}"
|
88
|
+
end
|
89
|
+
@id = id
|
90
|
+
end
|
91
|
+
|
92
|
+
# @author Maxine Michalski
|
93
|
+
#
|
94
|
+
# @param post [Hash] post data, if present
|
95
|
+
#
|
96
|
+
# Fetch data from e621 to current post id
|
97
|
+
def show!(post = nil)
|
98
|
+
post = API.new.fetch('post', 'show', id: @id) if post.nil?
|
99
|
+
@created_at = Time.at(post[:created_at][:s].to_i)
|
100
|
+
@status = post[:status].to_sym
|
101
|
+
setup_author(post)
|
102
|
+
setup_relatives(post)
|
103
|
+
setup_file_data(post)
|
104
|
+
setup_additional_data(post)
|
105
|
+
end
|
106
|
+
|
107
|
+
# @author Maxine Michalski
|
108
|
+
#
|
109
|
+
# @param post [Hash] post data, if present
|
110
|
+
#
|
111
|
+
# Fetch data from e621 to current post id
|
112
|
+
def show(post = nil)
|
113
|
+
post = API.new.fetch('post', 'show', id: @id) if post.nil?
|
114
|
+
tmp = Post.new(post[:id].to_i)
|
115
|
+
tmp.show!(post)
|
116
|
+
tmp
|
117
|
+
end
|
118
|
+
|
119
|
+
# @author Maxine Michalski
|
120
|
+
#
|
121
|
+
# Retrieve an Array of this post's tags
|
122
|
+
#
|
123
|
+
# @return [Array<Tag>] array of tags
|
124
|
+
def tags
|
125
|
+
API.new.fetch('post', 'tags', id: @id).map do |tag|
|
126
|
+
Tag.new(tag[:id]).show(tag)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# @author Maxine Michalski
|
131
|
+
#
|
132
|
+
# Test status with an optional parameter. This is more meant to be used by
|
133
|
+
# alias methods
|
134
|
+
#
|
135
|
+
# @return [TrueClass]
|
136
|
+
# @return [FalseClass]
|
137
|
+
def test_status(status = nil)
|
138
|
+
status ||= __callee__.to_s.sub(/\?/, '').to_sym
|
139
|
+
@status == status
|
140
|
+
end
|
141
|
+
alias active? test_status
|
142
|
+
alias flagged? test_status
|
143
|
+
alias pending? test_status
|
144
|
+
alias deleted? test_status
|
145
|
+
|
146
|
+
# @author Maxine Michalski
|
147
|
+
#
|
148
|
+
# Check a post for a certain rating. This is rather meant to be used via
|
149
|
+
# alias methids.
|
150
|
+
#
|
151
|
+
# @return [TrueClass]
|
152
|
+
# @return [FalseClass]
|
153
|
+
def test_rating(rating = nil)
|
154
|
+
rating ||= __callee__.to_s.sub(/\?/, '').to_sym
|
155
|
+
@rating == rating
|
156
|
+
end
|
157
|
+
alias safe? test_rating
|
158
|
+
alias questionable? test_rating
|
159
|
+
alias explicit? test_rating
|
160
|
+
|
161
|
+
# @author Maxine Michalski
|
162
|
+
#
|
163
|
+
# Comparison method for posts
|
164
|
+
#
|
165
|
+
# @return [TrueClass, FalseClass]
|
166
|
+
def ==(other)
|
167
|
+
other.is_a?(Post) && @id == other.id
|
168
|
+
end
|
169
|
+
|
170
|
+
private
|
171
|
+
|
172
|
+
# @author Maxine Michalski
|
173
|
+
#
|
174
|
+
# Helper function, to setup post file data
|
175
|
+
def setup_file_data(post)
|
176
|
+
@md5 = post[:md5]
|
177
|
+
@image = E621::Image.new(url: post[:file_url], ext: post[:file_ext],
|
178
|
+
width: post[:width], height: post[:height])
|
179
|
+
setup_sample(post)
|
180
|
+
setup_preview(post)
|
181
|
+
end
|
182
|
+
|
183
|
+
# @author Maxine Michalski
|
184
|
+
#
|
185
|
+
# Helper function, to setup post sample data
|
186
|
+
def setup_sample(post)
|
187
|
+
@sample = E621::Sample.new(url: post[:sample_url], ext: post[:file_ext],
|
188
|
+
width: post[:sample_width],
|
189
|
+
height: post[:sample_height])
|
190
|
+
end
|
191
|
+
|
192
|
+
# @author Maxine Michalski
|
193
|
+
#
|
194
|
+
# Helper function, to setup post preview data
|
195
|
+
def setup_preview(post)
|
196
|
+
@preview = E621::Preview.new(url: post[:preview_url], ext: 'jpg',
|
197
|
+
width: post[:preview_width],
|
198
|
+
height: post[:preview_height])
|
199
|
+
end
|
200
|
+
|
201
|
+
# @author Maxine Michalski
|
202
|
+
#
|
203
|
+
# Helper function to add additional post data
|
204
|
+
def setup_additional_data(post)
|
205
|
+
@sources = post[:source].nil? ? [] : post[:sources]
|
206
|
+
@artists = post[:artist].map { |a| Artist.new(a) }
|
207
|
+
@description = post[:description]
|
208
|
+
@favorites = post[:fav_count].to_i
|
209
|
+
@score = post[:score].to_i
|
210
|
+
@rating = case post[:rating]
|
211
|
+
when 's' then :safe
|
212
|
+
when 'q' then :questionable
|
213
|
+
when 'e' then :explicit
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
# @author Maxine Michalski
|
218
|
+
#
|
219
|
+
# Helper function to related posts (children, parent)
|
220
|
+
def setup_relatives(post)
|
221
|
+
@children = post[:children].split(',').map { |i| Post.new(i) }
|
222
|
+
@parent = post[:parent_id].nil? ? nil : Post.new(post[:parent_id])
|
223
|
+
end
|
224
|
+
|
225
|
+
# @author Maxine Michalski
|
226
|
+
#
|
227
|
+
# Helper function to set author of a post
|
228
|
+
def setup_author(post)
|
229
|
+
@author = User.new(id: post[:creator_id], name: post[:author])
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
# This class holds post information, fetched from e621, and gives access in a
|
234
|
+
# more Ruby like manner.
|
235
|
+
# This is only for deleted posts.
|
236
|
+
#
|
237
|
+
# @author Maxine Michalski
|
238
|
+
# @since 1.0.0
|
239
|
+
class DeletedPost < Post
|
240
|
+
# @return [String] deletion reason, when available
|
241
|
+
attr_reader :reason
|
242
|
+
|
243
|
+
# @author Maxine Michalski
|
244
|
+
#
|
245
|
+
# Initializer for DeletedPost.
|
246
|
+
#
|
247
|
+
# @param id [Integer] post id on e621
|
248
|
+
# @param delreason [String] reason of deletion
|
249
|
+
#
|
250
|
+
# @return the object
|
251
|
+
def initialize(id, delreason)
|
252
|
+
super(id)
|
253
|
+
@reason = delreason
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
@@ -0,0 +1,99 @@
|
|
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
|
+
# Module to hold search classes
|
19
|
+
#
|
20
|
+
# @author Maxine Michalski
|
21
|
+
# @since 1.0.0
|
22
|
+
module Search
|
23
|
+
# Class to hold methods for Post searches.
|
24
|
+
#
|
25
|
+
# @author Maxine Michalski
|
26
|
+
# @since 1.0.0
|
27
|
+
class Posts
|
28
|
+
# @author Maxine Michalski
|
29
|
+
#
|
30
|
+
# Retrieve a list of deleted post, with deletion reason. Only id and
|
31
|
+
# del_reason is present.
|
32
|
+
# This method accepts blocks and only returns one page without blocks
|
33
|
+
#
|
34
|
+
# @param page [Integer] page of deleted posts to return
|
35
|
+
#
|
36
|
+
# @return [Array<Post>] an array of deleted posts
|
37
|
+
def self.deleted(page = 1)
|
38
|
+
d = fetch_deleted(page)
|
39
|
+
while block_given? && d != []
|
40
|
+
d.each { |del| yield del }
|
41
|
+
d = fetch_deleted(page)
|
42
|
+
page += 1
|
43
|
+
end
|
44
|
+
d
|
45
|
+
end
|
46
|
+
|
47
|
+
# @author Maxine Michalski
|
48
|
+
#
|
49
|
+
# Retrieve a list of post data, which is filtered by arguments.
|
50
|
+
# This method requires a block to be passed to it!
|
51
|
+
#
|
52
|
+
# @param tags [String] this can be any request that can be done on e621
|
53
|
+
# too
|
54
|
+
# @param limit [Integer] number of posts to return. This has a hard limit
|
55
|
+
# of 320
|
56
|
+
# @param before_id [Integer] start post ID is lesser than this ID
|
57
|
+
#
|
58
|
+
# This method accepts blocks and only returns one page without blocks
|
59
|
+
#
|
60
|
+
# @return [Array<Post>] an array of posts
|
61
|
+
def self.list(tags, limit = 320, before_id = 2_000_000)
|
62
|
+
parameters = { tags: tags, limit: limit, before_id: before_id }
|
63
|
+
posts = fetch_posts(parameters)
|
64
|
+
while block_given? && posts != []
|
65
|
+
posts.each { |post| yield post }
|
66
|
+
posts = fetch_posts(parameters)
|
67
|
+
parameters[:before_id] = posts.last.nil? ? 0 : posts.last.id
|
68
|
+
end
|
69
|
+
posts
|
70
|
+
end
|
71
|
+
|
72
|
+
# @author Maxine Michalski
|
73
|
+
#
|
74
|
+
# Helper function for deleted posts
|
75
|
+
#
|
76
|
+
# @return [Array<Post>] array of deleted posts
|
77
|
+
def self.fetch_deleted(page)
|
78
|
+
api = API.new
|
79
|
+
api.fetch('post', 'deleted_index', page: page).map do |post|
|
80
|
+
DeletedPost.new(post[:id], post[:delreason])
|
81
|
+
end
|
82
|
+
end
|
83
|
+
private_class_method :fetch_deleted
|
84
|
+
|
85
|
+
# @author Maxine Michalski
|
86
|
+
#
|
87
|
+
# Helper function for posts
|
88
|
+
#
|
89
|
+
# @return [Array<Post>] array of posts
|
90
|
+
def self.fetch_posts(parameters)
|
91
|
+
api = API.new
|
92
|
+
api.fetch('post', 'index', parameters).map do |data|
|
93
|
+
Post.new(data[:id]).show(data)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
private_class_method :fetch_deleted
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,65 @@
|
|
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
|
+
# Module to hold search classes
|
19
|
+
#
|
20
|
+
# @author Maxine Michalski
|
21
|
+
# @since 1.0.0
|
22
|
+
module Search
|
23
|
+
# Class to hold methods for Tag searches.
|
24
|
+
#
|
25
|
+
# @author Maxine Michalski
|
26
|
+
# @since 1.0.0
|
27
|
+
class Tags
|
28
|
+
# @author Maxine Michalski
|
29
|
+
#
|
30
|
+
# Retrieve a list of post data, which is filtered by arguments.
|
31
|
+
# This method accepts a block and returns only one page without one.
|
32
|
+
#
|
33
|
+
# @param name [String] name pattern to search tags with
|
34
|
+
# @param limit [Integer] number of tags to return. This has a hard limit
|
35
|
+
# of 500
|
36
|
+
# @param after_id [Integer] only look for tags after this ID
|
37
|
+
#
|
38
|
+
# @return [Array<Tag>] array of tags
|
39
|
+
def self.list(name, limit = 500, page = 1)
|
40
|
+
params = { name_pattern: name, order: :date, limit: limit,
|
41
|
+
page: page }
|
42
|
+
t = fetch_tags(params)
|
43
|
+
while block_given? && t != []
|
44
|
+
t.each { |tag| yield tag }
|
45
|
+
t = fetch_tags(params)
|
46
|
+
params[:page] += 1
|
47
|
+
end
|
48
|
+
t
|
49
|
+
end
|
50
|
+
|
51
|
+
# @author Maxine Michalski
|
52
|
+
#
|
53
|
+
# Helper function to get Tag data
|
54
|
+
#
|
55
|
+
# @return [Array<Tag>] array of tags
|
56
|
+
def self.fetch_tags(params)
|
57
|
+
api = API.new
|
58
|
+
api.fetch('tag', 'index', params).map do |data|
|
59
|
+
Tag.new(data[:id]).show(data)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
private_class_method :fetch_tags
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,89 @@
|
|
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 tag information.
|
19
|
+
#
|
20
|
+
# @author Maxine Michalski
|
21
|
+
# @since 1.0.0
|
22
|
+
class Tag
|
23
|
+
# @return [Integer] id of tag
|
24
|
+
attr_reader :id
|
25
|
+
|
26
|
+
# @return [String] name of tag
|
27
|
+
attr_reader :name
|
28
|
+
|
29
|
+
# @return [Integer] number of posts that have this tag assigned to them
|
30
|
+
attr_reader :count
|
31
|
+
|
32
|
+
# @return [Type] type of this tag
|
33
|
+
attr_reader :type
|
34
|
+
|
35
|
+
# @author Maxine Michalski
|
36
|
+
#
|
37
|
+
# Initializer for Tag.
|
38
|
+
#
|
39
|
+
# @raise InvalidIDError
|
40
|
+
#
|
41
|
+
# @param tag [Integer] tag data, fetched from e621
|
42
|
+
#
|
43
|
+
# @return the object
|
44
|
+
def initialize(id)
|
45
|
+
unless id.is_a?(Integer) && id > 0
|
46
|
+
raise InvalidIDError, "ID out of range: #{id}"
|
47
|
+
end
|
48
|
+
@id = id
|
49
|
+
end
|
50
|
+
|
51
|
+
# @author Maxine Michalski
|
52
|
+
#
|
53
|
+
# Bang method to fill tag data. If data is already available at creation,
|
54
|
+
# use the initializer!
|
55
|
+
def show!(tag = nil)
|
56
|
+
tag = API.new.fetch('tag', 'show', id: @id) if tag.nil?
|
57
|
+
@name = tag[:name]
|
58
|
+
@count = tag[:count].to_i
|
59
|
+
@type = (Type.new(tag[:type], tag[:type_locked]) unless tag[:type].nil?)
|
60
|
+
end
|
61
|
+
|
62
|
+
# @author Maxine Michalski
|
63
|
+
#
|
64
|
+
# Bang method to fill tag data. If data is already available at creation,
|
65
|
+
# use the initializer!
|
66
|
+
def show(tag = nil)
|
67
|
+
new_tag = Tag.new(@id)
|
68
|
+
new_tag.show!(tag)
|
69
|
+
new_tag
|
70
|
+
end
|
71
|
+
|
72
|
+
# @author Maxine Michalski
|
73
|
+
#
|
74
|
+
# Comparison operator for Tag, to override the default one.
|
75
|
+
# @note This method looks for same id and same name only.
|
76
|
+
# @note If there is only a an ID set with one argument, then only compare
|
77
|
+
# IDs
|
78
|
+
#
|
79
|
+
# @return [TrueClass, FalseClass]
|
80
|
+
def ==(other)
|
81
|
+
return false unless other.is_a?(Tag)
|
82
|
+
if @name.nil? || other.name.nil?
|
83
|
+
@id == other.id
|
84
|
+
else
|
85
|
+
@id == other.id && @name == other.name
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|