Merge remote-tracking branch 'misskey-original/develop' into develop
# Conflicts: # packages/frontend/src/components/MkEmojiEditDialog.vue # packages/frontend/src/components/MkMenu.vue # packages/frontend/src/pages/about.vue # packages/frontend/src/pages/admin/index.vue # packages/frontend/src/pages/custom-emojis-manager.vue # packages/frontend/src/pages/settings/mute-block.vue # packages/frontend/src/pages/settings/theme.vue # packages/frontend/src/ui/_common_/navbar-for-mobile.vue
This commit is contained in:
commit
8d058b0529
208 changed files with 1583 additions and 904 deletions
|
|
@ -7,7 +7,6 @@ import { URLSearchParams } from 'node:url';
|
|||
import * as nodemailer from 'nodemailer';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { validate as validateEmail } from 'deep-email-validator';
|
||||
import { SubOutputFormat } from 'deep-email-validator/dist/output/output.js';
|
||||
import { MetaService } from '@/core/MetaService.js';
|
||||
import { UtilityService } from '@/core/UtilityService.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
|
|
@ -166,7 +165,10 @@ export class EmailService {
|
|||
email: emailAddress,
|
||||
});
|
||||
|
||||
let validated;
|
||||
let validated: {
|
||||
valid: boolean,
|
||||
reason?: string | null,
|
||||
};
|
||||
|
||||
if (meta.enableActiveEmailValidation) {
|
||||
if (meta.enableVerifymailApi && meta.verifymailAuthKey != null) {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -222,7 +222,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';
|
||||
|
|
@ -672,31 +672,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
|
||||
|
|
@ -880,6 +855,7 @@ export class NoteCreateService implements OnApplicationShutdown {
|
|||
// ダイレクトのとき、そのリストが対象外のユーザーの場合
|
||||
if (
|
||||
note.visibility === 'specified' &&
|
||||
note.userId !== userListMembership.userListUserId &&
|
||||
!note.visibleUserIds.some(v => v === userListMembership.userListUserId)
|
||||
) continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ export class ReactionService {
|
|||
reaction = reacterHost ? `:${name}@${reacterHost}:` : `:${name}:`;
|
||||
|
||||
// センシティブ
|
||||
if ((note.reactionAcceptance === 'nonSensitiveOnly') && emoji.isSensitive) {
|
||||
if ((note.reactionAcceptance === 'nonSensitiveOnly' || note.reactionAcceptance === 'nonSensitiveOnlyForLocalLikeOnlyForRemote') && emoji.isSensitive) {
|
||||
reaction = FALLBACK;
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -381,6 +381,10 @@ export const meta = {
|
|||
type: 'string',
|
||||
optional: false, nullable: true,
|
||||
},
|
||||
shortName: {
|
||||
type: 'string',
|
||||
optional: false, nullable: true,
|
||||
},
|
||||
objectStorageS3ForcePathStyle: {
|
||||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
|
|
|
|||
|
|
@ -29,37 +29,10 @@ export const meta = {
|
|||
optional: false,
|
||||
nullable: false,
|
||||
items: {
|
||||
properties: {
|
||||
id: { type: 'string' },
|
||||
firstRetrievedAt: { type: 'string' },
|
||||
host: { type: 'string' },
|
||||
usersCount: { type: 'number' },
|
||||
notesCount: { type: 'number' },
|
||||
followingCount: { type: 'number' },
|
||||
followersCount: { type: 'number' },
|
||||
isNotResponding: { type: 'boolean' },
|
||||
isSuspended: { type: 'boolean' },
|
||||
isBlocked: { type: 'boolean' },
|
||||
softwareName: { type: 'string' },
|
||||
softwareVersion: { type: 'string' },
|
||||
openRegistrations: { type: 'boolean' },
|
||||
name: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
maintainerName: { type: 'string' },
|
||||
maintainerEmail: { type: 'string' },
|
||||
isSilenced: { type: 'boolean' },
|
||||
iconUrl: { type: 'string' },
|
||||
faviconUrl: { type: 'string' },
|
||||
themeColor: { type: 'string' },
|
||||
infoUpdatedAt: {
|
||||
type: 'string',
|
||||
nullable: true,
|
||||
},
|
||||
latestRequestReceivedAt: {
|
||||
type: 'string',
|
||||
nullable: true,
|
||||
},
|
||||
}
|
||||
type: 'object',
|
||||
optional: false,
|
||||
nullable: false,
|
||||
ref: 'FederationInstance',
|
||||
},
|
||||
},
|
||||
otherFollowersCount: { type: 'number' },
|
||||
|
|
@ -68,42 +41,15 @@ export const meta = {
|
|||
optional: false,
|
||||
nullable: false,
|
||||
items: {
|
||||
properties: {
|
||||
id: { type: 'string' },
|
||||
firstRetrievedAt: { type: 'string' },
|
||||
host: { type: 'string' },
|
||||
usersCount: { type: 'number' },
|
||||
notesCount: { type: 'number' },
|
||||
followingCount: { type: 'number' },
|
||||
followersCount: { type: 'number' },
|
||||
isNotResponding: { type: 'boolean' },
|
||||
isSuspended: { type: 'boolean' },
|
||||
isBlocked: { type: 'boolean' },
|
||||
softwareName: { type: 'string' },
|
||||
softwareVersion: { type: 'string' },
|
||||
openRegistrations: { type: 'boolean' },
|
||||
name: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
maintainerName: { type: 'string' },
|
||||
maintainerEmail: { type: 'string' },
|
||||
isSilenced: { type: 'boolean' },
|
||||
iconUrl: { type: 'string' },
|
||||
faviconUrl: { type: 'string' },
|
||||
themeColor: { type: 'string' },
|
||||
infoUpdatedAt: {
|
||||
type: 'string',
|
||||
nullable: true,
|
||||
},
|
||||
latestRequestReceivedAt: {
|
||||
type: 'string',
|
||||
nullable: true,
|
||||
},
|
||||
}
|
||||
type: 'object',
|
||||
optional: false,
|
||||
nullable: false,
|
||||
ref: 'FederationInstance',
|
||||
},
|
||||
},
|
||||
otherFollowingCount: { type: 'number' },
|
||||
},
|
||||
}
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
|
|
|||
|
|
@ -164,20 +164,34 @@ export const meta = {
|
|||
type: 'object',
|
||||
optional: false, nullable: false,
|
||||
properties: {
|
||||
place: {
|
||||
id: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'id',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
url: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'url',
|
||||
},
|
||||
place: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
ratio: {
|
||||
type: 'number',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
imageUrl: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'url',
|
||||
},
|
||||
dayOfWeek: {
|
||||
type: 'integer',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@ export const meta = {
|
|||
res: {
|
||||
type: 'object',
|
||||
optional: false, nullable: false,
|
||||
properties: {
|
||||
sourceLang: { type: 'string' },
|
||||
text: { type: 'string' },
|
||||
},
|
||||
},
|
||||
|
||||
errors: {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue