mizzkey/packages/backend/src/server/api/endpoints/notes/global-timeline.ts
romaboo 054417354c
feat: user-level instance mute (#7712)
* Update ja-JP.yml

* Added settable config for muted instances

* added psql query for removal of muted notes

* Added filtering and trimming for instance mutes

* cleaned up filtering of bad instance mutes and added a refresh at the end for the list on the client

* Added notification & streaming timeline muting

* Updated changelog

* Added missing semicolon

* Apply japanese string suggestions from robflop

Co-authored-by: Robin B. <robflop98@outlook.com>

* Changed Ja-JP instance mute title string to one suggested by sousuke

Co-authored-by: sousuke0422 <sousuke20xx@gmail.com>

* Update ja-JP instanceMuteDescription based on sousuke's suggestion

Co-authored-by: sousuke0422 <sousuke20xx@gmail.com>

* added notification mute

* added notification and note children muting

* Fixed a bug where local notifications were getting filtered on cold start

* Fixed instance mute imports

* Fixed not saving/loading instance mutes

* removed en-US translations for instance mute

* moved instance mute migration to js

* changed settings index back to spaces

* removed destructuring assignment from notification stream in instance mute check call

Co-authored-by: tamaina <tamaina@hotmail.co.jp>

* added .note accessor for checking note data instead of notification data

* changed note to use Packed<'Note'> instead of any and removed usage of snake case

Co-authored-by: tamaina <tamaina@hotmail.co.jp>

* changed notification mute check to check specifically for notification host

* changed to using single quotes

* moved @click to the end for the linter

* revert unnecessary changes

* restored newlines

* whitespace removal

Co-authored-by: syuilo <syuilotan@yahoo.co.jp>
Co-authored-by: Robin B. <robflop98@outlook.com>
Co-authored-by: sousuke0422 <sousuke20xx@gmail.com>
Co-authored-by: puffaboo <emilis@jigglypuff.club>
Co-authored-by: tamaina <tamaina@hotmail.co.jp>
2021-12-09 21:38:56 +09:00

104 lines
2.7 KiB
TypeScript

import $ from 'cafy';
import { ID } from '@/misc/cafy-id';
import define from '../../define';
import { fetchMeta } from '@/misc/fetch-meta';
import { ApiError } from '../../error';
import { makePaginationQuery } from '../../common/make-pagination-query';
import { Notes } from '@/models/index';
import { generateMutedUserQuery } from '../../common/generate-muted-user-query';
import { generateMutedInstanceQuery } from '../../common/generate-muted-instance-query';
import { activeUsersChart } from '@/services/chart/index';
import { generateRepliesQuery } from '../../common/generate-replies-query';
import { generateMutedNoteQuery } from '../../common/generate-muted-note-query';
import { generateBlockedUserQuery } from '../../common/generate-block-query';
export const meta = {
tags: ['notes'],
params: {
withFiles: {
validator: $.optional.bool,
},
limit: {
validator: $.optional.num.range(1, 100),
default: 10
},
sinceId: {
validator: $.optional.type(ID),
},
untilId: {
validator: $.optional.type(ID),
},
sinceDate: {
validator: $.optional.num
},
untilDate: {
validator: $.optional.num
},
},
res: {
type: 'array' as const,
optional: false as const, nullable: false as const,
items: {
type: 'object' as const,
optional: false as const, nullable: false as const,
ref: 'Note',
}
},
errors: {
gtlDisabled: {
message: 'Global timeline has been disabled.',
code: 'GTL_DISABLED',
id: '0332fc13-6ab2-4427-ae80-a9fadffd1a6b'
},
}
};
export default define(meta, async (ps, user) => {
const m = await fetchMeta();
if (m.disableGlobalTimeline) {
if (user == null || (!user.isAdmin && !user.isModerator)) {
throw new ApiError(meta.errors.gtlDisabled);
}
}
//#region Construct query
const query = makePaginationQuery(Notes.createQueryBuilder('note'),
ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
.andWhere('note.visibility = \'public\'')
.andWhere('note.channelId IS NULL')
.innerJoinAndSelect('note.user', 'user')
.leftJoinAndSelect('note.reply', 'reply')
.leftJoinAndSelect('note.renote', 'renote')
.leftJoinAndSelect('reply.user', 'replyUser')
.leftJoinAndSelect('renote.user', 'renoteUser');
generateRepliesQuery(query, user);
if (user) generateMutedUserQuery(query, user);
if (user) generateMutedNoteQuery(query, user);
if (user) generateBlockedUserQuery(query, user);
if (user) generateMutedInstanceQuery(query, user);
if (ps.withFiles) {
query.andWhere('note.fileIds != \'{}\'');
}
//#endregion
const timeline = await query.take(ps.limit!).getMany();
process.nextTick(() => {
if (user) {
activeUsersChart.update(user);
}
});
return await Notes.packMany(timeline, user);
});