ordinals 1.0.0 → 1.0.1
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 +1 -1
- data/Manifest.txt +0 -4
- data/README.md +7 -134
- data/Rakefile +3 -4
- data/lib/ordinals.rb +1 -12
- metadata +8 -27
- data/bin/ordbase +0 -17
- data/lib/ordinals/collection.rb +0 -256
- data/lib/ordinals/stats.rb +0 -142
- data/lib/ordinals/tool.rb +0 -121
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 99bcfe173a347fb795174d2fc8a38ed2e8bde67089ae0340edda7c146592107c
|
|
4
|
+
data.tar.gz: e916e620469af7171250c630e09fbeb8c223eb9e197643e109127d07eed27519
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d15fc49964cfe2473a23ce61f36bed070d31e722afcb2110dfa33e0452f68ec6653a668b986c17924f0ce7b9ad20d9e8c63f594d4622dc2feb72641352b25f3e
|
|
7
|
+
data.tar.gz: 421f3eec03fd8cddbd290edae6eaec5a3d37b1448ce3736242fb58a28f0802c6fea6eea0d2ab49b635957aee103ebb5d9bc010830d947ac849f77a2e1ddf0ab4
|
data/CHANGELOG.md
CHANGED
data/Manifest.txt
CHANGED
data/README.md
CHANGED
|
@@ -1,156 +1,28 @@
|
|
|
1
1
|
# ordinals
|
|
2
2
|
|
|
3
|
-
ordinals gem -
|
|
3
|
+
ordinals gem - ordinals (inscription) api wrapper & helpers for Bitcoin, Litcoin, Dogecoin & co.
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
* home :: [github.com/pixelartexchange/
|
|
7
|
-
* bugs :: [github.com/pixelartexchange/
|
|
6
|
+
* home :: [github.com/pixelartexchange/artbase](https://github.com/pixelartexchange/artbase)
|
|
7
|
+
* bugs :: [github.com/pixelartexchange/artbase/issues](https://github.com/pixelartexchange/artbase/issues)
|
|
8
8
|
* gem :: [rubygems.org/gems/ordinals](https://rubygems.org/gems/ordinals)
|
|
9
9
|
* rdoc :: [rubydoc.info/gems/ordinals](http://rubydoc.info/gems/ordinals)
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
## Usage
|
|
12
13
|
|
|
13
|
-
## Command-Line Usage
|
|
14
14
|
|
|
15
|
-
Let's use the 100 Ordinal Punks collection to try out the
|
|
16
|
-
`ordbase` command-line tool shipping with the ordinals package.
|
|
17
15
|
|
|
18
|
-
Tip: New to Ordinal Punks? For some background see [**Awesome 100 Ordinal Punks (Anno 2023) Notes - 24×24 Pixel Art on the (Bitcoin) Blockchain »**](https://github.com/cryptopunksnotdead/cryptopunks/tree/master/awesome-ordinalpunks)
|
|
19
16
|
|
|
20
17
|
|
|
21
|
-
### Step 0: Prepare A Tabular Dataset (List) Of All Ordinals w/ ID
|
|
22
18
|
|
|
23
|
-
For now a manual step - prepare a list of all ordinals with id in the comma-separated values (.csv) tabular dataset format.
|
|
24
|
-
Example - [ordinalpunks/ordinals.csv](https://github.com/pixelartexchange/ordinals.sandbox/blob/master/ordinalpunks/ordinals.csv):
|
|
25
19
|
|
|
26
|
-
``` csv
|
|
27
|
-
num, id
|
|
28
|
-
1, 96d87d7e59d75ebc0e6144b09fdd96355fcdaa86fd098d64c46f19a424012bbei0
|
|
29
|
-
2, acda637db995df796b35035fd978cc1a947f1e6fd5215968da88b7e38a7e4b37i0
|
|
30
|
-
3, 0406654dffdd01a49794bd8531bf33721986cc7c6546f871962adee921a39a9di0
|
|
31
|
-
4, 2fe9bb034f60db694701acb23a76c3d7d5aba4328dbd315764f6ee406ba41786i0
|
|
32
|
-
5, dcfa240f2681d1e4a8948120a3a64567262e3c78d5497cb4e97351bfa836b638i0
|
|
33
|
-
6, 16df62c86321895df2b93236d103c935015ed77e189485be649ce2c7e6ac8a4ei0
|
|
34
|
-
7, 81e8d9159b8e9a27c692a5bb3ba18ca037757e94e975b53e175eaaeb2c52f15ai0
|
|
35
|
-
8, c2e15fe87c4b1fd61de65f2804858e6d1152b6316bcb9c2b39b69c9c21638f5di0
|
|
36
|
-
9, 3ed569f3a92ade9f1b47031eb2db2045e7dee3e00787954a88c67ed2ad9854bbi0
|
|
37
|
-
...
|
|
38
|
-
```
|
|
39
20
|
|
|
40
|
-
|
|
41
|
-
### Step 1: Download All Pixel Art Images Via Ordinals.com
|
|
42
|
-
|
|
43
|
-
Use
|
|
44
|
-
|
|
45
|
-
```
|
|
46
|
-
$ ordbase ordinalpunks image # or
|
|
47
|
-
$ ordbase ordinalpunks img
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
to download all images via the ordinals.com (web) service.
|
|
51
|
-
All images get stored in the (temporary) `token-i/` directory.
|
|
52
|
-
Resulting in:
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
/ordinalpunks
|
|
56
|
-
ordinals.csv
|
|
57
|
-
/token-i
|
|
58
|
-
1.png
|
|
59
|
-
2.png
|
|
60
|
-
3.png
|
|
61
|
-
...
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-

|
|
65
|
-

|
|
66
|
-

|
|
67
|
-

|
|
68
|
-

|
|
69
|
-

|
|
70
|
-
...
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
### Step 2: Downsample ("Pixelate") All Pixel Art Images
|
|
76
|
-
|
|
77
|
-
Note: Most pixel art collections upload / inscribe images with a zoom.
|
|
78
|
-
The ordinal punks, for example, use a 8x zoom factor for the 24×24px originals, thus,
|
|
79
|
-
resulting in 192×192px.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
Add a ["artbase-compatible"](https://github.com/pixelartexchange/artbase) collection configuration file to lists the source format(s)
|
|
83
|
-
and the minimal true pixel format.
|
|
84
|
-
Example - [ordinalpunks/collection.yml](https://github.com/pixelartexchange/ordinals.sandbox/blob/master/ordinalpunks/collection.yml):
|
|
85
|
-
|
|
86
|
-
``` yaml
|
|
87
|
-
slug: ordinalpunks
|
|
88
|
-
count: 100
|
|
89
|
-
format: 24x24
|
|
90
|
-
source: 192x192
|
|
91
|
-
offset: 1
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
Use
|
|
95
|
-
|
|
96
|
-
```
|
|
97
|
-
$ ordbase ordinalpunks pixelate # or
|
|
98
|
-
$ ordbase ordinalpunks px
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
to downsample ("pixelate") all images
|
|
102
|
-
in the (temporary) `token-i/` directory.
|
|
103
|
-
Resulting in a `24x24`/ directory with all images
|
|
104
|
-
in the "minimal" `24x24` format:
|
|
105
|
-
|
|
106
|
-
```
|
|
107
|
-
/ordinalpunks
|
|
108
|
-
ordinals.csv
|
|
109
|
-
collections.yml
|
|
110
|
-
/24x24
|
|
111
|
-
1.png
|
|
112
|
-
2.png
|
|
113
|
-
3.png
|
|
114
|
-
...
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-

|
|
118
|
-

|
|
119
|
-

|
|
120
|
-

|
|
121
|
-

|
|
122
|
-

|
|
123
|
-
...
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
### Bonus: Step 3: Make An All-In-One Collect'Em All Composite Image
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
Use
|
|
131
|
-
|
|
132
|
-
```
|
|
133
|
-
$ ordbase ordinalpunks composite # or
|
|
134
|
-
$ ordbase ordinalpunks comp
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
to make an all-in-one image composite for the complete collection.
|
|
138
|
-
Resulting in `/tmp/ordinalpunks.png` (~11kb).
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-

|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
That's it for now.
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
## Bonus: More Ordinal Pixel Art Collections
|
|
21
|
+
## Bonus: Ordinal Pixel Art Collections
|
|
150
22
|
|
|
151
23
|
|
|
152
24
|
See the [**Ordinals (Pixel Art) Sandbox (& Cache)**](https://github.com/pixelartexchange/ordinals.sandbox)
|
|
153
|
-
for
|
|
25
|
+
for collections incl. Ordinal Punks & Phunks (24×24), Bitcoin Punks (24×24), Ordinal Mini Doges (24×24), Ordinal Doggies (32×32),
|
|
154
26
|
Extra Ordinal Women (32×32), Ordinal Penguins (35×35),
|
|
155
27
|
Ordinal Birds (42×42), Bitcoin Bears (48×48) and much more.
|
|
156
28
|
|
|
@@ -158,6 +30,7 @@ Add your sandbox or "right-clicker" ordinal backup / archive / gallery here. Yes
|
|
|
158
30
|
|
|
159
31
|
|
|
160
32
|
|
|
33
|
+
|
|
161
34
|
## License
|
|
162
35
|
|
|
163
36
|
The scripts are dedicated to the public domain.
|
data/Rakefile
CHANGED
|
@@ -10,12 +10,12 @@ end
|
|
|
10
10
|
|
|
11
11
|
Hoe.spec 'ordinals' do
|
|
12
12
|
|
|
13
|
-
self.version = '1.0.
|
|
13
|
+
self.version = '1.0.1'
|
|
14
14
|
|
|
15
|
-
self.summary = 'ordinals gem -
|
|
15
|
+
self.summary = 'ordinals gem - ordinals (inscription) api wrapper & helpers for Bitcoin, Litecoin, Dogecoin & co.'
|
|
16
16
|
self.description = summary
|
|
17
17
|
|
|
18
|
-
self.urls = { home: 'https://github.com/pixelartexchange/
|
|
18
|
+
self.urls = { home: 'https://github.com/pixelartexchange/artbase' }
|
|
19
19
|
|
|
20
20
|
self.author = 'Gerald Bauer'
|
|
21
21
|
self.email = 'wwwmake@googlegroups.com'
|
|
@@ -26,7 +26,6 @@ Hoe.spec 'ordinals' do
|
|
|
26
26
|
|
|
27
27
|
self.extra_deps = [
|
|
28
28
|
['cocos'],
|
|
29
|
-
['pixelart'],
|
|
30
29
|
['nokogiri'], ## required / used by api support (html parsing)
|
|
31
30
|
]
|
|
32
31
|
|
data/lib/ordinals.rb
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
|
|
2
1
|
require 'cocos'
|
|
3
|
-
require 'pixelart'
|
|
4
|
-
|
|
5
|
-
require 'optparse'
|
|
6
|
-
|
|
7
2
|
|
|
8
|
-
## add nokogiri for api (html parsing)
|
|
3
|
+
## note: add nokogiri for api (html parsing)
|
|
9
4
|
require 'nokogiri'
|
|
10
5
|
|
|
11
6
|
|
|
12
7
|
|
|
13
8
|
|
|
14
|
-
|
|
15
9
|
module Ordinals
|
|
16
10
|
class Configuration
|
|
17
11
|
|
|
@@ -83,10 +77,5 @@ end # module Ordinals
|
|
|
83
77
|
|
|
84
78
|
## our own code
|
|
85
79
|
require_relative 'ordinals/api'
|
|
86
|
-
require_relative 'ordinals/collection'
|
|
87
|
-
require_relative 'ordinals/stats'
|
|
88
|
-
|
|
89
|
-
require_relative 'ordinals/tool'
|
|
90
|
-
|
|
91
80
|
|
|
92
81
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ordinals
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gerald Bauer
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-03-
|
|
11
|
+
date: 2023-03-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: cocos
|
|
@@ -24,20 +24,6 @@ dependencies:
|
|
|
24
24
|
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '0'
|
|
27
|
-
- !ruby/object:Gem::Dependency
|
|
28
|
-
name: pixelart
|
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
|
30
|
-
requirements:
|
|
31
|
-
- - ">="
|
|
32
|
-
- !ruby/object:Gem::Version
|
|
33
|
-
version: '0'
|
|
34
|
-
type: :runtime
|
|
35
|
-
prerelease: false
|
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
-
requirements:
|
|
38
|
-
- - ">="
|
|
39
|
-
- !ruby/object:Gem::Version
|
|
40
|
-
version: '0'
|
|
41
27
|
- !ruby/object:Gem::Dependency
|
|
42
28
|
name: nokogiri
|
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -86,11 +72,10 @@ dependencies:
|
|
|
86
72
|
- - "~>"
|
|
87
73
|
- !ruby/object:Gem::Version
|
|
88
74
|
version: '3.23'
|
|
89
|
-
description: ordinals gem -
|
|
90
|
-
|
|
75
|
+
description: ordinals gem - ordinals (inscription) api wrapper & helpers for Bitcoin,
|
|
76
|
+
Litecoin, Dogecoin & co.
|
|
91
77
|
email: wwwmake@googlegroups.com
|
|
92
|
-
executables:
|
|
93
|
-
- ordbase
|
|
78
|
+
executables: []
|
|
94
79
|
extensions: []
|
|
95
80
|
extra_rdoc_files:
|
|
96
81
|
- CHANGELOG.md
|
|
@@ -101,13 +86,9 @@ files:
|
|
|
101
86
|
- Manifest.txt
|
|
102
87
|
- README.md
|
|
103
88
|
- Rakefile
|
|
104
|
-
- bin/ordbase
|
|
105
89
|
- lib/ordinals.rb
|
|
106
90
|
- lib/ordinals/api.rb
|
|
107
|
-
|
|
108
|
-
- lib/ordinals/stats.rb
|
|
109
|
-
- lib/ordinals/tool.rb
|
|
110
|
-
homepage: https://github.com/pixelartexchange/ordinals.sandbox
|
|
91
|
+
homepage: https://github.com/pixelartexchange/artbase
|
|
111
92
|
licenses:
|
|
112
93
|
- Public Domain
|
|
113
94
|
metadata: {}
|
|
@@ -131,6 +112,6 @@ requirements: []
|
|
|
131
112
|
rubygems_version: 3.3.7
|
|
132
113
|
signing_key:
|
|
133
114
|
specification_version: 4
|
|
134
|
-
summary: ordinals gem -
|
|
135
|
-
|
|
115
|
+
summary: ordinals gem - ordinals (inscription) api wrapper & helpers for Bitcoin,
|
|
116
|
+
Litecoin, Dogecoin & co.
|
|
136
117
|
test_files: []
|
data/bin/ordbase
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
###################
|
|
4
|
-
# == DEV TIPS:
|
|
5
|
-
#
|
|
6
|
-
# For local testing run like:
|
|
7
|
-
#
|
|
8
|
-
# ruby -Ilib bin/ordbase
|
|
9
|
-
#
|
|
10
|
-
# Set the executable bit in Linux. Example:
|
|
11
|
-
#
|
|
12
|
-
# % chmod a+x bin/ordbase
|
|
13
|
-
#
|
|
14
|
-
|
|
15
|
-
require 'ordinals'
|
|
16
|
-
|
|
17
|
-
Ordinals::Tool.main
|
data/lib/ordinals/collection.rb
DELETED
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
module Ordinals
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class Collection
|
|
6
|
-
attr_reader :slug,
|
|
7
|
-
:width, :height,
|
|
8
|
-
:sources
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def initialize( slug )
|
|
12
|
-
@slug = slug
|
|
13
|
-
|
|
14
|
-
## read config if present
|
|
15
|
-
config_path = "./#{@slug}/collection.yml"
|
|
16
|
-
if File.exist?( config_path )
|
|
17
|
-
config = read_yaml( config_path )
|
|
18
|
-
pp config
|
|
19
|
-
|
|
20
|
-
@width, @height = _parse_dimension( config['format'] )
|
|
21
|
-
|
|
22
|
-
## note: allow multiple source formats / dimensions
|
|
23
|
-
### e.g. convert 512x512 into [ [512,512] ]
|
|
24
|
-
##
|
|
25
|
-
source = config['source']
|
|
26
|
-
source = [source] unless source.is_a?( Array )
|
|
27
|
-
@sources = source.map { |dimension| _parse_dimension( dimension ) }
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def ordinals
|
|
33
|
-
@ordinals ||= begin
|
|
34
|
-
recs = read_csv( "./#{@slug}/ordinals.csv" )
|
|
35
|
-
puts " #{recs.size} record(s)"
|
|
36
|
-
recs
|
|
37
|
-
end
|
|
38
|
-
@ordinals
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def count() ordinals.size; end
|
|
42
|
-
alias_method :size, :count
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def each_ordinal( &block )
|
|
47
|
-
ordinals.each_with_index do |rec, i| ## pass along hash rec for now - why? why not?
|
|
48
|
-
block.call( rec, i )
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
## add each_source_image or each_token_image or each_original_image or such - why? why not??
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def each_image( &block )
|
|
57
|
-
each_ordinal do |rec, i|
|
|
58
|
-
id = rec['id']
|
|
59
|
-
num = rec.has_key?('num') ? rec['num'].to_i(10) : i+1
|
|
60
|
-
|
|
61
|
-
path = "./#{@slug}/#{@width}x#{@height}/#{num}.png"
|
|
62
|
-
img = Image.read( path )
|
|
63
|
-
|
|
64
|
-
block.call( img, num )
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def image_dir() "./#{@slug}/token-i"; end
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
## e.g. convert dimension (width x height) "24x24" or "24 x 24" to [24,24]
|
|
75
|
-
def _parse_dimension( str )
|
|
76
|
-
str.split( /x/i ).map { |str| str.strip.to_i }
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def pixelate
|
|
81
|
-
each_ordinal do |rec, i|
|
|
82
|
-
id = rec['id']
|
|
83
|
-
num = rec.has_key?('num') ? rec['num'].to_i(10) : i+1
|
|
84
|
-
|
|
85
|
-
outpath = "./#{@slug}/#{@width}x#{@height}/#{num}.png"
|
|
86
|
-
next if File.exist?( outpath )
|
|
87
|
-
|
|
88
|
-
path = "#{image_dir}/#{num}.png"
|
|
89
|
-
puts "==> reading #{path}..."
|
|
90
|
-
|
|
91
|
-
img = Image.read( path )
|
|
92
|
-
puts " #{img.width}x#{img.height}"
|
|
93
|
-
|
|
94
|
-
## check for source images
|
|
95
|
-
if !@sources.include?( [img.width, img.height] )
|
|
96
|
-
puts " !! ERROR - unexpected image size; sorry - expected:"
|
|
97
|
-
pp @sources
|
|
98
|
-
exit 1
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
## check for special case source == format!!
|
|
102
|
-
if [img.width,img.height] == [@width,@height]
|
|
103
|
-
puts " note: saving image as is - no downsampling"
|
|
104
|
-
img.save( outpath )
|
|
105
|
-
else
|
|
106
|
-
steps_x = Image.calc_sample_steps( img.width, @width )
|
|
107
|
-
steps_y = Image.calc_sample_steps( img.height, @height )
|
|
108
|
-
|
|
109
|
-
img = img.sample( steps_x, steps_y )
|
|
110
|
-
img.save( outpath )
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
def make_composite
|
|
119
|
-
cols, rows = case count
|
|
120
|
-
when 10 then [5, 2]
|
|
121
|
-
when 12 then [4, 3]
|
|
122
|
-
when 15 then [5, 3]
|
|
123
|
-
when 20 then [5, 4]
|
|
124
|
-
when 50 then [10, 5]
|
|
125
|
-
when 69 then [10, 7]
|
|
126
|
-
when 80 then [10, 8]
|
|
127
|
-
when 88 then [10, 9]
|
|
128
|
-
when 98,99 then [10, 10]
|
|
129
|
-
when 100 then [10, 10]
|
|
130
|
-
when 101 then [11, 10]
|
|
131
|
-
when 111 then [11, 11]
|
|
132
|
-
when 130 then [10, 13]
|
|
133
|
-
when 512 then [20, 26]
|
|
134
|
-
else
|
|
135
|
-
raise ArgumentError, "sorry - unknown composite count #{count} for now"
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
composite = ImageComposite.new( cols, rows,
|
|
139
|
-
width: @width,
|
|
140
|
-
height: @height )
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
each_image do |img, num|
|
|
144
|
-
puts "==> #{num}"
|
|
145
|
-
composite << img
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
composite.save( "./#{@slug}/tmp/#{@slug}.png" )
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
def convert_images
|
|
154
|
-
Image.convert( image_dir, from: 'jpg',
|
|
155
|
-
to: 'png' )
|
|
156
|
-
|
|
157
|
-
Image.convert( image_dir, from: 'gif',
|
|
158
|
-
to: 'png' )
|
|
159
|
-
|
|
160
|
-
Image.convert( image_dir, from: 'webp',
|
|
161
|
-
to: 'png' )
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
def fix_images ## todo - find a different names for resaving png images?
|
|
167
|
-
## "repair" png images
|
|
168
|
-
## starting w/
|
|
169
|
-
## - why?
|
|
170
|
-
##
|
|
171
|
-
## verify_signature! - ChunkyPNG::SignatureMismatch:
|
|
172
|
-
## PNG signature not found,
|
|
173
|
-
## found "RIFF\\xFE\\b\\x00\\x00"
|
|
174
|
-
## instead of "\\x89PNG\\r\\n\\x1A\\n"
|
|
175
|
-
|
|
176
|
-
Image.convert( image_dir, from: 'png',
|
|
177
|
-
to: 'png' )
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
def download_meta ## inscription metadata
|
|
182
|
-
each_ordinal do |rec, i|
|
|
183
|
-
id = rec['id']
|
|
184
|
-
num = rec.has_key?('num') ? rec['num'].to_i(10) : i+1
|
|
185
|
-
|
|
186
|
-
chain = Ordinals.config.chain
|
|
187
|
-
path = "../ordinals.cache/#{chain}/#{id}.json"
|
|
188
|
-
next if File.exist?( path )
|
|
189
|
-
|
|
190
|
-
puts "==> downloading #{chain} inscription meta #{num} w/ id #{id}..."
|
|
191
|
-
|
|
192
|
-
data = Ordinals.client.inscription( id )
|
|
193
|
-
|
|
194
|
-
write_json( path, data )
|
|
195
|
-
|
|
196
|
-
sleep( 1.0 ) ## sleep (delay_in_s)
|
|
197
|
-
end
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
def dump_stats
|
|
201
|
-
stats = InscriptionStats.new
|
|
202
|
-
|
|
203
|
-
each_ordinal do |rec, i|
|
|
204
|
-
id = rec['id']
|
|
205
|
-
|
|
206
|
-
chain = Ordinals.config.chain
|
|
207
|
-
path = "../ordinals.cache/#{chain}/#{id}.json"
|
|
208
|
-
|
|
209
|
-
data = read_json( path )
|
|
210
|
-
stats.update( data )
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
pp stats.data
|
|
214
|
-
puts
|
|
215
|
-
puts stats.format
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
def download_images
|
|
220
|
-
each_ordinal do |rec, i|
|
|
221
|
-
id = rec['id']
|
|
222
|
-
num = rec.has_key?('num') ? rec['num'].to_i(10) : i+1
|
|
223
|
-
|
|
224
|
-
next if File.exist?( "#{image_dir}/#{num}.png" )
|
|
225
|
-
|
|
226
|
-
puts "==> downloading image ##{num}..."
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
content = Ordinals.client.content( id )
|
|
230
|
-
|
|
231
|
-
puts " content_type: #{content.type}, content_length: #{content.length}"
|
|
232
|
-
|
|
233
|
-
format = if content.type =~ %r{image/jpeg}i
|
|
234
|
-
'jpg'
|
|
235
|
-
elsif content.type =~ %r{image/png}i
|
|
236
|
-
'png'
|
|
237
|
-
elsif content.type =~ %r{image/gif}i
|
|
238
|
-
'gif'
|
|
239
|
-
elsif content.type =~ %r{image/webp}i
|
|
240
|
-
'webp'
|
|
241
|
-
else
|
|
242
|
-
puts "!! ERROR:"
|
|
243
|
-
puts " unknown image format content type: >#{content.type}<"
|
|
244
|
-
exit 1
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
## save image - using b(inary) mode
|
|
248
|
-
write_blob( "#{image_dir}/#{num}.#{format}", content.blob )
|
|
249
|
-
|
|
250
|
-
sleep( 1.0 ) ## sleep (delay_in_s)
|
|
251
|
-
end
|
|
252
|
-
end
|
|
253
|
-
|
|
254
|
-
end # class Collection
|
|
255
|
-
end # module Ordinals
|
|
256
|
-
|
data/lib/ordinals/stats.rb
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
class InscriptionStats
|
|
4
|
-
|
|
5
|
-
TITLE_RX = /^Inscription[ ]+(?<ord>[0-9]+)$/
|
|
6
|
-
BYTES_RX = /^(?<bytes>[0-9]+)[ ]+bytes$/
|
|
7
|
-
|
|
8
|
-
def initialize
|
|
9
|
-
@stats = {
|
|
10
|
-
count: 0,
|
|
11
|
-
ord: { '<1000' => 0,
|
|
12
|
-
'<10000' => 0,
|
|
13
|
-
'<100000' => 0,
|
|
14
|
-
'<1000000' => 0,
|
|
15
|
-
'min' => nil,
|
|
16
|
-
'max' => nil, },
|
|
17
|
-
type: Hash.new(0),
|
|
18
|
-
bytes: { '<100' => 0,
|
|
19
|
-
'<1000' => 0,
|
|
20
|
-
'<10000' => 0,
|
|
21
|
-
'<100000' => 0,
|
|
22
|
-
'<1000000' => 0,
|
|
23
|
-
'min' => nil,
|
|
24
|
-
'max' => nil, },
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
@days = Hash.new(0)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def size() @stats[:count]; end
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def update( data )
|
|
35
|
-
data = JSON.parse( data) if data.is_a?( String )
|
|
36
|
-
|
|
37
|
-
@stats[ :count ] += 1
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
ord = nil
|
|
41
|
-
if m=TITLE_RX.match( data['title'] )
|
|
42
|
-
ord = m[:ord].to_i(10)
|
|
43
|
-
else
|
|
44
|
-
puts "!! ERROR - cannot find ord in inscription title; sorry"
|
|
45
|
-
pp data
|
|
46
|
-
exit 1
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
if ord < 1000 then @stats[:ord]['<1000'] += 1
|
|
50
|
-
elsif ord < 10000 then @stats[:ord]['<10000'] += 1
|
|
51
|
-
elsif ord < 100000 then @stats[:ord]['<100000'] += 1
|
|
52
|
-
elsif ord < 1000000 then @stats[:ord]['<1000000'] += 1
|
|
53
|
-
else
|
|
54
|
-
puts "!! ERROR ord out-of-bounds"
|
|
55
|
-
exit 1
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
## update min/max
|
|
59
|
-
@stats[:ord]['min'] = ord if ord < (@stats[:ord]['min'] || 9999999)
|
|
60
|
-
@stats[:ord]['max'] = ord if ord > (@stats[:ord]['max'] || -1)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
bytes = nil
|
|
64
|
-
if m=BYTES_RX.match( data['content length'] )
|
|
65
|
-
bytes = m[:bytes].to_i(10)
|
|
66
|
-
else
|
|
67
|
-
puts "!! ERROR - cannot find bytes in inscription content length; sorry"
|
|
68
|
-
pp data
|
|
69
|
-
exit 1
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
if bytes < 100 then @stats[:bytes]['<100'] += 1
|
|
73
|
-
elsif bytes < 1000 then @stats[:bytes]['<1000'] += 1
|
|
74
|
-
elsif bytes < 10000 then @stats[:bytes]['<10000'] += 1
|
|
75
|
-
elsif bytes < 100000 then @stats[:bytes]['<100000'] += 1
|
|
76
|
-
elsif bytes < 1000000 then @stats[:bytes]['<1000000'] += 1
|
|
77
|
-
else
|
|
78
|
-
puts "!! ERROR bytes (content-length) out-of-bounds"
|
|
79
|
-
exit 1
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
## update min/max
|
|
83
|
-
@stats[:bytes]['min'] = bytes if bytes < (@stats[:bytes]['min'] || 9999999)
|
|
84
|
-
@stats[:bytes]['max'] = bytes if bytes > (@stats[:bytes]['max'] || -1)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
type = data['content type']
|
|
88
|
-
|
|
89
|
-
@stats[:type][ type ] += 1
|
|
90
|
-
|
|
91
|
-
## "timestamp"=>"2023-02-05 01:45:22 UTC",
|
|
92
|
-
ts = Time.strptime( data['timestamp'], '%Y-%m-%d %H:%M:%S' )
|
|
93
|
-
|
|
94
|
-
@days[ ts.strftime('%Y-%m-%d') ] +=1
|
|
95
|
-
end # method update
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
def data ## rename to model or such - why? why not?
|
|
99
|
-
## sort days
|
|
100
|
-
days = @days.sort {|l,r| l[0] <=> r[0] }
|
|
101
|
-
## add to stats
|
|
102
|
-
@stats[:days] = {}
|
|
103
|
-
days.each {|k,v| @stats[:days][k] = v }
|
|
104
|
-
@stats
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
=begin
|
|
108
|
-
{:count=>101,
|
|
109
|
-
:ord=>{"<1000"=>0, "<10000"=>0, "<100000"=>101, "<1000000"=>0, "min"=>14343, "max"=>42901},
|
|
110
|
-
:type=>{"image/png"=>101},
|
|
111
|
-
:bytes=>{"<100"=>0, "<1000"=>101, "<10000"=>0, "<100000"=>0, "<1000000"=>0, "min"=>274, "max"=>512},
|
|
112
|
-
:days=>{"2023-02-22"=>10, "2023-02-25"=>17, "2023-02-26"=>74}}
|
|
113
|
-
=end
|
|
114
|
-
|
|
115
|
-
def format ## rename to pretty_print or such - why? why not?
|
|
116
|
-
stat = data
|
|
117
|
-
|
|
118
|
-
buf = String.new('')
|
|
119
|
-
buf << "#{stat[:count]} inscription(s)\n"
|
|
120
|
-
|
|
121
|
-
buf << "- from ##{stat[:ord]['min']} to ##{stat[:ord]['max']} (min. to max.)\n"
|
|
122
|
-
buf << " - <1000 => #{stat[:ord]['<1000']}\n" if stat[:ord]["<1000"] > 0
|
|
123
|
-
buf << " - <10000 => #{stat[:ord]['<10000']}\n" if stat[:ord]["<10000"] > 0
|
|
124
|
-
buf << " - <100000 => #{stat[:ord]['<100000']}\n" if stat[:ord]["<100000"] > 0
|
|
125
|
-
buf << " - <1000000 => #{stat[:ord]['<1000000']}\n" if stat[:ord]["<1000000"] > 0
|
|
126
|
-
|
|
127
|
-
buf << "- format(s)\n"
|
|
128
|
-
stat[:type].each do |k,v|
|
|
129
|
-
buf << " - #{k} => #{v}\n"
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
buf << "- day(s)\n"
|
|
133
|
-
stat[:days].each do |k,v|
|
|
134
|
-
buf << " - #{k} => #{v}\n"
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
buf
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
end ## class InscriptionStats
|
|
141
|
-
|
|
142
|
-
|
data/lib/ordinals/tool.rb
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
module Ordinals
|
|
2
|
-
class Tool
|
|
3
|
-
|
|
4
|
-
def self.main( args=ARGV )
|
|
5
|
-
puts "==> welcome to ordinals/ordbase tool with args:"
|
|
6
|
-
pp args
|
|
7
|
-
|
|
8
|
-
options = {
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
parser = OptionParser.new do |opts|
|
|
12
|
-
opts.on( "--doge", "--dogecoin", "Use Dogecoin / DOGE") do
|
|
13
|
-
## switch to doge
|
|
14
|
-
Ordinals.config.chain = :doge
|
|
15
|
-
end
|
|
16
|
-
opts.on( "--ltc", "--litecoin", "Use Litecoin / LTC") do
|
|
17
|
-
## switch to ltc
|
|
18
|
-
Ordinals.config.chain = :ltc
|
|
19
|
-
end
|
|
20
|
-
opts.on( "--btc", "--bitcoin", "Use Bitcoin / BTC") do
|
|
21
|
-
## switch to btc (default)
|
|
22
|
-
Ordinals.config.chain = :btc
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
opts.on("-h", "--help", "Prints this help") do
|
|
26
|
-
puts opts
|
|
27
|
-
exit
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
parser.parse!( args )
|
|
32
|
-
puts "options:"
|
|
33
|
-
pp options
|
|
34
|
-
|
|
35
|
-
puts "args:"
|
|
36
|
-
pp args
|
|
37
|
-
|
|
38
|
-
if args.size < 1
|
|
39
|
-
puts "!! ERROR - no collection found - use <collection> <command>..."
|
|
40
|
-
puts ""
|
|
41
|
-
exit
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
slug = args[0]
|
|
45
|
-
command = args[1] || 'image'
|
|
46
|
-
|
|
47
|
-
if ['m', 'meta'].include?( command )
|
|
48
|
-
do_download_meta( slug )
|
|
49
|
-
elsif ['stat', 'stats'].include?( command )
|
|
50
|
-
do_dump_stats( slug )
|
|
51
|
-
elsif ['i','img', 'image'].include?( command )
|
|
52
|
-
do_download_images( slug )
|
|
53
|
-
elsif ['conv','convert'].include?( command )
|
|
54
|
-
do_convert_images( slug )
|
|
55
|
-
elsif ['fix'].include?( command )
|
|
56
|
-
do_fix_images( slug )
|
|
57
|
-
elsif ['px','pix', 'pixelate' ].include?( command )
|
|
58
|
-
do_pixelate( slug )
|
|
59
|
-
elsif ['comp','composite' ].include?( command )
|
|
60
|
-
do_make_composite( slug )
|
|
61
|
-
else
|
|
62
|
-
puts "!! ERROR - unknown command >#{command}<, sorry"
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
puts "bye"
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
def self.do_dump_stats( slug )
|
|
70
|
-
puts "==> dump inscription stats for collection >#{slug}<..."
|
|
71
|
-
|
|
72
|
-
col = Collection.new( slug )
|
|
73
|
-
col.dump_stats
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def self.do_download_meta( slug )
|
|
77
|
-
puts "==> download meta for collection >#{slug}<..."
|
|
78
|
-
|
|
79
|
-
col = Collection.new( slug )
|
|
80
|
-
col.download_meta
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def self.do_download_images( slug )
|
|
84
|
-
puts "==> download images for collection >#{slug}<..."
|
|
85
|
-
|
|
86
|
-
col = Collection.new( slug )
|
|
87
|
-
col.download_images
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def self.do_convert_images( slug )
|
|
92
|
-
puts "==> convert images for collection >#{slug}<..."
|
|
93
|
-
|
|
94
|
-
col = Collection.new( slug )
|
|
95
|
-
col.convert_images
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def self.do_fix_images( slug )
|
|
99
|
-
puts "==> fix images for collection >#{slug}<..."
|
|
100
|
-
|
|
101
|
-
col = Collection.new( slug )
|
|
102
|
-
col.fix_images
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
def self.do_pixelate( slug )
|
|
107
|
-
puts "==> downsample / pixelate images for collection >#{slug}<..."
|
|
108
|
-
|
|
109
|
-
col = Collection.new( slug )
|
|
110
|
-
col.pixelate
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def self.do_make_composite( slug )
|
|
114
|
-
puts "==> make composite for collection >#{slug}<..."
|
|
115
|
-
|
|
116
|
-
col = Collection.new( slug )
|
|
117
|
-
col.make_composite
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
end # class Tool
|
|
121
|
-
end # module Ordinals
|