ordlite 0.2.0 → 0.2.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 +1 -0
- data/README.md +108 -44
- data/Rakefile +1 -0
- data/lib/ordlite/base.rb +8 -0
- data/lib/ordlite/factory.rb +132 -0
- data/lib/ordlite/importer.rb +172 -53
- data/lib/ordlite/models/collection.rb +5 -1
- data/lib/ordlite/models/factory.rb +6 -1
- data/lib/ordlite/models/inscribe.rb +17 -5
- data/lib/ordlite/version.rb +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6f1f6f768a785a0badc768db45c1c8ca831958f983b673fe48990846f3d4260e
|
4
|
+
data.tar.gz: 234d31cabdc7ed109144487792da9f77c39821f935e3d7d91a151b91e817d511
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 403e1addf0b974af179de293a26c5f1f47da8d0f665da1ca1a44a89cbcfb025a642a04930f49f6df35681527b2cbcaae855f87de4b7ce09e6cd88b4cffab1472
|
7
|
+
data.tar.gz: ab359d39d1dcdf307e8b3239ed61e2f10f8fc6bfc4316c3f9f5554a9fbc2d88b0d1c24f120afcab9b035c675d82d22e0292c6d1202db7219d64f5e8f2c214b54
|
data/CHANGELOG.md
CHANGED
data/Manifest.txt
CHANGED
data/README.md
CHANGED
@@ -13,7 +13,7 @@ ordlite - ordinals inscription (on bitcoin & co) database let's you query via sq
|
|
13
13
|
|
14
14
|
## SQL Database Model
|
15
15
|
|
16
|
-
Inscribes •
|
16
|
+
Inscribes • Blobs • Collections • Factories • Generatives
|
17
17
|
|
18
18
|
|
19
19
|
Table Inscribes
|
@@ -63,6 +63,7 @@ puts
|
|
63
63
|
puts " #{Inscribe.count} inscribe(s)"
|
64
64
|
puts " #{Blob.count} blob(s)"
|
65
65
|
puts " #{Collection.count} collection(s)"
|
66
|
+
puts " #{Factory.count} factories"
|
66
67
|
puts " #{Generative.count} generative(s)"
|
67
68
|
|
68
69
|
#=> 0 inscribe(s)
|
@@ -74,68 +75,134 @@ puts " #{Generative.count} generative(s)"
|
|
74
75
|
|
75
76
|
|
76
77
|
|
77
|
-
### Example No 1 -
|
78
|
+
### Example No 1 - Auto-Add (Via Ordinals.com) First Thousand Inscriptions (Sub 1k)
|
78
79
|
|
79
80
|
``` ruby
|
80
81
|
require 'ordlite'
|
81
82
|
|
82
83
|
|
83
|
-
OrdDb.
|
84
|
-
database: './ord.db' )
|
84
|
+
OrdDb.open( './ord.db' )
|
85
85
|
|
86
86
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
87
|
+
1000.times do |num| # auto-add inscription 0-999
|
88
|
+
OrdDb.import( num )
|
89
|
+
end
|
90
|
+
|
91
|
+
puts
|
92
|
+
puts " #{Inscribe.count} inscribe(s)"
|
93
|
+
puts " #{Blob.count} blob(s)"
|
94
|
+
#=> 1000 inscribe(s)
|
95
|
+
#=> 1000 blob(s)
|
96
|
+
```
|
95
97
|
|
96
|
-
|
97
|
-
|
98
|
+
Let's query for the ten biggest (by bytes) inscriptions
|
99
|
+
(and pretty print the result):
|
98
100
|
|
99
|
-
|
100
|
-
|
101
|
-
|
101
|
+
```ruby
|
102
|
+
Inscribe.biggest.limit(10).each do |rec|
|
103
|
+
print "#{number_to_human_size(rec.bytes)} (#{rec.bytes} bytes) - "
|
104
|
+
print "Inscribe №#{rec.num} (#{rec.content_type}) - "
|
105
|
+
print "#{rec.date} - #{rec.fee} fee in sats"
|
106
|
+
print "\n"
|
102
107
|
end
|
108
|
+
```
|
103
109
|
|
110
|
+
resulting in:
|
104
111
|
|
105
|
-
|
106
|
-
|
112
|
+
```
|
113
|
+
3.73 MB (3915537 bytes) - Inscribe №652 (image/jpeg) - 2023-02-01 20:38:33 - 0 fee in sats
|
114
|
+
385 KB (394718 bytes) - Inscribe №978 (application/epub+zip) - 2023-02-02 06:46:04 - 109325 fee in sats
|
115
|
+
385 KB (394479 bytes) - Inscribe №546 (image/gif) - 2023-02-01 10:41:50 - 1489860 fee in sats
|
116
|
+
385 KB (394440 bytes) - Inscribe №833 (image/png) - 2023-02-02 01:13:51 - 99314 fee in sats
|
117
|
+
381 KB (389858 bytes) - Inscribe №388 (image/jpeg) - 2023-01-31 14:01:38 - 981620 fee in sats
|
118
|
+
379 KB (388417 bytes) - Inscribe №291 (image/gif) - 2023-01-30 17:58:54 - 586794 fee in sats
|
119
|
+
378 KB (386858 bytes) - Inscribe №857 (image/png) - 2023-02-02 01:17:54 - 97407 fee in sats
|
120
|
+
374 KB (383322 bytes) - Inscribe №538 (image/jpeg) - 2023-02-01 10:20:28 - 96519 fee in sats
|
121
|
+
367 KB (375414 bytes) - Inscribe №378 (image/gif) - 2023-01-31 09:47:55 - 945300 fee in sats
|
122
|
+
365 KB (373504 bytes) - Inscribe №288 (image/jpeg) - 2023-01-30 16:51:46 - 94050 fee in sats
|
123
|
+
```
|
107
124
|
|
108
125
|
|
126
|
+
Let's query for all inscriptions grouped by date (day) and dump the results:
|
109
127
|
|
110
|
-
|
111
|
-
##
|
112
|
-
|
113
|
-
## e.g. sql where clause like
|
114
|
-
## content LIKE '%mint%'
|
115
|
-
## AND ( content LIKE '%orc-721%'
|
116
|
-
## OR content LIKE '%og%')
|
128
|
+
```ruby
|
129
|
+
pp Inscribe.counts_by_date ## or count_by_day
|
130
|
+
```
|
117
131
|
|
118
|
-
|
119
|
-
puts " #{mints.size} mint candidate(s)"
|
132
|
+
resulting in:
|
120
133
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
134
|
+
```
|
135
|
+
{"2022-12-14" => 1,
|
136
|
+
"2022-12-17" => 1,
|
137
|
+
"2022-12-19" => 1,
|
138
|
+
"2023-01-05" => 1,
|
139
|
+
"2023-01-10" => 1,
|
140
|
+
"2023-01-12" => 1,
|
141
|
+
"2023-01-13" => 2,
|
142
|
+
"2023-01-15" => 1,
|
143
|
+
"2023-01-16" => 1,
|
144
|
+
"2023-01-19" => 5,
|
145
|
+
"2023-01-20" => 3,
|
146
|
+
"2023-01-21" => 5,
|
147
|
+
"2023-01-22" => 34,
|
148
|
+
"2023-01-23" => 23,
|
149
|
+
"2023-01-24" => 4,
|
150
|
+
"2023-01-25" => 9,
|
151
|
+
"2023-01-26" => 12,
|
152
|
+
"2023-01-27" => 19,
|
153
|
+
"2023-01-28" => 16,
|
154
|
+
"2023-01-29" => 128,
|
155
|
+
"2023-01-30" => 82,
|
156
|
+
"2023-01-31" => 98,
|
157
|
+
"2023-02-01" => 220,
|
158
|
+
"2023-02-02" => 332}
|
159
|
+
```
|
126
160
|
|
161
|
+
Let's query for all inscriptions grouped by month and dump the results:
|
162
|
+
|
163
|
+
```ruby
|
164
|
+
pp Inscribe.counts_by_month
|
165
|
+
```
|
166
|
+
|
167
|
+
resulting in:
|
168
|
+
|
169
|
+
```
|
170
|
+
{"2022-12" => 3,
|
171
|
+
"2023-01" => 445,
|
172
|
+
"2023-02" => 552}
|
173
|
+
```
|
127
174
|
|
128
|
-
phunks_mints = Inscribe.mints_by( slug: 'diyphunks')
|
129
|
-
puts " #{phunks_mints.size} mint candidate(s)"
|
130
175
|
|
176
|
+
Let's query for all content types and group by count (descending) and dump the results:
|
131
177
|
|
132
|
-
puts " #{deploys.size} deploy candidate(s)"
|
133
|
-
puts " #{mints.size} mint candidate(s)"
|
134
178
|
|
135
|
-
|
136
|
-
|
179
|
+
```ruby
|
180
|
+
pp Inscribe.counts_by_content_type
|
137
181
|
```
|
138
182
|
|
183
|
+
resulting in:
|
184
|
+
|
185
|
+
```
|
186
|
+
{"image/png" => 475,
|
187
|
+
"image/jpeg" => 188,
|
188
|
+
"image/webp" => 117,
|
189
|
+
"text/plain;charset=utf-8" => 112,
|
190
|
+
"image/svg+xml" => 62,
|
191
|
+
"text/html;charset=utf-8" => 18,
|
192
|
+
"image/gif" => 11,
|
193
|
+
"audio/mpeg" => 6,
|
194
|
+
"application/pdf" => 2,
|
195
|
+
"image/avif" => 2,
|
196
|
+
"video/webm" => 2,
|
197
|
+
"application/epub+zip" => 1,
|
198
|
+
"application/pgp-signature" => 1,
|
199
|
+
"audio/midi" => 1,
|
200
|
+
"audio/mod" => 1,
|
201
|
+
"video/mp4" => 1}
|
202
|
+
```
|
203
|
+
|
204
|
+
and so on.
|
205
|
+
|
139
206
|
|
140
207
|
|
141
208
|
|
@@ -150,13 +217,10 @@ into an (sql) database e.g. `ord.db`:
|
|
150
217
|
``` ruby
|
151
218
|
require 'ordlite'
|
152
219
|
|
153
|
-
OrdDb.
|
154
|
-
database: './ord.db' )
|
155
|
-
|
156
|
-
OrdDb.create_all # build table schema
|
220
|
+
OrdDb.open( './ord.db' )
|
157
221
|
|
158
222
|
cache_dir = './ordinals.cache/inscription'
|
159
|
-
cache =
|
223
|
+
cache = Ordinals::Cache.new( cache_dir )
|
160
224
|
cache.import_all
|
161
225
|
|
162
226
|
|
data/Rakefile
CHANGED
data/lib/ordlite/base.rb
CHANGED
@@ -134,5 +134,13 @@ module OrdDb
|
|
134
134
|
end # module OrdDb
|
135
135
|
|
136
136
|
|
137
|
+
|
138
|
+
####
|
139
|
+
# add factory (ordgen/orc-721) support here for now - why? why not?
|
140
|
+
require 'pixelart'
|
141
|
+
require_relative 'factory'
|
142
|
+
|
143
|
+
|
144
|
+
|
137
145
|
# say hello
|
138
146
|
puts Ordlite.banner ## if defined?($RUBYCOCOS_DEBUG) && $RUBCOCOS_DEBUG
|
@@ -0,0 +1,132 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
class FactorySpritesheet ## check - rename to catalog or atlas NOT spritesheet - why? why not?
|
4
|
+
def self.read_inscribes( *inscribes, width:,
|
5
|
+
height: )
|
6
|
+
## map inscribes to images
|
7
|
+
images = inscribes.map {|inscribe| Pixelart::Image.blob( inscribe.content ) }
|
8
|
+
## puts " #{images.size} image(s)"
|
9
|
+
|
10
|
+
new( *images, width: width,
|
11
|
+
height: height)
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize( *images, width:,
|
15
|
+
height: )
|
16
|
+
@tile_width = width
|
17
|
+
@tile_height = height
|
18
|
+
@tiles = []
|
19
|
+
images.each {|img| add(img) }
|
20
|
+
end
|
21
|
+
|
22
|
+
def count() @tiles.size; end
|
23
|
+
alias_method :size, :count
|
24
|
+
alias_method :tile_count, :count ## add tile_count - why? why not?
|
25
|
+
def tile_width() @tile_width; end ## use width - why? why not?
|
26
|
+
def tile_height() @tile_height; end ## use height - why? why not?
|
27
|
+
|
28
|
+
def tile( index ) @tiles[ index ]; end
|
29
|
+
alias_method :[], :tile
|
30
|
+
|
31
|
+
def add_inscribe( inscribe ) _add( Pixelart::Image.blob( inscribe.content )); end
|
32
|
+
def add( img )
|
33
|
+
## 1:1 tile; use as is
|
34
|
+
if img.width == @tile_width && img.height == @tile_height
|
35
|
+
@tiles << img
|
36
|
+
else ## assume spritesheet??
|
37
|
+
## wrap into composite image
|
38
|
+
composite = Pixelart::ImageComposite.new( img.image, width: @tile_width,
|
39
|
+
height: @tile_height )
|
40
|
+
cols = img.width / composite.tile_width
|
41
|
+
rows = img.height / composite.tile_height
|
42
|
+
puts " #{composite.count} tile(s) in #{cols}x#{rows} grid"
|
43
|
+
composite.each {|tile| @tiles << tile }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
alias_method :<<, :add
|
47
|
+
end ## class Spritesheet
|
48
|
+
|
49
|
+
|
50
|
+
class FactoryGenerator
|
51
|
+
###################
|
52
|
+
## convenience setup helper(s)
|
53
|
+
def self.read_inscribes( *inscribes, width:,
|
54
|
+
height: )
|
55
|
+
new( FactorySpritesheet.read_inscribes( *inscribes,
|
56
|
+
width: width,
|
57
|
+
height: height ))
|
58
|
+
end
|
59
|
+
|
60
|
+
def initialize( spritesheet )
|
61
|
+
@spritesheet = spritesheet
|
62
|
+
end
|
63
|
+
|
64
|
+
def _parse( spec )
|
65
|
+
## for delimiter allow for now: - why? why not?
|
66
|
+
## (multiple) space ( )
|
67
|
+
## command or semicolon
|
68
|
+
spec.strip.split( %r{[ ,;/_-]+} ).map {|v| v.to_i(10) }
|
69
|
+
end
|
70
|
+
|
71
|
+
def parse( spec )
|
72
|
+
## convenience helper
|
73
|
+
## parses g spec in various (delimited) formats
|
74
|
+
g = _parse( spec )
|
75
|
+
generate( *g )
|
76
|
+
end
|
77
|
+
|
78
|
+
def generate( *attributes )
|
79
|
+
img = Pixelart::Image.new( width, height )
|
80
|
+
attributes.each do |num|
|
81
|
+
img.compose!( @spritesheet[ num ] )
|
82
|
+
end
|
83
|
+
img
|
84
|
+
end
|
85
|
+
alias_method :g, :generate
|
86
|
+
|
87
|
+
def width() @spritesheet.tile_width; end
|
88
|
+
def height() @spritesheet.tile_height; end
|
89
|
+
def count() @spritesheet.count; end
|
90
|
+
end # class FactoryGenerator
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
module OrdDb
|
95
|
+
module Model
|
96
|
+
|
97
|
+
class Factory
|
98
|
+
|
99
|
+
## use id/slug to cache generators / spritesheets - why? why not?
|
100
|
+
def self.generators
|
101
|
+
@generators ||= {}
|
102
|
+
end
|
103
|
+
|
104
|
+
def generator
|
105
|
+
generators = self.class.generators
|
106
|
+
if generators.has_key?( id )
|
107
|
+
generators[ id ]
|
108
|
+
else
|
109
|
+
## auto-add generator on first-time/hit/demand
|
110
|
+
width, height = _parse_dimension( dim )
|
111
|
+
inscribes = layers.to_a ## get layer inscribe records
|
112
|
+
generator = FactoryGenerator.read_inscribes( *inscribes,
|
113
|
+
width: width,
|
114
|
+
height: height )
|
115
|
+
generators[ id ] = generator
|
116
|
+
generator
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def generate( *attributes ) ## add g shortcut alias - why? why not?
|
121
|
+
generator.generate( *attributes )
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
## e.g. convert dimension (width x height) "24x24" or "24 x 24" to [24,24]
|
126
|
+
def _parse_dimension( str )
|
127
|
+
str.split( /x/i ).map { |str| str.strip.to_i(10) }
|
128
|
+
end
|
129
|
+
|
130
|
+
end # class Factory
|
131
|
+
end # module Model
|
132
|
+
end # module OrdDb
|
data/lib/ordlite/importer.rb
CHANGED
@@ -1,8 +1,82 @@
|
|
1
|
+
module OrdDb
|
1
2
|
|
3
|
+
class Importer
|
4
|
+
Inscribe = Model::Inscribe
|
5
|
+
Blob = Model::Blob
|
6
|
+
Collection = Model::Collection
|
2
7
|
|
3
|
-
module OrdDb
|
4
8
|
|
5
|
-
|
9
|
+
|
10
|
+
def import_collection_csv( path,
|
11
|
+
name:,
|
12
|
+
content: true )
|
13
|
+
## or use
|
14
|
+
## import_collection( format: 'csv') - why? why not?
|
15
|
+
recs = read_csv( path )
|
16
|
+
puts " #{recs.size} inscribe id(s)"
|
17
|
+
|
18
|
+
col = Collection.find_by( name: name )
|
19
|
+
if col && col.items.count > 0
|
20
|
+
puts "!! WARN - collection already in db; delete first to reimport"
|
21
|
+
return
|
22
|
+
elsif col
|
23
|
+
## do nothing; (re)use collection record; add items
|
24
|
+
else
|
25
|
+
col = Collection.create(
|
26
|
+
name: name
|
27
|
+
## max: recs.size ## auto-add max - why? why not?
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
recs.each_with_index do |rec,i|
|
32
|
+
id = rec['id']
|
33
|
+
name = rec['name'] || rec['title']
|
34
|
+
puts "==> #{i+1}/#{recs.size} >#{name}< @ #{id}..."
|
35
|
+
|
36
|
+
col.items.create( pos: i,
|
37
|
+
inscribe_id: id,
|
38
|
+
name: name )
|
39
|
+
|
40
|
+
_import( id, content: content )
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
def import_collection_inscriptions( path,
|
46
|
+
name:,
|
47
|
+
content: true )
|
48
|
+
recs = read_json( path )
|
49
|
+
puts " #{recs.size} inscribe id(s)"
|
50
|
+
|
51
|
+
col = Collection.find_by( name: name )
|
52
|
+
if col && col.items.count > 0
|
53
|
+
puts "!! WARN - collection already in db; delete first to reimport"
|
54
|
+
return
|
55
|
+
elsif col
|
56
|
+
## do nothing; (re)use collection record; add items
|
57
|
+
else
|
58
|
+
col = Model::Collection.create(
|
59
|
+
name: name
|
60
|
+
## max: recs.size ## auto-add max - why? why not?
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
64
|
+
recs.each_with_index do |rec,i|
|
65
|
+
id = rec['id']
|
66
|
+
meta = rec['meta']
|
67
|
+
name = meta['name']
|
68
|
+
puts "==> #{i+1}/#{recs.size} >#{name}< @ #{id}..."
|
69
|
+
|
70
|
+
col.items.create( pos: i,
|
71
|
+
inscribe_id: id,
|
72
|
+
name: name )
|
73
|
+
|
74
|
+
_import( id, content: content )
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
def import_collection( path, content: true )
|
6
80
|
data = read_json( path )
|
7
81
|
|
8
82
|
meta = data['collection']
|
@@ -10,13 +84,13 @@ def self.import_collection( path, content: true )
|
|
10
84
|
|
11
85
|
name = meta['name']
|
12
86
|
|
13
|
-
col =
|
87
|
+
col = Collection.find_by( name: name )
|
14
88
|
if col
|
15
89
|
puts "!! WARN - collection already in db; delete first to reimport"
|
16
90
|
return
|
17
91
|
end
|
18
92
|
|
19
|
-
col =
|
93
|
+
col = Collection.create(
|
20
94
|
name: name,
|
21
95
|
desc: meta['description'],
|
22
96
|
max: meta['max_supply']
|
@@ -33,35 +107,12 @@ def self.import_collection( path, content: true )
|
|
33
107
|
inscribe_id: id,
|
34
108
|
name: name )
|
35
109
|
|
36
|
-
|
37
|
-
inscribe = Model::Inscribe.find_by( id: id )
|
38
|
-
if inscribe ## already in db; dump record
|
39
|
-
## pp inscribe
|
40
|
-
else ## fetch via ordinals.com api and update db
|
41
|
-
data = Ordinals.inscription( id )
|
42
|
-
pp data
|
43
|
-
Model::Inscribe.create_from_api( data )
|
44
|
-
sleep( 1 ) ## delay in seconds (before next request)
|
45
|
-
end
|
46
|
-
|
47
|
-
if content
|
48
|
-
## check if (content) blob is already in db?
|
49
|
-
blob = Model::Blob.find_by( id: id )
|
50
|
-
if blob ## already in db; do nothing
|
51
|
-
else ## fetch via ordinals.com api and update db
|
52
|
-
content = Ordinals.content( id )
|
53
|
-
puts " content-type: #{content.type}"
|
54
|
-
puts " content-length: #{content.length}"
|
55
|
-
|
56
|
-
Model::Blob.create( id: id, content: content.data )
|
57
|
-
sleep( 1 ) ## delay in seconds (before next request)
|
58
|
-
end
|
59
|
-
end
|
110
|
+
_import( id, content: content )
|
60
111
|
end
|
61
112
|
end
|
62
113
|
|
63
114
|
|
64
|
-
def
|
115
|
+
def import_csv( path, content: true )
|
65
116
|
recs = read_csv( path )
|
66
117
|
puts " #{recs.size} inscribe id(s)"
|
67
118
|
#=> 1000 inscribe id(s)
|
@@ -70,30 +121,98 @@ def self.import_csv( path, content: true )
|
|
70
121
|
id = rec['id']
|
71
122
|
puts "==> #{i+1}/#{rec.size} @ #{id}..."
|
72
123
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
## pp inscribe
|
77
|
-
else ## fetch via ordinals.com api and update db
|
78
|
-
data = Ordinals.inscription( id )
|
79
|
-
pp data
|
80
|
-
Model::Inscribe.create_from_api( data )
|
81
|
-
sleep( 1 ) ## delay in seconds (before next request)
|
82
|
-
end
|
124
|
+
_import( id, content: content )
|
125
|
+
end
|
126
|
+
end # method import_csv
|
83
127
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
Model::Blob.create( id: id, content: content.data )
|
94
|
-
sleep( 1 ) ## delay in seconds (before next request)
|
95
|
-
end
|
128
|
+
def import( id_or_ids, content: true )
|
129
|
+
if id_or_ids.is_a?( String )
|
130
|
+
id = id_or_ids
|
131
|
+
_import( id, content: content )
|
132
|
+
else ## assume array
|
133
|
+
ids = id_or_ids
|
134
|
+
ids.each do |id|
|
135
|
+
_import( id, content: content )
|
96
136
|
end
|
97
|
-
|
98
|
-
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def _import( id, content: true )
|
141
|
+
## check if inscription / inscribe is already in db?
|
142
|
+
inscribe = Inscribe.find_by( id: id )
|
143
|
+
if inscribe ## already in db; dump record
|
144
|
+
## pp inscribe
|
145
|
+
else ## fetch via ordinals.com api and update db
|
146
|
+
data = Ordinals.inscription( id )
|
147
|
+
|
148
|
+
pp data
|
149
|
+
Inscribe.create_from_api( data )
|
150
|
+
end
|
151
|
+
|
152
|
+
if content
|
153
|
+
## check if (content) blob is already in db?
|
154
|
+
blob = Blob.find_by( id: id )
|
155
|
+
if blob ## already in db; do nothing
|
156
|
+
else ## fetch via ordinals.com api and update db
|
157
|
+
content = Ordinals.content( id )
|
158
|
+
|
159
|
+
puts " content-type: #{content.type}"
|
160
|
+
puts " content-length: #{content.length}"
|
161
|
+
|
162
|
+
Blob.create( id: id, content: content.data )
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
end # class Importer
|
168
|
+
|
169
|
+
|
170
|
+
|
171
|
+
###
|
172
|
+
## convenience helpers
|
173
|
+
|
174
|
+
def self.importer ## "default" importer
|
175
|
+
@importer ||= Importer.new
|
176
|
+
end
|
177
|
+
|
178
|
+
def self.import( id_or_ids, content: true )
|
179
|
+
importer.import( id_or_ids, content: content )
|
180
|
+
end
|
181
|
+
|
182
|
+
|
183
|
+
def self.import_csv( path, content: true )
|
184
|
+
importer.import_csv( path, content: content )
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
def self.import_collection( path, content: true )
|
189
|
+
importer.import_collection( path, content: content )
|
190
|
+
end
|
191
|
+
|
192
|
+
def self.import_collection_inscriptions( path,
|
193
|
+
name:,
|
194
|
+
content: true )
|
195
|
+
importer.import_collection_inscriptions( path,
|
196
|
+
name: name,
|
197
|
+
content: content )
|
198
|
+
end
|
199
|
+
|
200
|
+
def self.import_collection_csv( path,
|
201
|
+
name:,
|
202
|
+
content: true )
|
203
|
+
importer.import_collection_csv( path,
|
204
|
+
name: name,
|
205
|
+
content: content )
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
module Model
|
210
|
+
class Inscribe
|
211
|
+
def self.import( id_or_ids, content: true )
|
212
|
+
OrdDb.importer.import( id_or_ids, content: content )
|
213
|
+
end
|
214
|
+
end # class Inscribe
|
215
|
+
end # module Model
|
216
|
+
|
217
|
+
|
99
218
|
end # module OrdDb
|
@@ -2,7 +2,11 @@ module OrdDb
|
|
2
2
|
module Model
|
3
3
|
|
4
4
|
class Collection < ActiveRecord::Base
|
5
|
-
has_many :items
|
5
|
+
has_many :items
|
6
|
+
## -> { order('pos') }
|
7
|
+
## note: default_scope (order)
|
8
|
+
## will break all count queries and more
|
9
|
+
## thus - no "magic" - always sort if pos order required!!!
|
6
10
|
has_many :inscribes, :through => :items
|
7
11
|
end # class Collection
|
8
12
|
|
@@ -7,7 +7,12 @@ module OrdDb
|
|
7
7
|
|
8
8
|
belongs_to :inscribe
|
9
9
|
|
10
|
-
has_many :inscriberefs
|
10
|
+
has_many :inscriberefs ## join table (use habtm - why? why not?)
|
11
|
+
## -> { order('pos') }
|
12
|
+
## note: default_scope (order)
|
13
|
+
## will break all count queries and more
|
14
|
+
## thus - no "magic" - always sort if pos order required!!!
|
15
|
+
|
11
16
|
has_many :layers, :through => :inscriberefs,
|
12
17
|
:source => :inscribe
|
13
18
|
|
@@ -66,29 +66,40 @@ SQL
|
|
66
66
|
def self.sub20k() where( 'num < 20000' ); end
|
67
67
|
def self.sub100k() where( 'num < 100000' ); end
|
68
68
|
def self.sub1m() where( 'num < 1000000' ); end
|
69
|
+
def self.sub2m() where( 'num < 2000000' ); end
|
70
|
+
def self.sub10m() where( 'num < 10000000' ); end
|
71
|
+
def self.sub20m() where( 'num < 20000000' ); end
|
72
|
+
def self.sub21m() where( 'num < 21000000' ); end
|
69
73
|
|
70
74
|
|
71
75
|
def self.largest
|
72
76
|
order( 'bytes DESC' )
|
73
77
|
end
|
74
78
|
|
79
|
+
def self.address_counts
|
80
|
+
group( 'address' )
|
81
|
+
.order( Arel.sql( 'COUNT(*) DESC')).count
|
82
|
+
end
|
83
|
+
|
75
84
|
def self.block_counts
|
76
|
-
|
85
|
+
group( 'block' )
|
86
|
+
.order( 'block').count
|
77
87
|
end
|
78
88
|
|
79
89
|
def self.block_with_timestamp_counts
|
80
|
-
|
90
|
+
group( Arel.sql( "block || ' @ ' || date" ))
|
91
|
+
.order( Arel.sql( "block || ' @ ' || date" ) ).count
|
81
92
|
end
|
82
93
|
|
83
94
|
def self.content_type_counts
|
84
|
-
|
95
|
+
group( 'content_type' )
|
85
96
|
.order( Arel.sql( 'COUNT(*) DESC, content_type')).count
|
86
97
|
end
|
87
98
|
|
88
99
|
|
89
100
|
def self.date_counts
|
90
101
|
## note: strftime is SQLite specific/only!!!
|
91
|
-
|
102
|
+
group( Arel.sql("strftime('%Y-%m-%d', date)"))
|
92
103
|
.order( Arel.sql("strftime('%Y-%m-%d', date)")).count
|
93
104
|
end
|
94
105
|
|
@@ -100,13 +111,14 @@ SQL
|
|
100
111
|
|
101
112
|
def self.hour_counts
|
102
113
|
## note: strftime is SQLite specific/only!!!
|
103
|
-
|
114
|
+
group( Arel.sql("strftime('%Y-%m-%d %Hh', date)"))
|
104
115
|
.order( Arel.sql("strftime('%Y-%m-%d %Hh', date)")).count
|
105
116
|
end
|
106
117
|
|
107
118
|
|
108
119
|
class << self
|
109
120
|
alias_method :biggest, :largest
|
121
|
+
alias_method :counts_by_address, :address_counts
|
110
122
|
alias_method :counts_by_content_type, :content_type_counts
|
111
123
|
alias_method :counts_by_date, :date_counts
|
112
124
|
alias_method :counts_by_day, :date_counts
|
data/lib/ordlite/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ordlite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.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-07
|
11
|
+
date: 2023-08-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ordinals
|
@@ -122,6 +122,20 @@ dependencies:
|
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: pixelart
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
140
|
name: rdoc
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -173,6 +187,7 @@ files:
|
|
173
187
|
- lib/ordlite.rb
|
174
188
|
- lib/ordlite/base.rb
|
175
189
|
- lib/ordlite/cache.rb
|
190
|
+
- lib/ordlite/factory.rb
|
176
191
|
- lib/ordlite/importer.rb
|
177
192
|
- lib/ordlite/models/blob.rb
|
178
193
|
- lib/ordlite/models/collection.rb
|