mastodonCzStats/mastodonCzStats.js
Jan Andrle 91993f5c06 🎉
Signed-off-by: Jan Andrle <andrle.jan@centrum.cz>
2023-08-01 13:28:28 +02:00

98 lines
3.2 KiB
JavaScript

#!/usr/bin/env nodejsscript
/* jshint esversion: 11,-W097, -W040, module: true, node: true, expr: true, undef: true *//* global echo, $, pipe, s, fetch, cyclicLoop */
const instances_cz_pre= new Set([
"mastodonczech.cz",
"mastodon.arch-linux.cz",
"nasface.cz",
"witter.cz",
"cztwitter.cz",
"mastodon.pirati.cz",
"gomastodon.cz",
"f.cz",
"toot.whatever.cz",
"mastodon.macsnet.cz",
"lgbtcz.social",
"kompost.cz",
"boskovice.social",
"propulse.club",
"mastodon.1984.cz",
"mastodon.rozhlas.cz",
"fediverse.cz",
"mastodon.queerclub.cz",
"mastodon.urbancloud.cz",
"kocour.club",
"mastodon.telekomunikace.cz",
"ajtaci.club",
"mastodon.darksheep.social",
"social.filik.eu",
"social.meyer.cz",
"mastodon.posvic.cz",
"mastodon.starnet.cz",
"blogator.com",
"hatedon.1984.cz",
"mastodon.loutaci.cz",
"social.gwei.cz",
"mastodon.vyboh.net",
"mastodon.skorpil.cz",
"mastodon.hinata.cz",
"social.toxwat.cz",
"spondr.cz",
"hlidacstatu.social",
"mastodon.train.cz",
"social.bobek.cz",
"social.blep.cz",
"mastodon.kickme.cz",
"mastodon.starlink.cz",
"mastodon.kiklhorn.cz",
"mastodon.haxo.cz",
"mutant.cz",
"masto.den1.cz",
"mastodon.gmb.cz",
"rodina-sucha.cz",
"social.taborsky.cz",
]);
const timeOut= (l= 500)=> AbortSignal.timeout(l);
(async function main(){
let stats= [];
for(const instance of instances_cz_pre){
echo.use("-R", "Shromažďuji instance: " + instance);
const peers= await fetch("https://"+instance+"/api/v1/instance/peers", { signal: timeOut() })
.then(res=> res.json()).catch(()=> []);
if(peers && Array.isArray(peers))
peers.filter(i=> i.endsWith(".cz")).forEach(i=> instances_cz_pre.add(i));
}
const instances_cz= Array.from(instances_cz_pre);
const { length }= instances_cz;
for await(const data of collectStats(instances_cz, 4)){
echo.use("-R", "Shromažďuji data za instance: " + instances_cz.indexOf(data.instance)+"/"+length+": "+data.instance);
stats.push(data);
}
const out= {
instances_cz: stats.sort((a, b)=> b.registrations-a.registrations),
sum: stats.reduce((acc, stats) => sumStats([acc, stats]), { statuses: 0, logins: 0, registrations: 0, mau: 0, user_count: 0 })
};
echo(JSON.stringify(out, null, " ")).to("./mastodonCzStats.json");
$.exit(0);
})();
async function* collectStats(instances, weeks = 1) {
for(const instance of instances){
const { stats, mau, user_count }= await fetchInstanceStats(instance).catch(e=> ({}));
if(!stats || !Array.isArray(stats)) continue;
yield { instance, mau, user_count, ...sumStats(stats.slice(0, weeks + 1)) };
}
}
function sumStats(arr) {
const out= Object.keys(arr[0]).reduce((acc, curr)=> (acc[curr]= 0, acc), {});
for (const key of Object.keys(out))
for (const s of arr) out[key]+= Number(s[key]);
return out;
}
async function fetchInstanceStats(instance) {
const url_main= "https://" + instance + "/api/";
const stats= await fetch(url_main+"v1/instance/activity", { signal: timeOut() }).then(res=> res.json());
const { usage: { users } }= await fetch(url_main+"v2/instance", { signal: timeOut() }).then(res=> res.json());
const { stats: { user_count } }= await fetch(url_main+"v1/instance", { signal: timeOut() }).then(res=> res.json());
return { instance, stats, mau: users.active_month, user_count };
}