Merge branch 'develop' of https://github.com/syuilo/misskey into develop
This commit is contained in:
		
						commit
						7e18fd18b0
					
				
					 2 changed files with 86 additions and 8 deletions
				
			
		|  | @ -1,11 +1,17 @@ | |||
| import { DriveFile } from '../../models/entities/drive-file'; | ||||
| import { InternalStorage } from './internal-storage'; | ||||
| import { DriveFiles, Instances, Notes } from '../../models'; | ||||
| import { DriveFiles, Instances, Notes, Users } from '../../models'; | ||||
| import { driveChart, perUserDriveChart, instanceChart } from '../chart'; | ||||
| import { createDeleteObjectStorageFileJob } from '../../queue'; | ||||
| import { fetchMeta } from '../../misc/fetch-meta'; | ||||
| import { getS3 } from './s3'; | ||||
| import { v4 as uuid } from 'uuid'; | ||||
| import { Note } from '../../models/entities/note'; | ||||
| import { renderActivity } from '../../remote/activitypub/renderer'; | ||||
| import renderDelete from '../../remote/activitypub/renderer/delete'; | ||||
| import renderTombstone from '../../remote/activitypub/renderer/tombstone'; | ||||
| import config from '../../config'; | ||||
| import { deliverToFollowers } from '../../remote/activitypub/deliver-manager'; | ||||
| 
 | ||||
| export async function deleteFile(file: DriveFile, isExpired = false) { | ||||
| 	if (file.storedInternal) { | ||||
|  | @ -63,7 +69,7 @@ export async function deleteFileSync(file: DriveFile, isExpired = false) { | |||
| 	postProcess(file, isExpired); | ||||
| } | ||||
| 
 | ||||
| function postProcess(file: DriveFile, isExpired = false) { | ||||
| async function postProcess(file: DriveFile, isExpired = false) { | ||||
| 	// リモートファイル期限切れ削除後は直リンクにする
 | ||||
| 	if (isExpired && file.userHost !== null && file.uri != null) { | ||||
| 		DriveFiles.update(file.id, { | ||||
|  | @ -81,8 +87,23 @@ function postProcess(file: DriveFile, isExpired = false) { | |||
| 		DriveFiles.delete(file.id); | ||||
| 
 | ||||
| 		// TODO: トランザクション
 | ||||
| 		const relatedNotes = await findRelatedNotes(file.id); | ||||
| 		for (const relatedNote of relatedNotes) { // for each note with deleted driveFile
 | ||||
| 			const cascadingNotes = (await findCascadingNotes(relatedNote)).filter(note => !note.localOnly); | ||||
| 			for (const cascadingNote of cascadingNotes) { // for each notes subject to cascade deletion
 | ||||
| 				if (!cascadingNote.user) continue; | ||||
| 				if (!Users.isLocalUser(cascadingNote.user)) continue; | ||||
| 				const content = renderActivity(renderDelete(renderTombstone(`${config.url}/notes/${cascadingNote.id}`), cascadingNote.user)); | ||||
| 				deliverToFollowers(cascadingNote.user, content); // federate delete msg
 | ||||
| 			} | ||||
| 			if (!relatedNote.user) continue; | ||||
| 			if (Users.isLocalUser(relatedNote.user)) { | ||||
| 				const content = renderActivity(renderDelete(renderTombstone(`${config.url}/notes/${relatedNote.id}`), relatedNote.user)); | ||||
| 				deliverToFollowers(relatedNote.user, content); | ||||
| 			} | ||||
| 		} | ||||
| 		Notes.createQueryBuilder().delete() | ||||
| 			.where(':id = ANY(fileIds)', { id: file.id }) | ||||
| 			.where(':id = ANY("fileIds")', { id: file.id }) | ||||
| 			.execute(); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -106,3 +127,32 @@ export async function deleteObjectStorageFile(key: string) { | |||
| 		Key: key | ||||
| 	}).promise(); | ||||
| } | ||||
| 
 | ||||
| async function findRelatedNotes(fileId: string) { | ||||
| 	// NOTE: When running raw query, TypeORM converts field name to lowercase. Wrap in quotes to prevent conversion.
 | ||||
| 	const relatedNotes = await Notes.createQueryBuilder('note').where(':id = ANY("fileIds")', { id: fileId }).getMany(); | ||||
| 	for (const relatedNote of relatedNotes) { | ||||
| 		const user = await Users.findOne({ id: relatedNote.userId }); | ||||
| 		if (user) | ||||
| 			relatedNote.user = user; | ||||
| 	} | ||||
| 	return relatedNotes; | ||||
| } | ||||
| 
 | ||||
| async function findCascadingNotes(note: Note) { | ||||
| 	const cascadingNotes: Note[] = []; | ||||
| 
 | ||||
| 	const recursive = async (noteId: string) => { | ||||
| 		const query = Notes.createQueryBuilder('note') | ||||
| 			.where('note.replyId = :noteId', { noteId }) | ||||
| 			.leftJoinAndSelect('note.user', 'user'); | ||||
| 		const replies = await query.getMany(); | ||||
| 		for (const reply of replies) { | ||||
| 			cascadingNotes.push(reply); | ||||
| 			await recursive(reply.id); | ||||
| 		} | ||||
| 	}; | ||||
| 	await recursive(note.id); | ||||
| 
 | ||||
| 	return cascadingNotes.filter(note => note.userHost === null); // filter out non-local users
 | ||||
| } | ||||
|  |  | |||
|  | @ -20,11 +20,6 @@ import { deliverToFollowers } from '../../remote/activitypub/deliver-manager'; | |||
| export default async function(user: User, note: Note, quiet = false) { | ||||
| 	const deletedAt = new Date(); | ||||
| 
 | ||||
| 	await Notes.delete({ | ||||
| 		id: note.id, | ||||
| 		userId: user.id | ||||
| 	}); | ||||
| 
 | ||||
| 	if (note.renoteId) { | ||||
| 		Notes.decrement({ id: note.renoteId }, 'renoteCount', 1); | ||||
| 		Notes.decrement({ id: note.renoteId }, 'score', 1); | ||||
|  | @ -39,6 +34,7 @@ export default async function(user: User, note: Note, quiet = false) { | |||
| 		if (Users.isLocalUser(user)) { | ||||
| 			let renote: Note | undefined; | ||||
| 
 | ||||
| 			// if deletd note is renote
 | ||||
| 			if (note.renoteId && note.text == null && !note.hasPoll && (note.fileIds == null || note.fileIds.length == 0)) { | ||||
| 				renote = await Notes.findOne({ | ||||
| 					id: note.renoteId | ||||
|  | @ -51,6 +47,15 @@ export default async function(user: User, note: Note, quiet = false) { | |||
| 
 | ||||
| 			deliverToFollowers(user, content); | ||||
| 		} | ||||
| 
 | ||||
| 		// also deliever delete activity to cascaded notes
 | ||||
| 		const cascadingNotes = (await findCascadingNotes(note)).filter(note => !note.localOnly); // filter out local-only notes
 | ||||
| 		for (const cascadingNote of cascadingNotes) { | ||||
| 			if (!cascadingNote.user) continue; | ||||
| 			if (!Users.isLocalUser(cascadingNote.user)) continue; | ||||
| 			const content = renderActivity(renderDelete(renderTombstone(`${config.url}/notes/${cascadingNote.id}`), cascadingNote.user)); | ||||
| 			deliverToFollowers(cascadingNote.user, content); | ||||
| 		} | ||||
| 		//#endregion
 | ||||
| 
 | ||||
| 		// 統計を更新
 | ||||
|  | @ -64,4 +69,27 @@ export default async function(user: User, note: Note, quiet = false) { | |||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	await Notes.delete({ | ||||
| 		id: note.id, | ||||
| 		userId: user.id | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| async function findCascadingNotes(note: Note) { | ||||
| 	const cascadingNotes: Note[] = []; | ||||
| 
 | ||||
| 	const recursive = async (noteId: string) => { | ||||
| 		const query = Notes.createQueryBuilder('note') | ||||
| 			.where('note.replyId = :noteId', { noteId }) | ||||
| 			.leftJoinAndSelect('note.user', 'user'); | ||||
| 		const replies = await query.getMany(); | ||||
| 		for (const reply of replies) { | ||||
| 			cascadingNotes.push(reply); | ||||
| 			await recursive(reply.id); | ||||
| 		} | ||||
| 	}; | ||||
| 	await recursive(note.id); | ||||
| 
 | ||||
| 	return cascadingNotes.filter(note => note.userHost === null); // filter out non-local users
 | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue