mirror of
https://git.joinsharkey.org/Sharkey/Sharkey.git
synced 2024-11-30 04:13:09 +02:00
merge: upstream
This commit is contained in:
commit
ca428977a5
11 changed files with 66 additions and 116 deletions
|
@ -21,7 +21,7 @@
|
||||||
- Enhance: TLの返信表示オプションを記憶するように
|
- Enhance: TLの返信表示オプションを記憶するように
|
||||||
|
|
||||||
### Server
|
### Server
|
||||||
-
|
- Enhance: ストリーミングAPIのパフォーマンスを向上
|
||||||
|
|
||||||
## 2023.10.1
|
## 2023.10.1
|
||||||
### General
|
### General
|
||||||
|
@ -38,6 +38,7 @@
|
||||||
### NOTE
|
### NOTE
|
||||||
- 2023.9.2で導入されたノート編集機能はクオリティの高い実装が困難であることが判明したため撤回されました
|
- 2023.9.2で導入されたノート編集機能はクオリティの高い実装が困難であることが判明したため撤回されました
|
||||||
- アップデートを行うと、タイムラインが一時的にリセットされます
|
- アップデートを行うと、タイムラインが一時的にリセットされます
|
||||||
|
- アンテナ内のノートも含む
|
||||||
- ソフトミュート設定はクライアントではなくサーバー側に保存されるようになったため、アップデートを行うとソフトミュートの設定がリセットされます
|
- ソフトミュート設定はクライアントではなくサーバー側に保存されるようになったため、アップデートを行うとソフトミュートの設定がリセットされます
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
|
|
|
@ -578,7 +578,7 @@ export class NoteCreateService implements OnApplicationShutdown {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pack the note
|
// Pack the note
|
||||||
const noteObj = await this.noteEntityService.pack(note);
|
const noteObj = await this.noteEntityService.pack(note, null, { skipHide: true });
|
||||||
|
|
||||||
this.globalEventService.publishNotesStream(noteObj);
|
this.globalEventService.publishNotesStream(noteObj);
|
||||||
|
|
||||||
|
|
|
@ -542,7 +542,7 @@ export class NoteEditService implements OnApplicationShutdown {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pack the note
|
// Pack the note
|
||||||
const noteObj = await this.noteEntityService.pack(note);
|
const noteObj = await this.noteEntityService.pack(note, null, { skipHide: true });
|
||||||
if (data.poll != null) {
|
if (data.poll != null) {
|
||||||
this.globalEventService.publishNoteStream(note.id, 'updated', {
|
this.globalEventService.publishNoteStream(note.id, 'updated', {
|
||||||
cw: note.cw,
|
cw: note.cw,
|
||||||
|
|
|
@ -16,6 +16,7 @@ import type { UsersRepository, NotesRepository, FollowingsRepository, PollsRepos
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { isNotNull } from '@/misc/is-not-null.js';
|
import { isNotNull } from '@/misc/is-not-null.js';
|
||||||
import { DebounceLoader } from '@/misc/loader.js';
|
import { DebounceLoader } from '@/misc/loader.js';
|
||||||
|
import { IdService } from '@/core/IdService.js';
|
||||||
import type { OnModuleInit } from '@nestjs/common';
|
import type { OnModuleInit } from '@nestjs/common';
|
||||||
import type { CustomEmojiService } from '../CustomEmojiService.js';
|
import type { CustomEmojiService } from '../CustomEmojiService.js';
|
||||||
import type { ReactionService } from '../ReactionService.js';
|
import type { ReactionService } from '../ReactionService.js';
|
||||||
|
@ -29,6 +30,7 @@ export class NoteEntityService implements OnModuleInit {
|
||||||
private driveFileEntityService: DriveFileEntityService;
|
private driveFileEntityService: DriveFileEntityService;
|
||||||
private customEmojiService: CustomEmojiService;
|
private customEmojiService: CustomEmojiService;
|
||||||
private reactionService: ReactionService;
|
private reactionService: ReactionService;
|
||||||
|
private idService: IdService;
|
||||||
private noteLoader = new DebounceLoader(this.findNoteOrFail);
|
private noteLoader = new DebounceLoader(this.findNoteOrFail);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -70,6 +72,7 @@ export class NoteEntityService implements OnModuleInit {
|
||||||
this.driveFileEntityService = this.moduleRef.get('DriveFileEntityService');
|
this.driveFileEntityService = this.moduleRef.get('DriveFileEntityService');
|
||||||
this.customEmojiService = this.moduleRef.get('CustomEmojiService');
|
this.customEmojiService = this.moduleRef.get('CustomEmojiService');
|
||||||
this.reactionService = this.moduleRef.get('ReactionService');
|
this.reactionService = this.moduleRef.get('ReactionService');
|
||||||
|
this.idService = this.moduleRef.get('IdService');
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
|
@ -171,11 +174,11 @@ export class NoteEntityService implements OnModuleInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
private async populateMyReaction(note: MiNote, meId: MiUser['id'], _hint_?: {
|
public async populateMyReaction(noteId: MiNote['id'], meId: MiUser['id'], _hint_?: {
|
||||||
myReactions: Map<MiNote['id'], MiNoteReaction | null>;
|
myReactions: Map<MiNote['id'], MiNoteReaction | null>;
|
||||||
}) {
|
}) {
|
||||||
if (_hint_?.myReactions) {
|
if (_hint_?.myReactions) {
|
||||||
const reaction = _hint_.myReactions.get(note.id);
|
const reaction = _hint_.myReactions.get(noteId);
|
||||||
if (reaction) {
|
if (reaction) {
|
||||||
return this.reactionService.convertLegacyReaction(reaction.reaction);
|
return this.reactionService.convertLegacyReaction(reaction.reaction);
|
||||||
} else if (reaction === null) {
|
} else if (reaction === null) {
|
||||||
|
@ -185,13 +188,13 @@ export class NoteEntityService implements OnModuleInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
// パフォーマンスのためノートが作成されてから2秒以上経っていない場合はリアクションを取得しない
|
// パフォーマンスのためノートが作成されてから2秒以上経っていない場合はリアクションを取得しない
|
||||||
if (note.createdAt.getTime() + 2000 > Date.now()) {
|
if (this.idService.parse(noteId).date.getTime() + 2000 > Date.now()) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const reaction = await this.noteReactionsRepository.findOneBy({
|
const reaction = await this.noteReactionsRepository.findOneBy({
|
||||||
userId: meId,
|
userId: meId,
|
||||||
noteId: note.id,
|
noteId: noteId,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (reaction) {
|
if (reaction) {
|
||||||
|
@ -360,6 +363,12 @@ export class NoteEntityService implements OnModuleInit {
|
||||||
detail: true,
|
detail: true,
|
||||||
_hint_: options?._hint_,
|
_hint_: options?._hint_,
|
||||||
}) : undefined,
|
}) : undefined,
|
||||||
|
|
||||||
|
poll: note.hasPoll ? this.populatePoll(note, meId) : undefined,
|
||||||
|
|
||||||
|
...(meId ? {
|
||||||
|
myReaction: this.populateMyReaction(note.id, meId, options?._hint_),
|
||||||
|
} : {}),
|
||||||
} : {}),
|
} : {}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -38,19 +38,6 @@ class ChannelChannel extends Channel {
|
||||||
private async onNote(note: Packed<'Note'>) {
|
private async onNote(note: Packed<'Note'>) {
|
||||||
if (note.channelId !== this.channelId) return;
|
if (note.channelId !== this.channelId) return;
|
||||||
|
|
||||||
// リプライなら再pack
|
|
||||||
if (note.replyId != null) {
|
|
||||||
note.reply = await this.noteEntityService.pack(note.replyId, this.user, {
|
|
||||||
detail: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Renoteなら再pack
|
|
||||||
if (note.renoteId != null) {
|
|
||||||
note.renote = await this.noteEntityService.pack(note.renoteId, this.user, {
|
|
||||||
detail: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する
|
// 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する
|
||||||
if (isUserRelated(note, this.userIdsWhoMeMuting)) return;
|
if (isUserRelated(note, this.userIdsWhoMeMuting)) return;
|
||||||
// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する
|
// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する
|
||||||
|
@ -58,6 +45,11 @@ class ChannelChannel extends Channel {
|
||||||
|
|
||||||
if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return;
|
if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return;
|
||||||
|
|
||||||
|
if (this.user && note.renoteId && !note.text) {
|
||||||
|
const myRenoteReaction = await this.noteEntityService.populateMyReaction(note.renoteId, this.user.id);
|
||||||
|
note.renote!.myReaction = myRenoteReaction;
|
||||||
|
}
|
||||||
|
|
||||||
this.connection.cacheNote(note);
|
this.connection.cacheNote(note);
|
||||||
|
|
||||||
this.send('note', note);
|
this.send('note', note);
|
||||||
|
|
|
@ -52,19 +52,6 @@ class GlobalTimelineChannel extends Channel {
|
||||||
if (note.visibility !== 'public') return;
|
if (note.visibility !== 'public') return;
|
||||||
if (note.channelId != null) return;
|
if (note.channelId != null) return;
|
||||||
|
|
||||||
// リプライなら再pack
|
|
||||||
if (note.replyId != null) {
|
|
||||||
note.reply = await this.noteEntityService.pack(note.replyId, this.user, {
|
|
||||||
detail: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Renoteなら再pack
|
|
||||||
if (note.renoteId != null) {
|
|
||||||
note.renote = await this.noteEntityService.pack(note.renoteId, this.user, {
|
|
||||||
detail: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 関係ない返信は除外
|
// 関係ない返信は除外
|
||||||
if (note.reply && !this.following[note.userId]?.withReplies) {
|
if (note.reply && !this.following[note.userId]?.withReplies) {
|
||||||
const reply = note.reply;
|
const reply = note.reply;
|
||||||
|
@ -84,6 +71,11 @@ class GlobalTimelineChannel extends Channel {
|
||||||
|
|
||||||
if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return;
|
if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return;
|
||||||
|
|
||||||
|
if (this.user && note.renoteId && !note.text) {
|
||||||
|
const myRenoteReaction = await this.noteEntityService.populateMyReaction(note.renoteId, this.user.id);
|
||||||
|
note.renote!.myReaction = myRenoteReaction;
|
||||||
|
}
|
||||||
|
|
||||||
this.connection.cacheNote(note);
|
this.connection.cacheNote(note);
|
||||||
|
|
||||||
this.send('note', note);
|
this.send('note', note);
|
||||||
|
|
|
@ -43,13 +43,6 @@ class HashtagChannel extends Channel {
|
||||||
const matched = this.q.some(tags => tags.every(tag => noteTags.includes(normalizeForSearch(tag))));
|
const matched = this.q.some(tags => tags.every(tag => noteTags.includes(normalizeForSearch(tag))));
|
||||||
if (!matched) return;
|
if (!matched) return;
|
||||||
|
|
||||||
// Renoteなら再pack
|
|
||||||
if (note.renoteId != null) {
|
|
||||||
note.renote = await this.noteEntityService.pack(note.renoteId, this.user, {
|
|
||||||
detail: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する
|
// 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する
|
||||||
if (isUserRelated(note, this.userIdsWhoMeMuting)) return;
|
if (isUserRelated(note, this.userIdsWhoMeMuting)) return;
|
||||||
// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する
|
// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する
|
||||||
|
@ -57,6 +50,11 @@ class HashtagChannel extends Channel {
|
||||||
|
|
||||||
if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return;
|
if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return;
|
||||||
|
|
||||||
|
if (this.user && note.renoteId && !note.text) {
|
||||||
|
const myRenoteReaction = await this.noteEntityService.populateMyReaction(note.renoteId, this.user.id);
|
||||||
|
note.renote!.myReaction = myRenoteReaction;
|
||||||
|
}
|
||||||
|
|
||||||
this.connection.cacheNote(note);
|
this.connection.cacheNote(note);
|
||||||
|
|
||||||
this.send('note', note);
|
this.send('note', note);
|
||||||
|
|
|
@ -51,27 +51,10 @@ class HomeTimelineChannel extends Channel {
|
||||||
// Ignore notes from instances the user has muted
|
// Ignore notes from instances the user has muted
|
||||||
if (isInstanceMuted(note, new Set<string>(this.userProfile!.mutedInstances ?? []))) return;
|
if (isInstanceMuted(note, new Set<string>(this.userProfile!.mutedInstances ?? []))) return;
|
||||||
|
|
||||||
if (['followers', 'specified'].includes(note.visibility)) {
|
if (note.visibility === 'followers') {
|
||||||
note = await this.noteEntityService.pack(note.id, this.user!, {
|
if (!Object.hasOwn(this.following, note.userId)) return;
|
||||||
detail: true,
|
} else if (note.visibility === 'specified') {
|
||||||
});
|
if (!note.visibleUserIds!.includes(this.user!.id)) return;
|
||||||
|
|
||||||
if (note.isHidden) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// リプライなら再pack
|
|
||||||
if (note.replyId != null) {
|
|
||||||
note.reply = await this.noteEntityService.pack(note.replyId, this.user!, {
|
|
||||||
detail: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Renoteなら再pack
|
|
||||||
if (note.renoteId != null) {
|
|
||||||
note.renote = await this.noteEntityService.pack(note.renoteId, this.user!, {
|
|
||||||
detail: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 関係ない返信は除外
|
// 関係ない返信は除外
|
||||||
|
@ -90,6 +73,11 @@ class HomeTimelineChannel extends Channel {
|
||||||
|
|
||||||
if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return;
|
if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return;
|
||||||
|
|
||||||
|
if (this.user && note.renoteId && !note.text) {
|
||||||
|
const myRenoteReaction = await this.noteEntityService.populateMyReaction(note.renoteId, this.user.id);
|
||||||
|
note.renote!.myReaction = myRenoteReaction;
|
||||||
|
}
|
||||||
|
|
||||||
this.connection.cacheNote(note);
|
this.connection.cacheNote(note);
|
||||||
|
|
||||||
this.send('note', note);
|
this.send('note', note);
|
||||||
|
|
|
@ -62,27 +62,10 @@ class HybridTimelineChannel extends Channel {
|
||||||
(note.channelId != null && this.followingChannels.has(note.channelId))
|
(note.channelId != null && this.followingChannels.has(note.channelId))
|
||||||
)) return;
|
)) return;
|
||||||
|
|
||||||
if (['followers', 'specified'].includes(note.visibility)) {
|
if (note.visibility === 'followers') {
|
||||||
note = await this.noteEntityService.pack(note.id, this.user!, {
|
if (!Object.hasOwn(this.following, note.userId)) return;
|
||||||
detail: true,
|
} else if (note.visibility === 'specified') {
|
||||||
});
|
if (!note.visibleUserIds!.includes(this.user!.id)) return;
|
||||||
|
|
||||||
if (note.isHidden) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// リプライなら再pack
|
|
||||||
if (note.replyId != null) {
|
|
||||||
note.reply = await this.noteEntityService.pack(note.replyId, this.user!, {
|
|
||||||
detail: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Renoteなら再pack
|
|
||||||
if (note.renoteId != null) {
|
|
||||||
note.renote = await this.noteEntityService.pack(note.renoteId, this.user!, {
|
|
||||||
detail: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore notes from instances the user has muted
|
// Ignore notes from instances the user has muted
|
||||||
|
@ -104,6 +87,11 @@ class HybridTimelineChannel extends Channel {
|
||||||
|
|
||||||
if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return;
|
if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return;
|
||||||
|
|
||||||
|
if (this.user && note.renoteId && !note.text) {
|
||||||
|
const myRenoteReaction = await this.noteEntityService.populateMyReaction(note.renoteId, this.user.id);
|
||||||
|
note.renote!.myReaction = myRenoteReaction;
|
||||||
|
}
|
||||||
|
|
||||||
this.connection.cacheNote(note);
|
this.connection.cacheNote(note);
|
||||||
|
|
||||||
this.send('note', note);
|
this.send('note', note);
|
||||||
|
|
|
@ -54,19 +54,6 @@ class LocalTimelineChannel extends Channel {
|
||||||
if (note.visibility !== 'public') return;
|
if (note.visibility !== 'public') return;
|
||||||
if (note.channelId != null && !this.followingChannels.has(note.channelId)) return;
|
if (note.channelId != null && !this.followingChannels.has(note.channelId)) return;
|
||||||
|
|
||||||
// リプライなら再pack
|
|
||||||
if (note.replyId != null) {
|
|
||||||
note.reply = await this.noteEntityService.pack(note.replyId, this.user, {
|
|
||||||
detail: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Renoteなら再pack
|
|
||||||
if (note.renoteId != null) {
|
|
||||||
note.renote = await this.noteEntityService.pack(note.renoteId, this.user, {
|
|
||||||
detail: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 関係ない返信は除外
|
// 関係ない返信は除外
|
||||||
if (note.reply && this.user && !this.following[note.userId]?.withReplies && !this.withReplies) {
|
if (note.reply && this.user && !this.following[note.userId]?.withReplies && !this.withReplies) {
|
||||||
const reply = note.reply;
|
const reply = note.reply;
|
||||||
|
@ -83,6 +70,11 @@ class LocalTimelineChannel extends Channel {
|
||||||
|
|
||||||
if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return;
|
if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return;
|
||||||
|
|
||||||
|
if (this.user && note.renoteId && !note.text) {
|
||||||
|
const myRenoteReaction = await this.noteEntityService.populateMyReaction(note.renoteId, this.user.id);
|
||||||
|
note.renote!.myReaction = myRenoteReaction;
|
||||||
|
}
|
||||||
|
|
||||||
this.connection.cacheNote(note);
|
this.connection.cacheNote(note);
|
||||||
|
|
||||||
this.send('note', note);
|
this.send('note', note);
|
||||||
|
|
|
@ -82,27 +82,10 @@ class UserListChannel extends Channel {
|
||||||
|
|
||||||
if (!Object.hasOwn(this.membershipsMap, note.userId)) return;
|
if (!Object.hasOwn(this.membershipsMap, note.userId)) return;
|
||||||
|
|
||||||
if (['followers', 'specified'].includes(note.visibility)) {
|
if (note.visibility === 'followers') {
|
||||||
note = await this.noteEntityService.pack(note.id, this.user, {
|
if (!Object.hasOwn(this.following, note.userId)) return;
|
||||||
detail: true,
|
} else if (note.visibility === 'specified') {
|
||||||
});
|
if (!note.visibleUserIds!.includes(this.user!.id)) return;
|
||||||
|
|
||||||
if (note.isHidden) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// リプライなら再pack
|
|
||||||
if (note.replyId != null) {
|
|
||||||
note.reply = await this.noteEntityService.pack(note.replyId, this.user, {
|
|
||||||
detail: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Renoteなら再pack
|
|
||||||
if (note.renoteId != null) {
|
|
||||||
note.renote = await this.noteEntityService.pack(note.renoteId, this.user, {
|
|
||||||
detail: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 関係ない返信は除外
|
// 関係ない返信は除外
|
||||||
|
@ -119,6 +102,13 @@ class UserListChannel extends Channel {
|
||||||
|
|
||||||
if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return;
|
if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return;
|
||||||
|
|
||||||
|
if (this.user && note.renoteId && !note.text) {
|
||||||
|
const myRenoteReaction = await this.noteEntityService.populateMyReaction(note.renoteId, this.user.id);
|
||||||
|
note.renote!.myReaction = myRenoteReaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.connection.cacheNote(note);
|
||||||
|
|
||||||
this.send('note', note);
|
this.send('note', note);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue