mirror of
https://git.joinsharkey.org/Sharkey/Sharkey.git
synced 2024-11-05 08:53:08 +02:00
enhance(backend): センシティブワードの設定がハッシュタグトレンドにも適用されるように
This commit is contained in:
parent
316ffcea54
commit
6fce36374d
4 changed files with 43 additions and 26 deletions
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -12,6 +12,17 @@
|
|||
|
||||
-->
|
||||
|
||||
## 2023.12.1
|
||||
|
||||
### General
|
||||
-
|
||||
|
||||
### Client
|
||||
-
|
||||
|
||||
### Server
|
||||
- Enhance: センシティブワードの設定がハッシュタグトレンドにも適用されるようになりました
|
||||
|
||||
## 2023.12.0
|
||||
|
||||
### Note
|
||||
|
|
|
@ -15,6 +15,7 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
|||
import { bindThis } from '@/decorators.js';
|
||||
import { FeaturedService } from '@/core/FeaturedService.js';
|
||||
import { MetaService } from '@/core/MetaService.js';
|
||||
import { UtilityService } from '@/core/UtilityService.js';
|
||||
|
||||
@Injectable()
|
||||
export class HashtagService {
|
||||
|
@ -29,6 +30,7 @@ export class HashtagService {
|
|||
private featuredService: FeaturedService,
|
||||
private idService: IdService,
|
||||
private metaService: MetaService,
|
||||
private utilityService: UtilityService,
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -161,6 +163,7 @@ export class HashtagService {
|
|||
const instance = await this.metaService.fetch();
|
||||
const hiddenTags = instance.hiddenTags.map(t => normalizeForSearch(t));
|
||||
if (hiddenTags.includes(hashtag)) return;
|
||||
if (this.utilityService.isSensitiveWordIncluded(hashtag, instance.sensitiveWords)) return;
|
||||
|
||||
// YYYYMMDDHHmm (10分間隔)
|
||||
const now = new Date();
|
||||
|
|
|
@ -253,7 +253,7 @@ export class NoteCreateService implements OnApplicationShutdown {
|
|||
|
||||
if (data.visibility === 'public' && data.channel == null) {
|
||||
const sensitiveWords = meta.sensitiveWords;
|
||||
if (this.isSensitive(data, sensitiveWords)) {
|
||||
if (this.utilityService.isSensitiveWordIncluded(data.cw ?? data.text ?? '', sensitiveWords)) {
|
||||
data.visibility = 'home';
|
||||
} else if ((await this.roleService.getUserPolicies(user.id)).canPublicNote === false) {
|
||||
data.visibility = 'home';
|
||||
|
@ -704,31 +704,6 @@ export class NoteCreateService implements OnApplicationShutdown {
|
|||
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
|
||||
private isQuote(note: Option): note is Option & { renote: MiNote } {
|
||||
// sync with misc/is-quote.ts
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
import { URL } from 'node:url';
|
||||
import { toASCII } from 'punycode';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import RE2 from 're2';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
@ -41,6 +42,33 @@ export class UtilityService {
|
|||
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
|
||||
public extractDbHost(uri: string): string {
|
||||
const url = new URL(uri);
|
||||
|
|
Loading…
Reference in a new issue