wip
This commit is contained in:
		
							parent
							
								
									df71c90f9f
								
							
						
					
					
						commit
						335200c31e
					
				
					 9 changed files with 17 additions and 206 deletions
				
			
		|  | @ -1,101 +0,0 @@ | ||||||
| const chalk = require('chalk'); |  | ||||||
| const log = require('single-line-log').stdout; |  | ||||||
| const sequential = require('promise-sequential'); |  | ||||||
| const { default: DriveFile, DriveFileChunk } = require('../built/models/drive-file'); |  | ||||||
| const { default: DriveFileThumbnail, DriveFileThumbnailChunk } = require('../built/models/drive-file-thumbnail'); |  | ||||||
| const { default: User } = require('../built/models/user'); |  | ||||||
| 
 |  | ||||||
| const q = { |  | ||||||
| 	'metadata._user.host': { |  | ||||||
| 		$ne: null |  | ||||||
| 	}, |  | ||||||
| 	'metadata.withoutChunks': false |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| async function main() { |  | ||||||
| 	const promiseGens = []; |  | ||||||
| 
 |  | ||||||
| 	const count = await DriveFile.count(q); |  | ||||||
| 
 |  | ||||||
| 	let prev; |  | ||||||
| 
 |  | ||||||
| 	for (let i = 0; i < count; i++) { |  | ||||||
| 		promiseGens.push(() => { |  | ||||||
| 			const promise = new Promise(async (res, rej) => { |  | ||||||
| 				const file = await DriveFile.findOne(prev ? Object.assign({ |  | ||||||
| 					_id: { $lt: prev._id } |  | ||||||
| 				}, q) : q, { |  | ||||||
| 					sort: { |  | ||||||
| 						_id: -1 |  | ||||||
| 					} |  | ||||||
| 				}); |  | ||||||
| 
 |  | ||||||
| 				prev = file; |  | ||||||
| 
 |  | ||||||
| 				function skip() { |  | ||||||
| 					res([i, file, false]); |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				if (file == null) return skip(); |  | ||||||
| 
 |  | ||||||
| 				log(chalk`{gray ${i}} scanning {bold ${file._id}} ${file.filename} ...`); |  | ||||||
| 
 |  | ||||||
| 				const attachingUsersCount = await User.count({ |  | ||||||
| 					$or: [{ |  | ||||||
| 						avatarId: file._id |  | ||||||
| 					}, { |  | ||||||
| 						bannerId: file._id |  | ||||||
| 					}] |  | ||||||
| 				}, { limit: 1 }); |  | ||||||
| 				if (attachingUsersCount !== 0) return skip(); |  | ||||||
| 
 |  | ||||||
| 				Promise.all([ |  | ||||||
| 					// チャンクをすべて削除
 |  | ||||||
| 					DriveFileChunk.remove({ |  | ||||||
| 						files_id: file._id |  | ||||||
| 					}), |  | ||||||
| 
 |  | ||||||
| 					DriveFile.update({ _id: file._id }, { |  | ||||||
| 						$set: { |  | ||||||
| 							'metadata.withoutChunks': true |  | ||||||
| 						} |  | ||||||
| 					}) |  | ||||||
| 				]).then(async () => { |  | ||||||
| 					res([i, file, true]); |  | ||||||
| 
 |  | ||||||
| 					//#region サムネイルもあれば削除
 |  | ||||||
| 					const thumbnail = await DriveFileThumbnail.findOne({ |  | ||||||
| 						'metadata.originalId': file._id |  | ||||||
| 					}); |  | ||||||
| 
 |  | ||||||
| 					if (thumbnail) { |  | ||||||
| 						DriveFileThumbnailChunk.remove({ |  | ||||||
| 							files_id: thumbnail._id |  | ||||||
| 						}); |  | ||||||
| 
 |  | ||||||
| 						DriveFileThumbnail.remove({ _id: thumbnail._id }); |  | ||||||
| 					} |  | ||||||
| 					//#endregion
 |  | ||||||
| 				}); |  | ||||||
| 			}); |  | ||||||
| 
 |  | ||||||
| 			promise.then(([i, file, deleted]) => { |  | ||||||
| 				if (deleted) { |  | ||||||
| 					log(chalk`{gray ${i}} {red deleted: {bold ${file._id}} ${file.filename}}`); |  | ||||||
| 				} else { |  | ||||||
| 					log(chalk`{gray ${i}} {green skipped: {bold ${file._id}} ${file.filename}}`); |  | ||||||
| 				} |  | ||||||
| 				log.clear(); |  | ||||||
| 				console.log(); |  | ||||||
| 			}); |  | ||||||
| 
 |  | ||||||
| 			return promise; |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return await sequential(promiseGens); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| main().then(() => { |  | ||||||
| 	console.log('ALL DONE'); |  | ||||||
| }).catch(console.error); |  | ||||||
|  | @ -1,80 +0,0 @@ | ||||||
| const chalk = require('chalk'); |  | ||||||
| const log = require('single-line-log').stdout; |  | ||||||
| const sequential = require('promise-sequential'); |  | ||||||
| const { default: DriveFile, deleteDriveFile } = require('../built/models/drive-file'); |  | ||||||
| const { default: Note } = require('../built/models/note'); |  | ||||||
| const { default: MessagingMessage } = require('../built/models/messaging-message'); |  | ||||||
| const { default: User } = require('../built/models/user'); |  | ||||||
| 
 |  | ||||||
| async function main() { |  | ||||||
| 	const promiseGens = []; |  | ||||||
| 
 |  | ||||||
| 	const count = await DriveFile.count({}); |  | ||||||
| 
 |  | ||||||
| 	let prev; |  | ||||||
| 
 |  | ||||||
| 	for (let i = 0; i < count; i++) { |  | ||||||
| 		promiseGens.push(() => { |  | ||||||
| 			const promise = new Promise(async (res, rej) => { |  | ||||||
| 				const file = await DriveFile.findOne(prev ? { |  | ||||||
| 					_id: { $lt: prev._id } |  | ||||||
| 				} : {}, { |  | ||||||
| 					sort: { |  | ||||||
| 						_id: -1 |  | ||||||
| 					} |  | ||||||
| 				}); |  | ||||||
| 
 |  | ||||||
| 				prev = file; |  | ||||||
| 
 |  | ||||||
| 				function skip() { |  | ||||||
| 					res([i, file, false]); |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				if (file == null) return skip(); |  | ||||||
| 
 |  | ||||||
| 				log(chalk`{gray ${i}} scanning {bold ${file._id}} ${file.filename} ...`); |  | ||||||
| 
 |  | ||||||
| 				const attachingUsersCount = await User.count({ |  | ||||||
| 					$or: [{ |  | ||||||
| 						avatarId: file._id |  | ||||||
| 					}, { |  | ||||||
| 						bannerId: file._id |  | ||||||
| 					}] |  | ||||||
| 				}, { limit: 1 }); |  | ||||||
| 				if (attachingUsersCount !== 0) return skip(); |  | ||||||
| 
 |  | ||||||
| 				const attachingNotesCount = await Note.count({ |  | ||||||
| 					mediaIds: file._id |  | ||||||
| 				}, { limit: 1 }); |  | ||||||
| 				if (attachingNotesCount !== 0) return skip(); |  | ||||||
| 
 |  | ||||||
| 				const attachingMessagesCount = await MessagingMessage.count({ |  | ||||||
| 					fileId: file._id |  | ||||||
| 				}, { limit: 1 }); |  | ||||||
| 				if (attachingMessagesCount !== 0) return skip(); |  | ||||||
| 
 |  | ||||||
| 				deleteDriveFile(file).then(() => { |  | ||||||
| 					res([i, file, true]); |  | ||||||
| 				}).catch(rej); |  | ||||||
| 			}); |  | ||||||
| 
 |  | ||||||
| 			promise.then(([i, file, deleted]) => { |  | ||||||
| 				if (deleted) { |  | ||||||
| 					log(chalk`{gray ${i}} {red deleted: {bold ${file._id}} ${file.filename}}`); |  | ||||||
| 				} else { |  | ||||||
| 					log(chalk`{gray ${i}} {green skipped: {bold ${file._id}} ${file.filename}}`); |  | ||||||
| 				} |  | ||||||
| 				log.clear(); |  | ||||||
| 				console.log(); |  | ||||||
| 			}); |  | ||||||
| 
 |  | ||||||
| 			return promise; |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return await sequential(promiseGens); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| main().then(() => { |  | ||||||
| 	console.log('done'); |  | ||||||
| }).catch(console.error); |  | ||||||
|  | @ -33,14 +33,3 @@ node cli/suspend @syuilo@misskey.xyz | ||||||
| ``` shell | ``` shell | ||||||
| node cli/reset-password (User-ID or Username) | node cli/reset-password (User-ID or Username) | ||||||
| ``` | ``` | ||||||
| 
 |  | ||||||
| ## Clean up cached remote files |  | ||||||
| ``` shell |  | ||||||
| node cli/clean-cached-remote-files |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| ## Clean up unused drive files |  | ||||||
| ``` shell |  | ||||||
| node cli/clean-unused-drive-files |  | ||||||
| ``` |  | ||||||
| > We recommend that you announce a user that unused drive files will be deleted before performing this operation, as it may delete the user's important files. |  | ||||||
|  |  | ||||||
|  | @ -33,14 +33,3 @@ node cli/suspend @syuilo@misskey.xyz | ||||||
| ``` shell | ``` shell | ||||||
| node cli/reset-password (ユーザーID または ユーザー名) | node cli/reset-password (ユーザーID または ユーザー名) | ||||||
| ``` | ``` | ||||||
| 
 |  | ||||||
| ## キャッシュされたリモートファイルをクリーンアップする |  | ||||||
| ``` shell |  | ||||||
| node cli/clean-cached-remote-files |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| ## 使われていないドライブのファイルをクリーンアップする |  | ||||||
| ``` shell |  | ||||||
| node cli/clean-unused-drive-files |  | ||||||
| ``` |  | ||||||
| > ユーザーの大事なファイルを削除する可能性があるので、この操作を実行する前にユーザーに告知することをお勧めします。 |  | ||||||
|  |  | ||||||
|  | @ -17,6 +17,7 @@ import { isLocalUser, IUser, IRemoteUser } from '../../models/user'; | ||||||
| import delFile from './delete-file'; | import delFile from './delete-file'; | ||||||
| import config from '../../config'; | import config from '../../config'; | ||||||
| import { getDriveFileThumbnailBucket } from '../../models/drive-file-thumbnail'; | import { getDriveFileThumbnailBucket } from '../../models/drive-file-thumbnail'; | ||||||
|  | import { updateDriveStats } from '../update-chart'; | ||||||
| 
 | 
 | ||||||
| const log = debug('misskey:drive:add-file'); | const log = debug('misskey:drive:add-file'); | ||||||
| 
 | 
 | ||||||
|  | @ -377,7 +378,8 @@ export default async function( | ||||||
| 		publishDriveStream(user._id, 'file_created', packedFile); | 		publishDriveStream(user._id, 'file_created', packedFile); | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
| 	// TODO: サムネイル生成
 | 	// 統計を更新
 | ||||||
|  | 	updateDriveStats(driveFile, true); | ||||||
| 
 | 
 | ||||||
| 	return driveFile; | 	return driveFile; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ import * as Minio from 'minio'; | ||||||
| import DriveFile, { DriveFileChunk, IDriveFile } from '../../models/drive-file'; | import DriveFile, { DriveFileChunk, IDriveFile } from '../../models/drive-file'; | ||||||
| import DriveFileThumbnail, { DriveFileThumbnailChunk } from '../../models/drive-file-thumbnail'; | import DriveFileThumbnail, { DriveFileThumbnailChunk } from '../../models/drive-file-thumbnail'; | ||||||
| import config from '../../config'; | import config from '../../config'; | ||||||
|  | import { updateDriveStats } from '../update-chart'; | ||||||
| 
 | 
 | ||||||
| export default async function(file: IDriveFile, isExpired = false) { | export default async function(file: IDriveFile, isExpired = false) { | ||||||
| 	if (file.metadata.storage == 'minio') { | 	if (file.metadata.storage == 'minio') { | ||||||
|  | @ -45,4 +46,7 @@ export default async function(file: IDriveFile, isExpired = false) { | ||||||
| 		await DriveFileThumbnail.remove({ _id: thumbnail._id }); | 		await DriveFileThumbnail.remove({ _id: thumbnail._id }); | ||||||
| 	} | 	} | ||||||
| 	//#endregion
 | 	//#endregion
 | ||||||
|  | 
 | ||||||
|  | 	// 統計を更新
 | ||||||
|  | 	updateDriveStats(file, false); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -23,6 +23,7 @@ import registerHashtag from '../register-hashtag'; | ||||||
| import isQuote from '../../misc/is-quote'; | import isQuote from '../../misc/is-quote'; | ||||||
| import { TextElementMention } from '../../mfm/parse/elements/mention'; | import { TextElementMention } from '../../mfm/parse/elements/mention'; | ||||||
| import { TextElementHashtag } from '../../mfm/parse/elements/hashtag'; | import { TextElementHashtag } from '../../mfm/parse/elements/hashtag'; | ||||||
|  | import { updateNoteStats } from '../update-chart'; | ||||||
| 
 | 
 | ||||||
| type NotificationType = 'reply' | 'renote' | 'quote' | 'mention'; | type NotificationType = 'reply' | 'renote' | 'quote' | 'mention'; | ||||||
| 
 | 
 | ||||||
|  | @ -142,6 +143,9 @@ export default async (user: IUser, data: Option, silent = false) => new Promise< | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	// 統計を更新
 | ||||||
|  | 	updateNoteStats(note, true); | ||||||
|  | 
 | ||||||
| 	// ハッシュタグ登録
 | 	// ハッシュタグ登録
 | ||||||
| 	tags.map(tag => registerHashtag(user, tag)); | 	tags.map(tag => registerHashtag(user, tag)); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ import pack from '../../remote/activitypub/renderer'; | ||||||
| import { deliver } from '../../queue'; | import { deliver } from '../../queue'; | ||||||
| import Following from '../../models/following'; | import Following from '../../models/following'; | ||||||
| import renderNote from '../../remote/activitypub/renderer/note'; | import renderNote from '../../remote/activitypub/renderer/note'; | ||||||
|  | import { updateNoteStats } from '../update-chart'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * 投稿を削除します。 |  * 投稿を削除します。 | ||||||
|  | @ -43,4 +44,7 @@ export default async function(user: IUser, note: INote) { | ||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
| 	//#endregion
 | 	//#endregion
 | ||||||
|  | 
 | ||||||
|  | 	// 統計を更新
 | ||||||
|  | 	updateNoteStats(note, false); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -201,13 +201,13 @@ export async function updateNoteStats(note: INote, isAdditional: boolean) { | ||||||
| 	await update(inc); | 	await update(inc); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function updateDriveStats(user: IUser, file: IDriveFile, isAdditional: boolean) { | export async function updateDriveStats(file: IDriveFile, isAdditional: boolean) { | ||||||
| 	const inc = {} as any; | 	const inc = {} as any; | ||||||
| 
 | 
 | ||||||
| 	const amount = isAdditional ? 1 : -1; | 	const amount = isAdditional ? 1 : -1; | ||||||
| 	const size = isAdditional ? file.length : -file.length; | 	const size = isAdditional ? file.length : -file.length; | ||||||
| 
 | 
 | ||||||
| 	if (isLocalUser(user)) { | 	if (isLocalUser(file.metadata._user)) { | ||||||
| 		inc['drive.local.totalCount'] = amount; | 		inc['drive.local.totalCount'] = amount; | ||||||
| 		inc['drive.local.diffCount'] = amount; | 		inc['drive.local.diffCount'] = amount; | ||||||
| 		inc['drive.local.totalSize'] = size; | 		inc['drive.local.totalSize'] = size; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue