diff --git a/CHANGELOG.md b/CHANGELOG.md index cde4ad96a6d85eef81e58d95dedf1f052a5684bd..460e75b22b031d639651cceabb280302ca9261ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ChangeLog ========= ------------------- +### ✨Improvements +* アンテナã§é™¤å¤–ã‚ーワードをè¨å®šã§ãるよã†ã« + ### ðŸ›Fixes * ãƒãƒƒã‚·ãƒ¥ã‚¿ã‚°ã‚’ã‚‚ã£ã¨è¦‹ã‚‹ã§ããªã„ã®ã‚’ä¿®æ£ * 無効ã«ãªã£ã¦ã„るタイムラインã§ã‚‚使用ã§ãã‚‹ã‹ã®ã‚ˆã†ã«è¡¨ç¤ºã•ã‚Œã‚‹å•é¡Œã‚’ä¿®æ£ diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index da255351e4826e2407ba216f2152b99c2794dbb9..e65deb61c5895b34744e1946ab11e98bc7a1af59 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -286,6 +286,7 @@ manageAntennas: "アンテナã®ç®¡ç†" name: "åå‰" antennaSource: "å—信ソース" antennaKeywords: "å—ä¿¡ã‚ーワード" +antennaExcludeKeywords: "除外ã‚ーワード" antennaKeywordsDescription: "スペースã§åŒºåˆ‡ã‚‹ã¨AND指定ã«ãªã‚Šã€æ”¹è¡Œã§åŒºåˆ‡ã‚‹ã¨OR指定ã«ãªã‚Šã¾ã™" notifyAntenna: "æ–°ã—ã„ノートを通知ã™ã‚‹" withFileAntenna: "ファイルãŒæ·»ä»˜ã•ã‚ŒãŸãƒŽãƒ¼ãƒˆã®ã¿" diff --git a/migration/1582210532752-antenna-exclude.ts b/migration/1582210532752-antenna-exclude.ts new file mode 100644 index 0000000000000000000000000000000000000000..bff47a3ec6e16461a4777e4d1b756fc63c6cf939 --- /dev/null +++ b/migration/1582210532752-antenna-exclude.ts @@ -0,0 +1,14 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class antennaExclude1582210532752 implements MigrationInterface { + name = 'antennaExclude1582210532752' + + public async up(queryRunner: QueryRunner): Promise<any> { + await queryRunner.query(`ALTER TABLE "antenna" ADD "excludeKeywords" jsonb NOT NULL DEFAULT '[]'`, undefined); + } + + public async down(queryRunner: QueryRunner): Promise<any> { + await queryRunner.query(`ALTER TABLE "antenna" DROP COLUMN "excludeKeywords"`, undefined); + } + +} diff --git a/src/client/pages/my-antennas/index.antenna.vue b/src/client/pages/my-antennas/index.antenna.vue index d0259a55c65284c6fd03d17626a793e808e6d46b..2a9aebbcbf90be57f900850f4dc09a31ce429feb 100644 --- a/src/client/pages/my-antennas/index.antenna.vue +++ b/src/client/pages/my-antennas/index.antenna.vue @@ -30,6 +30,10 @@ <span>{{ $t('antennaKeywords') }}</span> <template #desc>{{ $t('antennaKeywordsDescription') }}</template> </mk-textarea> + <mk-textarea v-model="excludeKeywords"> + <span>{{ $t('antennaExcludeKeywords') }}</span> + <template #desc>{{ $t('antennaKeywordsDescription') }}</template> + </mk-textarea> <mk-switch v-model="caseSensitive">{{ $t('caseSensitive') }}</mk-switch> <mk-switch v-model="withFile">{{ $t('withFileAntenna') }}</mk-switch> <mk-switch v-model="notify">{{ $t('notifyAntenna') }}</mk-switch> @@ -75,6 +79,7 @@ export default Vue.extend({ userGroupId: null, users: '', keywords: '', + excludeKeywords: '', caseSensitive: false, withReplies: false, withFile: false, @@ -107,6 +112,7 @@ export default Vue.extend({ this.userGroupId = this.antenna.userGroupId; this.users = this.antenna.users.join('\n'); this.keywords = this.antenna.keywords.map(x => x.join(' ')).join('\n'); + this.excludeKeywords = this.antenna.excludeKeywords.map(x => x.join(' ')).join('\n'); this.caseSensitive = this.antenna.caseSensitive; this.withReplies = this.antenna.withReplies; this.withFile = this.antenna.withFile; @@ -126,7 +132,8 @@ export default Vue.extend({ notify: this.notify, caseSensitive: this.caseSensitive, users: this.users.trim().split('\n').map(x => x.trim()), - keywords: this.keywords.trim().split('\n').map(x => x.trim().split(' ')) + keywords: this.keywords.trim().split('\n').map(x => x.trim().split(' ')), + excludeKeywords: this.excludeKeywords.trim().split('\n').map(x => x.trim().split(' ')), }); this.$emit('created'); } else { @@ -141,7 +148,8 @@ export default Vue.extend({ notify: this.notify, caseSensitive: this.caseSensitive, users: this.users.trim().split('\n').map(x => x.trim()), - keywords: this.keywords.trim().split('\n').map(x => x.trim().split(' ')) + keywords: this.keywords.trim().split('\n').map(x => x.trim().split(' ')), + excludeKeywords: this.excludeKeywords.trim().split('\n').map(x => x.trim().split(' ')), }); } diff --git a/src/client/pages/my-antennas/index.vue b/src/client/pages/my-antennas/index.vue index 8ac70ac37825b41878550f07eb9e335b9e5819d9..a5f6076ebff5bd222e0c7a1978ec6e869dcdd45b 100644 --- a/src/client/pages/my-antennas/index.vue +++ b/src/client/pages/my-antennas/index.vue @@ -53,6 +53,7 @@ export default Vue.extend({ userGroupId: null, users: [], keywords: [], + excludeKeywords: [], withReplies: false, caseSensitive: false, withFile: false, diff --git a/src/misc/check-hit-antenna.ts b/src/misc/check-hit-antenna.ts index c229a07ebed82d6ae00d7a7d65d0e29ea4c81a21..0d72c3f34007b557543cf68f85eb5d28258dde6c 100644 --- a/src/misc/check-hit-antenna.ts +++ b/src/misc/check-hit-antenna.ts @@ -52,6 +52,19 @@ export async function checkHitAntenna(antenna: Antenna, note: Note, noteUser: Us if (!matched) return false; } + if (antenna.excludeKeywords.length > 0) { + if (note.text == null) return false; + + const matched = antenna.excludeKeywords.some(keywords => + keywords.every(keyword => + antenna.caseSensitive + ? note.text!.includes(keyword) + : note.text!.toLowerCase().includes(keyword.toLowerCase()) + )); + + if (matched) return false; + } + if (antenna.withFile) { if (note.fileIds.length === 0) return false; } diff --git a/src/models/entities/antenna.ts b/src/models/entities/antenna.ts index 7c2027b6ec126d3f4e57fbb4da8071792abbc344..bcfe09a8293c610b1da80466467cc101ce1d4206 100644 --- a/src/models/entities/antenna.ts +++ b/src/models/entities/antenna.ts @@ -71,6 +71,11 @@ export class Antenna { }) public keywords: string[][]; + @Column('jsonb', { + default: [] + }) + public excludeKeywords: string[][]; + @Column('boolean', { default: false }) diff --git a/src/models/repositories/antenna.ts b/src/models/repositories/antenna.ts index 9f8aa11347d0ea2a22b40c73004a9a522b040791..16ef2e5a390f506d025de2bfa03bbc91df096b48 100644 --- a/src/models/repositories/antenna.ts +++ b/src/models/repositories/antenna.ts @@ -21,6 +21,7 @@ export class AntennaRepository extends Repository<Antenna> { createdAt: antenna.createdAt.toISOString(), name: antenna.name, keywords: antenna.keywords, + excludeKeywords: antenna.excludeKeywords, src: antenna.src, userListId: antenna.userListId, userGroupId: userGroupJoining ? userGroupJoining.userGroupId : null, diff --git a/src/server/api/endpoints/antennas/create.ts b/src/server/api/endpoints/antennas/create.ts index 658b8221f2c3460635ea2ea7cde7526596c9a675..f11b198f8683440e3fe707df72d34164852da381 100644 --- a/src/server/api/endpoints/antennas/create.ts +++ b/src/server/api/endpoints/antennas/create.ts @@ -33,6 +33,10 @@ export const meta = { validator: $.arr($.arr($.str)) }, + excludeKeywords: { + validator: $.arr($.arr($.str)) + }, + users: { validator: $.arr($.str) }, @@ -102,6 +106,7 @@ export default define(meta, async (ps, user) => { userListId: userList ? userList.id : null, userGroupJoiningId: userGroupJoining ? userGroupJoining.id : null, keywords: ps.keywords, + excludeKeywords: ps.excludeKeywords, users: ps.users, caseSensitive: ps.caseSensitive, withReplies: ps.withReplies, diff --git a/src/server/api/endpoints/antennas/update.ts b/src/server/api/endpoints/antennas/update.ts index 520e17c4ae0a8960c72a23709e376154d724f19f..ab4ce57937e92d8fba15c872c2461835ad23ebbd 100644 --- a/src/server/api/endpoints/antennas/update.ts +++ b/src/server/api/endpoints/antennas/update.ts @@ -36,6 +36,10 @@ export const meta = { validator: $.arr($.arr($.str)) }, + excludeKeywords: { + validator: $.arr($.arr($.str)) + }, + users: { validator: $.arr($.str) }, @@ -118,6 +122,7 @@ export default define(meta, async (ps, user) => { userListId: userList ? userList.id : null, userGroupJoiningId: userGroupJoining ? userGroupJoining.id : null, keywords: ps.keywords, + excludeKeywords: ps.excludeKeywords, users: ps.users, caseSensitive: ps.caseSensitive, withReplies: ps.withReplies,