Set file usage hints on local avatar/banner uploads as well + export "valid" values as type
This commit is contained in:
parent
4823abd3a9
commit
c0f93de94b
|
@ -16,6 +16,8 @@ import { DriveFolder } from "./drive-folder.js";
|
|||
import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js";
|
||||
import { NoteFile } from "./note-file.js";
|
||||
|
||||
export type DriveFileUsageHint = "user_avatar" | "user_banner" | null;
|
||||
|
||||
@Entity()
|
||||
@Index(["userId", "folderId", "id"])
|
||||
export class DriveFile {
|
||||
|
@ -182,7 +184,7 @@ export class DriveFile {
|
|||
nullable: true,
|
||||
comment: "Hint for what the file is used for.",
|
||||
})
|
||||
public usageHint: string | null;
|
||||
public usageHint: DriveFileUsageHint;
|
||||
|
||||
/**
|
||||
* 外部の(信頼されていない)URLへの直リンクか否か
|
||||
|
|
|
@ -3,7 +3,7 @@ import type { CacheableRemoteUser } from "@/models/entities/user.js";
|
|||
import Resolver from "../resolver.js";
|
||||
import { fetchMeta } from "backend-rs";
|
||||
import { apLogger } from "../logger.js";
|
||||
import type { DriveFile } from "@/models/entities/drive-file.js";
|
||||
import type { DriveFile, DriveFileUsageHint } from "@/models/entities/drive-file.js";
|
||||
import { DriveFiles } from "@/models/index.js";
|
||||
import { truncate } from "@/misc/truncate.js";
|
||||
import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js";
|
||||
|
@ -16,7 +16,7 @@ const logger = apLogger;
|
|||
export async function createImage(
|
||||
actor: CacheableRemoteUser,
|
||||
value: any,
|
||||
usage: 'avatar' | 'banner' | null
|
||||
usage: DriveFileUsageHint
|
||||
): Promise<DriveFile> {
|
||||
// Skip if author is frozen.
|
||||
if (actor.isSuspended) {
|
||||
|
@ -75,7 +75,7 @@ export async function createImage(
|
|||
export async function resolveImage(
|
||||
actor: CacheableRemoteUser,
|
||||
value: any,
|
||||
usage: 'avatar' | 'banner' | null,
|
||||
usage: DriveFileUsageHint,
|
||||
): Promise<DriveFile> {
|
||||
// TODO
|
||||
|
||||
|
|
|
@ -365,7 +365,7 @@ export async function createPerson(
|
|||
[person.icon, person.image].map((img, index) =>
|
||||
img == null
|
||||
? Promise.resolve(null)
|
||||
: resolveImage(user!, img, index === 0 ? "avatar" : index === 1 ? "banner" : null).catch(() => null),
|
||||
: resolveImage(user, img, index === 0 ? "user_avatar" : index === 1 ? "user_banner" : null).catch(() => null)
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -441,7 +441,7 @@ export async function updatePerson(
|
|||
[person.icon, person.image].map((img, index) =>
|
||||
img == null
|
||||
? Promise.resolve(null)
|
||||
: resolveImage(user, img, index === 0 ? "avatar" : index === 1 ? "banner" : null).catch(() => null),
|
||||
: resolveImage(user, img, index === 0 ? "user_avatar" : index === 1 ? "user_banner" : null).catch(() => null),
|
||||
),
|
||||
);
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import { normalizeForSearch } from "@/misc/normalize-for-search.js";
|
|||
import { verifyLink } from "@/services/fetch-rel-me.js";
|
||||
import { ApiError } from "@/server/api/error.js";
|
||||
import define from "@/server/api/define.js";
|
||||
import { DriveFile } from "@/models/entities/drive-file";
|
||||
|
||||
export const meta = {
|
||||
tags: ["account"],
|
||||
|
@ -241,8 +242,9 @@ export default define(meta, paramDef, async (ps, _user, token) => {
|
|||
if (ps.emailNotificationTypes !== undefined)
|
||||
profileUpdates.emailNotificationTypes = ps.emailNotificationTypes;
|
||||
|
||||
let avatar: DriveFile | null = null
|
||||
if (ps.avatarId) {
|
||||
const avatar = await DriveFiles.findOneBy({ id: ps.avatarId });
|
||||
avatar = await DriveFiles.findOneBy({ id: ps.avatarId });
|
||||
|
||||
if (avatar == null || avatar.userId !== user.id)
|
||||
throw new ApiError(meta.errors.noSuchAvatar);
|
||||
|
@ -250,8 +252,9 @@ export default define(meta, paramDef, async (ps, _user, token) => {
|
|||
throw new ApiError(meta.errors.avatarNotAnImage);
|
||||
}
|
||||
|
||||
let banner: DriveFile | null = null
|
||||
if (ps.bannerId) {
|
||||
const banner = await DriveFiles.findOneBy({ id: ps.bannerId });
|
||||
banner = await DriveFiles.findOneBy({ id: ps.bannerId });
|
||||
|
||||
if (banner == null || banner.userId !== user.id)
|
||||
throw new ApiError(meta.errors.noSuchBanner);
|
||||
|
@ -328,6 +331,22 @@ export default define(meta, paramDef, async (ps, _user, token) => {
|
|||
updateUsertags(user, tags);
|
||||
//#endregion
|
||||
|
||||
// Update old/new avatar usage hints
|
||||
if (avatar)
|
||||
{
|
||||
if (user.avatarId)
|
||||
await DriveFiles.update(user.avatarId, {usageHint: null});
|
||||
await DriveFiles.update(avatar.id, {usageHint: "user_avatar"});
|
||||
}
|
||||
|
||||
// Update old/new banner usage hints
|
||||
if (banner)
|
||||
{
|
||||
if (user.bannerId)
|
||||
await DriveFiles.update(user.bannerId, {usageHint: null});
|
||||
await DriveFiles.update(banner.id, {usageHint: "user_banner"});
|
||||
}
|
||||
|
||||
if (Object.keys(updates).length > 0) await Users.update(user.id, updates);
|
||||
if (Object.keys(profileUpdates).length > 0)
|
||||
await UserProfiles.update(user.id, profileUpdates);
|
||||
|
|
|
@ -16,6 +16,7 @@ import {
|
|||
UserProfiles,
|
||||
} from "@/models/index.js";
|
||||
import { DriveFile } from "@/models/entities/drive-file.js";
|
||||
import type { DriveFileUsageHint } from "@/models/entities/drive-file.js";
|
||||
import type { IRemoteUser, User } from "@/models/entities/user.js";
|
||||
import { genId } from "backend-rs";
|
||||
import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js";
|
||||
|
@ -65,7 +66,7 @@ function urlPathJoin(
|
|||
* @param type Content-Type for original
|
||||
* @param hash Hash for original
|
||||
* @param size Size for original
|
||||
* @param usage Optional usage hint for file (f.e. "avatar")
|
||||
* @param usage Optional usage hint for file (f.e. "user_avatar")
|
||||
*/
|
||||
async function save(
|
||||
file: DriveFile,
|
||||
|
@ -74,7 +75,7 @@ async function save(
|
|||
type: string,
|
||||
hash: string,
|
||||
size: number,
|
||||
usage: string | null = null
|
||||
usage: DriveFileUsageHint = null
|
||||
): Promise<DriveFile> {
|
||||
// thunbnail, webpublic を必要なら生成
|
||||
const alts = await generateAlts(path, type, !file.uri);
|
||||
|
@ -456,7 +457,7 @@ type AddFileArgs = {
|
|||
requestHeaders?: Record<string, string> | null;
|
||||
|
||||
/** Whether this file has a known use case, like user avatar or instance icon */
|
||||
usageHint?: string | null;
|
||||
usageHint?: DriveFileUsageHint;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue