wao 0.1.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.
- package/cjs/accounts.js +96 -0
- package/cjs/ao.js +1543 -0
- package/cjs/aoconnect.js +758 -0
- package/cjs/ar.js +794 -0
- package/cjs/dirname.js +7 -0
- package/cjs/helpers.js +381 -0
- package/cjs/index.js +20 -0
- package/cjs/utils.js +438 -0
- package/esm/.cache/opt.json +1 -0
- package/esm/accounts.js +91 -0
- package/esm/ao.js +737 -0
- package/esm/aoconnect.js +318 -0
- package/esm/ar.js +243 -0
- package/esm/dirname.js +1 -0
- package/esm/helpers.js +161 -0
- package/esm/index.js +4 -0
- package/esm/lua/aos-sqlite.wasm +0 -0
- package/esm/lua/aos.wasm +0 -0
- package/esm/lua/aos2.lua +33 -0
- package/esm/lua/aos2_0_1.wasm +0 -0
- package/esm/lua/atomic-asset.lua +238 -0
- package/esm/lua/atomic-note-library.lua +2274 -0
- package/esm/lua/atomic-note.lua +11 -0
- package/esm/lua/collection-registry.lua +202 -0
- package/esm/lua/collection.lua +173 -0
- package/esm/lua/notebook.lua +173 -0
- package/esm/lua/profile.lua +858 -0
- package/esm/lua/profile000.lua +666 -0
- package/esm/lua/proxy.lua +24 -0
- package/esm/lua/registry.lua +858 -0
- package/esm/lua/registry000.lua +636 -0
- package/esm/test.js +94 -0
- package/esm/utils.js +342 -0
- package/package.json +21 -0
- package/test/.cache/opt.json +1 -0
- package/test/accounts.js +91 -0
- package/test/ao.js +737 -0
- package/test/aoconnect.js +318 -0
- package/test/ar.js +243 -0
- package/test/dirname.js +1 -0
- package/test/helpers.js +161 -0
- package/test/index.js +4 -0
- package/test/lua/aos-sqlite.wasm +0 -0
- package/test/lua/aos.wasm +0 -0
- package/test/lua/aos2.lua +33 -0
- package/test/lua/aos2_0_1.wasm +0 -0
- package/test/lua/atomic-asset.lua +238 -0
- package/test/lua/atomic-note-library.lua +2274 -0
- package/test/lua/atomic-note.lua +11 -0
- package/test/lua/collection-registry.lua +202 -0
- package/test/lua/collection.lua +173 -0
- package/test/lua/notebook.lua +173 -0
- package/test/lua/profile.lua +858 -0
- package/test/lua/profile000.lua +666 -0
- package/test/lua/proxy.lua +24 -0
- package/test/lua/registry.lua +858 -0
- package/test/lua/registry000.lua +636 -0
- package/test/package.json +21 -0
- package/test/test.js +94 -0
- package/test/utils.js +342 -0
|
@@ -0,0 +1,636 @@
|
|
|
1
|
+
local json = require('json')
|
|
2
|
+
local sqlite3 = require('lsqlite3')
|
|
3
|
+
|
|
4
|
+
Db = Db or sqlite3.open_memory()
|
|
5
|
+
|
|
6
|
+
local function decode_message_data(data)
|
|
7
|
+
local status, decoded_data = pcall(json.decode, data)
|
|
8
|
+
if not status or type(decoded_data) ~= 'table' then
|
|
9
|
+
return false, nil
|
|
10
|
+
end
|
|
11
|
+
return true, decoded_data
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
local function is_authorized(profile_id, address)
|
|
15
|
+
if not profile_id then return true end
|
|
16
|
+
local query = [[
|
|
17
|
+
SELECT role
|
|
18
|
+
FROM ao_profile_authorization
|
|
19
|
+
WHERE profile_id = ? AND delegate_address = ?
|
|
20
|
+
LIMIT 1
|
|
21
|
+
]]
|
|
22
|
+
local stmt = Db:prepare(query)
|
|
23
|
+
stmt:bind_values(profile_id, address)
|
|
24
|
+
local authorized = false
|
|
25
|
+
for row in stmt:nrows() do
|
|
26
|
+
authorized = true
|
|
27
|
+
break
|
|
28
|
+
end
|
|
29
|
+
stmt:finalize()
|
|
30
|
+
return authorized
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
local function process_profile_action(msg, profile_id_to_check_for_update)
|
|
34
|
+
if profile_id_to_check_for_update and not is_authorized(profile_id_to_check_for_update, msg.From) then
|
|
35
|
+
ao.send({
|
|
36
|
+
Target = msg.From,
|
|
37
|
+
Action = 'Authorization-Error',
|
|
38
|
+
Tags = {
|
|
39
|
+
Status = 'Error',
|
|
40
|
+
Message = 'Unauthorized to access this handler'
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
return
|
|
44
|
+
end
|
|
45
|
+
local decode_check, data = decode_message_data(msg.Data)
|
|
46
|
+
if not decode_check then
|
|
47
|
+
ao.send({
|
|
48
|
+
Target = msg.From,
|
|
49
|
+
Action = 'DB_CODE',
|
|
50
|
+
Tags = {
|
|
51
|
+
Status = 'DECODE_FAILED',
|
|
52
|
+
Message = "Failed to decode data"
|
|
53
|
+
},
|
|
54
|
+
Data = { Code = "DECODE_FAILED" }
|
|
55
|
+
})
|
|
56
|
+
return
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
local tags = msg.Tags or {}
|
|
60
|
+
|
|
61
|
+
--local insert_languages = [[ INSERT INTO ]]
|
|
62
|
+
local upsert_metadata_stmt = [[
|
|
63
|
+
INSERT INTO ao_profile_metadata (id, username, profile_image, cover_image, description, display_name, date_updated, date_created)
|
|
64
|
+
VALUES (:id, :username, :profile_image, :cover_image, :description, :display_name, :date_updated, :date_created)
|
|
65
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
66
|
+
username = COALESCE(excluded.username, ao_profile_metadata.username),
|
|
67
|
+
profile_image = CASE
|
|
68
|
+
WHEN excluded.profile_image IS NULL THEN NULL
|
|
69
|
+
WHEN excluded.profile_image = 'NULL' THEN NULL
|
|
70
|
+
ELSE COALESCE(excluded.profile_image, ao_profile_metadata.profile_image, NULL)
|
|
71
|
+
END,
|
|
72
|
+
cover_image = CASE
|
|
73
|
+
WHEN excluded.cover_image IS NULL THEN NULL
|
|
74
|
+
WHEN excluded.cover_image = 'NULL' THEN NULL
|
|
75
|
+
ELSE COALESCE(excluded.cover_image, ao_profile_metadata.cover_image, NULL)
|
|
76
|
+
END,
|
|
77
|
+
description = CASE
|
|
78
|
+
WHEN excluded.description IS NULL THEN NULL
|
|
79
|
+
WHEN excluded.description = 'NULL' THEN NULL
|
|
80
|
+
ELSE COALESCE(excluded.description, ao_profile_metadata.description, NULL)
|
|
81
|
+
END,
|
|
82
|
+
display_name = CASE
|
|
83
|
+
WHEN excluded.display_name IS NULL THEN NULL
|
|
84
|
+
WHEN excluded.display_name = 'NULL' THEN NULL
|
|
85
|
+
ELSE COALESCE(excluded.display_name, ao_profile_metadata.display_name, NULL)
|
|
86
|
+
END,
|
|
87
|
+
date_updated = CASE
|
|
88
|
+
WHEN excluded.date_updated IS NULL THEN excluded.date_created
|
|
89
|
+
WHEN excluded.date_updated = "NULL" THEN excluded.date_created
|
|
90
|
+
ELSE excluded.date_updated
|
|
91
|
+
END,
|
|
92
|
+
date_created = CASE
|
|
93
|
+
WHEN excluded.date_created IS NULL THEN ao_profile_metadata.date_created
|
|
94
|
+
WHEN excluded.date_created = "NULL" THEN ao_profile_metadata.date_created
|
|
95
|
+
ELSE excluded.date_created
|
|
96
|
+
END
|
|
97
|
+
]]
|
|
98
|
+
local upsert_meta = Db:prepare(upsert_metadata_stmt)
|
|
99
|
+
|
|
100
|
+
local names_bound = {
|
|
101
|
+
id = profile_id_to_check_for_update or msg.From,
|
|
102
|
+
username = tags.UserName or data.UserName,
|
|
103
|
+
profile_image = tags.ProfileImage or data.ProfileImage,
|
|
104
|
+
cover_image = tags.CoverImage or data.CoverImage,
|
|
105
|
+
description = tags.Description or data.Description,
|
|
106
|
+
display_name = tags.DisplayName or data.DisplayName,
|
|
107
|
+
date_updated = tags.DateUpdated or tags.DateCreated or data.DateUpdated or data.DateCreated,
|
|
108
|
+
date_created = tags.DateCreated or data.DateCreated or "NULL"
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if upsert_meta then
|
|
112
|
+
upsert_meta:bind_names(names_bound)
|
|
113
|
+
else
|
|
114
|
+
ao.send({
|
|
115
|
+
Target = msg.From,
|
|
116
|
+
Action = 'DB_CODE',
|
|
117
|
+
Tags = {
|
|
118
|
+
Status = 'DB_PREPARE_FAILED',
|
|
119
|
+
Message = "DB PREPARED QUERY FAILED"
|
|
120
|
+
},
|
|
121
|
+
Data = { Code = "Failed to prepare insert statement" }
|
|
122
|
+
})
|
|
123
|
+
print("Failed to prepare insert statement")
|
|
124
|
+
return json.encode({ Code = 'DB_PREPARE_FAILED' })
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
local step_status = upsert_meta:step()
|
|
128
|
+
if step_status ~= sqlite3.OK and step_status ~= sqlite3.DONE and step_status ~= sqlite3.ROW then
|
|
129
|
+
ao.send({
|
|
130
|
+
Target = msg.From,
|
|
131
|
+
Action = 'DB_STEP_CODE',
|
|
132
|
+
Tags = {
|
|
133
|
+
Status = 'ERROR',
|
|
134
|
+
Message = step_status
|
|
135
|
+
},
|
|
136
|
+
Data = { DB_STEP_MSG = step_status }
|
|
137
|
+
})
|
|
138
|
+
return json.encode({ Code = step_status })
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
ao.send({
|
|
142
|
+
Target = msg.From,
|
|
143
|
+
Action = 'Success',
|
|
144
|
+
Tags = {
|
|
145
|
+
Status = 'Success',
|
|
146
|
+
Message = 'Record Inserted'
|
|
147
|
+
},
|
|
148
|
+
Data = json.encode(names_bound)
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
upsert_meta:finalize()
|
|
152
|
+
if (not profile_id_to_check_for_update) then
|
|
153
|
+
local check = Db:prepare('SELECT 1 FROM ao_profile_authorization WHERE delegate_address = ? LIMIT 1')
|
|
154
|
+
check:bind_values(msg.From)
|
|
155
|
+
if check:step() ~= sqlite3.ROW then
|
|
156
|
+
local insert_auth = Db:prepare(
|
|
157
|
+
'INSERT INTO ao_profile_authorization (profile_id, delegate_address, role) VALUES (?, ?, ?)')
|
|
158
|
+
insert_auth:bind_values(msg.From, data.AuthorizedAddress, 'Admin')
|
|
159
|
+
insert_auth:step()
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
-- Handlers.add('migrate-database', ... , Db:exec [[ ALTER TABLE _ ADD new_field type ]]
|
|
165
|
+
|
|
166
|
+
Handlers.add('Prepare-Database', Handlers.utils.hasMatchingTag('Action', 'Prepare-Database'),
|
|
167
|
+
function(msg)
|
|
168
|
+
if msg.From ~= Owner and msg.From ~= ao.id then
|
|
169
|
+
ao.send({
|
|
170
|
+
Target = msg.From,
|
|
171
|
+
Action = 'Authorization-Error',
|
|
172
|
+
Tags = {
|
|
173
|
+
Status = 'Error',
|
|
174
|
+
Message = 'Unauthorized to access this handler'
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
return
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
--todo create tables for: languages, following, followed, topic-tags, locations, external_links, external_wallets
|
|
181
|
+
|
|
182
|
+
Db:exec [[
|
|
183
|
+
CREATE TABLE IF NOT EXISTS ao_profile_metadata (
|
|
184
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
185
|
+
username TEXT,
|
|
186
|
+
display_name TEXT,
|
|
187
|
+
description TEXT,
|
|
188
|
+
profile_image TEXT,
|
|
189
|
+
cover_image TEXT,
|
|
190
|
+
date_created INTEGER NOT NULL,
|
|
191
|
+
date_updated INTEGER NOT NULL
|
|
192
|
+
);
|
|
193
|
+
]]
|
|
194
|
+
|
|
195
|
+
Db:exec [[
|
|
196
|
+
CREATE TABLE IF NOT EXISTS ao_profile_authorization (
|
|
197
|
+
profile_id TEXT NOT NULL,
|
|
198
|
+
delegate_address TEXT NOT NULL,
|
|
199
|
+
role TEXT NOT NULL,
|
|
200
|
+
PRIMARY KEY (profile_id, delegate_address),
|
|
201
|
+
FOREIGN KEY (profile_id) REFERENCES ao_profile_metadata (id) ON DELETE CASCADE
|
|
202
|
+
);
|
|
203
|
+
]]
|
|
204
|
+
|
|
205
|
+
ao.send({
|
|
206
|
+
Target = Owner,
|
|
207
|
+
Action = 'DB-Init-Success',
|
|
208
|
+
Tags = {
|
|
209
|
+
Status = 'Success',
|
|
210
|
+
Message = 'Created DB'
|
|
211
|
+
}
|
|
212
|
+
})
|
|
213
|
+
end)
|
|
214
|
+
|
|
215
|
+
-- Data - { ProfileIds [] }
|
|
216
|
+
Handlers.add('Get-Metadata-By-ProfileIds', Handlers.utils.hasMatchingTag('Action', 'Get-Metadata-By-ProfileIds'),
|
|
217
|
+
function(msg)
|
|
218
|
+
local decode_check, data = decode_message_data(msg.Data)
|
|
219
|
+
|
|
220
|
+
if decode_check and data then
|
|
221
|
+
if not data.ProfileIds then
|
|
222
|
+
ao.send({
|
|
223
|
+
Target = msg.From,
|
|
224
|
+
Action = 'Input-Error',
|
|
225
|
+
Tags = {
|
|
226
|
+
Status = 'Error',
|
|
227
|
+
Message = 'Invalid arguments, required { ProfileIds }'
|
|
228
|
+
}
|
|
229
|
+
})
|
|
230
|
+
return
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
local metadata = {}
|
|
234
|
+
if data.ProfileIds and #data.ProfileIds > 0 then
|
|
235
|
+
local profileIdList = {}
|
|
236
|
+
for _, id in ipairs(data.ProfileIds) do
|
|
237
|
+
table.insert(profileIdList, string.format("'%s'", id))
|
|
238
|
+
end
|
|
239
|
+
local idString = table.concat(profileIdList, ',')
|
|
240
|
+
|
|
241
|
+
if #idString > 0 then
|
|
242
|
+
local query = string.format('SELECT * FROM ao_profile_metadata WHERE id IN (%s)', idString)
|
|
243
|
+
|
|
244
|
+
local foundRows = false
|
|
245
|
+
for row in Db:nrows(query) do
|
|
246
|
+
foundRows = true
|
|
247
|
+
table.insert(metadata,
|
|
248
|
+
{
|
|
249
|
+
ProfileId = row.id,
|
|
250
|
+
Username = row.username,
|
|
251
|
+
ProfileImage = row.profile_image,
|
|
252
|
+
CoverImage =
|
|
253
|
+
row.cover_image,
|
|
254
|
+
Description = row.description,
|
|
255
|
+
DisplayName = row.display_name
|
|
256
|
+
})
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
if not foundRows then
|
|
260
|
+
print('No rows found matching the criteria.')
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
ao.send({
|
|
264
|
+
Target = msg.From,
|
|
265
|
+
Action = 'Get-Metadata-Success',
|
|
266
|
+
Tags = {
|
|
267
|
+
Status = 'Success',
|
|
268
|
+
Message = 'Metadata retrieved',
|
|
269
|
+
},
|
|
270
|
+
Data = json.encode(metadata)
|
|
271
|
+
})
|
|
272
|
+
else
|
|
273
|
+
print('Profile ID list is empty after validation.')
|
|
274
|
+
end
|
|
275
|
+
else
|
|
276
|
+
print('No ProfileIds provided or the list is empty.')
|
|
277
|
+
end
|
|
278
|
+
else
|
|
279
|
+
ao.send({
|
|
280
|
+
Target = msg.From,
|
|
281
|
+
Action = 'Input-Error',
|
|
282
|
+
Tags = {
|
|
283
|
+
Status = 'Error',
|
|
284
|
+
Message = string.format(
|
|
285
|
+
'Failed to parse data, received: %s. %s.', msg.Data,
|
|
286
|
+
'Data must be an object - { ProfileIds }')
|
|
287
|
+
}
|
|
288
|
+
})
|
|
289
|
+
end
|
|
290
|
+
end)
|
|
291
|
+
|
|
292
|
+
-- Data - { Address }
|
|
293
|
+
Handlers.add('Get-Profiles-By-Delegate', Handlers.utils.hasMatchingTag('Action', 'Get-Profiles-By-Delegate'),
|
|
294
|
+
function(msg)
|
|
295
|
+
local decode_check, data = decode_message_data(msg.Data)
|
|
296
|
+
|
|
297
|
+
if decode_check and data then
|
|
298
|
+
if not data.Address then
|
|
299
|
+
ao.send({
|
|
300
|
+
Target = msg.From,
|
|
301
|
+
Action = 'Input-Error',
|
|
302
|
+
Tags = {
|
|
303
|
+
Status = 'Error',
|
|
304
|
+
Message = 'Invalid arguments, required { Address }'
|
|
305
|
+
}
|
|
306
|
+
})
|
|
307
|
+
return
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
local associated_profiles = {}
|
|
311
|
+
|
|
312
|
+
local authorization_lookup = Db:prepare([[
|
|
313
|
+
SELECT profile_id, delegate_address, role
|
|
314
|
+
FROM ao_profile_authorization
|
|
315
|
+
WHERE delegate_address = ?
|
|
316
|
+
]])
|
|
317
|
+
|
|
318
|
+
authorization_lookup:bind_values(data.Address)
|
|
319
|
+
|
|
320
|
+
for row in authorization_lookup:nrows() do
|
|
321
|
+
table.insert(associated_profiles, {
|
|
322
|
+
ProfileId = row.profile_id,
|
|
323
|
+
CallerAddress = row.delegate_address,
|
|
324
|
+
Role = row.role
|
|
325
|
+
})
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
authorization_lookup:finalize()
|
|
329
|
+
|
|
330
|
+
if #associated_profiles > 0 then
|
|
331
|
+
ao.send({
|
|
332
|
+
Target = msg.From,
|
|
333
|
+
Action = 'Profile-Success',
|
|
334
|
+
Tags = {
|
|
335
|
+
Status = 'Success',
|
|
336
|
+
Message = 'Associated profiles fetched'
|
|
337
|
+
},
|
|
338
|
+
Data = json.encode(associated_profiles)
|
|
339
|
+
})
|
|
340
|
+
else
|
|
341
|
+
ao.send({
|
|
342
|
+
Target = msg.From,
|
|
343
|
+
Action = 'Profile-Error',
|
|
344
|
+
Tags = {
|
|
345
|
+
Status = 'Error',
|
|
346
|
+
Message = 'This wallet address is not associated with a profile'
|
|
347
|
+
}
|
|
348
|
+
})
|
|
349
|
+
end
|
|
350
|
+
else
|
|
351
|
+
ao.send({
|
|
352
|
+
Target = msg.From,
|
|
353
|
+
Action = 'Input-Error',
|
|
354
|
+
Tags = {
|
|
355
|
+
Status = 'Error',
|
|
356
|
+
Message = string.format(
|
|
357
|
+
'Failed to parse data, received: %s. %s.', msg.Data,
|
|
358
|
+
'Data must be an object - { Address }')
|
|
359
|
+
}
|
|
360
|
+
})
|
|
361
|
+
end
|
|
362
|
+
end)
|
|
363
|
+
|
|
364
|
+
-- Data - { Addresses }
|
|
365
|
+
Handlers.add('Read-Profiles', Handlers.utils.hasMatchingTag('Action', 'Read-Profiles'),
|
|
366
|
+
function(msg)
|
|
367
|
+
local json = require 'json'
|
|
368
|
+
|
|
369
|
+
local function decode_message_data(data)
|
|
370
|
+
local status, decoded_data = pcall(json.decode, data)
|
|
371
|
+
if not status or type(decoded_data) ~= 'table' then
|
|
372
|
+
return false, nil
|
|
373
|
+
end
|
|
374
|
+
return true, decoded_data
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
local decode_check, data = decode_message_data(msg.Data)
|
|
378
|
+
|
|
379
|
+
if decode_check and data then
|
|
380
|
+
if not data.Addresses or type(data.Addresses) ~= 'table' then
|
|
381
|
+
ao.send({
|
|
382
|
+
Target = msg.From,
|
|
383
|
+
Action = 'Input-Error',
|
|
384
|
+
Tags = {
|
|
385
|
+
Status = 'Error',
|
|
386
|
+
Message = 'Invalid arguments, required { Addresses }'
|
|
387
|
+
}
|
|
388
|
+
})
|
|
389
|
+
return
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
local associated_profiles = {}
|
|
393
|
+
|
|
394
|
+
-- Create placeholders
|
|
395
|
+
local placeholders = {}
|
|
396
|
+
for i = 1, #data.Addresses do
|
|
397
|
+
table.insert(placeholders, '?')
|
|
398
|
+
end
|
|
399
|
+
local placeholders_str = table.concat(placeholders, ', ')
|
|
400
|
+
|
|
401
|
+
-- Prepare the SQL query
|
|
402
|
+
local sql_query = [[
|
|
403
|
+
SELECT profile_id, delegate_address
|
|
404
|
+
FROM ao_profile_authorization
|
|
405
|
+
WHERE delegate_address IN (]] .. placeholders_str .. [[)
|
|
406
|
+
]]
|
|
407
|
+
|
|
408
|
+
local authorization_lookup = Db:prepare(sql_query)
|
|
409
|
+
|
|
410
|
+
-- Bind values
|
|
411
|
+
for i, address in ipairs(data.Addresses) do
|
|
412
|
+
authorization_lookup:bind(i, address)
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
-- Execute query and gather results
|
|
416
|
+
for row in authorization_lookup:nrows() do
|
|
417
|
+
table.insert(associated_profiles, {
|
|
418
|
+
ProfileId = row.profile_id,
|
|
419
|
+
CallerAddress = row.delegate_address
|
|
420
|
+
})
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
authorization_lookup:finalize()
|
|
424
|
+
|
|
425
|
+
if #associated_profiles > 0 then
|
|
426
|
+
ao.send({
|
|
427
|
+
Target = msg.From,
|
|
428
|
+
Action = 'Profile-Success',
|
|
429
|
+
Tags = {
|
|
430
|
+
Status = 'Success',
|
|
431
|
+
Message = 'Associated profiles fetched'
|
|
432
|
+
},
|
|
433
|
+
Data = json.encode(associated_profiles)
|
|
434
|
+
})
|
|
435
|
+
else
|
|
436
|
+
ao.send({
|
|
437
|
+
Target = msg.From,
|
|
438
|
+
Action = 'Profile-Error',
|
|
439
|
+
Tags = {
|
|
440
|
+
Status = 'Error',
|
|
441
|
+
Message = 'No profiles associated with the provided addresses'
|
|
442
|
+
}
|
|
443
|
+
})
|
|
444
|
+
end
|
|
445
|
+
else
|
|
446
|
+
ao.send({
|
|
447
|
+
Target = msg.From,
|
|
448
|
+
Action = 'Input-Error',
|
|
449
|
+
Tags = {
|
|
450
|
+
Status = 'Error',
|
|
451
|
+
Message = string.format(
|
|
452
|
+
'Failed to parse data, received: %s. %s.', msg.Data,
|
|
453
|
+
'Data must be an object - { Addresses }')
|
|
454
|
+
}
|
|
455
|
+
})
|
|
456
|
+
end
|
|
457
|
+
end)
|
|
458
|
+
|
|
459
|
+
-- Create-Profile Handler
|
|
460
|
+
Handlers.add('Create-Profile', Handlers.utils.hasMatchingTag('Action', 'Create-Profile'),
|
|
461
|
+
function(msg)
|
|
462
|
+
process_profile_action(msg, nil)
|
|
463
|
+
end)
|
|
464
|
+
|
|
465
|
+
-- Update-Profile Handler
|
|
466
|
+
Handlers.add('Update-Profile', Handlers.utils.hasMatchingTag('Action', 'Update-Profile'),
|
|
467
|
+
function(msg)
|
|
468
|
+
process_profile_action(msg, msg.Target)
|
|
469
|
+
end)
|
|
470
|
+
|
|
471
|
+
Handlers.add('Count-Profiles', Handlers.utils.hasMatchingTag('Action', 'Count-Profiles'),
|
|
472
|
+
function(msg)
|
|
473
|
+
local count_sql = [[
|
|
474
|
+
SELECT COUNT(*)
|
|
475
|
+
FROM ao_profile_metadata
|
|
476
|
+
]]
|
|
477
|
+
local stmt = Db:prepare(count_sql)
|
|
478
|
+
local result = stmt:step()
|
|
479
|
+
local count = 0
|
|
480
|
+
|
|
481
|
+
if result == sqlite3.ROW then
|
|
482
|
+
count = stmt:get_value(0)
|
|
483
|
+
else
|
|
484
|
+
count = -1
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
ao.send({
|
|
488
|
+
Target = msg.From,
|
|
489
|
+
Action = 'Count-Profiles-Success',
|
|
490
|
+
Tags = {
|
|
491
|
+
Status = 'Success',
|
|
492
|
+
Message = 'Profiles Counted',
|
|
493
|
+
},
|
|
494
|
+
Data = json.encode({ Count = count })
|
|
495
|
+
})
|
|
496
|
+
return json.encode({ Count = count })
|
|
497
|
+
end)
|
|
498
|
+
|
|
499
|
+
Handlers.add('Read-Metadata', Handlers.utils.hasMatchingTag('Action', 'Read-Metadata'),
|
|
500
|
+
function(msg)
|
|
501
|
+
local metadata = {}
|
|
502
|
+
local status, err = pcall(function()
|
|
503
|
+
for row in Db:nrows('SELECT username, profile_image, cover_image, description, display_name, date_updated, date_created FROM ao_profile_metadata') do
|
|
504
|
+
table.insert(metadata, {
|
|
505
|
+
Username = row.username,
|
|
506
|
+
ProfileImage = row.profile_image,
|
|
507
|
+
CoverImage = row.cover_image,
|
|
508
|
+
Description = row.description,
|
|
509
|
+
DisplayName = row.display_name,
|
|
510
|
+
DateCreated = row.date_created,
|
|
511
|
+
DateUpdated = row.date_updated
|
|
512
|
+
})
|
|
513
|
+
end
|
|
514
|
+
end)
|
|
515
|
+
if not status then
|
|
516
|
+
print("Error: ", err)
|
|
517
|
+
return
|
|
518
|
+
end
|
|
519
|
+
ao.send({
|
|
520
|
+
Target = msg.From,
|
|
521
|
+
Action = 'Read-Metadata-Success',
|
|
522
|
+
Tags = {
|
|
523
|
+
Status = 'Success',
|
|
524
|
+
Message = 'Metadata retrieved',
|
|
525
|
+
},
|
|
526
|
+
Data = json.encode(metadata)
|
|
527
|
+
})
|
|
528
|
+
|
|
529
|
+
return json.encode(metadata)
|
|
530
|
+
end)
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
Handlers.add('Read-Auth', Handlers.utils.hasMatchingTag('Action', 'Read-Auth'),
|
|
534
|
+
function(msg)
|
|
535
|
+
local metadata = {}
|
|
536
|
+
local status, err = pcall(function()
|
|
537
|
+
for row in Db:nrows('SELECT profile_id, delegate_address, role FROM ao_profile_authorization') do
|
|
538
|
+
table.insert(metadata, {
|
|
539
|
+
ProfileId = row.profile_id,
|
|
540
|
+
CallerAddress = row.delegate_address,
|
|
541
|
+
Role = row.role,
|
|
542
|
+
})
|
|
543
|
+
end
|
|
544
|
+
end)
|
|
545
|
+
if not status then
|
|
546
|
+
print("Error: ", err)
|
|
547
|
+
return
|
|
548
|
+
end
|
|
549
|
+
ao.send({
|
|
550
|
+
Target = msg.From,
|
|
551
|
+
Action = 'Read-Metadata-Success',
|
|
552
|
+
Tags = {
|
|
553
|
+
Status = 'Success',
|
|
554
|
+
Message = 'Metadata retrieved',
|
|
555
|
+
},
|
|
556
|
+
Data = json.encode(metadata)
|
|
557
|
+
})
|
|
558
|
+
return json.encode(metadata)
|
|
559
|
+
end)
|
|
560
|
+
|
|
561
|
+
Handlers.add('Read-Profile', Handlers.utils.hasMatchingTag('Action', 'Read-Profile'),
|
|
562
|
+
function(msg)
|
|
563
|
+
local decode_check, data = decode_message_data(msg.Data)
|
|
564
|
+
|
|
565
|
+
if decode_check ~= true then
|
|
566
|
+
ao.send({
|
|
567
|
+
Target = msg.From,
|
|
568
|
+
Action = 'DB_CODE',
|
|
569
|
+
Tags = {
|
|
570
|
+
Status = 'DECODE_FAILED',
|
|
571
|
+
Message = "Failed to decode data"
|
|
572
|
+
},
|
|
573
|
+
Data = { Code = "DECODE_FAILED" }
|
|
574
|
+
})
|
|
575
|
+
return
|
|
576
|
+
end
|
|
577
|
+
|
|
578
|
+
local selectsql = [[
|
|
579
|
+
SELECT *
|
|
580
|
+
FROM ao_profile_metadata
|
|
581
|
+
WHERE id = ?
|
|
582
|
+
]]
|
|
583
|
+
|
|
584
|
+
local row
|
|
585
|
+
local select_stmt = Db:prepare(selectsql)
|
|
586
|
+
local bind = -1
|
|
587
|
+
if select_stmt then
|
|
588
|
+
bind = select_stmt:bind_values(data.ProfileId)
|
|
589
|
+
else
|
|
590
|
+
ao.send({
|
|
591
|
+
Target = msg.From,
|
|
592
|
+
Action = 'DB_CODE',
|
|
593
|
+
Tags = {
|
|
594
|
+
Status = 'DB_PREPARE_FAILED',
|
|
595
|
+
Message = "DB PREPARED QUERY FAILED"
|
|
596
|
+
},
|
|
597
|
+
Data = { Code = "Failed to prepare select statement" }
|
|
598
|
+
})
|
|
599
|
+
print("Failed to prepare select statement")
|
|
600
|
+
return json.encode({ Code = 'DB_PREPARE_FAILED' })
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
local step_status = select_stmt:step()
|
|
604
|
+
if step_status ~= sqlite3.OK and step_status ~= sqlite3.DONE and step_status ~= sqlite3.ROW then
|
|
605
|
+
ao.send({
|
|
606
|
+
Target = msg.From,
|
|
607
|
+
Action = 'DB_STEP_CODE',
|
|
608
|
+
Tags = {
|
|
609
|
+
Status = 'ERROR',
|
|
610
|
+
Message = 'sqlite step error'
|
|
611
|
+
},
|
|
612
|
+
Data = { DB_STEP_MSG = step_status }
|
|
613
|
+
})
|
|
614
|
+
return json.encode({ Code = step_status })
|
|
615
|
+
end
|
|
616
|
+
|
|
617
|
+
row = select_stmt:get_named_values()
|
|
618
|
+
local metadata = {
|
|
619
|
+
Username = row.username,
|
|
620
|
+
ProfileImage = row.profile_image,
|
|
621
|
+
CoverImage = row.cover_image,
|
|
622
|
+
Description = row.description,
|
|
623
|
+
DisplayName = row.display_name,
|
|
624
|
+
DateCreated = row.date_created,
|
|
625
|
+
DateUpdated = row.date_updated
|
|
626
|
+
}
|
|
627
|
+
ao.send({
|
|
628
|
+
Target = msg.From,
|
|
629
|
+
Action = 'Success',
|
|
630
|
+
Tags = {
|
|
631
|
+
Status = 'Success',
|
|
632
|
+
Message = 'Record Inserted'
|
|
633
|
+
},
|
|
634
|
+
Data = json.encode(metadata)
|
|
635
|
+
})
|
|
636
|
+
end)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "wao",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"module": "index.js",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=20.0.0"
|
|
9
|
+
},
|
|
10
|
+
"author": "",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@babel/plugin-transform-modules-commonjs": "^7.24.8",
|
|
14
|
+
"@permaweb/ao-loader": "^0.0.43",
|
|
15
|
+
"@permaweb/aoconnect": "^0.0.61",
|
|
16
|
+
"arbundles": "^0.11.1",
|
|
17
|
+
"arweave": "^1.15.1",
|
|
18
|
+
"base64url": "^3.0.1",
|
|
19
|
+
"ramda": "^0.30.1"
|
|
20
|
+
}
|
|
21
|
+
}
|