mirror of
https://iceshrimp.dev/iceshrimp/iceshrimp
synced 2024-12-02 00:38:08 +09:00
fix remote move queue
This commit is contained in:
parent
d39d7827c0
commit
635290bd33
@ -60,12 +60,24 @@ const birthdaySchema = { type: 'string', pattern: /^([0-9]{4})-([0-9]{2})-([0-9]
|
||||
|
||||
function isLocalUser(user: User): user is ILocalUser;
|
||||
function isLocalUser<T extends { host: User['host'] }>(user: T): user is T & { host: null; };
|
||||
/**
|
||||
* Returns true if the user is local.
|
||||
*
|
||||
* @param user The user to check.
|
||||
* @returns True if the user is local.
|
||||
*/
|
||||
function isLocalUser(user: User | { host: User['host'] }): boolean {
|
||||
return user.host == null;
|
||||
}
|
||||
|
||||
function isRemoteUser(user: User): user is IRemoteUser;
|
||||
function isRemoteUser<T extends { host: User['host'] }>(user: T): user is T & { host: string; };
|
||||
/**
|
||||
* Returns true if the user is remote.
|
||||
*
|
||||
* @param user The user to check.
|
||||
* @returns True if the user is remote.
|
||||
*/
|
||||
function isRemoteUser(user: User | { host: User['host'] }): boolean {
|
||||
return !isLocalUser(user);
|
||||
}
|
||||
|
@ -12,27 +12,44 @@ import { ApiError } from '@/server/api/error.js';
|
||||
import { meta } from '@/server/api/endpoints/following/create.js';
|
||||
import { IObject, IActor } from '../../type.js';
|
||||
import type { IMove } from '../../type.js';
|
||||
import Resolver from '@/remote/activitypub/resolver.js';
|
||||
|
||||
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();
|
||||
const resolver = new Resolver();
|
||||
let new_acc = await dbResolver.getUserFromApId(activity.target);
|
||||
if (!new_acc) new_acc = await getRemoteUser(<string>activity.target);
|
||||
let actor_new;
|
||||
let actor_old;
|
||||
if (!new_acc) actor_new = await resolver.resolve(<string>activity.target) as IActor;
|
||||
|
||||
let old_acc = await dbResolver.getUserFromApId(activity.actor);
|
||||
if (!old_acc) new_acc = await getRemoteUser(<string>activity.actor);
|
||||
let old_acc = actor;
|
||||
if (!old_acc) actor_old = await resolver.resolve(<string>activity.actor) as IActor;
|
||||
|
||||
if (!new_acc || new_acc.uri === null) {
|
||||
if ((!new_acc || new_acc.uri === null) && (!actor_new || actor_new.id === null)) {
|
||||
return 'move: new acc not found';
|
||||
}
|
||||
if (!old_acc || old_acc.uri === null) {
|
||||
if ((!old_acc || old_acc.uri === null) && (!actor_old || actor_old.id === 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);
|
||||
|
||||
let newUri: string | null | undefined
|
||||
let oldUri: string | null | undefined
|
||||
newUri = new_acc ? new_acc.uri :
|
||||
actor_new?.url?.toString();
|
||||
|
||||
oldUri = old_acc ? old_acc.uri :
|
||||
actor_old?.url?.toString();
|
||||
|
||||
if(newUri === null || newUri === undefined) return 'move: new acc not found #2';
|
||||
if(oldUri === null || oldUri === undefined) return 'move: old acc not found #2';
|
||||
|
||||
await updatePerson(newUri);
|
||||
await updatePerson(oldUri);
|
||||
|
||||
new_acc = await getRemoteUser(newUri);
|
||||
old_acc = await getRemoteUser(oldUri);
|
||||
|
||||
if (old_acc === null || old_acc.uri === null || !new_acc.alsoKnownAs?.includes(old_acc.uri)) return 'move: accounts invalid';
|
||||
|
||||
@ -45,18 +62,18 @@ export default async (actor: CacheableRemoteUser, activity: IMove): Promise<stri
|
||||
const followings = await query
|
||||
.getMany();
|
||||
|
||||
followings.forEach(following => {
|
||||
if (!following.follower?.host) {
|
||||
followings.forEach(async following => {
|
||||
if (following.follower?.host) {
|
||||
const follower = following.follower;
|
||||
deleteFollowing(follower!, old_acc!);
|
||||
await deleteFollowing(follower!, old_acc!);
|
||||
try {
|
||||
create(follower!, new_acc!);
|
||||
await 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);
|
||||
if (e.id === '710e8fb0-b8c3-4922-be49-d5d93d8e6a6e') return meta.errors.blocking;
|
||||
if (e.id === '3338392a-f764-498d-8855-db939dcf8c48') return meta.errors.blocked;
|
||||
}
|
||||
throw e;
|
||||
return e;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -279,21 +279,21 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us
|
||||
}
|
||||
|
||||
/**
|
||||
* Personの情報を更新します。
|
||||
* Misskeyに対象のPersonが登録されていなければ無視します。
|
||||
* Update Person data from remote.
|
||||
* If the target Person is not registered in Calckey, it is ignored.
|
||||
* @param uri URI of Person
|
||||
* @param resolver Resolver
|
||||
* @param hint Hint of Person object (この値が正当なPersonの場合、Remote resolveをせずに更新に利用します)
|
||||
* @param hint Hint of Person object (If this value is a valid Person, it is used for updating without Remote resolve)
|
||||
*/
|
||||
export async function updatePerson(uri: string, resolver?: Resolver | null, hint?: IObject): Promise<void> {
|
||||
if (typeof uri !== 'string') throw new Error('uri is not string');
|
||||
|
||||
// URIがこのサーバーを指しているならスキップ
|
||||
// Skip if the URI points to this server
|
||||
if (uri.startsWith(config.url + '/')) {
|
||||
return;
|
||||
}
|
||||
|
||||
//#region このサーバーに既に登録されているか
|
||||
//#region Already registered on this server?
|
||||
const exist = await Users.findOneBy({ uri }) as IRemoteUser;
|
||||
|
||||
if (exist == null) {
|
||||
@ -309,7 +309,7 @@ export async function updatePerson(uri: string, resolver?: Resolver | null, hint
|
||||
|
||||
logger.info(`Updating the Person: ${person.id}`);
|
||||
|
||||
// アバターとヘッダー画像をフェッチ
|
||||
// Fetch avatar and header image
|
||||
const [avatar, banner] = await Promise.all([
|
||||
person.icon,
|
||||
person.image,
|
||||
@ -319,7 +319,7 @@ export async function updatePerson(uri: string, resolver?: Resolver | null, hint
|
||||
: resolveImage(exist, img).catch(() => null),
|
||||
));
|
||||
|
||||
// カスタム絵文字取得
|
||||
// Custom pictogram acquisition
|
||||
const emojis = await extractEmojis(person.tag || [], exist.host).catch(e => {
|
||||
logger.info(`extractEmojis: ${e}`);
|
||||
return [] as Emoji[];
|
||||
@ -378,10 +378,10 @@ export async function updatePerson(uri: string, resolver?: Resolver | null, hint
|
||||
|
||||
publishInternalEvent('remoteUserUpdated', { id: exist.id });
|
||||
|
||||
// ハッシュタグ更新
|
||||
// Hashtag Update
|
||||
updateUsertags(exist, tags);
|
||||
|
||||
// 該当ユーザーが既にフォロワーになっていた場合はFollowingもアップデートする
|
||||
// If the user in question is a follower, followers will also be updated.
|
||||
await Followings.update({
|
||||
followerId: exist.id,
|
||||
}, {
|
||||
@ -392,15 +392,15 @@ export async function updatePerson(uri: string, resolver?: Resolver | null, hint
|
||||
}
|
||||
|
||||
/**
|
||||
* Personを解決します。
|
||||
* Resolve Person.
|
||||
*
|
||||
* Misskeyに対象のPersonが登録されていればそれを返し、そうでなければ
|
||||
* リモートサーバーからフェッチしてMisskeyに登録しそれを返します。
|
||||
* If the target person is registered in Calckey, it returns it;
|
||||
* otherwise, it fetches it from the remote server, registers it in Calckey, and returns it.
|
||||
*/
|
||||
export async function resolvePerson(uri: string, resolver?: Resolver): Promise<CacheableUser> {
|
||||
if (typeof uri !== 'string') throw new Error('uri is not string');
|
||||
|
||||
//#region このサーバーに既に登録されていたらそれを返す
|
||||
//#region If already registered on this server, return it.
|
||||
const exist = await fetchPerson(uri);
|
||||
|
||||
if (exist) {
|
||||
@ -408,7 +408,7 @@ export async function resolvePerson(uri: string, resolver?: Resolver): Promise<C
|
||||
}
|
||||
//#endregion
|
||||
|
||||
// リモートサーバーからフェッチしてきて登録
|
||||
// Fetched from remote server and registered
|
||||
if (resolver == null) resolver = new Resolver();
|
||||
return await createPerson(uri, resolver);
|
||||
}
|
||||
@ -486,14 +486,14 @@ export async function updateFeatured(userId: User['id'], resolver?: Resolver) {
|
||||
// Resolve and regist Notes
|
||||
const limit = promiseLimit<Note | null>(2);
|
||||
const featuredNotes = await Promise.all(items
|
||||
.filter(item => getApType(item) === 'Note') // TODO: Noteでなくてもいいかも
|
||||
.filter(item => getApType(item) === 'Note') // TODO: Maybe it doesn't have to be a Note.
|
||||
.slice(0, 5)
|
||||
.map(item => limit(() => resolveNote(item, resolver))));
|
||||
|
||||
await db.transaction(async transactionalEntityManager => {
|
||||
await transactionalEntityManager.delete(UserNotePining, { userId: user.id });
|
||||
|
||||
// とりあえずidを別の時間で生成して順番を維持
|
||||
// For now, generate the id at a different time and maintain the order.
|
||||
let td = 0;
|
||||
for (const note of featuredNotes.filter(note => note != null)) {
|
||||
td -= 1000;
|
||||
|
@ -61,7 +61,7 @@ export default async (ctx: Router.RouterContext) => {
|
||||
followerId: user.id,
|
||||
} as FindOptionsWhere<Following>;
|
||||
|
||||
// カーソルが指定されている場合
|
||||
// If a cursor is specified
|
||||
if (cursor) {
|
||||
query.id = LessThan(cursor);
|
||||
}
|
||||
@ -73,7 +73,7 @@ export default async (ctx: Router.RouterContext) => {
|
||||
order: { id: -1 },
|
||||
});
|
||||
|
||||
// 「次のページ」があるかどうか
|
||||
// Whether there is a "next page" or not
|
||||
const inStock = followings.length === limit + 1;
|
||||
if (inStock) followings.pop();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user