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 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