Compare commits

...

5 commits

Author SHA1 Message Date
Kisaragi b9f3ca39aa
Merge c167caf3e7 into 85339ca751 2024-04-27 10:51:49 +09:00
Cocoa Hoto 85339ca751
feat: improve emoji endpoint (#13742) 2024-04-25 11:03:34 +09:00
FineArchs 553ba84792
AiScriptのバージョンを0.18.0に上げる (#13743)
* Update package.json

* Update autogen files

* Update flash-edit.vue

* Update flash-edit.vue

* Update CHANGELOG.md

* revert
2024-04-25 10:34:26 +09:00
Kisaragi Marine c167caf3e7
refactor(backend): encapsulate any affection in ApiCallService.ts 2024-03-14 19:50:07 +09:00
Kisaragi 4711e1a33f
refactor(backend): encapsulate any affection in ApiCallService.ts 2024-03-09 03:40:35 +09:00
6 changed files with 79 additions and 37 deletions

View file

@ -35,6 +35,7 @@
- Enhance: リプライにて引用がある場合テキストが空でもノートできるように
- 引用したいートのURLをコピーしリプライ投稿画面にペーストして添付することで達成できます
- Enhance: フォローするかどうかの確認ダイアログを出せるように
- Chore: AiScriptを0.18.0にバージョンアップ
- Fix: 一部のページ内リンクが正しく動作しない問題を修正
- Fix: 周年の実績が閏年を考慮しない問題を修正
- Fix: ローカルURLのプレビューポップアップが左上に表示される

View file

@ -120,12 +120,20 @@ export class ServerService implements OnApplicationShutdown {
return;
}
const name = path.split('@')[0].replace(/\.webp$/i, '');
const host = path.split('@')[1]?.replace(/\.webp$/i, '');
const emojiPath = path.replace(/\.webp$/i, '');
const pathChunks = emojiPath.split('@');
if (pathChunks.length > 2) {
reply.code(400);
return;
}
const name = pathChunks.shift();
const host = pathChunks.pop();
const emoji = await this.emojisRepository.findOneBy({
// `@.` is the spec of ReactionService.decodeReaction
host: (host == null || host === '.') ? IsNull() : host,
host: (host === undefined || host === '.') ? IsNull() : host,
name: name,
});

View file

@ -89,11 +89,18 @@ export class ApiCallService implements OnApplicationShutdown {
}
@bindThis
public handleRequest(
endpoint: IEndpoint & { exec: any },
public async handleRequest<Ret extends string | number | Record<string, unknown> | null | undefined>(
endpoint: IEndpoint & { exec: (
data: Record<string, unknown> | undefined,
user: MiLocalUser | null | undefined,
token: MiAccessToken | null | undefined,
file: { name: string, path: string } | null,
ip: string,
headers: any,
) => Promise<Ret> },
request: FastifyRequest<{ Body: Record<string, unknown> | undefined, Querystring: Record<string, unknown> }>,
reply: FastifyReply,
): void {
): Promise<void> {
const body = request.method === 'GET'
? request.query
: request.body;
@ -126,7 +133,14 @@ export class ApiCallService implements OnApplicationShutdown {
@bindThis
public async handleMultipartRequest(
endpoint: IEndpoint & { exec: any },
endpoint: IEndpoint & { exec: (
data: unknown,
user: MiLocalUser | null | undefined,
token: MiAccessToken | null | undefined,
file: { name: string, path: string } | null,
ip: string,
headers: any,
) => Promise<string | number | Record<string, unknown> | null | undefined> },
request: FastifyRequest<{ Body: Record<string, unknown>, Querystring: Record<string, unknown> }>,
reply: FastifyReply,
): Promise<void> {
@ -173,8 +187,18 @@ export class ApiCallService implements OnApplicationShutdown {
});
}
/**
*
* @param reply Fastifyのレスポンス
* @param x
* `null``undefined`204
* `number``y`
* `string`bodyとしJSON化してbodyとする
* @param y
* @private
*/
@bindThis
private send(reply: FastifyReply, x?: any, y?: ApiError) {
private send(reply: FastifyReply, x?: number | string | Record<string, unknown> | null | undefined, y?: ApiError) {
if (x == null) {
reply.code(204);
reply.send();
@ -220,11 +244,18 @@ export class ApiCallService implements OnApplicationShutdown {
}
@bindThis
private async call(
ep: IEndpoint & { exec: any },
private async call<Data, Ret>(
ep: IEndpoint & { exec: (
data: Data,
user: MiLocalUser | null | undefined,
token: MiAccessToken | null | undefined,
file: { name: string, path: string } | null,
ip: string,
headers: any,
) => Promise<Ret> },
user: MiLocalUser | null | undefined,
token: MiAccessToken | null | undefined,
data: any,
data: Data,
file: {
name: string;
path: string;
@ -344,8 +375,10 @@ export class ApiCallService implements OnApplicationShutdown {
if ((ep.meta.requireFile || request.method === 'GET') && ep.params.properties) {
for (const k of Object.keys(ep.params.properties)) {
const param = ep.params.properties![k];
// @ts-expect-error TS7053: Element implicitly has an any type because expression of type string can't be used to index type unknown
if (['boolean', 'number', 'integer'].includes(param.type ?? '') && typeof data[k] === 'string') {
try {
// @ts-expect-error TS7053: Element implicitly has an any type because expression of type string can't be used to index type unknown
data[k] = JSON.parse(data[k]);
} catch (e) {
throw new ApiError({
@ -362,7 +395,7 @@ export class ApiCallService implements OnApplicationShutdown {
}
// API invoking
return await ep.exec(data, user, token, file, request.ip, request.headers).catch((err: Error) => {
return await ep.exec(data, user, token, file, request.ip, request.headers).catch((err) => {
if (err instanceof ApiError || err instanceof AuthenticationError) {
throw err;
} else {

View file

@ -24,7 +24,7 @@
"@rollup/plugin-json": "6.1.0",
"@rollup/plugin-replace": "5.0.5",
"@rollup/pluginutils": "5.1.0",
"@syuilo/aiscript": "0.17.0",
"@syuilo/aiscript": "0.18.0",
"@tabler/icons-webfont": "2.44.0",
"@twemoji/parser": "15.0.0",
"@vitejs/plugin-vue": "5.0.4",

View file

@ -48,7 +48,7 @@ import MkInput from '@/components/MkInput.vue';
import MkSelect from '@/components/MkSelect.vue';
import { useRouter } from '@/router/supplier.js';
const PRESET_DEFAULT = `/// @ 0.16.0
const PRESET_DEFAULT = `/// @ 0.18.0
var name = ""
@ -60,13 +60,13 @@ Ui:render([
Ui:C:button({
text: "Hello"
onClick: @() {
Mk:dialog(null \`Hello, {name}!\`)
Mk:dialog(null, \`Hello, {name}!\`)
}
})
])
`;
const PRESET_OMIKUJI = `/// @ 0.16.0
const PRESET_OMIKUJI = `/// @ 0.18.0
//
//
@ -81,11 +81,11 @@ let choices = [
"大凶"
]
// ID+
let random = Math:gen_rng(\`{USER_ID}{Date:year()}{Date:month()}{Date:day()}\`)
// PlayID+ID+
let random = Math:gen_rng(\`{THIS_ID}{USER_ID}{Date:year()}{Date:month()}{Date:day()}\`)
//
let chosen = choices[random(0 (choices.len - 1))]
let chosen = choices[random(0, (choices.len - 1))]
//
let result = \`今日のあなたの運勢は **{chosen}** です。\`
@ -109,7 +109,7 @@ Ui:render([
])
`;
const PRESET_SHUFFLE = `/// @ 0.16.0
const PRESET_SHUFFLE = `/// @ 0.18.0
//
let string = "ペペロンチーノ"
@ -123,13 +123,13 @@ var cursor = 0
@do() {
if (cursor != 0) {
results = results.slice(0 (cursor + 1))
results = results.slice(0, (cursor + 1))
cursor = 0
}
let chars = []
for (let i, length) {
let r = Math:rnd(0 (length - 1))
let r = Math:rnd(0, (length - 1))
chars.push(string.pick(r))
}
let result = chars.join("")
@ -188,27 +188,27 @@ var cursor = 0
do()
`;
const PRESET_QUIZ = `/// @ 0.16.0
const PRESET_QUIZ = `/// @ 0.18.0
let title = '地理クイズ'
let qas = [{
q: 'オーストラリアの首都は?'
choices: ['シドニー' 'キャンベラ' 'メルボルン']
choices: ['シドニー', 'キャンベラ', 'メルボルン']
a: 'キャンベラ'
aDescription: '最大の都市はシドニーですが首都はキャンベラです。'
} {
q: '国土面積2番目の国は'
choices: ['カナダ' 'アメリカ' '中国']
choices: ['カナダ', 'アメリカ', '中国']
a: 'カナダ'
aDescription: '大きい順にロシア、カナダ、アメリカ、中国です。'
} {
q: '二重内陸国ではないのは?'
choices: ['リヒテンシュタイン' 'ウズベキスタン' 'レソト']
choices: ['リヒテンシュタイン', 'ウズベキスタン', 'レソト']
a: 'レソト'
aDescription: 'レソトは(一重)内陸国です。'
} {
q: '閘門がない運河は?'
choices: ['キール運河' 'スエズ運河' 'パナマ運河']
choices: ['キール運河', 'スエズ運河', 'パナマ運河']
a: 'スエズ運河'
aDescription: 'スエズ運河は高低差がないので閘門はありません。'
}]
@ -296,12 +296,12 @@ qaEls.push(Ui:C:container({
onClick: finish
})
]
} 'footer'))
}, 'footer'))
Ui:render(qaEls)
`;
const PRESET_TIMELINE = `/// @ 0.16.0
const PRESET_TIMELINE = `/// @ 0.18.0
// API
@fetch() {
@ -315,7 +315,7 @@ const PRESET_TIMELINE = `/// @ 0.16.0
])
//
let notes = Mk:api("notes/local-timeline" {})
let notes = Mk:api("notes/local-timeline", {})
// UI
let noteEls = []

View file

@ -707,8 +707,8 @@ importers:
specifier: 5.1.0
version: 5.1.0(rollup@4.12.0)
'@syuilo/aiscript':
specifier: 0.17.0
version: 0.17.0
specifier: 0.18.0
version: 0.18.0
'@tabler/icons-webfont':
specifier: 2.44.0
version: 2.44.0
@ -6678,7 +6678,7 @@ packages:
ts-dedent: 2.2.0
type-fest: 2.19.0
vue: 3.4.21(typescript@5.3.3)
vue-component-type-helpers: 2.0.10
vue-component-type-helpers: 2.0.14
transitivePeerDependencies:
- encoding
- supports-color
@ -6944,8 +6944,8 @@ packages:
dev: false
optional: true
/@syuilo/aiscript@0.17.0:
resolution: {integrity: sha512-3JtQ1rWJHMxQ3153zLCXMUOwrOgjPPYGBl0dPHhR0ohm4tn7okMQRugxMCT0t3YxByemb9FfiM6TUjd0tEGxdA==}
/@syuilo/aiscript@0.18.0:
resolution: {integrity: sha512-/iY9Vv4LLjtW/KUzId1QwXC4BlpIEPCMcoT7dyRhYdyxtwhS3Hx4b/4j1HYP+n3Pq9XKyW5zvkY72/+DNu4g6Q==}
dependencies:
seedrandom: 3.0.5
stringz: 2.1.0
@ -19347,8 +19347,8 @@ packages:
resolution: {integrity: sha512-6bnLkn8O0JJyiFSIF0EfCogzeqNXpnjJ0vW/SZzNHfe6sPx30lTtTXlE5TFs2qhJlAtDFybStVNpL73cPe3OMQ==}
dev: true
/vue-component-type-helpers@2.0.10:
resolution: {integrity: sha512-FC5fKJjDks3Ue/KRSYBdsiCaZa0kUPQfs8yQpb8W9mlO6BenV8G1z58xobeRMzevnmEcDa09LLwuXDwb4f6NMQ==}
/vue-component-type-helpers@2.0.14:
resolution: {integrity: sha512-DInfgOyXlMyliyqAAD9frK28tTfch0+tMi4qoWJcZlRxUf+NFAtraJBnAsKLep+FOyLMiajkhfyEb3xLK08i7w==}
dev: true
/vue-demi@0.14.7(vue@3.4.21):