Fixed 267U.pre2
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
import { IsNull, Not } from "typeorm";
|
||||
import { Followings, Users } from "../../models/index.js";
|
||||
import { deliver } from "../../queue/index.js";
|
||||
import { skippedInstances } from "../../misc/skipped-instances.js";
|
||||
import { apLogger } from "./logger.js";
|
||||
const isFollowers = (recipe)=>recipe.type === "Followers";
|
||||
const isDirect = (recipe)=>recipe.type === "Direct";
|
||||
//#endregion
|
||||
export default class DeliverManager {
|
||||
actor;
|
||||
activity;
|
||||
recipes = [];
|
||||
/**
|
||||
* Constructor
|
||||
* @param actor Actor
|
||||
* @param activity Activity to deliver
|
||||
*/ constructor(actor, activity){
|
||||
this.actor = actor;
|
||||
this.activity = activity;
|
||||
}
|
||||
/**
|
||||
* Add recipe for followers deliver
|
||||
*/ addFollowersRecipe() {
|
||||
const deliver = {
|
||||
type: "Followers"
|
||||
};
|
||||
this.addRecipe(deliver);
|
||||
}
|
||||
/**
|
||||
* Add recipe for direct deliver
|
||||
* @param to To
|
||||
*/ addDirectRecipe(to) {
|
||||
const recipe = {
|
||||
type: "Direct",
|
||||
to
|
||||
};
|
||||
this.addRecipe(recipe);
|
||||
}
|
||||
/**
|
||||
* Add recipe
|
||||
* @param recipe Recipe
|
||||
*/ addRecipe(recipe) {
|
||||
this.recipes.push(recipe);
|
||||
}
|
||||
/**
|
||||
* Execute delivers
|
||||
*/ async execute() {
|
||||
if (!Users.isLocalUser(this.actor)) return;
|
||||
const inboxes = new Set();
|
||||
/*
|
||||
build inbox list
|
||||
|
||||
Process follower recipes first to avoid duplication when processing
|
||||
direct recipes later.
|
||||
*/ if (this.recipes.some((r)=>isFollowers(r))) {
|
||||
// followers deliver
|
||||
// TODO: SELECT DISTINCT ON ("followerSharedInbox") "followerSharedInbox" みたいな問い合わせにすればよりパフォーマンス向上できそう
|
||||
// ただ、sharedInboxがnullなリモートユーザーも稀におり、その対応ができなさそう?
|
||||
const followers = await Followings.find({
|
||||
where: {
|
||||
followeeId: this.actor.id,
|
||||
followerHost: Not(IsNull())
|
||||
},
|
||||
select: {
|
||||
followerSharedInbox: true,
|
||||
followerInbox: true
|
||||
}
|
||||
});
|
||||
for (const following of followers){
|
||||
const inbox = following.followerSharedInbox || following.followerInbox;
|
||||
inboxes.add(inbox);
|
||||
}
|
||||
}
|
||||
this.recipes.filter((recipe)=>// followers recipes have already been processed
|
||||
isDirect(recipe) && // check that shared inbox has not been added yet
|
||||
!(recipe.to.sharedInbox && inboxes.has(recipe.to.sharedInbox)) && // check that they actually have an inbox
|
||||
recipe.to.inbox != null).forEach((recipe)=>inboxes.add(recipe.to.inbox));
|
||||
const instancesToSkip = await skippedInstances(// get (unique) list of hosts
|
||||
Array.from(new Set(Array.from(inboxes).map((inbox)=>{
|
||||
try {
|
||||
return new URL(inbox).host;
|
||||
} catch (e) {
|
||||
apLogger.error(`Invalid inbox URL: ${inbox}`);
|
||||
return null;
|
||||
}
|
||||
}).filter((host)=>host != null))));
|
||||
// deliver
|
||||
for (const inbox of inboxes){
|
||||
// skip instances as indicated
|
||||
try {
|
||||
const host = new URL(inbox).host;
|
||||
if (instancesToSkip.includes(host)) continue;
|
||||
} catch (e) {
|
||||
// skip invalid URLs
|
||||
apLogger.error(`Invalid inbox URL: ${inbox}`);
|
||||
continue;
|
||||
}
|
||||
deliver(this.actor, this.activity, inbox);
|
||||
}
|
||||
}
|
||||
}
|
||||
//#region Utilities
|
||||
/**
|
||||
* Deliver activity to followers
|
||||
* @param activity Activity
|
||||
* @param from Followee
|
||||
*/ export async function deliverToFollowers(actor, activity) {
|
||||
const manager = new DeliverManager(actor, activity);
|
||||
manager.addFollowersRecipe();
|
||||
await manager.execute();
|
||||
}
|
||||
/**
|
||||
* Deliver activity to user
|
||||
* @param activity Activity
|
||||
* @param to Target user
|
||||
*/ export async function deliverToUser(actor, activity, to) {
|
||||
const manager = new DeliverManager(actor, activity);
|
||||
manager.addDirectRecipe(to);
|
||||
await manager.execute();
|
||||
} //#endregion
|
||||
Reference in New Issue
Block a user