From 8fb8d7c10caac6696a9364beb3457521f3966c31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Fri, 29 Dec 2023 18:22:40 +0900 Subject: [PATCH 1/5] =?UTF-8?q?enhance(frontend):=20=E3=83=8F=E3=83=83?= =?UTF-8?q?=E3=82=B7=E3=83=A5=E3=82=BF=E3=82=B0=E5=85=A5=E5=8A=9B=E6=99=82?= =?UTF-8?q?=E3=81=AB=E3=80=81=E6=9C=AC=E6=96=87=E3=81=AE=E6=9C=AB=E5=B0=BE?= =?UTF-8?q?=E3=81=AE=E8=A1=8C=E3=81=AB=E4=BD=95=E3=82=82=E6=9B=B8=E3=81=8B?= =?UTF-8?q?=E3=82=8C=E3=81=A6=E3=81=84=E3=81=AA=E3=81=84=E5=A0=B4=E5=90=88?= =?UTF-8?q?=E3=81=AF=E6=96=B0=E3=81=9F=E3=81=AB=E3=82=B9=E3=83=9A=E3=83=BC?= =?UTF-8?q?=E3=82=B9=E3=82=92=E8=BF=BD=E5=8A=A0=E3=81=97=E3=81=AA=E3=81=84?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=20(#12851)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * (enhance) ハッシュタグ入力時に、本文の末尾の行に何も書かれていないならスペースを追記しない * Updahe Changelog --- CHANGELOG.md | 5 +++++ packages/frontend/src/components/MkPostForm.vue | 12 +++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30e2e57b7d..ea34fa9ef7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,11 @@ --> +## 202x.x.x (Unreleased) + +### Client +- Enhance: ハッシュタグ入力時に、本文の末尾の行に何も書かれていない場合は新たにスペースを追加しないように + ## 2023.12.2 ### General diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue index 3aacf4c2da..b86f50eac6 100644 --- a/packages/frontend/src/components/MkPostForm.vue +++ b/packages/frontend/src/components/MkPostForm.vue @@ -752,7 +752,17 @@ async function post(ev?: MouseEvent) { if (withHashtags.value && hashtags.value && hashtags.value.trim() !== '') { const hashtags_ = hashtags.value.trim().split(' ').map(x => x.startsWith('#') ? x : '#' + x).join(' '); - postData.text = postData.text ? `${postData.text} ${hashtags_}` : hashtags_; + if (!postData.text) { + postData.text = hashtags_; + } else { + const postTextLines = postData.text.split('\n'); + if (postTextLines[postTextLines.length - 1].trim() === '') { + postTextLines[postTextLines.length - 1] += hashtags_; + } else { + postTextLines[postTextLines.length - 1] += ' ' + hashtags_; + } + postData.text = postTextLines.join('\n'); + } } // plugin From 7948018e6a4735fc32d61e8690319802e38baf3a Mon Sep 17 00:00:00 2001 From: MomentQYC <62551256+MomentQYC@users.noreply.github.com> Date: Fri, 29 Dec 2023 17:23:29 +0800 Subject: [PATCH 2/5] feat: Add support for TrueMail (#12850) Co-authored-by: MarryDream <2190758465@qq.com> --- .../1703658526000-supportTrueMailApi.js | 20 ++++++ packages/backend/src/core/EmailService.ts | 69 ++++++++++++++++++- packages/backend/src/models/Meta.ts | 17 +++++ .../src/server/api/endpoints/admin/meta.ts | 15 ++++ .../server/api/endpoints/admin/update-meta.ts | 23 +++++++ .../frontend/src/pages/admin/security.vue | 17 +++++ 6 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 packages/backend/migration/1703658526000-supportTrueMailApi.js diff --git a/packages/backend/migration/1703658526000-supportTrueMailApi.js b/packages/backend/migration/1703658526000-supportTrueMailApi.js new file mode 100644 index 0000000000..0054d54122 --- /dev/null +++ b/packages/backend/migration/1703658526000-supportTrueMailApi.js @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: syuilo and other misskey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export class SupportTrueMailApi1703658526000 { + name = 'SupportTrueMailApi1703658526000' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ADD "truemailInstance" character varying(1024)`); + await queryRunner.query(`ALTER TABLE "meta" ADD "truemailAuthKey" character varying(1024)`); + await queryRunner.query(`ALTER TABLE "meta" ADD "enableTruemailApi" boolean NOT NULL DEFAULT false`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableTruemailApi"`); + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "truemailInstance"`); + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "truemailAuthKey"`); + } +} diff --git a/packages/backend/src/core/EmailService.ts b/packages/backend/src/core/EmailService.ts index 7fc7800783..7e812b4df2 100644 --- a/packages/backend/src/core/EmailService.ts +++ b/packages/backend/src/core/EmailService.ts @@ -156,7 +156,7 @@ export class EmailService { @bindThis public async validateEmailForAccount(emailAddress: string): Promise<{ available: boolean; - reason: null | 'used' | 'format' | 'disposable' | 'mx' | 'smtp' | 'banned'; + reason: null | 'used' | 'format' | 'disposable' | 'mx' | 'smtp' | 'banned' | 'network' | 'blacklist'; }> { const meta = await this.metaService.fetch(); @@ -173,6 +173,8 @@ export class EmailService { if (meta.enableActiveEmailValidation) { if (meta.enableVerifymailApi && meta.verifymailAuthKey != null) { validated = await this.verifyMail(emailAddress, meta.verifymailAuthKey); + } else if (meta.enableTruemailApi && meta.truemailInstance && meta.truemailAuthKey != null) { + validated = await this.trueMail(meta.truemailInstance, emailAddress, meta.truemailAuthKey); } else { validated = await validateEmail({ email: emailAddress, @@ -201,6 +203,8 @@ export class EmailService { validated.reason === 'disposable' ? 'disposable' : validated.reason === 'mx' ? 'mx' : validated.reason === 'smtp' ? 'smtp' : + validated.reason === 'network' ? 'network' : + validated.reason === 'blacklist' ? 'blacklist' : null, }; } @@ -265,4 +269,67 @@ export class EmailService { reason: null, }; } + + private async trueMail(truemailInstance: string, emailAddress: string, truemailAuthKey: string): Promise<{ + valid: boolean; + reason: 'used' | 'format' | 'blacklist' | 'mx' | 'smtp' | 'network' | T | null; + }> { + const endpoint = truemailInstance + '?email=' + emailAddress; + try { + const res = await this.httpRequestService.send(endpoint, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + Authorization: truemailAuthKey + }, + }); + + const json = (await res.json()) as { + email: string; + success: boolean; + errors?: { + list_match?: string; + regex?: string; + mx?: string; + smtp?: string; + } | null; + }; + + if (json.email === undefined || (json.email !== undefined && json.errors?.regex)) { + return { + valid: false, + reason: 'format', + }; + } + if (json.errors?.smtp) { + return { + valid: false, + reason: 'smtp', + }; + } + if (json.errors?.mx) { + return { + valid: false, + reason: 'mx', + }; + } + if (!json.success) { + return { + valid: false, + reason: json.errors?.list_match as T || 'blacklist', + }; + } + + return { + valid: true, + reason: null, + }; + } catch (error) { + return { + valid: false, + reason: 'network', + }; + } + } } diff --git a/packages/backend/src/models/Meta.ts b/packages/backend/src/models/Meta.ts index 84ca762492..f5a75ed28a 100644 --- a/packages/backend/src/models/Meta.ts +++ b/packages/backend/src/models/Meta.ts @@ -457,6 +457,23 @@ export class MiMeta { }) public verifymailAuthKey: string | null; + @Column('boolean', { + default: false, + }) + public enableTruemailApi: boolean; + + @Column('varchar', { + length: 1024, + nullable: true, + }) + public truemailInstance: string | null; + + @Column('varchar', { + length: 1024, + nullable: true, + }) + public truemailAuthKey: string | null; + @Column('boolean', { default: true, }) diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index febc4ab1b1..281f6c484c 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -284,6 +284,18 @@ export const meta = { type: 'string', optional: false, nullable: true, }, + enableTruemailApi: { + type: 'boolean', + optional: false, nullable: false, + }, + truemailInstance: { + type: 'string', + optional: false, nullable: true, + }, + truemailAuthKey: { + type: 'string', + optional: false, nullable: true, + }, enableChartsForRemoteUser: { type: 'boolean', optional: false, nullable: false, @@ -520,6 +532,9 @@ export default class extends Endpoint { // eslint- enableActiveEmailValidation: instance.enableActiveEmailValidation, enableVerifymailApi: instance.enableVerifymailApi, verifymailAuthKey: instance.verifymailAuthKey, + enableTruemailApi: instance.enableTruemailApi, + truemailInstance: instance.truemailInstance, + truemailAuthKey: instance.truemailAuthKey, enableChartsForRemoteUser: instance.enableChartsForRemoteUser, enableChartsForFederatedInstances: instance.enableChartsForFederatedInstances, enableServerMachineStats: instance.enableServerMachineStats, diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts index 5a215696fb..3a6426435d 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -116,6 +116,9 @@ export const paramDef = { enableActiveEmailValidation: { type: 'boolean' }, enableVerifymailApi: { type: 'boolean' }, verifymailAuthKey: { type: 'string', nullable: true }, + enableTruemailApi: { type: 'boolean' }, + truemailInstance: { type: 'string', nullable: true }, + truemailAuthKey: { type: 'string', nullable: true }, enableChartsForRemoteUser: { type: 'boolean' }, enableChartsForFederatedInstances: { type: 'boolean' }, enableServerMachineStats: { type: 'boolean' }, @@ -469,6 +472,26 @@ export default class extends Endpoint { // eslint- set.verifymailAuthKey = ps.verifymailAuthKey; } } + + if (ps.enableTruemailApi !== undefined) { + set.enableTruemailApi = ps.enableTruemailApi; + } + + if (ps.truemailInstance !== undefined) { + if (ps.truemailInstance === '') { + set.truemailInstance = null; + } else { + set.truemailInstance = ps.truemailInstance; + } + } + + if (ps.truemailAuthKey !== undefined) { + if (ps.truemailAuthKey === '') { + set.truemailAuthKey = null; + } else { + set.truemailAuthKey = ps.truemailAuthKey; + } + } if (ps.enableChartsForRemoteUser !== undefined) { set.enableChartsForRemoteUser = ps.enableChartsForRemoteUser; diff --git a/packages/frontend/src/pages/admin/security.vue b/packages/frontend/src/pages/admin/security.vue index 7070157ca9..8d79dea20f 100644 --- a/packages/frontend/src/pages/admin/security.vue +++ b/packages/frontend/src/pages/admin/security.vue @@ -80,6 +80,17 @@ SPDX-License-Identifier: AGPL-3.0-only + + + + + + + + + + + @@ -153,6 +164,9 @@ const enableIpLogging = ref(false); const enableActiveEmailValidation = ref(false); const enableVerifymailApi = ref(false); const verifymailAuthKey = ref(null); +const enableTruemailApi = ref(false); +const truemailInstance = ref(null); +const truemailAuthKey = ref(null); const bannedEmailDomains = ref(''); async function init() { @@ -194,6 +208,9 @@ function save() { enableActiveEmailValidation: enableActiveEmailValidation.value, enableVerifymailApi: enableVerifymailApi.value, verifymailAuthKey: verifymailAuthKey.value, + enableTruemailApi: enableTruemailApi.value, + truemailInstance: truemailInstance.value, + truemailAuthKey: truemailAuthKey.value, bannedEmailDomains: bannedEmailDomains.value.split('\n'), }).then(() => { fetchInstance(); From 30594dde181e9d151542c41c6f09e673fcbb3124 Mon Sep 17 00:00:00 2001 From: woxtu Date: Fri, 29 Dec 2023 22:50:03 +0900 Subject: [PATCH 3/5] Fix a typo (#12853) --- COPYING | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/COPYING b/COPYING index c218443d42..905d3e1236 100644 --- a/COPYING +++ b/COPYING @@ -1,5 +1,5 @@ Unless otherwise stated this repository is -Copyright © 2014-2023 syuilo and contributers +Copyright © 2014-2023 syuilo and contributors And is distributed under The GNU Affero General Public License Version 3, you should have received a copy of the license file as LICENSE. From c0466d1585d37a32537e545ee9df3b990da44e85 Mon Sep 17 00:00:00 2001 From: woxtu Date: Sun, 31 Dec 2023 07:51:58 +0900 Subject: [PATCH 4/5] Convert symbols to strings explicitly (#12844) --- packages/frontend/src/pizzax.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/pizzax.ts b/packages/frontend/src/pizzax.ts index b2254a0611..d26899dbde 100644 --- a/packages/frontend/src/pizzax.ts +++ b/packages/frontend/src/pizzax.ts @@ -168,7 +168,7 @@ export class Storage { this.reactiveState[key].value = this.state[key] = rawValue; return this.addIdbSetJob(async () => { - if (_DEV_) console.log(`set ${key} start`); + if (_DEV_) console.log(`set ${String(key)} start`); switch (this.def[key].where) { case 'device': { this.pizzaxChannel.postMessage({ @@ -207,7 +207,7 @@ export class Storage { break; } } - if (_DEV_) console.log(`set ${key} complete`); + if (_DEV_) console.log(`set ${String(key)} complete`); }); } From 2a3398181104e8cfa1aed84badd2fdf64428ec2b Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 31 Dec 2023 09:45:35 +0900 Subject: [PATCH 5/5] chore: use summaly, browser-image-resizer, and sharp-read-bmp on registry.npmjs.org instead of git (#12856) * chore: use @misskey-dev/summaly on registry.npmjs.org instead of git * fix backend dependency * fic backend dependency * @misskey-dev/sharp-read-bmp * fix * use @misskey-dev/browser-image-resizer --- packages/backend/package.json | 4 +- packages/backend/src/core/DriveService.ts | 2 +- .../backend/src/server/FileServerService.ts | 2 +- .../src/server/web/UrlPreviewService.ts | 2 +- packages/frontend/package.json | 4 +- .../frontend/src/components/MkUrlPreview.vue | 2 +- packages/frontend/src/scripts/upload.ts | 2 +- .../src/scripts/upload/compress-config.ts | 4 +- packages/frontend/test/url-preview.test.ts | 2 +- pnpm-lock.yaml | 130 ++++++------------ 10 files changed, 54 insertions(+), 100 deletions(-) diff --git a/packages/backend/package.json b/packages/backend/package.json index 4d1e9936aa..710412c43d 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -74,6 +74,8 @@ "@fastify/multipart": "8.0.0", "@fastify/static": "6.12.0", "@fastify/view": "8.2.0", + "@misskey-dev/sharp-read-bmp": "^1.1.1", + "@misskey-dev/summaly": "^5.0.3", "@nestjs/common": "10.2.10", "@nestjs/core": "10.2.10", "@nestjs/testing": "10.2.10", @@ -157,11 +159,9 @@ "sanitize-html": "2.11.0", "secure-json-parse": "2.7.0", "sharp": "0.32.6", - "sharp-read-bmp": "github:misskey-dev/sharp-read-bmp", "slacc": "0.0.10", "strict-event-emitter-types": "2.0.0", "stringz": "2.1.0", - "summaly": "github:misskey-dev/summaly", "systeminformation": "5.21.20", "tinycolor2": "1.6.0", "tmp": "0.2.1", diff --git a/packages/backend/src/core/DriveService.ts b/packages/backend/src/core/DriveService.ts index 484f4fc52e..04f0e38e6f 100644 --- a/packages/backend/src/core/DriveService.ts +++ b/packages/backend/src/core/DriveService.ts @@ -7,7 +7,7 @@ import { randomUUID } from 'node:crypto'; import * as fs from 'node:fs'; import { Inject, Injectable } from '@nestjs/common'; import sharp from 'sharp'; -import { sharpBmp } from 'sharp-read-bmp'; +import { sharpBmp } from '@misskey-dev/sharp-read-bmp'; import { IsNull } from 'typeorm'; import { DeleteObjectCommandInput, PutObjectCommandInput, NoSuchKey } from '@aws-sdk/client-s3'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/FileServerService.ts b/packages/backend/src/server/FileServerService.ts index 0c7fc8cefe..f59996ce17 100644 --- a/packages/backend/src/server/FileServerService.ts +++ b/packages/backend/src/server/FileServerService.ts @@ -9,7 +9,7 @@ import { dirname } from 'node:path'; import { Inject, Injectable } from '@nestjs/common'; import rename from 'rename'; import sharp from 'sharp'; -import { sharpBmp } from 'sharp-read-bmp'; +import { sharpBmp } from '@misskey-dev/sharp-read-bmp'; import type { Config } from '@/config.js'; import type { MiDriveFile, DriveFilesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/web/UrlPreviewService.ts b/packages/backend/src/server/web/UrlPreviewService.ts index d590244e34..3fd88355dd 100644 --- a/packages/backend/src/server/web/UrlPreviewService.ts +++ b/packages/backend/src/server/web/UrlPreviewService.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import { summaly } from 'summaly'; +import { summaly } from '@misskey-dev/summaly'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import { MetaService } from '@/core/MetaService.js'; diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 523fc281b3..d3c655b0db 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -19,6 +19,7 @@ "dependencies": { "@discordapp/twemoji": "15.0.2", "@github/webauthn-json": "2.1.1", + "@misskey-dev/browser-image-resizer": "2.2.1-misskey.10", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-replace": "5.0.5", "@rollup/pluginutils": "5.1.0", @@ -30,7 +31,6 @@ "aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.0.6", "astring": "1.8.6", "broadcast-channel": "7.0.0", - "browser-image-resizer": "github:misskey-dev/browser-image-resizer#v2.2.1-misskey.3", "buraha": "0.0.1", "canvas-confetti": "1.6.1", "chart.js": "4.4.1", @@ -74,6 +74,7 @@ "vuedraggable": "next" }, "devDependencies": { + "@misskey-dev/summaly": "^5.0.3", "@storybook/addon-actions": "7.6.5", "@storybook/addon-essentials": "7.6.5", "@storybook/addon-interactions": "7.6.5", @@ -127,7 +128,6 @@ "start-server-and-test": "2.0.3", "storybook": "7.6.5", "storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme", - "summaly": "github:misskey-dev/summaly", "vite-plugin-turbosnap": "1.0.3", "vitest": "0.34.6", "vitest-fetch-mock": "0.2.2", diff --git a/packages/frontend/src/components/MkUrlPreview.vue b/packages/frontend/src/components/MkUrlPreview.vue index f0f1a13d0b..54f23780c2 100644 --- a/packages/frontend/src/components/MkUrlPreview.vue +++ b/packages/frontend/src/components/MkUrlPreview.vue @@ -84,7 +84,7 @@ SPDX-License-Identifier: AGPL-3.0-only