Files
FrozenFriendsYume/packages/backend/built/server/api/endpoints/federation/instances.js
T
2026-07-26 18:25:37 +09:00

202 lines
6.0 KiB
JavaScript

import define from "../../define.js";
import { Instances } from "../../../../models/index.js";
import { fetchMeta } from "../../../../misc/fetch-meta.js";
import { sqlLikeEscape } from "../../../../misc/sql-like-escape.js";
export const meta = {
tags: [
"federation"
],
requireCredential: false,
requireCredentialPrivateMode: true,
res: {
type: "array",
optional: false,
nullable: false,
items: {
type: "object",
optional: false,
nullable: false,
ref: "FederationInstance"
}
}
};
export const paramDef = {
type: "object",
properties: {
host: {
type: "string",
nullable: true,
description: "Omit or use `null` to not filter by host."
},
blocked: {
type: "boolean",
nullable: true
},
notResponding: {
type: "boolean",
nullable: true
},
suspended: {
type: "boolean",
nullable: true
},
federating: {
type: "boolean",
nullable: true
},
silenced: {
type: "boolean",
nullable: true
},
subscribing: {
type: "boolean",
nullable: true
},
publishing: {
type: "boolean",
nullable: true
},
limit: {
type: "integer",
minimum: 1,
maximum: 100,
default: 30
},
offset: {
type: "integer",
default: 0
},
sort: {
type: "string"
}
},
required: []
};
export default define(meta, paramDef, async (ps, me)=>{
if (!me) {
ps.blocked = false;
ps.suspended = false;
ps.silenced = false;
}
const query = Instances.createQueryBuilder("instance");
switch(ps.sort){
case "+pubSub":
query.orderBy("instance.followingCount", "DESC").orderBy("instance.followersCount", "DESC");
break;
case "-pubSub":
query.orderBy("instance.followingCount", "ASC").orderBy("instance.followersCount", "ASC");
break;
case "+notes":
query.orderBy("instance.notesCount", "DESC");
break;
case "-notes":
query.orderBy("instance.notesCount", "ASC");
break;
case "+users":
query.orderBy("instance.usersCount", "DESC");
break;
case "-users":
query.orderBy("instance.usersCount", "ASC");
break;
case "+following":
query.orderBy("instance.followingCount", "DESC");
break;
case "-following":
query.orderBy("instance.followingCount", "ASC");
break;
case "+followers":
query.orderBy("instance.followersCount", "DESC");
break;
case "-followers":
query.orderBy("instance.followersCount", "ASC");
break;
case "+caughtAt":
query.orderBy("instance.caughtAt", "DESC");
break;
case "-caughtAt":
query.orderBy("instance.caughtAt", "ASC");
break;
case "+lastCommunicatedAt":
query.orderBy("instance.lastCommunicatedAt", "DESC");
break;
case "-lastCommunicatedAt":
query.orderBy("instance.lastCommunicatedAt", "ASC");
break;
default:
query.orderBy("instance.id", "DESC");
break;
}
if (typeof ps.blocked === "boolean") {
const meta = await fetchMeta(true);
if (ps.blocked) {
if (meta.blockedHosts.length === 0) {
return [];
}
query.andWhere("instance.host IN (:...blocks)", {
blocks: meta.blockedHosts
});
} else if (meta.blockedHosts.length > 0) {
query.andWhere("instance.host NOT IN (:...blocks)", {
blocks: meta.blockedHosts
});
}
}
if (typeof ps.silenced === "boolean") {
const meta = await fetchMeta(true);
if (ps.silenced) {
if (meta.silencedHosts.length === 0) {
return [];
}
query.andWhere("instance.host IN (:...silences)", {
silences: meta.silencedHosts
});
} else if (meta.silencedHosts.length > 0) {
query.andWhere("instance.host NOT IN (:...silences)", {
silences: meta.silencedHosts
});
}
}
if (typeof ps.notResponding === "boolean") {
if (ps.notResponding) {
query.andWhere("instance.isNotResponding = TRUE");
} else {
query.andWhere("instance.isNotResponding = FALSE");
}
}
if (typeof ps.suspended === "boolean") {
if (ps.suspended) {
query.andWhere("instance.isSuspended = TRUE");
} else {
query.andWhere("instance.isSuspended = FALSE");
}
}
if (typeof ps.federating === "boolean") {
if (ps.federating) {
query.andWhere("((instance.followingCount > 0) OR (instance.followersCount > 0))");
} else {
query.andWhere("((instance.followingCount = 0) AND (instance.followersCount = 0))");
}
}
if (typeof ps.subscribing === "boolean") {
if (ps.subscribing) {
query.andWhere("instance.followersCount > 0");
} else {
query.andWhere("instance.followersCount = 0");
}
}
if (typeof ps.publishing === "boolean") {
if (ps.publishing) {
query.andWhere("instance.followingCount > 0");
} else {
query.andWhere("instance.followingCount = 0");
}
}
if (ps.host) {
query.andWhere("instance.host like :host", {
host: `%${sqlLikeEscape(ps.host.toLowerCase())}%`
});
}
const instances = await query.take(ps.limit).skip(ps.offset).getMany();
return await Instances.packMany(instances, me !== null);
});