summaryrefslogtreecommitdiff
path: root/src/server/api/endpoints
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2021-08-15 20:26:44 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2021-08-15 20:26:44 +0900
commitcced83024bfb578ee802ab13fc8af72a1be9a1e1 (patch)
tree359d6a3eff6250600e714e5ec2a5ae2516cd8353 /src/server/api/endpoints
parentchore: Remove vips from Dockerfile (#7633) (diff)
downloadsharkey-cced83024bfb578ee802ab13fc8af72a1be9a1e1.tar.gz
sharkey-cced83024bfb578ee802ab13fc8af72a1be9a1e1.tar.bz2
sharkey-cced83024bfb578ee802ab13fc8af72a1be9a1e1.zip
feat: ノートの翻訳機能
Resolve #5213
Diffstat (limited to 'src/server/api/endpoints')
-rw-r--r--src/server/api/endpoints/admin/update-meta.ts12
-rw-r--r--src/server/api/endpoints/meta.ts6
-rw-r--r--src/server/api/endpoints/notes/translate.ts79
3 files changed, 97 insertions, 0 deletions
diff --git a/src/server/api/endpoints/admin/update-meta.ts b/src/server/api/endpoints/admin/update-meta.ts
index a18956b3f7..573f22822c 100644
--- a/src/server/api/endpoints/admin/update-meta.ts
+++ b/src/server/api/endpoints/admin/update-meta.ts
@@ -145,6 +145,10 @@ export const meta = {
validator: $.optional.nullable.str,
},
+ deeplAuthKey: {
+ validator: $.optional.nullable.str,
+ },
+
enableTwitterIntegration: {
validator: $.optional.bool,
},
@@ -562,6 +566,14 @@ export default define(meta, async (ps, me) => {
set.objectStorageS3ForcePathStyle = ps.objectStorageS3ForcePathStyle;
}
+ if (ps.deeplAuthKey !== undefined) {
+ if (ps.deeplAuthKey === '') {
+ set.deeplAuthKey = null;
+ } else {
+ set.deeplAuthKey = ps.deeplAuthKey;
+ }
+ }
+
await getConnection().transaction(async transactionalEntityManager => {
const meta = await transactionalEntityManager.findOne(Meta, {
order: {
diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts
index dd75149ad2..561d473d6f 100644
--- a/src/server/api/endpoints/meta.ts
+++ b/src/server/api/endpoints/meta.ts
@@ -232,6 +232,10 @@ export const meta = {
type: 'boolean' as const,
optional: false as const, nullable: false as const
},
+ translatorAvailable: {
+ type: 'boolean' as const,
+ optional: false as const, nullable: false as const
+ },
proxyAccountName: {
type: 'string' as const,
optional: false as const, nullable: true as const
@@ -512,6 +516,8 @@ export default define(meta, async (ps, me) => {
enableServiceWorker: instance.enableServiceWorker,
+ translatorAvailable: instance.deeplAuthKey != null,
+
...(ps.detail ? {
pinnedPages: instance.pinnedPages,
pinnedClipId: instance.pinnedClipId,
diff --git a/src/server/api/endpoints/notes/translate.ts b/src/server/api/endpoints/notes/translate.ts
new file mode 100644
index 0000000000..bbc11274ab
--- /dev/null
+++ b/src/server/api/endpoints/notes/translate.ts
@@ -0,0 +1,79 @@
+import $ from 'cafy';
+import { ID } from '@/misc/cafy-id';
+import define from '../../define';
+import { getNote } from '../../common/getters';
+import { ApiError } from '../../error';
+import fetch from 'node-fetch';
+import config from '@/config';
+import { getAgentByUrl } from '@/misc/fetch';
+import { URLSearchParams } from 'url';
+import { fetchMeta } from '@/misc/fetch-meta';
+
+export const meta = {
+ tags: ['notes'],
+
+ requireCredential: false as const,
+
+ params: {
+ noteId: {
+ validator: $.type(ID),
+ },
+ targetLang: {
+ validator: $.str,
+ },
+ },
+
+ res: {
+ type: 'object' as const,
+ optional: false as const, nullable: false as const,
+ },
+
+ errors: {
+ noSuchNote: {
+ message: 'No such note.',
+ code: 'NO_SUCH_NOTE',
+ id: 'bea9b03f-36e0-49c5-a4db-627a029f8971'
+ }
+ }
+};
+
+export default define(meta, async (ps, user) => {
+ const note = await getNote(ps.noteId).catch(e => {
+ if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
+ throw e;
+ });
+
+ if (note.text == null) {
+ return 204;
+ }
+
+ const instance = await fetchMeta();
+
+ if (instance.deeplAuthKey == null) {
+ return 204; // TODO: 良い感じのエラー返す
+ }
+
+ const params = new URLSearchParams();
+ params.append('auth_key', instance.deeplAuthKey);
+ params.append('text', note.text);
+ params.append('target_lang', ps.targetLang);
+
+ const res = await fetch('https://api-free.deepl.com/v2/translate', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ 'User-Agent': config.userAgent,
+ Accept: 'application/json, */*'
+ },
+ body: params,
+ timeout: 10000,
+ agent: getAgentByUrl,
+ });
+
+ const json = await res.json();
+
+ return {
+ sourceLang: json.translations[0].detected_source_language,
+ text: json.translations[0].text
+ };
+});