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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a0ba6239bf1b972497e5a67367385ee5078361e5
4
- data.tar.gz: 2dbb6830d9893988e6b08bea317ad1b44e0d1321
2
+ SHA256:
3
+ metadata.gz: 1920d433c32360d24b4091fa37a7132f9fac4ccf36b400e034b2491679bee5b0
4
+ data.tar.gz: 7abdf32fcfaf560525b03697b7c68e63faff335bb6677c3569631b6d6b71b69e
5
5
  SHA512:
6
- metadata.gz: 60745e307ebad26cff032df12f73b0c9d8315869193f2de75e5accc3f1d7bdd72f5d6cb29ab62c22360bf853c887a9b9d239d0c9a19a42bfd2e1be6a470f1149
7
- data.tar.gz: 7cbec7dcd77f387ef16d5a44377de26985c5af75a2deaad789ca3b433a1dd2973712389604765c3e782ee4de59eed57da1fe2d97a55f583f813a6853596fdaff
6
+ metadata.gz: 8a682ee7cba26e33eed44ddc234d41ea8ea31fd8e1dc06d9838ad2096aecc0fb97bcd47721dfb4731181ee02f675c283d4948a98a73957636239d8a1b5b639b5
7
+ data.tar.gz: 23b285239417e638de6b8873d8023b0840cb2039fb778382f367d7c9e8542da653737ea002108307fc9bfcbf6dd0790d72fc5b387ab62e6365e2aa4eeb73000c
@@ -1,33 +1,41 @@
1
- =begin
2
- Copyright 2014, 2015, 2017 Maxine Michalski <maxine@furfind.net>
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
- This file is part of rubyhexagon.
18
+ require 'open-uri'
19
+ require 'uri'
20
+ require 'json'
21
+ require 'digest/md5'
5
22
 
6
- rubyhexagon is free software: you can redistribute it and/or modify
7
- it under the terms of the GNU General Public License as published by
8
- the Free Software Foundation, either version 3 of the License, or
9
- (at your option) any later version.
10
-
11
- rubyhexagon is distributed in the hope that it will be useful,
12
- but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- GNU General Public License for more details.
15
-
16
- You should have received a copy of the GNU General Public License
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
- Name = "rubyhexagon"
32
- Version = "0.4.3"
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