feat: show unlisted posts from following users in antennas

This commit is contained in:
naskya 2024-03-01 23:41:55 +09:00
parent 7a78dceb52
commit 412cdad209
No known key found for this signature in database
GPG key ID: 712D413B3A9FED5C
3 changed files with 25 additions and 10 deletions

View file

@ -6,6 +6,7 @@ Critical security updates are indicated by the :warning: icon.
- Introduce new full-text search engine and post search filters
- Refactoring
- Show unlisted posts from following users in antennas (similar to [Fedibird](https://github.com/fedibird/mastodon/tree/fedibird) and [kmyblue](https://github.com/kmycode/mastodon), unlisted posts from people you don't follow won't be shown)
## v20240301

View file

@ -2,12 +2,12 @@ import type { Antenna } from "@/models/entities/antenna.js";
import type { Note } from "@/models/entities/note.js";
import type { User } from "@/models/entities/user.js";
import type { UserProfile } from "@/models/entities/user-profile.js";
import { Blockings, UserProfiles } from "@/models/index.js";
import { Blockings, Followings, UserProfiles } from "@/models/index.js";
import { getFullApAccount } from "@/misc/convert-host.js";
import * as Acct from "@/misc/acct.js";
import { getWordHardMute } from "@/misc/check-word-mute.js";
import type { Packed } from "@/misc/schema.js";
import { Cache } from "@/misc/cache.js";
import { getWordHardMute } from "@/misc/check-word-mute.js";
const blockingCache = new Cache<User["id"][]>("blocking", 60 * 5);
const hardMutesCache = new Cache<{
@ -15,6 +15,7 @@ const hardMutesCache = new Cache<{
mutedWords: UserProfile["mutedWords"];
mutedPatterns: UserProfile["mutedPatterns"];
}>("hardMutes", 60 * 5);
const followingCache = new Cache<User["id"][]>("following", 60 * 5);
export async function checkHitAntenna(
antenna: Antenna,
@ -22,11 +23,10 @@ export async function checkHitAntenna(
noteUser: { id: User["id"]; username: string; host: string | null },
): Promise<boolean> {
if (note.visibility === "specified") return false;
if (note.visibility === "home") return false;
if (!antenna.withReplies && note.replyId != null) return false;
if (antenna.withFile) {
if (note.fileIds && note.fileIds.length === 0) return false;
}
if (!antenna.withReplies && note.replyId != null) return false;
if (antenna.src === "users") {
const accts = antenna.users.map((x) => {
@ -53,14 +53,19 @@ export async function checkHitAntenna(
.map((xs) => xs.filter((x) => x !== ""))
.filter((xs) => xs.length > 0);
let text = `${note.text ?? ""} ${note.cw ?? ""}`;
if (note.files != null)
text += ` ${note.files.map((f) => f.comment ?? "").join(" ")}`;
text = text.trim();
if (keywords.length > 0) {
if (note.text == null) return false;
const matched = keywords.some((and) =>
and.every((keyword) =>
antenna.caseSensitive
? note.text!.includes(keyword)
: note.text!.toLowerCase().includes(keyword.toLowerCase()),
? text.includes(keyword)
: text.toLowerCase().includes(keyword.toLowerCase()),
),
);
@ -78,8 +83,8 @@ export async function checkHitAntenna(
const matched = excludeKeywords.some((and) =>
and.every((keyword) =>
antenna.caseSensitive
? note.text!.includes(keyword)
: note.text!.toLowerCase().includes(keyword.toLowerCase()),
? note.text?.includes(keyword)
: note.text?.toLowerCase().includes(keyword.toLowerCase()),
),
);
@ -94,6 +99,16 @@ export async function checkHitAntenna(
);
if (blockings.includes(antenna.userId)) return false;
if (note.visibility === "followers" || note.visibility === "home") {
const following = await followingCache.fetch(antenna.userId, () =>
Followings.find({
where: { followerId: antenna.userId },
select: ["followeeId"],
}).then((relations) => relations.map((relation) => relation.followeeId)),
);
if (!following.includes(note.userId)) return false;
}
const mutes = await hardMutesCache.fetch(antenna.userId, () =>
UserProfiles.findOneByOrFail({
userId: antenna.userId,

View file

@ -111,8 +111,7 @@ export default define(meta, paramDef, async (ps, user) => {
.leftJoinAndSelect("replyUser.banner", "replyUserBanner")
.leftJoinAndSelect("renote.user", "renoteUser")
.leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar")
.leftJoinAndSelect("renoteUser.banner", "renoteUserBanner")
.andWhere("note.visibility != 'home'");
.leftJoinAndSelect("renoteUser.banner", "renoteUserBanner");
generateVisibilityQuery(query, user);
generateMutedUserQuery(query, user);