Merge branch 'misskey-dev:develop' into notes-embed
This commit is contained in:
commit
bdcaf7a998
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"version": "13.11.0.beta-3",
|
"version": "13.11.0-beta.4",
|
||||||
"codename": "nasubi",
|
"codename": "nasubi",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -50,13 +50,13 @@
|
||||||
"gulp-replace": "1.1.4",
|
"gulp-replace": "1.1.4",
|
||||||
"gulp-terser": "2.1.0",
|
"gulp-terser": "2.1.0",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
"typescript": "5.0.2"
|
"typescript": "5.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/gulp": "4.0.10",
|
"@types/gulp": "4.0.10",
|
||||||
"@types/gulp-rename": "2.0.1",
|
"@types/gulp-rename": "2.0.1",
|
||||||
"@typescript-eslint/eslint-plugin": "5.57.0",
|
"@typescript-eslint/eslint-plugin": "5.57.1",
|
||||||
"@typescript-eslint/parser": "5.57.0",
|
"@typescript-eslint/parser": "5.57.1",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"cypress": "12.9.0",
|
"cypress": "12.9.0",
|
||||||
"eslint": "8.37.0",
|
"eslint": "8.37.0",
|
||||||
|
|
|
@ -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"`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,24 +22,24 @@
|
||||||
"test-and-coverage": "pnpm jest-and-coverage"
|
"test-and-coverage": "pnpm jest-and-coverage"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@swc/core-android-arm64": "^1.3.11",
|
"@swc/core-android-arm64": "1.3.11",
|
||||||
"@swc/core-darwin-arm64": "^1.3.42",
|
"@swc/core-darwin-arm64": "1.3.46",
|
||||||
"@swc/core-darwin-x64": "^1.3.42",
|
"@swc/core-darwin-x64": "1.3.46",
|
||||||
"@swc/core-linux-arm-gnueabihf": "^1.3.42",
|
"@swc/core-linux-arm-gnueabihf": "1.3.46",
|
||||||
"@swc/core-linux-arm64-gnu": "^1.3.42",
|
"@swc/core-linux-arm64-gnu": "1.3.46",
|
||||||
"@swc/core-linux-arm64-musl": "^1.3.42",
|
"@swc/core-linux-arm64-musl": "1.3.46",
|
||||||
"@swc/core-linux-x64-gnu": "^1.3.42",
|
"@swc/core-linux-x64-gnu": "1.3.46",
|
||||||
"@swc/core-linux-x64-musl": "^1.3.42",
|
"@swc/core-linux-x64-musl": "1.3.46",
|
||||||
"@swc/core-win32-arm64-msvc": "^1.3.42",
|
"@swc/core-win32-arm64-msvc": "1.3.46",
|
||||||
"@swc/core-win32-ia32-msvc": "^1.3.42",
|
"@swc/core-win32-ia32-msvc": "1.3.46",
|
||||||
"@swc/core-win32-x64-msvc": "^1.3.42",
|
"@swc/core-win32-x64-msvc": "1.3.46",
|
||||||
"@tensorflow/tfjs": "4.2.0",
|
"@tensorflow/tfjs": "4.2.0",
|
||||||
"@tensorflow/tfjs-node": "4.2.0"
|
"@tensorflow/tfjs-node": "4.2.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "3.301.0",
|
"@aws-sdk/client-s3": "3.306.0",
|
||||||
"@aws-sdk/lib-storage": "3.301.0",
|
"@aws-sdk/lib-storage": "3.306.0",
|
||||||
"@aws-sdk/node-http-handler": "3.296.0",
|
"@aws-sdk/node-http-handler": "3.306.0",
|
||||||
"@bull-board/api": "5.0.0",
|
"@bull-board/api": "5.0.0",
|
||||||
"@bull-board/fastify": "5.0.0",
|
"@bull-board/fastify": "5.0.0",
|
||||||
"@bull-board/ui": "5.0.0",
|
"@bull-board/ui": "5.0.0",
|
||||||
|
@ -49,15 +49,15 @@
|
||||||
"@fastify/cors": "8.2.1",
|
"@fastify/cors": "8.2.1",
|
||||||
"@fastify/http-proxy": "9.0.0",
|
"@fastify/http-proxy": "9.0.0",
|
||||||
"@fastify/multipart": "7.5.0",
|
"@fastify/multipart": "7.5.0",
|
||||||
"@fastify/static": "6.9.0",
|
"@fastify/static": "6.10.0",
|
||||||
"@fastify/view": "7.4.1",
|
"@fastify/view": "7.4.1",
|
||||||
"@nestjs/common": "9.3.12",
|
"@nestjs/common": "9.4.0",
|
||||||
"@nestjs/core": "9.3.12",
|
"@nestjs/core": "9.4.0",
|
||||||
"@nestjs/testing": "9.3.12",
|
"@nestjs/testing": "9.4.0",
|
||||||
"@peertube/http-signature": "1.7.0",
|
"@peertube/http-signature": "1.7.0",
|
||||||
"@sinonjs/fake-timers": "10.0.2",
|
"@sinonjs/fake-timers": "10.0.2",
|
||||||
"@swc/cli": "0.1.62",
|
"@swc/cli": "0.1.62",
|
||||||
"@swc/core": "1.3.42",
|
"@swc/core": "1.3.46",
|
||||||
"accepts": "1.3.8",
|
"accepts": "1.3.8",
|
||||||
"ajv": "8.12.0",
|
"ajv": "8.12.0",
|
||||||
"archiver": "5.3.1",
|
"archiver": "5.3.1",
|
||||||
|
@ -136,8 +136,8 @@
|
||||||
"tsc-alias": "1.8.5",
|
"tsc-alias": "1.8.5",
|
||||||
"tsconfig-paths": "4.2.0",
|
"tsconfig-paths": "4.2.0",
|
||||||
"twemoji-parser": "14.0.0",
|
"twemoji-parser": "14.0.0",
|
||||||
"typeorm": "0.3.11",
|
"typeorm": "0.3.13",
|
||||||
"typescript": "5.0.2",
|
"typescript": "5.0.3",
|
||||||
"ulid": "2.3.0",
|
"ulid": "2.3.0",
|
||||||
"unzipper": "0.10.11",
|
"unzipper": "0.10.11",
|
||||||
"uuid": "9.0.0",
|
"uuid": "9.0.0",
|
||||||
|
@ -190,8 +190,8 @@
|
||||||
"@types/web-push": "3.3.2",
|
"@types/web-push": "3.3.2",
|
||||||
"@types/websocket": "1.0.5",
|
"@types/websocket": "1.0.5",
|
||||||
"@types/ws": "8.5.4",
|
"@types/ws": "8.5.4",
|
||||||
"@typescript-eslint/eslint-plugin": "5.57.0",
|
"@typescript-eslint/eslint-plugin": "5.57.1",
|
||||||
"@typescript-eslint/parser": "5.57.0",
|
"@typescript-eslint/parser": "5.57.1",
|
||||||
"aws-sdk-client-mock": "^2.1.1",
|
"aws-sdk-client-mock": "^2.1.1",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"eslint": "8.37.0",
|
"eslint": "8.37.0",
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -266,6 +266,7 @@ export class DriveFileEntityService {
|
||||||
fileIds: DriveFile['id'][],
|
fileIds: DriveFile['id'][],
|
||||||
options?: PackOptions,
|
options?: PackOptions,
|
||||||
): Promise<Map<Packed<'DriveFile'>['id'], Packed<'DriveFile'> | null>> {
|
): Promise<Map<Packed<'DriveFile'>['id'], Packed<'DriveFile'> | null>> {
|
||||||
|
if (fileIds.length === 0) return new Map();
|
||||||
const files = await this.driveFilesRepository.findBy({ id: In(fileIds) });
|
const files = await this.driveFilesRepository.findBy({ id: In(fileIds) });
|
||||||
const packedFiles = await this.packMany(files, options);
|
const packedFiles = await this.packMany(files, options);
|
||||||
const map = new Map<Packed<'DriveFile'>['id'], Packed<'DriveFile'> | null>(packedFiles.map(f => [f.id, f]));
|
const map = new Map<Packed<'DriveFile'>['id'], Packed<'DriveFile'> | null>(packedFiles.map(f => [f.id, f]));
|
||||||
|
@ -280,6 +281,7 @@ export class DriveFileEntityService {
|
||||||
fileIds: DriveFile['id'][],
|
fileIds: DriveFile['id'][],
|
||||||
options?: PackOptions,
|
options?: PackOptions,
|
||||||
): Promise<Packed<'DriveFile'>[]> {
|
): Promise<Packed<'DriveFile'>[]> {
|
||||||
|
if (fileIds.length === 0) return [];
|
||||||
const filesMap = await this.packManyByIdsMap(fileIds, options);
|
const filesMap = await this.packManyByIdsMap(fileIds, options);
|
||||||
return fileIds.map(id => filesMap.get(id)).filter(isNotNull);
|
return fileIds.map(id => filesMap.get(id)).filter(isNotNull);
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,6 +183,11 @@ export class NoteEntityService implements OnModuleInit {
|
||||||
// 実装上抜けがあるだけかもしれないので、「ヒントに含まれてなかったら(=undefinedなら)return」のようにはしない
|
// 実装上抜けがあるだけかもしれないので、「ヒントに含まれてなかったら(=undefinedなら)return」のようにはしない
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// パフォーマンスのためノートが作成されてから1秒以上経っていない場合はリアクションを取得しない
|
||||||
|
if (note.createdAt.getTime() + 1000 > Date.now()) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
const reaction = await this.noteReactionsRepository.findOneBy({
|
const reaction = await this.noteReactionsRepository.findOneBy({
|
||||||
userId: meId,
|
userId: meId,
|
||||||
noteId: note.id,
|
noteId: note.id,
|
||||||
|
@ -395,7 +400,8 @@ export class NoteEntityService implements OnModuleInit {
|
||||||
const myReactionsMap = new Map<Note['id'], NoteReaction | null>();
|
const myReactionsMap = new Map<Note['id'], NoteReaction | null>();
|
||||||
if (meId) {
|
if (meId) {
|
||||||
const renoteIds = notes.filter(n => n.renoteId != null).map(n => n.renoteId!);
|
const renoteIds = notes.filter(n => n.renoteId != null).map(n => n.renoteId!);
|
||||||
const targets = [...notes.map(n => n.id), ...renoteIds];
|
// パフォーマンスのためノートが作成されてから1秒以上経っていない場合はリアクションを取得しない
|
||||||
|
const targets = [...notes.filter(n => n.createdAt.getTime() + 1000 < Date.now()).map(n => n.id), ...renoteIds];
|
||||||
const myReactions = await this.noteReactionsRepository.findBy({
|
const myReactions = await this.noteReactionsRepository.findBy({
|
||||||
userId: meId,
|
userId: meId,
|
||||||
noteId: In(targets),
|
noteId: In(targets),
|
||||||
|
@ -409,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,
|
||||||
|
|
|
@ -108,27 +108,30 @@ export class NotificationEntityService implements OnModuleInit {
|
||||||
) {
|
) {
|
||||||
if (notifications.length === 0) return [];
|
if (notifications.length === 0) return [];
|
||||||
|
|
||||||
const noteIds = notifications.map(x => x.noteId).filter(isNotNull);
|
let validNotifications = notifications;
|
||||||
|
|
||||||
|
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,
|
||||||
});
|
});
|
||||||
const packedNotes = new Map(packedNotesArray.map(p => [p.id, p]));
|
const packedNotes = new Map(packedNotesArray.map(p => [p.id, p]));
|
||||||
|
|
||||||
const userIds = notifications.map(x => x.notifierId).filter(isNotNull);
|
validNotifications = validNotifications.filter(x => x.noteId == null || packedNotes.has(x.noteId));
|
||||||
|
|
||||||
|
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,
|
||||||
});
|
});
|
||||||
const packedUsers = new Map(packedUsersArray.map(p => [p.id, p]));
|
const packedUsers = new Map(packedUsersArray.map(p => [p.id, p]));
|
||||||
|
|
||||||
return await Promise.all(notifications.map(x => this.pack(x, meId, {}, {
|
return await Promise.all(validNotifications.map(x => this.pack(x, meId, {}, {
|
||||||
packedNotes,
|
packedNotes,
|
||||||
packedUsers,
|
packedUsers,
|
||||||
})));
|
})));
|
||||||
|
|
|
@ -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',
|
||||||
|
@ -511,7 +511,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,
|
||||||
|
@ -535,7 +535,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,
|
||||||
|
@ -559,7 +559,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,
|
||||||
|
@ -581,7 +581,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`,
|
||||||
|
|
|
@ -59,13 +59,13 @@
|
||||||
"strict-event-emitter-types": "2.0.0",
|
"strict-event-emitter-types": "2.0.0",
|
||||||
"syuilo-password-strength": "0.0.1",
|
"syuilo-password-strength": "0.0.1",
|
||||||
"textarea-caret": "3.1.0",
|
"textarea-caret": "3.1.0",
|
||||||
"three": "0.150.1",
|
"three": "0.151.3",
|
||||||
"throttle-debounce": "5.0.0",
|
"throttle-debounce": "5.0.0",
|
||||||
"tinycolor2": "1.6.0",
|
"tinycolor2": "1.6.0",
|
||||||
"tsc-alias": "1.8.5",
|
"tsc-alias": "1.8.5",
|
||||||
"tsconfig-paths": "4.2.0",
|
"tsconfig-paths": "4.2.0",
|
||||||
"twemoji-parser": "14.0.0",
|
"twemoji-parser": "14.0.0",
|
||||||
"typescript": "5.0.2",
|
"typescript": "5.0.3",
|
||||||
"uuid": "9.0.0",
|
"uuid": "9.0.0",
|
||||||
"vanilla-tilt": "1.8.0",
|
"vanilla-tilt": "1.8.0",
|
||||||
"vite": "4.2.1",
|
"vite": "4.2.1",
|
||||||
|
@ -92,10 +92,10 @@
|
||||||
"@storybook/types": "7.0.2",
|
"@storybook/types": "7.0.2",
|
||||||
"@storybook/vue3": "7.0.2",
|
"@storybook/vue3": "7.0.2",
|
||||||
"@storybook/vue3-vite": "7.0.2",
|
"@storybook/vue3-vite": "7.0.2",
|
||||||
"@testing-library/jest-dom": "^5.16.5",
|
"@testing-library/jest-dom": "5.16.5",
|
||||||
"@testing-library/vue": "^6.6.1",
|
"@testing-library/vue": "7.0.0",
|
||||||
"@types/escape-regexp": "0.0.1",
|
"@types/escape-regexp": "0.0.1",
|
||||||
"@types/estree": "^1.0.0",
|
"@types/estree": "1.0.0",
|
||||||
"@types/gulp": "4.0.10",
|
"@types/gulp": "4.0.10",
|
||||||
"@types/gulp-rename": "2.0.1",
|
"@types/gulp-rename": "2.0.1",
|
||||||
"@types/iframe-resizer": "^3.5.9",
|
"@types/iframe-resizer": "^3.5.9",
|
||||||
|
@ -110,32 +110,32 @@
|
||||||
"@types/uuid": "9.0.1",
|
"@types/uuid": "9.0.1",
|
||||||
"@types/websocket": "1.0.5",
|
"@types/websocket": "1.0.5",
|
||||||
"@types/ws": "8.5.4",
|
"@types/ws": "8.5.4",
|
||||||
"@typescript-eslint/eslint-plugin": "5.57.0",
|
"@typescript-eslint/eslint-plugin": "5.57.1",
|
||||||
"@typescript-eslint/parser": "5.57.0",
|
"@typescript-eslint/parser": "5.57.1",
|
||||||
"@vitest/coverage-c8": "^0.29.8",
|
"@vitest/coverage-c8": "^0.29.8",
|
||||||
"@vue/runtime-core": "3.2.47",
|
"@vue/runtime-core": "3.2.47",
|
||||||
"astring": "^1.8.4",
|
"astring": "^1.8.4",
|
||||||
"chokidar-cli": "^3.0.0",
|
"chokidar-cli": "^3.0.0",
|
||||||
"chromatic": "^6.17.2",
|
"chromatic": "6.17.3",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"cypress": "12.9.0",
|
"cypress": "12.9.0",
|
||||||
"eslint": "8.37.0",
|
"eslint": "8.37.0",
|
||||||
"eslint-plugin-import": "2.27.5",
|
"eslint-plugin-import": "2.27.5",
|
||||||
"eslint-plugin-vue": "9.10.0",
|
"eslint-plugin-vue": "9.10.0",
|
||||||
"fast-glob": "^3.2.12",
|
"fast-glob": "3.2.12",
|
||||||
"happy-dom": "8.9.0",
|
"happy-dom": "8.9.0",
|
||||||
"msw": "^1.1.0",
|
"msw": "1.2.1",
|
||||||
"msw-storybook-addon": "^1.8.0",
|
"msw-storybook-addon": "1.8.0",
|
||||||
"prettier": "^2.8.4",
|
"prettier": "2.8.7",
|
||||||
"react": "^18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"start-server-and-test": "2.0.0",
|
"start-server-and-test": "2.0.0",
|
||||||
"storybook": "7.0.2",
|
"storybook": "7.0.2",
|
||||||
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
|
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
|
||||||
"summaly": "github:misskey-dev/summaly",
|
"summaly": "github:misskey-dev/summaly",
|
||||||
"vitest": "^0.29.8",
|
"vitest": "0.29.8",
|
||||||
"vitest-fetch-mock": "^0.2.2",
|
"vitest-fetch-mock": "0.2.2",
|
||||||
"vue-eslint-parser": "9.1.0",
|
"vue-eslint-parser": "9.1.1",
|
||||||
"vue-tsc": "1.2.0"
|
"vue-tsc": "1.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,6 +217,7 @@ const patrons = [
|
||||||
'氷月氷華里',
|
'氷月氷華里',
|
||||||
'Ebise Lutica',
|
'Ebise Lutica',
|
||||||
'巣黒るい@リスケモ男の娘VTuber!',
|
'巣黒るい@リスケモ男の娘VTuber!',
|
||||||
|
'ふぇいぽむ',
|
||||||
];
|
];
|
||||||
|
|
||||||
let thereIsTreasure = $ref($i && !claimedAchievements.includes('foundTreasure'));
|
let thereIsTreasure = $ref($i && !claimedAchievements.includes('foundTreasure'));
|
||||||
|
|
|
@ -24,23 +24,23 @@
|
||||||
"@swc/jest": "0.2.24",
|
"@swc/jest": "0.2.24",
|
||||||
"@types/jest": "29.5.0",
|
"@types/jest": "29.5.0",
|
||||||
"@types/node": "18.15.11",
|
"@types/node": "18.15.11",
|
||||||
"@typescript-eslint/eslint-plugin": "5.57.0",
|
"@typescript-eslint/eslint-plugin": "5.57.1",
|
||||||
"@typescript-eslint/parser": "5.57.0",
|
"@typescript-eslint/parser": "5.57.1",
|
||||||
"eslint": "8.37.0",
|
"eslint": "8.37.0",
|
||||||
"jest": "^29.5.0",
|
"jest": "29.5.0",
|
||||||
"jest-fetch-mock": "^3.0.3",
|
"jest-fetch-mock": "3.0.3",
|
||||||
"jest-websocket-mock": "2.4.0",
|
"jest-websocket-mock": "2.4.0",
|
||||||
"mock-socket": "9.2.1",
|
"mock-socket": "9.2.1",
|
||||||
"tsd": "0.28.1",
|
"tsd": "0.28.1",
|
||||||
"typescript": "5.0.2"
|
"typescript": "5.0.3"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"built"
|
"built"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@swc/cli": "0.1.62",
|
"@swc/cli": "0.1.62",
|
||||||
"@swc/core": "1.3.42",
|
"@swc/core": "1.3.46",
|
||||||
"eventemitter3": "5.0.0",
|
"eventemitter3": "5.0.0",
|
||||||
"reconnecting-websocket": "^4.4.0"
|
"reconnecting-websocket": "4.4.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,10 @@
|
||||||
"misskey-js": "workspace:*"
|
"misskey-js": "workspace:*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@typescript-eslint/parser": "5.57.0",
|
"@typescript-eslint/parser": "5.57.1",
|
||||||
"@typescript/lib-webworker": "npm:@types/serviceworker@0.0.67",
|
"@typescript/lib-webworker": "npm:@types/serviceworker@0.0.67",
|
||||||
"eslint": "8.37.0",
|
"eslint": "8.37.0",
|
||||||
"eslint-plugin-import": "2.27.5",
|
"eslint-plugin-import": "2.27.5",
|
||||||
"typescript": "5.0.2"
|
"typescript": "5.0.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1642
pnpm-lock.yaml
1642
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue