2019-04-09 06:31:45 +03:00
|
|
|
process.env.NODE_ENV = 'production';
|
|
|
|
|
2019-04-08 19:03:58 +03:00
|
|
|
import monk from 'monk';
|
|
|
|
import * as mongo from 'mongodb';
|
|
|
|
import * as fs from 'fs';
|
|
|
|
import * as uuid from 'uuid';
|
2019-04-09 06:31:45 +03:00
|
|
|
import chalk from 'chalk';
|
2019-04-08 14:33:42 +03:00
|
|
|
import config from './config';
|
|
|
|
import { initDb } from './db/postgre';
|
|
|
|
import { User } from './models/entities/user';
|
|
|
|
import { getRepository } from 'typeorm';
|
|
|
|
import generateUserToken from './server/api/common/generate-native-user-token';
|
2019-04-08 17:24:44 +03:00
|
|
|
import { DriveFile } from './models/entities/drive-file';
|
2019-04-08 19:31:54 +03:00
|
|
|
import { DriveFolder } from './models/entities/drive-folder';
|
2019-04-08 19:03:58 +03:00
|
|
|
import { InternalStorage } from './services/drive/internal-storage';
|
|
|
|
import { createTemp } from './misc/create-temp';
|
2019-04-09 06:31:45 +03:00
|
|
|
import { Note } from './models/entities/note';
|
2019-04-08 14:33:42 +03:00
|
|
|
|
|
|
|
const u = (config as any).mongodb.user ? encodeURIComponent((config as any).mongodb.user) : null;
|
|
|
|
const p = (config as any).mongodb.pass ? encodeURIComponent((config as any).mongodb.pass) : null;
|
|
|
|
|
|
|
|
const uri = `mongodb://${u && p ? `${u}:${p}@` : ''}${(config as any).mongodb.host}:${(config as any).mongodb.port}/${(config as any).mongodb.db}`;
|
|
|
|
|
2019-04-08 19:03:58 +03:00
|
|
|
const db = monk(uri);
|
|
|
|
let mdb: mongo.Db;
|
|
|
|
|
|
|
|
const nativeDbConn = async (): Promise<mongo.Db> => {
|
|
|
|
if (mdb) return mdb;
|
|
|
|
|
|
|
|
const db = await ((): Promise<mongo.Db> => new Promise((resolve, reject) => {
|
|
|
|
mongo.MongoClient.connect(uri, { useNewUrlParser: true }, (e: Error, client: any) => {
|
|
|
|
if (e) return reject(e);
|
2019-04-08 19:31:54 +03:00
|
|
|
resolve(client.db((config as any).mongodb.db));
|
2019-04-08 19:03:58 +03:00
|
|
|
});
|
|
|
|
}))();
|
|
|
|
|
|
|
|
mdb = db;
|
|
|
|
|
|
|
|
return db;
|
|
|
|
};
|
2019-04-08 14:33:42 +03:00
|
|
|
|
|
|
|
const _User = db.get<any>('users');
|
2019-04-08 17:24:44 +03:00
|
|
|
const _DriveFile = db.get<any>('driveFiles.files');
|
2019-04-08 19:31:54 +03:00
|
|
|
const _DriveFolder = db.get<any>('driveFolders');
|
2019-04-09 06:31:45 +03:00
|
|
|
const _Note = db.get<any>('notes');
|
2019-04-08 19:03:58 +03:00
|
|
|
const getDriveFileBucket = async (): Promise<mongo.GridFSBucket> => {
|
|
|
|
const db = await nativeDbConn();
|
|
|
|
const bucket = new mongo.GridFSBucket(db, {
|
|
|
|
bucketName: 'driveFiles'
|
|
|
|
});
|
|
|
|
return bucket;
|
|
|
|
};
|
2019-04-08 14:33:42 +03:00
|
|
|
|
|
|
|
async function main() {
|
|
|
|
await initDb();
|
|
|
|
const Users = getRepository(User);
|
2019-04-08 17:24:44 +03:00
|
|
|
const DriveFiles = getRepository(DriveFile);
|
2019-04-08 19:31:54 +03:00
|
|
|
const DriveFolders = getRepository(DriveFolder);
|
2019-04-09 06:31:45 +03:00
|
|
|
const Notes = getRepository(Note);
|
2019-04-08 19:31:54 +03:00
|
|
|
|
|
|
|
async function migrateDriveFile(file: any) {
|
|
|
|
const user = await _User.findOne({
|
|
|
|
_id: file.metadata.userId
|
|
|
|
});
|
|
|
|
if (file.metadata.storage && file.metadata.storage.key) { // when object storage
|
|
|
|
await DriveFiles.save({
|
|
|
|
id: file._id.toHexString(),
|
|
|
|
userId: user._id.toHexString(),
|
|
|
|
userHost: user.host,
|
|
|
|
createdAt: file.uploadDate || new Date(),
|
|
|
|
md5: file.md5,
|
|
|
|
name: file.filename,
|
|
|
|
type: file.contentType,
|
|
|
|
properties: file.metadata.properties,
|
|
|
|
size: file.length,
|
|
|
|
url: file.metadata.url,
|
|
|
|
uri: file.metadata.uri,
|
|
|
|
accessKey: file.metadata.storage.key,
|
|
|
|
folderId: file.metadata.folderId,
|
|
|
|
storedInternal: false,
|
|
|
|
isRemote: false
|
|
|
|
});
|
|
|
|
} else if (!file.metadata.isRemote) {
|
|
|
|
const [temp, clean] = await createTemp();
|
|
|
|
await new Promise(async (res, rej) => {
|
|
|
|
const bucket = await getDriveFileBucket();
|
|
|
|
const readable = bucket.openDownloadStream(file._id);
|
|
|
|
const dest = fs.createWriteStream(temp);
|
2019-04-08 19:42:07 +03:00
|
|
|
readable.pipe(dest);
|
2019-04-08 19:31:54 +03:00
|
|
|
readable.on('end', () => {
|
|
|
|
dest.end();
|
|
|
|
res();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
const key = uuid.v4();
|
|
|
|
const url = InternalStorage.saveFromPath(key, temp);
|
|
|
|
await DriveFiles.save({
|
|
|
|
id: file._id.toHexString(),
|
|
|
|
userId: user._id.toHexString(),
|
|
|
|
userHost: user.host,
|
|
|
|
createdAt: file.uploadDate || new Date(),
|
|
|
|
md5: file.md5,
|
|
|
|
name: file.filename,
|
|
|
|
type: file.contentType,
|
|
|
|
properties: file.metadata.properties,
|
|
|
|
size: file.length,
|
|
|
|
url: url,
|
|
|
|
uri: file.metadata.uri,
|
|
|
|
accessKey: key,
|
|
|
|
folderId: file.metadata.folderId,
|
|
|
|
storedInternal: true,
|
|
|
|
isRemote: false
|
|
|
|
});
|
|
|
|
clean();
|
|
|
|
} else {
|
|
|
|
await DriveFiles.save({
|
|
|
|
id: file._id.toHexString(),
|
|
|
|
userId: user._id.toHexString(),
|
|
|
|
userHost: user.host,
|
|
|
|
createdAt: file.uploadDate || new Date(),
|
|
|
|
md5: file.md5,
|
|
|
|
name: file.filename,
|
|
|
|
type: file.contentType,
|
|
|
|
properties: file.metadata.properties,
|
|
|
|
size: file.length,
|
|
|
|
url: file.metadata.url,
|
|
|
|
uri: file.metadata.uri,
|
|
|
|
accessKey: null,
|
|
|
|
folderId: file.metadata.folderId,
|
|
|
|
storedInternal: false,
|
|
|
|
isRemote: true
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2019-04-08 14:33:42 +03:00
|
|
|
|
2019-04-09 06:31:45 +03:00
|
|
|
async function migrateNote(note: any) {
|
|
|
|
await Notes.insert({
|
|
|
|
id: note._id.toHexString(),
|
|
|
|
createdAt: note.createdAt || new Date(),
|
|
|
|
text: note.text,
|
|
|
|
cw: note.cw || null,
|
|
|
|
tags: note.tags || [],
|
|
|
|
userId: note.userId.toHexString(),
|
|
|
|
viaMobile: note.viaMobile || false,
|
|
|
|
geo: note.geo,
|
|
|
|
appId: null,
|
|
|
|
visibility: note.visibility || 'public',
|
|
|
|
visibleUserIds: note.visibleUserIds ? note.visibleUserIds.map((id: any) => id.toHexString()) : [],
|
|
|
|
replyId: note.replyId ? note.replyId.toHexString() : null,
|
|
|
|
renoteId: note.renoteId ? note.renoteId.toHexString() : null,
|
|
|
|
userHost: null,
|
|
|
|
fileIds: note.fileIds ? note.fileIds.map((id: any) => id.toHexString()) : [],
|
|
|
|
localOnly: note.localOnly || false
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-04-08 14:33:42 +03:00
|
|
|
const allUsersCount = await _User.count();
|
|
|
|
for (let i = 0; i < allUsersCount; i++) {
|
|
|
|
const user = await _User.findOne({}, {
|
|
|
|
skip: i
|
|
|
|
});
|
2019-04-09 06:31:45 +03:00
|
|
|
await Users.insert({
|
2019-04-08 14:33:42 +03:00
|
|
|
id: user._id.toHexString(),
|
|
|
|
createdAt: user.createdAt || new Date(),
|
|
|
|
username: user.username,
|
|
|
|
usernameLower: user.username.toLowerCase(),
|
|
|
|
host: user.host,
|
|
|
|
token: generateUserToken(),
|
|
|
|
password: user.password,
|
|
|
|
isAdmin: user.isAdmin,
|
|
|
|
autoAcceptFollowed: true,
|
2019-04-08 17:24:44 +03:00
|
|
|
autoWatch: false,
|
|
|
|
name: user.name,
|
2019-04-08 19:03:58 +03:00
|
|
|
location: user.profile ? user.profile.location : null,
|
|
|
|
birthday: user.profile ? user.profile.birthday : null,
|
2019-04-08 17:24:44 +03:00
|
|
|
followersCount: user.followersCount,
|
|
|
|
followingCount: user.followingCount,
|
|
|
|
notesCount: user.notesCount,
|
|
|
|
description: user.description,
|
|
|
|
isBot: user.isBot,
|
|
|
|
isCat: user.isCat,
|
|
|
|
isVerified: user.isVerified,
|
|
|
|
inbox: user.inbox,
|
|
|
|
sharedInbox: user.sharedInbox,
|
|
|
|
uri: user.uri,
|
|
|
|
});
|
2019-04-09 06:31:45 +03:00
|
|
|
console.log(`USER (${i + 1}/${allUsersCount}) ${user._id} ${chalk.green('DONE')}`);
|
2019-04-08 17:24:44 +03:00
|
|
|
}
|
|
|
|
|
2019-04-08 19:31:54 +03:00
|
|
|
const allDriveFoldersCount = await _DriveFolder.count();
|
|
|
|
for (let i = 0; i < allDriveFoldersCount; i++) {
|
|
|
|
const folder = await _DriveFolder.findOne({}, {
|
|
|
|
skip: i
|
|
|
|
});
|
|
|
|
await DriveFolders.save({
|
|
|
|
id: folder._id.toHexString(),
|
|
|
|
createdAt: folder.createdAt || new Date(),
|
|
|
|
name: folder.name,
|
|
|
|
parentId: folder.parentId,
|
|
|
|
});
|
2019-04-09 06:31:45 +03:00
|
|
|
console.log(`DRIVEFOLDER (${i + 1}/${allDriveFoldersCount}) ${folder._id} ${chalk.green('DONE')}`);
|
2019-04-08 19:31:54 +03:00
|
|
|
}
|
|
|
|
|
2019-04-08 17:24:44 +03:00
|
|
|
const allDriveFilesCount = await _DriveFile.count();
|
|
|
|
for (let i = 0; i < allDriveFilesCount; i++) {
|
|
|
|
const file = await _DriveFile.findOne({}, {
|
|
|
|
skip: i
|
|
|
|
});
|
2019-04-08 19:31:54 +03:00
|
|
|
try {
|
|
|
|
await migrateDriveFile(file);
|
2019-04-09 06:31:45 +03:00
|
|
|
console.log(`DRIVEFILE (${i + 1}/${allDriveFilesCount}) ${file._id} ${chalk.green('DONE')}`);
|
|
|
|
} catch (e) {
|
|
|
|
console.log(`DRIVEFILE (${i + 1}/${allDriveFilesCount}) ${file._id} ${chalk.red('ERR')}`);
|
|
|
|
console.error(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const allNotesCount = await _Note.count({
|
|
|
|
'_user.host': null
|
|
|
|
});
|
|
|
|
for (let i = 0; i < allNotesCount; i++) {
|
|
|
|
const note = await _Note.findOne({
|
|
|
|
'_user.host': null
|
|
|
|
}, {
|
|
|
|
skip: i
|
|
|
|
});
|
|
|
|
try {
|
|
|
|
await migrateNote(note);
|
|
|
|
console.log(`NOTE (${i + 1}/${allNotesCount}) ${note._id} ${chalk.green('DONE')}`);
|
2019-04-08 19:31:54 +03:00
|
|
|
} catch (e) {
|
2019-04-09 06:31:45 +03:00
|
|
|
console.log(`NOTE (${i + 1}/${allNotesCount}) ${note._id} ${chalk.red('ERR')}`);
|
|
|
|
console.error(e);
|
2019-04-08 19:03:58 +03:00
|
|
|
}
|
2019-04-08 14:33:42 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
main();
|