holosphere 1.0.2 → 1.0.3
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/index.js +187 -24
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -6,24 +6,132 @@ import { createHash } from "crypto";
|
|
|
6
6
|
|
|
7
7
|
class HoloSphere {
|
|
8
8
|
constructor(appname, openaikey = null) {
|
|
9
|
-
this.appname = appname;
|
|
10
9
|
this.validator = new Ajv2019({ allErrors: false, strict: false });
|
|
11
10
|
this.gun = Gun({
|
|
12
|
-
peers: ['https://59.src.eco/gun'],
|
|
13
|
-
axe: false
|
|
11
|
+
peers: [ 'http://localhost:8765','http://gun.holons.io', 'https://gun-eu.herokuapp.com/gun','https://59.src.eco/gun'],
|
|
12
|
+
axe: false,
|
|
13
|
+
// uuid: (content) => { // generate a unique id for each node
|
|
14
|
+
// console.log('uuid', content);
|
|
15
|
+
// return content;}
|
|
14
16
|
});
|
|
15
17
|
|
|
18
|
+
this.gun = this.gun.get(appname)
|
|
19
|
+
|
|
16
20
|
if (openaikey != null) {
|
|
17
21
|
this.openai = new OpenAI({
|
|
18
22
|
apiKey: openaikey,
|
|
19
23
|
});
|
|
20
24
|
}
|
|
21
25
|
|
|
26
|
+
//this.bot.command('sethex', async (ctx) => { this.setHex(ctx) }) TODO: MOVE HERE FROM SETTINGS
|
|
27
|
+
|
|
28
|
+
// this.bot.command('resethex', async (ctx) => {
|
|
29
|
+
// let chatID = ctx.message.chat.id;
|
|
30
|
+
// let hex = (await this.db.get('settings', chatID)).hex
|
|
31
|
+
// this.delete(hex, ctx.message.text.split(' ')[1])
|
|
32
|
+
// })
|
|
33
|
+
|
|
34
|
+
// this.bot.command('get', async (ctx) => {
|
|
35
|
+
// const chatID = ctx.message.chat.id;
|
|
36
|
+
// const lense = ctx.message.text.split(' ')[1];
|
|
37
|
+
// if (!lense) {
|
|
38
|
+
// return ctx.reply('Please specify a tag.');
|
|
39
|
+
// }
|
|
40
|
+
// let hex = (await this.db.get('settings', chatID)).hex
|
|
41
|
+
// //let hex = settings.hex
|
|
42
|
+
// console.log('hex', hex)
|
|
43
|
+
|
|
44
|
+
// let data = await this.get(ctx, hex, lense)
|
|
45
|
+
|
|
46
|
+
// })
|
|
47
|
+
|
|
48
|
+
// this.bot.command('gethex', async (ctx) => {
|
|
49
|
+
// let settings = await this.db.get('settings', chatID)
|
|
50
|
+
// let id = settings.hex ? settings.hex : 'Hex not set, use /sethex'
|
|
51
|
+
// ctx.reply(id)
|
|
52
|
+
// })
|
|
53
|
+
|
|
54
|
+
// this.bot.command('compute', async (ctx) => {
|
|
55
|
+
// const chatID = ctx.message.chat.id;
|
|
56
|
+
// let operation = ctx.message.text.split(' ')[1];
|
|
57
|
+
// if (operation != 'sum') {
|
|
58
|
+
// ctx.reply('Operation not implemented')
|
|
59
|
+
// return
|
|
60
|
+
// }
|
|
61
|
+
// let lense = ctx.message.text.split(' ')[2]
|
|
62
|
+
// if (!lense) {
|
|
63
|
+
// ctx.reply('Please specify a lense where to perform the operation ')
|
|
64
|
+
// return
|
|
65
|
+
// }
|
|
66
|
+
// let hex = (await this.db.get('settings', chatID)).hex
|
|
67
|
+
// await this.compute(hex, lense, operation)
|
|
68
|
+
|
|
69
|
+
// // let parentInfo = await this.getCellInfo(parent)
|
|
70
|
+
// // parentInfo.wisdom[id] = report
|
|
71
|
+
// // //update summary
|
|
72
|
+
// // let summary = await this.summarize(Object.values(parentInfo.wisdom).join('\n'))
|
|
73
|
+
// // parentInfo.summary = summary
|
|
74
|
+
|
|
75
|
+
// // await this.db.put('cell', parentInfo)
|
|
76
|
+
// // return parentInfo
|
|
77
|
+
|
|
78
|
+
// // let content = await this.db.getAll(hex+'/tags')
|
|
79
|
+
// })
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
// this.bot.command('cast', async (ctx) => {
|
|
85
|
+
// if (!ctx.message.reply_to_message) {
|
|
86
|
+
// return ctx.reply('Please reply to a message you want to tag.');
|
|
87
|
+
// }
|
|
88
|
+
// const tags = ctx.message.text.split(' ').slice(1);
|
|
89
|
+
// if (tags.length === 0) {
|
|
90
|
+
// return ctx.reply('Please provide at least one tag.');
|
|
91
|
+
// }
|
|
92
|
+
|
|
93
|
+
// const messageID = ctx.message.reply_to_message.message_id;
|
|
94
|
+
// const chatID = ctx.message.chat.id;
|
|
95
|
+
// const messageContent = ctx.message.reply_to_message.text;
|
|
96
|
+
// let settings = await this.db.get('settings', chatID)
|
|
97
|
+
// let id = settings.hex ? settings.hex : 'Hex not set, use /sethex'
|
|
98
|
+
// //create root node for the item
|
|
99
|
+
// let node = await this.gun.get(chatID + '/' + messageID).put({ id: chatID + '/' + messageID, content: messageContent })
|
|
100
|
+
// for (let tag of tags) {
|
|
101
|
+
// await this.gun.get(id).get(tag).set(node)
|
|
102
|
+
// this.upcast(id, tag, node)
|
|
103
|
+
// }
|
|
104
|
+
// })
|
|
105
|
+
|
|
106
|
+
// this.bot.command('publish', async (ctx) => {
|
|
107
|
+
// console.log(ctx.message)
|
|
108
|
+
// if (!ctx.message.reply_to_message) {
|
|
109
|
+
// return ctx.reply('Please reply to a message you want to tag.');
|
|
110
|
+
// }
|
|
111
|
+
// const tags = ctx.message.text.split(' ').slice(1);
|
|
112
|
+
// if (tags.length === 0) {
|
|
113
|
+
// return ctx.reply('Please provide at least one tag.');
|
|
114
|
+
// }
|
|
115
|
+
|
|
116
|
+
// const messageID = ctx.message.reply_to_message.message_id;
|
|
117
|
+
// const chatID = ctx.message.chat.id;
|
|
118
|
+
// const messageContent = ctx.message.reply_to_message.text;
|
|
119
|
+
// let settings = await this.db.get('settings', chatID)
|
|
120
|
+
// let hex = settings.hex
|
|
121
|
+
|
|
122
|
+
// for (let tag of tags) {
|
|
123
|
+
// let node = await this.gun.get(chatID + '/' + messageID).put({ id: chatID + '/' + messageID, content: messageContent })
|
|
124
|
+
// await this.put(hex, tag, node)
|
|
125
|
+
// }
|
|
126
|
+
|
|
127
|
+
// ctx.reply('Tag published.');
|
|
128
|
+
// });
|
|
129
|
+
|
|
22
130
|
}
|
|
23
131
|
|
|
24
132
|
async setSchema(lense, schema) {
|
|
25
133
|
return new Promise((resolve, reject) => {
|
|
26
|
-
this.gun.get(
|
|
134
|
+
this.gun.get(lense).get('schema').put(JSON.stringify(schema), ack => {
|
|
27
135
|
if (ack.err) {
|
|
28
136
|
resolve(new Error('Failed to add schema: ' + ack.err));
|
|
29
137
|
} else {
|
|
@@ -36,7 +144,7 @@ class HoloSphere {
|
|
|
36
144
|
|
|
37
145
|
async getSchema(lense) {
|
|
38
146
|
return new Promise((resolve) => {
|
|
39
|
-
this.gun.get(
|
|
147
|
+
this.gun.get(lense).get('schema').once(data => {
|
|
40
148
|
if (data) {
|
|
41
149
|
let parsed;
|
|
42
150
|
try {
|
|
@@ -71,12 +179,11 @@ class HoloSphere {
|
|
|
71
179
|
}
|
|
72
180
|
|
|
73
181
|
async delete(id, tag) {
|
|
74
|
-
await this.gun.get(
|
|
182
|
+
await this.gun.get(id).get(tag).put(null)
|
|
75
183
|
}
|
|
76
184
|
|
|
77
185
|
async put(hex, lense, content) {
|
|
78
186
|
// Retrieve the schema for the lense
|
|
79
|
-
console.log('HoloSphere: Putting content in lense:', lense, 'at hex:', hex, 'content:', content)
|
|
80
187
|
let schema = await this.getSchema(lense)
|
|
81
188
|
if (schema) {
|
|
82
189
|
// Validate the content against the schema
|
|
@@ -93,16 +200,16 @@ class HoloSphere {
|
|
|
93
200
|
let noderef;
|
|
94
201
|
|
|
95
202
|
if (content.id) { //use the user-defined id. Important to be able to send updates using put
|
|
96
|
-
noderef = this.gun.get(
|
|
97
|
-
this.gun.get(
|
|
203
|
+
noderef = this.gun.get(lense).get(content.id).put(payload)
|
|
204
|
+
this.gun.get(hex.toString()).get(lense).get(content.id).put(payload)
|
|
98
205
|
} else { // create a content-addressable reference like IPFS. Note: no updates possible using put
|
|
99
206
|
const hash = createHash("sha256").update(payload).digest("hex");
|
|
100
|
-
noderef = this.gun.get(
|
|
101
|
-
this.gun.get(
|
|
207
|
+
noderef = this.gun.get(lense).get(hash).put(payload)
|
|
208
|
+
this.gun.get(hex.toString()).get(lense).get(hash).put(payload)
|
|
102
209
|
}
|
|
103
210
|
|
|
104
211
|
// return new Promise((resolve, reject) => {
|
|
105
|
-
// this.gun.get(
|
|
212
|
+
// this.gun.get(hex.toString()).get(lense).set(noderef, ack => {
|
|
106
213
|
// if (ack.err) {
|
|
107
214
|
// reject(new Error('Failed to add content: ' + ack.err));
|
|
108
215
|
// } else {
|
|
@@ -127,16 +234,16 @@ class HoloSphere {
|
|
|
127
234
|
return new Promise(async (resolve, reject) => {
|
|
128
235
|
let output = []
|
|
129
236
|
let counter = 0
|
|
130
|
-
this.gun.get(
|
|
237
|
+
this.gun.get(hex.toString()).get(lense).once((data, key) => {
|
|
131
238
|
if (data) {
|
|
132
239
|
const maplenght = Object.keys(data).length - 1
|
|
133
240
|
console.log('Map length:', maplenght)
|
|
134
|
-
this.gun.get(
|
|
241
|
+
this.gun.get(hex.toString()).get(lense).map().once(async (itemdata, key) => {
|
|
135
242
|
counter += 1
|
|
136
243
|
if (itemdata) {
|
|
137
244
|
// if (itemdata._["#"]) {
|
|
138
245
|
// // If the data is a reference, fetch the actual content
|
|
139
|
-
// itemdata = await this.gun.get(
|
|
246
|
+
// itemdata = await this.gun.get(itemdata._['#']).then();
|
|
140
247
|
// console.log("Data :",itemdata)
|
|
141
248
|
// }
|
|
142
249
|
var parsed = {}
|
|
@@ -151,7 +258,7 @@ class HoloSphere {
|
|
|
151
258
|
let valid = this.validator.validate(schema, parsed);
|
|
152
259
|
if (!valid || parsed == null || parsed == undefined) {
|
|
153
260
|
console.log('Removing Invalid content:', this.validator.errors);
|
|
154
|
-
this.gun.get(
|
|
261
|
+
this.gun.get(hex).get(lense).get(key).put(null);
|
|
155
262
|
|
|
156
263
|
} else {
|
|
157
264
|
output.push(parsed);
|
|
@@ -208,7 +315,7 @@ class HoloSphere {
|
|
|
208
315
|
console.log('Content:', content);
|
|
209
316
|
let computed = await this.summarize(content.join('\n'))
|
|
210
317
|
console.log('Computed:', computed)
|
|
211
|
-
let node = await this.gun.get(
|
|
318
|
+
let node = await this.gun.get(parent + '_summary').put({ id: parent + '_summary', content: computed })
|
|
212
319
|
|
|
213
320
|
this.put(parent, lense, node);
|
|
214
321
|
this.compute(parent, lense, operation)
|
|
@@ -218,10 +325,10 @@ class HoloSphere {
|
|
|
218
325
|
let entities = {};
|
|
219
326
|
|
|
220
327
|
// Get list out of Gun
|
|
221
|
-
this.gun.get(
|
|
328
|
+
this.gun.get(hex).get(lense).map().once((data, key) => {
|
|
222
329
|
//entities = data;
|
|
223
330
|
//const id = Object.keys(entities)[0] // since this would be in object form, you can manipulate it as you would like.
|
|
224
|
-
this.gun.get(
|
|
331
|
+
this.gun.get(hex).get(lense).put({ [key]: null })
|
|
225
332
|
})
|
|
226
333
|
}
|
|
227
334
|
|
|
@@ -260,15 +367,15 @@ class HoloSphere {
|
|
|
260
367
|
|
|
261
368
|
async upcast(hex, lense, content) {
|
|
262
369
|
let res = h3.getResolution(hex)
|
|
263
|
-
|
|
264
|
-
if (res == 0)
|
|
265
|
-
return content
|
|
370
|
+
|
|
266
371
|
|
|
267
372
|
console.log('Upcasting ', hex, lense, content)
|
|
268
373
|
let parent = h3.cellToParent(hex, res - 1)
|
|
269
374
|
await this.put(parent, lense, content)
|
|
270
|
-
|
|
271
|
-
|
|
375
|
+
if (res == 0)
|
|
376
|
+
return content
|
|
377
|
+
else
|
|
378
|
+
return this.upcast(parent, lense, content)
|
|
272
379
|
}
|
|
273
380
|
|
|
274
381
|
|
|
@@ -312,6 +419,62 @@ class HoloSphere {
|
|
|
312
419
|
}
|
|
313
420
|
return list
|
|
314
421
|
}
|
|
422
|
+
|
|
423
|
+
subscribe(hex, lense, callback) {
|
|
424
|
+
this.gun.get(hex).get(lense).map().on((data, key) => {
|
|
425
|
+
callback(data, key)
|
|
426
|
+
})
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// VOTING SYSTEM
|
|
430
|
+
|
|
431
|
+
getFinalVote(userId, topic, votes, visited = new Set()) {
|
|
432
|
+
if (visited.has(userId)) {
|
|
433
|
+
return null; // Avoid circular delegations
|
|
434
|
+
}
|
|
435
|
+
visited.add(userId);
|
|
436
|
+
|
|
437
|
+
const delegation = users[userId].delegations[topic];
|
|
438
|
+
if (delegation && votes[delegation] === undefined) {
|
|
439
|
+
return getFinalVote(delegation, topic, votes, visited); // Follow delegation
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
return votes[userId] !== undefined ? votes[userId] : null; // Return direct vote or null
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
aggregateVotes(hexId, topic) {
|
|
446
|
+
const votes = hexagonVotes[hexId][topic];
|
|
447
|
+
const aggregatedVotes = {};
|
|
448
|
+
|
|
449
|
+
Object.keys(votes).forEach(userId => {
|
|
450
|
+
const finalVote = getFinalVote(userId, topic, votes);
|
|
451
|
+
if (finalVote !== null) {
|
|
452
|
+
aggregatedVotes[finalVote] = (aggregatedVotes[finalVote] || 0) + 1;
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
return aggregatedVotes;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
async delegateVote(userId, topic, delegateTo) {
|
|
460
|
+
const response = await fetch('/delegate', {
|
|
461
|
+
method: 'POST',
|
|
462
|
+
headers: { 'Content-Type': 'application/json' },
|
|
463
|
+
body: JSON.stringify({ userId, topic, delegateTo })
|
|
464
|
+
});
|
|
465
|
+
alert(await response.text());
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
async vote(userId, hexId, topic, vote) {
|
|
469
|
+
const response = await fetch('/vote', {
|
|
470
|
+
method: 'POST',
|
|
471
|
+
headers: { 'Content-Type': 'application/json' },
|
|
472
|
+
body: JSON.stringify({ userId, hexId, topic, vote })
|
|
473
|
+
});
|
|
474
|
+
alert(await response.text());
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
|
|
315
478
|
}
|
|
316
479
|
|
|
317
480
|
export default HoloSphere;
|