mirror of
https://iceshrimp.dev/limepotato/jormungandr-bite.git
synced 2024-11-29 13:27:31 -07:00
Implement recieve moveTo
Untested, hopefully it works.. Signed-off-by: cutestnekoaqua <waterdev@galaxycrow.de>
This commit is contained in:
parent
cfab9ff2ad
commit
db52926594
7 changed files with 100 additions and 12 deletions
|
@ -7,7 +7,7 @@ export async function fetchMeta(noCache = false): Promise<Meta> {
|
||||||
if (!noCache && cache) return cache;
|
if (!noCache && cache) return cache;
|
||||||
|
|
||||||
return await db.transaction(async transactionalEntityManager => {
|
return await db.transaction(async transactionalEntityManager => {
|
||||||
// 過去のバグでレコードが複数出来てしまっている可能性があるので新しいIDを優先する
|
// New IDs are prioritized because multiple records may have been created due to past bugs.
|
||||||
const metas = await transactionalEntityManager.find(Meta, {
|
const metas = await transactionalEntityManager.find(Meta, {
|
||||||
order: {
|
order: {
|
||||||
id: 'DESC',
|
id: 'DESC',
|
||||||
|
@ -20,7 +20,7 @@ export async function fetchMeta(noCache = false): Promise<Meta> {
|
||||||
cache = meta;
|
cache = meta;
|
||||||
return meta;
|
return meta;
|
||||||
} else {
|
} else {
|
||||||
// metaが空のときfetchMetaが同時に呼ばれるとここが同時に呼ばれてしまうことがあるのでフェイルセーフなupsertを使う
|
// If fetchMeta is called at the same time when meta is empty, this part may be called at the same time, so use fail-safe upsert.
|
||||||
const saved = await transactionalEntityManager
|
const saved = await transactionalEntityManager
|
||||||
.upsert(
|
.upsert(
|
||||||
Meta,
|
Meta,
|
||||||
|
|
|
@ -5,7 +5,7 @@ import DbResolver from '../../db-resolver.js';
|
||||||
import { Users } from '@/models/index.js';
|
import { Users } from '@/models/index.js';
|
||||||
|
|
||||||
export default async (actor: CacheableRemoteUser, activity: IBlock): Promise<string> => {
|
export default async (actor: CacheableRemoteUser, activity: IBlock): Promise<string> => {
|
||||||
// ※ activity.objectにブロック対象があり、それは存在するローカルユーザーのはず
|
// ※ There is a block target in activity.object, which should be a local user that exists.
|
||||||
|
|
||||||
const dbResolver = new DbResolver();
|
const dbResolver = new DbResolver();
|
||||||
const blockee = await dbResolver.getUserFromApId(activity.object);
|
const blockee = await dbResolver.getUserFromApId(activity.object);
|
||||||
|
@ -15,7 +15,7 @@ export default async (actor: CacheableRemoteUser, activity: IBlock): Promise<str
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blockee.host != null) {
|
if (blockee.host != null) {
|
||||||
return `skip: ブロックしようとしているユーザーはローカルユーザーではありません`;
|
return `skip: The user you are trying to block is not a local user`;
|
||||||
}
|
}
|
||||||
|
|
||||||
await block(await Users.findOneByOrFail({ id: actor.id }), await Users.findOneByOrFail({ id: blockee.id }));
|
await block(await Users.findOneByOrFail({ id: actor.id }), await Users.findOneByOrFail({ id: blockee.id }));
|
||||||
|
|
|
@ -1,4 +1,23 @@
|
||||||
import { IObject, isCreate, isDelete, isUpdate, isRead, isFollow, isAccept, isReject, isAdd, isRemove, isAnnounce, isLike, isUndo, isBlock, isCollectionOrOrderedCollection, isCollection, isFlag } from '../type.js';
|
import {
|
||||||
|
IObject,
|
||||||
|
isCreate,
|
||||||
|
isDelete,
|
||||||
|
isUpdate,
|
||||||
|
isRead,
|
||||||
|
isFollow,
|
||||||
|
isAccept,
|
||||||
|
isReject,
|
||||||
|
isAdd,
|
||||||
|
isRemove,
|
||||||
|
isAnnounce,
|
||||||
|
isLike,
|
||||||
|
isUndo,
|
||||||
|
isBlock,
|
||||||
|
isCollectionOrOrderedCollection,
|
||||||
|
isCollection,
|
||||||
|
isFlag,
|
||||||
|
isMove
|
||||||
|
} from '../type.js';
|
||||||
import { CacheableRemoteUser } from '@/models/entities/user.js';
|
import { CacheableRemoteUser } from '@/models/entities/user.js';
|
||||||
import create from './create/index.js';
|
import create from './create/index.js';
|
||||||
import performDeleteActivity from './delete/index.js';
|
import performDeleteActivity from './delete/index.js';
|
||||||
|
@ -17,7 +36,7 @@ import flag from './flag/index.js';
|
||||||
import { apLogger } from '../logger.js';
|
import { apLogger } from '../logger.js';
|
||||||
import Resolver from '../resolver.js';
|
import Resolver from '../resolver.js';
|
||||||
import { toArray } from '@/prelude/array.js';
|
import { toArray } from '@/prelude/array.js';
|
||||||
import { Users } from '@/models/index.js';
|
import move from './move/index.js';
|
||||||
|
|
||||||
export async function performActivity(actor: CacheableRemoteUser, activity: IObject) {
|
export async function performActivity(actor: CacheableRemoteUser, activity: IObject) {
|
||||||
if (isCollectionOrOrderedCollection(activity)) {
|
if (isCollectionOrOrderedCollection(activity)) {
|
||||||
|
@ -68,6 +87,8 @@ async function performOneActivity(actor: CacheableRemoteUser, activity: IObject)
|
||||||
await block(actor, activity);
|
await block(actor, activity);
|
||||||
} else if (isFlag(activity)) {
|
} else if (isFlag(activity)) {
|
||||||
await flag(actor, activity);
|
await flag(actor, activity);
|
||||||
|
} else if (isMove(activity)) {
|
||||||
|
await move(actor,activity);
|
||||||
} else {
|
} else {
|
||||||
apLogger.warn(`unrecognized activity type: ${(activity as any).type}`);
|
apLogger.warn(`unrecognized activity type: ${(activity as any).type}`);
|
||||||
}
|
}
|
||||||
|
|
63
packages/backend/src/remote/activitypub/kernel/move/index.ts
Normal file
63
packages/backend/src/remote/activitypub/kernel/move/index.ts
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
import {CacheableRemoteUser, IRemoteUser, User} from '@/models/entities/user.js';
|
||||||
|
import {IMove, IObject, IActor} from '../../type.js';
|
||||||
|
import DbResolver from "@/remote/activitypub/db-resolver";
|
||||||
|
import {getRemoteUser} from '@/server/api/common/getters.js';
|
||||||
|
import { updatePerson } from '@/remote/activitypub/models/person.js';
|
||||||
|
import {Followings, Users} from "@/models";
|
||||||
|
import {makePaginationQuery} from "@/server/api/common/make-pagination-query";
|
||||||
|
import deleteFollowing from '@/services/following/delete.js';
|
||||||
|
import create from '@/services/following/create.js';
|
||||||
|
import {IdentifiableError} from "@/misc/identifiable-error";
|
||||||
|
import {ApiError} from "@/server/api/error";
|
||||||
|
import {meta} from "@/server/api/endpoints/following/create";
|
||||||
|
|
||||||
|
export default async (actor: CacheableRemoteUser, activity: IMove): Promise<string> => {
|
||||||
|
// ※ There is a block target in activity.object, which should be a local user that exists.
|
||||||
|
|
||||||
|
const dbResolver = new DbResolver();
|
||||||
|
let new_acc = await dbResolver.getUserFromApId(activity.target);
|
||||||
|
if (!new_acc) new_acc = await getRemoteUser(<string>activity.target);
|
||||||
|
|
||||||
|
let old_acc = await dbResolver.getUserFromApId(activity.actor);
|
||||||
|
if (!old_acc) new_acc = await getRemoteUser(<string>activity.actor);
|
||||||
|
|
||||||
|
if (!new_acc || new_acc.uri === null) {
|
||||||
|
return `move: new acc not found`;
|
||||||
|
}
|
||||||
|
if (!old_acc || old_acc.uri === null) {
|
||||||
|
return `move: old acc not found`;
|
||||||
|
}
|
||||||
|
await updatePerson(new_acc.uri);
|
||||||
|
await updatePerson(old_acc.uri);
|
||||||
|
new_acc = await getRemoteUser(new_acc.uri);
|
||||||
|
old_acc = await getRemoteUser(old_acc.uri);
|
||||||
|
|
||||||
|
if(old_acc === null || old_acc.uri === null || !new_acc?.alsoKnownAs?.includes(old_acc.uri)) return `move: accounts invalid`;
|
||||||
|
|
||||||
|
old_acc.movedToUri = new_acc?.uri
|
||||||
|
|
||||||
|
const query = makePaginationQuery(Followings.createQueryBuilder('following'))
|
||||||
|
.andWhere('following.followeeId = :userId', { userId: old_acc.id })
|
||||||
|
.innerJoinAndSelect('following.follower', 'follower');
|
||||||
|
|
||||||
|
const followings = await query
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
followings.forEach(following => {
|
||||||
|
if(!following.follower?.host) {
|
||||||
|
let follower = following.follower;
|
||||||
|
deleteFollowing(follower!, old_acc!);
|
||||||
|
try {
|
||||||
|
create(follower!, new_acc!);
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof IdentifiableError) {
|
||||||
|
if (e.id === '710e8fb0-b8c3-4922-be49-d5d93d8e6a6e') throw new ApiError(meta.errors.blocking);
|
||||||
|
if (e.id === '3338392a-f764-498d-8855-db939dcf8c48') throw new ApiError(meta.errors.blocked);
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return `ok`;
|
||||||
|
};
|
|
@ -160,7 +160,7 @@ export interface IActor extends IObject {
|
||||||
alsoKnownAs?: string[];
|
alsoKnownAs?: string[];
|
||||||
discoverable?: boolean;
|
discoverable?: boolean;
|
||||||
inbox: string;
|
inbox: string;
|
||||||
sharedInbox?: string; // 後方互換性のため
|
sharedInbox?: string; // backward compatibility.. ig
|
||||||
publicKey?: {
|
publicKey?: {
|
||||||
id: string;
|
id: string;
|
||||||
publicKeyPem: string;
|
publicKeyPem: string;
|
||||||
|
@ -283,6 +283,7 @@ export interface IFlag extends IActivity {
|
||||||
|
|
||||||
export interface IMove extends IActivity {
|
export interface IMove extends IActivity {
|
||||||
type: 'Move';
|
type: 'Move';
|
||||||
|
target: IObject | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isCreate = (object: IObject): object is ICreate => getApType(object) === 'Create';
|
export const isCreate = (object: IObject): object is ICreate => getApType(object) === 'Create';
|
||||||
|
@ -299,3 +300,4 @@ export const isLike = (object: IObject): object is ILike => getApType(object) ==
|
||||||
export const isAnnounce = (object: IObject): object is IAnnounce => getApType(object) === 'Announce';
|
export const isAnnounce = (object: IObject): object is IAnnounce => getApType(object) === 'Announce';
|
||||||
export const isBlock = (object: IObject): object is IBlock => getApType(object) === 'Block';
|
export const isBlock = (object: IObject): object is IBlock => getApType(object) === 'Block';
|
||||||
export const isFlag = (object: IObject): object is IFlag => getApType(object) === 'Flag';
|
export const isFlag = (object: IObject): object is IFlag => getApType(object) === 'Flag';
|
||||||
|
export const isMove = (object: IObject): object is IMove => getApType(object) === 'Move';
|
||||||
|
|
|
@ -19,7 +19,7 @@ import { genIdenticon } from '@/misc/gen-identicon.js';
|
||||||
import { createTemp } from '@/misc/create-temp.js';
|
import { createTemp } from '@/misc/create-temp.js';
|
||||||
import { publishMainStream } from '@/services/stream.js';
|
import { publishMainStream } from '@/services/stream.js';
|
||||||
import * as Acct from '@/misc/acct.js';
|
import * as Acct from '@/misc/acct.js';
|
||||||
import { envOption } from '../env.js';
|
import { envOption } from '@/env';
|
||||||
import activityPub from './activitypub.js';
|
import activityPub from './activitypub.js';
|
||||||
import nodeinfo from './nodeinfo.js';
|
import nodeinfo from './nodeinfo.js';
|
||||||
import wellKnown from './well-known.js';
|
import wellKnown from './well-known.js';
|
||||||
|
@ -164,5 +164,6 @@ export default () => new Promise(resolve => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
server.listen(config.port, resolve);
|
server.listen(config.port, resolve);
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,11 +11,11 @@ const router = new Router();
|
||||||
const nodeinfo2_1path = '/nodeinfo/2.1';
|
const nodeinfo2_1path = '/nodeinfo/2.1';
|
||||||
const nodeinfo2_0path = '/nodeinfo/2.0';
|
const nodeinfo2_0path = '/nodeinfo/2.0';
|
||||||
|
|
||||||
export const links = [/* (awaiting release) {
|
export const links = [{
|
||||||
rel: 'http://nodeinfo.diaspora.software/ns/schema/2.1',
|
rel: 'https://nodeinfo.diaspora.software/ns/schema/2.1',
|
||||||
href: config.url + nodeinfo2_1path
|
href: config.url + nodeinfo2_1path
|
||||||
}, */{
|
}, {
|
||||||
rel: 'http://nodeinfo.diaspora.software/ns/schema/2.0',
|
rel: 'https://nodeinfo.diaspora.software/ns/schema/2.0',
|
||||||
href: config.url + nodeinfo2_0path,
|
href: config.url + nodeinfo2_0path,
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
@ -96,6 +96,7 @@ router.get(nodeinfo2_1path, async ctx => {
|
||||||
router.get(nodeinfo2_0path, async ctx => {
|
router.get(nodeinfo2_0path, async ctx => {
|
||||||
const base = await cache.fetch(null, () => nodeinfo2());
|
const base = await cache.fetch(null, () => nodeinfo2());
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
delete base.software.repository;
|
delete base.software.repository;
|
||||||
|
|
||||||
ctx.body = { version: '2.0', ...base };
|
ctx.body = { version: '2.0', ...base };
|
||||||
|
|
Loading…
Reference in a new issue