mirror of
https://activitypub.software/TransFem-org/Sharkey
synced 2025-01-03 06:01:18 +00:00
remove body of NoteCreateService.import
`create(user,data,true)` does exactly the same thing now
This commit is contained in:
parent
b5e0342136
commit
7ff7464896
1 changed files with 2 additions and 273 deletions
|
@ -419,178 +419,8 @@ export class NoteCreateService implements OnApplicationShutdown {
|
||||||
host: MiUser['host'];
|
host: MiUser['host'];
|
||||||
isBot: MiUser['isBot'];
|
isBot: MiUser['isBot'];
|
||||||
noindex: MiUser['noindex'];
|
noindex: MiUser['noindex'];
|
||||||
}, data: Option, silent = false): Promise<MiNote> {
|
}, data: Option): Promise<MiNote> {
|
||||||
// チャンネル外にリプライしたら対象のスコープに合わせる
|
return this.create(user, data, true);
|
||||||
// (クライアントサイドでやっても良い処理だと思うけどとりあえずサーバーサイドで)
|
|
||||||
if (data.reply && data.channel && data.reply.channelId !== data.channel.id) {
|
|
||||||
if (data.reply.channelId) {
|
|
||||||
data.channel = await this.channelsRepository.findOneBy({ id: data.reply.channelId });
|
|
||||||
} else {
|
|
||||||
data.channel = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// チャンネル内にリプライしたら対象のスコープに合わせる
|
|
||||||
// (クライアントサイドでやっても良い処理だと思うけどとりあえずサーバーサイドで)
|
|
||||||
if (data.reply && (data.channel == null) && data.reply.channelId) {
|
|
||||||
data.channel = await this.channelsRepository.findOneBy({ id: data.reply.channelId });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.createdAt == null) data.createdAt = new Date();
|
|
||||||
if (data.visibility == null) data.visibility = 'public';
|
|
||||||
if (data.localOnly == null) data.localOnly = false;
|
|
||||||
if (data.channel != null) data.visibility = 'public';
|
|
||||||
if (data.channel != null) data.visibleUsers = [];
|
|
||||||
if (data.channel != null) data.localOnly = true;
|
|
||||||
|
|
||||||
const meta = await this.metaService.fetch();
|
|
||||||
|
|
||||||
if (data.visibility === 'public' && data.channel == null) {
|
|
||||||
const sensitiveWords = meta.sensitiveWords;
|
|
||||||
if (this.utilityService.isKeyWordIncluded(data.cw ?? data.text ?? '', sensitiveWords)) {
|
|
||||||
data.visibility = 'home';
|
|
||||||
} else if ((await this.roleService.getUserPolicies(user.id)).canPublicNote === false) {
|
|
||||||
data.visibility = 'home';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const hasProhibitedWords = await this.checkProhibitedWordsContain({
|
|
||||||
cw: data.cw,
|
|
||||||
text: data.text,
|
|
||||||
pollChoices: data.poll?.choices,
|
|
||||||
}, meta.prohibitedWords);
|
|
||||||
|
|
||||||
if (hasProhibitedWords) {
|
|
||||||
throw new IdentifiableError('689ee33f-f97c-479a-ac49-1b9f8140af99', 'Note contains prohibited words');
|
|
||||||
}
|
|
||||||
|
|
||||||
const inSilencedInstance = this.utilityService.isSilencedHost(meta.silencedHosts, user.host);
|
|
||||||
|
|
||||||
if (data.visibility === 'public' && inSilencedInstance && user.host !== null) {
|
|
||||||
data.visibility = 'home';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.renote) {
|
|
||||||
switch (data.renote.visibility) {
|
|
||||||
case 'public':
|
|
||||||
// public noteは無条件にrenote可能
|
|
||||||
break;
|
|
||||||
case 'home':
|
|
||||||
// home noteはhome以下にrenote可能
|
|
||||||
if (data.visibility === 'public') {
|
|
||||||
data.visibility = 'home';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'followers':
|
|
||||||
// 他人のfollowers noteはreject
|
|
||||||
if (data.renote.userId !== user.id) {
|
|
||||||
throw new Error('Renote target is not public or home');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Renote対象がfollowersならfollowersにする
|
|
||||||
data.visibility = 'followers';
|
|
||||||
break;
|
|
||||||
case 'specified':
|
|
||||||
// specified / direct noteはreject
|
|
||||||
throw new Error('Renote target is not public or home');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check blocking
|
|
||||||
if (this.isRenote(data) && !this.isQuote(data)) {
|
|
||||||
if (data.renote.userHost === null) {
|
|
||||||
if (data.renote.userId !== user.id) {
|
|
||||||
const blocked = await this.userBlockingService.checkBlocked(data.renote.userId, user.id);
|
|
||||||
if (blocked) {
|
|
||||||
throw new Error('blocked');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 返信対象がpublicではないならhomeにする
|
|
||||||
if (data.reply && data.reply.visibility !== 'public' && data.visibility === 'public') {
|
|
||||||
data.visibility = 'home';
|
|
||||||
}
|
|
||||||
|
|
||||||
// ローカルのみをRenoteしたらローカルのみにする
|
|
||||||
if (data.renote && data.renote.localOnly && data.channel == null) {
|
|
||||||
data.localOnly = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ローカルのみにリプライしたらローカルのみにする
|
|
||||||
if (data.reply && data.reply.localOnly && data.channel == null) {
|
|
||||||
data.localOnly = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.text) {
|
|
||||||
if (data.text.length > DB_MAX_NOTE_TEXT_LENGTH) {
|
|
||||||
data.text = data.text.slice(0, DB_MAX_NOTE_TEXT_LENGTH);
|
|
||||||
}
|
|
||||||
data.text = data.text.trim();
|
|
||||||
if (data.text === '') {
|
|
||||||
data.text = null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
data.text = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let tags = data.apHashtags;
|
|
||||||
let emojis = data.apEmojis;
|
|
||||||
let mentionedUsers = data.apMentions;
|
|
||||||
|
|
||||||
// Parse MFM if needed
|
|
||||||
if (!tags || !emojis || !mentionedUsers) {
|
|
||||||
const tokens = (data.text ? mfm.parse(data.text)! : []);
|
|
||||||
const cwTokens = data.cw ? mfm.parse(data.cw)! : [];
|
|
||||||
const choiceTokens = data.poll && data.poll.choices
|
|
||||||
? concat(data.poll.choices.map(choice => mfm.parse(choice)!))
|
|
||||||
: [];
|
|
||||||
|
|
||||||
const combinedTokens = tokens.concat(cwTokens).concat(choiceTokens);
|
|
||||||
|
|
||||||
tags = data.apHashtags ?? extractHashtags(combinedTokens);
|
|
||||||
|
|
||||||
emojis = data.apEmojis ?? extractCustomEmojisFromMfm(combinedTokens);
|
|
||||||
|
|
||||||
mentionedUsers = data.apMentions ?? await this.extractMentionedUsers(user, combinedTokens);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the host is media-silenced, custom emojis are not allowed
|
|
||||||
if (this.utilityService.isMediaSilencedHost(meta.mediaSilencedHosts, user.host)) emojis = [];
|
|
||||||
|
|
||||||
tags = tags.filter(tag => Array.from(tag).length <= 128).splice(0, 32);
|
|
||||||
|
|
||||||
if (data.reply && (user.id !== data.reply.userId) && !mentionedUsers.some(u => u.id === data.reply!.userId)) {
|
|
||||||
mentionedUsers.push(await this.usersRepository.findOneByOrFail({ id: data.reply!.userId }));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.visibility === 'specified') {
|
|
||||||
if (data.visibleUsers == null) throw new Error('invalid param');
|
|
||||||
|
|
||||||
for (const u of data.visibleUsers) {
|
|
||||||
if (!mentionedUsers.some(x => x.id === u.id)) {
|
|
||||||
mentionedUsers.push(u);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.reply && !data.visibleUsers.some(x => x.id === data.reply!.userId)) {
|
|
||||||
data.visibleUsers.push(await this.usersRepository.findOneByOrFail({ id: data.reply!.userId }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mentionedUsers.length > 0 && mentionedUsers.length > (await this.roleService.getUserPolicies(user.id)).mentionLimit) {
|
|
||||||
throw new IdentifiableError('9f466dab-c856-48cd-9e65-ff90ff750580', 'Note contains too many mentions');
|
|
||||||
}
|
|
||||||
|
|
||||||
const note = await this.insertNote(user, data, tags, emojis, mentionedUsers);
|
|
||||||
|
|
||||||
setImmediate('post created', { signal: this.#shutdownController.signal }).then(
|
|
||||||
() => this.postNoteImported(note, user, data, silent, tags!, mentionedUsers!),
|
|
||||||
() => { /* aborted, ignore this */ },
|
|
||||||
);
|
|
||||||
|
|
||||||
return note;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
|
@ -970,107 +800,6 @@ export class NoteCreateService implements OnApplicationShutdown {
|
||||||
if (!user.noindex) this.index(note);
|
if (!user.noindex) this.index(note);
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
|
||||||
private async postNoteImported(note: MiNote, user: {
|
|
||||||
id: MiUser['id'];
|
|
||||||
username: MiUser['username'];
|
|
||||||
host: MiUser['host'];
|
|
||||||
isBot: MiUser['isBot'];
|
|
||||||
noindex: MiUser['noindex'];
|
|
||||||
}, data: Option, silent: boolean, tags: string[], mentionedUsers: MinimumUser[]) {
|
|
||||||
const meta = await this.metaService.fetch();
|
|
||||||
|
|
||||||
this.notesChart.update(note, true);
|
|
||||||
if (note.visibility !== 'specified' && (meta.enableChartsForRemoteUser || (user.host == null))) {
|
|
||||||
this.perUserNotesChart.update(user, note, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register host
|
|
||||||
if (this.userEntityService.isRemoteUser(user)) {
|
|
||||||
this.federatedInstanceService.fetch(user.host).then(async i => {
|
|
||||||
if (note.renote && note.text) {
|
|
||||||
this.instancesRepository.increment({ id: i.id }, 'notesCount', 1);
|
|
||||||
} else if (!note.renote) {
|
|
||||||
this.instancesRepository.increment({ id: i.id }, 'notesCount', 1);
|
|
||||||
}
|
|
||||||
if ((await this.metaService.fetch()).enableChartsForFederatedInstances) {
|
|
||||||
this.instanceChart.updateNote(i.host, note, true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.renote && data.text) {
|
|
||||||
// Increment notes count (user)
|
|
||||||
this.incNotesCountOfUser(user);
|
|
||||||
} else if (!data.renote) {
|
|
||||||
// Increment notes count (user)
|
|
||||||
this.incNotesCountOfUser(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.pushToTl(note, user);
|
|
||||||
|
|
||||||
this.antennaService.addNoteToAntennas(note, user);
|
|
||||||
|
|
||||||
if (data.reply) {
|
|
||||||
this.saveReply(data.reply, note);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.reply == null) {
|
|
||||||
// TODO: キャッシュ
|
|
||||||
this.followingsRepository.findBy({
|
|
||||||
followeeId: user.id,
|
|
||||||
notify: 'normal',
|
|
||||||
}).then(followings => {
|
|
||||||
if (note.visibility !== 'specified') {
|
|
||||||
for (const following of followings) {
|
|
||||||
// TODO: ワードミュート考慮
|
|
||||||
this.notificationService.createNotification(following.followerId, 'note', {
|
|
||||||
noteId: note.id,
|
|
||||||
}, user.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.renote && data.text == null && data.renote.userId !== user.id && !user.isBot) {
|
|
||||||
this.incRenoteCount(data.renote);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.poll && data.poll.expiresAt) {
|
|
||||||
const delay = data.poll.expiresAt.getTime() - Date.now();
|
|
||||||
this.queueService.endedPollNotificationQueue.add(note.id, {
|
|
||||||
noteId: note.id,
|
|
||||||
}, {
|
|
||||||
delay,
|
|
||||||
removeOnComplete: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pack the note
|
|
||||||
const noteObj = await this.noteEntityService.pack(note, null, { skipHide: true, withReactionAndUserPairCache: true });
|
|
||||||
|
|
||||||
if (data.channel) {
|
|
||||||
this.channelsRepository.increment({ id: data.channel.id }, 'notesCount', 1);
|
|
||||||
this.channelsRepository.update(data.channel.id, {
|
|
||||||
lastNotedAt: new Date(),
|
|
||||||
});
|
|
||||||
|
|
||||||
this.notesRepository.countBy({
|
|
||||||
userId: user.id,
|
|
||||||
channelId: data.channel.id,
|
|
||||||
}).then(count => {
|
|
||||||
// この処理が行われるのはノート作成後なので、ノートが一つしかなかったら最初の投稿だと判断できる
|
|
||||||
// TODO: とはいえノートを削除して何回も投稿すればその分だけインクリメントされる雑さもあるのでどうにかしたい
|
|
||||||
if (count === 1) {
|
|
||||||
this.channelsRepository.increment({ id: data.channel!.id }, 'usersCount', 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register to search database
|
|
||||||
if (!user.noindex) this.index(note);
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
private isRenote(note: Option): note is Option & { renote: MiNote } {
|
private isRenote(note: Option): note is Option & { renote: MiNote } {
|
||||||
return note.renote != null;
|
return note.renote != null;
|
||||||
|
|
Loading…
Reference in a new issue