mirror of
https://iceshrimp.dev/limepotato/jormungandr-bite.git
synced 2024-11-28 21:08:52 -07:00
[backend] Include avatar & banner url and blurhash in the user table
This drastically improves timeline performance due to the many (2-6 per query) database joins that are now no longer required
This commit is contained in:
parent
6e82e18eea
commit
302b112f05
28 changed files with 142 additions and 165 deletions
|
@ -0,0 +1,32 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class UserAvatarBannerRefactor1700517975122 implements MigrationInterface {
|
||||||
|
name = 'UserAvatarBannerRefactor1700517975122'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" ADD "avatarUrl" character varying(512)`);
|
||||||
|
await queryRunner.query(`COMMENT ON COLUMN "user"."avatarUrl" IS 'The URL of the avatar DriveFile'`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" ADD "avatarBlurhash" character varying(128)`);
|
||||||
|
await queryRunner.query(`COMMENT ON COLUMN "user"."avatarBlurhash" IS 'The blurhash of the avatar DriveFile'`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" ADD "bannerUrl" character varying(512)`);
|
||||||
|
await queryRunner.query(`COMMENT ON COLUMN "user"."bannerUrl" IS 'The URL of the banner DriveFile'`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" ADD "bannerBlurhash" character varying(128)`);
|
||||||
|
await queryRunner.query(`COMMENT ON COLUMN "user"."bannerBlurhash" IS 'The blurhash of the banner DriveFile'`);
|
||||||
|
|
||||||
|
await queryRunner.query(`UPDATE "user" SET "avatarUrl" = (SELECT COALESCE("thumbnailUrl", "webpublicUrl", "url") FROM "drive_file" WHERE "id" = "user"."avatarId") WHERE "avatarId" IS NOT NULL`);
|
||||||
|
await queryRunner.query(`UPDATE "user" SET "avatarBlurhash" = (SELECT "blurhash" FROM "drive_file" WHERE "id" = "user"."avatarId") WHERE "avatarId" IS NOT NULL`);
|
||||||
|
await queryRunner.query(`UPDATE "user" SET "bannerUrl" = (SELECT COALESCE("webpublicUrl", "url") FROM "drive_file" WHERE "id" = "user"."bannerId") WHERE "bannerId" IS NOT NULL`);
|
||||||
|
await queryRunner.query(`UPDATE "user" SET "bannerBlurhash" = (SELECT "blurhash" FROM "drive_file" WHERE "id" = "user"."bannerId") WHERE "bannerId" IS NOT NULL`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`COMMENT ON COLUMN "user"."bannerBlurhash" IS 'The blurhash of the banner DriveFile'`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "bannerBlurhash"`);
|
||||||
|
await queryRunner.query(`COMMENT ON COLUMN "user"."bannerUrl" IS 'The URL of the banner DriveFile'`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "bannerUrl"`);
|
||||||
|
await queryRunner.query(`COMMENT ON COLUMN "user"."avatarBlurhash" IS 'The blurhash of the avatar DriveFile'`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "avatarBlurhash"`);
|
||||||
|
await queryRunner.query(`COMMENT ON COLUMN "user"."avatarUrl" IS 'The URL of the avatar DriveFile'`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "avatarUrl"`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -103,6 +103,20 @@ export class User {
|
||||||
})
|
})
|
||||||
public avatarId: DriveFile["id"] | null;
|
public avatarId: DriveFile["id"] | null;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
length: 512,
|
||||||
|
nullable: true,
|
||||||
|
comment: "The URL of the avatar DriveFile",
|
||||||
|
})
|
||||||
|
public avatarUrl: string | null;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
length: 128,
|
||||||
|
nullable: true,
|
||||||
|
comment: "The blurhash of the avatar DriveFile",
|
||||||
|
})
|
||||||
|
public avatarBlurhash: string | null;
|
||||||
|
|
||||||
@OneToOne((type) => DriveFile, {
|
@OneToOne((type) => DriveFile, {
|
||||||
onDelete: "SET NULL",
|
onDelete: "SET NULL",
|
||||||
})
|
})
|
||||||
|
@ -116,6 +130,20 @@ export class User {
|
||||||
})
|
})
|
||||||
public bannerId: DriveFile["id"] | null;
|
public bannerId: DriveFile["id"] | null;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
length: 512,
|
||||||
|
nullable: true,
|
||||||
|
comment: "The URL of the banner DriveFile",
|
||||||
|
})
|
||||||
|
public bannerUrl: string | null;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
length: 128,
|
||||||
|
nullable: true,
|
||||||
|
comment: "The blurhash of the banner DriveFile",
|
||||||
|
})
|
||||||
|
public bannerBlurhash: string | null;
|
||||||
|
|
||||||
@OneToOne((type) => DriveFile, {
|
@OneToOne((type) => DriveFile, {
|
||||||
onDelete: "SET NULL",
|
onDelete: "SET NULL",
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,13 +2,11 @@ import { db } from "@/db/postgre.js";
|
||||||
import { DriveFile } from "@/models/entities/drive-file.js";
|
import { DriveFile } from "@/models/entities/drive-file.js";
|
||||||
import type { User } from "@/models/entities/user.js";
|
import type { User } from "@/models/entities/user.js";
|
||||||
import { toPuny } from "@/misc/convert-host.js";
|
import { toPuny } from "@/misc/convert-host.js";
|
||||||
import { awaitAll, Promiseable } from "@/prelude/await-all.js";
|
import { awaitAll } from "@/prelude/await-all.js";
|
||||||
import type { Packed } from "@/misc/schema.js";
|
import type { Packed } from "@/misc/schema.js";
|
||||||
import config from "@/config/index.js";
|
import config from "@/config/index.js";
|
||||||
import { query, appendQuery } from "@/prelude/url.js";
|
import { appendQuery, query } from "@/prelude/url.js";
|
||||||
import { Meta } from "@/models/entities/meta.js";
|
import { DriveFolders, Users } from "../index.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
|
||||||
import { Users, DriveFolders } from "../index.js";
|
|
||||||
import { deepClone } from "@/misc/clone.js";
|
import { deepClone } from "@/misc/clone.js";
|
||||||
|
|
||||||
type PackOptions = {
|
type PackOptions = {
|
||||||
|
@ -44,6 +42,19 @@ export const DriveFileRepository = db.getRepository(DriveFile).extend({
|
||||||
return file.properties;
|
return file.properties;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isImage(file: DriveFile): boolean {
|
||||||
|
return !!file.type &&
|
||||||
|
[
|
||||||
|
"image/png",
|
||||||
|
"image/apng",
|
||||||
|
"image/gif",
|
||||||
|
"image/jpeg",
|
||||||
|
"image/webp",
|
||||||
|
"image/svg+xml",
|
||||||
|
"image/avif",
|
||||||
|
].includes(file.type);
|
||||||
|
},
|
||||||
|
|
||||||
getPublicUrl(file: DriveFile, thumbnail = false): string | null {
|
getPublicUrl(file: DriveFile, thumbnail = false): string | null {
|
||||||
// リモートかつメディアプロキシ
|
// リモートかつメディアプロキシ
|
||||||
if (
|
if (
|
||||||
|
@ -70,23 +81,17 @@ export const DriveFileRepository = db.getRepository(DriveFile).extend({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const isImage =
|
|
||||||
file.type &&
|
|
||||||
[
|
|
||||||
"image/png",
|
|
||||||
"image/apng",
|
|
||||||
"image/gif",
|
|
||||||
"image/jpeg",
|
|
||||||
"image/webp",
|
|
||||||
"image/svg+xml",
|
|
||||||
"image/avif",
|
|
||||||
].includes(file.type);
|
|
||||||
|
|
||||||
return thumbnail
|
return thumbnail
|
||||||
? file.thumbnailUrl || (isImage ? file.webpublicUrl || file.url : null)
|
? file.thumbnailUrl || (this.isImage(file) ? file.webpublicUrl || file.url : null)
|
||||||
: file.webpublicUrl || file.url;
|
: file.webpublicUrl || file.url;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getDatabasePrefetchUrl(file: DriveFile, thumbnail = false): string | null {
|
||||||
|
return thumbnail
|
||||||
|
? file.thumbnailUrl ?? file.webpublicUrl ?? file.url
|
||||||
|
: file.webpublicUrl ?? file.url;
|
||||||
|
},
|
||||||
|
|
||||||
async calcDriveUsageOf(
|
async calcDriveUsageOf(
|
||||||
user: User["id"] | { id: User["id"] },
|
user: User["id"] | { id: User["id"] },
|
||||||
): Promise<number> {
|
): Promise<number> {
|
||||||
|
|
|
@ -339,6 +339,7 @@ export const UserRepository = db.getRepository(User).extend({
|
||||||
this.getIdenticonUrl(user.id)
|
this.getIdenticonUrl(user.id)
|
||||||
);
|
);
|
||||||
} else if (user.avatarId) {
|
} else if (user.avatarId) {
|
||||||
|
if (user.avatarUrl) return user.avatarUrl;
|
||||||
const avatar = await DriveFiles.findOneByOrFail({ id: user.avatarId });
|
const avatar = await DriveFiles.findOneByOrFail({ id: user.avatarId });
|
||||||
return (
|
return (
|
||||||
DriveFiles.getPublicUrl(avatar, true) || this.getIdenticonUrl(user.id)
|
DriveFiles.getPublicUrl(avatar, true) || this.getIdenticonUrl(user.id)
|
||||||
|
@ -349,7 +350,9 @@ export const UserRepository = db.getRepository(User).extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
getAvatarUrlSync(user: User): string {
|
getAvatarUrlSync(user: User): string {
|
||||||
if (user.avatar) {
|
if (user.avatarId && user.avatarUrl) {
|
||||||
|
return user.avatarUrl;
|
||||||
|
} else if (user.avatar) {
|
||||||
return (
|
return (
|
||||||
DriveFiles.getPublicUrl(user.avatar, true) ||
|
DriveFiles.getPublicUrl(user.avatar, true) ||
|
||||||
this.getIdenticonUrl(user.id)
|
this.getIdenticonUrl(user.id)
|
||||||
|
@ -388,17 +391,9 @@ export const UserRepository = db.getRepository(User).extend({
|
||||||
|
|
||||||
if (typeof src === "object") {
|
if (typeof src === "object") {
|
||||||
user = src;
|
user = src;
|
||||||
if (src.avatar === undefined && src.avatarId)
|
|
||||||
src.avatar = (await DriveFiles.findOneBy({ id: src.avatarId })) ?? null;
|
|
||||||
if (src.banner === undefined && src.bannerId)
|
|
||||||
src.banner = (await DriveFiles.findOneBy({ id: src.bannerId })) ?? null;
|
|
||||||
} else {
|
} else {
|
||||||
user = await this.findOneOrFail({
|
user = await this.findOneOrFail({
|
||||||
where: { id: src },
|
where: { id: src },
|
||||||
relations: {
|
|
||||||
avatar: true,
|
|
||||||
banner: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,7 +469,7 @@ export const UserRepository = db.getRepository(User).extend({
|
||||||
username: user.username,
|
username: user.username,
|
||||||
host: user.host,
|
host: user.host,
|
||||||
avatarUrl: this.getAvatarUrlSync(user),
|
avatarUrl: this.getAvatarUrlSync(user),
|
||||||
avatarBlurhash: user.avatar?.blurhash || null,
|
avatarBlurhash: user.avatarId ? (user.avatarBlurhash ?? user.avatar?.blurhash ?? null) : null,
|
||||||
avatarColor: null, // 後方互換性のため
|
avatarColor: null, // 後方互換性のため
|
||||||
isAdmin: user.isAdmin || falsy,
|
isAdmin: user.isAdmin || falsy,
|
||||||
isModerator: user.isModerator || falsy,
|
isModerator: user.isModerator || falsy,
|
||||||
|
@ -519,10 +514,10 @@ export const UserRepository = db.getRepository(User).extend({
|
||||||
lastFetchedAt: user.lastFetchedAt
|
lastFetchedAt: user.lastFetchedAt
|
||||||
? user.lastFetchedAt.toISOString()
|
? user.lastFetchedAt.toISOString()
|
||||||
: null,
|
: null,
|
||||||
bannerUrl: user.banner
|
bannerUrl: user.bannerId ? (user.bannerUrl ?? (user.banner
|
||||||
? DriveFiles.getPublicUrl(user.banner, false)
|
? DriveFiles.getPublicUrl(user.banner, false)
|
||||||
: null,
|
: null)) : null,
|
||||||
bannerBlurhash: user.banner?.blurhash || null,
|
bannerBlurhash: user.bannerId ? (user.bannerBlurhash ?? user.banner?.blurhash ?? null) : null,
|
||||||
bannerColor: null, // 後方互換性のため
|
bannerColor: null, // 後方互換性のため
|
||||||
isSilenced: user.isSilenced || falsy,
|
isSilenced: user.isSilenced || falsy,
|
||||||
isSuspended: user.isSuspended || falsy,
|
isSuspended: user.isSuspended || falsy,
|
||||||
|
|
|
@ -409,16 +409,28 @@ export async function createPerson(
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
const avatarId = avatar ? avatar.id : null;
|
const avatarId = avatar?.id ?? null;
|
||||||
const bannerId = banner ? banner.id : null;
|
const avatarBlurhash = avatar?.blurhash ?? null;
|
||||||
|
const avatarUrl = avatar ? DriveFiles.getDatabasePrefetchUrl(avatar, true) : null;
|
||||||
|
const bannerId = banner?.id ?? null;
|
||||||
|
const bannerBlurhash = banner?.blurhash ?? null;
|
||||||
|
const bannerUrl = banner ? DriveFiles.getDatabasePrefetchUrl(banner, false) : null;
|
||||||
|
|
||||||
await Users.update(user!.id, {
|
await Users.update(user!.id, {
|
||||||
avatarId,
|
avatarId,
|
||||||
|
avatarBlurhash,
|
||||||
|
avatarUrl,
|
||||||
bannerId,
|
bannerId,
|
||||||
|
bannerBlurhash,
|
||||||
|
bannerUrl,
|
||||||
});
|
});
|
||||||
|
|
||||||
user!.avatarId = avatarId;
|
user!.avatarId = avatarId;
|
||||||
|
user!.avatarBlurhash = avatarBlurhash;
|
||||||
|
user!.avatarUrl = avatarUrl;
|
||||||
user!.bannerId = bannerId;
|
user!.bannerId = bannerId;
|
||||||
|
user!.bannerBlurhash = bannerBlurhash;
|
||||||
|
user!.bannerUrl = bannerUrl;
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region Get custom emoji
|
//#region Get custom emoji
|
||||||
|
@ -576,10 +588,14 @@ export async function updatePerson(
|
||||||
|
|
||||||
if (avatar) {
|
if (avatar) {
|
||||||
updates.avatarId = avatar.id;
|
updates.avatarId = avatar.id;
|
||||||
|
updates.avatarUrl = DriveFiles.getDatabasePrefetchUrl(avatar, true);
|
||||||
|
updates.avatarBlurhash = avatar.blurhash;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (banner) {
|
if (banner) {
|
||||||
updates.bannerId = banner.id;
|
updates.bannerId = banner.id;
|
||||||
|
updates.bannerUrl = DriveFiles.getDatabasePrefetchUrl(banner, false);
|
||||||
|
updates.bannerBlurhash = banner.blurhash;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (host) {
|
if (host) {
|
||||||
|
|
|
@ -97,16 +97,10 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
const query = makePaginationQuery(Notes.createQueryBuilder("note"))
|
const query = makePaginationQuery(Notes.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")
|
|
||||||
.andWhere("note.visibility != 'home'");
|
.andWhere("note.visibility != 'home'");
|
||||||
|
|
||||||
generateVisibilityQuery(query, user);
|
generateVisibilityQuery(query, user);
|
||||||
|
|
|
@ -62,16 +62,10 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
)
|
)
|
||||||
.andWhere("note.channelId = :channelId", { channelId: channel.id })
|
.andWhere("note.channelId = :channelId", { channelId: channel.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")
|
|
||||||
.leftJoinAndSelect("note.channel", "channel");
|
.leftJoinAndSelect("note.channel", "channel");
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
|
|
@ -70,16 +70,10 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
"clipNote.noteId = note.id",
|
"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 (user) {
|
if (user) {
|
||||||
|
|
|
@ -100,16 +100,10 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
.leftJoinAndSelect("notifier.avatar", "notifierAvatar")
|
.leftJoinAndSelect("notifier.avatar", "notifierAvatar")
|
||||||
.leftJoinAndSelect("notifier.banner", "notifierBanner")
|
.leftJoinAndSelect("notifier.banner", "notifierBanner")
|
||||||
.leftJoinAndSelect("note.user", "user")
|
.leftJoinAndSelect("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");
|
|
||||||
|
|
||||||
// muted users
|
// muted users
|
||||||
query.andWhere(
|
query.andWhere(
|
||||||
|
|
|
@ -215,22 +215,27 @@ export default define(meta, paramDef, async (ps, _user, token) => {
|
||||||
if (ps.emailNotificationTypes !== undefined)
|
if (ps.emailNotificationTypes !== undefined)
|
||||||
profileUpdates.emailNotificationTypes = ps.emailNotificationTypes;
|
profileUpdates.emailNotificationTypes = ps.emailNotificationTypes;
|
||||||
|
|
||||||
if (ps.avatarId) {
|
const avatar = ps.avatarId ? await DriveFiles.findOneBy({ id: ps.avatarId }) : null;
|
||||||
const avatar = await DriveFiles.findOneBy({ id: ps.avatarId });
|
const banner = ps.bannerId ? await DriveFiles.findOneBy({ id: ps.bannerId }) : null;
|
||||||
|
|
||||||
|
if (ps.avatarId) {
|
||||||
if (avatar == null || avatar.userId !== user.id)
|
if (avatar == null || avatar.userId !== user.id)
|
||||||
throw new ApiError(meta.errors.noSuchAvatar);
|
throw new ApiError(meta.errors.noSuchAvatar);
|
||||||
if (!avatar.type.startsWith("image/"))
|
if (!avatar.type.startsWith("image/"))
|
||||||
throw new ApiError(meta.errors.avatarNotAnImage);
|
throw new ApiError(meta.errors.avatarNotAnImage);
|
||||||
|
|
||||||
|
updates.avatarUrl = DriveFiles.getDatabasePrefetchUrl(avatar, true);
|
||||||
|
updates.avatarBlurhash = avatar.blurhash;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ps.bannerId) {
|
if (ps.bannerId) {
|
||||||
const banner = await DriveFiles.findOneBy({ id: ps.bannerId });
|
|
||||||
|
|
||||||
if (banner == null || banner.userId !== user.id)
|
if (banner == null || banner.userId !== user.id)
|
||||||
throw new ApiError(meta.errors.noSuchBanner);
|
throw new ApiError(meta.errors.noSuchBanner);
|
||||||
if (!banner.type.startsWith("image/"))
|
if (!banner.type.startsWith("image/"))
|
||||||
throw new ApiError(meta.errors.bannerNotAnImage);
|
throw new ApiError(meta.errors.bannerNotAnImage);
|
||||||
|
|
||||||
|
updates.bannerUrl = DriveFiles.getDatabasePrefetchUrl(banner, false);
|
||||||
|
updates.bannerBlurhash = banner.blurhash;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ps.pinnedPageId) {
|
if (ps.pinnedPageId) {
|
||||||
|
|
|
@ -43,16 +43,10 @@ export default define(meta, paramDef, async (ps) => {
|
||||||
.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");
|
||||||
|
|
|
@ -47,9 +47,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
"note.id IN (SELECT id FROM note_replies(:noteId, :depth, :limit))",
|
"note.id IN (SELECT id FROM note_replies(:noteId, :depth, :limit))",
|
||||||
{ noteId: ps.noteId, depth: ps.depth, limit: ps.limit },
|
{ noteId: ps.noteId, depth: ps.depth, limit: ps.limit },
|
||||||
)
|
)
|
||||||
.innerJoinAndSelect("note.user", "user")
|
.innerJoinAndSelect("note.user", "user");
|
||||||
.leftJoinAndSelect("user.avatar", "avatar")
|
|
||||||
.leftJoinAndSelect("user.banner", "banner");
|
|
||||||
|
|
||||||
generateVisibilityQuery(query, user);
|
generateVisibilityQuery(query, user);
|
||||||
if (user) {
|
if (user) {
|
||||||
|
|
|
@ -47,16 +47,10 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
.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");
|
|
||||||
|
|
||||||
switch (ps.origin) {
|
switch (ps.origin) {
|
||||||
case "local":
|
case "local":
|
||||||
|
|
|
@ -81,16 +81,10 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
.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");
|
|
||||||
|
|
||||||
generateRepliesQuery(query, ps.withReplies, user);
|
generateRepliesQuery(query, ps.withReplies, user);
|
||||||
if (user) {
|
if (user) {
|
||||||
|
|
|
@ -97,16 +97,10 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.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());
|
||||||
|
|
||||||
generateListQuery(query, user);
|
generateListQuery(query, user);
|
||||||
|
|
|
@ -91,16 +91,10 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
.andWhere("note.visibility = 'public'")
|
.andWhere("note.visibility = 'public'")
|
||||||
.andWhere("note.userHost IS NULL")
|
.andWhere("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");
|
|
||||||
|
|
||||||
generateChannelQuery(query, user);
|
generateChannelQuery(query, user);
|
||||||
generateRepliesQuery(query, ps.withReplies, user);
|
generateRepliesQuery(query, ps.withReplies, user);
|
||||||
|
|
|
@ -56,16 +56,10 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.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");
|
|
||||||
|
|
||||||
generateVisibilityQuery(query, user);
|
generateVisibilityQuery(query, user);
|
||||||
generateMutedUserQuery(query, user);
|
generateMutedUserQuery(query, user);
|
||||||
|
|
|
@ -91,16 +91,10 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
.andWhere(`note.userHost IN (:...instances)`, { instances: m.recommendedInstances })
|
.andWhere(`note.userHost IN (:...instances)`, { instances: m.recommendedInstances })
|
||||||
.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");
|
|
||||||
|
|
||||||
generateChannelQuery(query, user);
|
generateChannelQuery(query, user);
|
||||||
generateRepliesQuery(query, ps.withReplies, user);
|
generateRepliesQuery(query, ps.withReplies, user);
|
||||||
|
|
|
@ -66,16 +66,10 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
query
|
query
|
||||||
.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");
|
|
||||||
|
|
||||||
generateVisibilityQuery(query, user);
|
generateVisibilityQuery(query, user);
|
||||||
if (user) generateMutedUserQuery(query, user);
|
if (user) generateMutedUserQuery(query, user);
|
||||||
|
|
|
@ -43,16 +43,10 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
)
|
)
|
||||||
.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");
|
|
||||||
|
|
||||||
generateVisibilityQuery(query, user);
|
generateVisibilityQuery(query, user);
|
||||||
if (user) generateMutedUserQuery(query, user);
|
if (user) generateMutedUserQuery(query, user);
|
||||||
|
|
|
@ -76,16 +76,10 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
ps.untilId,
|
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");
|
|
||||||
|
|
||||||
generateVisibilityQuery(query, me);
|
generateVisibilityQuery(query, me);
|
||||||
if (me) generateMutedUserQuery(query, me);
|
if (me) generateMutedUserQuery(query, me);
|
||||||
|
|
|
@ -75,16 +75,10 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
|
|
||||||
query
|
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");
|
|
||||||
|
|
||||||
generateFtsQuery(query, ps.query);
|
generateFtsQuery(query, ps.query);
|
||||||
generateVisibilityQuery(query, me);
|
generateVisibilityQuery(query, me);
|
||||||
|
|
|
@ -75,16 +75,10 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
ps.untilDate,
|
ps.untilDate,
|
||||||
)
|
)
|
||||||
.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");
|
|
||||||
|
|
||||||
await generateFollowingQuery(query, user);
|
await generateFollowingQuery(query, user);
|
||||||
generateListQuery(query, user);
|
generateListQuery(query, user);
|
||||||
|
|
|
@ -80,16 +80,10 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
"userListJoining.userId = note.userId",
|
"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", {
|
.andWhere("userListJoining.userListId = :userListId", {
|
||||||
userListId: list.id,
|
userListId: list.id,
|
||||||
});
|
});
|
||||||
|
|
|
@ -76,16 +76,10 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
)
|
)
|
||||||
.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");
|
|
||||||
|
|
||||||
generateVisibilityQuery(query, me);
|
generateVisibilityQuery(query, me);
|
||||||
if (me) {
|
if (me) {
|
||||||
|
|
|
@ -35,11 +35,11 @@ export class UserConverter {
|
||||||
const profile = UserProfiles.findOneBy({ userId: u.id });
|
const profile = UserProfiles.findOneBy({ userId: u.id });
|
||||||
const bio = profile.then(profile => MfmHelpers.toHtml(mfm.parse(profile?.description ?? ""), profile?.mentions, u.host).then(p => p ?? escapeMFM(profile?.description ?? "")));
|
const bio = profile.then(profile => MfmHelpers.toHtml(mfm.parse(profile?.description ?? ""), profile?.mentions, u.host).then(p => p ?? escapeMFM(profile?.description ?? "")));
|
||||||
const avatar = u.avatarId
|
const avatar = u.avatarId
|
||||||
? (DriveFiles.findOneBy({ id: u.avatarId }))
|
? u.avatarUrl ?? (DriveFiles.findOneBy({ id: u.avatarId }))
|
||||||
.then(p => p?.url ?? Users.getIdenticonUrl(u.id))
|
.then(p => p?.url ?? Users.getIdenticonUrl(u.id))
|
||||||
: Users.getIdenticonUrl(u.id);
|
: Users.getIdenticonUrl(u.id);
|
||||||
const banner = u.bannerId
|
const banner = u.bannerId
|
||||||
? (DriveFiles.findOneBy({ id: u.bannerId }))
|
? u.bannerUrl ?? (DriveFiles.findOneBy({ id: u.bannerId }))
|
||||||
.then(p => p?.url ?? `${config.url}/static-assets/transparent.png`)
|
.then(p => p?.url ?? `${config.url}/static-assets/transparent.png`)
|
||||||
: `${config.url}/static-assets/transparent.png`;
|
: `${config.url}/static-assets/transparent.png`;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Note } from "@/models/entities/note.js";
|
import { Note } from "@/models/entities/note.js";
|
||||||
import { ILocalUser, IRemoteUser, User } from "@/models/entities/user.js";
|
import { ILocalUser, IRemoteUser, User } from "@/models/entities/user.js";
|
||||||
import {
|
import {
|
||||||
Blockings,
|
Blockings, DriveFiles,
|
||||||
Followings,
|
Followings,
|
||||||
FollowRequests,
|
FollowRequests,
|
||||||
Mutings,
|
Mutings,
|
||||||
|
@ -173,11 +173,15 @@ export class UserHelpers {
|
||||||
if (avatar) {
|
if (avatar) {
|
||||||
const file = await MediaHelpers.uploadMediaBasic(avatar, ctx);
|
const file = await MediaHelpers.uploadMediaBasic(avatar, ctx);
|
||||||
updates.avatarId = file.id;
|
updates.avatarId = file.id;
|
||||||
|
updates.avatarBlurhash = file.blurhash;
|
||||||
|
updates.avatarUrl = DriveFiles.getDatabasePrefetchUrl(file, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header) {
|
if (header) {
|
||||||
const file = await MediaHelpers.uploadMediaBasic(header, ctx);
|
const file = await MediaHelpers.uploadMediaBasic(header, ctx);
|
||||||
updates.bannerId = file.id;
|
updates.bannerId = file.id;
|
||||||
|
updates.bannerBlurhash = file.blurhash;
|
||||||
|
updates.bannerUrl = DriveFiles.getDatabasePrefetchUrl(file, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (formData.fields_attributes) {
|
if (formData.fields_attributes) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import type { DriveFile } from "@/models/entities/drive-file.js";
|
import type { DriveFile } from "@/models/entities/drive-file.js";
|
||||||
import { InternalStorage } from "./internal-storage.js";
|
import { InternalStorage } from "./internal-storage.js";
|
||||||
import { DriveFiles, Instances } from "@/models/index.js";
|
import { DriveFiles, Instances, Users } from "@/models/index.js";
|
||||||
import {
|
import {
|
||||||
driveChart,
|
driveChart,
|
||||||
perUserDriveChart,
|
perUserDriveChart,
|
||||||
|
@ -81,6 +81,8 @@ async function postProcess(file: DriveFile, isExpired = false) {
|
||||||
thumbnailAccessKey: `thumbnail-${uuid()}`,
|
thumbnailAccessKey: `thumbnail-${uuid()}`,
|
||||||
webpublicAccessKey: `webpublic-${uuid()}`,
|
webpublicAccessKey: `webpublic-${uuid()}`,
|
||||||
});
|
});
|
||||||
|
Users.update({ avatarId: file.id }, { avatarUrl: file.uri });
|
||||||
|
Users.update({ bannerId: file.id }, { bannerUrl: file.uri });
|
||||||
} else {
|
} else {
|
||||||
DriveFiles.delete(file.id);
|
DriveFiles.delete(file.id);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue