mirror of
https://codeberg.org/yeentown/barkey.git
synced 2025-07-07 20:44:34 +00:00
more QueryService fixes
This commit is contained in:
parent
7ab5ce1537
commit
15ebb0ef85
1 changed files with 178 additions and 114 deletions
|
@ -7,10 +7,11 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { Brackets, Not, WhereExpressionBuilder } from 'typeorm';
|
import { Brackets, Not, WhereExpressionBuilder } from 'typeorm';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import type { MiUser } from '@/models/User.js';
|
import type { MiUser } from '@/models/User.js';
|
||||||
import type { UserProfilesRepository, FollowingsRepository, ChannelFollowingsRepository, BlockingsRepository, NoteThreadMutingsRepository, MutingsRepository, RenoteMutingsRepository, MiMeta, InstancesRepository, MiInstance } from '@/models/_.js';
|
import { MiInstance } from '@/models/Instance.js';
|
||||||
|
import type { UserProfilesRepository, FollowingsRepository, ChannelFollowingsRepository, BlockingsRepository, NoteThreadMutingsRepository, MutingsRepository, RenoteMutingsRepository, MiMeta, InstancesRepository } from '@/models/_.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { IdService } from '@/core/IdService.js';
|
import { IdService } from '@/core/IdService.js';
|
||||||
import type { SelectQueryBuilder, FindOptionsWhere, ObjectLiteral } from 'typeorm';
|
import type { SelectQueryBuilder, ObjectLiteral } from 'typeorm';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class QueryService {
|
export class QueryService {
|
||||||
|
@ -79,32 +80,31 @@ export class QueryService {
|
||||||
// 投稿の作者にブロックされていない かつ
|
// 投稿の作者にブロックされていない かつ
|
||||||
// 投稿の返信先の作者にブロックされていない かつ
|
// 投稿の返信先の作者にブロックされていない かつ
|
||||||
// 投稿の引用元の作者にブロックされていない
|
// 投稿の引用元の作者にブロックされていない
|
||||||
return this.excludeBlockingUser(q, 'note.userId', ':meId')
|
return this
|
||||||
.andWhere(new Brackets(qb => {
|
.andNotBlockingUser(q, 'note.userId', ':meId')
|
||||||
this.excludeBlockingUser(qb, 'note.replyUserId', ':meId', 'orWhere')
|
.andWhere(new Brackets(qb => this
|
||||||
.orWhere('note.replyUserId IS NULL');
|
.orNotBlockingUser(qb, 'note.replyUserId', ':meId')
|
||||||
}))
|
.orWhere('note.replyUserId IS NULL')))
|
||||||
.andWhere(new Brackets(qb => {
|
.andWhere(new Brackets(qb => this
|
||||||
this.excludeBlockingUser(qb, 'note.renoteUserId', ':meId', 'orWhere')
|
.orNotBlockingUser(qb, 'note.renoteUserId', ':meId')
|
||||||
.orWhere('note.renoteUserId IS NULL');
|
.orWhere('note.renoteUserId IS NULL')))
|
||||||
}))
|
|
||||||
.setParameters({ meId: me.id });
|
.setParameters({ meId: me.id });
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public generateBlockQueryForUsers<E extends ObjectLiteral>(q: SelectQueryBuilder<E>, me: { id: MiUser['id'] }): SelectQueryBuilder<E> {
|
public generateBlockQueryForUsers<E extends ObjectLiteral>(q: SelectQueryBuilder<E>, me: { id: MiUser['id'] }): SelectQueryBuilder<E> {
|
||||||
this.excludeBlockingUser(q, ':meId', 'user.id');
|
this.andNotBlockingUser(q, ':meId', 'user.id');
|
||||||
this.excludeBlockingUser(q, 'user.id', ':me.id');
|
this.andNotBlockingUser(q, 'user.id', ':me.id');
|
||||||
return q.setParameters({ meId: me.id });
|
return q.setParameters({ meId: me.id });
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public generateMutedNoteThreadQuery<E extends ObjectLiteral>(q: SelectQueryBuilder<E>, me: { id: MiUser['id'] }): SelectQueryBuilder<E> {
|
public generateMutedNoteThreadQuery<E extends ObjectLiteral>(q: SelectQueryBuilder<E>, me: { id: MiUser['id'] }): SelectQueryBuilder<E> {
|
||||||
return this.excludeMutingThread(q, ':meId', 'note.id')
|
return this
|
||||||
.andWhere(new Brackets(qb => {
|
.andNotMutingThread(q, ':meId', 'note.id')
|
||||||
this.excludeMutingThread(qb, ':meId', 'note.threadId', 'orWhere')
|
.andWhere(new Brackets(qb => this
|
||||||
.orWhere('note.threadId IS NULL');
|
.orNotMutingThread(qb, ':meId', 'note.threadId')
|
||||||
}))
|
.orWhere('note.threadId IS NULL')))
|
||||||
.setParameters({ meId: me.id });
|
.setParameters({ meId: me.id });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,33 +113,32 @@ export class QueryService {
|
||||||
// 投稿の作者をミュートしていない かつ
|
// 投稿の作者をミュートしていない かつ
|
||||||
// 投稿の返信先の作者をミュートしていない かつ
|
// 投稿の返信先の作者をミュートしていない かつ
|
||||||
// 投稿の引用元の作者をミュートしていない
|
// 投稿の引用元の作者をミュートしていない
|
||||||
this.excludeMutingUser(q, ':meId', 'note.userId', 'andWhere', exclude)
|
return this
|
||||||
.andWhere(new Brackets(qb => {
|
.andNotMutingUser(q, ':meId', 'note.userId', exclude)
|
||||||
this.excludeMutingUser(qb, ':meId', 'note.replyUserId', 'orWhere', exclude)
|
.andWhere(new Brackets(qb => this
|
||||||
.orWhere('note.replyUserId IS NULL');
|
.orNotMutingUser(qb, ':meId', 'note.replyUserId', exclude)
|
||||||
}))
|
.orWhere('note.replyUserId IS NULL')))
|
||||||
.andWhere(new Brackets(qb => {
|
.andWhere(new Brackets(qb => this
|
||||||
this.excludeMutingUser(qb, ':meId', 'note.renoteUserId', 'orWhere', exclude)
|
.orNotMutingUser(qb, ':meId', 'note.renoteUserId', exclude)
|
||||||
.orWhere('note.renoteUserId IS NULL');
|
.orWhere('note.renoteUserId IS NULL')))
|
||||||
}));
|
// TODO exclude should also pass a host to skip these instances
|
||||||
|
// mute instances
|
||||||
// mute instances
|
.andWhere(new Brackets(qb => this
|
||||||
this.excludeMutingInstance(q, ':meId', 'note.userHost', 'andWhere')
|
.andNotMutingInstance(qb, ':meId', 'note.userHost')
|
||||||
.andWhere(new Brackets(qb => {
|
.orWhere('note.userHost IS NULL')))
|
||||||
this.excludeMutingInstance(qb, ':meId', 'note.replyUserHost', 'orWhere')
|
.andWhere(new Brackets(qb => this
|
||||||
.orWhere('note.replyUserHost IS NULL');
|
.orNotMutingInstance(qb, ':meId', 'note.replyUserHost')
|
||||||
}))
|
.orWhere('note.replyUserHost IS NULL')))
|
||||||
.andWhere(new Brackets(qb => {
|
.andWhere(new Brackets(qb => this
|
||||||
this.excludeMutingInstance(qb, ':meId', 'note.renoteUserHost', 'orWhere')
|
.orNotMutingInstance(qb, ':meId', 'note.renoteUserHost')
|
||||||
.orWhere('note.renoteUserHost IS NULL');
|
.orWhere('note.renoteUserHost IS NULL')))
|
||||||
}));
|
.setParameters({ meId: me.id });
|
||||||
|
|
||||||
return q.setParameters({ meId: me.id });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public generateMutedUserQueryForUsers<E extends ObjectLiteral>(q: SelectQueryBuilder<E>, me: { id: MiUser['id'] }): SelectQueryBuilder<E> {
|
public generateMutedUserQueryForUsers<E extends ObjectLiteral>(q: SelectQueryBuilder<E>, me: { id: MiUser['id'] }): SelectQueryBuilder<E> {
|
||||||
return this.excludeMutingUser(q, ':meId', 'user.id')
|
return this
|
||||||
|
.andNotMutingUser(q, ':meId', 'user.id')
|
||||||
.setParameters({ meId: me.id });
|
.setParameters({ meId: me.id });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,11 +164,9 @@ export class QueryService {
|
||||||
// Mentions me
|
// Mentions me
|
||||||
.orWhere(':meId = ANY (note.mentions)')
|
.orWhere(':meId = ANY (note.mentions)')
|
||||||
// Followers-only post
|
// Followers-only post
|
||||||
.orWhere(new Brackets(qb => {
|
.orWhere(new Brackets(qb => this
|
||||||
// または フォロワー宛ての投稿であり、
|
.andFollowingUser(qb, ':meId', 'note.userId')
|
||||||
this.addFollowingUser(qb, ':meId', 'note.userId')
|
.andWhere('note.visibility = \'followers\'')));
|
||||||
.andWhere('note.visibility = \'followers\'');
|
|
||||||
}));
|
|
||||||
|
|
||||||
q.setParameters({ meId: me.id });
|
q.setParameters({ meId: me.id });
|
||||||
}
|
}
|
||||||
|
@ -178,38 +175,43 @@ export class QueryService {
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public generateMutedUserRenotesQueryForNotes<E extends ObjectLiteral>(q: SelectQueryBuilder<E>, me: { id: MiUser['id'] }): SelectQueryBuilder<E> {
|
public generateMutedUserRenotesQueryForNotes<E extends ObjectLiteral>(q: SelectQueryBuilder<E>, me: { id: MiUser['id'] }): SelectQueryBuilder<E> {
|
||||||
return q.andWhere(new Brackets(qb => {
|
return q
|
||||||
this.excludeMutingRenote(qb, ':meId', 'note.userId')
|
.andWhere(new Brackets(qb => this
|
||||||
|
.orNotMutingRenote(qb, ':meId', 'note.userId')
|
||||||
.orWhere('note.renoteId IS NULL')
|
.orWhere('note.renoteId IS NULL')
|
||||||
.orWhere('note.text IS NOT NULL')
|
.orWhere('note.text IS NOT NULL')
|
||||||
.orWhere('note.cw IS NOT NULL')
|
.orWhere('note.cw IS NOT NULL')
|
||||||
.orWhere('note.replyId IS NOT NULL')
|
.orWhere('note.replyId IS NOT NULL')
|
||||||
.orWhere('note.hasPoll = true')
|
.orWhere('note.hasPoll = true')
|
||||||
.orWhere('note.fileIds != \'{}\'');
|
.orWhere('note.fileIds != \'{}\'')))
|
||||||
}))
|
|
||||||
.setParameters({ meId: me.id });
|
.setParameters({ meId: me.id });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@bindThis
|
||||||
|
public generateExcludedRenotesQueryForNotes<E extends ObjectLiteral>(q: SelectQueryBuilder<E>): SelectQueryBuilder<E> {
|
||||||
|
return q
|
||||||
|
.andWhere(new Brackets(qb => qb
|
||||||
|
.orWhere('note.renoteId IS NULL')
|
||||||
|
.orWhere('note.text IS NOT NULL')
|
||||||
|
.orWhere('note.cw IS NOT NULL')
|
||||||
|
.orWhere('note.replyId IS NOT NULL')
|
||||||
|
.orWhere('note.hasPoll = true')
|
||||||
|
.orWhere('note.fileIds != \'{}\'')));
|
||||||
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public generateBlockedHostQueryForNote<E extends ObjectLiteral>(q: SelectQueryBuilder<E>, excludeAuthor?: boolean): SelectQueryBuilder<E> {
|
public generateBlockedHostQueryForNote<E extends ObjectLiteral>(q: SelectQueryBuilder<E>, excludeAuthor?: boolean): SelectQueryBuilder<E> {
|
||||||
const checkFor = (key: 'user' | 'replyUser' | 'renoteUser') => {
|
const checkFor = (key: 'user' | 'replyUser' | 'renoteUser') => this
|
||||||
q.andWhere(new Brackets(qb => {
|
.leftJoinInstance(q, `note.${key}Instance`, `${key}Instance`)
|
||||||
qb.orWhere(`note.${key}Host IS NULL`); // local
|
.andWhere(new Brackets(qb => {
|
||||||
|
qb
|
||||||
|
.orWhere(`"${key}Instance" IS NULL`) // local
|
||||||
|
.orWhere(`"${key}Instance"."isBlocked" = false`); // not blocked
|
||||||
|
|
||||||
if (key !== 'user') {
|
if (excludeAuthor) {
|
||||||
// note.userId always exists and is non-null
|
qb.orWhere(`note.userId = note.${key}Id`); // author
|
||||||
qb.orWhere(`note.${key}Id IS NULL`); // no corresponding user
|
|
||||||
|
|
||||||
// note.userId always equals note.userId
|
|
||||||
if (excludeAuthor) {
|
|
||||||
qb.orWhere(`note.userId = note.${key}Id`); // author
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// not blocked
|
|
||||||
this.excludeInstanceWhere(qb, `note.${key}Host`, { isBlocked: false }, 'orWhere');
|
|
||||||
}));
|
}));
|
||||||
};
|
|
||||||
|
|
||||||
if (!excludeAuthor) {
|
if (!excludeAuthor) {
|
||||||
checkFor('user');
|
checkFor('user');
|
||||||
|
@ -221,62 +223,58 @@ export class QueryService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public generateSilencedUserQueryForNotes<E extends ObjectLiteral>(q: SelectQueryBuilder<E>, me?: { id: MiUser['id'] } | null, userProp = 'user'): SelectQueryBuilder<E> {
|
public generateSilencedUserQueryForNotes<E extends ObjectLiteral>(q: SelectQueryBuilder<E>, me?: { id: MiUser['id'] } | null): SelectQueryBuilder<E> {
|
||||||
if (!me) {
|
if (!me) {
|
||||||
return q.andWhere(`${userProp}.isSilenced = false`);
|
return q.andWhere('user.isSilenced = false');
|
||||||
}
|
}
|
||||||
|
|
||||||
return q
|
return this
|
||||||
.andWhere(new Brackets(qb => {
|
.leftJoinInstance(q, 'note.userInstance', 'userInstance')
|
||||||
|
.andWhere(new Brackets(qb => this
|
||||||
// case 1: we are following the user
|
// case 1: we are following the user
|
||||||
this.addFollowingUser(qb, ':meId', `${userProp}.id`, 'orWhere');
|
.orFollowingUser(qb, ':meId', 'note.userId')
|
||||||
// case 2: user not silenced AND instance not silenced
|
// case 2: user not silenced AND instance not silenced
|
||||||
qb.orWhere(new Brackets(qbb => {
|
.orWhere(new Brackets(qbb => qbb
|
||||||
this.includeInstanceWhere(qbb, `${userProp}.host`, { isSilenced: false });
|
.andWhere(new Brackets(qbbb => qbbb
|
||||||
qbb.andWhere(`${userProp}.isSilenced = false`);
|
.orWhere('"userInstance"."isSilenced" = false')
|
||||||
}));
|
.orWhere('"userInstance" IS NULL')))
|
||||||
}))
|
.andWhere('user.isSilenced = false')))))
|
||||||
.setParameters({ meId: me.id });
|
.setParameters({ meId: me.id });
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
|
||||||
public generateMatchingHostQueryForNote<E extends ObjectLiteral>(q: SelectQueryBuilder<E>, filters: FindOptionsWhere<MiInstance> | FindOptionsWhere<MiInstance>[], hostProp = 'note.userHost'): SelectQueryBuilder<E> {
|
|
||||||
return this.includeInstanceWhere(q, hostProp, filters);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds condition that hostProp (instance host) matches the given filters.
|
* Left-joins an instance in to the query with a given alias and optional condition.
|
||||||
* The prop should be an expression, not raw values.
|
* These calls are de-duplicated - multiple uses of the same alias are skipped.
|
||||||
*/
|
*/
|
||||||
@bindThis
|
@bindThis
|
||||||
public includeInstanceWhere<Q extends WhereExpressionBuilder>(q: Q, hostProp: string, filters: FindOptionsWhere<MiInstance> | FindOptionsWhere<MiInstance>[], join: 'andWhere' | 'orWhere' = 'andWhere'): Q {
|
public leftJoinInstance<E extends ObjectLiteral>(q: SelectQueryBuilder<E>, relation: string | typeof MiInstance, alias: string, condition?: string): SelectQueryBuilder<E> {
|
||||||
const instancesQuery = this.instancesRepository.createQueryBuilder('instance')
|
// Skip if it's already joined, otherwise we'll get an error
|
||||||
.select('1')
|
if (!q.expressionMap.joinAttributes.some(j => j.alias.name === alias)) {
|
||||||
.andWhere(`instance.host = ${hostProp}`)
|
q.leftJoin(relation, alias, condition);
|
||||||
.andWhere(filters);
|
}
|
||||||
|
|
||||||
return q[join](`EXISTS (${instancesQuery.getQuery()})`, instancesQuery.getParameters());
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds condition that hostProp (instance host) matches the given filters.
|
* Adds OR condition that followerProp (user ID) is following followeeProp (user ID).
|
||||||
* The prop should be an expression, not raw values.
|
|
||||||
*/
|
|
||||||
@bindThis
|
|
||||||
public excludeInstanceWhere<Q extends WhereExpressionBuilder>(q: Q, hostProp: string, filters: FindOptionsWhere<MiInstance> | FindOptionsWhere<MiInstance>[], join: 'andWhere' | 'orWhere' = 'andWhere'): Q {
|
|
||||||
const instancesQuery = this.instancesRepository.createQueryBuilder('instance')
|
|
||||||
.select('1')
|
|
||||||
.andWhere(`instance.host = ${hostProp}`)
|
|
||||||
.andWhere(filters);
|
|
||||||
|
|
||||||
return q[join](`NOT EXISTS (${instancesQuery.getQuery()})`, instancesQuery.getParameters());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds condition that followerProp (user ID) is following followeeProp (user ID).
|
|
||||||
* Both props should be expressions, not raw values.
|
* Both props should be expressions, not raw values.
|
||||||
*/
|
*/
|
||||||
public addFollowingUser<Q extends WhereExpressionBuilder>(q: Q, followerProp: string, followeeProp: string, join: 'andWhere' | 'orWhere' = 'andWhere'): Q {
|
@bindThis
|
||||||
|
public orFollowingUser<Q extends WhereExpressionBuilder>(q: Q, followerProp: string, followeeProp: string): Q {
|
||||||
|
return this.addFollowingUser(q, followerProp, followeeProp, 'orWhere');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds AND condition that followerProp (user ID) is following followeeProp (user ID).
|
||||||
|
* Both props should be expressions, not raw values.
|
||||||
|
*/
|
||||||
|
@bindThis
|
||||||
|
public andFollowingUser<Q extends WhereExpressionBuilder>(q: Q, followerProp: string, followeeProp: string): Q {
|
||||||
|
return this.addFollowingUser(q, followerProp, followeeProp, 'andWhere');
|
||||||
|
}
|
||||||
|
|
||||||
|
private addFollowingUser<Q extends WhereExpressionBuilder>(q: Q, followerProp: string, followeeProp: string, join: 'andWhere' | 'orWhere'): Q {
|
||||||
const followingQuery = this.followingsRepository.createQueryBuilder('following')
|
const followingQuery = this.followingsRepository.createQueryBuilder('following')
|
||||||
.select('1')
|
.select('1')
|
||||||
.andWhere(`following.followerId = ${followerProp}`)
|
.andWhere(`following.followerId = ${followerProp}`)
|
||||||
|
@ -286,11 +284,24 @@ export class QueryService {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds condition that blockerProp (user ID) is not blocking blockeeProp (user ID).
|
* Adds OR condition that blockerProp (user ID) is not blocking blockeeProp (user ID).
|
||||||
* Both props should be expressions, not raw values.
|
* Both props should be expressions, not raw values.
|
||||||
*/
|
*/
|
||||||
@bindThis
|
@bindThis
|
||||||
public excludeBlockingUser<Q extends WhereExpressionBuilder>(q: Q, blockerProp: string, blockeeProp: string, join: 'andWhere' | 'orWhere' = 'andWhere'): Q {
|
public orNotBlockingUser<Q extends WhereExpressionBuilder>(q: Q, blockerProp: string, blockeeProp: string): Q {
|
||||||
|
return this.excludeBlockingUser(q, blockerProp, blockeeProp, 'orWhere');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds AND condition that blockerProp (user ID) is not blocking blockeeProp (user ID).
|
||||||
|
* Both props should be expressions, not raw values.
|
||||||
|
*/
|
||||||
|
@bindThis
|
||||||
|
public andNotBlockingUser<Q extends WhereExpressionBuilder>(q: Q, blockerProp: string, blockeeProp: string): Q {
|
||||||
|
return this.excludeBlockingUser(q, blockerProp, blockeeProp, 'andWhere');
|
||||||
|
}
|
||||||
|
|
||||||
|
private excludeBlockingUser<Q extends WhereExpressionBuilder>(q: Q, blockerProp: string, blockeeProp: string, join: 'andWhere' | 'orWhere'): Q {
|
||||||
const blockingQuery = this.blockingsRepository.createQueryBuilder('blocking')
|
const blockingQuery = this.blockingsRepository.createQueryBuilder('blocking')
|
||||||
.select('1')
|
.select('1')
|
||||||
.andWhere(`blocking.blockerId = ${blockerProp}`)
|
.andWhere(`blocking.blockerId = ${blockerProp}`)
|
||||||
|
@ -300,11 +311,24 @@ export class QueryService {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds condition that muterProp (user ID) is not muting muteeProp (user ID).
|
* Adds OR condition that muterProp (user ID) is not muting muteeProp (user ID).
|
||||||
* Both props should be expressions, not raw values.
|
* Both props should be expressions, not raw values.
|
||||||
*/
|
*/
|
||||||
@bindThis
|
@bindThis
|
||||||
public excludeMutingUser<Q extends WhereExpressionBuilder>(q: Q, muterProp: string, muteeProp: string, join: 'andWhere' | 'orWhere' = 'andWhere', exclude?: { id: MiUser['id'] }): Q {
|
public orNotMutingUser<Q extends WhereExpressionBuilder>(q: Q, muterProp: string, muteeProp: string, exclude?: { id: MiUser['id'] }): Q {
|
||||||
|
return this.excludeMutingUser(q, muterProp, muteeProp, 'orWhere', exclude);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds AND condition that muterProp (user ID) is not muting muteeProp (user ID).
|
||||||
|
* Both props should be expressions, not raw values.
|
||||||
|
*/
|
||||||
|
@bindThis
|
||||||
|
public andNotMutingUser<Q extends WhereExpressionBuilder>(q: Q, muterProp: string, muteeProp: string, exclude?: { id: MiUser['id'] }): Q {
|
||||||
|
return this.excludeMutingUser(q, muterProp, muteeProp, 'andWhere', exclude);
|
||||||
|
}
|
||||||
|
|
||||||
|
private excludeMutingUser<Q extends WhereExpressionBuilder>(q: Q, muterProp: string, muteeProp: string, join: 'andWhere' | 'orWhere', exclude?: { id: MiUser['id'] }): Q {
|
||||||
const mutingQuery = this.mutingsRepository.createQueryBuilder('muting')
|
const mutingQuery = this.mutingsRepository.createQueryBuilder('muting')
|
||||||
.select('1')
|
.select('1')
|
||||||
.andWhere(`muting.muterId = ${muterProp}`)
|
.andWhere(`muting.muterId = ${muterProp}`)
|
||||||
|
@ -318,10 +342,24 @@ export class QueryService {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds condition that muterProp (user ID) is not muting renotes by muteeProp (user ID).
|
* Adds OR condition that muterProp (user ID) is not muting renotes by muteeProp (user ID).
|
||||||
* Both props should be expressions, not raw values.
|
* Both props should be expressions, not raw values.
|
||||||
*/
|
*/
|
||||||
public excludeMutingRenote<Q extends WhereExpressionBuilder>(q: Q, muterProp: string, muteeProp: string, join: 'andWhere' | 'orWhere' = 'andWhere'): Q {
|
@bindThis
|
||||||
|
public orNotMutingRenote<Q extends WhereExpressionBuilder>(q: Q, muterProp: string, muteeProp: string): Q {
|
||||||
|
return this.excludeMutingRenote(q, muterProp, muteeProp, 'orWhere');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds AND condition that muterProp (user ID) is not muting renotes by muteeProp (user ID).
|
||||||
|
* Both props should be expressions, not raw values.
|
||||||
|
*/
|
||||||
|
@bindThis
|
||||||
|
public andNotMutingRenote<Q extends WhereExpressionBuilder>(q: Q, muterProp: string, muteeProp: string): Q {
|
||||||
|
return this.excludeMutingRenote(q, muterProp, muteeProp, 'andWhere');
|
||||||
|
}
|
||||||
|
|
||||||
|
private excludeMutingRenote<Q extends WhereExpressionBuilder>(q: Q, muterProp: string, muteeProp: string, join: 'andWhere' | 'orWhere'): Q {
|
||||||
const mutingQuery = this.renoteMutingsRepository.createQueryBuilder('renote_muting')
|
const mutingQuery = this.renoteMutingsRepository.createQueryBuilder('renote_muting')
|
||||||
.select('1')
|
.select('1')
|
||||||
.andWhere(`renote_muting.muterId = ${muterProp}`)
|
.andWhere(`renote_muting.muterId = ${muterProp}`)
|
||||||
|
@ -331,11 +369,24 @@ export class QueryService {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds condition that muterProp (user ID) is not muting muteeProp (instance host).
|
* Adds OR condition that muterProp (user ID) is not muting muteeProp (instance host).
|
||||||
* Both props should be expressions, not raw values.
|
* Both props should be expressions, not raw values.
|
||||||
*/
|
*/
|
||||||
@bindThis
|
@bindThis
|
||||||
public excludeMutingInstance<Q extends WhereExpressionBuilder>(q: Q, muterProp: string, muteeProp: string, join: 'andWhere' | 'orWhere' = 'andWhere'): Q {
|
public orNotMutingInstance<Q extends WhereExpressionBuilder>(q: Q, muterProp: string, muteeProp: string): Q {
|
||||||
|
return this.excludeMutingInstance(q, muterProp, muteeProp, 'orWhere');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds AND condition that muterProp (user ID) is not muting muteeProp (instance host).
|
||||||
|
* Both props should be expressions, not raw values.
|
||||||
|
*/
|
||||||
|
@bindThis
|
||||||
|
public andNotMutingInstance<Q extends WhereExpressionBuilder>(q: Q, muterProp: string, muteeProp: string): Q {
|
||||||
|
return this.excludeMutingInstance(q, muterProp, muteeProp, 'andWhere');
|
||||||
|
}
|
||||||
|
|
||||||
|
private excludeMutingInstance<Q extends WhereExpressionBuilder>(q: Q, muterProp: string, muteeProp: string, join: 'andWhere' | 'orWhere'): Q {
|
||||||
const mutingInstanceQuery = this.userProfilesRepository.createQueryBuilder('user_profile')
|
const mutingInstanceQuery = this.userProfilesRepository.createQueryBuilder('user_profile')
|
||||||
.select('1')
|
.select('1')
|
||||||
.andWhere(`user_profile.userId = ${muterProp}`)
|
.andWhere(`user_profile.userId = ${muterProp}`)
|
||||||
|
@ -345,11 +396,24 @@ export class QueryService {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds condition that muterProp (user ID) is not muting muteeProp (note ID).
|
* Adds OR condition that muterProp (user ID) is not muting muteeProp (note ID).
|
||||||
* Both props should be expressions, not raw values.
|
* Both props should be expressions, not raw values.
|
||||||
*/
|
*/
|
||||||
@bindThis
|
@bindThis
|
||||||
public excludeMutingThread<Q extends WhereExpressionBuilder>(q: Q, muterProp: string, muteeProp: string, join: 'andWhere' | 'orWhere' = 'andWhere'): Q {
|
public orNotMutingThread<Q extends WhereExpressionBuilder>(q: Q, muterProp: string, muteeProp: string): Q {
|
||||||
|
return this.excludeMutingThread(q, muterProp, muteeProp, 'orWhere');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds AND condition that muterProp (user ID) is not muting muteeProp (note ID).
|
||||||
|
* Both props should be expressions, not raw values.
|
||||||
|
*/
|
||||||
|
@bindThis
|
||||||
|
public andNotMutingThread<Q extends WhereExpressionBuilder>(q: Q, muterProp: string, muteeProp: string): Q {
|
||||||
|
return this.excludeMutingThread(q, muterProp, muteeProp, 'andWhere');
|
||||||
|
}
|
||||||
|
|
||||||
|
private excludeMutingThread<Q extends WhereExpressionBuilder>(q: Q, muterProp: string, muteeProp: string, join: 'andWhere' | 'orWhere'): Q {
|
||||||
const threadMutedQuery = this.noteThreadMutingsRepository.createQueryBuilder('threadMuted')
|
const threadMutedQuery = this.noteThreadMutingsRepository.createQueryBuilder('threadMuted')
|
||||||
.select('1')
|
.select('1')
|
||||||
.andWhere(`threadMuted.userId = ${muterProp}`)
|
.andWhere(`threadMuted.userId = ${muterProp}`)
|
||||||
|
|
Loading…
Add table
Reference in a new issue