feat: local-only antenna

Resolve #11869
This commit is contained in:
syuilo 2023-10-16 15:06:00 +09:00
parent 6a321ba340
commit 3ebed5aa3e
15 changed files with 47 additions and 3 deletions

View File

@ -15,7 +15,7 @@
## 2023.x.x (unreleased) ## 2023.x.x (unreleased)
### General ### General
- - Feat: アンテナでローカルの投稿のみ収集できるようになりました
### Client ### Client
- Enhance: TLの返信表示オプションを記憶するように - Enhance: TLの返信表示オプションを記憶するように

View File

@ -0,0 +1,16 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class AntennaLocalOnly1697436246389 {
name = 'AntennaLocalOnly1697436246389'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "antenna" ADD "localOnly" boolean NOT NULL DEFAULT false`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "antenna" DROP COLUMN "localOnly"`);
}
}

View File

@ -98,6 +98,8 @@ export class AntennaService implements OnApplicationShutdown {
if (note.visibility === 'specified') return false; if (note.visibility === 'specified') return false;
if (note.visibility === 'followers') return false; if (note.visibility === 'followers') return false;
if (antenna.localOnly && noteUser.host != null) return false;
if (!antenna.withReplies && note.replyId != null) return false; if (!antenna.withReplies && note.replyId != null) return false;
if (antenna.src === 'home') { if (antenna.src === 'home') {

View File

@ -37,6 +37,7 @@ export class AntennaEntityService {
userListId: antenna.userListId, userListId: antenna.userListId,
users: antenna.users, users: antenna.users,
caseSensitive: antenna.caseSensitive, caseSensitive: antenna.caseSensitive,
localOnly: antenna.localOnly,
notify: antenna.notify, notify: antenna.notify,
withReplies: antenna.withReplies, withReplies: antenna.withReplies,
withFile: antenna.withFile, withFile: antenna.withFile,

View File

@ -93,4 +93,9 @@ export class MiAntenna {
default: true, default: true,
}) })
public isActive: boolean; public isActive: boolean;
@Column('boolean', {
default: false,
})
public localOnly: boolean;
} }

View File

@ -67,6 +67,11 @@ export const packedAntennaSchema = {
optional: false, nullable: false, optional: false, nullable: false,
default: false, default: false,
}, },
localOnly: {
type: 'boolean',
optional: false, nullable: false,
default: false,
},
notify: { notify: {
type: 'boolean', type: 'boolean',
optional: false, nullable: false, optional: false, nullable: false,

View File

@ -80,6 +80,7 @@ export class ExportAntennasProcessorService {
return this.utilityService.getFullApAccount(u.username, u.host); // acct return this.utilityService.getFullApAccount(u.username, u.host); // acct
}) : null, }) : null,
caseSensitive: antenna.caseSensitive, caseSensitive: antenna.caseSensitive,
localOnly: antenna.localOnly,
withReplies: antenna.withReplies, withReplies: antenna.withReplies,
withFile: antenna.withFile, withFile: antenna.withFile,
notify: antenna.notify, notify: antenna.notify,

View File

@ -43,6 +43,7 @@ const validate = new Ajv().compile({
type: 'string', type: 'string',
} }, } },
caseSensitive: { type: 'boolean' }, caseSensitive: { type: 'boolean' },
localOnly: { type: 'boolean' },
withReplies: { type: 'boolean' }, withReplies: { type: 'boolean' },
withFile: { type: 'boolean' }, withFile: { type: 'boolean' },
notify: { type: 'boolean' }, notify: { type: 'boolean' },
@ -86,6 +87,7 @@ export class ImportAntennasProcessorService {
excludeKeywords: antenna.excludeKeywords, excludeKeywords: antenna.excludeKeywords,
users: (antenna.src === 'list' && antenna.userListAccts !== null ? antenna.userListAccts : antenna.users).filter(Boolean), users: (antenna.src === 'list' && antenna.userListAccts !== null ? antenna.userListAccts : antenna.users).filter(Boolean),
caseSensitive: antenna.caseSensitive, caseSensitive: antenna.caseSensitive,
localOnly: antenna.localOnly,
withReplies: antenna.withReplies, withReplies: antenna.withReplies,
withFile: antenna.withFile, withFile: antenna.withFile,
notify: antenna.notify, notify: antenna.notify,

View File

@ -63,6 +63,7 @@ export const paramDef = {
type: 'string', type: 'string',
} }, } },
caseSensitive: { type: 'boolean' }, caseSensitive: { type: 'boolean' },
localOnly: { type: 'boolean' },
withReplies: { type: 'boolean' }, withReplies: { type: 'boolean' },
withFile: { type: 'boolean' }, withFile: { type: 'boolean' },
notify: { type: 'boolean' }, notify: { type: 'boolean' },
@ -122,6 +123,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
excludeKeywords: ps.excludeKeywords, excludeKeywords: ps.excludeKeywords,
users: ps.users, users: ps.users,
caseSensitive: ps.caseSensitive, caseSensitive: ps.caseSensitive,
localOnly: ps.localOnly,
withReplies: ps.withReplies, withReplies: ps.withReplies,
withFile: ps.withFile, withFile: ps.withFile,
notify: ps.notify, notify: ps.notify,

View File

@ -62,6 +62,7 @@ export const paramDef = {
type: 'string', type: 'string',
} }, } },
caseSensitive: { type: 'boolean' }, caseSensitive: { type: 'boolean' },
localOnly: { type: 'boolean' },
withReplies: { type: 'boolean' }, withReplies: { type: 'boolean' },
withFile: { type: 'boolean' }, withFile: { type: 'boolean' },
notify: { type: 'boolean' }, notify: { type: 'boolean' },
@ -116,6 +117,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
excludeKeywords: ps.excludeKeywords, excludeKeywords: ps.excludeKeywords,
users: ps.users, users: ps.users,
caseSensitive: ps.caseSensitive, caseSensitive: ps.caseSensitive,
localOnly: ps.localOnly,
withReplies: ps.withReplies, withReplies: ps.withReplies,
withFile: ps.withFile, withFile: ps.withFile,
notify: ps.notify, notify: ps.notify,

View File

@ -188,6 +188,7 @@ describe('Account Move', () => {
excludeKeywords: [], excludeKeywords: [],
users: [], users: [],
caseSensitive: false, caseSensitive: false,
localOnly: false,
withReplies: false, withReplies: false,
withFile: false, withFile: false,
notify: false, notify: false,
@ -431,6 +432,7 @@ describe('Account Move', () => {
excludeKeywords: [], excludeKeywords: [],
users: [eve.id], users: [eve.id],
caseSensitive: false, caseSensitive: false,
localOnly: false,
withReplies: false, withReplies: false,
withFile: false, withFile: false,
notify: false, notify: false,

View File

@ -14,7 +14,7 @@ import XAntenna from './editor.vue';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { definePageMetadata } from '@/scripts/page-metadata.js'; import { definePageMetadata } from '@/scripts/page-metadata.js';
import { useRouter } from '@/router.js'; import { useRouter } from '@/router.js';
import { antennasCache } from '@/cache'; import { antennasCache } from '@/cache.js';
const router = useRouter(); const router = useRouter();
@ -27,6 +27,7 @@ let draft = $ref({
excludeKeywords: [], excludeKeywords: [],
withReplies: false, withReplies: false,
caseSensitive: false, caseSensitive: false,
localOnly: false,
withFile: false, withFile: false,
notify: false, notify: false,
}); });

View File

@ -35,6 +35,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #label>{{ i18n.ts.antennaExcludeKeywords }}</template> <template #label>{{ i18n.ts.antennaExcludeKeywords }}</template>
<template #caption>{{ i18n.ts.antennaKeywordsDescription }}</template> <template #caption>{{ i18n.ts.antennaKeywordsDescription }}</template>
</MkTextarea> </MkTextarea>
<MkSwitch v-model="localOnly">{{ i18n.ts.localOnly }}</MkSwitch>
<MkSwitch v-model="caseSensitive">{{ i18n.ts.caseSensitive }}</MkSwitch> <MkSwitch v-model="caseSensitive">{{ i18n.ts.caseSensitive }}</MkSwitch>
<MkSwitch v-model="withFile">{{ i18n.ts.withFileAntenna }}</MkSwitch> <MkSwitch v-model="withFile">{{ i18n.ts.withFileAntenna }}</MkSwitch>
<MkSwitch v-model="notify">{{ i18n.ts.notifyAntenna }}</MkSwitch> <MkSwitch v-model="notify">{{ i18n.ts.notifyAntenna }}</MkSwitch>
@ -75,6 +76,7 @@ let users: string = $ref(props.antenna.users.join('\n'));
let keywords: string = $ref(props.antenna.keywords.map(x => x.join(' ')).join('\n')); let keywords: string = $ref(props.antenna.keywords.map(x => x.join(' ')).join('\n'));
let excludeKeywords: string = $ref(props.antenna.excludeKeywords.map(x => x.join(' ')).join('\n')); let excludeKeywords: string = $ref(props.antenna.excludeKeywords.map(x => x.join(' ')).join('\n'));
let caseSensitive: boolean = $ref(props.antenna.caseSensitive); let caseSensitive: boolean = $ref(props.antenna.caseSensitive);
let localOnly: boolean = $ref(props.antenna.localOnly);
let withReplies: boolean = $ref(props.antenna.withReplies); let withReplies: boolean = $ref(props.antenna.withReplies);
let withFile: boolean = $ref(props.antenna.withFile); let withFile: boolean = $ref(props.antenna.withFile);
let notify: boolean = $ref(props.antenna.notify); let notify: boolean = $ref(props.antenna.notify);
@ -95,6 +97,7 @@ async function saveAntenna() {
withFile, withFile,
notify, notify,
caseSensitive, caseSensitive,
localOnly,
users: users.trim().split('\n').map(x => x.trim()), users: users.trim().split('\n').map(x => x.trim()),
keywords: keywords.trim().split('\n').map(x => x.trim().split(' ')), keywords: keywords.trim().split('\n').map(x => x.trim().split(' ')),
excludeKeywords: excludeKeywords.trim().split('\n').map(x => x.trim().split(' ')), excludeKeywords: excludeKeywords.trim().split('\n').map(x => x.trim().split(' ')),

View File

@ -61,6 +61,7 @@ type Antenna = {
userGroupId: ID | null; userGroupId: ID | null;
users: string[]; users: string[];
caseSensitive: boolean; caseSensitive: boolean;
localOnly: boolean;
notify: boolean; notify: boolean;
withReplies: boolean; withReplies: boolean;
withFile: boolean; withFile: boolean;
@ -2984,7 +2985,7 @@ type UserSorting = '+follower' | '-follower' | '+createdAt' | '-createdAt' | '+u
// src/api.types.ts:18:25 - (ae-forgotten-export) The symbol "NoParams" needs to be exported by the entry point index.d.ts // src/api.types.ts:18:25 - (ae-forgotten-export) The symbol "NoParams" needs to be exported by the entry point index.d.ts
// src/api.types.ts:630:18 - (ae-forgotten-export) The symbol "ShowUserReq" needs to be exported by the entry point index.d.ts // src/api.types.ts:630:18 - (ae-forgotten-export) The symbol "ShowUserReq" needs to be exported by the entry point index.d.ts
// src/entities.ts:107:2 - (ae-forgotten-export) The symbol "notificationTypes_2" needs to be exported by the entry point index.d.ts // src/entities.ts:107:2 - (ae-forgotten-export) The symbol "notificationTypes_2" needs to be exported by the entry point index.d.ts
// src/entities.ts:600:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts // src/entities.ts:601:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts
// src/streaming.types.ts:33:4 - (ae-forgotten-export) The symbol "FIXME" needs to be exported by the entry point index.d.ts // src/streaming.types.ts:33:4 - (ae-forgotten-export) The symbol "FIXME" needs to be exported by the entry point index.d.ts
// (No @packageDocumentation comment for this package) // (No @packageDocumentation comment for this package)

View File

@ -470,6 +470,7 @@ export type Antenna = {
userGroupId: ID | null; // TODO userGroupId: ID | null; // TODO
users: string[]; // TODO users: string[]; // TODO
caseSensitive: boolean; caseSensitive: boolean;
localOnly: boolean;
notify: boolean; notify: boolean;
withReplies: boolean; withReplies: boolean;
withFile: boolean; withFile: boolean;