enhance(backend): センシティブワードの設定がハッシュタグトレンドにも適用されるように
This commit is contained in:
parent
316ffcea54
commit
6fce36374d
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -12,6 +12,17 @@
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
## 2023.12.1
|
||||||
|
|
||||||
|
### General
|
||||||
|
-
|
||||||
|
|
||||||
|
### Client
|
||||||
|
-
|
||||||
|
|
||||||
|
### Server
|
||||||
|
- Enhance: センシティブワードの設定がハッシュタグトレンドにも適用されるようになりました
|
||||||
|
|
||||||
## 2023.12.0
|
## 2023.12.0
|
||||||
|
|
||||||
### Note
|
### Note
|
||||||
|
|
|
@ -15,6 +15,7 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { FeaturedService } from '@/core/FeaturedService.js';
|
import { FeaturedService } from '@/core/FeaturedService.js';
|
||||||
import { MetaService } from '@/core/MetaService.js';
|
import { MetaService } from '@/core/MetaService.js';
|
||||||
|
import { UtilityService } from '@/core/UtilityService.js';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class HashtagService {
|
export class HashtagService {
|
||||||
|
@ -29,6 +30,7 @@ export class HashtagService {
|
||||||
private featuredService: FeaturedService,
|
private featuredService: FeaturedService,
|
||||||
private idService: IdService,
|
private idService: IdService,
|
||||||
private metaService: MetaService,
|
private metaService: MetaService,
|
||||||
|
private utilityService: UtilityService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,6 +163,7 @@ export class HashtagService {
|
||||||
const instance = await this.metaService.fetch();
|
const instance = await this.metaService.fetch();
|
||||||
const hiddenTags = instance.hiddenTags.map(t => normalizeForSearch(t));
|
const hiddenTags = instance.hiddenTags.map(t => normalizeForSearch(t));
|
||||||
if (hiddenTags.includes(hashtag)) return;
|
if (hiddenTags.includes(hashtag)) return;
|
||||||
|
if (this.utilityService.isSensitiveWordIncluded(hashtag, instance.sensitiveWords)) return;
|
||||||
|
|
||||||
// YYYYMMDDHHmm (10分間隔)
|
// YYYYMMDDHHmm (10分間隔)
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|
|
@ -253,7 +253,7 @@ export class NoteCreateService implements OnApplicationShutdown {
|
||||||
|
|
||||||
if (data.visibility === 'public' && data.channel == null) {
|
if (data.visibility === 'public' && data.channel == null) {
|
||||||
const sensitiveWords = meta.sensitiveWords;
|
const sensitiveWords = meta.sensitiveWords;
|
||||||
if (this.isSensitive(data, sensitiveWords)) {
|
if (this.utilityService.isSensitiveWordIncluded(data.cw ?? data.text ?? '', sensitiveWords)) {
|
||||||
data.visibility = 'home';
|
data.visibility = 'home';
|
||||||
} else if ((await this.roleService.getUserPolicies(user.id)).canPublicNote === false) {
|
} else if ((await this.roleService.getUserPolicies(user.id)).canPublicNote === false) {
|
||||||
data.visibility = 'home';
|
data.visibility = 'home';
|
||||||
|
@ -704,31 +704,6 @@ export class NoteCreateService implements OnApplicationShutdown {
|
||||||
this.index(note);
|
this.index(note);
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
|
||||||
private isSensitive(note: Option, sensitiveWord: string[]): boolean {
|
|
||||||
if (sensitiveWord.length > 0) {
|
|
||||||
const text = note.cw ?? note.text ?? '';
|
|
||||||
if (text === '') return false;
|
|
||||||
const matched = sensitiveWord.some(filter => {
|
|
||||||
// represents RegExp
|
|
||||||
const regexp = filter.match(/^\/(.+)\/(.*)$/);
|
|
||||||
// This should never happen due to input sanitisation.
|
|
||||||
if (!regexp) {
|
|
||||||
const words = filter.split(' ');
|
|
||||||
return words.every(keyword => text.includes(keyword));
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return new RE2(regexp[1], regexp[2]).test(text);
|
|
||||||
} catch (err) {
|
|
||||||
// This should never happen due to input sanitisation.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (matched) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
private isQuote(note: Option): note is Option & { renote: MiNote } {
|
private isQuote(note: Option): note is Option & { renote: MiNote } {
|
||||||
// sync with misc/is-quote.ts
|
// sync with misc/is-quote.ts
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
import { URL } from 'node:url';
|
import { URL } from 'node:url';
|
||||||
import { toASCII } from 'punycode';
|
import { toASCII } from 'punycode';
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import RE2 from 're2';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import type { Config } from '@/config.js';
|
import type { Config } from '@/config.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
@ -41,6 +42,33 @@ export class UtilityService {
|
||||||
return silencedHosts.some(x => `.${host.toLowerCase()}`.endsWith(`.${x}`));
|
return silencedHosts.some(x => `.${host.toLowerCase()}`.endsWith(`.${x}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@bindThis
|
||||||
|
public isSensitiveWordIncluded(text: string, sensitiveWords: string[]): boolean {
|
||||||
|
if (sensitiveWords.length === 0) return false;
|
||||||
|
if (text === '') return false;
|
||||||
|
|
||||||
|
const regexpregexp = /^\/(.+)\/(.*)$/;
|
||||||
|
|
||||||
|
const matched = sensitiveWords.some(filter => {
|
||||||
|
// represents RegExp
|
||||||
|
const regexp = filter.match(regexpregexp);
|
||||||
|
// This should never happen due to input sanitisation.
|
||||||
|
if (!regexp) {
|
||||||
|
const words = filter.split(' ');
|
||||||
|
return words.every(keyword => text.includes(keyword));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// TODO: RE2インスタンスをキャッシュ
|
||||||
|
return new RE2(regexp[1], regexp[2]).test(text);
|
||||||
|
} catch (err) {
|
||||||
|
// This should never happen due to input sanitisation.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return matched;
|
||||||
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public extractDbHost(uri: string): string {
|
public extractDbHost(uri: string): string {
|
||||||
const url = new URL(uri);
|
const url = new URL(uri);
|
||||||
|
|
Loading…
Reference in a new issue