Merge remote-tracking branch 'misskey-dev/develop' into io
This commit is contained in:
commit
d18e3e9b93
|
@ -28,6 +28,10 @@
|
|||
- Fix: nodeinfoにenableMcaptchaとenableTurnstileが無いのを修正
|
||||
- エンドポイント`flash/update`の`flashId`以外のパラメータは必須ではなくなりました
|
||||
- Fix: 禁止キーワードを含むノートがDelayed Queueに追加されて再処理される問題を修正
|
||||
- エンドポイント`admin/emoji/update`の各種修正
|
||||
- 必須パラメータを`id`または`name`のいずれかのみに
|
||||
- `id`の代わりに`name`で絵文字を指定可能に(`id`・`name`両指定時は従来通り`name`を変更する挙動)
|
||||
- `category`および`licence`が指定なしの時勝手にnullに上書きされる挙動を修正
|
||||
|
||||
## 2024.2.0
|
||||
|
||||
|
|
|
@ -405,6 +405,11 @@ export class CustomEmojiService implements OnApplicationShutdown {
|
|||
return this.emojisRepository.findOneBy({ id });
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public getEmojiByName(name: string): Promise<MiEmoji | null> {
|
||||
return this.emojisRepository.findOneBy({ name, host: IsNull() });
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public dispose(): void {
|
||||
this.cache.dispose();
|
||||
|
|
|
@ -148,6 +148,9 @@ export const packedUserLiteSchema = {
|
|||
emojis: {
|
||||
type: 'object',
|
||||
nullable: false, optional: false,
|
||||
additionalProperties: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
onlineStatus: {
|
||||
type: 'string',
|
||||
|
|
|
@ -31,7 +31,10 @@ export const meta = {
|
|||
},
|
||||
},
|
||||
|
||||
ref: 'EmojiDetailed',
|
||||
res: {
|
||||
type: 'object',
|
||||
ref: 'EmojiDetailed',
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
|
|
@ -64,7 +64,10 @@ export const paramDef = {
|
|||
format: 'misskey:id',
|
||||
} },
|
||||
},
|
||||
required: ['id', 'name', 'aliases'],
|
||||
anyOf: [
|
||||
{ required: ['id'] },
|
||||
{ required: ['name'] },
|
||||
],
|
||||
} as const;
|
||||
|
||||
@Injectable()
|
||||
|
@ -77,27 +80,33 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
let driveFile;
|
||||
|
||||
if (ps.fileId) {
|
||||
driveFile = await this.driveFilesRepository.findOneBy({ id: ps.fileId });
|
||||
if (driveFile == null) throw new ApiError(meta.errors.noSuchFile);
|
||||
}
|
||||
const emoji = await this.customEmojiService.getEmojiById(ps.id);
|
||||
if (emoji != null) {
|
||||
if (ps.name !== emoji.name) {
|
||||
|
||||
let emojiId;
|
||||
if (ps.id) {
|
||||
emojiId = ps.id;
|
||||
const emoji = await this.customEmojiService.getEmojiById(ps.id);
|
||||
if (!emoji) throw new ApiError(meta.errors.noSuchEmoji);
|
||||
if (ps.name && (ps.name !== emoji.name)) {
|
||||
const isDuplicate = await this.customEmojiService.checkDuplicate(ps.name);
|
||||
if (isDuplicate) throw new ApiError(meta.errors.sameNameEmojiExists);
|
||||
}
|
||||
} 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,
|
||||
name: ps.name,
|
||||
category: ps.category ?? null,
|
||||
category: ps.category,
|
||||
aliases: ps.aliases,
|
||||
license: ps.license ?? null,
|
||||
license: ps.license,
|
||||
isSensitive: ps.isSensitive,
|
||||
localOnly: ps.localOnly,
|
||||
requestedBy: ps.requestedBy ?? null,
|
||||
|
|
|
@ -401,7 +401,8 @@ function toStories(component: string): Promise<string> {
|
|||
// glob('src/{components,pages,ui,widgets}/**/*.vue')
|
||||
(async () => {
|
||||
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/MkDigitalClock.vue'),
|
||||
glob('src/components/MkGalleryPostPreview.vue'),
|
||||
|
|
|
@ -32,7 +32,8 @@ export const Default = {
|
|||
async play({ canvasElement }) {
|
||||
const canvas = within(canvasElement);
|
||||
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 tick();
|
||||
const menu = canvas.getByRole('menu');
|
||||
|
@ -44,6 +45,7 @@ export const Default = {
|
|||
},
|
||||
args: {
|
||||
to: '#test',
|
||||
behavior: 'browser',
|
||||
},
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
|
|
|
@ -10,7 +10,7 @@ import MkTime from './MkTime.vue';
|
|||
import { i18n } from '@/i18n.js';
|
||||
import { dateTimeFormat } from '@/scripts/intl-const.js';
|
||||
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 oneDayAgo = new Date(now.getTime() - 86400000);
|
||||
const oneWeekAgo = new Date(now.getTime() - 604800000);
|
||||
|
@ -49,7 +49,7 @@ export const Empty = {
|
|||
export const RelativeFuture = {
|
||||
...Empty,
|
||||
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: {
|
||||
...Empty.args,
|
||||
|
|
|
@ -145,6 +145,9 @@ type AdminEmojiAddAliasesBulkRequest = operations['admin/emoji/add-aliases-bulk'
|
|||
// @public (undocumented)
|
||||
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)
|
||||
type AdminEmojiCopyRequest = operations['admin/emoji/copy']['requestBody']['content']['application/json'];
|
||||
|
||||
|
@ -1202,6 +1205,7 @@ declare namespace entities {
|
|||
AdminDriveShowFileResponse,
|
||||
AdminEmojiAddAliasesBulkRequest,
|
||||
AdminEmojiAddRequest,
|
||||
AdminEmojiAddResponse,
|
||||
AdminEmojiCopyRequest,
|
||||
AdminEmojiCopyResponse,
|
||||
AdminEmojiDeleteBulkRequest,
|
||||
|
|
|
@ -41,6 +41,7 @@ import type {
|
|||
AdminDriveShowFileResponse,
|
||||
AdminEmojiAddAliasesBulkRequest,
|
||||
AdminEmojiAddRequest,
|
||||
AdminEmojiAddResponse,
|
||||
AdminEmojiCopyRequest,
|
||||
AdminEmojiCopyResponse,
|
||||
AdminEmojiDeleteBulkRequest,
|
||||
|
@ -597,7 +598,7 @@ export type Endpoints = {
|
|||
'admin/drive/files': { req: AdminDriveFilesRequest; res: AdminDriveFilesResponse };
|
||||
'admin/drive/show-file': { req: AdminDriveShowFileRequest; res: AdminDriveShowFileResponse };
|
||||
'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/delete-bulk': { req: AdminEmojiDeleteBulkRequest; 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 AdminEmojiAddAliasesBulkRequest = operations['admin/emoji/add-aliases-bulk']['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 AdminEmojiCopyResponse = operations['admin/emoji/copy']['responses']['200']['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;
|
||||
themeColor: string | null;
|
||||
};
|
||||
emojis: Record<string, never>;
|
||||
emojis: {
|
||||
[key: string]: string;
|
||||
};
|
||||
/** @enum {string} */
|
||||
onlineStatus: 'unknown' | 'online' | 'active' | 'offline';
|
||||
badgeRoles?: ({
|
||||
|
@ -6947,9 +6949,11 @@ export type operations = {
|
|||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description OK (without any results) */
|
||||
204: {
|
||||
content: never;
|
||||
/** @description OK (with results) */
|
||||
200: {
|
||||
content: {
|
||||
'application/json': components['schemas']['EmojiDetailed'];
|
||||
};
|
||||
};
|
||||
/** @description Client error */
|
||||
400: {
|
||||
|
@ -7560,13 +7564,13 @@ export type operations = {
|
|||
content: {
|
||||
'application/json': {
|
||||
/** Format: misskey:id */
|
||||
id: string;
|
||||
name: string;
|
||||
id?: string;
|
||||
name?: string;
|
||||
/** Format: misskey:id */
|
||||
fileId?: string;
|
||||
/** @description Use `null` to reset the category. */
|
||||
category?: string | null;
|
||||
aliases: string[];
|
||||
aliases?: string[];
|
||||
license?: string | null;
|
||||
isSensitive?: boolean;
|
||||
localOnly?: boolean;
|
||||
|
|
Loading…
Reference in New Issue