diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2021-11-12 02:02:25 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2021-11-12 02:02:25 +0900 |
| commit | 0e4a111f81cceed275d9bec2695f6e401fb654d8 (patch) | |
| tree | 40874799472fa07416f17b50a398ac33b7771905 /packages/backend/src/server/api/endpoints/federation | |
| parent | update deps (diff) | |
| download | sharkey-0e4a111f81cceed275d9bec2695f6e401fb654d8.tar.gz sharkey-0e4a111f81cceed275d9bec2695f6e401fb654d8.tar.bz2 sharkey-0e4a111f81cceed275d9bec2695f6e401fb654d8.zip | |
refactoring
Resolve #7779
Diffstat (limited to 'packages/backend/src/server/api/endpoints/federation')
7 files changed, 396 insertions, 0 deletions
diff --git a/packages/backend/src/server/api/endpoints/federation/dns.ts b/packages/backend/src/server/api/endpoints/federation/dns.ts new file mode 100644 index 0000000000..7ba566301a --- /dev/null +++ b/packages/backend/src/server/api/endpoints/federation/dns.ts @@ -0,0 +1,43 @@ +import { promises as dns } from 'dns'; +import $ from 'cafy'; +import define from '../../define'; +import { Instances } from '@/models/index'; +import { toPuny } from '@/misc/convert-host'; + +const resolver = new dns.Resolver(); +resolver.setServers(['1.1.1.1']); + +export const meta = { + tags: ['federation'], + + requireCredential: false as const, + + params: { + host: { + validator: $.str + } + }, +}; + +export default define(meta, async (ps, me) => { + const instance = await Instances.findOneOrFail({ host: toPuny(ps.host) }); + + const [ + resolved4, + resolved6, + resolvedCname, + resolvedTxt, + ] = await Promise.all([ + resolver.resolve4(instance.host).catch(() => []), + resolver.resolve6(instance.host).catch(() => []), + resolver.resolveCname(instance.host).catch(() => []), + resolver.resolveTxt(instance.host).catch(() => []), + ]); + + return { + a: resolved4, + aaaa: resolved6, + cname: resolvedCname, + txt: resolvedTxt, + }; +}); diff --git a/packages/backend/src/server/api/endpoints/federation/followers.ts b/packages/backend/src/server/api/endpoints/federation/followers.ts new file mode 100644 index 0000000000..655e7b7b9a --- /dev/null +++ b/packages/backend/src/server/api/endpoints/federation/followers.ts @@ -0,0 +1,51 @@ +import $ from 'cafy'; +import { ID } from '@/misc/cafy-id'; +import define from '../../define'; +import { Followings } from '@/models/index'; +import { makePaginationQuery } from '../../common/make-pagination-query'; + +export const meta = { + tags: ['federation'], + + requireCredential: false as const, + + params: { + host: { + validator: $.str + }, + + sinceId: { + validator: $.optional.type(ID), + }, + + untilId: { + validator: $.optional.type(ID), + }, + + limit: { + validator: $.optional.num.range(1, 100), + default: 10 + }, + }, + + res: { + type: 'array' as const, + optional: false as const, nullable: false as const, + items: { + type: 'object' as const, + optional: false as const, nullable: false as const, + ref: 'Following', + } + }, +}; + +export default define(meta, async (ps, me) => { + const query = makePaginationQuery(Followings.createQueryBuilder('following'), ps.sinceId, ps.untilId) + .andWhere(`following.followeeHost = :host`, { host: ps.host }); + + const followings = await query + .take(ps.limit!) + .getMany(); + + return await Followings.packMany(followings, me, { populateFollowee: true }); +}); diff --git a/packages/backend/src/server/api/endpoints/federation/following.ts b/packages/backend/src/server/api/endpoints/federation/following.ts new file mode 100644 index 0000000000..5b283581a6 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/federation/following.ts @@ -0,0 +1,51 @@ +import $ from 'cafy'; +import { ID } from '@/misc/cafy-id'; +import define from '../../define'; +import { Followings } from '@/models/index'; +import { makePaginationQuery } from '../../common/make-pagination-query'; + +export const meta = { + tags: ['federation'], + + requireCredential: false as const, + + params: { + host: { + validator: $.str + }, + + sinceId: { + validator: $.optional.type(ID), + }, + + untilId: { + validator: $.optional.type(ID), + }, + + limit: { + validator: $.optional.num.range(1, 100), + default: 10 + }, + }, + + res: { + type: 'array' as const, + optional: false as const, nullable: false as const, + items: { + type: 'object' as const, + optional: false as const, nullable: false as const, + ref: 'Following', + } + }, +}; + +export default define(meta, async (ps, me) => { + const query = makePaginationQuery(Followings.createQueryBuilder('following'), ps.sinceId, ps.untilId) + .andWhere(`following.followerHost = :host`, { host: ps.host }); + + const followings = await query + .take(ps.limit!) + .getMany(); + + return await Followings.packMany(followings, me, { populateFollowee: true }); +}); diff --git a/packages/backend/src/server/api/endpoints/federation/instances.ts b/packages/backend/src/server/api/endpoints/federation/instances.ts new file mode 100644 index 0000000000..cf5e44ebd5 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/federation/instances.ts @@ -0,0 +1,149 @@ +import $ from 'cafy'; +import config from '@/config/index'; +import define from '../../define'; +import { Instances } from '@/models/index'; +import { fetchMeta } from '@/misc/fetch-meta'; + +export const meta = { + tags: ['federation'], + + requireCredential: false as const, + + params: { + host: { + validator: $.optional.nullable.str, + }, + + blocked: { + validator: $.optional.nullable.bool, + }, + + notResponding: { + validator: $.optional.nullable.bool, + }, + + suspended: { + validator: $.optional.nullable.bool, + }, + + federating: { + validator: $.optional.nullable.bool, + }, + + subscribing: { + validator: $.optional.nullable.bool, + }, + + publishing: { + validator: $.optional.nullable.bool, + }, + + limit: { + validator: $.optional.num.range(1, 100), + default: 30 + }, + + offset: { + validator: $.optional.num.min(0), + default: 0 + }, + + sort: { + validator: $.optional.str, + } + }, + + res: { + type: 'array' as const, + optional: false as const, nullable: false as const, + items: { + type: 'object' as const, + optional: false as const, nullable: false as const, + ref: 'FederationInstance' + } + } +}; + +export default define(meta, async (ps, me) => { + 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; + case '+driveUsage': query.orderBy('instance.driveUsage', 'DESC'); break; + case '-driveUsage': query.orderBy('instance.driveUsage', 'ASC'); break; + case '+driveFiles': query.orderBy('instance.driveFiles', 'DESC'); break; + case '-driveFiles': query.orderBy('instance.driveFiles', 'ASC'); break; + + default: query.orderBy('instance.id', 'DESC'); break; + } + + if (typeof ps.blocked === 'boolean') { + const meta = await fetchMeta(true); + if (ps.blocked) { + query.andWhere('instance.host IN (:...blocks)', { blocks: meta.blockedHosts }); + } else { + query.andWhere('instance.host NOT IN (:...blocks)', { blocks: meta.blockedHosts }); + } + } + + 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: '%' + ps.host.toLowerCase() + '%' }); + } + + const instances = await query.take(ps.limit!).skip(ps.offset).getMany(); + + return instances; +}); diff --git a/packages/backend/src/server/api/endpoints/federation/show-instance.ts b/packages/backend/src/server/api/endpoints/federation/show-instance.ts new file mode 100644 index 0000000000..f8352aefb3 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/federation/show-instance.ts @@ -0,0 +1,29 @@ +import $ from 'cafy'; +import define from '../../define'; +import { Instances } from '@/models/index'; +import { toPuny } from '@/misc/convert-host'; + +export const meta = { + tags: ['federation'], + + requireCredential: false as const, + + params: { + host: { + validator: $.str + } + }, + + res: { + type: 'object' as const, + optional: false as const, nullable: false as const, + ref: 'FederationInstance' + } +}; + +export default define(meta, async (ps, me) => { + const instance = await Instances + .findOne({ host: toPuny(ps.host) }); + + return instance; +}); diff --git a/packages/backend/src/server/api/endpoints/federation/update-remote-user.ts b/packages/backend/src/server/api/endpoints/federation/update-remote-user.ts new file mode 100644 index 0000000000..580c3cb3d9 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/federation/update-remote-user.ts @@ -0,0 +1,22 @@ +import $ from 'cafy'; +import { ID } from '@/misc/cafy-id'; +import define from '../../define'; +import { getRemoteUser } from '../../common/getters'; +import { updatePerson } from '@/remote/activitypub/models/person'; + +export const meta = { + tags: ['federation'], + + requireCredential: true as const, + + params: { + userId: { + validator: $.type(ID), + }, + } +}; + +export default define(meta, async (ps) => { + const user = await getRemoteUser(ps.userId); + await updatePerson(user.uri!); +}); diff --git a/packages/backend/src/server/api/endpoints/federation/users.ts b/packages/backend/src/server/api/endpoints/federation/users.ts new file mode 100644 index 0000000000..0e35df3e1c --- /dev/null +++ b/packages/backend/src/server/api/endpoints/federation/users.ts @@ -0,0 +1,51 @@ +import $ from 'cafy'; +import { ID } from '@/misc/cafy-id'; +import define from '../../define'; +import { Users } from '@/models/index'; +import { makePaginationQuery } from '../../common/make-pagination-query'; + +export const meta = { + tags: ['federation'], + + requireCredential: false as const, + + params: { + host: { + validator: $.str + }, + + sinceId: { + validator: $.optional.type(ID), + }, + + untilId: { + validator: $.optional.type(ID), + }, + + limit: { + validator: $.optional.num.range(1, 100), + default: 10 + }, + }, + + res: { + type: 'array' as const, + optional: false as const, nullable: false as const, + items: { + type: 'object' as const, + optional: false as const, nullable: false as const, + ref: 'User', + } + }, +}; + +export default define(meta, async (ps, me) => { + const query = makePaginationQuery(Users.createQueryBuilder('user'), ps.sinceId, ps.untilId) + .andWhere(`user.host = :host`, { host: ps.host }); + + const users = await query + .take(ps.limit!) + .getMany(); + + return await Users.packMany(users, me, { detail: true }); +}); |