noteのread処理
This commit is contained in:
		
							parent
							
								
									00bc097abb
								
							
						
					
					
						commit
						7e4a800352
					
				
					 10 changed files with 132 additions and 57 deletions
				
			
		
							
								
								
									
										36
									
								
								src/misc/antenna-cache.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/misc/antenna-cache.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,36 @@
 | 
				
			||||||
 | 
					import { Antennas } from '../models';
 | 
				
			||||||
 | 
					import { Antenna } from '../models/entities/antenna';
 | 
				
			||||||
 | 
					import { subsdcriber } from '../db/redis';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let antennasFetched = false;
 | 
				
			||||||
 | 
					let antennas: Antenna[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export async function getAntennas() {
 | 
				
			||||||
 | 
						if (!antennasFetched) {
 | 
				
			||||||
 | 
							antennas = await Antennas.find();
 | 
				
			||||||
 | 
							antennasFetched = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return antennas;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					subsdcriber.on('message', async (_, data) => {
 | 
				
			||||||
 | 
						const obj = JSON.parse(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (obj.channel === 'internal') {
 | 
				
			||||||
 | 
							const { type, body } = obj.message;
 | 
				
			||||||
 | 
							switch (type) {
 | 
				
			||||||
 | 
								case 'antennaCreated':
 | 
				
			||||||
 | 
									antennas.push(body);
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case 'antennaUpdated':
 | 
				
			||||||
 | 
									antennas[antennas.findIndex(a => a.id === body.id)] = body;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case 'antennaDeleted':
 | 
				
			||||||
 | 
									antennas = antennas.filter(a => a.id !== body.id);
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
| 
						 | 
					@ -4,18 +4,24 @@ import { User } from '../models/entities/user';
 | 
				
			||||||
import { UserListJoinings, UserGroupJoinings } from '../models';
 | 
					import { UserListJoinings, UserGroupJoinings } from '../models';
 | 
				
			||||||
import parseAcct from './acct/parse';
 | 
					import parseAcct from './acct/parse';
 | 
				
			||||||
import { getFullApAccount } from './convert-host';
 | 
					import { getFullApAccount } from './convert-host';
 | 
				
			||||||
 | 
					import { PackedNote } from '../models/repositories/note';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function checkHitAntenna(antenna: Antenna, note: Note, noteUser: User, followers: User['id'][]): Promise<boolean> {
 | 
					/**
 | 
				
			||||||
 | 
					 * noteUserFollowers / antennaUserFollowing はどちらか一方が指定されていればよい
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export async function checkHitAntenna(antenna: Antenna, note: (Note | PackedNote), noteUser: { username: string; host: string | null; }, noteUserFollowers?: User['id'][], antennaUserFollowing?: User['id'][]): Promise<boolean> {
 | 
				
			||||||
	if (note.visibility === 'specified') return false;
 | 
						if (note.visibility === 'specified') return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (note.visibility === 'followers') {
 | 
						if (note.visibility === 'followers') {
 | 
				
			||||||
		if (!followers.includes(antenna.userId)) return false;
 | 
							if (noteUserFollowers && !noteUserFollowers.includes(antenna.userId)) return false;
 | 
				
			||||||
 | 
							if (antennaUserFollowing && !antennaUserFollowing.includes(note.userId)) return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!antenna.withReplies && note.replyId != null) return false;
 | 
						if (!antenna.withReplies && note.replyId != null) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (antenna.src === 'home') {
 | 
						if (antenna.src === 'home') {
 | 
				
			||||||
		if (!followers.includes(antenna.userId)) return false;
 | 
							if (noteUserFollowers && !noteUserFollowers.includes(antenna.userId)) return false;
 | 
				
			||||||
 | 
							if (antennaUserFollowing && !antennaUserFollowing.includes(note.userId)) return false;
 | 
				
			||||||
	} else if (antenna.src === 'list') {
 | 
						} else if (antenna.src === 'list') {
 | 
				
			||||||
		const listUsers = (await UserListJoinings.find({
 | 
							const listUsers = (await UserListJoinings.find({
 | 
				
			||||||
			userListId: antenna.userListId!
 | 
								userListId: antenna.userListId!
 | 
				
			||||||
| 
						 | 
					@ -75,7 +81,7 @@ export async function checkHitAntenna(antenna: Antenna, note: Note, noteUser: Us
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (antenna.withFile) {
 | 
						if (antenna.withFile) {
 | 
				
			||||||
		if (note.fileIds.length === 0) return false;
 | 
							if (note.fileIds && note.fileIds.length === 0) return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO: eval expression
 | 
						// TODO: eval expression
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@ import config from '../../config';
 | 
				
			||||||
import { SchemaType } from '../../misc/schema';
 | 
					import { SchemaType } from '../../misc/schema';
 | 
				
			||||||
import { awaitAll } from '../../prelude/await-all';
 | 
					import { awaitAll } from '../../prelude/await-all';
 | 
				
			||||||
import { populateEmojis } from '../../misc/populate-emojis';
 | 
					import { populateEmojis } from '../../misc/populate-emojis';
 | 
				
			||||||
 | 
					import { getAntennas } from '../../misc/antenna-cache';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type PackedUser = SchemaType<typeof packedUserSchema>;
 | 
					export type PackedUser = SchemaType<typeof packedUserSchema>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -97,10 +98,10 @@ export class UserRepository extends Repository<User> {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public async getHasUnreadAntenna(userId: User['id']): Promise<boolean> {
 | 
						public async getHasUnreadAntenna(userId: User['id']): Promise<boolean> {
 | 
				
			||||||
		const antennas = await Antennas.find({ userId });
 | 
							const myAntennas = (await getAntennas()).filter(a => a.userId === userId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const unread = antennas.length > 0 ? await AntennaNotes.findOne({
 | 
							const unread = myAntennas.length > 0 ? await AntennaNotes.findOne({
 | 
				
			||||||
			antennaId: In(antennas.map(x => x.id)),
 | 
								antennaId: In(myAntennas.map(x => x.id)),
 | 
				
			||||||
			read: false
 | 
								read: false
 | 
				
			||||||
		}) : null;
 | 
							}) : null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@ import { genId } from '../../../../misc/gen-id';
 | 
				
			||||||
import { Antennas, UserLists, UserGroupJoinings } from '../../../../models';
 | 
					import { Antennas, UserLists, UserGroupJoinings } from '../../../../models';
 | 
				
			||||||
import { ID } from '../../../../misc/cafy-id';
 | 
					import { ID } from '../../../../misc/cafy-id';
 | 
				
			||||||
import { ApiError } from '../../error';
 | 
					import { ApiError } from '../../error';
 | 
				
			||||||
 | 
					import { publishInternalEvent } from '../../../../services/stream';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const meta = {
 | 
					export const meta = {
 | 
				
			||||||
	desc: {
 | 
						desc: {
 | 
				
			||||||
| 
						 | 
					@ -108,7 +109,7 @@ export default define(meta, async (ps, user) => {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const antenna = await Antennas.save({
 | 
						const antenna = await Antennas.insert({
 | 
				
			||||||
		id: genId(),
 | 
							id: genId(),
 | 
				
			||||||
		createdAt: new Date(),
 | 
							createdAt: new Date(),
 | 
				
			||||||
		userId: user.id,
 | 
							userId: user.id,
 | 
				
			||||||
| 
						 | 
					@ -123,7 +124,9 @@ export default define(meta, async (ps, user) => {
 | 
				
			||||||
		withReplies: ps.withReplies,
 | 
							withReplies: ps.withReplies,
 | 
				
			||||||
		withFile: ps.withFile,
 | 
							withFile: ps.withFile,
 | 
				
			||||||
		notify: ps.notify,
 | 
							notify: ps.notify,
 | 
				
			||||||
	});
 | 
						}).then(x => Antennas.findOneOrFail(x.identifiers[0]));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						publishInternalEvent('antennaCreated', antenna);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return await Antennas.pack(antenna);
 | 
						return await Antennas.pack(antenna);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
 | 
				
			||||||
import define from '../../define';
 | 
					import define from '../../define';
 | 
				
			||||||
import { ApiError } from '../../error';
 | 
					import { ApiError } from '../../error';
 | 
				
			||||||
import { Antennas } from '../../../../models';
 | 
					import { Antennas } from '../../../../models';
 | 
				
			||||||
 | 
					import { publishInternalEvent } from '../../../../services/stream';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const meta = {
 | 
					export const meta = {
 | 
				
			||||||
	desc: {
 | 
						desc: {
 | 
				
			||||||
| 
						 | 
					@ -42,4 +43,6 @@ export default define(meta, async (ps, user) => {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	await Antennas.delete(antenna.id);
 | 
						await Antennas.delete(antenna.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						publishInternalEvent('antennaDeleted', antenna);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
 | 
				
			||||||
import define from '../../define';
 | 
					import define from '../../define';
 | 
				
			||||||
import { ApiError } from '../../error';
 | 
					import { ApiError } from '../../error';
 | 
				
			||||||
import { Antennas, UserLists, UserGroupJoinings } from '../../../../models';
 | 
					import { Antennas, UserLists, UserGroupJoinings } from '../../../../models';
 | 
				
			||||||
 | 
					import { publishInternalEvent } from '../../../../services/stream';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const meta = {
 | 
					export const meta = {
 | 
				
			||||||
	desc: {
 | 
						desc: {
 | 
				
			||||||
| 
						 | 
					@ -141,5 +142,7 @@ export default define(meta, async (ps, user) => {
 | 
				
			||||||
		notify: ps.notify,
 | 
							notify: ps.notify,
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						publishInternalEvent('antennaUpdated', Antennas.findOneOrFail(antenna.id));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return await Antennas.pack(antenna.id);
 | 
						return await Antennas.pack(antenna.id);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -168,17 +168,10 @@ export default class Connection {
 | 
				
			||||||
		if (note == null) return;
 | 
							if (note == null) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (this.user && (note.userId !== this.user.id)) {
 | 
							if (this.user && (note.userId !== this.user.id)) {
 | 
				
			||||||
			if (note.mentions && note.mentions.includes(this.user.id)) {
 | 
								readNote(this.user.id, [note], {
 | 
				
			||||||
				readNote(this.user.id, [note]);
 | 
									following: this.following,
 | 
				
			||||||
			} else if (note.visibleUserIds && note.visibleUserIds.includes(this.user.id)) {
 | 
									followingChannels: this.followingChannels,
 | 
				
			||||||
				readNote(this.user.id, [note]);
 | 
								});
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (this.followingChannels.has(note.channelId)) {
 | 
					 | 
				
			||||||
				// TODO
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// TODO: アンテナの既読処理
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,6 +33,7 @@ import { countSameRenotes } from '../../misc/count-same-renotes';
 | 
				
			||||||
import { deliverToRelays } from '../relay';
 | 
					import { deliverToRelays } from '../relay';
 | 
				
			||||||
import { Channel } from '../../models/entities/channel';
 | 
					import { Channel } from '../../models/entities/channel';
 | 
				
			||||||
import { normalizeForSearch } from '../../misc/normalize-for-search';
 | 
					import { normalizeForSearch } from '../../misc/normalize-for-search';
 | 
				
			||||||
 | 
					import { getAntennas } from '../../misc/antenna-cache';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';
 | 
					type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -241,6 +242,7 @@ export default async (user: User, data: Option, silent = false) => new Promise<N
 | 
				
			||||||
	incNotesCountOfUser(user);
 | 
						incNotesCountOfUser(user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Word mute
 | 
						// Word mute
 | 
				
			||||||
 | 
						// TODO: cache
 | 
				
			||||||
	UserProfiles.find({
 | 
						UserProfiles.find({
 | 
				
			||||||
		enableWordMute: true
 | 
							enableWordMute: true
 | 
				
			||||||
	}).then(us => {
 | 
						}).then(us => {
 | 
				
			||||||
| 
						 | 
					@ -262,10 +264,9 @@ export default async (user: User, data: Option, silent = false) => new Promise<N
 | 
				
			||||||
	Followings.createQueryBuilder('following')
 | 
						Followings.createQueryBuilder('following')
 | 
				
			||||||
		.andWhere(`following.followeeId = :userId`, { userId: note.userId })
 | 
							.andWhere(`following.followeeId = :userId`, { userId: note.userId })
 | 
				
			||||||
		.getMany()
 | 
							.getMany()
 | 
				
			||||||
		.then(followings => {
 | 
							.then(async followings => {
 | 
				
			||||||
			const followers = followings.map(f => f.followerId);
 | 
								const followers = followings.map(f => f.followerId);
 | 
				
			||||||
			Antennas.find().then(async antennas => {
 | 
								for (const antenna of (await getAntennas())) {
 | 
				
			||||||
				for (const antenna of antennas) {
 | 
					 | 
				
			||||||
				checkHitAntenna(antenna, note, user, followers).then(hit => {
 | 
									checkHitAntenna(antenna, note, user, followers).then(hit => {
 | 
				
			||||||
					if (hit) {
 | 
										if (hit) {
 | 
				
			||||||
						addNoteToAntenna(antenna, note, user);
 | 
											addNoteToAntenna(antenna, note, user);
 | 
				
			||||||
| 
						 | 
					@ -273,7 +274,6 @@ export default async (user: User, data: Option, silent = false) => new Promise<N
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Channel
 | 
						// Channel
 | 
				
			||||||
	if (note.channelId) {
 | 
						if (note.channelId) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,23 +1,59 @@
 | 
				
			||||||
import { publishMainStream } from '../stream';
 | 
					import { publishMainStream } from '../stream';
 | 
				
			||||||
import { Note } from '../../models/entities/note';
 | 
					import { Note } from '../../models/entities/note';
 | 
				
			||||||
import { User } from '../../models/entities/user';
 | 
					import { User } from '../../models/entities/user';
 | 
				
			||||||
import { NoteUnreads, Antennas, AntennaNotes, Users } from '../../models';
 | 
					import { NoteUnreads, AntennaNotes, Users } from '../../models';
 | 
				
			||||||
import { Not, IsNull, In } from 'typeorm';
 | 
					import { Not, IsNull, In } from 'typeorm';
 | 
				
			||||||
 | 
					import { Channel } from '../../models/entities/channel';
 | 
				
			||||||
 | 
					import { checkHitAntenna } from '../../misc/check-hit-antenna';
 | 
				
			||||||
 | 
					import { getAntennas } from '../../misc/antenna-cache';
 | 
				
			||||||
 | 
					import { PackedNote } from '../../models/repositories/note';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Mark notes as read
 | 
					 * Mark notes as read
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default async function(
 | 
					export default async function(
 | 
				
			||||||
	userId: User['id'],
 | 
						userId: User['id'],
 | 
				
			||||||
	noteIds: Note['id'][]
 | 
						notes: (Note | PackedNote)[],
 | 
				
			||||||
 | 
						info: {
 | 
				
			||||||
 | 
							following: Set<Channel['id']>;
 | 
				
			||||||
 | 
							followingChannels: Set<Channel['id']>;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
	async function careNoteUnreads() {
 | 
						const myAntennas = (await getAntennas()).filter(a => a.userId === userId);
 | 
				
			||||||
 | 
						const readMentions: (Note | PackedNote)[] = [];
 | 
				
			||||||
 | 
						const readSpecifiedNotes: (Note | PackedNote)[] = [];
 | 
				
			||||||
 | 
						const readChannelNotes: (Note | PackedNote)[] = [];
 | 
				
			||||||
 | 
						const readAntennaNotes: (Note | PackedNote)[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (const note of notes) {
 | 
				
			||||||
 | 
							if (note.mentions && note.mentions.includes(userId)) {
 | 
				
			||||||
 | 
								readMentions.push(note);
 | 
				
			||||||
 | 
							} else if (note.visibleUserIds && note.visibleUserIds.includes(userId)) {
 | 
				
			||||||
 | 
								readSpecifiedNotes.push(note);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (note.channelId && info.followingChannels.has(note.channelId)) {
 | 
				
			||||||
 | 
								readChannelNotes.push(note);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (note.user != null) { // たぶんnullになることは無いはずだけど一応
 | 
				
			||||||
 | 
								for (const antenna of myAntennas) {
 | 
				
			||||||
 | 
									if (checkHitAntenna(antenna, note, note.user as any, undefined, Array.from(info.following))) {
 | 
				
			||||||
 | 
										readAntennaNotes.push(note);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((readMentions.length > 0) || (readSpecifiedNotes.length > 0) || (readChannelNotes.length > 0)) {
 | 
				
			||||||
		// Remove the record
 | 
							// Remove the record
 | 
				
			||||||
		await NoteUnreads.delete({
 | 
							await NoteUnreads.delete({
 | 
				
			||||||
			userId: userId,
 | 
								userId: userId,
 | 
				
			||||||
			noteId: In(noteIds),
 | 
								noteId: In([...readMentions.map(n => n.id), ...readSpecifiedNotes.map(n => n.id), ...readChannelNotes.map(n => n.id)]),
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// TODO: ↓まとめてクエリしたい
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		NoteUnreads.count({
 | 
							NoteUnreads.count({
 | 
				
			||||||
			userId: userId,
 | 
								userId: userId,
 | 
				
			||||||
			isMentioned: true
 | 
								isMentioned: true
 | 
				
			||||||
| 
						 | 
					@ -49,33 +85,25 @@ export default async function(
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	async function careAntenna() {
 | 
						if (readAntennaNotes.length > 0) {
 | 
				
			||||||
		const antennas = await Antennas.find({ userId });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		await Promise.all(antennas.map(async antenna => {
 | 
					 | 
				
			||||||
			const countBefore = await AntennaNotes.count({
 | 
					 | 
				
			||||||
				antennaId: antenna.id,
 | 
					 | 
				
			||||||
				read: false
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (countBefore === 0) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		await AntennaNotes.update({
 | 
							await AntennaNotes.update({
 | 
				
			||||||
				antennaId: antenna.id,
 | 
								antennaId: In(myAntennas.map(a => a.id)),
 | 
				
			||||||
				noteId: In(noteIds)
 | 
								noteId: In(readAntennaNotes.map(n => n.id))
 | 
				
			||||||
		}, {
 | 
							}, {
 | 
				
			||||||
			read: true
 | 
								read: true
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			const countAfter = await AntennaNotes.count({
 | 
							// TODO: まとめてクエリしたい
 | 
				
			||||||
 | 
							for (const antenna of myAntennas) {
 | 
				
			||||||
 | 
								const count = await AntennaNotes.count({
 | 
				
			||||||
				antennaId: antenna.id,
 | 
									antennaId: antenna.id,
 | 
				
			||||||
				read: false
 | 
									read: false
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (countAfter === 0) {
 | 
								if (count === 0) {
 | 
				
			||||||
				publishMainStream(userId, 'readAntenna', antenna);
 | 
									publishMainStream(userId, 'readAntenna', antenna);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}));
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Users.getHasUnreadAntenna(userId).then(unread => {
 | 
							Users.getHasUnreadAntenna(userId).then(unread => {
 | 
				
			||||||
			if (!unread) {
 | 
								if (!unread) {
 | 
				
			||||||
| 
						 | 
					@ -83,7 +111,4 @@ export default async function(
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	careNoteUnreads();
 | 
					 | 
				
			||||||
	careAntenna();
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,10 @@ class Publisher {
 | 
				
			||||||
		}));
 | 
							}));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public publishInternalEvent = (type: string, value?: any): void => {
 | 
				
			||||||
 | 
							this.publish('internal', type, typeof value === 'undefined' ? null : value);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public publishUserEvent = (userId: User['id'], type: string, value?: any): void => {
 | 
						public publishUserEvent = (userId: User['id'], type: string, value?: any): void => {
 | 
				
			||||||
		this.publish(`user:${userId}`, type, typeof value === 'undefined' ? null : value);
 | 
							this.publish(`user:${userId}`, type, typeof value === 'undefined' ? null : value);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -88,6 +92,7 @@ const publisher = new Publisher();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default publisher;
 | 
					export default publisher;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const publishInternalEvent = publisher.publishInternalEvent;
 | 
				
			||||||
export const publishUserEvent = publisher.publishUserEvent;
 | 
					export const publishUserEvent = publisher.publishUserEvent;
 | 
				
			||||||
export const publishBroadcastStream = publisher.publishBroadcastStream;
 | 
					export const publishBroadcastStream = publisher.publishBroadcastStream;
 | 
				
			||||||
export const publishMainStream = publisher.publishMainStream;
 | 
					export const publishMainStream = publisher.publishMainStream;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue