Merge branch 'develop'

This commit is contained in:
syuilo 2022-04-03 14:01:19 +09:00
commit 090f8eff67
39 changed files with 315 additions and 112 deletions

View file

@ -16,7 +16,7 @@ jobs:
submodules: true submodules: true
- uses: actions/setup-node@v1 - uses: actions/setup-node@v1
with: with:
node-version: 12.x node-version: 16.x
- uses: actions/cache@v2 - uses: actions/cache@v2
with: with:
path: '**/node_modules' path: '**/node_modules'

View file

@ -10,6 +10,12 @@
You should also include the user name that made the change. You should also include the user name that made the change.
--> -->
## 12.109.2 (2022/04/03)
### Bugfixes
- API: admin/update-meta was not working @syuilo
- Client: テーマを切り替えたり読み込んだりするとmeta[name="theme-color"]のcontentがundefinedになる問題を修正 @tamaina
## 12.109.1 (2022/04/02) ## 12.109.1 (2022/04/02)
### Bugfixes ### Bugfixes

View file

@ -1,6 +1,6 @@
{ {
"name": "misskey", "name": "misskey",
"version": "12.109.1", "version": "12.109.2",
"codename": "indigo", "codename": "indigo",
"repository": { "repository": {
"type": "git", "type": "git",

View file

@ -5,7 +5,7 @@
"scripts": { "scripts": {
"build": "tsc -p tsconfig.json || echo done. && tsc-alias -p tsconfig.json", "build": "tsc -p tsconfig.json || echo done. && tsc-alias -p tsconfig.json",
"watch": "node watch.mjs", "watch": "node watch.mjs",
"lint": "eslint --quiet src/**/*.ts", "lint": "eslint --quiet 'src/**/*.ts'",
"mocha": "cross-env TS_NODE_FILES=true TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT=\"./test/tsconfig.json\" mocha", "mocha": "cross-env TS_NODE_FILES=true TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT=\"./test/tsconfig.json\" mocha",
"test": "npm run mocha" "test": "npm run mocha"
}, },

View file

@ -27,6 +27,7 @@ export const packedEmojiSchema = {
host: { host: {
type: 'string', type: 'string',
optional: false, nullable: true, optional: false, nullable: true,
description: 'The local host is represented with `null`.',
}, },
url: { url: {
type: 'string', type: 'string',

View file

@ -21,6 +21,7 @@ export const packedUserLiteSchema = {
type: 'string', type: 'string',
nullable: true, optional: false, nullable: true, optional: false,
example: 'misskey.example.com', example: 'misskey.example.com',
description: 'The local host is represented with `null`.',
}, },
avatarUrl: { avatarUrl: {
type: 'string', type: 'string',

View file

@ -27,7 +27,12 @@ export const paramDef = {
untilId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' },
type: { type: 'string', nullable: true, pattern: /^[a-zA-Z0-9\/\-*]+$/.toString().slice(1, -1) }, type: { type: 'string', nullable: true, pattern: /^[a-zA-Z0-9\/\-*]+$/.toString().slice(1, -1) },
origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: "local" }, origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: "local" },
hostname: { type: 'string', nullable: true, default: null }, hostname: {
type: 'string',
nullable: true,
default: null,
description: 'The local host is represented with `null`.',
},
}, },
required: [], required: [],
} as const; } as const;

View file

@ -40,6 +40,7 @@ export const meta = {
userHost: { userHost: {
type: 'string', type: 'string',
optional: false, nullable: true, optional: false, nullable: true,
description: 'The local host is represented with `null`.',
}, },
md5: { md5: {
type: 'string', type: 'string',
@ -151,11 +152,20 @@ export const meta = {
export const paramDef = { export const paramDef = {
type: 'object', type: 'object',
properties: { anyOf: [
fileId: { type: 'string', format: 'misskey:id' }, {
url: { type: 'string' }, properties: {
}, fileId: { type: 'string', format: 'misskey:id' },
required: [], },
required: ['fileId'],
},
{
properties: {
url: { type: 'string' },
},
required: ['url'],
},
],
} as const; } as const;
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export

View file

@ -40,6 +40,7 @@ export const meta = {
host: { host: {
type: 'string', type: 'string',
optional: false, nullable: true, optional: false, nullable: true,
description: 'The local host is represented with `null`.',
}, },
url: { url: {
type: 'string', type: 'string',
@ -54,7 +55,12 @@ export const paramDef = {
type: 'object', type: 'object',
properties: { properties: {
query: { type: 'string', nullable: true, default: null }, query: { type: 'string', nullable: true, default: null },
host: { type: 'string', nullable: true, default: null }, host: {
type: 'string',
nullable: true,
default: null,
description: 'Use `null` to represent the local host.',
},
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
sinceId: { type: 'string', format: 'misskey:id' }, sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' },

View file

@ -38,8 +38,9 @@ export const meta = {
optional: false, nullable: true, optional: false, nullable: true,
}, },
host: { host: {
type: 'string', type: 'null',
optional: false, nullable: true, optional: false,
description: 'The local host is represented with `null`. The field exists for compatibility with other API endpoints that return files.',
}, },
url: { url: {
type: 'string', type: 'string',

View file

@ -17,7 +17,11 @@ export const paramDef = {
ids: { type: 'array', items: { ids: { type: 'array', items: {
type: 'string', format: 'misskey:id', type: 'string', format: 'misskey:id',
} }, } },
category: { type: 'string', nullable: true }, category: {
type: 'string',
nullable: true,
description: 'Use `null` to reset the category.',
},
}, },
required: ['ids'], required: ['ids'],
} as const; } as const;

View file

@ -23,7 +23,11 @@ export const paramDef = {
properties: { properties: {
id: { type: 'string', format: 'misskey:id' }, id: { type: 'string', format: 'misskey:id' },
name: { type: 'string' }, name: { type: 'string' },
category: { type: 'string', nullable: true }, category: {
type: 'string',
nullable: true,
description: 'Use `null` to reset the category.',
},
aliases: { type: 'array', items: { aliases: { type: 'array', items: {
type: 'string', type: 'string',
} }, } },

View file

@ -26,8 +26,13 @@ export const paramDef = {
sort: { type: 'string', enum: ['+follower', '-follower', '+createdAt', '-createdAt', '+updatedAt', '-updatedAt'] }, sort: { type: 'string', enum: ['+follower', '-follower', '+createdAt', '-createdAt', '+updatedAt', '-updatedAt'] },
state: { type: 'string', enum: ['all', 'available', 'admin', 'moderator', 'adminOrModerator', 'silenced', 'suspended'], default: "all" }, state: { type: 'string', enum: ['all', 'available', 'admin', 'moderator', 'adminOrModerator', 'silenced', 'suspended'], default: "all" },
origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: "local" }, origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: "local" },
username: { type: 'string', default: null }, username: { type: 'string', nullable: true, default: null },
hostname: { type: 'string', default: null }, hostname: {
type: 'string',
nullable: true,
default: null,
description: 'The local host is represented with `null`.',
},
}, },
required: [], required: [],
} as const; } as const;

View file

@ -397,12 +397,14 @@ export default define(meta, paramDef, async (ps, me) => {
} }
await db.transaction(async transactionalEntityManager => { await db.transaction(async transactionalEntityManager => {
const meta = await transactionalEntityManager.findOne(Meta, { const metas = await transactionalEntityManager.find(Meta, {
order: { order: {
id: 'DESC', id: 'DESC',
}, },
}); });
const meta = metas[0];
if (meta) { if (meta) {
await transactionalEntityManager.update(Meta, meta.id, set); await transactionalEntityManager.update(Meta, meta.id, set);
} else { } else {

View file

@ -20,7 +20,7 @@ export const paramDef = {
type: 'object', type: 'object',
properties: { properties: {
name: { type: 'string', minLength: 1, maxLength: 100 }, name: { type: 'string', minLength: 1, maxLength: 100 },
isPublic: { type: 'boolean' }, isPublic: { type: 'boolean', default: false },
description: { type: 'string', nullable: true, minLength: 1, maxLength: 2048 }, description: { type: 'string', nullable: true, minLength: 1, maxLength: 2048 },
}, },
required: ['name'], required: ['name'],

View file

@ -28,22 +28,25 @@ export const meta = {
code: 'ACCESS_DENIED', code: 'ACCESS_DENIED',
id: '25b73c73-68b1-41d0-bad1-381cfdf6579f', id: '25b73c73-68b1-41d0-bad1-381cfdf6579f',
}, },
fileIdOrUrlRequired: {
message: 'fileId or url required.',
code: 'INVALID_PARAM',
id: '89674805-722c-440c-8d88-5641830dc3e4',
},
}, },
} as const; } as const;
export const paramDef = { export const paramDef = {
type: 'object', type: 'object',
properties: { anyOf: [
fileId: { type: 'string', format: 'misskey:id' }, {
url: { type: 'string' }, properties: {
}, fileId: { type: 'string', format: 'misskey:id' },
required: [], },
required: ['fileId'],
},
{
properties: {
url: { type: 'string' },
},
required: ['url'],
},
],
} as const; } as const;
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export
@ -62,8 +65,6 @@ export default define(meta, paramDef, async (ps, user) => {
thumbnailUrl: ps.url, thumbnailUrl: ps.url,
}], }],
}); });
} else {
throw new ApiError(meta.errors.fileIdOrUrlRequired);
} }
if (file == null) { if (file == null) {

View file

@ -22,7 +22,7 @@ export const meta = {
export const paramDef = { export const paramDef = {
type: 'object', type: 'object',
properties: { properties: {
host: { type: 'string', nullable: true }, host: { type: 'string', nullable: true, description: 'Omit or use `null` to not filter by host.' },
blocked: { type: 'boolean', nullable: true }, blocked: { type: 'boolean', nullable: true },
notResponding: { type: 'boolean', nullable: true }, notResponding: { type: 'boolean', nullable: true },
suspended: { type: 'boolean', nullable: true }, suspended: { type: 'boolean', nullable: true },

View file

@ -47,14 +47,25 @@ export const meta = {
export const paramDef = { export const paramDef = {
type: 'object', type: 'object',
properties: { properties: {
userId: { type: 'string', format: 'misskey:id' },
groupId: { type: 'string', format: 'misskey:id' },
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
sinceId: { type: 'string', format: 'misskey:id' }, sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' },
markAsRead: { type: 'boolean', default: true }, markAsRead: { type: 'boolean', default: true },
}, },
required: [], anyOf: [
{
properties: {
userId: { type: 'string', format: 'misskey:id' },
},
required: ['userId'],
},
{
properties: {
groupId: { type: 'string', format: 'misskey:id' },
},
required: ['groupId'],
},
],
} as const; } as const;
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export
@ -126,7 +137,5 @@ export default define(meta, paramDef, async (ps, user) => {
return await Promise.all(messages.map(message => MessagingMessages.pack(message, user, { return await Promise.all(messages.map(message => MessagingMessages.pack(message, user, {
populateGroup: false, populateGroup: false,
}))); })));
} else {
throw new Error();
} }
}); });

View file

@ -67,12 +67,23 @@ export const meta = {
export const paramDef = { export const paramDef = {
type: 'object', type: 'object',
properties: { properties: {
userId: { type: 'string', format: 'misskey:id' },
groupId: { type: 'string', format: 'misskey:id' },
text: { type: 'string', nullable: true, maxLength: 3000 }, text: { type: 'string', nullable: true, maxLength: 3000 },
fileId: { type: 'string', format: 'misskey:id' }, fileId: { type: 'string', format: 'misskey:id' },
}, },
required: [], anyOf: [
{
properties: {
userId: { type: 'string', format: 'misskey:id' },
},
required: ['userId'],
},
{
properties: {
groupId: { type: 'string', format: 'misskey:id' },
},
required: ['groupId'],
},
],
} as const; } as const;
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export

View file

@ -169,6 +169,7 @@ export const meta = {
host: { host: {
type: 'string', type: 'string',
optional: false, nullable: true, optional: false, nullable: true,
description: 'The local host is represented with `null`.',
}, },
url: { url: {
type: 'string', type: 'string',

View file

@ -38,7 +38,11 @@ export const paramDef = {
type: 'object', type: 'object',
properties: { properties: {
userId: { type: 'string', format: 'misskey:id' }, userId: { type: 'string', format: 'misskey:id' },
expiresAt: { type: 'integer', nullable: true }, expiresAt: {
type: 'integer',
nullable: true,
description: 'A Unix Epoch timestamp that must lie in the future. `null` means an indefinite mute.',
},
}, },
required: ['userId'], required: ['userId'],
} as const; } as const;

View file

@ -19,7 +19,7 @@ export const meta = {
export const paramDef = { export const paramDef = {
type: 'object', type: 'object',
properties: { properties: {
local: { type: 'boolean' }, local: { type: 'boolean', default: false },
reply: { type: 'boolean' }, reply: { type: 'boolean' },
renote: { type: 'boolean' }, renote: { type: 'boolean' },
withFiles: { type: 'boolean' }, withFiles: { type: 'boolean' },

View file

@ -59,12 +59,6 @@ export const meta = {
id: '3ac74a84-8fd5-4bb0-870f-01804f82ce15', id: '3ac74a84-8fd5-4bb0-870f-01804f82ce15',
}, },
contentRequired: {
message: 'Content required. You need to set text, fileIds, renoteId or poll.',
code: 'CONTENT_REQUIRED',
id: '6f57e42b-c348-439b-bc45-993995cc515a',
},
cannotCreateAlreadyExpiredPoll: { cannotCreateAlreadyExpiredPoll: {
message: 'Poll is already expired.', message: 'Poll is already expired.',
code: 'CANNOT_CREATE_ALREADY_EXPIRED_POLL', code: 'CANNOT_CREATE_ALREADY_EXPIRED_POLL',
@ -92,29 +86,41 @@ export const paramDef = {
visibleUserIds: { type: 'array', uniqueItems: true, items: { visibleUserIds: { type: 'array', uniqueItems: true, items: {
type: 'string', format: 'misskey:id', type: 'string', format: 'misskey:id',
} }, } },
text: { type: 'string', nullable: true, maxLength: MAX_NOTE_TEXT_LENGTH, default: null }, text: { type: 'string', maxLength: MAX_NOTE_TEXT_LENGTH, nullable: true },
cw: { type: 'string', nullable: true, maxLength: 100 }, cw: { type: 'string', nullable: true, maxLength: 100 },
localOnly: { type: 'boolean', default: false }, localOnly: { type: 'boolean', default: false },
noExtractMentions: { type: 'boolean', default: false }, noExtractMentions: { type: 'boolean', default: false },
noExtractHashtags: { type: 'boolean', default: false }, noExtractHashtags: { type: 'boolean', default: false },
noExtractEmojis: { type: 'boolean', default: false }, noExtractEmojis: { type: 'boolean', default: false },
fileIds: { type: 'array', uniqueItems: true, minItems: 1, maxItems: 16, items: { fileIds: {
type: 'string', format: 'misskey:id', type: 'array',
} }, uniqueItems: true,
mediaIds: { type: 'array', uniqueItems: true, minItems: 1, maxItems: 16, items: { minItems: 1,
type: 'string', format: 'misskey:id', maxItems: 16,
} }, items: { type: 'string', format: 'misskey:id' },
},
mediaIds: {
deprecated: true,
description: 'Use `fileIds` instead. If both are specified, this property is discarded.',
type: 'array',
uniqueItems: true,
minItems: 1,
maxItems: 16,
items: { type: 'string', format: 'misskey:id' },
},
replyId: { type: 'string', format: 'misskey:id', nullable: true }, replyId: { type: 'string', format: 'misskey:id', nullable: true },
renoteId: { type: 'string', format: 'misskey:id', nullable: true }, renoteId: { type: 'string', format: 'misskey:id', nullable: true },
channelId: { type: 'string', format: 'misskey:id', nullable: true }, channelId: { type: 'string', format: 'misskey:id', nullable: true },
poll: { poll: {
type: 'object', nullable: true, type: 'object',
nullable: true,
properties: { properties: {
choices: { choices: {
type: 'array', uniqueItems: true, minItems: 2, maxItems: 10, type: 'array',
items: { uniqueItems: true,
type: 'string', minLength: 1, maxLength: 50, minItems: 2,
}, maxItems: 10,
items: { type: 'string', minLength: 1, maxLength: 50 },
}, },
multiple: { type: 'boolean', default: false }, multiple: { type: 'boolean', default: false },
expiresAt: { type: 'integer', nullable: true }, expiresAt: { type: 'integer', nullable: true },
@ -123,7 +129,34 @@ export const paramDef = {
required: ['choices'], required: ['choices'],
}, },
}, },
required: [], anyOf: [
{
// (re)note with text, files and poll are optional
properties: {
text: { type: 'string', maxLength: MAX_NOTE_TEXT_LENGTH, nullable: false },
},
required: ['text'],
},
{
// (re)note with files, text and poll are optional
required: ['fileIds'],
},
{
// (re)note with files, text and poll are optional
required: ['mediaIds'],
},
{
// (re)note with poll, text and files are optional
properties: {
poll: { type: 'object', nullable: false, },
},
required: ['poll'],
},
{
// pure renote
required: ['renoteId'],
},
],
} as const; } as const;
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export
@ -152,7 +185,7 @@ export default define(meta, paramDef, async (ps, user) => {
if (renote == null) { if (renote == null) {
throw new ApiError(meta.errors.noSuchRenoteTarget); throw new ApiError(meta.errors.noSuchRenoteTarget);
} else if (renote.renoteId && !renote.text && !renote.fileIds) { } else if (renote.renoteId && !renote.text && !renote.fileIds && !renote.poll) {
throw new ApiError(meta.errors.cannotReRenote); throw new ApiError(meta.errors.cannotReRenote);
} }
@ -175,10 +208,7 @@ export default define(meta, paramDef, async (ps, user) => {
if (reply == null) { if (reply == null) {
throw new ApiError(meta.errors.noSuchReplyTarget); throw new ApiError(meta.errors.noSuchReplyTarget);
} } else if (reply.renoteId && !reply.text && !reply.fileIds && !renote.poll) {
// 返信対象が引用でないRenoteだったらエラー
if (reply.renoteId && !reply.text && !reply.fileIds) {
throw new ApiError(meta.errors.cannotReplyToPureRenote); throw new ApiError(meta.errors.cannotReplyToPureRenote);
} }
@ -204,11 +234,6 @@ export default define(meta, paramDef, async (ps, user) => {
} }
} }
// テキストが無いかつ添付ファイルが無いかつRenoteも無いかつ投票も無かったらエラー
if (!(ps.text || files.length || renote || ps.poll)) {
throw new ApiError(meta.errors.contentRequired);
}
let channel: Channel | undefined; let channel: Channel | undefined;
if (ps.channelId != null) { if (ps.channelId != null) {
channel = await Channels.findOneBy({ id: ps.channelId }); channel = await Channels.findOneBy({ id: ps.channelId });

View file

@ -35,7 +35,11 @@ export const meta = {
export const paramDef = { export const paramDef = {
type: 'object', type: 'object',
properties: { properties: {
withFiles: { type: 'boolean' }, withFiles: {
type: 'boolean',
default: false,
description: 'Only show notes that have attached files.',
},
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
sinceId: { type: 'string', format: 'misskey:id' }, sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' },

View file

@ -48,7 +48,11 @@ export const paramDef = {
includeMyRenotes: { type: 'boolean', default: true }, includeMyRenotes: { type: 'boolean', default: true },
includeRenotedMyNotes: { type: 'boolean', default: true }, includeRenotedMyNotes: { type: 'boolean', default: true },
includeLocalRenotes: { type: 'boolean', default: true }, includeLocalRenotes: { type: 'boolean', default: true },
withFiles: { type: 'boolean' }, withFiles: {
type: 'boolean',
default: false,
description: 'Only show notes that have attached files.',
},
}, },
required: [], required: [],
} as const; } as const;

View file

@ -37,7 +37,11 @@ export const meta = {
export const paramDef = { export const paramDef = {
type: 'object', type: 'object',
properties: { properties: {
withFiles: { type: 'boolean' }, withFiles: {
type: 'boolean',
default: false,
description: 'Only show notes that have attached files.',
},
fileType: { type: 'array', items: { fileType: { type: 'array', items: {
type: 'string', type: 'string',
} }, } },

View file

@ -25,21 +25,44 @@ export const meta = {
export const paramDef = { export const paramDef = {
type: 'object', type: 'object',
properties: { properties: {
tag: { type: 'string' },
query: { type: 'array', items: {
type: 'array', items: {
type: 'string',
},
} },
reply: { type: 'boolean', nullable: true, default: null }, reply: { type: 'boolean', nullable: true, default: null },
renote: { type: 'boolean', nullable: true, default: null }, renote: { type: 'boolean', nullable: true, default: null },
withFiles: { type: 'boolean' }, withFiles: {
type: 'boolean',
default: false,
description: 'Only show notes that have attached files.',
},
poll: { type: 'boolean', nullable: true, default: null }, poll: { type: 'boolean', nullable: true, default: null },
sinceId: { type: 'string', format: 'misskey:id' }, sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' },
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
}, },
required: [], anyOf: [
{
properties: {
tag: { type: 'string', minLength: 1 },
},
required: ['tag'],
},
{
properties: {
query: {
type: 'array',
description: 'The outer arrays are chained with OR, the inner arrays are chained with AND.',
items: {
type: 'array',
items: {
type: 'string',
minLength: 1,
},
minItems: 1,
},
minItems: 1,
},
},
required: ['query'],
},
],
} as const; } as const;
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export

View file

@ -35,7 +35,11 @@ export const paramDef = {
untilId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' },
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
offset: { type: 'integer', default: 0 }, offset: { type: 'integer', default: 0 },
host: { type: 'string', nullable: true }, host: {
type: 'string',
nullable: true,
description: 'The local host is represented with `null`.',
},
userId: { type: 'string', format: 'misskey:id', nullable: true, default: null }, userId: { type: 'string', format: 'misskey:id', nullable: true, default: null },
channelId: { type: 'string', format: 'misskey:id', nullable: true, default: null }, channelId: { type: 'string', format: 'misskey:id', nullable: true, default: null },
}, },

View file

@ -38,7 +38,11 @@ export const paramDef = {
includeMyRenotes: { type: 'boolean', default: true }, includeMyRenotes: { type: 'boolean', default: true },
includeRenotedMyNotes: { type: 'boolean', default: true }, includeRenotedMyNotes: { type: 'boolean', default: true },
includeLocalRenotes: { type: 'boolean', default: true }, includeLocalRenotes: { type: 'boolean', default: true },
withFiles: { type: 'boolean' }, withFiles: {
type: 'boolean',
default: false,
description: 'Only show notes that have attached files.',
},
}, },
required: [], required: [],
} as const; } as const;

View file

@ -42,7 +42,11 @@ export const paramDef = {
includeMyRenotes: { type: 'boolean', default: true }, includeMyRenotes: { type: 'boolean', default: true },
includeRenotedMyNotes: { type: 'boolean', default: true }, includeRenotedMyNotes: { type: 'boolean', default: true },
includeLocalRenotes: { type: 'boolean', default: true }, includeLocalRenotes: { type: 'boolean', default: true },
withFiles: { type: 'boolean' }, withFiles: {
type: 'boolean',
default: false,
description: 'Only show notes that have attached files.',
},
}, },
required: ['listId'], required: ['listId'],
} as const; } as const;

View file

@ -26,12 +26,21 @@ export const meta = {
export const paramDef = { export const paramDef = {
type: 'object', type: 'object',
properties: { anyOf: [
pageId: { type: 'string', format: 'misskey:id' }, {
name: { type: 'string' }, properties: {
username: { type: 'string' }, pageId: { type: 'string', format: 'misskey:id' },
}, },
required: [], required: ['pageId'],
},
{
properties: {
name: { type: 'string' },
username: { type: 'string' },
},
required: ['name', 'username'],
},
],
} as const; } as const;
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export

View file

@ -38,14 +38,29 @@ export const meta = {
export const paramDef = { export const paramDef = {
type: 'object', type: 'object',
properties: { properties: {
userId: { type: 'string', format: 'misskey:id' },
username: { type: 'string' },
host: { type: 'string', nullable: true },
sinceId: { type: 'string', format: 'misskey:id' }, sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' },
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
}, },
required: [], anyOf: [
{
properties: {
userId: { type: 'string', format: 'misskey:id' },
},
required: ['userId'],
},
{
properties: {
username: { type: 'string' },
host: {
type: 'string',
nullable: true,
description: 'The local host is represented with `null`.',
},
},
required: ['username', 'host'],
},
],
} as const; } as const;
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export

View file

@ -38,14 +38,29 @@ export const meta = {
export const paramDef = { export const paramDef = {
type: 'object', type: 'object',
properties: { properties: {
userId: { type: 'string', format: 'misskey:id' },
username: { type: 'string' },
host: { type: 'string', nullable: true },
sinceId: { type: 'string', format: 'misskey:id' }, sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' },
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
}, },
required: [], anyOf: [
{
properties: {
userId: { type: 'string', format: 'misskey:id' },
},
required: ['userId'],
},
{
properties: {
username: { type: 'string' },
host: {
type: 'string',
nullable: true,
description: 'The local host is represented with `null`.',
},
},
required: ['username', 'host'],
},
],
} as const; } as const;
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export

View file

@ -28,7 +28,10 @@ export const paramDef = {
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
detail: { type: 'boolean', default: true }, detail: { type: 'boolean', default: true },
}, },
required: [], anyOf: [
{ required: ['username'] },
{ required: ['host'] },
],
} as const; } as const;
// TODO: avatar,bannerをJOINしたいけどエラーになる // TODO: avatar,bannerをJOINしたいけどエラーになる

View file

@ -46,15 +46,33 @@ export const meta = {
export const paramDef = { export const paramDef = {
type: 'object', type: 'object',
properties: { anyOf: [
userId: { type: 'string', format: 'misskey:id' }, {
userIds: { type: 'array', uniqueItems: true, items: { properties: {
type: 'string', format: 'misskey:id', userId: { type: 'string', format: 'misskey:id' },
} }, },
username: { type: 'string' }, required: ['userId'],
host: { type: 'string', nullable: true }, },
}, {
required: [], properties: {
userIds: { type: 'array', uniqueItems: true, items: {
type: 'string', format: 'misskey:id',
} },
},
required: ['userIds'],
},
{
properties: {
username: { type: 'string' },
host: {
type: 'string',
nullable: true,
description: 'The local host is represented with `null`.',
},
},
required: ['username', 'host'],
},
],
} as const; } as const;
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export

View file

@ -3,7 +3,7 @@
"scripts": { "scripts": {
"watch": "webpack --watch", "watch": "webpack --watch",
"build": "webpack", "build": "webpack",
"lint": "eslint --quiet src/**/*.{ts,vue}" "lint": "eslint --quiet 'src/**/*.{ts,vue}'"
}, },
"resolutions": { "resolutions": {
"chokidar": "^3.3.1", "chokidar": "^3.3.1",

View file

@ -51,14 +51,14 @@ export function applyTheme(theme: Theme, persist = true) {
if (_theme.base) { if (_theme.base) {
const base = [lightTheme, darkTheme].find(x => x.id === _theme.base); const base = [lightTheme, darkTheme].find(x => x.id === _theme.base);
_theme.props = Object.assign({}, base.props, _theme.props); if (base) _theme.props = Object.assign({}, base.props, _theme.props);
} }
const props = compile(_theme); const props = compile(_theme);
for (const tag of document.head.children) { for (const tag of document.head.children) {
if (tag.tagName === 'META' && tag.getAttribute('name') === 'theme-color') { if (tag.tagName === 'META' && tag.getAttribute('name') === 'theme-color') {
tag.setAttribute('content', props['html']); tag.setAttribute('content', props['htmlThemeColor']);
break; break;
} }
} }