artbase 0.1.0 → 0.2.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 +4 -4
- data/CHANGELOG.md +3 -3
- data/Manifest.txt +3 -6
- data/README.md +274 -39
- data/Rakefile +38 -29
- data/bin/artbase +17 -17
- data/lib/artbase/attributes.rb +83 -83
- data/lib/artbase/collection/base.rb +268 -0
- data/lib/artbase/collection/image.rb +39 -39
- data/lib/artbase/collection/opensea.rb +297 -484
- data/lib/artbase/collection/token.rb +362 -72
- data/lib/artbase/collection.rb +12 -12
- data/lib/artbase/helper.rb +168 -149
- data/lib/artbase/image/sample.rb +31 -0
- data/lib/artbase/image.rb +31 -75
- data/lib/artbase/retry.rb +41 -0
- data/lib/artbase/tool.rb +169 -159
- data/lib/artbase/version.rb +22 -22
- data/lib/artbase.rb +103 -42
- metadata +22 -12
- data/LICENSE.md +0 -116
- data/lib/artbase/image/24x24.rb +0 -68
- data/lib/artbase/image/32x32.rb +0 -43
- data/lib/artbase/image/60x60.rb +0 -70
- data/lib/artbase/image/80x80.rb +0 -90
- data/lib/artbase/opensea.rb +0 -144
data/lib/artbase/helper.rb
CHANGED
@@ -1,149 +1,168 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
def slugify( name )
|
5
|
-
name.downcase.gsub( /[^a-z0-9 ()$_-]/ ) do |_|
|
6
|
-
puts " !! WARN: asciify - found (and removing) non-ascii char >#{Regexp.last_match}<"
|
7
|
-
'' ## remove - use empty string
|
8
|
-
end.gsub( ' ', '_')
|
9
|
-
end
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
def convert_images( collection, from: 'jpg',
|
15
|
-
to: 'png'
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
files.
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
end
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
1
|
+
|
2
|
+
|
3
|
+
|
4
|
+
def slugify( name )
|
5
|
+
name.downcase.gsub( /[^a-z0-9 ()$_-]/ ) do |_|
|
6
|
+
puts " !! WARN: asciify - found (and removing) non-ascii char >#{Regexp.last_match}<"
|
7
|
+
'' ## remove - use empty string
|
8
|
+
end.gsub( ' ', '_')
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
def convert_images( collection, from: 'jpg',
|
15
|
+
to: 'png',
|
16
|
+
dir: 'i',
|
17
|
+
overwrite: true )
|
18
|
+
files = Dir.glob( "./#{collection}/#{dir}/*.#{from}" )
|
19
|
+
puts "==> converting #{files.size} image(s) from #{from} to #{to}"
|
20
|
+
|
21
|
+
files.each_with_index do |file,i|
|
22
|
+
dirname = File.dirname( file )
|
23
|
+
extname = File.extname( file )
|
24
|
+
basename = File.basename( file, extname )
|
25
|
+
|
26
|
+
## skip convert if target / dest file already exists
|
27
|
+
next if overwrite == false && File.exist?( "#{dirname}/#{basename}.#{to}" )
|
28
|
+
|
29
|
+
|
30
|
+
cmd = "magick convert #{dirname}/#{basename}.#{from} #{dirname}/#{basename}.#{to}"
|
31
|
+
|
32
|
+
puts " [#{i+1}/#{files.size}] - #{cmd}"
|
33
|
+
system( cmd )
|
34
|
+
|
35
|
+
if from == 'gif'
|
36
|
+
## assume multi-images for gif
|
37
|
+
## save image-0.png to image.png
|
38
|
+
path0 = "#{dirname}/#{basename}-0.#{to}"
|
39
|
+
path = "#{dirname}/#{basename}.#{to}"
|
40
|
+
|
41
|
+
puts " saving #{path0} to #{path}..."
|
42
|
+
|
43
|
+
blob = File.open( path0, 'rb' ) { |f| f.read }
|
44
|
+
File.open( path, 'wb' ) { |f| f.write( blob ) }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
def copy_json( src, dest )
|
57
|
+
uri = URI.parse( src )
|
58
|
+
|
59
|
+
http = Net::HTTP.new( uri.host, uri.port )
|
60
|
+
|
61
|
+
puts "[debug] GET #{uri.request_uri} uri=#{uri}"
|
62
|
+
|
63
|
+
headers = { 'User-Agent' => "ruby v#{RUBY_VERSION}" }
|
64
|
+
|
65
|
+
|
66
|
+
request = Net::HTTP::Get.new( uri.request_uri, headers )
|
67
|
+
if uri.instance_of? URI::HTTPS
|
68
|
+
http.use_ssl = true
|
69
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
70
|
+
end
|
71
|
+
|
72
|
+
response = http.request( request )
|
73
|
+
|
74
|
+
if response.code == '200'
|
75
|
+
puts "#{response.code} #{response.message}"
|
76
|
+
puts " content_type: #{response.content_type}, content_length: #{response.content_length}"
|
77
|
+
|
78
|
+
text = response.body.to_s
|
79
|
+
text = text.force_encoding( Encoding::UTF_8 )
|
80
|
+
|
81
|
+
data = JSON.parse( text )
|
82
|
+
|
83
|
+
File.open( dest, "w:utf-8" ) do |f|
|
84
|
+
f.write( JSON.pretty_generate( data ) )
|
85
|
+
end
|
86
|
+
else
|
87
|
+
puts "!! error:"
|
88
|
+
puts "#{response.code} #{response.message}"
|
89
|
+
exit 1
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
def copy_image( src, dest,
|
95
|
+
dump_headers: false )
|
96
|
+
uri = URI.parse( src )
|
97
|
+
|
98
|
+
http = Net::HTTP.new( uri.host, uri.port )
|
99
|
+
|
100
|
+
puts "[debug] GET #{uri.request_uri} uri=#{uri}"
|
101
|
+
|
102
|
+
headers = { 'User-Agent' => "ruby v#{RUBY_VERSION}" }
|
103
|
+
|
104
|
+
request = Net::HTTP::Get.new( uri.request_uri, headers )
|
105
|
+
if uri.instance_of? URI::HTTPS
|
106
|
+
http.use_ssl = true
|
107
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
108
|
+
end
|
109
|
+
|
110
|
+
response = http.request( request )
|
111
|
+
|
112
|
+
if response.code == '200'
|
113
|
+
puts "#{response.code} #{response.message}"
|
114
|
+
|
115
|
+
content_type = response.content_type
|
116
|
+
content_length = response.content_length
|
117
|
+
puts " content_type: #{content_type}, content_length: #{content_length}"
|
118
|
+
|
119
|
+
if dump_headers ## for debugging dump headers
|
120
|
+
headers = response.each_header.to_h
|
121
|
+
puts "htttp respone headers:"
|
122
|
+
pp headers
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
format = if content_type =~ %r{image/jpeg}i
|
127
|
+
'jpg'
|
128
|
+
elsif content_type =~ %r{image/png}i
|
129
|
+
'png'
|
130
|
+
elsif content_type =~ %r{image/gif}i
|
131
|
+
'gif'
|
132
|
+
elsif content_type =~ %r{image/svg}i
|
133
|
+
'svg'
|
134
|
+
else
|
135
|
+
puts "!! error:"
|
136
|
+
puts " unknown image format content type: >#{content_type}<"
|
137
|
+
exit 1
|
138
|
+
end
|
139
|
+
|
140
|
+
## make sure path exits - autocreate dirs
|
141
|
+
## make sure path exists
|
142
|
+
dirname = File.dirname( "#{dest}.#{format}" )
|
143
|
+
FileUtils.mkdir_p( dirname ) unless Dir.exist?( dirname )
|
144
|
+
|
145
|
+
if format == 'svg'
|
146
|
+
## save as text (note: assume utf-8 encoding for now)
|
147
|
+
text = response.body.to_s
|
148
|
+
text = text.force_encoding( Encoding::UTF_8 )
|
149
|
+
|
150
|
+
File.open( "#{dest}.svg", 'w:utf-8' ) do |f|
|
151
|
+
f.write( text )
|
152
|
+
end
|
153
|
+
else
|
154
|
+
## save as binary
|
155
|
+
File.open( "#{dest}.#{format}", 'wb' ) do |f|
|
156
|
+
f.write( response.body )
|
157
|
+
end
|
158
|
+
end
|
159
|
+
else
|
160
|
+
puts "!! error:"
|
161
|
+
puts "#{response.code} #{response.message}"
|
162
|
+
exit 1
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
|
168
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Pixelart
|
2
|
+
|
3
|
+
class Image
|
4
|
+
|
5
|
+
###
|
6
|
+
# add common
|
7
|
+
# pixel(ate) steps/offsets (for re/down/sampling)
|
8
|
+
DOwNSAMPLING_STEPS = {
|
9
|
+
'24x24' => {
|
10
|
+
'269x269' => Image.calc_sample_steps( 269, 24 ), # width (269px), new_width (24px)
|
11
|
+
'512x512' => Image.calc_sample_steps( 512, 24 ), # width (512px), new_width (24px)
|
12
|
+
},
|
13
|
+
'32x32' => {
|
14
|
+
'320x320' => Image.calc_sample_steps( 320, 32 ),
|
15
|
+
'512x512' => Image.calc_sample_steps( 512, 32 ),
|
16
|
+
},
|
17
|
+
'35x35' => {
|
18
|
+
'512x512' => Image.calc_sample_steps( 512, 35 ),
|
19
|
+
},
|
20
|
+
'60x60' => {
|
21
|
+
'512x512' => Image.calc_sample_steps( 512, 60 ),
|
22
|
+
},
|
23
|
+
'80x80' => {
|
24
|
+
'512x512' => Image.calc_sample_steps( 512, 80 ),
|
25
|
+
},
|
26
|
+
}
|
27
|
+
|
28
|
+
end # class Image
|
29
|
+
end # module Pixelart
|
30
|
+
|
31
|
+
|
data/lib/artbase/image.rb
CHANGED
@@ -1,75 +1,31 @@
|
|
1
|
-
######################
|
2
|
-
# pixelart image extensions
|
3
|
-
# move upstream!!!!!
|
4
|
-
|
5
|
-
|
6
|
-
module Pixelart
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
dest
|
34
|
-
end
|
35
|
-
alias_method :pixelate, :sample
|
36
|
-
end # class Image
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
class ImageComposite
|
41
|
-
def add_glob( glob )
|
42
|
-
files = Dir.glob( glob )
|
43
|
-
puts "#{files.size} file(s) found matching >#{glob}<"
|
44
|
-
|
45
|
-
|
46
|
-
files = files.sort
|
47
|
-
## puts files.inspect
|
48
|
-
|
49
|
-
files.each_with_index do |file,i|
|
50
|
-
puts "==> [#{i+1}/#{files.size}] - #{file}"
|
51
|
-
img = Image.read( file )
|
52
|
-
|
53
|
-
self << img ## todo/check: use add alias - why? why not?
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end # class ImageComposite
|
57
|
-
end # module Pixelart
|
58
|
-
|
59
|
-
|
60
|
-
###
|
61
|
-
# add common
|
62
|
-
# pixel(ate) offsets (for sampling)
|
63
|
-
PIXEL_OFFSETS = {}
|
64
|
-
|
65
|
-
module Pixelart
|
66
|
-
class Image
|
67
|
-
PIXEL_OFFSETS = ::PIXEL_OFFSETS
|
68
|
-
end
|
69
|
-
end # module Pixelart
|
70
|
-
|
71
|
-
|
72
|
-
require_relative 'image/24x24'
|
73
|
-
require_relative 'image/32x32'
|
74
|
-
require_relative 'image/60x60'
|
75
|
-
require_relative 'image/80x80'
|
1
|
+
######################
|
2
|
+
# pixelart image extensions
|
3
|
+
# move upstream!!!!!
|
4
|
+
|
5
|
+
|
6
|
+
module Pixelart
|
7
|
+
class ImageComposite
|
8
|
+
def add_glob( glob )
|
9
|
+
files = Dir.glob( glob )
|
10
|
+
puts "#{files.size} file(s) found matching >#{glob}<"
|
11
|
+
|
12
|
+
|
13
|
+
files = files.sort
|
14
|
+
## puts files.inspect
|
15
|
+
|
16
|
+
files.each_with_index do |file,i|
|
17
|
+
puts "==> [#{i+1}/#{files.size}] - #{file}"
|
18
|
+
img = Image.read( file )
|
19
|
+
|
20
|
+
self << img ## todo/check: use add alias - why? why not?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end # class ImageComposite
|
24
|
+
end # module Pixelart
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
require_relative 'image/sample' ## check - change to downsample/pixelate - why? why not?
|
29
|
+
|
30
|
+
|
31
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
## for more ideas on retry
|
3
|
+
## see https://github.com/ooyala/retries
|
4
|
+
|
5
|
+
|
6
|
+
## todo/check: use a different name than retry - why? why not?
|
7
|
+
def retry_on_error( max_tries: 3, &block )
|
8
|
+
errors = []
|
9
|
+
delay = 3 ## 3 secs
|
10
|
+
|
11
|
+
begin
|
12
|
+
block.call
|
13
|
+
|
14
|
+
## note: add more exception here (separated by comma) like
|
15
|
+
## rescue Errno::ETIMEDOUT, Errno::ECONNREFUSED => e
|
16
|
+
rescue Net::ReadTimeout => e
|
17
|
+
## (re)raise (use raise with arguments or such - why? why not?)
|
18
|
+
raise if errors.size >= max_tries
|
19
|
+
|
20
|
+
## ReadTimeout, a subclass of Timeout::Error, is raised if a chunk of the response cannot be read within the read_timeout.
|
21
|
+
## subclass of RuntimeError
|
22
|
+
## subclass of StandardError
|
23
|
+
## subclass of Exception
|
24
|
+
puts "!! ERROR - #{e}:"
|
25
|
+
pp e
|
26
|
+
|
27
|
+
errors << e
|
28
|
+
|
29
|
+
puts
|
30
|
+
puts "==> retrying (count=#{errors.size}, max_tries=#{max_tries}) in #{delay} sec(s)..."
|
31
|
+
sleep( delay )
|
32
|
+
retry
|
33
|
+
end
|
34
|
+
|
35
|
+
if errors.size > 0
|
36
|
+
puts " #{errors.size} retry attempt(s) on error(s):"
|
37
|
+
pp errors
|
38
|
+
end
|
39
|
+
|
40
|
+
errors
|
41
|
+
end
|