46 lines
1.3 KiB
TypeScript
46 lines
1.3 KiB
TypeScript
|
import rndstr from 'rndstr';
|
|||
|
import { Note } from '../../../models/entities/note';
|
|||
|
import { User } from '../../../models/entities/user';
|
|||
|
import { Notes, UserProfiles } from '../../../models';
|
|||
|
import { generateMuteQuery } from './generate-mute-query';
|
|||
|
import { ensure } from '../../../prelude/ensure';
|
|||
|
|
|||
|
// TODO: リアクション、Renote、返信などをしたノートは除外する
|
|||
|
|
|||
|
export async function injectFeatured(timeline: Note[], user?: User | null) {
|
|||
|
if (timeline.length < 5) return;
|
|||
|
|
|||
|
if (user) {
|
|||
|
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
|||
|
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'`)
|
|||
|
.leftJoinAndSelect('note.user', 'user');
|
|||
|
|
|||
|
if (user) generateMuteQuery(query, user);
|
|||
|
|
|||
|
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);
|
|||
|
}
|