perf(backend): cache avatar and banner url to db
This commit is contained in:
parent
de9d136a3f
commit
521eb95dbc
@ -0,0 +1,17 @@
|
|||||||
|
export class AvatarUrlAndBannerUrl1680775031481 {
|
||||||
|
name = 'AvatarUrlAndBannerUrl1680775031481'
|
||||||
|
|
||||||
|
async up(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" ADD "avatarUrl" character varying(512)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" ADD "bannerUrl" character varying(512)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" ADD "avatarBlurhash" character varying(128)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" ADD "bannerBlurhash" character varying(128)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async down(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "bannerBlurhash"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "avatarBlurhash"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "bannerUrl"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "avatarUrl"`);
|
||||||
|
}
|
||||||
|
}
|
@ -31,6 +31,7 @@ import type { UtilityService } from '@/core/UtilityService.js';
|
|||||||
import type { UserEntityService } from '@/core/entities/UserEntityService.js';
|
import type { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { MetaService } from '@/core/MetaService.js';
|
import { MetaService } from '@/core/MetaService.js';
|
||||||
|
import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
|
||||||
import { getApId, getApType, getOneApHrefNullable, isActor, isCollection, isCollectionOrOrderedCollection, isPropertyValue } from '../type.js';
|
import { getApId, getApType, getOneApHrefNullable, isActor, isCollection, isCollectionOrOrderedCollection, isPropertyValue } from '../type.js';
|
||||||
import { extractApHashtags } from './tag.js';
|
import { extractApHashtags } from './tag.js';
|
||||||
import type { OnModuleInit } from '@nestjs/common';
|
import type { OnModuleInit } from '@nestjs/common';
|
||||||
@ -49,6 +50,7 @@ const summaryLength = 2048;
|
|||||||
export class ApPersonService implements OnModuleInit {
|
export class ApPersonService implements OnModuleInit {
|
||||||
private utilityService: UtilityService;
|
private utilityService: UtilityService;
|
||||||
private userEntityService: UserEntityService;
|
private userEntityService: UserEntityService;
|
||||||
|
private driveFileEntityService: DriveFileEntityService;
|
||||||
private idService: IdService;
|
private idService: IdService;
|
||||||
private globalEventService: GlobalEventService;
|
private globalEventService: GlobalEventService;
|
||||||
private metaService: MetaService;
|
private metaService: MetaService;
|
||||||
@ -113,6 +115,7 @@ export class ApPersonService implements OnModuleInit {
|
|||||||
onModuleInit() {
|
onModuleInit() {
|
||||||
this.utilityService = this.moduleRef.get('UtilityService');
|
this.utilityService = this.moduleRef.get('UtilityService');
|
||||||
this.userEntityService = this.moduleRef.get('UserEntityService');
|
this.userEntityService = this.moduleRef.get('UserEntityService');
|
||||||
|
this.driveFileEntityService = this.moduleRef.get('DriveFileEntityService');
|
||||||
this.idService = this.moduleRef.get('IdService');
|
this.idService = this.moduleRef.get('IdService');
|
||||||
this.globalEventService = this.moduleRef.get('GlobalEventService');
|
this.globalEventService = this.moduleRef.get('GlobalEventService');
|
||||||
this.metaService = this.moduleRef.get('MetaService');
|
this.metaService = this.moduleRef.get('MetaService');
|
||||||
@ -356,14 +359,26 @@ export class ApPersonService implements OnModuleInit {
|
|||||||
|
|
||||||
const avatarId = avatar ? avatar.id : null;
|
const avatarId = avatar ? avatar.id : null;
|
||||||
const bannerId = banner ? banner.id : null;
|
const bannerId = banner ? banner.id : null;
|
||||||
|
const avatarUrl = avatar ? this.driveFileEntityService.getPublicUrl(avatar, 'avatar') : null;
|
||||||
|
const bannerUrl = banner ? this.driveFileEntityService.getPublicUrl(banner) : null;
|
||||||
|
const avatarBlurhash = avatar ? avatar.blurhash : null;
|
||||||
|
const bannerBlurhash = banner ? banner.blurhash : null;
|
||||||
|
|
||||||
await this.usersRepository.update(user!.id, {
|
await this.usersRepository.update(user!.id, {
|
||||||
avatarId,
|
avatarId,
|
||||||
bannerId,
|
bannerId,
|
||||||
|
avatarUrl,
|
||||||
|
bannerUrl,
|
||||||
|
avatarBlurhash,
|
||||||
|
bannerBlurhash,
|
||||||
});
|
});
|
||||||
|
|
||||||
user!.avatarId = avatarId;
|
user!.avatarId = avatarId;
|
||||||
user!.bannerId = bannerId;
|
user!.bannerId = bannerId;
|
||||||
|
user!.avatarUrl = avatarUrl;
|
||||||
|
user!.bannerUrl = bannerUrl;
|
||||||
|
user!.avatarBlurhash = avatarBlurhash;
|
||||||
|
user!.bannerBlurhash = bannerBlurhash;
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region カスタム絵文字取得
|
//#region カスタム絵文字取得
|
||||||
@ -463,10 +478,14 @@ export class ApPersonService implements OnModuleInit {
|
|||||||
|
|
||||||
if (avatar) {
|
if (avatar) {
|
||||||
updates.avatarId = avatar.id;
|
updates.avatarId = avatar.id;
|
||||||
|
updates.avatarUrl = this.driveFileEntityService.getPublicUrl(avatar, 'avatar');
|
||||||
|
updates.avatarBlurhash = avatar.blurhash;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (banner) {
|
if (banner) {
|
||||||
updates.bannerId = banner.id;
|
updates.bannerId = banner.id;
|
||||||
|
updates.bannerUrl = this.driveFileEntityService.getPublicUrl(banner);
|
||||||
|
updates.bannerBlurhash = banner.blurhash;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update user
|
// Update user
|
||||||
|
@ -415,7 +415,7 @@ export class NoteEntityService implements OnModuleInit {
|
|||||||
await this.customEmojiService.prefetchEmojis(this.aggregateNoteEmojis(notes));
|
await this.customEmojiService.prefetchEmojis(this.aggregateNoteEmojis(notes));
|
||||||
// TODO: 本当は renote とか reply がないのに renoteId とか replyId があったらここで解決しておく
|
// TODO: 本当は renote とか reply がないのに renoteId とか replyId があったらここで解決しておく
|
||||||
const fileIds = notes.map(n => [n.fileIds, n.renote?.fileIds, n.reply?.fileIds]).flat(2).filter(isNotNull);
|
const fileIds = notes.map(n => [n.fileIds, n.renote?.fileIds, n.reply?.fileIds]).flat(2).filter(isNotNull);
|
||||||
const packedFiles = await this.driveFileEntityService.packManyByIdsMap(fileIds);
|
const packedFiles = fileIds.length > 0 ? await this.driveFileEntityService.packManyByIdsMap(fileIds) : new Map();
|
||||||
|
|
||||||
return await Promise.all(notes.map(n => this.pack(n, me, {
|
return await Promise.all(notes.map(n => this.pack(n, me, {
|
||||||
...options,
|
...options,
|
||||||
|
@ -113,7 +113,7 @@ export class NotificationEntityService implements OnModuleInit {
|
|||||||
const noteIds = validNotifications.map(x => x.noteId).filter(isNotNull);
|
const noteIds = validNotifications.map(x => x.noteId).filter(isNotNull);
|
||||||
const notes = noteIds.length > 0 ? await this.notesRepository.find({
|
const notes = noteIds.length > 0 ? await this.notesRepository.find({
|
||||||
where: { id: In(noteIds) },
|
where: { id: In(noteIds) },
|
||||||
relations: ['user', 'user.avatar', 'user.banner', 'reply', 'reply.user', 'reply.user.avatar', 'reply.user.banner', 'renote', 'renote.user', 'renote.user.avatar', 'renote.user.banner'],
|
relations: ['user', 'reply', 'reply.user', 'renote', 'renote.user'],
|
||||||
}) : [];
|
}) : [];
|
||||||
const packedNotesArray = await this.noteEntityService.packMany(notes, { id: meId }, {
|
const packedNotesArray = await this.noteEntityService.packMany(notes, { id: meId }, {
|
||||||
detail: true,
|
detail: true,
|
||||||
@ -125,7 +125,6 @@ export class NotificationEntityService implements OnModuleInit {
|
|||||||
const userIds = validNotifications.map(x => x.notifierId).filter(isNotNull);
|
const userIds = validNotifications.map(x => x.notifierId).filter(isNotNull);
|
||||||
const users = userIds.length > 0 ? await this.usersRepository.find({
|
const users = userIds.length > 0 ? await this.usersRepository.find({
|
||||||
where: { id: In(userIds) },
|
where: { id: In(userIds) },
|
||||||
relations: ['avatar', 'banner'],
|
|
||||||
}) : [];
|
}) : [];
|
||||||
const packedUsersArray = await this.userEntityService.packMany(users, { id: meId }, {
|
const packedUsersArray = await this.userEntityService.packMany(users, { id: meId }, {
|
||||||
detail: false,
|
detail: false,
|
||||||
|
@ -269,27 +269,6 @@ export class UserEntityService implements OnModuleInit {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
|
||||||
public async getAvatarUrl(user: User): Promise<string> {
|
|
||||||
if (user.avatar) {
|
|
||||||
return this.driveFileEntityService.getPublicUrl(user.avatar, 'avatar') ?? this.getIdenticonUrl(user);
|
|
||||||
} else if (user.avatarId) {
|
|
||||||
const avatar = await this.driveFilesRepository.findOneByOrFail({ id: user.avatarId });
|
|
||||||
return this.driveFileEntityService.getPublicUrl(avatar, 'avatar') ?? this.getIdenticonUrl(user);
|
|
||||||
} else {
|
|
||||||
return this.getIdenticonUrl(user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
|
||||||
public getAvatarUrlSync(user: User): string {
|
|
||||||
if (user.avatar) {
|
|
||||||
return this.driveFileEntityService.getPublicUrl(user.avatar, 'avatar') ?? this.getIdenticonUrl(user);
|
|
||||||
} else {
|
|
||||||
return this.getIdenticonUrl(user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public getIdenticonUrl(user: User): string {
|
public getIdenticonUrl(user: User): string {
|
||||||
return `${this.config.url}/identicon/${user.username.toLowerCase()}@${user.host ?? this.config.host}`;
|
return `${this.config.url}/identicon/${user.username.toLowerCase()}@${user.host ?? this.config.host}`;
|
||||||
@ -309,19 +288,23 @@ export class UserEntityService implements OnModuleInit {
|
|||||||
includeSecrets: false,
|
includeSecrets: false,
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
let user: User;
|
const user = typeof src === 'object' ? src : await this.usersRepository.findOneByOrFail({ id: src });
|
||||||
|
|
||||||
if (typeof src === 'object') {
|
// migration
|
||||||
user = src;
|
if (user.avatarId != null && user.avatarUrl === null) {
|
||||||
if (src.avatar === undefined && src.avatarId) src.avatar = await this.driveFilesRepository.findOneBy({ id: src.avatarId }) ?? null;
|
const avatar = await this.driveFilesRepository.findOneByOrFail({ id: user.avatarId });
|
||||||
if (src.banner === undefined && src.bannerId) src.banner = await this.driveFilesRepository.findOneBy({ id: src.bannerId }) ?? null;
|
user.avatarUrl = this.driveFileEntityService.getPublicUrl(avatar, 'avatar');
|
||||||
} else {
|
this.usersRepository.update(user.id, {
|
||||||
user = await this.usersRepository.findOneOrFail({
|
avatarUrl: user.avatarUrl,
|
||||||
where: { id: src },
|
avatarBlurhash: avatar.blurhash,
|
||||||
relations: {
|
});
|
||||||
avatar: true,
|
}
|
||||||
banner: true,
|
if (user.bannerId != null && user.bannerUrl === null) {
|
||||||
},
|
const banner = await this.driveFilesRepository.findOneByOrFail({ id: user.bannerId });
|
||||||
|
user.bannerUrl = this.driveFileEntityService.getPublicUrl(banner);
|
||||||
|
this.usersRepository.update(user.id, {
|
||||||
|
bannerUrl: user.bannerUrl,
|
||||||
|
bannerBlurhash: banner.blurhash,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,8 +339,8 @@ export class UserEntityService implements OnModuleInit {
|
|||||||
name: user.name,
|
name: user.name,
|
||||||
username: user.username,
|
username: user.username,
|
||||||
host: user.host,
|
host: user.host,
|
||||||
avatarUrl: this.getAvatarUrlSync(user),
|
avatarUrl: user.avatarUrl ?? this.getIdenticonUrl(user),
|
||||||
avatarBlurhash: user.avatar?.blurhash ?? null,
|
avatarBlurhash: user.avatarBlurhash,
|
||||||
isBot: user.isBot ?? falsy,
|
isBot: user.isBot ?? falsy,
|
||||||
isCat: user.isCat ?? falsy,
|
isCat: user.isCat ?? falsy,
|
||||||
instance: user.host ? this.userInstanceCache.fetch(user.host,
|
instance: user.host ? this.userInstanceCache.fetch(user.host,
|
||||||
@ -386,8 +369,8 @@ export class UserEntityService implements OnModuleInit {
|
|||||||
createdAt: user.createdAt.toISOString(),
|
createdAt: user.createdAt.toISOString(),
|
||||||
updatedAt: user.updatedAt ? user.updatedAt.toISOString() : null,
|
updatedAt: user.updatedAt ? user.updatedAt.toISOString() : null,
|
||||||
lastFetchedAt: user.lastFetchedAt ? user.lastFetchedAt.toISOString() : null,
|
lastFetchedAt: user.lastFetchedAt ? user.lastFetchedAt.toISOString() : null,
|
||||||
bannerUrl: user.banner ? this.driveFileEntityService.getPublicUrl(user.banner) : null,
|
bannerUrl: user.bannerUrl,
|
||||||
bannerBlurhash: user.banner?.blurhash ?? null,
|
bannerBlurhash: user.bannerBlurhash,
|
||||||
isLocked: user.isLocked,
|
isLocked: user.isLocked,
|
||||||
isSilenced: this.roleService.getUserPolicies(user.id).then(r => !r.canPublicNote),
|
isSilenced: this.roleService.getUserPolicies(user.id).then(r => !r.canPublicNote),
|
||||||
isSuspended: user.isSuspended ?? falsy,
|
isSuspended: user.isSuspended ?? falsy,
|
||||||
|
@ -100,6 +100,26 @@ export class User {
|
|||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public banner: DriveFile | null;
|
public banner: DriveFile | null;
|
||||||
|
|
||||||
|
@Column('varchar', {
|
||||||
|
length: 512, nullable: true,
|
||||||
|
})
|
||||||
|
public avatarUrl: string | null;
|
||||||
|
|
||||||
|
@Column('varchar', {
|
||||||
|
length: 512, nullable: true,
|
||||||
|
})
|
||||||
|
public bannerUrl: string | null;
|
||||||
|
|
||||||
|
@Column('varchar', {
|
||||||
|
length: 128, nullable: true,
|
||||||
|
})
|
||||||
|
public avatarBlurhash: string | null;
|
||||||
|
|
||||||
|
@Column('varchar', {
|
||||||
|
length: 128, nullable: true,
|
||||||
|
})
|
||||||
|
public bannerBlurhash: string | null;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column('varchar', {
|
@Column('varchar', {
|
||||||
length: 128, array: true, default: '{}',
|
length: 128, array: true, default: '{}',
|
||||||
|
@ -149,13 +149,12 @@ export class ServerService implements OnApplicationShutdown {
|
|||||||
host: (host == null) || (host === this.config.host) ? IsNull() : host,
|
host: (host == null) || (host === this.config.host) ? IsNull() : host,
|
||||||
isSuspended: false,
|
isSuspended: false,
|
||||||
},
|
},
|
||||||
relations: ['avatar'],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
reply.header('Cache-Control', 'public, max-age=86400');
|
reply.header('Cache-Control', 'public, max-age=86400');
|
||||||
|
|
||||||
if (user) {
|
if (user) {
|
||||||
reply.redirect(this.userEntityService.getAvatarUrlSync(user));
|
reply.redirect(user.avatarUrl ?? this.userEntityService.getIdenticonUrl(user));
|
||||||
} else {
|
} else {
|
||||||
reply.redirect('/static-assets/user-unknown.png');
|
reply.redirect('/static-assets/user-unknown.png');
|
||||||
}
|
}
|
||||||
|
@ -95,16 +95,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
const query = this.notesRepository.createQueryBuilder('note')
|
const query = this.notesRepository.createQueryBuilder('note')
|
||||||
.where('note.id IN (:...noteIds)', { noteIds: noteIds })
|
.where('note.id IN (:...noteIds)', { noteIds: noteIds })
|
||||||
.innerJoinAndSelect('note.user', 'user')
|
.innerJoinAndSelect('note.user', 'user')
|
||||||
.leftJoinAndSelect('user.avatar', 'avatar')
|
|
||||||
.leftJoinAndSelect('user.banner', 'banner')
|
|
||||||
.leftJoinAndSelect('note.reply', 'reply')
|
.leftJoinAndSelect('note.reply', 'reply')
|
||||||
.leftJoinAndSelect('note.renote', 'renote')
|
.leftJoinAndSelect('note.renote', 'renote')
|
||||||
.leftJoinAndSelect('reply.user', 'replyUser')
|
.leftJoinAndSelect('reply.user', 'replyUser')
|
||||||
.leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar')
|
.leftJoinAndSelect('renote.user', 'renoteUser');
|
||||||
.leftJoinAndSelect('replyUser.banner', 'replyUserBanner')
|
|
||||||
.leftJoinAndSelect('renote.user', 'renoteUser')
|
|
||||||
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
|
|
||||||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner');
|
|
||||||
|
|
||||||
this.queryService.generateVisibilityQuery(query, me);
|
this.queryService.generateVisibilityQuery(query, me);
|
||||||
this.queryService.generateMutedUserQuery(query, me);
|
this.queryService.generateMutedUserQuery(query, me);
|
||||||
|
@ -93,16 +93,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
const query = this.notesRepository.createQueryBuilder('note')
|
const query = this.notesRepository.createQueryBuilder('note')
|
||||||
.where('note.id IN (:...noteIds)', { noteIds: noteIds })
|
.where('note.id IN (:...noteIds)', { noteIds: noteIds })
|
||||||
.innerJoinAndSelect('note.user', 'user')
|
.innerJoinAndSelect('note.user', 'user')
|
||||||
.leftJoinAndSelect('user.avatar', 'avatar')
|
|
||||||
.leftJoinAndSelect('user.banner', 'banner')
|
|
||||||
.leftJoinAndSelect('note.reply', 'reply')
|
.leftJoinAndSelect('note.reply', 'reply')
|
||||||
.leftJoinAndSelect('note.renote', 'renote')
|
.leftJoinAndSelect('note.renote', 'renote')
|
||||||
.leftJoinAndSelect('reply.user', 'replyUser')
|
.leftJoinAndSelect('reply.user', 'replyUser')
|
||||||
.leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar')
|
|
||||||
.leftJoinAndSelect('replyUser.banner', 'replyUserBanner')
|
|
||||||
.leftJoinAndSelect('renote.user', 'renoteUser')
|
.leftJoinAndSelect('renote.user', 'renoteUser')
|
||||||
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
|
|
||||||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner')
|
|
||||||
.leftJoinAndSelect('note.channel', 'channel');
|
.leftJoinAndSelect('note.channel', 'channel');
|
||||||
|
|
||||||
if (me) {
|
if (me) {
|
||||||
|
@ -75,16 +75,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId)
|
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId)
|
||||||
.innerJoin(this.clipNotesRepository.metadata.targetName, 'clipNote', 'clipNote.noteId = note.id')
|
.innerJoin(this.clipNotesRepository.metadata.targetName, 'clipNote', 'clipNote.noteId = note.id')
|
||||||
.innerJoinAndSelect('note.user', 'user')
|
.innerJoinAndSelect('note.user', 'user')
|
||||||
.leftJoinAndSelect('user.avatar', 'avatar')
|
|
||||||
.leftJoinAndSelect('user.banner', 'banner')
|
|
||||||
.leftJoinAndSelect('note.reply', 'reply')
|
.leftJoinAndSelect('note.reply', 'reply')
|
||||||
.leftJoinAndSelect('note.renote', 'renote')
|
.leftJoinAndSelect('note.renote', 'renote')
|
||||||
.leftJoinAndSelect('reply.user', 'replyUser')
|
.leftJoinAndSelect('reply.user', 'replyUser')
|
||||||
.leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar')
|
|
||||||
.leftJoinAndSelect('replyUser.banner', 'replyUserBanner')
|
|
||||||
.leftJoinAndSelect('renote.user', 'renoteUser')
|
.leftJoinAndSelect('renote.user', 'renoteUser')
|
||||||
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
|
|
||||||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner')
|
|
||||||
.andWhere('clipNote.clipId = :clipId', { clipId: clip.id });
|
.andWhere('clipNote.clipId = :clipId', { clipId: clip.id });
|
||||||
|
|
||||||
if (me) {
|
if (me) {
|
||||||
|
@ -19,6 +19,7 @@ import { HashtagService } from '@/core/HashtagService.js';
|
|||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import { RoleService } from '@/core/RoleService.js';
|
import { RoleService } from '@/core/RoleService.js';
|
||||||
import { CacheService } from '@/core/CacheService.js';
|
import { CacheService } from '@/core/CacheService.js';
|
||||||
|
import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
|
||||||
import { ApiError } from '../../error.js';
|
import { ApiError } from '../../error.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
@ -148,6 +149,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
private pagesRepository: PagesRepository,
|
private pagesRepository: PagesRepository,
|
||||||
|
|
||||||
private userEntityService: UserEntityService,
|
private userEntityService: UserEntityService,
|
||||||
|
private driveFileEntityService: DriveFileEntityService,
|
||||||
private globalEventService: GlobalEventService,
|
private globalEventService: GlobalEventService,
|
||||||
private userFollowingService: UserFollowingService,
|
private userFollowingService: UserFollowingService,
|
||||||
private accountUpdateService: AccountUpdateService,
|
private accountUpdateService: AccountUpdateService,
|
||||||
@ -170,8 +172,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
if (ps.location !== undefined) profileUpdates.location = ps.location;
|
if (ps.location !== undefined) profileUpdates.location = ps.location;
|
||||||
if (ps.birthday !== undefined) profileUpdates.birthday = ps.birthday;
|
if (ps.birthday !== undefined) profileUpdates.birthday = ps.birthday;
|
||||||
if (ps.ffVisibility !== undefined) profileUpdates.ffVisibility = ps.ffVisibility;
|
if (ps.ffVisibility !== undefined) profileUpdates.ffVisibility = ps.ffVisibility;
|
||||||
if (ps.avatarId !== undefined) updates.avatarId = ps.avatarId;
|
|
||||||
if (ps.bannerId !== undefined) updates.bannerId = ps.bannerId;
|
|
||||||
if (ps.mutedWords !== undefined) {
|
if (ps.mutedWords !== undefined) {
|
||||||
// TODO: ちゃんと数える
|
// TODO: ちゃんと数える
|
||||||
const length = JSON.stringify(ps.mutedWords).length;
|
const length = JSON.stringify(ps.mutedWords).length;
|
||||||
@ -217,6 +217,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
|
|
||||||
if (avatar == null || avatar.userId !== user.id) throw new ApiError(meta.errors.noSuchAvatar);
|
if (avatar == null || avatar.userId !== user.id) throw new ApiError(meta.errors.noSuchAvatar);
|
||||||
if (!avatar.type.startsWith('image/')) throw new ApiError(meta.errors.avatarNotAnImage);
|
if (!avatar.type.startsWith('image/')) throw new ApiError(meta.errors.avatarNotAnImage);
|
||||||
|
|
||||||
|
updates.avatarId = avatar.id;
|
||||||
|
updates.avatarUrl = this.driveFileEntityService.getPublicUrl(avatar, 'avatar');
|
||||||
|
updates.avatarBlurhash = avatar.blurhash;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ps.bannerId) {
|
if (ps.bannerId) {
|
||||||
@ -224,6 +228,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
|
|
||||||
if (banner == null || banner.userId !== user.id) throw new ApiError(meta.errors.noSuchBanner);
|
if (banner == null || banner.userId !== user.id) throw new ApiError(meta.errors.noSuchBanner);
|
||||||
if (!banner.type.startsWith('image/')) throw new ApiError(meta.errors.bannerNotAnImage);
|
if (!banner.type.startsWith('image/')) throw new ApiError(meta.errors.bannerNotAnImage);
|
||||||
|
|
||||||
|
updates.bannerId = banner.id;
|
||||||
|
updates.bannerUrl = this.driveFileEntityService.getPublicUrl(banner);
|
||||||
|
updates.bannerBlurhash = banner.blurhash;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ps.pinnedPageId) {
|
if (ps.pinnedPageId) {
|
||||||
|
@ -49,16 +49,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
.andWhere('note.visibility = \'public\'')
|
.andWhere('note.visibility = \'public\'')
|
||||||
.andWhere('note.localOnly = FALSE')
|
.andWhere('note.localOnly = FALSE')
|
||||||
.innerJoinAndSelect('note.user', 'user')
|
.innerJoinAndSelect('note.user', 'user')
|
||||||
.leftJoinAndSelect('user.avatar', 'avatar')
|
|
||||||
.leftJoinAndSelect('user.banner', 'banner')
|
|
||||||
.leftJoinAndSelect('note.reply', 'reply')
|
.leftJoinAndSelect('note.reply', 'reply')
|
||||||
.leftJoinAndSelect('note.renote', 'renote')
|
.leftJoinAndSelect('note.renote', 'renote')
|
||||||
.leftJoinAndSelect('reply.user', 'replyUser')
|
.leftJoinAndSelect('reply.user', 'replyUser')
|
||||||
.leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar')
|
.leftJoinAndSelect('renote.user', 'renoteUser');
|
||||||
.leftJoinAndSelect('replyUser.banner', 'replyUserBanner')
|
|
||||||
.leftJoinAndSelect('renote.user', 'renoteUser')
|
|
||||||
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
|
|
||||||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner');
|
|
||||||
|
|
||||||
if (ps.local) {
|
if (ps.local) {
|
||||||
query.andWhere('note.userHost IS NULL');
|
query.andWhere('note.userHost IS NULL');
|
||||||
|
@ -57,16 +57,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
}));
|
}));
|
||||||
}))
|
}))
|
||||||
.innerJoinAndSelect('note.user', 'user')
|
.innerJoinAndSelect('note.user', 'user')
|
||||||
.leftJoinAndSelect('user.avatar', 'avatar')
|
|
||||||
.leftJoinAndSelect('user.banner', 'banner')
|
|
||||||
.leftJoinAndSelect('note.reply', 'reply')
|
.leftJoinAndSelect('note.reply', 'reply')
|
||||||
.leftJoinAndSelect('note.renote', 'renote')
|
.leftJoinAndSelect('note.renote', 'renote')
|
||||||
.leftJoinAndSelect('reply.user', 'replyUser')
|
.leftJoinAndSelect('reply.user', 'replyUser')
|
||||||
.leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar')
|
.leftJoinAndSelect('renote.user', 'renoteUser');
|
||||||
.leftJoinAndSelect('replyUser.banner', 'replyUserBanner')
|
|
||||||
.leftJoinAndSelect('renote.user', 'renoteUser')
|
|
||||||
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
|
|
||||||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner');
|
|
||||||
|
|
||||||
this.queryService.generateVisibilityQuery(query, me);
|
this.queryService.generateVisibilityQuery(query, me);
|
||||||
if (me) {
|
if (me) {
|
||||||
|
@ -53,16 +53,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
.andWhere('note.createdAt > :date', { date: new Date(Date.now() - day) })
|
.andWhere('note.createdAt > :date', { date: new Date(Date.now() - day) })
|
||||||
.andWhere('note.visibility = \'public\'')
|
.andWhere('note.visibility = \'public\'')
|
||||||
.innerJoinAndSelect('note.user', 'user')
|
.innerJoinAndSelect('note.user', 'user')
|
||||||
.leftJoinAndSelect('user.avatar', 'avatar')
|
|
||||||
.leftJoinAndSelect('user.banner', 'banner')
|
|
||||||
.leftJoinAndSelect('note.reply', 'reply')
|
.leftJoinAndSelect('note.reply', 'reply')
|
||||||
.leftJoinAndSelect('note.renote', 'renote')
|
.leftJoinAndSelect('note.renote', 'renote')
|
||||||
.leftJoinAndSelect('reply.user', 'replyUser')
|
.leftJoinAndSelect('reply.user', 'replyUser')
|
||||||
.leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar')
|
.leftJoinAndSelect('renote.user', 'renoteUser');
|
||||||
.leftJoinAndSelect('replyUser.banner', 'replyUserBanner')
|
|
||||||
.leftJoinAndSelect('renote.user', 'renoteUser')
|
|
||||||
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
|
|
||||||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner');
|
|
||||||
|
|
||||||
if (ps.channelId) query.andWhere('note.channelId = :channelId', { channelId: ps.channelId });
|
if (ps.channelId) query.andWhere('note.channelId = :channelId', { channelId: ps.channelId });
|
||||||
|
|
||||||
|
@ -73,16 +73,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
.andWhere('note.visibility = \'public\'')
|
.andWhere('note.visibility = \'public\'')
|
||||||
.andWhere('note.channelId IS NULL')
|
.andWhere('note.channelId IS NULL')
|
||||||
.innerJoinAndSelect('note.user', 'user')
|
.innerJoinAndSelect('note.user', 'user')
|
||||||
.leftJoinAndSelect('user.avatar', 'avatar')
|
|
||||||
.leftJoinAndSelect('user.banner', 'banner')
|
|
||||||
.leftJoinAndSelect('note.reply', 'reply')
|
.leftJoinAndSelect('note.reply', 'reply')
|
||||||
.leftJoinAndSelect('note.renote', 'renote')
|
.leftJoinAndSelect('note.renote', 'renote')
|
||||||
.leftJoinAndSelect('reply.user', 'replyUser')
|
.leftJoinAndSelect('reply.user', 'replyUser')
|
||||||
.leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar')
|
.leftJoinAndSelect('renote.user', 'renoteUser');
|
||||||
.leftJoinAndSelect('replyUser.banner', 'replyUserBanner')
|
|
||||||
.leftJoinAndSelect('renote.user', 'renoteUser')
|
|
||||||
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
|
|
||||||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner');
|
|
||||||
|
|
||||||
this.queryService.generateRepliesQuery(query, me);
|
this.queryService.generateRepliesQuery(query, me);
|
||||||
if (me) {
|
if (me) {
|
||||||
|
@ -91,16 +91,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
.orWhere('(note.visibility = \'public\') AND (note.userHost IS NULL)');
|
.orWhere('(note.visibility = \'public\') AND (note.userHost IS NULL)');
|
||||||
}))
|
}))
|
||||||
.innerJoinAndSelect('note.user', 'user')
|
.innerJoinAndSelect('note.user', 'user')
|
||||||
.leftJoinAndSelect('user.avatar', 'avatar')
|
|
||||||
.leftJoinAndSelect('user.banner', 'banner')
|
|
||||||
.leftJoinAndSelect('note.reply', 'reply')
|
.leftJoinAndSelect('note.reply', 'reply')
|
||||||
.leftJoinAndSelect('note.renote', 'renote')
|
.leftJoinAndSelect('note.renote', 'renote')
|
||||||
.leftJoinAndSelect('reply.user', 'replyUser')
|
.leftJoinAndSelect('reply.user', 'replyUser')
|
||||||
.leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar')
|
|
||||||
.leftJoinAndSelect('replyUser.banner', 'replyUserBanner')
|
|
||||||
.leftJoinAndSelect('renote.user', 'renoteUser')
|
.leftJoinAndSelect('renote.user', 'renoteUser')
|
||||||
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
|
|
||||||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner')
|
|
||||||
.setParameters(followingQuery.getParameters());
|
.setParameters(followingQuery.getParameters());
|
||||||
|
|
||||||
this.queryService.generateChannelQuery(query, me);
|
this.queryService.generateChannelQuery(query, me);
|
||||||
|
@ -80,16 +80,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
.andWhere('note.id > :minId', { minId: this.idService.genId(new Date(Date.now() - (1000 * 60 * 60 * 24 * 10))) }) // 10日前まで
|
.andWhere('note.id > :minId', { minId: this.idService.genId(new Date(Date.now() - (1000 * 60 * 60 * 24 * 10))) }) // 10日前まで
|
||||||
.andWhere('(note.visibility = \'public\') AND (note.userHost IS NULL)')
|
.andWhere('(note.visibility = \'public\') AND (note.userHost IS NULL)')
|
||||||
.innerJoinAndSelect('note.user', 'user')
|
.innerJoinAndSelect('note.user', 'user')
|
||||||
.leftJoinAndSelect('user.avatar', 'avatar')
|
|
||||||
.leftJoinAndSelect('user.banner', 'banner')
|
|
||||||
.leftJoinAndSelect('note.reply', 'reply')
|
.leftJoinAndSelect('note.reply', 'reply')
|
||||||
.leftJoinAndSelect('note.renote', 'renote')
|
.leftJoinAndSelect('note.renote', 'renote')
|
||||||
.leftJoinAndSelect('reply.user', 'replyUser')
|
.leftJoinAndSelect('reply.user', 'replyUser')
|
||||||
.leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar')
|
.leftJoinAndSelect('renote.user', 'renoteUser');
|
||||||
.leftJoinAndSelect('replyUser.banner', 'replyUserBanner')
|
|
||||||
.leftJoinAndSelect('renote.user', 'renoteUser')
|
|
||||||
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
|
|
||||||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner');
|
|
||||||
|
|
||||||
this.queryService.generateChannelQuery(query, me);
|
this.queryService.generateChannelQuery(query, me);
|
||||||
this.queryService.generateRepliesQuery(query, me);
|
this.queryService.generateRepliesQuery(query, me);
|
||||||
|
@ -60,16 +60,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
.orWhere(`'{"${me.id}"}' <@ note.visibleUserIds`);
|
.orWhere(`'{"${me.id}"}' <@ note.visibleUserIds`);
|
||||||
}))
|
}))
|
||||||
.innerJoinAndSelect('note.user', 'user')
|
.innerJoinAndSelect('note.user', 'user')
|
||||||
.leftJoinAndSelect('user.avatar', 'avatar')
|
|
||||||
.leftJoinAndSelect('user.banner', 'banner')
|
|
||||||
.leftJoinAndSelect('note.reply', 'reply')
|
.leftJoinAndSelect('note.reply', 'reply')
|
||||||
.leftJoinAndSelect('note.renote', 'renote')
|
.leftJoinAndSelect('note.renote', 'renote')
|
||||||
.leftJoinAndSelect('reply.user', 'replyUser')
|
.leftJoinAndSelect('reply.user', 'replyUser')
|
||||||
.leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar')
|
.leftJoinAndSelect('renote.user', 'renoteUser');
|
||||||
.leftJoinAndSelect('replyUser.banner', 'replyUserBanner')
|
|
||||||
.leftJoinAndSelect('renote.user', 'renoteUser')
|
|
||||||
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
|
|
||||||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner');
|
|
||||||
|
|
||||||
this.queryService.generateVisibilityQuery(query, me);
|
this.queryService.generateVisibilityQuery(query, me);
|
||||||
this.queryService.generateMutedUserQuery(query, me);
|
this.queryService.generateMutedUserQuery(query, me);
|
||||||
|
@ -75,7 +75,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
order: {
|
order: {
|
||||||
id: -1,
|
id: -1,
|
||||||
},
|
},
|
||||||
relations: ['user', 'user.avatar', 'user.banner', 'note'],
|
relations: ['user', 'note'],
|
||||||
});
|
});
|
||||||
|
|
||||||
return await Promise.all(reactions.map(reaction => this.noteReactionEntityService.pack(reaction, me)));
|
return await Promise.all(reactions.map(reaction => this.noteReactionEntityService.pack(reaction, me)));
|
||||||
|
@ -4,8 +4,8 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
|
|||||||
import { QueryService } from '@/core/QueryService.js';
|
import { QueryService } from '@/core/QueryService.js';
|
||||||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import { ApiError } from '../../error.js';
|
|
||||||
import { GetterService } from '@/server/api/GetterService.js';
|
import { GetterService } from '@/server/api/GetterService.js';
|
||||||
|
import { ApiError } from '../../error.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['notes'],
|
tags: ['notes'],
|
||||||
@ -62,16 +62,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId)
|
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId)
|
||||||
.andWhere('note.renoteId = :renoteId', { renoteId: note.id })
|
.andWhere('note.renoteId = :renoteId', { renoteId: note.id })
|
||||||
.innerJoinAndSelect('note.user', 'user')
|
.innerJoinAndSelect('note.user', 'user')
|
||||||
.leftJoinAndSelect('user.avatar', 'avatar')
|
|
||||||
.leftJoinAndSelect('user.banner', 'banner')
|
|
||||||
.leftJoinAndSelect('note.reply', 'reply')
|
.leftJoinAndSelect('note.reply', 'reply')
|
||||||
.leftJoinAndSelect('note.renote', 'renote')
|
.leftJoinAndSelect('note.renote', 'renote')
|
||||||
.leftJoinAndSelect('reply.user', 'replyUser')
|
.leftJoinAndSelect('reply.user', 'replyUser')
|
||||||
.leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar')
|
.leftJoinAndSelect('renote.user', 'renoteUser');
|
||||||
.leftJoinAndSelect('replyUser.banner', 'replyUserBanner')
|
|
||||||
.leftJoinAndSelect('renote.user', 'renoteUser')
|
|
||||||
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
|
|
||||||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner');
|
|
||||||
|
|
||||||
this.queryService.generateVisibilityQuery(query, me);
|
this.queryService.generateVisibilityQuery(query, me);
|
||||||
if (me) this.queryService.generateMutedUserQuery(query, me);
|
if (me) this.queryService.generateMutedUserQuery(query, me);
|
||||||
|
@ -46,16 +46,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId)
|
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId)
|
||||||
.andWhere('note.replyId = :replyId', { replyId: ps.noteId })
|
.andWhere('note.replyId = :replyId', { replyId: ps.noteId })
|
||||||
.innerJoinAndSelect('note.user', 'user')
|
.innerJoinAndSelect('note.user', 'user')
|
||||||
.leftJoinAndSelect('user.avatar', 'avatar')
|
|
||||||
.leftJoinAndSelect('user.banner', 'banner')
|
|
||||||
.leftJoinAndSelect('note.reply', 'reply')
|
.leftJoinAndSelect('note.reply', 'reply')
|
||||||
.leftJoinAndSelect('note.renote', 'renote')
|
.leftJoinAndSelect('note.renote', 'renote')
|
||||||
.leftJoinAndSelect('reply.user', 'replyUser')
|
.leftJoinAndSelect('reply.user', 'replyUser')
|
||||||
.leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar')
|
.leftJoinAndSelect('renote.user', 'renoteUser');
|
||||||
.leftJoinAndSelect('replyUser.banner', 'replyUserBanner')
|
|
||||||
.leftJoinAndSelect('renote.user', 'renoteUser')
|
|
||||||
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
|
|
||||||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner');
|
|
||||||
|
|
||||||
this.queryService.generateVisibilityQuery(query, me);
|
this.queryService.generateVisibilityQuery(query, me);
|
||||||
if (me) this.queryService.generateMutedUserQuery(query, me);
|
if (me) this.queryService.generateMutedUserQuery(query, me);
|
||||||
|
@ -71,16 +71,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId)
|
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId)
|
||||||
.innerJoinAndSelect('note.user', 'user')
|
.innerJoinAndSelect('note.user', 'user')
|
||||||
.leftJoinAndSelect('user.avatar', 'avatar')
|
|
||||||
.leftJoinAndSelect('user.banner', 'banner')
|
|
||||||
.leftJoinAndSelect('note.reply', 'reply')
|
.leftJoinAndSelect('note.reply', 'reply')
|
||||||
.leftJoinAndSelect('note.renote', 'renote')
|
.leftJoinAndSelect('note.renote', 'renote')
|
||||||
.leftJoinAndSelect('reply.user', 'replyUser')
|
.leftJoinAndSelect('reply.user', 'replyUser')
|
||||||
.leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar')
|
.leftJoinAndSelect('renote.user', 'renoteUser');
|
||||||
.leftJoinAndSelect('replyUser.banner', 'replyUserBanner')
|
|
||||||
.leftJoinAndSelect('renote.user', 'renoteUser')
|
|
||||||
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
|
|
||||||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner');
|
|
||||||
|
|
||||||
this.queryService.generateVisibilityQuery(query, me);
|
this.queryService.generateVisibilityQuery(query, me);
|
||||||
if (me) this.queryService.generateMutedUserQuery(query, me);
|
if (me) this.queryService.generateMutedUserQuery(query, me);
|
||||||
|
@ -85,16 +85,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
query
|
query
|
||||||
.andWhere('note.text ILIKE :q', { q: `%${ sqlLikeEscape(ps.query) }%` })
|
.andWhere('note.text ILIKE :q', { q: `%${ sqlLikeEscape(ps.query) }%` })
|
||||||
.innerJoinAndSelect('note.user', 'user')
|
.innerJoinAndSelect('note.user', 'user')
|
||||||
.leftJoinAndSelect('user.avatar', 'avatar')
|
|
||||||
.leftJoinAndSelect('user.banner', 'banner')
|
|
||||||
.leftJoinAndSelect('note.reply', 'reply')
|
.leftJoinAndSelect('note.reply', 'reply')
|
||||||
.leftJoinAndSelect('note.renote', 'renote')
|
.leftJoinAndSelect('note.renote', 'renote')
|
||||||
.leftJoinAndSelect('reply.user', 'replyUser')
|
.leftJoinAndSelect('reply.user', 'replyUser')
|
||||||
.leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar')
|
.leftJoinAndSelect('renote.user', 'renoteUser');
|
||||||
.leftJoinAndSelect('replyUser.banner', 'replyUserBanner')
|
|
||||||
.leftJoinAndSelect('renote.user', 'renoteUser')
|
|
||||||
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
|
|
||||||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner');
|
|
||||||
|
|
||||||
this.queryService.generateVisibilityQuery(query, me);
|
this.queryService.generateVisibilityQuery(query, me);
|
||||||
if (me) this.queryService.generateMutedUserQuery(query, me);
|
if (me) this.queryService.generateMutedUserQuery(query, me);
|
||||||
|
@ -70,16 +70,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
|
ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
|
||||||
.andWhere('note.id > :minId', { minId: this.idService.genId(new Date(Date.now() - (1000 * 60 * 60 * 24 * 10))) }) // 10日前まで
|
.andWhere('note.id > :minId', { minId: this.idService.genId(new Date(Date.now() - (1000 * 60 * 60 * 24 * 10))) }) // 10日前まで
|
||||||
.innerJoinAndSelect('note.user', 'user')
|
.innerJoinAndSelect('note.user', 'user')
|
||||||
.leftJoinAndSelect('user.avatar', 'avatar')
|
|
||||||
.leftJoinAndSelect('user.banner', 'banner')
|
|
||||||
.leftJoinAndSelect('note.reply', 'reply')
|
.leftJoinAndSelect('note.reply', 'reply')
|
||||||
.leftJoinAndSelect('note.renote', 'renote')
|
.leftJoinAndSelect('note.renote', 'renote')
|
||||||
.leftJoinAndSelect('reply.user', 'replyUser')
|
.leftJoinAndSelect('reply.user', 'replyUser')
|
||||||
.leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar')
|
.leftJoinAndSelect('renote.user', 'renoteUser');
|
||||||
.leftJoinAndSelect('replyUser.banner', 'replyUserBanner')
|
|
||||||
.leftJoinAndSelect('renote.user', 'renoteUser')
|
|
||||||
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
|
|
||||||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner');
|
|
||||||
|
|
||||||
if (followees.length > 0) {
|
if (followees.length > 0) {
|
||||||
const meOrFolloweeIds = [me.id, ...followees.map(f => f.followeeId)];
|
const meOrFolloweeIds = [me.id, ...followees.map(f => f.followeeId)];
|
||||||
|
@ -84,16 +84,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId)
|
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId)
|
||||||
.innerJoin(this.userListJoiningsRepository.metadata.targetName, 'userListJoining', 'userListJoining.userId = note.userId')
|
.innerJoin(this.userListJoiningsRepository.metadata.targetName, 'userListJoining', 'userListJoining.userId = note.userId')
|
||||||
.innerJoinAndSelect('note.user', 'user')
|
.innerJoinAndSelect('note.user', 'user')
|
||||||
.leftJoinAndSelect('user.avatar', 'avatar')
|
|
||||||
.leftJoinAndSelect('user.banner', 'banner')
|
|
||||||
.leftJoinAndSelect('note.reply', 'reply')
|
.leftJoinAndSelect('note.reply', 'reply')
|
||||||
.leftJoinAndSelect('note.renote', 'renote')
|
.leftJoinAndSelect('note.renote', 'renote')
|
||||||
.leftJoinAndSelect('reply.user', 'replyUser')
|
.leftJoinAndSelect('reply.user', 'replyUser')
|
||||||
.leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar')
|
|
||||||
.leftJoinAndSelect('replyUser.banner', 'replyUserBanner')
|
|
||||||
.leftJoinAndSelect('renote.user', 'renoteUser')
|
.leftJoinAndSelect('renote.user', 'renoteUser')
|
||||||
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
|
|
||||||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner')
|
|
||||||
.andWhere('userListJoining.userListId = :userListId', { userListId: list.id });
|
.andWhere('userListJoining.userListId = :userListId', { userListId: list.id });
|
||||||
|
|
||||||
this.queryService.generateVisibilityQuery(query, me);
|
this.queryService.generateVisibilityQuery(query, me);
|
||||||
|
@ -74,16 +74,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
|
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
|
||||||
.andWhere('note.userId = :userId', { userId: user.id })
|
.andWhere('note.userId = :userId', { userId: user.id })
|
||||||
.innerJoinAndSelect('note.user', 'user')
|
.innerJoinAndSelect('note.user', 'user')
|
||||||
.leftJoinAndSelect('user.avatar', 'avatar')
|
|
||||||
.leftJoinAndSelect('user.banner', 'banner')
|
|
||||||
.leftJoinAndSelect('note.reply', 'reply')
|
.leftJoinAndSelect('note.reply', 'reply')
|
||||||
.leftJoinAndSelect('note.renote', 'renote')
|
.leftJoinAndSelect('note.renote', 'renote')
|
||||||
.leftJoinAndSelect('reply.user', 'replyUser')
|
.leftJoinAndSelect('reply.user', 'replyUser')
|
||||||
.leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar')
|
.leftJoinAndSelect('renote.user', 'renoteUser');
|
||||||
.leftJoinAndSelect('replyUser.banner', 'replyUserBanner')
|
|
||||||
.leftJoinAndSelect('renote.user', 'renoteUser')
|
|
||||||
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
|
|
||||||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner');
|
|
||||||
|
|
||||||
this.queryService.generateVisibilityQuery(query, me);
|
this.queryService.generateVisibilityQuery(query, me);
|
||||||
if (me) {
|
if (me) {
|
||||||
|
@ -419,7 +419,7 @@ export class ClientServerService {
|
|||||||
reply.header('Cache-Control', 'public, max-age=15');
|
reply.header('Cache-Control', 'public, max-age=15');
|
||||||
return await reply.view('user', {
|
return await reply.view('user', {
|
||||||
user, profile, me,
|
user, profile, me,
|
||||||
avatarUrl: await this.userEntityService.getAvatarUrl(user),
|
avatarUrl: user.avatarUrl ?? this.userEntityService.getIdenticonUrl(user),
|
||||||
sub: request.params.sub,
|
sub: request.params.sub,
|
||||||
instanceName: meta.name ?? 'Misskey',
|
instanceName: meta.name ?? 'Misskey',
|
||||||
icon: meta.iconUrl,
|
icon: meta.iconUrl,
|
||||||
@ -464,7 +464,7 @@ export class ClientServerService {
|
|||||||
return await reply.view('note', {
|
return await reply.view('note', {
|
||||||
note: _note,
|
note: _note,
|
||||||
profile,
|
profile,
|
||||||
avatarUrl: await this.userEntityService.getAvatarUrl(await this.usersRepository.findOneByOrFail({ id: note.userId })),
|
avatarUrl: _note.user.avatarUrl,
|
||||||
// TODO: Let locale changeable by instance setting
|
// TODO: Let locale changeable by instance setting
|
||||||
summary: getNoteSummary(_note),
|
summary: getNoteSummary(_note),
|
||||||
instanceName: meta.name ?? 'Misskey',
|
instanceName: meta.name ?? 'Misskey',
|
||||||
@ -503,7 +503,7 @@ export class ClientServerService {
|
|||||||
return await reply.view('page', {
|
return await reply.view('page', {
|
||||||
page: _page,
|
page: _page,
|
||||||
profile,
|
profile,
|
||||||
avatarUrl: await this.userEntityService.getAvatarUrl(await this.usersRepository.findOneByOrFail({ id: page.userId })),
|
avatarUrl: _page.user.avatarUrl,
|
||||||
instanceName: meta.name ?? 'Misskey',
|
instanceName: meta.name ?? 'Misskey',
|
||||||
icon: meta.iconUrl,
|
icon: meta.iconUrl,
|
||||||
themeColor: meta.themeColor,
|
themeColor: meta.themeColor,
|
||||||
@ -527,7 +527,7 @@ export class ClientServerService {
|
|||||||
return await reply.view('flash', {
|
return await reply.view('flash', {
|
||||||
flash: _flash,
|
flash: _flash,
|
||||||
profile,
|
profile,
|
||||||
avatarUrl: await this.userEntityService.getAvatarUrl(await this.usersRepository.findOneByOrFail({ id: flash.userId })),
|
avatarUrl: _flash.user.avatarUrl,
|
||||||
instanceName: meta.name ?? 'Misskey',
|
instanceName: meta.name ?? 'Misskey',
|
||||||
icon: meta.iconUrl,
|
icon: meta.iconUrl,
|
||||||
themeColor: meta.themeColor,
|
themeColor: meta.themeColor,
|
||||||
@ -551,7 +551,7 @@ export class ClientServerService {
|
|||||||
return await reply.view('clip', {
|
return await reply.view('clip', {
|
||||||
clip: _clip,
|
clip: _clip,
|
||||||
profile,
|
profile,
|
||||||
avatarUrl: await this.userEntityService.getAvatarUrl(await this.usersRepository.findOneByOrFail({ id: clip.userId })),
|
avatarUrl: _clip.user.avatarUrl,
|
||||||
instanceName: meta.name ?? 'Misskey',
|
instanceName: meta.name ?? 'Misskey',
|
||||||
icon: meta.iconUrl,
|
icon: meta.iconUrl,
|
||||||
themeColor: meta.themeColor,
|
themeColor: meta.themeColor,
|
||||||
@ -573,7 +573,7 @@ export class ClientServerService {
|
|||||||
return await reply.view('gallery-post', {
|
return await reply.view('gallery-post', {
|
||||||
post: _post,
|
post: _post,
|
||||||
profile,
|
profile,
|
||||||
avatarUrl: await this.userEntityService.getAvatarUrl(await this.usersRepository.findOneByOrFail({ id: post.userId })),
|
avatarUrl: _post.user.avatarUrl,
|
||||||
instanceName: meta.name ?? 'Misskey',
|
instanceName: meta.name ?? 'Misskey',
|
||||||
icon: meta.iconUrl,
|
icon: meta.iconUrl,
|
||||||
themeColor: meta.themeColor,
|
themeColor: meta.themeColor,
|
||||||
|
@ -58,7 +58,7 @@ export class FeedService {
|
|||||||
generator: 'Misskey',
|
generator: 'Misskey',
|
||||||
description: `${user.notesCount} Notes, ${profile.ffVisibility === 'public' ? user.followingCount : '?'} Following, ${profile.ffVisibility === 'public' ? user.followersCount : '?'} Followers${profile.description ? ` · ${profile.description}` : ''}`,
|
description: `${user.notesCount} Notes, ${profile.ffVisibility === 'public' ? user.followingCount : '?'} Following, ${profile.ffVisibility === 'public' ? user.followersCount : '?'} Followers${profile.description ? ` · ${profile.description}` : ''}`,
|
||||||
link: author.link,
|
link: author.link,
|
||||||
image: await this.userEntityService.getAvatarUrl(user),
|
image: user.avatarUrl ?? this.userEntityService.getIdenticonUrl(user),
|
||||||
feedLinks: {
|
feedLinks: {
|
||||||
json: `${author.link}.json`,
|
json: `${author.link}.json`,
|
||||||
atom: `${author.link}.atom`,
|
atom: `${author.link}.atom`,
|
||||||
|
Loading…
Reference in New Issue
Block a user