forked from cory/tildefriends
Cory McWilliams
3b676d967e
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3972 ed5197a5-7fde-0310-b194-c3ffbd925b24
159 lines
4.0 KiB
JavaScript
159 lines
4.0 KiB
JavaScript
"use strict";
|
|
|
|
var g_following_cache = {};
|
|
var g_following_deep_cache = {};
|
|
var g_about_cache = {};
|
|
|
|
async function following(db, id) {
|
|
if (g_following_cache[id]) {
|
|
return g_following_cache[id];
|
|
}
|
|
var o = await db.get(id + ":following");
|
|
const k_version = 5;
|
|
var f = o ? JSON.parse(o) : o;
|
|
if (!f || f.version != k_version) {
|
|
f = {users: [], sequence: 0, version: k_version};
|
|
}
|
|
f.users = new Set(f.users);
|
|
await ssb.sqlStream(
|
|
"SELECT "+
|
|
" sequence, "+
|
|
" json_extract(content, '$.contact') AS contact, "+
|
|
" json_extract(content, '$.following') AS following "+
|
|
"FROM messages "+
|
|
"WHERE "+
|
|
" author = ?1 AND "+
|
|
" sequence > ?2 AND "+
|
|
" json_extract(content, '$.type') = 'contact' "+
|
|
"UNION SELECT MAX(sequence) AS sequence, NULL, NULL FROM messages WHERE author = ?1 "+
|
|
"ORDER BY sequence",
|
|
[id, f.sequence],
|
|
function(row) {
|
|
if (row.following) {
|
|
f.users.add(row.contact);
|
|
} else {
|
|
f.users.delete(row.contact);
|
|
}
|
|
f.sequence = row.sequence;
|
|
});
|
|
var as_set = f.users;
|
|
f.users = Array.from(f.users).sort();
|
|
var j = JSON.stringify(f);
|
|
if (o != j) {
|
|
await db.set(id + ":following", j);
|
|
}
|
|
f.users = as_set;
|
|
g_following_cache[id] = f.users;
|
|
return f.users;
|
|
}
|
|
|
|
async function followingDeep(db, seed_ids, depth) {
|
|
if (depth <= 0) {
|
|
return seed_ids;
|
|
}
|
|
var key = JSON.stringify([seed_ids, depth]);
|
|
if (g_following_deep_cache[key]) {
|
|
return g_following_deep_cache[key];
|
|
}
|
|
var f = await Promise.all(seed_ids.map(x => following(db, x).then(x => [...x])));
|
|
var ids = [].concat(...f);
|
|
var x = await followingDeep(db, [...new Set(ids)].sort(), depth - 1);
|
|
x = [...new Set([].concat(...x, ...seed_ids))].sort();
|
|
g_following_deep_cache[key] = x;
|
|
return x;
|
|
}
|
|
|
|
async function getAbout(db, id) {
|
|
if (g_about_cache[id]) {
|
|
return g_about_cache[id];
|
|
}
|
|
var o = await db.get(id + ":about");
|
|
const k_version = 4;
|
|
var f = o ? JSON.parse(o) : o;
|
|
if (!f || f.version != k_version) {
|
|
f = {about: {}, sequence: 0, version: k_version};
|
|
}
|
|
await ssb.sqlStream(
|
|
"SELECT "+
|
|
" sequence, "+
|
|
" content "+
|
|
"FROM messages "+
|
|
"WHERE "+
|
|
" author = ?1 AND "+
|
|
" sequence > ?2 AND "+
|
|
" json_extract(content, '$.type') = 'about' AND "+
|
|
" json_extract(content, '$.about') = ?1 "+
|
|
"UNION SELECT MAX(sequence) as sequence, NULL FROM messages WHERE author = ?1 "+
|
|
"ORDER BY sequence",
|
|
[id, f.sequence],
|
|
function(row) {
|
|
f.sequence = row.sequence;
|
|
if (row.content) {
|
|
var about = {};
|
|
try {
|
|
about = JSON.parse(row.content);
|
|
} catch {
|
|
}
|
|
delete about.about;
|
|
delete about.type;
|
|
f.about = Object.assign(f.about, about);
|
|
}
|
|
});
|
|
var j = JSON.stringify(f);
|
|
if (o != j) {
|
|
await db.set(id + ":about", j);
|
|
}
|
|
g_about_cache[id] = f.about;
|
|
return f.about;
|
|
}
|
|
|
|
async function getSize(db, id) {
|
|
let size = 0;
|
|
await ssb.sqlStream(
|
|
"SELECT (SUM(LENGTH(content)) + SUM(LENGTH(author)) + SUM(LENGTH(id))) AS size FROM messages WHERE author = ?1",
|
|
[id],
|
|
function (row) {
|
|
size += row.size;
|
|
});
|
|
return size;
|
|
}
|
|
|
|
function niceSize(bytes) {
|
|
let value = bytes;
|
|
let unit = 'B';
|
|
const k_units = ['kB', 'MB', 'GB', 'TB'];
|
|
for (let u of k_units) {
|
|
if (value >= 1024) {
|
|
value /= 1024;
|
|
unit = u;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
return Math.round(value * 10) / 10 + ' ' + unit;
|
|
}
|
|
|
|
async function buildTree(db, root, indent, depth) {
|
|
var f = await following(db, root);
|
|
var result = indent + '[' + f.size + '] ' + '<a target="_top" href="../index/#' + root + '">' + ((await getAbout(db, root)).name || root) + '</a> ' + niceSize(await getSize(db, root)) + '\n';
|
|
if (depth > 0) {
|
|
for (let next of f) {
|
|
result += await buildTree(db, next, indent + ' ', depth - 1);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
async function main() {
|
|
await app.setDocument('<pre style="color: #fff">building...</pre>');
|
|
var db = await database('ssb');
|
|
var whoami = await ssb.getIdentities();
|
|
var tree = '';
|
|
for (let id of whoami) {
|
|
await app.setDocument(`<pre style="color: #fff">building... ${id}</pre>`);
|
|
tree += await buildTree(db, id, '', 2);
|
|
}
|
|
await app.setDocument('<pre style="color: #fff">FOLLOWING:\n' + tree + '</pre>');
|
|
}
|
|
|
|
main(); |