suppress notification from silenced users and instances

This commit is contained in:
Namekuji 2023-04-30 20:22:50 -04:00
parent 9535bbcf89
commit 784f632b99
No known key found for this signature in database
GPG key ID: B541BD6E646CABC7
4 changed files with 35 additions and 35 deletions

View file

@ -6,11 +6,13 @@ import {
NoteThreadMutings, NoteThreadMutings,
UserProfiles, UserProfiles,
Users, Users,
Followings,
} from "@/models/index.js"; } from "@/models/index.js";
import { genId } from "@/misc/gen-id.js"; import { genId } from "@/misc/gen-id.js";
import type { User } from "@/models/entities/user.js"; import type { User } from "@/models/entities/user.js";
import type { Notification } from "@/models/entities/notification.js"; import type { Notification } from "@/models/entities/notification.js";
import { sendEmailNotification } from "./send-email-notification.js"; import { sendEmailNotification } from "./send-email-notification.js";
import { shouldSilenceInstance } from "@/misc/should-block-instance.js";
export async function createNotification( export async function createNotification(
notifieeId: User["id"], notifieeId: User["id"],
@ -21,6 +23,26 @@ export async function createNotification(
return null; return null;
} }
if (
data.notifierId &&
["mention", "reply", "renote", "quote", "reaction"].includes(type)
) {
const notifier = await Users.findOneBy({ id: data.notifierId });
// suppress if the notifier does not exist or is silenced.
if (!notifier) return null;
// suppress if the notifier is silenced or in a silenced instance, and not followed by the notifiee.
if (
(notifier.isSilenced ||
(Users.isRemoteUser(notifier) &&
(await shouldSilenceInstance(notifier.host)))) &&
!(await Followings.exist({
where: { followerId: notifieeId, followeeId: data.notifierId },
}))
)
return null;
}
const profile = await UserProfiles.findOneBy({ userId: notifieeId }); const profile = await UserProfiles.findOneBy({ userId: notifieeId });
const isMuted = profile?.mutingNotificationTypes.includes(type); const isMuted = profile?.mutingNotificationTypes.includes(type);

View file

@ -80,7 +80,13 @@ export default async function (
} }
if (Users.isLocalUser(follower) && Users.isRemoteUser(followee)) { if (Users.isLocalUser(follower) && Users.isRemoteUser(followee)) {
const content = renderActivity(renderFollow(follower, followee, requestId ?? `${config.url}/follows/${followRequest.id}`)); const content = renderActivity(
renderFollow(
follower,
followee,
requestId ?? `${config.url}/follows/${followRequest.id}`,
),
);
deliver(follower, content, followee.inbox); deliver(follower, content, followee.inbox);
} }
} }

View file

@ -205,11 +205,12 @@ export default async (
data.visibility = "home"; data.visibility = "home";
} }
const inSilencedInstance =
Users.isRemoteUser(user) && (await shouldSilenceInstance(user.host));
// Enforce home visibility if the user is in a silenced instance. // Enforce home visibility if the user is in a silenced instance.
if (data.visibility === "public" && inSilencedInstance) { if (
data.visibility === "public" &&
Users.isRemoteUser(user) &&
(await shouldSilenceInstance(user.host))
) {
data.visibility = "home"; data.visibility = "home";
} }
@ -317,16 +318,6 @@ export default async (
} }
} }
// Remove from mention the local users who aren't following the remote user in the silenced instance.
if (inSilencedInstance) {
const relations = await Followings.findBy([
{ followeeId: user.id, followerHost: IsNull() }, // a local user following the silenced user
]).then((rels) => rels.map((rel) => rel.followerId));
mentionedUsers = mentionedUsers.filter((mentioned) =>
relations.includes(mentioned.id),
);
}
const note = await insertNote(user, data, tags, emojis, mentionedUsers); const note = await insertNote(user, data, tags, emojis, mentionedUsers);
res(note); res(note);

View file

@ -12,7 +12,6 @@ import {
Notes, Notes,
Emojis, Emojis,
Blockings, Blockings,
Followings,
} from "@/models/index.js"; } from "@/models/index.js";
import { IsNull, Not } from "typeorm"; import { IsNull, Not } from "typeorm";
import { perUserReactionsChart } from "@/services/chart/index.js"; import { perUserReactionsChart } from "@/services/chart/index.js";
@ -22,7 +21,6 @@ import deleteReaction from "./delete.js";
import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js"; import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js";
import type { NoteReaction } from "@/models/entities/note-reaction.js"; import type { NoteReaction } from "@/models/entities/note-reaction.js";
import { IdentifiableError } from "@/misc/identifiable-error.js"; import { IdentifiableError } from "@/misc/identifiable-error.js";
import { shouldSilenceInstance } from "@/misc/should-block-instance.js";
export default async ( export default async (
user: { id: User["id"]; host: User["host"] }, user: { id: User["id"]; host: User["host"] },
@ -121,24 +119,7 @@ export default async (
}); });
// Create notification if the reaction target is a local user. // Create notification if the reaction target is a local user.
if ( if (note.userHost === null) {
note.userHost === null &&
// if a local user reacted, or
(Users.isLocalUser(user) ||
// if a remote user not in a silenced instance reacted
(Users.isRemoteUser(user) &&
// if a remote user is in a silenced instance and the target is a local follower.
!(
(await shouldSilenceInstance(user.host)) &&
!(await Followings.exist({
where: {
followerId: note.userId,
followerHost: IsNull(),
followeeId: user.id,
},
}))
)))
) {
createNotification(note.userId, "reaction", { createNotification(note.userId, "reaction", {
notifierId: user.id, notifierId: user.id,
note: note, note: note,