tildefriends/apps/storage/app.js

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

111 lines
3.1 KiB
JavaScript
Raw Normal View History

async function query(sql, args) {
let rows = [];
await ssb.sqlAsync(sql, args ?? [], function(row) {
rows.push(row);
});
return rows;;
}
async function get_biggest() {
return query(`
select author, sum(length(content)) as size from messages group by author order by size desc limit 10;
`);
}
2024-11-26 16:05:28 -05:00
async function get_total() {
return (await query(`
select sum(length(content)) as size, count(distinct author) as count from messages;
`))[0];
}
async function get_names(identities) {
return query(`
SELECT author, name FROM (
SELECT
messages.author,
RANK() OVER (PARTITION BY messages.author ORDER BY messages.sequence DESC) AS author_rank,
messages.content ->> 'name' AS name
FROM messages
JOIN json_each(?) AS identities ON identities.value = messages.author
WHERE
json_extract(messages.content, '$.type') = 'about' AND
content ->> 'about' = messages.author AND name IS NOT NULL)
WHERE author_rank = 1
`, [JSON.stringify(identities)]);
}
async function get_most_follows() {
return query(`
select author, count(*) as count
from messages
where content ->> 'type' = 'contact' and content ->> 'following' = true
group by author
order by count desc
limit 10;
`);
}
function nice_size(bytes) {
let value = bytes;
let index = 0;
let units = ['B', 'kB', 'MB', 'GB'];
while (value > 1024 && index < units.length - 1) {
value /= 1024;
index++;
}
return `${Math.round(value * 10) / 10} ${units[index]}`;
}
async function main() {
await app.setDocument('<p style="color: #fff">Finding the top 10 largest feeds...</p>');
let most_follows = await get_most_follows();
2024-11-26 16:05:28 -05:00
let total = await get_total();
let identities = await ssb.getAllIdentities();
let following1 = await ssb.following(identities, 1);
let following2 = await ssb.following(identities, 2);
let biggest = await get_biggest();
let names = await get_names([].concat(biggest.map(x => x.author), most_follows.map(x => x.author)));
names = Object.fromEntries(names.map(x => [x.author, x.name]));
for (let item of biggest) {
item.name = names[item.author];
item.following =
identities.indexOf(item.author) != -1 ? 0 :
following1[item.author] !== undefined ? 1 :
following2[item.author] !== undefined ? 2 :
undefined;
}
for (let item of most_follows) {
item.name = names[item.author];
}
let html = `<body style="color: #000; background-color: #ddd">\n
<h1>Storage Summary</h1>
<h2>Top 10 Accounts by Size</h2>
<ol>`;
for (let item of biggest) {
html += `<li>
<span style="color: #888">${nice_size(item.size)}</span>
<a target="_top" href="/~core/ssb/#${encodeURI(item.author)}">${item.name ?? item.author}</a>
2024-11-26 16:05:28 -05:00
</li>
\n`;
}
html += `
</ol>
<h2>Top 10 Accounts by Follows</h2>
<ol>`;
for (let item of most_follows) {
html += `<li>
<span style="color: #888">${item.count}</span>
${following2[item.author] ? '✅' : '🚫'}
<a target="_top" href="/~core/ssb/#${encodeURI(item.author)}">${item.name ?? item.author}</a>
</li>
\n`;
}
2024-11-26 16:05:28 -05:00
html += `
</ol>
<p>Total <span style="color: #888">${nice_size(total.size)}</span> in ${total.count} accounts.</p>
`;
await app.setDocument(html);
}
main().catch(function(e) { print(e); });