misskey/packages/backend/src/server/api/common/inject-featured.ts

57 lines
1.7 KiB
TypeScript
Raw Normal View History

2020-02-18 11:05:11 +01:00
import rndstr from 'rndstr';
import { Note } from '@/models/entities/note.js';
import { User } from '@/models/entities/user.js';
import { Notes, UserProfiles, NoteReactions } from '@/models/index.js';
import { generateMutedUserQuery } from './generate-muted-user-query.js';
import { generateBlockedUserQuery } from './generate-block-query.js';
2020-02-18 11:05:11 +01:00
// TODO: リアクション、Renote、返信などをしたートは除外する
export async function injectFeatured(timeline: Note[], user?: User | null) {
if (timeline.length < 5) return;
if (user) {
2021-02-13 07:33:38 +01:00
const profile = await UserProfiles.findOneOrFail(user.id);
2020-02-18 11:05:11 +01:00
if (!profile.injectFeaturedNote) return;
}
const max = 30;
const day = 1000 * 60 * 60 * 24 * 3; // 3日前まで
const query = Notes.createQueryBuilder('note')
.addSelect('note.score')
.where('note.userHost IS NULL')
.andWhere(`note.score > 0`)
.andWhere(`note.createdAt > :date`, { date: new Date(Date.now() - day) })
.andWhere(`note.visibility = 'public'`)
2021-03-21 04:33:37 +01:00
.innerJoinAndSelect('note.user', 'user');
2020-02-18 11:05:11 +01:00
2020-02-21 22:49:12 +01:00
if (user) {
query.andWhere('note.userId != :userId', { userId: user.id });
2020-07-28 02:38:41 +02:00
generateMutedUserQuery(query, user);
generateBlockedUserQuery(query, user);
2020-02-20 05:38:40 +01:00
2020-02-21 22:49:12 +01:00
const reactionQuery = NoteReactions.createQueryBuilder('reaction')
.select('reaction.noteId')
.where('reaction.userId = :userId', { userId: user.id });
query.andWhere(`note.id NOT IN (${ reactionQuery.getQuery() })`);
}
2020-02-18 11:05:11 +01:00
const notes = await query
.orderBy('note.score', 'DESC')
.take(max)
.getMany();
if (notes.length === 0) return;
// Pick random one
const featured = notes[Math.floor(Math.random() * notes.length)];
(featured as any)._featuredId_ = rndstr('a-z0-9', 8);
// Inject featured
timeline.splice(3, 0, featured);
}