enhance(antenna): Botの投稿を除外できるように (#13603)
* enhance(antenna): Botの投稿を除外できるように (MisskeyIO#545)
(cherry picked from commit a95ce067c6)
* Update Changelog
* remove translations
* spdx
---------
Co-authored-by: まっちゃとーにゅ <17376330+u1-liquid@users.noreply.github.com>
			
			
This commit is contained in:
		
							parent
							
								
									7795045b23
								
							
						
					
					
						commit
						f4838e50b4
					
				|  | @ -1,6 +1,8 @@ | |||
| ## Unreleased | ||||
| 
 | ||||
| ### General | ||||
| - Enhance: アンテナでBotによるノートを除外できるように   | ||||
|   (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/545) | ||||
| - Fix: Play作成時に設定した公開範囲が機能していない問題を修正 | ||||
| 
 | ||||
| ### Client | ||||
|  |  | |||
|  | @ -1616,6 +1616,10 @@ export interface Locale extends ILocale { | |||
|      * 除外キーワード | ||||
|      */ | ||||
|     "antennaExcludeKeywords": string; | ||||
|     /** | ||||
|      * Botアカウントを除外 | ||||
|      */ | ||||
|     "antennaExcludeBots": string; | ||||
|     /** | ||||
|      * スペースで区切るとAND指定になり、改行で区切るとOR指定になります | ||||
|      */ | ||||
|  |  | |||
|  | @ -400,6 +400,7 @@ name: "名前" | |||
| antennaSource: "受信ソース" | ||||
| antennaKeywords: "受信キーワード" | ||||
| antennaExcludeKeywords: "除外キーワード" | ||||
| antennaExcludeBots: "Botアカウントを除外" | ||||
| antennaKeywordsDescription: "スペースで区切るとAND指定になり、改行で区切るとOR指定になります" | ||||
| notifyAntenna: "新しいノートを通知する" | ||||
| withFileAntenna: "ファイルが添付されたノートのみ" | ||||
|  |  | |||
|  | @ -0,0 +1,16 @@ | |||
| /* | ||||
|  * SPDX-FileCopyrightText: syuilo and misskey-project | ||||
|  * SPDX-License-Identifier: AGPL-3.0-only | ||||
|  */ | ||||
| 
 | ||||
| export class AntennaExcludeBots1710919614510 { | ||||
|     name = 'AntennaExcludeBots1710919614510' | ||||
| 
 | ||||
|     async up(queryRunner) { | ||||
|         await queryRunner.query(`ALTER TABLE "antenna" ADD "excludeBots" boolean NOT NULL DEFAULT false`); | ||||
|     } | ||||
| 
 | ||||
|     async down(queryRunner) { | ||||
|         await queryRunner.query(`ALTER TABLE "antenna" DROP COLUMN "excludeBots"`); | ||||
|     } | ||||
| } | ||||
|  | @ -92,7 +92,7 @@ export class AntennaService implements OnApplicationShutdown { | |||
| 	} | ||||
| 
 | ||||
| 	@bindThis | ||||
| 	public async addNoteToAntennas(note: MiNote, noteUser: { id: MiUser['id']; username: string; host: string | null; }): Promise<void> { | ||||
| 	public async addNoteToAntennas(note: MiNote, noteUser: { id: MiUser['id']; username: string; host: string | null; isBot: boolean; }): Promise<void> { | ||||
| 		const antennas = await this.getAntennas(); | ||||
| 		const antennasWithMatchResult = await Promise.all(antennas.map(antenna => this.checkHitAntenna(antenna, note, noteUser).then(hit => [antenna, hit] as const))); | ||||
| 		const matchedAntennas = antennasWithMatchResult.filter(([, hit]) => hit).map(([antenna]) => antenna); | ||||
|  | @ -110,10 +110,12 @@ export class AntennaService implements OnApplicationShutdown { | |||
| 	// NOTE: フォローしているユーザーのノート、リストのユーザーのノート、グループのユーザーのノート指定はパフォーマンス上の理由で無効になっている
 | ||||
| 
 | ||||
| 	@bindThis | ||||
| 	public async checkHitAntenna(antenna: MiAntenna, note: (MiNote | Packed<'Note'>), noteUser: { id: MiUser['id']; username: string; host: string | null; }): Promise<boolean> { | ||||
| 	public async checkHitAntenna(antenna: MiAntenna, note: (MiNote | Packed<'Note'>), noteUser: { id: MiUser['id']; username: string; host: string | null; isBot: boolean; }): Promise<boolean> { | ||||
| 		if (note.visibility === 'specified') return false; | ||||
| 		if (note.visibility === 'followers') return false; | ||||
| 
 | ||||
| 		if (antenna.excludeBots && noteUser.isBot) return false; | ||||
| 
 | ||||
| 		if (antenna.localOnly && noteUser.host != null) return false; | ||||
| 
 | ||||
| 		if (!antenna.withReplies && note.replyId != null) return false; | ||||
|  |  | |||
|  | @ -39,6 +39,7 @@ export class AntennaEntityService { | |||
| 			caseSensitive: antenna.caseSensitive, | ||||
| 			localOnly: antenna.localOnly, | ||||
| 			notify: antenna.notify, | ||||
| 			excludeBots: antenna.excludeBots, | ||||
| 			withReplies: antenna.withReplies, | ||||
| 			withFile: antenna.withFile, | ||||
| 			isActive: antenna.isActive, | ||||
|  |  | |||
|  | @ -72,6 +72,11 @@ export class MiAntenna { | |||
| 	}) | ||||
| 	public caseSensitive: boolean; | ||||
| 
 | ||||
| 	@Column('boolean', { | ||||
| 		default: false, | ||||
| 	}) | ||||
| 	public excludeBots: boolean; | ||||
| 
 | ||||
| 	@Column('boolean', { | ||||
| 		default: false, | ||||
| 	}) | ||||
|  |  | |||
|  | @ -76,6 +76,11 @@ export const packedAntennaSchema = { | |||
| 			type: 'boolean', | ||||
| 			optional: false, nullable: false, | ||||
| 		}, | ||||
| 		excludeBots: { | ||||
| 			type: 'boolean', | ||||
| 			optional: false, nullable: false, | ||||
| 			default: false, | ||||
| 		}, | ||||
| 		withReplies: { | ||||
| 			type: 'boolean', | ||||
| 			optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -81,6 +81,7 @@ export class ExportAntennasProcessorService { | |||
| 					}) : null, | ||||
| 					caseSensitive: antenna.caseSensitive, | ||||
| 					localOnly: antenna.localOnly, | ||||
| 					excludeBots: antenna.excludeBots, | ||||
| 					withReplies: antenna.withReplies, | ||||
| 					withFile: antenna.withFile, | ||||
| 					notify: antenna.notify, | ||||
|  |  | |||
|  | @ -44,6 +44,7 @@ const validate = new Ajv().compile({ | |||
| 		} }, | ||||
| 		caseSensitive: { type: 'boolean' }, | ||||
| 		localOnly: { type: 'boolean' }, | ||||
| 		excludeBots: { type: 'boolean' }, | ||||
| 		withReplies: { type: 'boolean' }, | ||||
| 		withFile: { type: 'boolean' }, | ||||
| 		notify: { type: 'boolean' }, | ||||
|  | @ -88,6 +89,7 @@ export class ImportAntennasProcessorService { | |||
| 					users: (antenna.src === 'list' && antenna.userListAccts !== null ? antenna.userListAccts : antenna.users).filter(Boolean), | ||||
| 					caseSensitive: antenna.caseSensitive, | ||||
| 					localOnly: antenna.localOnly, | ||||
| 					excludeBots: antenna.excludeBots, | ||||
| 					withReplies: antenna.withReplies, | ||||
| 					withFile: antenna.withFile, | ||||
| 					notify: antenna.notify, | ||||
|  |  | |||
|  | @ -64,6 +64,7 @@ export const paramDef = { | |||
| 		} }, | ||||
| 		caseSensitive: { type: 'boolean' }, | ||||
| 		localOnly: { type: 'boolean' }, | ||||
| 		excludeBots: { type: 'boolean' }, | ||||
| 		withReplies: { type: 'boolean' }, | ||||
| 		withFile: { type: 'boolean' }, | ||||
| 		notify: { type: 'boolean' }, | ||||
|  | @ -124,6 +125,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- | |||
| 				users: ps.users, | ||||
| 				caseSensitive: ps.caseSensitive, | ||||
| 				localOnly: ps.localOnly, | ||||
| 				excludeBots: ps.excludeBots, | ||||
| 				withReplies: ps.withReplies, | ||||
| 				withFile: ps.withFile, | ||||
| 				notify: ps.notify, | ||||
|  |  | |||
|  | @ -63,6 +63,7 @@ export const paramDef = { | |||
| 		} }, | ||||
| 		caseSensitive: { type: 'boolean' }, | ||||
| 		localOnly: { type: 'boolean' }, | ||||
| 		excludeBots: { type: 'boolean' }, | ||||
| 		withReplies: { type: 'boolean' }, | ||||
| 		withFile: { type: 'boolean' }, | ||||
| 		notify: { type: 'boolean' }, | ||||
|  | @ -120,6 +121,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- | |||
| 				users: ps.users, | ||||
| 				caseSensitive: ps.caseSensitive, | ||||
| 				localOnly: ps.localOnly, | ||||
| 				excludeBots: ps.excludeBots, | ||||
| 				withReplies: ps.withReplies, | ||||
| 				withFile: ps.withFile, | ||||
| 				notify: ps.notify, | ||||
|  |  | |||
|  | @ -44,6 +44,7 @@ describe('アンテナ', () => { | |||
| 		users: [''], | ||||
| 		withFile: false, | ||||
| 		withReplies: false, | ||||
| 		excludeBots: false, | ||||
| 	}; | ||||
| 
 | ||||
| 	let root: User; | ||||
|  | @ -156,6 +157,7 @@ describe('アンテナ', () => { | |||
| 			users: [''], | ||||
| 			withFile: false, | ||||
| 			withReplies: false, | ||||
| 			excludeBots: false, | ||||
| 			localOnly: false, | ||||
| 		}; | ||||
| 		assert.deepStrictEqual(response, expected); | ||||
|  |  | |||
|  | @ -26,6 +26,7 @@ const draft = ref({ | |||
| 	users: [], | ||||
| 	keywords: [], | ||||
| 	excludeKeywords: [], | ||||
| 	excludeBots: false, | ||||
| 	withReplies: false, | ||||
| 	caseSensitive: false, | ||||
| 	localOnly: false, | ||||
|  |  | |||
|  | @ -26,6 +26,7 @@ SPDX-License-Identifier: AGPL-3.0-only | |||
| 				<template #label>{{ i18n.ts.users }}</template> | ||||
| 				<template #caption>{{ i18n.ts.antennaUsersDescription }} <button class="_textButton" @click="addUser">{{ i18n.ts.addUser }}</button></template> | ||||
| 			</MkTextarea> | ||||
| 			<MkSwitch v-model="excludeBots">{{ i18n.ts.antennaExcludeBots }}</MkSwitch> | ||||
| 			<MkSwitch v-model="withReplies">{{ i18n.ts.withReplies }}</MkSwitch> | ||||
| 			<MkTextarea v-model="keywords"> | ||||
| 				<template #label>{{ i18n.ts.antennaKeywords }}</template> | ||||
|  | @ -78,6 +79,7 @@ const keywords = ref<string>(props.antenna.keywords.map(x => x.join(' ')).join(' | |||
| const excludeKeywords = ref<string>(props.antenna.excludeKeywords.map(x => x.join(' ')).join('\n')); | ||||
| const caseSensitive = ref<boolean>(props.antenna.caseSensitive); | ||||
| const localOnly = ref<boolean>(props.antenna.localOnly); | ||||
| const excludeBots = ref<boolean>(props.antenna.excludeBots); | ||||
| const withReplies = ref<boolean>(props.antenna.withReplies); | ||||
| const withFile = ref<boolean>(props.antenna.withFile); | ||||
| const notify = ref<boolean>(props.antenna.notify); | ||||
|  | @ -94,6 +96,7 @@ async function saveAntenna() { | |||
| 		name: name.value, | ||||
| 		src: src.value, | ||||
| 		userListId: userListId.value, | ||||
| 		excludeBots: excludeBots.value, | ||||
| 		withReplies: withReplies.value, | ||||
| 		withFile: withFile.value, | ||||
| 		notify: notify.value, | ||||
|  |  | |||
|  | @ -4434,6 +4434,8 @@ export type components = { | |||
|       localOnly: boolean; | ||||
|       notify: boolean; | ||||
|       /** @default false */ | ||||
|       excludeBots: boolean; | ||||
|       /** @default false */ | ||||
|       withReplies: boolean; | ||||
|       withFile: boolean; | ||||
|       isActive: boolean; | ||||
|  | @ -9654,6 +9656,7 @@ export type operations = { | |||
|           users: string[]; | ||||
|           caseSensitive: boolean; | ||||
|           localOnly?: boolean; | ||||
|           excludeBots?: boolean; | ||||
|           withReplies: boolean; | ||||
|           withFile: boolean; | ||||
|           notify: boolean; | ||||
|  | @ -9935,6 +9938,7 @@ export type operations = { | |||
|           users?: string[]; | ||||
|           caseSensitive?: boolean; | ||||
|           localOnly?: boolean; | ||||
|           excludeBots?: boolean; | ||||
|           withReplies?: boolean; | ||||
|           withFile?: boolean; | ||||
|           notify?: boolean; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue