Merge pull request MisskeyIO#479 from merge-upstream
This commit is contained in:
commit
c52fa01111
|
@ -28,6 +28,10 @@
|
||||||
- Fix: nodeinfoにenableMcaptchaとenableTurnstileが無いのを修正
|
- Fix: nodeinfoにenableMcaptchaとenableTurnstileが無いのを修正
|
||||||
- エンドポイント`flash/update`の`flashId`以外のパラメータは必須ではなくなりました
|
- エンドポイント`flash/update`の`flashId`以外のパラメータは必須ではなくなりました
|
||||||
- Fix: 禁止キーワードを含むノートがDelayed Queueに追加されて再処理される問題を修正
|
- Fix: 禁止キーワードを含むノートがDelayed Queueに追加されて再処理される問題を修正
|
||||||
|
- エンドポイント`admin/emoji/update`の各種修正
|
||||||
|
- 必須パラメータを`id`または`name`のいずれかのみに
|
||||||
|
- `id`の代わりに`name`で絵文字を指定可能に(`id`・`name`両指定時は従来通り`name`を変更する挙動)
|
||||||
|
- `category`および`licence`が指定なしの時勝手にnullに上書きされる挙動を修正
|
||||||
|
|
||||||
## 2024.2.0
|
## 2024.2.0
|
||||||
|
|
||||||
|
|
|
@ -405,6 +405,11 @@ export class CustomEmojiService implements OnApplicationShutdown {
|
||||||
return this.emojisRepository.findOneBy({ id });
|
return this.emojisRepository.findOneBy({ id });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@bindThis
|
||||||
|
public getEmojiByName(name: string): Promise<MiEmoji | null> {
|
||||||
|
return this.emojisRepository.findOneBy({ name, host: IsNull() });
|
||||||
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public dispose(): void {
|
public dispose(): void {
|
||||||
this.cache.dispose();
|
this.cache.dispose();
|
||||||
|
|
|
@ -148,6 +148,9 @@ export const packedUserLiteSchema = {
|
||||||
emojis: {
|
emojis: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
nullable: false, optional: false,
|
nullable: false, optional: false,
|
||||||
|
additionalProperties: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
onlineStatus: {
|
onlineStatus: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
|
|
@ -31,7 +31,10 @@ export const meta = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
res: {
|
||||||
|
type: 'object',
|
||||||
ref: 'EmojiDetailed',
|
ref: 'EmojiDetailed',
|
||||||
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const paramDef = {
|
export const paramDef = {
|
||||||
|
|
|
@ -64,7 +64,10 @@ export const paramDef = {
|
||||||
format: 'misskey:id',
|
format: 'misskey:id',
|
||||||
} },
|
} },
|
||||||
},
|
},
|
||||||
required: ['id', 'name', 'aliases'],
|
anyOf: [
|
||||||
|
{ required: ['id'] },
|
||||||
|
{ required: ['name'] },
|
||||||
|
],
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -77,27 +80,33 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
let driveFile;
|
let driveFile;
|
||||||
|
|
||||||
if (ps.fileId) {
|
if (ps.fileId) {
|
||||||
driveFile = await this.driveFilesRepository.findOneBy({ id: ps.fileId });
|
driveFile = await this.driveFilesRepository.findOneBy({ id: ps.fileId });
|
||||||
if (driveFile == null) throw new ApiError(meta.errors.noSuchFile);
|
if (driveFile == null) throw new ApiError(meta.errors.noSuchFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let emojiId;
|
||||||
|
if (ps.id) {
|
||||||
|
emojiId = ps.id;
|
||||||
const emoji = await this.customEmojiService.getEmojiById(ps.id);
|
const emoji = await this.customEmojiService.getEmojiById(ps.id);
|
||||||
if (emoji != null) {
|
if (!emoji) throw new ApiError(meta.errors.noSuchEmoji);
|
||||||
if (ps.name !== emoji.name) {
|
if (ps.name && (ps.name !== emoji.name)) {
|
||||||
const isDuplicate = await this.customEmojiService.checkDuplicate(ps.name);
|
const isDuplicate = await this.customEmojiService.checkDuplicate(ps.name);
|
||||||
if (isDuplicate) throw new ApiError(meta.errors.sameNameEmojiExists);
|
if (isDuplicate) throw new ApiError(meta.errors.sameNameEmojiExists);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new ApiError(meta.errors.noSuchEmoji);
|
if (!ps.name) throw new Error('Invalid Params unexpectedly passed. This is a BUG. Please report it to the development team.');
|
||||||
|
const emoji = await this.customEmojiService.getEmojiByName(ps.name);
|
||||||
|
if (!emoji) throw new ApiError(meta.errors.noSuchEmoji);
|
||||||
|
emojiId = emoji.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.customEmojiService.update(ps.id, {
|
await this.customEmojiService.update(emojiId, {
|
||||||
driveFile,
|
driveFile,
|
||||||
name: ps.name,
|
name: ps.name,
|
||||||
category: ps.category ?? null,
|
category: ps.category,
|
||||||
aliases: ps.aliases,
|
aliases: ps.aliases,
|
||||||
license: ps.license ?? null,
|
license: ps.license,
|
||||||
isSensitive: ps.isSensitive,
|
isSensitive: ps.isSensitive,
|
||||||
localOnly: ps.localOnly,
|
localOnly: ps.localOnly,
|
||||||
requestedBy: ps.requestedBy ?? null,
|
requestedBy: ps.requestedBy ?? null,
|
||||||
|
|
|
@ -401,7 +401,8 @@ function toStories(component: string): Promise<string> {
|
||||||
// glob('src/{components,pages,ui,widgets}/**/*.vue')
|
// glob('src/{components,pages,ui,widgets}/**/*.vue')
|
||||||
(async () => {
|
(async () => {
|
||||||
const globs = await Promise.all([
|
const globs = await Promise.all([
|
||||||
glob('src/components/global/*.vue'),
|
glob('src/components/global/Mk*.vue'),
|
||||||
|
glob('src/components/global/RouterView.vue'),
|
||||||
glob('src/components/Mk{A,B}*.vue'),
|
glob('src/components/Mk{A,B}*.vue'),
|
||||||
glob('src/components/MkDigitalClock.vue'),
|
glob('src/components/MkDigitalClock.vue'),
|
||||||
glob('src/components/MkGalleryPostPreview.vue'),
|
glob('src/components/MkGalleryPostPreview.vue'),
|
||||||
|
|
|
@ -32,7 +32,8 @@ export const Default = {
|
||||||
async play({ canvasElement }) {
|
async play({ canvasElement }) {
|
||||||
const canvas = within(canvasElement);
|
const canvas = within(canvasElement);
|
||||||
const a = canvas.getByRole<HTMLAnchorElement>('link');
|
const a = canvas.getByRole<HTMLAnchorElement>('link');
|
||||||
await expect(a.href).toMatch(/^https?:\/\/.*#test$/);
|
// FIXME: 通るけどその後落ちるのでコメントアウト
|
||||||
|
// await expect(a.href).toMatch(/^https?:\/\/.*#test$/);
|
||||||
await userEvent.pointer({ keys: '[MouseRight]', target: a });
|
await userEvent.pointer({ keys: '[MouseRight]', target: a });
|
||||||
await tick();
|
await tick();
|
||||||
const menu = canvas.getByRole('menu');
|
const menu = canvas.getByRole('menu');
|
||||||
|
@ -44,6 +45,7 @@ export const Default = {
|
||||||
},
|
},
|
||||||
args: {
|
args: {
|
||||||
to: '#test',
|
to: '#test',
|
||||||
|
behavior: 'browser',
|
||||||
},
|
},
|
||||||
parameters: {
|
parameters: {
|
||||||
layout: 'centered',
|
layout: 'centered',
|
||||||
|
|
|
@ -10,7 +10,7 @@ import MkTime from './MkTime.vue';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { dateTimeFormat } from '@/scripts/intl-const.js';
|
import { dateTimeFormat } from '@/scripts/intl-const.js';
|
||||||
const now = new Date('2023-04-01T00:00:00.000Z');
|
const now = new Date('2023-04-01T00:00:00.000Z');
|
||||||
const future = new Date('3000-04-01T00:00:00.000Z');
|
const future = new Date('2024-04-01T00:00:00.000Z');
|
||||||
const oneHourAgo = new Date(now.getTime() - 3600000);
|
const oneHourAgo = new Date(now.getTime() - 3600000);
|
||||||
const oneDayAgo = new Date(now.getTime() - 86400000);
|
const oneDayAgo = new Date(now.getTime() - 86400000);
|
||||||
const oneWeekAgo = new Date(now.getTime() - 604800000);
|
const oneWeekAgo = new Date(now.getTime() - 604800000);
|
||||||
|
@ -49,7 +49,7 @@ export const Empty = {
|
||||||
export const RelativeFuture = {
|
export const RelativeFuture = {
|
||||||
...Empty,
|
...Empty,
|
||||||
async play({ canvasElement }) {
|
async play({ canvasElement }) {
|
||||||
await expect(canvasElement).toHaveTextContent(i18n.tsx._timeIn.years({ n: 977 }));
|
await expect(canvasElement).toHaveTextContent(i18n.tsx._timeIn.years({ n: 1 })); // n (1) = future (2024) - now (2023)
|
||||||
},
|
},
|
||||||
args: {
|
args: {
|
||||||
...Empty.args,
|
...Empty.args,
|
||||||
|
|
|
@ -145,6 +145,9 @@ type AdminEmojiAddAliasesBulkRequest = operations['admin/emoji/add-aliases-bulk'
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
type AdminEmojiAddRequest = operations['admin/emoji/add']['requestBody']['content']['application/json'];
|
type AdminEmojiAddRequest = operations['admin/emoji/add']['requestBody']['content']['application/json'];
|
||||||
|
|
||||||
|
// @public (undocumented)
|
||||||
|
type AdminEmojiAddResponse = operations['admin/emoji/add']['responses']['200']['content']['application/json'];
|
||||||
|
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
type AdminEmojiCopyRequest = operations['admin/emoji/copy']['requestBody']['content']['application/json'];
|
type AdminEmojiCopyRequest = operations['admin/emoji/copy']['requestBody']['content']['application/json'];
|
||||||
|
|
||||||
|
@ -1202,6 +1205,7 @@ declare namespace entities {
|
||||||
AdminDriveShowFileResponse,
|
AdminDriveShowFileResponse,
|
||||||
AdminEmojiAddAliasesBulkRequest,
|
AdminEmojiAddAliasesBulkRequest,
|
||||||
AdminEmojiAddRequest,
|
AdminEmojiAddRequest,
|
||||||
|
AdminEmojiAddResponse,
|
||||||
AdminEmojiCopyRequest,
|
AdminEmojiCopyRequest,
|
||||||
AdminEmojiCopyResponse,
|
AdminEmojiCopyResponse,
|
||||||
AdminEmojiDeleteBulkRequest,
|
AdminEmojiDeleteBulkRequest,
|
||||||
|
|
|
@ -41,6 +41,7 @@ import type {
|
||||||
AdminDriveShowFileResponse,
|
AdminDriveShowFileResponse,
|
||||||
AdminEmojiAddAliasesBulkRequest,
|
AdminEmojiAddAliasesBulkRequest,
|
||||||
AdminEmojiAddRequest,
|
AdminEmojiAddRequest,
|
||||||
|
AdminEmojiAddResponse,
|
||||||
AdminEmojiCopyRequest,
|
AdminEmojiCopyRequest,
|
||||||
AdminEmojiCopyResponse,
|
AdminEmojiCopyResponse,
|
||||||
AdminEmojiDeleteBulkRequest,
|
AdminEmojiDeleteBulkRequest,
|
||||||
|
@ -597,7 +598,7 @@ export type Endpoints = {
|
||||||
'admin/drive/files': { req: AdminDriveFilesRequest; res: AdminDriveFilesResponse };
|
'admin/drive/files': { req: AdminDriveFilesRequest; res: AdminDriveFilesResponse };
|
||||||
'admin/drive/show-file': { req: AdminDriveShowFileRequest; res: AdminDriveShowFileResponse };
|
'admin/drive/show-file': { req: AdminDriveShowFileRequest; res: AdminDriveShowFileResponse };
|
||||||
'admin/emoji/add-aliases-bulk': { req: AdminEmojiAddAliasesBulkRequest; res: EmptyResponse };
|
'admin/emoji/add-aliases-bulk': { req: AdminEmojiAddAliasesBulkRequest; res: EmptyResponse };
|
||||||
'admin/emoji/add': { req: AdminEmojiAddRequest; res: EmptyResponse };
|
'admin/emoji/add': { req: AdminEmojiAddRequest; res: AdminEmojiAddResponse };
|
||||||
'admin/emoji/copy': { req: AdminEmojiCopyRequest; res: AdminEmojiCopyResponse };
|
'admin/emoji/copy': { req: AdminEmojiCopyRequest; res: AdminEmojiCopyResponse };
|
||||||
'admin/emoji/delete-bulk': { req: AdminEmojiDeleteBulkRequest; res: EmptyResponse };
|
'admin/emoji/delete-bulk': { req: AdminEmojiDeleteBulkRequest; res: EmptyResponse };
|
||||||
'admin/emoji/delete': { req: AdminEmojiDeleteRequest; res: EmptyResponse };
|
'admin/emoji/delete': { req: AdminEmojiDeleteRequest; res: EmptyResponse };
|
||||||
|
|
|
@ -43,6 +43,7 @@ export type AdminDriveShowFileRequest = operations['admin/drive/show-file']['req
|
||||||
export type AdminDriveShowFileResponse = operations['admin/drive/show-file']['responses']['200']['content']['application/json'];
|
export type AdminDriveShowFileResponse = operations['admin/drive/show-file']['responses']['200']['content']['application/json'];
|
||||||
export type AdminEmojiAddAliasesBulkRequest = operations['admin/emoji/add-aliases-bulk']['requestBody']['content']['application/json'];
|
export type AdminEmojiAddAliasesBulkRequest = operations['admin/emoji/add-aliases-bulk']['requestBody']['content']['application/json'];
|
||||||
export type AdminEmojiAddRequest = operations['admin/emoji/add']['requestBody']['content']['application/json'];
|
export type AdminEmojiAddRequest = operations['admin/emoji/add']['requestBody']['content']['application/json'];
|
||||||
|
export type AdminEmojiAddResponse = operations['admin/emoji/add']['responses']['200']['content']['application/json'];
|
||||||
export type AdminEmojiCopyRequest = operations['admin/emoji/copy']['requestBody']['content']['application/json'];
|
export type AdminEmojiCopyRequest = operations['admin/emoji/copy']['requestBody']['content']['application/json'];
|
||||||
export type AdminEmojiCopyResponse = operations['admin/emoji/copy']['responses']['200']['content']['application/json'];
|
export type AdminEmojiCopyResponse = operations['admin/emoji/copy']['responses']['200']['content']['application/json'];
|
||||||
export type AdminEmojiDeleteBulkRequest = operations['admin/emoji/delete-bulk']['requestBody']['content']['application/json'];
|
export type AdminEmojiDeleteBulkRequest = operations['admin/emoji/delete-bulk']['requestBody']['content']['application/json'];
|
||||||
|
|
|
@ -3678,7 +3678,9 @@ export type components = {
|
||||||
faviconUrl: string | null;
|
faviconUrl: string | null;
|
||||||
themeColor: string | null;
|
themeColor: string | null;
|
||||||
};
|
};
|
||||||
emojis: Record<string, never>;
|
emojis: {
|
||||||
|
[key: string]: string;
|
||||||
|
};
|
||||||
/** @enum {string} */
|
/** @enum {string} */
|
||||||
onlineStatus: 'unknown' | 'online' | 'active' | 'offline';
|
onlineStatus: 'unknown' | 'online' | 'active' | 'offline';
|
||||||
badgeRoles?: ({
|
badgeRoles?: ({
|
||||||
|
@ -6947,9 +6949,11 @@ export type operations = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
responses: {
|
responses: {
|
||||||
/** @description OK (without any results) */
|
/** @description OK (with results) */
|
||||||
204: {
|
200: {
|
||||||
content: never;
|
content: {
|
||||||
|
'application/json': components['schemas']['EmojiDetailed'];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
/** @description Client error */
|
/** @description Client error */
|
||||||
400: {
|
400: {
|
||||||
|
@ -7560,13 +7564,13 @@ export type operations = {
|
||||||
content: {
|
content: {
|
||||||
'application/json': {
|
'application/json': {
|
||||||
/** Format: misskey:id */
|
/** Format: misskey:id */
|
||||||
id: string;
|
id?: string;
|
||||||
name: string;
|
name?: string;
|
||||||
/** Format: misskey:id */
|
/** Format: misskey:id */
|
||||||
fileId?: string;
|
fileId?: string;
|
||||||
/** @description Use `null` to reset the category. */
|
/** @description Use `null` to reset the category. */
|
||||||
category?: string | null;
|
category?: string | null;
|
||||||
aliases: string[];
|
aliases?: string[];
|
||||||
license?: string | null;
|
license?: string | null;
|
||||||
isSensitive?: boolean;
|
isSensitive?: boolean;
|
||||||
localOnly?: boolean;
|
localOnly?: boolean;
|
||||||
|
|
Loading…
Reference in New Issue