2024-06-28 14:11:01 +02:00
|
|
|
|
#!/usr/bin/env -S npx nodejsscript
|
2023-08-01 13:28:28 +02:00
|
|
|
|
/* jshint esversion: 11,-W097, -W040, module: true, node: true, expr: true, undef: true *//* global echo, $, pipe, s, fetch, cyclicLoop */
|
2024-06-28 14:11:01 +02:00
|
|
|
|
const store= "./mastodonCzStats.json";
|
|
|
|
|
const instances_cz_pre= new Set(s.cat(store).xargs(JSON.parse).instances_cz.map(i=> i.instance));
|
|
|
|
|
const { version, description }= s.cat("package.json").xargs(JSON.parse);
|
2023-08-01 13:28:28 +02:00
|
|
|
|
const timeOut= (l= 500)=> AbortSignal.timeout(l);
|
2024-06-28 14:11:01 +02:00
|
|
|
|
|
|
|
|
|
$.api("", true)
|
|
|
|
|
.version(version)
|
|
|
|
|
.describe(description)
|
|
|
|
|
.option("--git", "Commit changes to git")
|
|
|
|
|
.action(async function main({ git: is_git }){
|
2023-08-01 13:28:28 +02:00
|
|
|
|
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 })
|
|
|
|
|
};
|
2024-08-01 16:55:14 +02:00
|
|
|
|
if(is_git) s.run`git pull --rebase`;
|
2024-06-28 14:11:01 +02:00
|
|
|
|
echo(JSON.stringify(out, null, " ")).to(store);
|
|
|
|
|
if(is_git) gitCommit([ store ], "cron");
|
2023-08-01 13:28:28 +02:00
|
|
|
|
$.exit(0);
|
2024-06-28 14:11:01 +02:00
|
|
|
|
})
|
|
|
|
|
.parse();
|
2023-08-01 13:28:28 +02:00
|
|
|
|
|
2024-06-28 14:11:01 +02:00
|
|
|
|
function gitCommit(files, des= "not specified"){
|
|
|
|
|
if(!files.length || !s.run`git diff --numstat`.trim())
|
|
|
|
|
return echo("Nothig todo");
|
|
|
|
|
|
|
|
|
|
echo("Diff to save");
|
|
|
|
|
s.run`git config user.name "Bot"`;
|
|
|
|
|
s.run`git config user.email "${"zc.murtnec@naj.elrdna".split("").reverse().join("")}"`;
|
|
|
|
|
s.run`git add ${files}`;
|
|
|
|
|
s.run`git commit -m "Updated by bot – ${des}"`;
|
|
|
|
|
s.run`git push`;
|
|
|
|
|
s.run`git config --remove-section user`;
|
|
|
|
|
}
|
2023-08-01 13:28:28 +02:00
|
|
|
|
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 };
|
|
|
|
|
}
|