mirror of
https://github.com/misskey-dev/misskey.git
synced 2024-12-23 00:29:22 +09:00
Merge branch 'develop' into feat-14931
This commit is contained in:
commit
662bfd64bb
@ -8,6 +8,7 @@
|
||||
### General
|
||||
- Feat: コンテンツの表示にログインを必須にできるように
|
||||
- Feat: 過去のノートを非公開化/フォロワーのみ表示可能にできるように
|
||||
- Fix: お知らせ作成時に画像URL入力欄を空欄に変更できないのを修正 ( #14976 )
|
||||
- Enhance: 依存関係の更新
|
||||
- Enhance: l10nの更新
|
||||
|
||||
@ -28,6 +29,7 @@
|
||||
- Enhance: 過去に送信したフォローリクエストを確認できるように
|
||||
(Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/663)
|
||||
- Enhance: サイドバーを簡単に展開・折りたたみできるように ( #14981 )
|
||||
- Enhance: リノートメニューに「リノートの詳細」を追加
|
||||
- Enhance: Blueskyの投稿埋め込みプレビューに対応
|
||||
- Fix: 通知の範囲指定の設定項目が必要ない通知設定でも範囲指定の設定がでている問題を修正
|
||||
- Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正
|
||||
@ -40,6 +42,8 @@
|
||||
- Fix: メールアドレス登録有効化時の「完了」ダイアログボックスの表示条件を修正
|
||||
- Fix: 画面幅が狭い環境でデザインが崩れる問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/815)
|
||||
- Fix: TypeScriptの型チェック対象ファイルを限定してビルドを高速化するように
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/725)
|
||||
|
||||
### Server
|
||||
- Enhance: DockerのNode.jsを22.11.0に更新
|
||||
|
4
locales/index.d.ts
vendored
4
locales/index.d.ts
vendored
@ -2362,6 +2362,10 @@ export interface Locale extends ILocale {
|
||||
* 詳細
|
||||
*/
|
||||
"details": string;
|
||||
/**
|
||||
* リノートの詳細
|
||||
*/
|
||||
"renoteDetails": string;
|
||||
/**
|
||||
* 絵文字を選択
|
||||
*/
|
||||
|
@ -586,6 +586,7 @@ masterVolume: "マスター音量"
|
||||
notUseSound: "サウンドを出力しない"
|
||||
useSoundOnlyWhenActive: "Misskeyがアクティブな時のみサウンドを出力する"
|
||||
details: "詳細"
|
||||
renoteDetails: "リノートの詳細"
|
||||
chooseEmoji: "絵文字を選択"
|
||||
unableToProcess: "操作を完了できません"
|
||||
recentUsed: "最近使用"
|
||||
|
@ -154,9 +154,9 @@ export class AbuseReportNotificationService implements OnApplicationShutdown {
|
||||
const convertedReports = abuseReports.map(it => {
|
||||
return {
|
||||
...it,
|
||||
reporter: usersMap.get(it.reporterId),
|
||||
targetUser: usersMap.get(it.targetUserId),
|
||||
assignee: it.assigneeId ? usersMap.get(it.assigneeId) : null,
|
||||
reporter: usersMap.get(it.reporterId) ?? null,
|
||||
targetUser: usersMap.get(it.targetUserId) ?? null,
|
||||
assignee: it.assigneeId ? (usersMap.get(it.assigneeId) ?? null) : null,
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -72,7 +72,7 @@ export class AnnouncementService {
|
||||
updatedAt: null,
|
||||
title: values.title,
|
||||
text: values.text,
|
||||
imageUrl: values.imageUrl,
|
||||
imageUrl: values.imageUrl || null,
|
||||
icon: values.icon,
|
||||
display: values.display,
|
||||
forExistingUsers: values.forExistingUsers,
|
||||
|
@ -7,13 +7,15 @@ import { randomUUID } from 'node:crypto';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import type { IActivity } from '@/core/activitypub/type.js';
|
||||
import type { MiDriveFile } from '@/models/DriveFile.js';
|
||||
import type { MiWebhook, WebhookEventTypes, webhookEventTypes } from '@/models/Webhook.js';
|
||||
import type { MiWebhook, WebhookEventTypes } from '@/models/Webhook.js';
|
||||
import type { MiSystemWebhook, SystemWebhookEventType } from '@/models/SystemWebhook.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { Antenna } from '@/server/api/endpoints/i/import-antennas.js';
|
||||
import { ApRequestCreator } from '@/core/activitypub/ApRequestService.js';
|
||||
import { type SystemWebhookPayload } from '@/core/SystemWebhookService.js';
|
||||
import { type UserWebhookPayload } from './UserWebhookService.js';
|
||||
import type {
|
||||
DbJobData,
|
||||
DeliverJobData,
|
||||
@ -30,12 +32,11 @@ import type {
|
||||
ObjectStorageQueue,
|
||||
RelationshipQueue,
|
||||
SystemQueue,
|
||||
UserWebhookDeliverQueue,
|
||||
SystemWebhookDeliverQueue,
|
||||
UserWebhookDeliverQueue,
|
||||
} from './QueueModule.js';
|
||||
import type httpSignature from '@peertube/http-signature';
|
||||
import type * as Bull from 'bullmq';
|
||||
import { type UserWebhookPayload } from './UserWebhookService.js';
|
||||
|
||||
@Injectable()
|
||||
export class QueueService {
|
||||
@ -501,10 +502,10 @@ export class QueueService {
|
||||
* @see SystemWebhookDeliverProcessorService
|
||||
*/
|
||||
@bindThis
|
||||
public systemWebhookDeliver(
|
||||
public systemWebhookDeliver<T extends SystemWebhookEventType>(
|
||||
webhook: MiSystemWebhook,
|
||||
type: SystemWebhookEventType,
|
||||
content: unknown,
|
||||
type: T,
|
||||
content: SystemWebhookPayload<T>,
|
||||
opts?: { attempts?: number },
|
||||
) {
|
||||
const data: SystemWebhookDeliverJobData = {
|
||||
|
@ -15,8 +15,39 @@ import { QueueService } from '@/core/QueueService.js';
|
||||
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||
import { LoggerService } from '@/core/LoggerService.js';
|
||||
import Logger from '@/logger.js';
|
||||
import { Packed } from '@/misc/json-schema.js';
|
||||
import { AbuseReportResolveType } from '@/models/AbuseUserReport.js';
|
||||
import { ModeratorInactivityRemainingTime } from '@/queue/processors/CheckModeratorsActivityProcessorService.js';
|
||||
import type { OnApplicationShutdown } from '@nestjs/common';
|
||||
|
||||
export type AbuseReportPayload = {
|
||||
id: string;
|
||||
targetUserId: string;
|
||||
targetUser: Packed<'UserLite'> | null;
|
||||
targetUserHost: string | null;
|
||||
reporterId: string;
|
||||
reporter: Packed<'UserLite'> | null;
|
||||
reporterHost: string | null;
|
||||
assigneeId: string | null;
|
||||
assignee: Packed<'UserLite'> | null;
|
||||
resolved: boolean;
|
||||
forwarded: boolean;
|
||||
comment: string;
|
||||
moderationNote: string;
|
||||
resolvedAs: AbuseReportResolveType | null;
|
||||
};
|
||||
|
||||
export type InactiveModeratorsWarningPayload = {
|
||||
remainingTime: ModeratorInactivityRemainingTime;
|
||||
};
|
||||
|
||||
export type SystemWebhookPayload<T extends SystemWebhookEventType> =
|
||||
T extends 'abuseReport' | 'abuseReportResolved' ? AbuseReportPayload :
|
||||
T extends 'userCreated' ? Packed<'UserLite'> :
|
||||
T extends 'inactiveModeratorsWarning' ? InactiveModeratorsWarningPayload :
|
||||
T extends 'inactiveModeratorsInvitationOnlyChanged' ? Record<string, never> :
|
||||
never;
|
||||
|
||||
@Injectable()
|
||||
export class SystemWebhookService implements OnApplicationShutdown {
|
||||
private logger: Logger;
|
||||
@ -168,7 +199,7 @@ export class SystemWebhookService implements OnApplicationShutdown {
|
||||
public async enqueueSystemWebhook<T extends SystemWebhookEventType>(
|
||||
webhook: MiSystemWebhook | MiSystemWebhook['id'],
|
||||
type: T,
|
||||
content: unknown,
|
||||
content: SystemWebhookPayload<T>,
|
||||
) {
|
||||
const webhookEntity = typeof webhook === 'string'
|
||||
? (await this.fetchActiveSystemWebhooks()).find(a => a.id === webhook)
|
||||
|
@ -7,7 +7,7 @@ import { Injectable } from '@nestjs/common';
|
||||
import { MiAbuseUserReport, MiNote, MiUser, MiWebhook } from '@/models/_.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { MiSystemWebhook, type SystemWebhookEventType } from '@/models/SystemWebhook.js';
|
||||
import { SystemWebhookService } from '@/core/SystemWebhookService.js';
|
||||
import { AbuseReportPayload, SystemWebhookPayload, SystemWebhookService } from '@/core/SystemWebhookService.js';
|
||||
import { Packed } from '@/misc/json-schema.js';
|
||||
import { type WebhookEventTypes } from '@/models/Webhook.js';
|
||||
import { type UserWebhookPayload, UserWebhookService } from '@/core/UserWebhookService.js';
|
||||
@ -16,13 +16,7 @@ import { ModeratorInactivityRemainingTime } from '@/queue/processors/CheckModera
|
||||
|
||||
const oneDayMillis = 24 * 60 * 60 * 1000;
|
||||
|
||||
type AbuseUserReportDto = Omit<MiAbuseUserReport, 'targetUser' | 'reporter' | 'assignee'> & {
|
||||
targetUser: Packed<'UserLite'> | null,
|
||||
reporter: Packed<'UserLite'> | null,
|
||||
assignee: Packed<'UserLite'> | null,
|
||||
};
|
||||
|
||||
function generateAbuseReport(override?: Partial<MiAbuseUserReport>): AbuseUserReportDto {
|
||||
function generateAbuseReport(override?: Partial<MiAbuseUserReport>): AbuseReportPayload {
|
||||
const result: MiAbuseUserReport = {
|
||||
id: 'dummy-abuse-report1',
|
||||
targetUserId: 'dummy-target-user',
|
||||
@ -389,7 +383,8 @@ export class WebhookTestService {
|
||||
break;
|
||||
}
|
||||
// まだ実装されていない (#9485)
|
||||
case 'reaction': return;
|
||||
case 'reaction':
|
||||
return;
|
||||
default: {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const _exhaustiveAssertion: never = params.type;
|
||||
@ -407,10 +402,10 @@ export class WebhookTestService {
|
||||
* - 送信対象イベント(on)に関する設定
|
||||
*/
|
||||
@bindThis
|
||||
public async testSystemWebhook(
|
||||
public async testSystemWebhook<T extends SystemWebhookEventType>(
|
||||
params: {
|
||||
webhookId: MiSystemWebhook['id'],
|
||||
type: SystemWebhookEventType,
|
||||
type: T,
|
||||
override?: Partial<Omit<MiSystemWebhook, 'id'>>,
|
||||
},
|
||||
) {
|
||||
@ -420,7 +415,7 @@ export class WebhookTestService {
|
||||
}
|
||||
|
||||
const webhook = webhooks[0];
|
||||
const send = (contents: unknown) => {
|
||||
const send = <U extends SystemWebhookEventType>(type: U, contents: SystemWebhookPayload<U>) => {
|
||||
const merged = {
|
||||
...webhook,
|
||||
...params.override,
|
||||
@ -428,12 +423,12 @@ export class WebhookTestService {
|
||||
|
||||
// テスト目的なのでSystemWebhookServiceの機能を経由せず直接キューに追加する(チェック処理などをスキップする意図).
|
||||
// また、Jobの試行回数も1回だけ.
|
||||
this.queueService.systemWebhookDeliver(merged, params.type, contents, { attempts: 1 });
|
||||
this.queueService.systemWebhookDeliver(merged, type, contents, { attempts: 1 });
|
||||
};
|
||||
|
||||
switch (params.type) {
|
||||
case 'abuseReport': {
|
||||
send(generateAbuseReport({
|
||||
send('abuseReport', generateAbuseReport({
|
||||
targetUserId: dummyUser1.id,
|
||||
targetUser: dummyUser1,
|
||||
reporterId: dummyUser2.id,
|
||||
@ -442,7 +437,7 @@ export class WebhookTestService {
|
||||
break;
|
||||
}
|
||||
case 'abuseReportResolved': {
|
||||
send(generateAbuseReport({
|
||||
send('abuseReportResolved', generateAbuseReport({
|
||||
targetUserId: dummyUser1.id,
|
||||
targetUser: dummyUser1,
|
||||
reporterId: dummyUser2.id,
|
||||
@ -454,7 +449,7 @@ export class WebhookTestService {
|
||||
break;
|
||||
}
|
||||
case 'userCreated': {
|
||||
send(toPackedUserLite(dummyUser1));
|
||||
send('userCreated', toPackedUserLite(dummyUser1));
|
||||
break;
|
||||
}
|
||||
case 'inactiveModeratorsWarning': {
|
||||
@ -464,15 +459,20 @@ export class WebhookTestService {
|
||||
asHours: 24,
|
||||
};
|
||||
|
||||
send({
|
||||
send('inactiveModeratorsWarning', {
|
||||
remainingTime: dummyTime,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'inactiveModeratorsInvitationOnlyChanged': {
|
||||
send({});
|
||||
send('inactiveModeratorsInvitationOnlyChanged', {});
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const _exhaustiveAssertion: never = params.type;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typ
|
||||
import { id } from './util/id.js';
|
||||
import { MiUser } from './User.js';
|
||||
|
||||
export type AbuseReportResolveType = 'accept' | 'reject';
|
||||
|
||||
@Entity('abuse_user_report')
|
||||
export class MiAbuseUserReport {
|
||||
@PrimaryColumn(id())
|
||||
@ -76,7 +78,7 @@ export class MiAbuseUserReport {
|
||||
@Column('varchar', {
|
||||
length: 128, nullable: true,
|
||||
})
|
||||
public resolvedAs: 'accept' | 'reject' | null;
|
||||
public resolvedAs: AbuseReportResolveType | null;
|
||||
|
||||
//#region Denormalized fields
|
||||
@Index()
|
||||
|
@ -55,7 +55,7 @@ export const paramDef = {
|
||||
properties: {
|
||||
title: { type: 'string', minLength: 1 },
|
||||
text: { type: 'string', minLength: 1 },
|
||||
imageUrl: { type: 'string', nullable: true, minLength: 1 },
|
||||
imageUrl: { type: 'string', nullable: true, minLength: 0 },
|
||||
icon: { type: 'string', enum: ['info', 'warning', 'error', 'success'], default: 'info' },
|
||||
display: { type: 'string', enum: ['normal', 'banner', 'dialog'], default: 'normal' },
|
||||
forExistingUsers: { type: 'boolean', default: false },
|
||||
@ -76,7 +76,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
updatedAt: null,
|
||||
title: ps.title,
|
||||
text: ps.text,
|
||||
imageUrl: ps.imageUrl,
|
||||
/* eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- 空の文字列の場合、nullを渡すようにするため */
|
||||
imageUrl: ps.imageUrl || null,
|
||||
icon: ps.icon,
|
||||
display: ps.display,
|
||||
forExistingUsers: ps.forExistingUsers,
|
||||
|
@ -33,7 +33,7 @@
|
||||
"./node_modules"
|
||||
],
|
||||
"types": [
|
||||
"vite/client",
|
||||
"vite/client"
|
||||
],
|
||||
"lib": [
|
||||
"esnext",
|
||||
@ -44,8 +44,9 @@
|
||||
},
|
||||
"compileOnSave": false,
|
||||
"include": [
|
||||
"./**/*.ts",
|
||||
"./**/*.vue"
|
||||
"./src/**/*.ts",
|
||||
"./src/**/*.vue",
|
||||
"./@types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
".storybook/**/*"
|
||||
|
@ -187,6 +187,7 @@ import MkUrlPreview from '@/components/MkUrlPreview.vue';
|
||||
import MkInstanceTicker from '@/components/MkInstanceTicker.vue';
|
||||
import { pleaseLogin, type OpenOnRemoteOptions } from '@/scripts/please-login.js';
|
||||
import { checkWordMute } from '@/scripts/check-word-mute.js';
|
||||
import { notePage } from '@/filters/note.js';
|
||||
import { userPage } from '@/filters/user.js';
|
||||
import number from '@/filters/number.js';
|
||||
import * as os from '@/os.js';
|
||||
@ -566,15 +567,24 @@ function showRenoteMenu(): void {
|
||||
};
|
||||
}
|
||||
|
||||
const renoteDetailsMenu: MenuItem = {
|
||||
type: 'link',
|
||||
text: i18n.ts.renoteDetails,
|
||||
icon: 'ti ti-info-circle',
|
||||
to: notePage(note.value),
|
||||
};
|
||||
|
||||
if (isMyRenote) {
|
||||
pleaseLogin({ openOnRemote: pleaseLoginContext.value });
|
||||
os.popupMenu([
|
||||
renoteDetailsMenu,
|
||||
getCopyNoteLinkMenu(note.value, i18n.ts.copyLinkRenote),
|
||||
{ type: 'divider' },
|
||||
getUnrenote(),
|
||||
], renoteTime.value);
|
||||
} else {
|
||||
os.popupMenu([
|
||||
renoteDetailsMenu,
|
||||
getCopyNoteLinkMenu(note.value, i18n.ts.copyLinkRenote),
|
||||
{ type: 'divider' },
|
||||
getAbuseNoteMenu(note.value, i18n.ts.reportAbuseRenote),
|
||||
|
@ -45,8 +45,11 @@
|
||||
},
|
||||
"compileOnSave": false,
|
||||
"include": [
|
||||
"./**/*.ts",
|
||||
"./**/*.vue"
|
||||
"./src/**/*.ts",
|
||||
"./src/**/*.vue",
|
||||
"./test/**/*.ts",
|
||||
"./test/**/*.vue",
|
||||
"./@types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
".storybook/**/*"
|
||||
|
Loading…
Reference in New Issue
Block a user