Merge branch 'develop' of codeberg.org:calckey/calckey into develop
This commit is contained in:
commit
d493665922
23
packages/backend/migration/1682777547198-LibreTranslate.js
Normal file
23
packages/backend/migration/1682777547198-LibreTranslate.js
Normal file
@ -0,0 +1,23 @@
|
||||
export class LibreTranslate1682777547198 {
|
||||
name = "LibreTranslate1682777547198";
|
||||
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "meta"
|
||||
ADD "libreTranslateApiUrl" character varying(512)
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "meta"
|
||||
ADD "libreTranslateApiKey" character varying(128)
|
||||
`);
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "meta" DROP COLUMN "libreTranslateApiKey"
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "meta" DROP COLUMN "libreTranslateApiUrl"
|
||||
`);
|
||||
}
|
||||
}
|
@ -89,6 +89,11 @@ export type Source = {
|
||||
authKey?: string;
|
||||
isPro?: boolean;
|
||||
};
|
||||
libreTranslate: {
|
||||
managed?: boolean;
|
||||
apiUrl?: string;
|
||||
apiKey?: string;
|
||||
};
|
||||
email: {
|
||||
managed?: boolean;
|
||||
address?: string;
|
||||
|
@ -386,6 +386,18 @@ export class Meta {
|
||||
})
|
||||
public deeplIsPro: boolean;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 512,
|
||||
nullable: true,
|
||||
})
|
||||
public libreTranslateApiUrl: string | null;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 128,
|
||||
nullable: true,
|
||||
})
|
||||
public libreTranslateApiKey: string | null;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 512,
|
||||
nullable: true,
|
||||
|
@ -30,6 +30,17 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||
set.deeplIsPro = config.deepl.isPro;
|
||||
}
|
||||
}
|
||||
if (
|
||||
config.libreTranslate.managed != null &&
|
||||
config.libreTranslate.managed === true
|
||||
) {
|
||||
if (typeof config.libreTranslate.apiUrl === "string") {
|
||||
set.libreTranslateApiUrl = config.libreTranslate.apiUrl;
|
||||
}
|
||||
if (typeof config.libreTranslate.apiKey === "string") {
|
||||
set.libreTranslateApiKey = config.libreTranslate.apiKey;
|
||||
}
|
||||
}
|
||||
if (config.email.managed != null && config.email.managed === true) {
|
||||
set.enableEmail = true;
|
||||
if (typeof config.email.address === "string") {
|
||||
|
@ -512,7 +512,8 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||
enableGithubIntegration: instance.enableGithubIntegration,
|
||||
enableDiscordIntegration: instance.enableDiscordIntegration,
|
||||
enableServiceWorker: instance.enableServiceWorker,
|
||||
translatorAvailable: instance.deeplAuthKey != null,
|
||||
translatorAvailable:
|
||||
instance.deeplAuthKey != null || instance.libreTranslateApiUrl != null,
|
||||
pinnedPages: instance.pinnedPages,
|
||||
pinnedClipId: instance.pinnedClipId,
|
||||
cacheRemoteFiles: instance.cacheRemoteFiles,
|
||||
@ -564,6 +565,8 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||
objectStorageS3ForcePathStyle: instance.objectStorageS3ForcePathStyle,
|
||||
deeplAuthKey: instance.deeplAuthKey,
|
||||
deeplIsPro: instance.deeplIsPro,
|
||||
libreTranslateApiUrl: instance.libreTranslateApiUrl,
|
||||
libreTranslateApiKey: instance.libreTranslateApiKey,
|
||||
enableIpLogging: instance.enableIpLogging,
|
||||
enableActiveEmailValidation: instance.enableActiveEmailValidation,
|
||||
};
|
||||
|
@ -124,6 +124,8 @@ export const paramDef = {
|
||||
summalyProxy: { type: "string", nullable: true },
|
||||
deeplAuthKey: { type: "string", nullable: true },
|
||||
deeplIsPro: { type: "boolean" },
|
||||
libreTranslateApiUrl: { type: "string", nullable: true },
|
||||
libreTranslateApiKey: { type: "string", nullable: true },
|
||||
enableTwitterIntegration: { type: "boolean" },
|
||||
twitterConsumerKey: { type: "string", nullable: true },
|
||||
twitterConsumerSecret: { type: "string", nullable: true },
|
||||
@ -515,6 +517,22 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||
set.deeplIsPro = ps.deeplIsPro;
|
||||
}
|
||||
|
||||
if (ps.libreTranslateApiUrl !== undefined) {
|
||||
if (ps.libreTranslateApiUrl === "") {
|
||||
set.libreTranslateApiUrl = null;
|
||||
} else {
|
||||
set.libreTranslateApiUrl = ps.libreTranslateApiUrl;
|
||||
}
|
||||
}
|
||||
|
||||
if (ps.libreTranslateApiKey !== undefined) {
|
||||
if (ps.libreTranslateApiKey === "") {
|
||||
set.libreTranslateApiKey = null;
|
||||
} else {
|
||||
set.libreTranslateApiKey = ps.libreTranslateApiKey;
|
||||
}
|
||||
}
|
||||
|
||||
if (ps.enableIpLogging !== undefined) {
|
||||
set.enableIpLogging = ps.enableIpLogging;
|
||||
}
|
||||
|
@ -482,7 +482,8 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||
|
||||
enableServiceWorker: instance.enableServiceWorker,
|
||||
|
||||
translatorAvailable: instance.deeplAuthKey != null,
|
||||
translatorAvailable:
|
||||
instance.deeplAuthKey != null || instance.libreTranslateApiUrl != null,
|
||||
defaultReaction: instance.defaultReaction,
|
||||
|
||||
...(ps.detail
|
||||
|
@ -51,15 +51,54 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||
|
||||
const instance = await fetchMeta();
|
||||
|
||||
if (instance.deeplAuthKey == null) {
|
||||
if (instance.deeplAuthKey == null && instance.libreTranslateApiUrl == null) {
|
||||
return 204; // TODO: 良い感じのエラー返す
|
||||
}
|
||||
|
||||
let targetLang = ps.targetLang;
|
||||
if (targetLang.includes("-")) targetLang = targetLang.split("-")[0];
|
||||
|
||||
if (instance.libreTranslateApiUrl != null) {
|
||||
const jsonBody = {
|
||||
q: note.text,
|
||||
source: "auto",
|
||||
target: targetLang,
|
||||
format: "text",
|
||||
api_key: instance.libreTranslateApiKey ?? "",
|
||||
};
|
||||
|
||||
const url = new URL(instance.libreTranslateApiUrl);
|
||||
if (url.pathname.endsWith("/")) {
|
||||
url.pathname = url.pathname.slice(0, -1);
|
||||
}
|
||||
if (!url.pathname.endsWith("/translate")) {
|
||||
url.pathname += "/translate";
|
||||
}
|
||||
const res = await fetch(url.toString(), {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(jsonBody),
|
||||
agent: getAgentByUrl,
|
||||
});
|
||||
|
||||
const json = (await res.json()) as {
|
||||
detectedLanguage?: {
|
||||
confidence: number;
|
||||
language: string;
|
||||
};
|
||||
translatedText: string;
|
||||
};
|
||||
|
||||
return {
|
||||
sourceLang: json.detectedLanguage?.language,
|
||||
text: json.translatedText,
|
||||
};
|
||||
}
|
||||
|
||||
const params = new URLSearchParams();
|
||||
params.append("auth_key", instance.deeplAuthKey);
|
||||
params.append("auth_key", instance.deeplAuthKey ?? "");
|
||||
params.append("text", note.text);
|
||||
params.append("target_lang", targetLang);
|
||||
|
||||
|
@ -1,7 +0,0 @@
|
||||
node_modules
|
||||
/built
|
||||
/coverage
|
||||
/.eslintrc.js
|
||||
/jest.config.ts
|
||||
/test
|
||||
/test-d
|
@ -1,65 +0,0 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
parser: "@typescript-eslint/parser",
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: ["./tsconfig.json"],
|
||||
},
|
||||
plugins: ["@typescript-eslint"],
|
||||
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
|
||||
rules: {
|
||||
indent: [
|
||||
"error",
|
||||
"tab",
|
||||
{
|
||||
SwitchCase: 1,
|
||||
MemberExpression: "off",
|
||||
flatTernaryExpressions: true,
|
||||
ArrayExpression: "first",
|
||||
ObjectExpression: "first",
|
||||
},
|
||||
],
|
||||
"eol-last": ["error", "always"],
|
||||
semi: ["error", "always"],
|
||||
quotes: ["error", "single"],
|
||||
"comma-dangle": ["error", "always-multiline"],
|
||||
"keyword-spacing": [
|
||||
"error",
|
||||
{
|
||||
before: true,
|
||||
after: true,
|
||||
},
|
||||
],
|
||||
"key-spacing": [
|
||||
"error",
|
||||
{
|
||||
beforeColon: false,
|
||||
afterColon: true,
|
||||
},
|
||||
],
|
||||
"space-infix-ops": ["error"],
|
||||
"space-before-blocks": ["error", "always"],
|
||||
"object-curly-spacing": ["error", "always"],
|
||||
"nonblock-statement-body-position": ["error", "beside"],
|
||||
eqeqeq: ["error", "always", { null: "ignore" }],
|
||||
"no-multiple-empty-lines": ["error", { max: 1 }],
|
||||
"no-multi-spaces": ["error"],
|
||||
"no-var": ["error"],
|
||||
"prefer-arrow-callback": ["error"],
|
||||
"no-throw-literal": ["error"],
|
||||
"no-param-reassign": ["warn"],
|
||||
"no-constant-condition": ["warn"],
|
||||
"no-empty-pattern": ["warn"],
|
||||
"@typescript-eslint/no-unnecessary-condition": ["error"],
|
||||
"@typescript-eslint/no-inferrable-types": ["warn"],
|
||||
"@typescript-eslint/no-non-null-assertion": ["warn"],
|
||||
"@typescript-eslint/explicit-function-return-type": ["warn"],
|
||||
"@typescript-eslint/no-misused-promises": [
|
||||
"error",
|
||||
{
|
||||
checksVoidReturn: false,
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/consistent-type-imports": "error",
|
||||
},
|
||||
};
|
@ -9,9 +9,8 @@
|
||||
"tsd": "tsd",
|
||||
"api": "pnpm api-extractor run --local --verbose",
|
||||
"api-prod": "pnpm api-extractor run --verbose",
|
||||
"eslint": "eslint . --ext .js,.jsx,.ts,.tsx",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"lint": "pnpm typecheck && pnpm eslint",
|
||||
"lint": "pnpm typecheck && pnpm rome check \"src/*.ts\"",
|
||||
"jest": "jest --coverage --detectOpenHandles",
|
||||
"test": "pnpm jest && pnpm tsd"
|
||||
},
|
||||
|
@ -371,6 +371,34 @@
|
||||
<template #label>Pro account</template>
|
||||
</FormSwitch>
|
||||
</FormSection>
|
||||
|
||||
<FormSection>
|
||||
<template #label>Libre Translate</template>
|
||||
|
||||
<FormInput
|
||||
v-model="libreTranslateApiUrl"
|
||||
class="_formBlock"
|
||||
>
|
||||
<template #prefix
|
||||
><i class="ph-link ph-bold ph-lg"></i
|
||||
></template>
|
||||
<template #label
|
||||
>Libre Translate API URL</template
|
||||
>
|
||||
</FormInput>
|
||||
|
||||
<FormInput
|
||||
v-model="libreTranslateApiKey"
|
||||
class="_formBlock"
|
||||
>
|
||||
<template #prefix
|
||||
><i class="ph-key ph-bold ph-lg"></i
|
||||
></template>
|
||||
<template #label
|
||||
>Libre Translate API Key</template
|
||||
>
|
||||
</FormInput>
|
||||
</FormSection>
|
||||
</div>
|
||||
</FormSuspense>
|
||||
</MkSpacer>
|
||||
@ -422,6 +450,8 @@ let swPublicKey: any = $ref(null);
|
||||
let swPrivateKey: any = $ref(null);
|
||||
let deeplAuthKey: string = $ref("");
|
||||
let deeplIsPro: boolean = $ref(false);
|
||||
let libreTranslateApiUrl: string = $ref("");
|
||||
let libreTranslateApiKey: string = $ref("");
|
||||
let defaultReaction: string = $ref("");
|
||||
let defaultReactionCustom: string = $ref("");
|
||||
|
||||
@ -456,6 +486,8 @@ async function init() {
|
||||
swPrivateKey = meta.swPrivateKey;
|
||||
deeplAuthKey = meta.deeplAuthKey;
|
||||
deeplIsPro = meta.deeplIsPro;
|
||||
libreTranslateApiUrl = meta.libreTranslateApiUrl;
|
||||
libreTranslateApiKey = meta.libreTranslateApiKey;
|
||||
defaultReaction = ["⭐", "👍", "❤️"].includes(meta.defaultReaction)
|
||||
? meta.defaultReaction
|
||||
: "custom";
|
||||
@ -498,6 +530,8 @@ function save() {
|
||||
swPrivateKey,
|
||||
deeplAuthKey,
|
||||
deeplIsPro,
|
||||
libreTranslateApiUrl,
|
||||
libreTranslateApiKey,
|
||||
defaultReaction,
|
||||
}).then(() => {
|
||||
fetchInstance();
|
||||
|
Loading…
Reference in New Issue
Block a user