From 18b1ef29adc6166c2b1a327b378c3e159a18b80c Mon Sep 17 00:00:00 2001 From: otofune Date: Mon, 6 Nov 2017 15:18:45 +0900 Subject: migration to GridFS's DriveFile --- src/api/endpoints/drive.ts | 6 ++--- src/api/endpoints/drive/files.ts | 9 ++++---- src/api/endpoints/drive/files/find.ts | 10 ++++----- src/api/endpoints/drive/files/show.ts | 6 ++--- src/api/endpoints/drive/files/update.ts | 31 +++++++++++++++----------- src/api/endpoints/messaging/messages/create.ts | 6 ++--- src/api/endpoints/posts/create.ts | 6 ++--- src/api/endpoints/posts/timeline.ts | 24 ++++++++++---------- 8 files changed, 49 insertions(+), 49 deletions(-) (limited to 'src/api/endpoints') diff --git a/src/api/endpoints/drive.ts b/src/api/endpoints/drive.ts index 41ad6301d7..b9c4e3e506 100644 --- a/src/api/endpoints/drive.ts +++ b/src/api/endpoints/drive.ts @@ -14,16 +14,16 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Calculate drive usage const usage = ((await DriveFile .aggregate([ - { $match: { user_id: user._id } }, + { $match: { metadata: { user_id: user._id } } }, { $project: { - datasize: true + length: true } }, { $group: { _id: null, - usage: { $sum: '$datasize' } + usage: { $sum: '$length' } } } ]))[0] || { diff --git a/src/api/endpoints/drive/files.ts b/src/api/endpoints/drive/files.ts index a68ae34817..eb0bfe6ba5 100644 --- a/src/api/endpoints/drive/files.ts +++ b/src/api/endpoints/drive/files.ts @@ -40,8 +40,10 @@ module.exports = (params, user, app) => new Promise(async (res, rej) => { _id: -1 }; const query = { - user_id: user._id, - folder_id: folderId + metadata: { + user_id: user._id, + folder_id: folderId + } } as any; if (sinceId) { sort._id = 1; @@ -57,9 +59,6 @@ module.exports = (params, user, app) => new Promise(async (res, rej) => { // Issue query const files = await DriveFile .find(query, { - fields: { - data: false - }, limit: limit, sort: sort }); diff --git a/src/api/endpoints/drive/files/find.ts b/src/api/endpoints/drive/files/find.ts index cd0b33f2ca..255faf94ec 100644 --- a/src/api/endpoints/drive/files/find.ts +++ b/src/api/endpoints/drive/files/find.ts @@ -24,12 +24,10 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Issue query const files = await DriveFile .find({ - name: name, - user_id: user._id, - folder_id: folderId - }, { - fields: { - data: false + metadata: { + name: name, + user_id: user._id, + folder_id: folderId } }); diff --git a/src/api/endpoints/drive/files/show.ts b/src/api/endpoints/drive/files/show.ts index 8dbc297e4f..9135a04c57 100644 --- a/src/api/endpoints/drive/files/show.ts +++ b/src/api/endpoints/drive/files/show.ts @@ -21,10 +21,8 @@ module.exports = (params, user) => new Promise(async (res, rej) => { const file = await DriveFile .findOne({ _id: fileId, - user_id: user._id - }, { - fields: { - data: false + metadata: { + user_id: user._id } }); diff --git a/src/api/endpoints/drive/files/update.ts b/src/api/endpoints/drive/files/update.ts index 1cfbdd8f0b..c4d2673688 100644 --- a/src/api/endpoints/drive/files/update.ts +++ b/src/api/endpoints/drive/files/update.ts @@ -20,25 +20,29 @@ module.exports = (params, user) => new Promise(async (res, rej) => { const [fileId, fileIdErr] = $(params.file_id).id().$; if (fileIdErr) return rej('invalid file_id param'); + console.dir(user) + // Fetch file const file = await DriveFile .findOne({ _id: fileId, - user_id: user._id - }, { - fields: { - data: false + metadata: { + user_id: user._id } }); + console.dir(file) + if (file === null) { return rej('file-not-found'); } + const updateQuery: any = {} + // Get 'name' parameter const [name, nameErr] = $(params.name).optional.string().pipe(validateFileName).$; if (nameErr) return rej('invalid name param'); - if (name) file.name = name; + if (name) updateQuery.name = name; // Get 'folder_id' parameter const [folderId, folderIdErr] = $(params.folder_id).optional.nullable.id().$; @@ -46,7 +50,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { if (folderId !== undefined) { if (folderId === null) { - file.folder_id = null; + updateQuery.folder_id = null; } else { // Fetch folder const folder = await DriveFolder @@ -59,19 +63,20 @@ module.exports = (params, user) => new Promise(async (res, rej) => { return rej('folder-not-found'); } - file.folder_id = folder._id; + updateQuery.folder_id = folder._id; } } - DriveFile.update(file._id, { - $set: { - name: file.name, - folder_id: file.folder_id - } + const updated = await DriveFile.update(file._id, { + $set: { metadata: updateQuery } }); + console.dir(updated) + // Serialize - const fileObj = await serialize(file); + const fileObj = await serialize(updated); + + console.dir(fileObj) // Response res(fileObj); diff --git a/src/api/endpoints/messaging/messages/create.ts b/src/api/endpoints/messaging/messages/create.ts index 8af55d850c..1d186268fb 100644 --- a/src/api/endpoints/messaging/messages/create.ts +++ b/src/api/endpoints/messaging/messages/create.ts @@ -54,9 +54,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => { if (fileId !== undefined) { file = await DriveFile.findOne({ _id: fileId, - user_id: user._id - }, { - data: false + metadata: { + user_id: user._id + } }); if (file === null) { diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts index f982b9ee93..1507639776 100644 --- a/src/api/endpoints/posts/create.ts +++ b/src/api/endpoints/posts/create.ts @@ -44,9 +44,9 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { // SELECT _id const entity = await DriveFile.findOne({ _id: mediaId, - user_id: user._id - }, { - _id: true + metadata: { + user_id: user._id + } }); if (entity === null) { diff --git a/src/api/endpoints/posts/timeline.ts b/src/api/endpoints/posts/timeline.ts index aa5aff5ba5..496de62b69 100644 --- a/src/api/endpoints/posts/timeline.ts +++ b/src/api/endpoints/posts/timeline.ts @@ -2,6 +2,7 @@ * Module dependencies */ import $ from 'cafy'; +import rap from '@prezzemolo/rap'; import Post from '../../models/post'; import ChannelWatching from '../../models/channel-watching'; import getFriends from '../../common/get-friends'; @@ -33,14 +34,15 @@ module.exports = (params, user, app) => new Promise(async (res, rej) => { return rej('cannot set since_id and max_id'); } - // ID list of the user itself and other users who the user follows - const followingIds = await getFriends(user._id); - - // Watchしているチャンネルを取得 - const watches = await ChannelWatching.find({ - user_id: user._id, - // 削除されたドキュメントは除く - deleted_at: { $exists: false } + const { followingIds, watchChannelIds } = await rap({ + // ID list of the user itself and other users who the user follows + followingIds: getFriends(user._id), + // Watchしているチャンネルを取得 + watchChannelIds: ChannelWatching.find({ + user_id: user._id, + // 削除されたドキュメントは除く + deleted_at: { $exists: false } + }).then(watches => watches.map(w => w.channel_id)) }); //#region Construct query @@ -65,7 +67,7 @@ module.exports = (params, user, app) => new Promise(async (res, rej) => { }, { // Watchしているチャンネルへの投稿 channel_id: { - $in: watches.map(w => w.channel_id) + $in: watchChannelIds } }] } as any; @@ -90,7 +92,5 @@ module.exports = (params, user, app) => new Promise(async (res, rej) => { }); // Serialize - res(await Promise.all(timeline.map(async post => - await serialize(post, user) - ))); + res(Promise.all(timeline.map(post => serialize(post, user)))); }); -- cgit v1.2.3-freya From 0ee6d6592113c5b2df071f4451cb1c1697b59d61 Mon Sep 17 00:00:00 2001 From: otofune Date: Mon, 6 Nov 2017 15:45:21 +0900 Subject: fix timeline --- src/api/endpoints/posts/timeline.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/api/endpoints') diff --git a/src/api/endpoints/posts/timeline.ts b/src/api/endpoints/posts/timeline.ts index 496de62b69..19578e59b1 100644 --- a/src/api/endpoints/posts/timeline.ts +++ b/src/api/endpoints/posts/timeline.ts @@ -92,5 +92,5 @@ module.exports = (params, user, app) => new Promise(async (res, rej) => { }); // Serialize - res(Promise.all(timeline.map(post => serialize(post, user)))); + res(await Promise.all(timeline.map(post => serialize(post, user)))); }); -- cgit v1.2.3-freya From 7b1fc2c5d62e229542e9411a29e078236a9d96db Mon Sep 17 00:00:00 2001 From: otofune Date: Mon, 6 Nov 2017 15:55:47 +0900 Subject: api - endpoint:timeline: unneed promise wrapping --- src/api/endpoints/posts/timeline.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src/api/endpoints') diff --git a/src/api/endpoints/posts/timeline.ts b/src/api/endpoints/posts/timeline.ts index 19578e59b1..978825a109 100644 --- a/src/api/endpoints/posts/timeline.ts +++ b/src/api/endpoints/posts/timeline.ts @@ -16,22 +16,22 @@ import serialize from '../../serializers/post'; * @param {any} app * @return {Promise} */ -module.exports = (params, user, app) => new Promise(async (res, rej) => { +module.exports = async (params, user, app) => { // Get 'limit' parameter const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$; - if (limitErr) return rej('invalid limit param'); + if (limitErr) throw 'invalid limit param'; // Get 'since_id' parameter const [sinceId, sinceIdErr] = $(params.since_id).optional.id().$; - if (sinceIdErr) return rej('invalid since_id param'); + if (sinceIdErr) throw 'invalid since_id param'; // Get 'max_id' parameter const [maxId, maxIdErr] = $(params.max_id).optional.id().$; - if (maxIdErr) return rej('invalid max_id param'); + if (maxIdErr) throw 'invalid max_id param'; // Check if both of since_id and max_id is specified if (sinceId && maxId) { - return rej('cannot set since_id and max_id'); + throw 'cannot set since_id and max_id'; } const { followingIds, watchChannelIds } = await rap({ @@ -92,5 +92,6 @@ module.exports = (params, user, app) => new Promise(async (res, rej) => { }); // Serialize - res(await Promise.all(timeline.map(post => serialize(post, user)))); -}); + const _timeline = await Promise.all(timeline.map(post => serialize(post, user))) + return _timeline +}; -- cgit v1.2.3-freya From 5279d062df205514f1f3cf95e3aab4fee425a3e4 Mon Sep 17 00:00:00 2001 From: otofune Date: Mon, 6 Nov 2017 16:09:51 +0900 Subject: fix --- src/api/endpoints/drive/files.ts | 18 +++++++++--------- src/api/endpoints/drive/files/show.ts | 14 ++++++++------ src/api/endpoints/drive/folders/find.ts | 3 +-- src/api/serializers/drive-file.ts | 2 ++ 4 files changed, 20 insertions(+), 17 deletions(-) (limited to 'src/api/endpoints') diff --git a/src/api/endpoints/drive/files.ts b/src/api/endpoints/drive/files.ts index eb0bfe6ba5..41687c4993 100644 --- a/src/api/endpoints/drive/files.ts +++ b/src/api/endpoints/drive/files.ts @@ -13,27 +13,27 @@ import serialize from '../../serializers/drive-file'; * @param {any} app * @return {Promise} */ -module.exports = (params, user, app) => new Promise(async (res, rej) => { +module.exports = async (params, user, app) => { // Get 'limit' parameter const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$; - if (limitErr) return rej('invalid limit param'); + if (limitErr) throw 'invalid limit param'; // Get 'since_id' parameter const [sinceId, sinceIdErr] = $(params.since_id).optional.id().$; - if (sinceIdErr) return rej('invalid since_id param'); + if (sinceIdErr) throw 'invalid since_id param'; // Get 'max_id' parameter const [maxId, maxIdErr] = $(params.max_id).optional.id().$; - if (maxIdErr) return rej('invalid max_id param'); + if (maxIdErr) throw 'invalid max_id param'; // Check if both of since_id and max_id is specified if (sinceId && maxId) { - return rej('cannot set since_id and max_id'); + throw 'cannot set since_id and max_id'; } // Get 'folder_id' parameter const [folderId = null, folderIdErr] = $(params.folder_id).optional.nullable.id().$; - if (folderIdErr) return rej('invalid folder_id param'); + if (folderIdErr) throw 'invalid folder_id param'; // Construct query const sort = { @@ -64,6 +64,6 @@ module.exports = (params, user, app) => new Promise(async (res, rej) => { }); // Serialize - res(await Promise.all(files.map(async file => - await serialize(file)))); -}); + const _files = await Promise.all(files.map(file => serialize(file))); + return _files +}; diff --git a/src/api/endpoints/drive/files/show.ts b/src/api/endpoints/drive/files/show.ts index 9135a04c57..8830346008 100644 --- a/src/api/endpoints/drive/files/show.ts +++ b/src/api/endpoints/drive/files/show.ts @@ -12,10 +12,10 @@ import serialize from '../../../serializers/drive-file'; * @param {any} user * @return {Promise} */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = async (params, user) => { // Get 'file_id' parameter const [fileId, fileIdErr] = $(params.file_id).id().$; - if (fileIdErr) return rej('invalid file_id param'); + if (fileIdErr) throw 'invalid file_id param'; // Fetch file const file = await DriveFile @@ -27,11 +27,13 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }); if (file === null) { - return rej('file-not-found'); + throw 'file-not-found'; } // Serialize - res(await serialize(file, { + const _file = await serialize(file, { detail: true - })); -}); + }); + + return _file +}; diff --git a/src/api/endpoints/drive/folders/find.ts b/src/api/endpoints/drive/folders/find.ts index cdf055839a..a5eb8e015d 100644 --- a/src/api/endpoints/drive/folders/find.ts +++ b/src/api/endpoints/drive/folders/find.ts @@ -30,6 +30,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }); // Serialize - res(await Promise.all(folders.map(async folder => - await serialize(folder)))); + res(await Promise.all(folders.map(folder => serialize(folder)))); }); diff --git a/src/api/serializers/drive-file.ts b/src/api/serializers/drive-file.ts index f98cdaa599..9858c3b3c7 100644 --- a/src/api/serializers/drive-file.ts +++ b/src/api/serializers/drive-file.ts @@ -25,6 +25,8 @@ export default ( detail: false }, options); + if (!file) return reject('invalid file arg.') + let _file: any; // Populate the file if 'file' is ID -- cgit v1.2.3-freya From 64be0d6deddef4b8caced377dc22f94425cc4358 Mon Sep 17 00:00:00 2001 From: otofune Date: Mon, 6 Nov 2017 16:22:18 +0900 Subject: MongoDBの階層構造検索に関する思い違いの修正 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/endpoints/drive.ts | 2 +- src/api/endpoints/drive/files.ts | 6 ++---- src/api/endpoints/drive/files/find.ts | 8 +++----- src/api/endpoints/drive/files/show.ts | 4 +--- src/api/endpoints/drive/files/update.ts | 19 +++++-------------- src/api/endpoints/messaging/messages/create.ts | 4 +--- src/api/endpoints/posts/create.ts | 4 +--- src/api/serializers/drive-folder.ts | 4 +--- 8 files changed, 15 insertions(+), 36 deletions(-) (limited to 'src/api/endpoints') diff --git a/src/api/endpoints/drive.ts b/src/api/endpoints/drive.ts index b9c4e3e506..d92473633a 100644 --- a/src/api/endpoints/drive.ts +++ b/src/api/endpoints/drive.ts @@ -14,7 +14,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Calculate drive usage const usage = ((await DriveFile .aggregate([ - { $match: { metadata: { user_id: user._id } } }, + { $match: { 'metadata.user_id': user._id } }, { $project: { length: true diff --git a/src/api/endpoints/drive/files.ts b/src/api/endpoints/drive/files.ts index 41687c4993..035916b309 100644 --- a/src/api/endpoints/drive/files.ts +++ b/src/api/endpoints/drive/files.ts @@ -40,10 +40,8 @@ module.exports = async (params, user, app) => { _id: -1 }; const query = { - metadata: { - user_id: user._id, - folder_id: folderId - } + 'metadata.user_id': user._id, + 'metadata.folder_id': folderId } as any; if (sinceId) { sort._id = 1; diff --git a/src/api/endpoints/drive/files/find.ts b/src/api/endpoints/drive/files/find.ts index 255faf94ec..1c818131d7 100644 --- a/src/api/endpoints/drive/files/find.ts +++ b/src/api/endpoints/drive/files/find.ts @@ -24,11 +24,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Issue query const files = await DriveFile .find({ - metadata: { - name: name, - user_id: user._id, - folder_id: folderId - } + 'metadata.name': name, + 'metadata.user_id': user._id, + 'metadata.folder_id': folderId }); // Serialize diff --git a/src/api/endpoints/drive/files/show.ts b/src/api/endpoints/drive/files/show.ts index 8830346008..0a19b19939 100644 --- a/src/api/endpoints/drive/files/show.ts +++ b/src/api/endpoints/drive/files/show.ts @@ -21,9 +21,7 @@ module.exports = async (params, user) => { const file = await DriveFile .findOne({ _id: fileId, - metadata: { - user_id: user._id - } + 'metadata.user_id': user._id }); if (file === null) { diff --git a/src/api/endpoints/drive/files/update.ts b/src/api/endpoints/drive/files/update.ts index c4d2673688..7a6d2562fb 100644 --- a/src/api/endpoints/drive/files/update.ts +++ b/src/api/endpoints/drive/files/update.ts @@ -20,19 +20,14 @@ module.exports = (params, user) => new Promise(async (res, rej) => { const [fileId, fileIdErr] = $(params.file_id).id().$; if (fileIdErr) return rej('invalid file_id param'); - console.dir(user) // Fetch file const file = await DriveFile .findOne({ _id: fileId, - metadata: { - user_id: user._id - } + 'metadata.user_id': user._id }); - console.dir(file) - if (file === null) { return rej('file-not-found'); } @@ -42,7 +37,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Get 'name' parameter const [name, nameErr] = $(params.name).optional.string().pipe(validateFileName).$; if (nameErr) return rej('invalid name param'); - if (name) updateQuery.name = name; + if (name) updateQuery['metadata.name'] = name; // Get 'folder_id' parameter const [folderId, folderIdErr] = $(params.folder_id).optional.nullable.id().$; @@ -50,7 +45,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { if (folderId !== undefined) { if (folderId === null) { - updateQuery.folder_id = null; + updateQuery['metadata.folder_id'] = null; } else { // Fetch folder const folder = await DriveFolder @@ -63,21 +58,17 @@ module.exports = (params, user) => new Promise(async (res, rej) => { return rej('folder-not-found'); } - updateQuery.folder_id = folder._id; + updateQuery['metadata.folder_id'] = folder._id; } } const updated = await DriveFile.update(file._id, { - $set: { metadata: updateQuery } + $set: { updateQuery } }); - console.dir(updated) - // Serialize const fileObj = await serialize(updated); - console.dir(fileObj) - // Response res(fileObj); diff --git a/src/api/endpoints/messaging/messages/create.ts b/src/api/endpoints/messaging/messages/create.ts index 1d186268fb..149852c093 100644 --- a/src/api/endpoints/messaging/messages/create.ts +++ b/src/api/endpoints/messaging/messages/create.ts @@ -54,9 +54,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { if (fileId !== undefined) { file = await DriveFile.findOne({ _id: fileId, - metadata: { - user_id: user._id - } + 'metadata.user_id': user._id }); if (file === null) { diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts index 1507639776..4f4b7e2e83 100644 --- a/src/api/endpoints/posts/create.ts +++ b/src/api/endpoints/posts/create.ts @@ -44,9 +44,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { // SELECT _id const entity = await DriveFile.findOne({ _id: mediaId, - metadata: { - user_id: user._id - } + 'metadata.user_id': user._id }); if (entity === null) { diff --git a/src/api/serializers/drive-folder.ts b/src/api/serializers/drive-folder.ts index 3b5f61aeed..6ebf454a28 100644 --- a/src/api/serializers/drive-folder.ts +++ b/src/api/serializers/drive-folder.ts @@ -44,9 +44,7 @@ const self = ( }); const childFilesCount = await DriveFile.count({ - metadata: { - folder_id: _folder.id - } + 'metadata.folder_id': _folder.id }); _folder.folders_count = childFoldersCount; -- cgit v1.2.3-freya From d5cc4cc9c28eb6a981ce37859def97cd7c57abc6 Mon Sep 17 00:00:00 2001 From: otofune Date: Mon, 6 Nov 2017 16:32:01 +0900 Subject: fix lint (automattic) --- src/api/common/add-file-to-drive.ts | 20 +++++++++--------- src/api/endpoints/drive/files.ts | 2 +- src/api/endpoints/drive/files/show.ts | 2 +- src/api/endpoints/drive/files/update.ts | 3 +-- src/api/endpoints/posts/timeline.ts | 4 ++-- src/api/models/drive-file.ts | 10 ++++----- src/api/serializers/drive-file.ts | 4 ++-- src/db/mongodb.ts | 18 ++++++++--------- src/file/server.ts | 36 ++++++++++++++++----------------- 9 files changed, 49 insertions(+), 50 deletions(-) (limited to 'src/api/endpoints') diff --git a/src/api/common/add-file-to-drive.ts b/src/api/common/add-file-to-drive.ts index dff2d52356..f9c22ccacd 100644 --- a/src/api/common/add-file-to-drive.ts +++ b/src/api/common/add-file-to-drive.ts @@ -14,16 +14,16 @@ import { Duplex } from 'stream'; const log = debug('misskey:register-drive-file'); const addToGridFS = (name, binary, metadata): Promise => new Promise(async (resolve, reject) => { - const dataStream = new Duplex() - dataStream.push(binary) - dataStream.push(null) - - const bucket = await getGridFSBucket() - const writeStream = bucket.openUploadStream(name, { metadata }) - writeStream.once('finish', (doc) => { resolve(doc) }) - writeStream.on('error', reject) - dataStream.pipe(writeStream) -}) + const dataStream = new Duplex(); + dataStream.push(binary); + dataStream.push(null); + + const bucket = await getGridFSBucket(); + const writeStream = bucket.openUploadStream(name, { metadata }); + writeStream.once('finish', (doc) => { resolve(doc); }); + writeStream.on('error', reject); + dataStream.pipe(writeStream); +}); /** * Add file to drive diff --git a/src/api/endpoints/drive/files.ts b/src/api/endpoints/drive/files.ts index 035916b309..53b48a8bec 100644 --- a/src/api/endpoints/drive/files.ts +++ b/src/api/endpoints/drive/files.ts @@ -63,5 +63,5 @@ module.exports = async (params, user, app) => { // Serialize const _files = await Promise.all(files.map(file => serialize(file))); - return _files + return _files; }; diff --git a/src/api/endpoints/drive/files/show.ts b/src/api/endpoints/drive/files/show.ts index 0a19b19939..3c7cf774f9 100644 --- a/src/api/endpoints/drive/files/show.ts +++ b/src/api/endpoints/drive/files/show.ts @@ -33,5 +33,5 @@ module.exports = async (params, user) => { detail: true }); - return _file + return _file; }; diff --git a/src/api/endpoints/drive/files/update.ts b/src/api/endpoints/drive/files/update.ts index 7a6d2562fb..4e56b30ace 100644 --- a/src/api/endpoints/drive/files/update.ts +++ b/src/api/endpoints/drive/files/update.ts @@ -20,7 +20,6 @@ module.exports = (params, user) => new Promise(async (res, rej) => { const [fileId, fileIdErr] = $(params.file_id).id().$; if (fileIdErr) return rej('invalid file_id param'); - // Fetch file const file = await DriveFile .findOne({ @@ -32,7 +31,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { return rej('file-not-found'); } - const updateQuery: any = {} + const updateQuery: any = {}; // Get 'name' parameter const [name, nameErr] = $(params.name).optional.string().pipe(validateFileName).$; diff --git a/src/api/endpoints/posts/timeline.ts b/src/api/endpoints/posts/timeline.ts index 978825a109..203413e23a 100644 --- a/src/api/endpoints/posts/timeline.ts +++ b/src/api/endpoints/posts/timeline.ts @@ -92,6 +92,6 @@ module.exports = async (params, user, app) => { }); // Serialize - const _timeline = await Promise.all(timeline.map(post => serialize(post, user))) - return _timeline + const _timeline = await Promise.all(timeline.map(post => serialize(post, user))); + return _timeline; }; diff --git a/src/api/models/drive-file.ts b/src/api/models/drive-file.ts index 79a87f6572..8968d065cd 100644 --- a/src/api/models/drive-file.ts +++ b/src/api/models/drive-file.ts @@ -8,14 +8,14 @@ const collection = monkDb.get('drive_files.files'); export default collection as any; // fuck type definition const getGridFSBucket = async (): Promise => { - const db = await nativeDbConn() + const db = await nativeDbConn(); const bucket = new mongodb.GridFSBucket(db, { bucketName: 'drive_files' - }) - return bucket -} + }); + return bucket; +}; -export { getGridFSBucket } +export { getGridFSBucket }; export function validateFileName(name: string): boolean { return ( diff --git a/src/api/serializers/drive-file.ts b/src/api/serializers/drive-file.ts index e749f80387..2af7db5726 100644 --- a/src/api/serializers/drive-file.ts +++ b/src/api/serializers/drive-file.ts @@ -40,13 +40,13 @@ export default ( _file = deepcopy(file); } - if (!_file) return reject('invalid file arg.') + if (!_file) return reject('invalid file arg.'); // rendered target let _target: any = {}; _target.id = _file._id; - _target.created_at = _file.uploadDate + _target.created_at = _file.uploadDate; _target = Object.assign(_target, _file.metadata); diff --git a/src/db/mongodb.ts b/src/db/mongodb.ts index 75f1a1d3c6..c978e6460f 100644 --- a/src/db/mongodb.ts +++ b/src/db/mongodb.ts @@ -16,7 +16,7 @@ export default db; /** * MongoDB native module (officialy) */ -import * as mongodb from 'mongodb' +import * as mongodb from 'mongodb'; let mdb: mongodb.Db; @@ -25,14 +25,14 @@ const nativeDbConn = async (): Promise => { const db = await ((): Promise => new Promise((resolve, reject) => { mongodb.MongoClient.connect(uri, (e, db) => { - if (e) return reject(e) - resolve(db) - }) - }))() + if (e) return reject(e); + resolve(db); + }); + }))(); - mdb = db + mdb = db; - return db -} + return db; +}; -export { nativeDbConn } +export { nativeDbConn }; diff --git a/src/file/server.ts b/src/file/server.ts index f38599b89c..375f29487d 100644 --- a/src/file/server.ts +++ b/src/file/server.ts @@ -97,7 +97,7 @@ app.get('/:id', async (req, res) => { return; } - const fileId = new mongodb.ObjectID(req.params.id) + const fileId = new mongodb.ObjectID(req.params.id); const file = await DriveFile.findOne({ _id: fileId }); if (file == null) { @@ -105,18 +105,18 @@ app.get('/:id', async (req, res) => { return; } - const bucket = await getGridFSBucket() + const bucket = await getGridFSBucket(); const buffer = await ((id): Promise => new Promise((resolve, reject) => { - const chunks = [] - const readableStream = bucket.openDownloadStream(id) - readableStream.on('data', chunk => { + const chunks = []; + const readableStream = bucket.openDownloadStream(id); + readableStream.on('data', chunk => { chunks.push(chunk); - }) + }); readableStream.on('end', () => { - resolve(Buffer.concat(chunks)) - }) - }))(fileId) + resolve(Buffer.concat(chunks)); + }); + }))(fileId); send(buffer, file.metadata.type, req, res); }); @@ -128,7 +128,7 @@ app.get('/:id/:name', async (req, res) => { return; } - const fileId = new mongodb.ObjectID(req.params.id) + const fileId = new mongodb.ObjectID(req.params.id); const file = await DriveFile.findOne({ _id: fileId }); if (file == null) { @@ -136,18 +136,18 @@ app.get('/:id/:name', async (req, res) => { return; } - const bucket = await getGridFSBucket() + const bucket = await getGridFSBucket(); const buffer = await ((id): Promise => new Promise((resolve, reject) => { - const chunks = [] - const readableStream = bucket.openDownloadStream(id) - readableStream.on('data', chunk => { + const chunks = []; + const readableStream = bucket.openDownloadStream(id); + readableStream.on('data', chunk => { chunks.push(chunk); - }) + }); readableStream.on('end', () => { - resolve(Buffer.concat(chunks)) - }) - }))(fileId) + resolve(Buffer.concat(chunks)); + }); + }))(fileId); send(buffer, file.metadata.type, req, res); }); -- cgit v1.2.3-freya From 3be69a8cb7bacca181fa400f234fd77c1d1d5bde Mon Sep 17 00:00:00 2001 From: otofune Date: Mon, 6 Nov 2017 16:49:07 +0900 Subject: /drive/files/update - return collectly value --- src/api/endpoints/drive/files/update.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'src/api/endpoints') diff --git a/src/api/endpoints/drive/files/update.ts b/src/api/endpoints/drive/files/update.ts index 4e56b30ace..d7b858c2ba 100644 --- a/src/api/endpoints/drive/files/update.ts +++ b/src/api/endpoints/drive/files/update.ts @@ -31,12 +31,10 @@ module.exports = (params, user) => new Promise(async (res, rej) => { return rej('file-not-found'); } - const updateQuery: any = {}; - // Get 'name' parameter const [name, nameErr] = $(params.name).optional.string().pipe(validateFileName).$; if (nameErr) return rej('invalid name param'); - if (name) updateQuery['metadata.name'] = name; + if (name) file.metadata.name = name; // Get 'folder_id' parameter const [folderId, folderIdErr] = $(params.folder_id).optional.nullable.id().$; @@ -44,7 +42,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { if (folderId !== undefined) { if (folderId === null) { - updateQuery['metadata.folder_id'] = null; + file.metadata.folder_id = null; } else { // Fetch folder const folder = await DriveFolder @@ -57,16 +55,19 @@ module.exports = (params, user) => new Promise(async (res, rej) => { return rej('folder-not-found'); } - updateQuery['metadata.folder_id'] = folder._id; + file.metadata.folder_id = folder._id; } } - const updated = await DriveFile.update(file._id, { - $set: { updateQuery } + await DriveFile.update(file._id, { + $set: { + 'metadata.name': file.metadata.name, + 'metadata.folder_id': file.metadata.folder_id + } }); // Serialize - const fileObj = await serialize(updated); + const fileObj = await serialize(file); // Response res(fileObj); -- cgit v1.2.3-freya From c1fc3b9f6ec176999932958a7856d160317b7762 Mon Sep 17 00:00:00 2001 From: otofune Date: Mon, 6 Nov 2017 18:30:49 +0900 Subject: add safety guard to serializers & fix importing uncorrect serializer --- src/api/endpoints/drive/folders/update.ts | 2 +- src/api/serializers/post.ts | 2 ++ src/api/serializers/user.ts | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src/api/endpoints') diff --git a/src/api/endpoints/drive/folders/update.ts b/src/api/endpoints/drive/folders/update.ts index eec2757878..4f2e3d2a7a 100644 --- a/src/api/endpoints/drive/folders/update.ts +++ b/src/api/endpoints/drive/folders/update.ts @@ -4,7 +4,7 @@ import $ from 'cafy'; import DriveFolder from '../../../models/drive-folder'; import { isValidFolderName } from '../../../models/drive-folder'; -import serialize from '../../../serializers/drive-file'; +import serialize from '../../../serializers/drive-folder'; import event from '../../../event'; /** diff --git a/src/api/serializers/post.ts b/src/api/serializers/post.ts index 5788b226f4..5a63384f0e 100644 --- a/src/api/serializers/post.ts +++ b/src/api/serializers/post.ts @@ -57,6 +57,8 @@ const self = async ( _post = deepcopy(post); } + if (!_post) throw 'invalid post arg.'; + const id = _post._id; // Rename _id to id diff --git a/src/api/serializers/user.ts b/src/api/serializers/user.ts index d00f073897..0d24d6cc04 100644 --- a/src/api/serializers/user.ts +++ b/src/api/serializers/user.ts @@ -56,6 +56,8 @@ export default ( _user = deepcopy(user); } + if (!_user) return reject('invalid user arg.'); + // Me const meId: mongo.ObjectID = me ? mongo.ObjectID.prototype.isPrototypeOf(me) -- cgit v1.2.3-freya From 26d4ebfe1a22615f4f69bf94cc6872659e6e4125 Mon Sep 17 00:00:00 2001 From: syuilo Date: Mon, 6 Nov 2017 20:03:50 +0900 Subject: Refactor --- src/api/endpoints/posts/timeline.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/api/endpoints') diff --git a/src/api/endpoints/posts/timeline.ts b/src/api/endpoints/posts/timeline.ts index 203413e23a..7af435e82a 100644 --- a/src/api/endpoints/posts/timeline.ts +++ b/src/api/endpoints/posts/timeline.ts @@ -34,11 +34,11 @@ module.exports = async (params, user, app) => { throw 'cannot set since_id and max_id'; } - const { followingIds, watchChannelIds } = await rap({ + const { followingIds, watchingChannelIds } = await rap({ // ID list of the user itself and other users who the user follows followingIds: getFriends(user._id), // Watchしているチャンネルを取得 - watchChannelIds: ChannelWatching.find({ + watchingChannelIds: ChannelWatching.find({ user_id: user._id, // 削除されたドキュメントは除く deleted_at: { $exists: false } @@ -67,7 +67,7 @@ module.exports = async (params, user, app) => { }, { // Watchしているチャンネルへの投稿 channel_id: { - $in: watchChannelIds + $in: watchingChannelIds } }] } as any; @@ -92,6 +92,5 @@ module.exports = async (params, user, app) => { }); // Serialize - const _timeline = await Promise.all(timeline.map(post => serialize(post, user))); - return _timeline; + return await Promise.all(timeline.map(post => serialize(post, user))); }; -- cgit v1.2.3-freya From fb422b4d603c53a70712caba55b35a48a8c2e619 Mon Sep 17 00:00:00 2001 From: otofune Date: Tue, 7 Nov 2017 09:30:51 +0900 Subject: use 'name' param as GridFS file's 'filename' --- src/api/common/add-file-to-drive.ts | 3 +-- src/api/endpoints/drive/files/find.ts | 2 +- src/api/endpoints/drive/files/update.ts | 4 ++-- src/api/serializers/drive-file.ts | 1 + src/file/server.ts | 2 +- tools/migration/use-gridfs.js | 4 +++- 6 files changed, 9 insertions(+), 7 deletions(-) (limited to 'src/api/endpoints') diff --git a/src/api/common/add-file-to-drive.ts b/src/api/common/add-file-to-drive.ts index f9c22ccacd..e1baf08191 100644 --- a/src/api/common/add-file-to-drive.ts +++ b/src/api/common/add-file-to-drive.ts @@ -144,11 +144,10 @@ export default ( } // Create DriveFile document - const file = await addToGridFS(`${user._id}/${name}`, data, { + const file = await addToGridFS(name, data, { user_id: user._id, folder_id: folder !== null ? folder._id : null, type: mime, - name: name, comment: comment, properties: properties }); diff --git a/src/api/endpoints/drive/files/find.ts b/src/api/endpoints/drive/files/find.ts index 1c818131d7..a1cdf1643e 100644 --- a/src/api/endpoints/drive/files/find.ts +++ b/src/api/endpoints/drive/files/find.ts @@ -24,7 +24,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Issue query const files = await DriveFile .find({ - 'metadata.name': name, + filename: name, 'metadata.user_id': user._id, 'metadata.folder_id': folderId }); diff --git a/src/api/endpoints/drive/files/update.ts b/src/api/endpoints/drive/files/update.ts index d7b858c2ba..f265142c4d 100644 --- a/src/api/endpoints/drive/files/update.ts +++ b/src/api/endpoints/drive/files/update.ts @@ -34,7 +34,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Get 'name' parameter const [name, nameErr] = $(params.name).optional.string().pipe(validateFileName).$; if (nameErr) return rej('invalid name param'); - if (name) file.metadata.name = name; + if (name) file.filename = name; // Get 'folder_id' parameter const [folderId, folderIdErr] = $(params.folder_id).optional.nullable.id().$; @@ -61,7 +61,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { await DriveFile.update(file._id, { $set: { - 'metadata.name': file.metadata.name, + filename: file.filename, 'metadata.folder_id': file.metadata.folder_id } }); diff --git a/src/api/serializers/drive-file.ts b/src/api/serializers/drive-file.ts index 2af7db5726..57b74cd975 100644 --- a/src/api/serializers/drive-file.ts +++ b/src/api/serializers/drive-file.ts @@ -47,6 +47,7 @@ export default ( _target.id = _file._id; _target.created_at = _file.uploadDate; + _target.name = _file.filename; _target = Object.assign(_target, _file.metadata); diff --git a/src/file/server.ts b/src/file/server.ts index 1152b650be..39c2cdd2a1 100644 --- a/src/file/server.ts +++ b/src/file/server.ts @@ -97,7 +97,7 @@ async function sendFileById(req: express.Request, res: express.Response): Promis const file = await DriveFile.findOne({ _id: fileId }); // validate name - if (req.params.name !== undefined && req.params.name !== file.metadata.name) { + if (req.params.name !== undefined && req.params.name !== file.filename) { res.status(404).send('there is no file has given name'); return; } diff --git a/tools/migration/use-gridfs.js b/tools/migration/use-gridfs.js index d41514416c..148f9be261 100644 --- a/tools/migration/use-gridfs.js +++ b/tools/migration/use-gridfs.js @@ -21,15 +21,17 @@ const migrateToGridFS = async (doc) => { const id = doc._id const buffer = doc.data.buffer const created_at = doc.created_at + const name = doc.name delete doc._id delete doc.created_at delete doc.datasize delete doc.hash delete doc.data + delete doc.name const bucket = await getGridFSBucket() - const added = await writeToGridFS(bucket, buffer, id, `${id}/${doc.name}`, { metadata: doc }) + const added = await writeToGridFS(bucket, buffer, id, name, { metadata: doc }) const result = await DriveFile.update(id, { $set: { -- cgit v1.2.3-freya From 253747ecfb8245d94fe0110e01d8f2ca65a28f5d Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 8 Nov 2017 14:43:42 +0900 Subject: Fix bugs --- src/api/endpoints/drive/stream.ts | 5 +---- src/api/serializers/drive-file.ts | 2 ++ src/web/app/mobile/tags/drive/file-viewer.tag | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) (limited to 'src/api/endpoints') diff --git a/src/api/endpoints/drive/stream.ts b/src/api/endpoints/drive/stream.ts index 32f7ac7e0a..58e7d11678 100644 --- a/src/api/endpoints/drive/stream.ts +++ b/src/api/endpoints/drive/stream.ts @@ -52,15 +52,12 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }; } if (type) { - query.type = new RegExp(`^${type.replace(/\*/g, '.+?')}$`); + query.contentType = new RegExp(`^${type.replace(/\*/g, '.+?')}$`); } // Issue query const files = await DriveFile .find(query, { - fields: { - data: false - }, limit: limit, sort: sort }); diff --git a/src/api/serializers/drive-file.ts b/src/api/serializers/drive-file.ts index 3b76979a44..dcdaa01fab 100644 --- a/src/api/serializers/drive-file.ts +++ b/src/api/serializers/drive-file.ts @@ -49,6 +49,8 @@ export default ( _target.created_at = _file.uploadDate; _target.name = _file.filename; _target.type = _file.contentType; + _target.datasize = _file.length; + _target.md5 = _file.md5; _target = Object.assign(_target, _file.metadata); diff --git a/src/web/app/mobile/tags/drive/file-viewer.tag b/src/web/app/mobile/tags/drive/file-viewer.tag index e6129652b0..8dc49a0865 100644 --- a/src/web/app/mobile/tags/drive/file-viewer.tag +++ b/src/web/app/mobile/tags/drive/file-viewer.tag @@ -44,7 +44,7 @@

%i18n:mobile.tags.mk-drive-file-viewer.hash%

- { file.hash } + { file.md5 } diff --git a/src/web/app/desktop/tags/index.js b/src/web/app/desktop/tags/index.js index 7997bcc7f2..c36a06e499 100644 --- a/src/web/app/desktop/tags/index.js +++ b/src/web/app/desktop/tags/index.js @@ -57,6 +57,7 @@ require('./pages/entrance.tag'); require('./pages/entrance/signin.tag'); require('./pages/entrance/signup.tag'); require('./pages/home.tag'); +require('./pages/home-customize.tag'); require('./pages/user.tag'); require('./pages/post.tag'); require('./pages/search.tag'); diff --git a/src/web/app/desktop/tags/pages/home-customize.tag b/src/web/app/desktop/tags/pages/home-customize.tag new file mode 100644 index 0000000000..4434015615 --- /dev/null +++ b/src/web/app/desktop/tags/pages/home-customize.tag @@ -0,0 +1,14 @@ + + + + + + + diff --git a/src/web/app/desktop/tags/settings.tag b/src/web/app/desktop/tags/settings.tag index eabddfb432..4c16f9eaa8 100644 --- a/src/web/app/desktop/tags/settings.tag +++ b/src/web/app/desktop/tags/settings.tag @@ -38,6 +38,7 @@

デザイン

+ ホームをカスタマイズ
diff --git a/src/web/app/desktop/tags/ui.tag b/src/web/app/desktop/tags/ui.tag index 0a3e8d9c53..6a4982877f 100644 --- a/src/web/app/desktop/tags/ui.tag +++ b/src/web/app/desktop/tags/ui.tag @@ -37,7 +37,7 @@ - +
diff --git a/src/web/app/init.js b/src/web/app/init.js index 5a6899ed4f..7e3c2ee377 100644 --- a/src/web/app/init.js +++ b/src/web/app/init.js @@ -11,7 +11,6 @@ import checkForUpdate from './common/scripts/check-for-update'; import Connection from './common/scripts/home-stream'; import Progress from './common/scripts/loading'; import mixin from './common/mixins'; -import generateDefaultUserdata from './common/scripts/generate-default-userdata'; import CONFIG from './common/scripts/config'; require('./common/tags'); @@ -156,9 +155,7 @@ function fetchme(token, cb) { res.json().then(i => { me = i; me.token = token; - - // initialize it if user data is empty - me.data ? done() : init(); + done(); }); }, () => { // When failure // Render the error screen @@ -170,17 +167,6 @@ function fetchme(token, cb) { function done() { if (cb) cb(me); } - - // Initialize user data - function init() { - const data = generateDefaultUserdata(); - api(token, 'i/appdata/set', { - data - }).then(() => { - me.data = data; - done(); - }); - } } // BSoD diff --git a/tools/migration/node.2017-11-08..js b/tools/migration/node.2017-11-08..js new file mode 100644 index 0000000000..e25b83b3f3 --- /dev/null +++ b/tools/migration/node.2017-11-08..js @@ -0,0 +1,89 @@ +const uuid = require('uuid'); +const { default: User } = require('../../built/api/models/user') +const { default: zip } = require('@prezzemolo/zip') + +const home = { + left: [ + 'profile', + 'calendar', + 'activity', + 'rss-reader', + 'trends', + 'photo-stream', + 'version' + ], + right: [ + 'broadcast', + 'notifications', + 'user-recommendation', + 'recommended-polls', + 'server', + 'donation', + 'nav', + 'tips' + ] +}; + + +const migrate = async (doc) => { + + //#region Construct home data + const homeData = []; + + home.left.forEach(widget => { + homeData.push({ + name: widget, + id: uuid(), + place: 'left', + data: {} + }); + }); + + home.right.forEach(widget => { + homeData.push({ + name: widget, + id: uuid(), + place: 'right', + data: {} + }); + }); + //#endregion + + const result = await User.update(doc._id, { + $unset: { + data: '' + }, + $set: { + 'settings': {}, + 'client_settings.home': homeData, + 'client_settings.show_donation': false + } + }) + + return added && result.ok === 1 +} + +async function main() { + const count = await db.get('users').count(); + + console.log(`there are ${count} users.`) + + const dop = Number.parseInt(process.argv[2]) || 5 + const idop = ((count - (count % dop)) / dop) + 1 + + return zip( + 1, + async (time) => { + console.log(`${time} / ${idop}`) + const docs = await db.get('users').find({}, { limit: dop, skip: time * dop }) + return Promise.all(docs.map(migrate)) + }, + idop + ).then(a => { + const rv = [] + a.forEach(e => rv.push(...e)) + return rv + }) +} + +main().then(console.dir).catch(console.error) -- cgit v1.2.3-freya From 860a322c3637ba8933639a84fc8f335c4c6323fb Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 9 Nov 2017 02:55:03 +0900 Subject: [API] Improve drive/files --- src/api/endpoints/drive/files.ts | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/api/endpoints') diff --git a/src/api/endpoints/drive/files.ts b/src/api/endpoints/drive/files.ts index 53b48a8bec..b2e094775c 100644 --- a/src/api/endpoints/drive/files.ts +++ b/src/api/endpoints/drive/files.ts @@ -35,6 +35,10 @@ module.exports = async (params, user, app) => { const [folderId = null, folderIdErr] = $(params.folder_id).optional.nullable.id().$; if (folderIdErr) throw 'invalid folder_id param'; + // Get 'type' parameter + const [type, typeErr] = $(params.type).optional.string().match(/^[a-zA-Z\/\-\*]+$/).$; + if (typeErr) throw 'invalid type param'; + // Construct query const sort = { _id: -1 @@ -53,6 +57,9 @@ module.exports = async (params, user, app) => { $lt: maxId }; } + if (type) { + query.contentType = new RegExp(`^${type.replace(/\*/g, '.+?')}$`); + } // Issue query const files = await DriveFile -- cgit v1.2.3-freya From ba85942f76c0b7c0b458b48289569ada9aee2be1 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 11 Nov 2017 10:58:13 +0900 Subject: #905 --- locales/en.yml | 9 ++ locales/ja.yml | 9 ++ src/api/endpoints/posts/timeline.ts | 23 ++- src/web/app/desktop/tags/home-widgets/timeline.tag | 18 ++- .../app/desktop/tags/home-widgets/timemachine.tag | 165 +++++++++++++++++++++ src/web/app/desktop/tags/home.tag | 4 +- src/web/app/desktop/tags/index.js | 1 + 7 files changed, 224 insertions(+), 5 deletions(-) create mode 100644 src/web/app/desktop/tags/home-widgets/timemachine.tag (limited to 'src/api/endpoints') diff --git a/locales/en.yml b/locales/en.yml index c69dc22b1d..4eae825074 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -13,6 +13,15 @@ common: months_ago: "{}month(s) ago" years_ago: "{}year(s) ago" + weekday-short: + sunday: "S" + monday: "M" + tuesday: "T" + wednesday: "W" + thursday: "T" + friday: "F" + satruday: "S" + reactions: like: "Like" love: "Love" diff --git a/locales/ja.yml b/locales/ja.yml index 782b87bd83..82589aadff 100644 --- a/locales/ja.yml +++ b/locales/ja.yml @@ -13,6 +13,15 @@ common: months_ago: "{}ヶ月前" years_ago: "{}年前" + weekday-short: + sunday: "日" + monday: "月" + tuesday: "火" + wednesday: "水" + thursday: "木" + friday: "金" + satruday: "土" + reactions: like: "いいね" love: "ハート" diff --git a/src/api/endpoints/posts/timeline.ts b/src/api/endpoints/posts/timeline.ts index 7af435e82a..0d08b95463 100644 --- a/src/api/endpoints/posts/timeline.ts +++ b/src/api/endpoints/posts/timeline.ts @@ -29,9 +29,17 @@ module.exports = async (params, user, app) => { const [maxId, maxIdErr] = $(params.max_id).optional.id().$; if (maxIdErr) throw 'invalid max_id param'; - // Check if both of since_id and max_id is specified - if (sinceId && maxId) { - throw 'cannot set since_id and max_id'; + // Get 'since_date' parameter + const [sinceDate, sinceDateErr] = $(params.since_date).optional.number().$; + if (sinceDateErr) throw 'invalid since_date param'; + + // Get 'max_date' parameter + const [maxDate, maxDateErr] = $(params.max_date).optional.number().$; + if (maxDateErr) throw 'invalid max_date param'; + + // Check if only one of since_id, max_id, since_date, max_date specified + if ([sinceId, maxId, sinceDate, maxDate].filter(x => x != null).length > 1) { + throw 'only one of since_id, max_id, since_date, max_date can be specified'; } const { followingIds, watchingChannelIds } = await rap({ @@ -81,6 +89,15 @@ module.exports = async (params, user, app) => { query._id = { $lt: maxId }; + } else if (sinceDate) { + sort._id = 1; + query.created_at = { + $gt: new Date(sinceDate) + }; + } else if (maxDate) { + query.created_at = { + $lt: new Date(maxDate) + }; } //#endregion diff --git a/src/web/app/desktop/tags/home-widgets/timeline.tag b/src/web/app/desktop/tags/home-widgets/timeline.tag index 08d96ad715..735783049c 100644 --- a/src/web/app/desktop/tags/home-widgets/timeline.tag +++ b/src/web/app/desktop/tags/home-widgets/timeline.tag @@ -70,7 +70,13 @@ }; this.load = (cb) => { - this.api('posts/timeline').then(posts => { + this.update({ + isLoading: true + }); + + this.api('posts/timeline', { + max_date: this.date ? this.date.getTime() : undefined + }).then(posts => { this.update({ isLoading: false, isEmpty: posts.length == 0 @@ -114,5 +120,15 @@ const current = window.scrollY + window.innerHeight; if (current > document.body.offsetHeight - 8) this.more(); }; + + this.warp = date => { + console.log(date); + + this.update({ + date: date + }); + + this.load(); + }; diff --git a/src/web/app/desktop/tags/home-widgets/timemachine.tag b/src/web/app/desktop/tags/home-widgets/timemachine.tag new file mode 100644 index 0000000000..b6c53e0284 --- /dev/null +++ b/src/web/app/desktop/tags/home-widgets/timemachine.tag @@ -0,0 +1,165 @@ + + +

{ year }/{ month }

+ + +
+
{ weekdayText[i] }
+
+
{ i + 1 }
+
+ + +
diff --git a/src/web/app/desktop/tags/home.tag b/src/web/app/desktop/tags/home.tag index ecfe23adee..452499d70c 100644 --- a/src/web/app/desktop/tags/home.tag +++ b/src/web/app/desktop/tags/home.tag @@ -5,6 +5,7 @@ @@ -36,6 +36,31 @@ :scope display block + &[data-compact] + font-size 0.8em + + > .history + > a + &:last-child + border-bottom none + + &:not([data-is-me]):not([data-is-read]) + > div + background-image none + border-left solid 4px #3aa2dc + + > div + padding 16px + + > header + > mk-time + font-size 1em + + > .avatar + width 42px + height 42px + margin 0 12px 0 0 + > .search display block position -webkit-sticky @@ -75,7 +100,7 @@ > input margin 0 - padding 0 12px 0 38px + padding 0 0 0 38px width 100% font-size 1em line-height 38px @@ -299,22 +324,59 @@ this.mixin('i'); this.mixin('api'); + this.mixin('messaging-index-stream'); + this.connection = this.messagingIndexStream.getConnection(); + this.connectionId = this.messagingIndexStream.use(); + this.searchResult = []; + this.registerMessage = message => { + message.is_me = message.user_id == this.I.id; + message._click = () => { + this.trigger('navigate-user', message.is_me ? message.recipient : message.user); + }; + }; + this.on('mount', () => { + this.connection.on('message', this.onMessage); + this.connection.on('read', this.onRead); + this.api('messaging/history').then(history => { this.isLoading = false; history.forEach(message => { - message.is_me = message.user_id == this.I.id - message._click = () => { - this.trigger('navigate-user', message.is_me ? message.recipient : message.user); - }; + this.registerMessage(message); }); this.history = history; this.update(); }); }); + this.on('unmount', () => { + this.connection.off('message', this.onMessage); + this.connection.off('read', this.onRead); + this.messagingIndexStream.dispose(this.connectionId); + }); + + this.onMessage = message => { + this.history = this.history.filter(m => !( + (m.recipient_id == message.recipient_id && m.user_id == message.user_id) || + (m.recipient_id == message.user_id && m.user_id == message.recipient_id))); + + this.registerMessage(message); + + this.history.unshift(message); + this.update(); + }; + + this.onRead = ids => { + ids.forEach(id => { + const found = this.history.find(m => m.id == id); + if (found) found.is_read = true; + }); + + this.update(); + }; + this.search = () => { const q = this.refs.search.value; if (q == '') { diff --git a/src/web/app/desktop/tags/home-widgets/messaging.tag b/src/web/app/desktop/tags/home-widgets/messaging.tag new file mode 100644 index 0000000000..d7e8375c8d --- /dev/null +++ b/src/web/app/desktop/tags/home-widgets/messaging.tag @@ -0,0 +1,50 @@ + + +

%i18n:desktop.tags.mk-messaging-home-widget.title%

+
+ + + +
diff --git a/src/web/app/desktop/tags/home.tag b/src/web/app/desktop/tags/home.tag index 88d06d2baa..5a0d194ba5 100644 --- a/src/web/app/desktop/tags/home.tag +++ b/src/web/app/desktop/tags/home.tag @@ -19,6 +19,7 @@ + diff --git a/src/web/app/desktop/tags/index.ts b/src/web/app/desktop/tags/index.ts index 8b5a52d670..cd22dde352 100644 --- a/src/web/app/desktop/tags/index.ts +++ b/src/web/app/desktop/tags/index.ts @@ -44,6 +44,7 @@ require('./home-widgets/channel.tag'); require('./home-widgets/timemachine.tag'); require('./home-widgets/post-form.tag'); require('./home-widgets/access-log.tag'); +require('./home-widgets/messaging.tag'); require('./timeline.tag'); require('./messaging/window.tag'); require('./messaging/room-window.tag'); -- cgit v1.2.3-freya From 64aedcaa6b3e9170e77c428ee306830464b42bcf Mon Sep 17 00:00:00 2001 From: otofune Date: Tue, 14 Nov 2017 03:46:30 +0900 Subject: add-file-to-drive - Promise百烈拳とメモリ削減 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 9 +- src/api/common/add-file-to-drive.ts | 344 ++++++++++++++--------- src/api/endpoints/drive/files/upload_from_url.ts | 74 ++++- 3 files changed, 272 insertions(+), 155 deletions(-) (limited to 'src/api/endpoints') diff --git a/package.json b/package.json index 5b26ee574a..235e64f7cc 100644 --- a/package.json +++ b/package.json @@ -54,13 +54,14 @@ "@types/node": "8.0.49", "@types/page": "1.5.32", "@types/proxy-addr": "2.0.0", - "@types/seedrandom": "2.4.27", "@types/ratelimiter": "2.1.28", "@types/redis": "2.8.1", - "@types/request": "2.0.7", + "@types/request": "^2.0.7", "@types/rimraf": "2.0.2", "@types/riot": "3.6.1", + "@types/seedrandom": "2.4.27", "@types/serve-favicon": "2.2.29", + "@types/tmp": "0.0.33", "@types/uuid": "3.4.3", "@types/webpack": "3.8.0", "@types/webpack-stream": "3.2.8", @@ -111,7 +112,6 @@ "deep-equal": "1.0.1", "deepcopy": "0.6.3", "diskusage": "0.2.2", - "download": "6.2.5", "elasticsearch": "13.3.1", "escape-regexp": "0.0.1", "express": "4.15.4", @@ -140,7 +140,7 @@ "recaptcha-promise": "0.1.3", "reconnecting-websocket": "3.2.2", "redis": "2.8.0", - "request": "2.83.0", + "request": "^2.83.0", "rimraf": "2.6.2", "riot": "3.7.4", "rndstr": "1.0.0", @@ -152,6 +152,7 @@ "syuilo-password-strength": "0.0.1", "tcp-port-used": "0.1.2", "textarea-caret": "3.0.2", + "tmp": "0.0.33", "ts-node": "3.3.0", "typescript": "2.6.1", "uuid": "3.1.0", diff --git a/src/api/common/add-file-to-drive.ts b/src/api/common/add-file-to-drive.ts index a96906d291..a7c7cb4644 100644 --- a/src/api/common/add-file-to-drive.ts +++ b/src/api/common/add-file-to-drive.ts @@ -9,28 +9,34 @@ import DriveFolder from '../models/drive-folder'; import serialize from '../serializers/drive-file'; import event from '../event'; import config from '../../conf'; -import { Duplex } from 'stream'; +import { Buffer } from 'buffer'; +import * as fs from 'fs'; +import * as tmp from 'tmp'; +import * as stream from 'stream'; const log = debug('misskey:register-drive-file'); -const addToGridFS = (name, binary, type, metadata): Promise => new Promise(async (resolve, reject) => { - const dataStream = new Duplex(); - dataStream.push(binary); - dataStream.push(null); - - const bucket = await getGridFSBucket(); - const writeStream = bucket.openUploadStream(name, { contentType: type, metadata }); - writeStream.once('finish', (doc) => { resolve(doc); }); - writeStream.on('error', reject); - dataStream.pipe(writeStream); -}); +const tmpFile = (): Promise => new Promise((resolve, reject) => { + tmp.file((e, path) => { + if (e) return reject(e) + resolve(path) + }) +}) + +const addToGridFS = (name: string, readable: stream.Readable, type: string, metadata: any): Promise => + getGridFSBucket() + .then(bucket => new Promise((resolve, reject) => { + const writeStream = bucket.openUploadStream(name, { contentType: type, metadata }); + writeStream.once('finish', (doc) => { resolve(doc); }); + writeStream.on('error', reject); + readable.pipe(writeStream); + })) /** * Add file to drive * * @param user User who wish to add file - * @param fileName File name - * @param data Contents + * @param file File path, binary, or readableStream * @param comment Comment * @param type File type * @param folderId Folder ID @@ -39,139 +45,201 @@ const addToGridFS = (name, binary, type, metadata): Promise => new Promise( */ export default ( user: any, - data: Buffer, + file: string | Buffer | stream.Readable, name: string = null, comment: string = null, folderId: mongodb.ObjectID = null, force: boolean = false -) => new Promise(async (resolve, reject) => { +) => new Promise((resolve, reject) => { log(`registering ${name} (user: ${user.username})`); - // File size - const size = data.byteLength; - - log(`size is ${size}`); - - // File type - let mime = 'application/octet-stream'; - const type = fileType(data); - if (type !== null) { - mime = type.mime; - - if (name === null) { - name = `untitled.${type.ext}`; + // Get file path + new Promise((res: (v: string) => void, rej) => { + if (typeof file === 'string') { + res(file) + return } - } else { - if (name === null) { - name = 'untitled'; + if (file instanceof Buffer) { + tmpFile() + .then(path => { + fs.writeFile(path, file, (err) => { + if (err) rej(err) + res(path) + }) + }) + .catch(rej) + return } - } - - log(`type is ${mime}`); - - // Generate hash - const hash = crypto - .createHash('md5') - .update(data) - .digest('hex') as string; - - log(`hash is ${hash}`); - - if (!force) { - // Check if there is a file with the same hash - const much = await DriveFile.findOne({ - md5: hash, - 'metadata.user_id': user._id - }); - - if (much !== null) { - log('file with same hash is found'); - return resolve(much); - } else { - log('file with same hash is not found'); + if (typeof file === 'object' && typeof file.read === 'function') { + tmpFile() + .then(path => { + const readable: stream.Readable = file + const writable = fs.createWriteStream(path) + readable + .on('error', rej) + .on('end', () => { + res(path) + }) + .pipe(writable) + .on('error', rej) + }) + .catch(rej) } - } - - // Calculate drive usage - const usage = ((await DriveFile - .aggregate([ - { $match: { 'metadata.user_id': user._id } }, - { $project: { - length: true - }}, - { $group: { - _id: null, - usage: { $sum: '$length' } - }} - ]))[0] || { - usage: 0 - }).usage; - - log(`drive usage is ${usage}`); - - // If usage limit exceeded - if (usage + size > user.drive_capacity) { - return reject('no-free-space'); - } - - // If the folder is specified - let folder: any = null; - if (folderId !== null) { - folder = await DriveFolder - .findOne({ - _id: folderId, - user_id: user._id - }); - - if (folder === null) { - return reject('folder-not-found'); - } - } - - let properties: any = null; - - // If the file is an image - if (/^image\/.*$/.test(mime)) { - // Calculate width and height to save in property - const g = gm(data, name); - const size = await prominence(g).size(); - properties = { - width: size.width, - height: size.height - }; - - log('image width and height is calculated'); - } - - // Create DriveFile document - const file = await addToGridFS(name, data, mime, { - user_id: user._id, - folder_id: folder !== null ? folder._id : null, - comment: comment, - properties: properties - }); - - log(`drive file has been created ${file._id}`); - - resolve(file); - - // Serialize - const fileObj = await serialize(file); - - // Publish drive_file_created event - event(user._id, 'drive_file_created', fileObj); + rej(new Error('un-compatible file.')) + }) + // Calculate hash, get content type and get file size + .then(path => Promise.all([ + path, + // hash + ((): Promise => new Promise((res, rej) => { + const readable = fs.createReadStream(path) + const hash = crypto.createHash('md5') + readable + .on('error', rej) + .on('end', () => { + res(hash.digest('hex')) + }) + .pipe(hash) + .on('error', rej) + }))(), + // mime + ((): Promise<[string, string | null]> => new Promise((res, rej) => { + const readable = fs.createReadStream(path) + readable + .on('error', rej) + .once('data', (buffer: Buffer) => { + readable.destroy() + const type = fileType(buffer) + if (!type) { + return res(['application/octet-stream', null]) + } + return res([type.mime, type.ext]) + }) + }))(), + // size + ((): Promise => new Promise((res, rej) => { + fs.stat(path, (err, stats) => { + if (err) return rej(err) + res(stats.size) + }) + }))() + ])) + .then(async ([path, hash, [mime, ext], size]) => { + log(`hash: ${hash}, mime: ${mime}, ext: ${ext}, size: ${size}`) + + // detect name + const detectedName: string = name || (ext ? `untitled.${ext}` : 'untitled'); + + if (!force) { + // Check if there is a file with the same hash + const much = await DriveFile.findOne({ + md5: hash, + 'metadata.user_id': user._id + }); + + if (much !== null) { + log('file with same hash is found'); + return resolve(much); + } else { + log('file with same hash is not found'); + } + } - // Register to search database - if (config.elasticsearch.enable) { - const es = require('../../db/elasticsearch'); - es.index({ - index: 'misskey', - type: 'drive_file', - id: file._id.toString(), - body: { - name: file.name, - user_id: user._id.toString() + const [properties, folder] = await Promise.all([ + // properties + (async () => { + if (!/^image\/.*$/.test(mime)) { + return null + } + // If the file is an image, calculate width and height to save in property + const g = gm(data, name); + const size = await prominence(g).size(); + const properties = { + width: size.width, + height: size.height + }; + log('image width and height is calculated'); + return properties + })(), + // folder + (async () => { + if (!folderId) { + return null + } + const driveFolder = await DriveFolder.findOne({ + _id: folderId, + user_id: user._id + }) + if (!driveFolder) { + throw 'folder-not-found' + } + return driveFolder + })(), + // usage checker + (async () => { + // Calculate drive usage + const usage = await DriveFile + .aggregate([ + { $match: { 'metadata.user_id': user._id } }, + { + $project: { + length: true + } + }, + { + $group: { + _id: null, + usage: { $sum: '$length' } + } + } + ]) + .then((aggregates: any[]) => { + if (aggregates.length > 0) { + return aggregates[0].usage + } + return 0 + }); + + log(`drive usage is ${usage}`); + + // If usage limit exceeded + if (usage + size > user.drive_capacity) { + throw 'no-free-space'; + } + })() + ]) + + const readable = fs.createReadStream(path) + + return addToGridFS(name, readable, mime, { + user_id: user._id, + folder_id: folder !== null ? folder._id : null, + comment: comment, + properties: properties + }) + }) + .then(file => { + log(`drive file has been created ${file._id}`); + resolve(file) + return serialize(file) + }) + .then(serializedFile => { + // Publish drive_file_created event + event(user._id, 'drive_file_created', fileObj); + + // Register to search database + if (config.elasticsearch.enable) { + const es = require('../../db/elasticsearch'); + es.index({ + index: 'misskey', + type: 'drive_file', + id: file._id.toString(), + body: { + name: file.name, + user_id: user._id.toString() + } + }); } - }); - } + }) + .catch(reject) }); diff --git a/src/api/endpoints/drive/files/upload_from_url.ts b/src/api/endpoints/drive/files/upload_from_url.ts index 46cfffb69c..9c759994e0 100644 --- a/src/api/endpoints/drive/files/upload_from_url.ts +++ b/src/api/endpoints/drive/files/upload_from_url.ts @@ -2,11 +2,17 @@ * Module dependencies */ import * as URL from 'url'; -const download = require('download'); import $ from 'cafy'; import { validateFileName } from '../../../models/drive-file'; import serialize from '../../../serializers/drive-file'; import create from '../../../common/add-file-to-drive'; +import * as debug from 'debug'; +import * as tmp from 'tmp'; +import * as fs from 'fs'; +import * as request from 'request'; +import * as crypto from 'crypto'; + +const log = debug('misskey:endpoint:upload_from_url') /** * Create a file from a URL @@ -15,7 +21,7 @@ import create from '../../../common/add-file-to-drive'; * @param {any} user * @return {Promise} */ -module.exports = (params, user) => new Promise(async (res, rej) => { +module.exports = (params, user) => new Promise((res, rej) => { // Get 'url' parameter // TODO: Validate this url const [url, urlErr] = $(params.url).string().$; @@ -30,15 +36,57 @@ module.exports = (params, user) => new Promise(async (res, rej) => { const [folderId = null, folderIdErr] = $(params.folder_id).optional.nullable.id().$; if (folderIdErr) return rej('invalid folder_id param'); - // Download file - const data = await download(url); - - // Create file - const driveFile = await create(user, data, name, null, folderId); - - // Serialize - const fileObj = await serialize(driveFile); - - // Response - res(fileObj); + // Create temp file + new Promise((res, rej) => { + tmp.file((e, path) => { + if (e) return rej(e) + res(path) + }) + }) + // Download file + .then((path: string) => new Promise((res, rej) => { + const writable = fs.createWriteStream(path) + request(url) + .on('error', rej) + .on('end', () => { + writable.close() + res(path) + }) + .pipe(writable) + .on('error', rej) + })) + // Calculate hash & content-type + .then((path: string) => new Promise((res, rej) => { + const readable = fs.createReadStream(path) + const hash = crypto.createHash('md5') + readable + .on('error', rej) + .on('end', () => { + hash.end() + res([path, hash.digest('hex')]) + }) + .pipe(hash) + .on('error', rej) + })) + // Create file + .then((rv: string[]) => new Promise((res, rej) => { + const [path, hash] = rv + create(user, { + stream: fs.createReadStream(path), + name, + hash + }, null, folderId) + .then(driveFile => { + res(driveFile) + // crean-up + fs.unlink(path, (e) => { + if (e) log(e.stack) + }) + }) + .catch(rej) + })) + // Serialize + .then(serialize) + .then(res) + .catch(rej) }); -- cgit v1.2.3-freya From e56f716a89227c76dfc05e48b3ca438f766f85b4 Mon Sep 17 00:00:00 2001 From: otofune Date: Tue, 14 Nov 2017 03:47:42 +0900 Subject: format --- src/api/common/add-file-to-drive.ts | 92 ++++++++++++------------ src/api/endpoints/drive/files/upload_from_url.ts | 38 +++++----- 2 files changed, 65 insertions(+), 65 deletions(-) (limited to 'src/api/endpoints') diff --git a/src/api/common/add-file-to-drive.ts b/src/api/common/add-file-to-drive.ts index a7c7cb4644..c6a4c4791d 100644 --- a/src/api/common/add-file-to-drive.ts +++ b/src/api/common/add-file-to-drive.ts @@ -18,10 +18,10 @@ const log = debug('misskey:register-drive-file'); const tmpFile = (): Promise => new Promise((resolve, reject) => { tmp.file((e, path) => { - if (e) return reject(e) - resolve(path) - }) -}) + if (e) return reject(e); + resolve(path); + }); +}); const addToGridFS = (name: string, readable: stream.Readable, type: string, metadata: any): Promise => getGridFSBucket() @@ -30,7 +30,7 @@ const addToGridFS = (name: string, readable: stream.Readable, type: string, meta writeStream.once('finish', (doc) => { resolve(doc); }); writeStream.on('error', reject); readable.pipe(writeStream); - })) + })); /** * Add file to drive @@ -56,76 +56,76 @@ export default ( // Get file path new Promise((res: (v: string) => void, rej) => { if (typeof file === 'string') { - res(file) - return + res(file); + return; } if (file instanceof Buffer) { tmpFile() .then(path => { fs.writeFile(path, file, (err) => { - if (err) rej(err) - res(path) - }) + if (err) rej(err); + res(path); + }); }) - .catch(rej) - return + .catch(rej); + return; } if (typeof file === 'object' && typeof file.read === 'function') { tmpFile() .then(path => { - const readable: stream.Readable = file - const writable = fs.createWriteStream(path) + const readable: stream.Readable = file; + const writable = fs.createWriteStream(path); readable .on('error', rej) .on('end', () => { - res(path) + res(path); }) .pipe(writable) - .on('error', rej) + .on('error', rej); }) - .catch(rej) + .catch(rej); } - rej(new Error('un-compatible file.')) + rej(new Error('un-compatible file.')); }) // Calculate hash, get content type and get file size .then(path => Promise.all([ path, // hash ((): Promise => new Promise((res, rej) => { - const readable = fs.createReadStream(path) - const hash = crypto.createHash('md5') + const readable = fs.createReadStream(path); + const hash = crypto.createHash('md5'); readable .on('error', rej) .on('end', () => { - res(hash.digest('hex')) + res(hash.digest('hex')); }) .pipe(hash) - .on('error', rej) + .on('error', rej); }))(), // mime ((): Promise<[string, string | null]> => new Promise((res, rej) => { - const readable = fs.createReadStream(path) + const readable = fs.createReadStream(path); readable .on('error', rej) .once('data', (buffer: Buffer) => { - readable.destroy() - const type = fileType(buffer) + readable.destroy(); + const type = fileType(buffer); if (!type) { - return res(['application/octet-stream', null]) + return res(['application/octet-stream', null]); } - return res([type.mime, type.ext]) - }) + return res([type.mime, type.ext]); + }); }))(), // size ((): Promise => new Promise((res, rej) => { fs.stat(path, (err, stats) => { - if (err) return rej(err) - res(stats.size) - }) + if (err) return rej(err); + res(stats.size); + }); }))() ])) .then(async ([path, hash, [mime, ext], size]) => { - log(`hash: ${hash}, mime: ${mime}, ext: ${ext}, size: ${size}`) + log(`hash: ${hash}, mime: ${mime}, ext: ${ext}, size: ${size}`); // detect name const detectedName: string = name || (ext ? `untitled.${ext}` : 'untitled'); @@ -149,7 +149,7 @@ export default ( // properties (async () => { if (!/^image\/.*$/.test(mime)) { - return null + return null; } // If the file is an image, calculate width and height to save in property const g = gm(data, name); @@ -159,21 +159,21 @@ export default ( height: size.height }; log('image width and height is calculated'); - return properties + return properties; })(), // folder (async () => { if (!folderId) { - return null + return null; } const driveFolder = await DriveFolder.findOne({ _id: folderId, user_id: user._id - }) + }); if (!driveFolder) { - throw 'folder-not-found' + throw 'folder-not-found'; } - return driveFolder + return driveFolder; })(), // usage checker (async () => { @@ -195,9 +195,9 @@ export default ( ]) .then((aggregates: any[]) => { if (aggregates.length > 0) { - return aggregates[0].usage + return aggregates[0].usage; } - return 0 + return 0; }); log(`drive usage is ${usage}`); @@ -207,21 +207,21 @@ export default ( throw 'no-free-space'; } })() - ]) + ]); - const readable = fs.createReadStream(path) + const readable = fs.createReadStream(path); return addToGridFS(name, readable, mime, { user_id: user._id, folder_id: folder !== null ? folder._id : null, comment: comment, properties: properties - }) + }); }) .then(file => { log(`drive file has been created ${file._id}`); - resolve(file) - return serialize(file) + resolve(file); + return serialize(file); }) .then(serializedFile => { // Publish drive_file_created event @@ -241,5 +241,5 @@ export default ( }); } }) - .catch(reject) + .catch(reject); }); diff --git a/src/api/endpoints/drive/files/upload_from_url.ts b/src/api/endpoints/drive/files/upload_from_url.ts index 9c759994e0..60332b4afe 100644 --- a/src/api/endpoints/drive/files/upload_from_url.ts +++ b/src/api/endpoints/drive/files/upload_from_url.ts @@ -12,7 +12,7 @@ import * as fs from 'fs'; import * as request from 'request'; import * as crypto from 'crypto'; -const log = debug('misskey:endpoint:upload_from_url') +const log = debug('misskey:endpoint:upload_from_url'); /** * Create a file from a URL @@ -39,54 +39,54 @@ module.exports = (params, user) => new Promise((res, rej) => { // Create temp file new Promise((res, rej) => { tmp.file((e, path) => { - if (e) return rej(e) - res(path) - }) + if (e) return rej(e); + res(path); + }); }) // Download file .then((path: string) => new Promise((res, rej) => { - const writable = fs.createWriteStream(path) + const writable = fs.createWriteStream(path); request(url) .on('error', rej) .on('end', () => { - writable.close() - res(path) + writable.close(); + res(path); }) .pipe(writable) - .on('error', rej) + .on('error', rej); })) // Calculate hash & content-type .then((path: string) => new Promise((res, rej) => { - const readable = fs.createReadStream(path) - const hash = crypto.createHash('md5') + const readable = fs.createReadStream(path); + const hash = crypto.createHash('md5'); readable .on('error', rej) .on('end', () => { - hash.end() - res([path, hash.digest('hex')]) + hash.end(); + res([path, hash.digest('hex')]); }) .pipe(hash) - .on('error', rej) + .on('error', rej); })) // Create file .then((rv: string[]) => new Promise((res, rej) => { - const [path, hash] = rv + const [path, hash] = rv; create(user, { stream: fs.createReadStream(path), name, hash }, null, folderId) .then(driveFile => { - res(driveFile) + res(driveFile); // crean-up fs.unlink(path, (e) => { - if (e) log(e.stack) - }) + if (e) log(e.stack); + }); }) - .catch(rej) + .catch(rej); })) // Serialize .then(serialize) .then(res) - .catch(rej) + .catch(rej); }); -- cgit v1.2.3-freya From 47f98fbab76e8680f5a7c99037b3b237c7256ca2 Mon Sep 17 00:00:00 2001 From: otofune Date: Tue, 14 Nov 2017 04:28:51 +0900 Subject: バグ修正 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/common/add-file-to-drive.ts | 35 +++++----- src/api/endpoints/drive/files/upload_from_url.ts | 81 ++++++++---------------- 2 files changed, 46 insertions(+), 70 deletions(-) (limited to 'src/api/endpoints') diff --git a/src/api/common/add-file-to-drive.ts b/src/api/common/add-file-to-drive.ts index 5f7d255e4b..1c8965e31d 100644 --- a/src/api/common/add-file-to-drive.ts +++ b/src/api/common/add-file-to-drive.ts @@ -214,7 +214,7 @@ export default ( const readable = fs.createReadStream(path); - return addToGridFS(name, readable, mime, { + return addToGridFS(detectedName, readable, mime, { user_id: user._id, folder_id: folder !== null ? folder._id : null, comment: comment, @@ -224,25 +224,26 @@ export default ( .then(file => { log(`drive file has been created ${file._id}`); resolve(file); - return serialize(file); - }) - .then(serializedFile => { - // Publish drive_file_created event - event(user._id, 'drive_file_created', fileObj); - // Register to search database - if (config.elasticsearch.enable) { - const es = require('../../db/elasticsearch'); - es.index({ - index: 'misskey', - type: 'drive_file', - id: file._id.toString(), - body: { - name: file.name, - user_id: user._id.toString() + serialize(file) + .then(serializedFile => { + // Publish drive_file_created event + event(user._id, 'drive_file_created', serializedFile); + + // Register to search database + if (config.elasticsearch.enable) { + const es = require('../../db/elasticsearch'); + es.index({ + index: 'misskey', + type: 'drive_file', + id: file._id.toString(), + body: { + name: file.name, + user_id: user._id.toString() + } + }); } }); - } }) .catch(reject); }); diff --git a/src/api/endpoints/drive/files/upload_from_url.ts b/src/api/endpoints/drive/files/upload_from_url.ts index 60332b4afe..519e0bdf65 100644 --- a/src/api/endpoints/drive/files/upload_from_url.ts +++ b/src/api/endpoints/drive/files/upload_from_url.ts @@ -10,7 +10,6 @@ import * as debug from 'debug'; import * as tmp from 'tmp'; import * as fs from 'fs'; import * as request from 'request'; -import * as crypto from 'crypto'; const log = debug('misskey:endpoint:upload_from_url'); @@ -21,11 +20,11 @@ const log = debug('misskey:endpoint:upload_from_url'); * @param {any} user * @return {Promise} */ -module.exports = (params, user) => new Promise((res, rej) => { +module.exports = async (params, user): Promise => { // Get 'url' parameter // TODO: Validate this url const [url, urlErr] = $(params.url).string().$; - if (urlErr) return rej('invalid url param'); + if (urlErr) throw 'invalid url param'; let name = URL.parse(url).pathname.split('/').pop(); if (!validateFileName(name)) { @@ -34,59 +33,35 @@ module.exports = (params, user) => new Promise((res, rej) => { // Get 'folder_id' parameter const [folderId = null, folderIdErr] = $(params.folder_id).optional.nullable.id().$; - if (folderIdErr) return rej('invalid folder_id param'); + if (folderIdErr) throw 'invalid folder_id param'; // Create temp file - new Promise((res, rej) => { + const path = await new Promise((res: (string) => void, rej) => { tmp.file((e, path) => { if (e) return rej(e); res(path); }); - }) - // Download file - .then((path: string) => new Promise((res, rej) => { - const writable = fs.createWriteStream(path); - request(url) - .on('error', rej) - .on('end', () => { - writable.close(); - res(path); - }) - .pipe(writable) - .on('error', rej); - })) - // Calculate hash & content-type - .then((path: string) => new Promise((res, rej) => { - const readable = fs.createReadStream(path); - const hash = crypto.createHash('md5'); - readable - .on('error', rej) - .on('end', () => { - hash.end(); - res([path, hash.digest('hex')]); - }) - .pipe(hash) - .on('error', rej); - })) - // Create file - .then((rv: string[]) => new Promise((res, rej) => { - const [path, hash] = rv; - create(user, { - stream: fs.createReadStream(path), - name, - hash - }, null, folderId) - .then(driveFile => { - res(driveFile); - // crean-up - fs.unlink(path, (e) => { - if (e) log(e.stack); - }); - }) - .catch(rej); - })) - // Serialize - .then(serialize) - .then(res) - .catch(rej); -}); + }); + + // write content at URL to temp file + await new Promise((res, rej) => { + const writable = fs.createWriteStream(path); + request(url) + .on('error', rej) + .on('end', () => { + writable.close(); + res(path); + }) + .pipe(writable) + .on('error', rej); + }); + + const driveFile = await create(user, path, name, null, folderId); + + // clean-up + fs.unlink(path, (e) => { + if (e) log(e.stack); + }); + + return serialize(driveFile); +}; -- cgit v1.2.3-freya From 342345cc2fb95e86d65095e0c9996441950ad628 Mon Sep 17 00:00:00 2001 From: otofune Date: Tue, 14 Nov 2017 04:35:25 +0900 Subject: create - バッファを使用しないように MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/endpoints/drive/files/create.ts | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) (limited to 'src/api/endpoints') diff --git a/src/api/endpoints/drive/files/create.ts b/src/api/endpoints/drive/files/create.ts index 7967c31187..7546eca309 100644 --- a/src/api/endpoints/drive/files/create.ts +++ b/src/api/endpoints/drive/files/create.ts @@ -1,7 +1,6 @@ /** * Module dependencies */ -import * as fs from 'fs'; import $ from 'cafy'; import { validateFileName } from '../../../models/drive-file'; import serialize from '../../../serializers/drive-file'; @@ -15,15 +14,11 @@ import create from '../../../common/add-file-to-drive'; * @param {any} user * @return {Promise} */ -module.exports = (file, params, user) => new Promise(async (res, rej) => { +module.exports = async (file, params, user): Promise => { if (file == null) { - return rej('file is required'); + throw 'file is required'; } - // TODO: 非同期にしたい。Promise対応してないんだろうか... - const buffer = fs.readFileSync(file.path); - fs.unlink(file.path, (err) => { if (err) console.log(err); }); - // Get 'name' parameter let name = file.originalname; if (name !== undefined && name !== null) { @@ -33,7 +28,7 @@ module.exports = (file, params, user) => new Promise(async (res, rej) => { } else if (name === 'blob') { name = null; } else if (!validateFileName(name)) { - return rej('invalid name'); + throw 'invalid name'; } } else { name = null; @@ -41,14 +36,11 @@ module.exports = (file, params, user) => new Promise(async (res, rej) => { // Get 'folder_id' parameter const [folderId = null, folderIdErr] = $(params.folder_id).optional.nullable.id().$; - if (folderIdErr) return rej('invalid folder_id param'); + if (folderIdErr) throw 'invalid folder_id param'; // Create file - const driveFile = await create(user, buffer, name, null, folderId); + const driveFile = await create(user, file.path, name, null, folderId); // Serialize - const fileObj = await serialize(driveFile); - - // Response - res(fileObj); -}); + return serialize(driveFile); +}; -- cgit v1.2.3-freya From 107ecfb07fe81dc5b89d9ef57a7be77657463d31 Mon Sep 17 00:00:00 2001 From: syuilo Date: Tue, 14 Nov 2017 08:21:19 +0900 Subject: なんか MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/endpoints/users/posts.ts | 28 +- src/web/app/desktop/tags/calendar.tag | 241 +++++++++++ .../app/desktop/tags/home-widgets/timemachine.tag | 231 +---------- src/web/app/desktop/tags/index.ts | 6 +- src/web/app/desktop/tags/user-graphs.tag | 41 -- src/web/app/desktop/tags/user-header.tag | 147 ------- src/web/app/desktop/tags/user-home.tag | 46 --- src/web/app/desktop/tags/user-photos.tag | 91 ---- src/web/app/desktop/tags/user-profile.tag | 102 ----- src/web/app/desktop/tags/user-timeline.tag | 9 + src/web/app/desktop/tags/user.tag | 457 ++++++++++++++++++++- 11 files changed, 727 insertions(+), 672 deletions(-) create mode 100644 src/web/app/desktop/tags/calendar.tag delete mode 100644 src/web/app/desktop/tags/user-graphs.tag delete mode 100644 src/web/app/desktop/tags/user-header.tag delete mode 100644 src/web/app/desktop/tags/user-home.tag delete mode 100644 src/web/app/desktop/tags/user-photos.tag delete mode 100644 src/web/app/desktop/tags/user-profile.tag (limited to 'src/api/endpoints') diff --git a/src/api/endpoints/users/posts.ts b/src/api/endpoints/users/posts.ts index d8204b8b80..fe821cf17a 100644 --- a/src/api/endpoints/users/posts.ts +++ b/src/api/endpoints/users/posts.ts @@ -46,9 +46,17 @@ module.exports = (params, me) => new Promise(async (res, rej) => { const [maxId, maxIdErr] = $(params.max_id).optional.id().$; if (maxIdErr) return rej('invalid max_id param'); - // Check if both of since_id and max_id is specified - if (sinceId && maxId) { - return rej('cannot set since_id and max_id'); + // Get 'since_date' parameter + const [sinceDate, sinceDateErr] = $(params.since_date).optional.number().$; + if (sinceDateErr) throw 'invalid since_date param'; + + // Get 'max_date' parameter + const [maxDate, maxDateErr] = $(params.max_date).optional.number().$; + if (maxDateErr) throw 'invalid max_date param'; + + // Check if only one of since_id, max_id, since_date, max_date specified + if ([sinceId, maxId, sinceDate, maxDate].filter(x => x != null).length > 1) { + throw 'only one of since_id, max_id, since_date, max_date can be specified'; } const q = userId !== undefined @@ -66,13 +74,15 @@ module.exports = (params, me) => new Promise(async (res, rej) => { return rej('user not found'); } - // Construct query + //#region Construct query const sort = { _id: -1 }; + const query = { user_id: user._id } as any; + if (sinceId) { sort._id = 1; query._id = { @@ -82,6 +92,15 @@ module.exports = (params, me) => new Promise(async (res, rej) => { query._id = { $lt: maxId }; + } else if (sinceDate) { + sort._id = 1; + query.created_at = { + $gt: new Date(sinceDate) + }; + } else if (maxDate) { + query.created_at = { + $lt: new Date(maxDate) + }; } if (!includeReplies) { @@ -94,6 +113,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => { $ne: null }; } + //#endregion // Issue query const posts = await Post diff --git a/src/web/app/desktop/tags/calendar.tag b/src/web/app/desktop/tags/calendar.tag new file mode 100644 index 0000000000..3535e81901 --- /dev/null +++ b/src/web/app/desktop/tags/calendar.tag @@ -0,0 +1,241 @@ + + + +

{ '%i18n:desktop.tags.mk-calendar.title%'.replace('{1}', year).replace('{2}', month) }

+ +
+ +
+
{ weekdayText[i] }
+
+
{ i + 1 }
+
+ + +
diff --git a/src/web/app/desktop/tags/home-widgets/timemachine.tag b/src/web/app/desktop/tags/home-widgets/timemachine.tag index 984258d2ba..2199cf4c67 100644 --- a/src/web/app/desktop/tags/home-widgets/timemachine.tag +++ b/src/web/app/desktop/tags/home-widgets/timemachine.tag @@ -1,139 +1,10 @@ - - - -

{ '%i18n:desktop.tags.mk-timemachine-home-widget.title%'.replace('{1}', year).replace('{2}', month) }

- -
- -
-
{ weekdayText[i] }
-
-
{ i + 1 }
-
+ + - diff --git a/src/web/app/desktop/tags/user-header.tag b/src/web/app/desktop/tags/user-header.tag deleted file mode 100644 index ea7ea6bb37..0000000000 --- a/src/web/app/desktop/tags/user-header.tag +++ /dev/null @@ -1,147 +0,0 @@ - - avatar -
-

{ user.name }

-

@{ user.username }

-

{ user.profile.location }

-
- - - -
diff --git a/src/web/app/desktop/tags/user-home.tag b/src/web/app/desktop/tags/user-home.tag deleted file mode 100644 index a879db5bb6..0000000000 --- a/src/web/app/desktop/tags/user-home.tag +++ /dev/null @@ -1,46 +0,0 @@ - -
- - -
-
- -
- - -
diff --git a/src/web/app/desktop/tags/user-photos.tag b/src/web/app/desktop/tags/user-photos.tag deleted file mode 100644 index dce1e50add..0000000000 --- a/src/web/app/desktop/tags/user-photos.tag +++ /dev/null @@ -1,91 +0,0 @@ - -

フォト

-

読み込んでいます

-
0 }> - -
-
-
-

写真はありません

- - -
diff --git a/src/web/app/desktop/tags/user-profile.tag b/src/web/app/desktop/tags/user-profile.tag deleted file mode 100644 index 7472a47801..0000000000 --- a/src/web/app/desktop/tags/user-profile.tag +++ /dev/null @@ -1,102 +0,0 @@ - -
- -

フォローされています

-
-
{ user.description }
-
-

{ user.profile.birthday.replace('-', '年').replace('-', '月') + '日' } ({ age(user.profile.birthday) }歳)

-
- -
-

{ user.posts_count }ポスト

-

{ user.following_count }人をフォロー

-

{ user.followers_count }人のフォロワー

-
- - -
diff --git a/src/web/app/desktop/tags/user-timeline.tag b/src/web/app/desktop/tags/user-timeline.tag index 08ab47b160..5df13c436c 100644 --- a/src/web/app/desktop/tags/user-timeline.tag +++ b/src/web/app/desktop/tags/user-timeline.tag @@ -91,6 +91,7 @@ this.fetch = cb => { this.api('users/posts', { user_id: this.user.id, + max_date: this.date ? this.date.getTime() : undefined, with_replies: this.mode == 'with-replies' }).then(posts => { this.update({ @@ -132,5 +133,13 @@ }); this.fetch(); }; + + this.warp = date => { + this.update({ + date: date + }); + + this.fetch(); + }; diff --git a/src/web/app/desktop/tags/user.tag b/src/web/app/desktop/tags/user.tag index 2e69872b78..c9bb53fedd 100644 --- a/src/web/app/desktop/tags/user.tag +++ b/src/web/app/desktop/tags/user.tag @@ -3,10 +3,8 @@
-
- - -
+ +
+ + + + avatar +
+

{ user.name }

+

@{ user.username }

+

{ user.profile.location }

+
+ + + +
+ + +
+ +

フォローされています

+
+
{ user.description }
+
+

{ user.profile.birthday.replace('-', '年').replace('-', '月') + '日' } ({ age(user.profile.birthday) }歳)

+
+ +
+

{ user.posts_count }ポスト

+

{ user.following_count }人をフォロー

+

{ user.followers_count }人のフォロワー

+
+ + +
+ + +

フォト

+

読み込んでいます

+
0 }> + +
+
+
+

写真はありません

+ + +
+ + +
+ + +
+
+ +
+
+ +
+ + +
+ + +
+

投稿

+ +
+
+

フォロー/フォロワー

+ +
+
+

いいね

+ +
+ + +
-- cgit v1.2.3-freya From 47e9e888164b6eafd341bba7459fe41cfa91b525 Mon Sep 17 00:00:00 2001 From: syuilo Date: Tue, 14 Nov 2017 23:38:18 +0900 Subject: :v: --- src/api/endpoints/users/get_frequently_replied_users.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/api/endpoints') diff --git a/src/api/endpoints/users/get_frequently_replied_users.ts b/src/api/endpoints/users/get_frequently_replied_users.ts index bb0f3b4cea..a8add623d4 100644 --- a/src/api/endpoints/users/get_frequently_replied_users.ts +++ b/src/api/endpoints/users/get_frequently_replied_users.ts @@ -11,6 +11,10 @@ module.exports = (params, me) => new Promise(async (res, rej) => { const [userId, userIdErr] = $(params.user_id).id().$; if (userIdErr) return rej('invalid user_id param'); + // Get 'limit' parameter + const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$; + if (limitErr) return rej('invalid limit param'); + // Lookup user const user = await User.findOne({ _id: userId @@ -82,8 +86,8 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // Sort replies by frequency const repliedUsersSorted = Object.keys(repliedUsers).sort((a, b) => repliedUsers[b] - repliedUsers[a]); - // Lookup top 10 replies - const topRepliedUsers = repliedUsersSorted.slice(0, 10); + // Extract top replied users + const topRepliedUsers = repliedUsersSorted.slice(0, limit); // Make replies object (includes weights) const repliesObj = await Promise.all(topRepliedUsers.map(async (user) => ({ -- cgit v1.2.3-freya From c46850a69a5f6f33df2cf0b9299c5f0dcf56bcfa Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 15 Nov 2017 09:47:47 +0900 Subject: :v: --- src/api/endpoints/meta.ts | 6 +++++- src/api/models/meta.ts | 7 +++++++ src/web/app/desktop/tags/pages/entrance.tag | 11 ++++++++--- 3 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 src/api/models/meta.ts (limited to 'src/api/endpoints') diff --git a/src/api/endpoints/meta.ts b/src/api/endpoints/meta.ts index a3f1d50329..4f626efa6f 100644 --- a/src/api/endpoints/meta.ts +++ b/src/api/endpoints/meta.ts @@ -4,6 +4,7 @@ import * as os from 'os'; import version from '../../version'; import config from '../../conf'; +import Meta from '../models/meta'; /** * @swagger @@ -39,6 +40,8 @@ import config from '../../conf'; * @return {Promise} */ module.exports = (params) => new Promise(async (res, rej) => { + const meta = (await Meta.findOne()) || {}; + res({ maintainer: config.maintainer, version: version, @@ -49,6 +52,7 @@ module.exports = (params) => new Promise(async (res, rej) => { cpu: { model: os.cpus()[0].model, cores: os.cpus().length - } + }, + top_image: meta.top_image }); }); diff --git a/src/api/models/meta.ts b/src/api/models/meta.ts new file mode 100644 index 0000000000..c7dba8fcba --- /dev/null +++ b/src/api/models/meta.ts @@ -0,0 +1,7 @@ +import db from '../../db/mongodb'; + +export default db.get('meta') as any; // fuck type definition + +export type IMeta = { + top_image: string; +}; diff --git a/src/web/app/desktop/tags/pages/entrance.tag b/src/web/app/desktop/tags/pages/entrance.tag index 914e6b0d58..0dfca1f7a7 100644 --- a/src/web/app/desktop/tags/pages/entrance.tag +++ b/src/web/app/desktop/tags/pages/entrance.tag @@ -113,9 +113,14 @@ this.mode = 'signin'; this.on('mount', () => { - document.documentElement.style.backgroundImage = 'url("/assets/desktop/index.jpg")'; - document.documentElement.style.backgroundSize = 'cover'; - document.documentElement.style.backgroundPosition = 'center'; + document.documentElement.style.backgroundColor = '#444'; + + this.api('meta').then(meta => { + const img = meta.top_image ? meta.top_image : '/assets/desktop/index.jpg'; + document.documentElement.style.backgroundImage = `url("${ img }")`; + document.documentElement.style.backgroundSize = 'cover'; + document.documentElement.style.backgroundPosition = 'center'; + }); this.api('stats').then(stats => { this.update({ -- cgit v1.2.3-freya From 0cd69cabc9f01f19754ad08ed32a15eb4d4518be Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 16 Nov 2017 14:19:14 +0900 Subject: お知らせをブロードキャストできるように MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/en.yml | 6 ++ locales/ja.yml | 6 ++ src/api/endpoints/meta.ts | 3 +- src/web/app/common/tags/raw.tag | 4 ++ .../app/desktop/tags/home-widgets/broadcast.tag | 71 ++++++++++++++++++++-- 5 files changed, 84 insertions(+), 6 deletions(-) (limited to 'src/api/endpoints') diff --git a/locales/en.yml b/locales/en.yml index a2bd9aa1be..9a54eed674 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -396,6 +396,12 @@ desktop: mk-messaging-home-widget: title: "Messaging" + mk-broadcast-home-widget: + fetching: "Fetching" + no-broadcasts: "No broadcasts" + have-a-nice-day: "Have a nice day!" + next: "Next" + mk-repost-form: quote: "Quote..." cancel: "Cancel" diff --git a/locales/ja.yml b/locales/ja.yml index d0292e8c42..dcf4663395 100644 --- a/locales/ja.yml +++ b/locales/ja.yml @@ -396,6 +396,12 @@ desktop: mk-messaging-home-widget: title: "メッセージ" + mk-broadcast-home-widget: + fetching: "確認中" + no-broadcasts: "お知らせはありません" + have-a-nice-day: "良い一日を!" + next: "次" + mk-repost-form: quote: "引用する..." cancel: "キャンセル" diff --git a/src/api/endpoints/meta.ts b/src/api/endpoints/meta.ts index 4f626efa6f..e27ca39e7e 100644 --- a/src/api/endpoints/meta.ts +++ b/src/api/endpoints/meta.ts @@ -53,6 +53,7 @@ module.exports = (params) => new Promise(async (res, rej) => { model: os.cpus()[0].model, cores: os.cpus().length }, - top_image: meta.top_image + top_image: meta.top_image, + broadcasts: meta.broadcasts }); }); diff --git a/src/web/app/common/tags/raw.tag b/src/web/app/common/tags/raw.tag index e1285694e4..adc6de5a3b 100644 --- a/src/web/app/common/tags/raw.tag +++ b/src/web/app/common/tags/raw.tag @@ -5,5 +5,9 @@ diff --git a/src/web/app/desktop/tags/home-widgets/broadcast.tag b/src/web/app/desktop/tags/home-widgets/broadcast.tag index 7caf4dcddd..00fef83742 100644 --- a/src/web/app/desktop/tags/home-widgets/broadcast.tag +++ b/src/web/app/desktop/tags/home-widgets/broadcast.tag @@ -1,4 +1,4 @@ - +
@@ -8,22 +8,35 @@
-

開発者募集中!

-

Misskeyはオープンソースで開発されています。リポジトリはこちら。

+

%i18n:desktop.tags.mk-broadcast-home-widget.fetching%

+

{ + broadcasts.length == 0 ? '%i18n:desktop.tags.mk-broadcast-home-widget.no-broadcasts%' : broadcasts[i].title + }

+

%i18n:desktop.tags.mk-broadcast-home-widget.have-a-nice-day%

+ 1 } onclick={ next }>%i18n:desktop.tags.mk-broadcast-home-widget.next% >>
-- cgit v1.2.3-freya From a8c6d0ed9023f7e0699cfe5c519532231e49cc3b Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 16 Nov 2017 23:46:36 +0900 Subject: #465 --- src/api/common/add-file-to-drive.ts | 3 ++- src/api/endpoints/drive/files/update.ts | 6 +++--- src/api/endpoints/drive/folders/create.ts | 6 +++--- src/api/endpoints/drive/folders/update.ts | 6 +++--- src/api/event.ts | 6 ++++++ src/api/stream/drive.ts | 10 ++++++++++ src/api/streaming.ts | 2 ++ src/web/app/common/mixins.ts | 3 ++- src/web/app/common/scripts/drive-stream-manager.ts | 20 ++++++++++++++++++++ src/web/app/common/scripts/drive-stream.ts | 14 ++++++++++++++ src/web/app/desktop/tags/drive/browser.tag | 22 +++++++++++++--------- src/web/app/mobile/tags/drive.tag | 22 +++++++++++++--------- 12 files changed, 91 insertions(+), 29 deletions(-) create mode 100644 src/api/stream/drive.ts create mode 100644 src/web/app/common/scripts/drive-stream-manager.ts create mode 100644 src/web/app/common/scripts/drive-stream.ts (limited to 'src/api/endpoints') diff --git a/src/api/common/add-file-to-drive.ts b/src/api/common/add-file-to-drive.ts index f96f58cb66..2a649788af 100644 --- a/src/api/common/add-file-to-drive.ts +++ b/src/api/common/add-file-to-drive.ts @@ -13,7 +13,7 @@ import prominence = require('prominence'); import DriveFile, { getGridFSBucket } from '../models/drive-file'; import DriveFolder from '../models/drive-folder'; import serialize from '../serializers/drive-file'; -import event from '../event'; +import event, { publishDriveStream } from '../event'; import config from '../../conf'; const log = debug('misskey:register-drive-file'); @@ -243,6 +243,7 @@ export default (user: any, file: string | stream.Readable, ...args) => new Promi serialize(file).then(serializedFile => { // Publish drive_file_created event event(user._id, 'drive_file_created', serializedFile); + publishDriveStream(user._id, 'file_created', serializedFile); // Register to search database if (config.elasticsearch.enable) { diff --git a/src/api/endpoints/drive/files/update.ts b/src/api/endpoints/drive/files/update.ts index f265142c4d..f39a420d6e 100644 --- a/src/api/endpoints/drive/files/update.ts +++ b/src/api/endpoints/drive/files/update.ts @@ -6,7 +6,7 @@ import DriveFolder from '../../../models/drive-folder'; import DriveFile from '../../../models/drive-file'; import { validateFileName } from '../../../models/drive-file'; import serialize from '../../../serializers/drive-file'; -import event from '../../../event'; +import { publishDriveStream } from '../../../event'; /** * Update a file @@ -72,6 +72,6 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Response res(fileObj); - // Publish drive_file_updated event - event(user._id, 'drive_file_updated', fileObj); + // Publish file_updated event + publishDriveStream(user._id, 'file_updated', fileObj); }); diff --git a/src/api/endpoints/drive/folders/create.ts b/src/api/endpoints/drive/folders/create.ts index 8c875db164..be847b2153 100644 --- a/src/api/endpoints/drive/folders/create.ts +++ b/src/api/endpoints/drive/folders/create.ts @@ -5,7 +5,7 @@ import $ from 'cafy'; import DriveFolder from '../../../models/drive-folder'; import { isValidFolderName } from '../../../models/drive-folder'; import serialize from '../../../serializers/drive-folder'; -import event from '../../../event'; +import { publishDriveStream } from '../../../event'; /** * Create drive folder @@ -52,6 +52,6 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Response res(folderObj); - // Publish drive_folder_created event - event(user._id, 'drive_folder_created', folderObj); + // Publish folder_created event + publishDriveStream(user._id, 'folder_created', folderObj); }); diff --git a/src/api/endpoints/drive/folders/update.ts b/src/api/endpoints/drive/folders/update.ts index 4f2e3d2a7a..ff673402ab 100644 --- a/src/api/endpoints/drive/folders/update.ts +++ b/src/api/endpoints/drive/folders/update.ts @@ -5,7 +5,7 @@ import $ from 'cafy'; import DriveFolder from '../../../models/drive-folder'; import { isValidFolderName } from '../../../models/drive-folder'; import serialize from '../../../serializers/drive-folder'; -import event from '../../../event'; +import { publishDriveStream } from '../../../event'; /** * Update a folder @@ -96,6 +96,6 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Response res(folderObj); - // Publish drive_folder_updated event - event(user._id, 'drive_folder_updated', folderObj); + // Publish folder_updated event + publishDriveStream(user._id, 'folder_updated', folderObj); }); diff --git a/src/api/event.ts b/src/api/event.ts index 927883737e..8605a0f1e4 100644 --- a/src/api/event.ts +++ b/src/api/event.ts @@ -17,6 +17,10 @@ class MisskeyEvent { this.publish(`user-stream:${userId}`, type, typeof value === 'undefined' ? null : value); } + public publishDriveStream(userId: ID, type: string, value?: any): void { + this.publish(`drive-stream:${userId}`, type, typeof value === 'undefined' ? null : value); + } + public publishPostStream(postId: ID, type: string, value?: any): void { this.publish(`post-stream:${postId}`, type, typeof value === 'undefined' ? null : value); } @@ -46,6 +50,8 @@ const ev = new MisskeyEvent(); export default ev.publishUserStream.bind(ev); +export const publishDriveStream = ev.publishDriveStream.bind(ev); + export const publishPostStream = ev.publishPostStream.bind(ev); export const publishMessagingStream = ev.publishMessagingStream.bind(ev); diff --git a/src/api/stream/drive.ts b/src/api/stream/drive.ts new file mode 100644 index 0000000000..c97ab80dcc --- /dev/null +++ b/src/api/stream/drive.ts @@ -0,0 +1,10 @@ +import * as websocket from 'websocket'; +import * as redis from 'redis'; + +export default function(request: websocket.request, connection: websocket.connection, subscriber: redis.RedisClient, user: any): void { + // Subscribe drive stream + subscriber.subscribe(`misskey:drive-stream:${user._id}`); + subscriber.on('message', (_, data) => { + connection.send(data); + }); +} diff --git a/src/api/streaming.ts b/src/api/streaming.ts index 1f0ba848c1..c06d64c245 100644 --- a/src/api/streaming.ts +++ b/src/api/streaming.ts @@ -7,6 +7,7 @@ import AccessToken from './models/access-token'; import isNativeToken from './common/is-native-token'; import homeStream from './stream/home'; +import driveStream from './stream/drive'; import messagingStream from './stream/messaging'; import messagingIndexStream from './stream/messaging-index'; import serverStream from './stream/server'; @@ -58,6 +59,7 @@ module.exports = (server: http.Server) => { const channel = request.resourceURL.pathname === '/' ? homeStream : + request.resourceURL.pathname === '/drive' ? driveStream : request.resourceURL.pathname === '/messaging' ? messagingStream : request.resourceURL.pathname === '/messaging-index' ? messagingIndexStream : null; diff --git a/src/web/app/common/mixins.ts b/src/web/app/common/mixins.ts index b5eb1acc78..5949069624 100644 --- a/src/web/app/common/mixins.ts +++ b/src/web/app/common/mixins.ts @@ -4,6 +4,7 @@ import MiOS from './mios'; import ServerStreamManager from './scripts/server-stream-manager'; import RequestsStreamManager from './scripts/requests-stream-manager'; import MessagingIndexStream from './scripts/messaging-index-stream-manager'; +import DriveStreamManager from './scripts/drive-stream-manager'; export default (mios: MiOS) => { (riot as any).mixin('os', { @@ -30,7 +31,7 @@ export default (mios: MiOS) => { (riot as any).mixin('api', { api: mios.api }); - + (riot as any).mixin('drive-stream', { driveStream: new DriveStreamManager(mios.i) }); (riot as any).mixin('stream', { stream: mios.stream }); (riot as any).mixin('server-stream', { serverStream: new ServerStreamManager() }); diff --git a/src/web/app/common/scripts/drive-stream-manager.ts b/src/web/app/common/scripts/drive-stream-manager.ts new file mode 100644 index 0000000000..8acdd7cbba --- /dev/null +++ b/src/web/app/common/scripts/drive-stream-manager.ts @@ -0,0 +1,20 @@ +import StreamManager from './stream-manager'; +import Connection from './drive-stream'; + +export default class DriveStreamManager extends StreamManager { + private me; + + constructor(me) { + super(); + + this.me = me; + } + + public getConnection() { + if (this.connection == null) { + this.connection = new Connection(this.me); + } + + return this.connection; + } +} diff --git a/src/web/app/common/scripts/drive-stream.ts b/src/web/app/common/scripts/drive-stream.ts new file mode 100644 index 0000000000..1b33435578 --- /dev/null +++ b/src/web/app/common/scripts/drive-stream.ts @@ -0,0 +1,14 @@ +import Stream from './stream'; + +/** + * Drive stream connection + */ +class Connection extends Stream { + constructor(me) { + super('drive', { + i: me.token + }); + } +} + +export default Connection; diff --git a/src/web/app/desktop/tags/drive/browser.tag b/src/web/app/desktop/tags/drive/browser.tag index 18e27f24bc..311209fcb6 100644 --- a/src/web/app/desktop/tags/drive/browser.tag +++ b/src/web/app/desktop/tags/drive/browser.tag @@ -247,7 +247,10 @@ this.mixin('i'); this.mixin('api'); - this.mixin('stream'); + + this.mixin('drive-stream'); + this.connection = this.driveStream.getConnection(); + this.connectionId = this.driveStream.use(); this.files = []; this.folders = []; @@ -280,10 +283,10 @@ }); }); - this.stream.on('drive_file_created', this.onStreamDriveFileCreated); - this.stream.on('drive_file_updated', this.onStreamDriveFileUpdated); - this.stream.on('drive_folder_created', this.onStreamDriveFolderCreated); - this.stream.on('drive_folder_updated', this.onStreamDriveFolderUpdated); + this.connection.on('file_created', this.onStreamDriveFileCreated); + this.connection.on('file_updated', this.onStreamDriveFileUpdated); + this.connection.on('folder_created', this.onStreamDriveFolderCreated); + this.connection.on('folder_updated', this.onStreamDriveFolderUpdated); if (this.opts.folder) { this.move(this.opts.folder); @@ -293,10 +296,11 @@ }); this.on('unmount', () => { - this.stream.off('drive_file_created', this.onStreamDriveFileCreated); - this.stream.off('drive_file_updated', this.onStreamDriveFileUpdated); - this.stream.off('drive_folder_created', this.onStreamDriveFolderCreated); - this.stream.off('drive_folder_updated', this.onStreamDriveFolderUpdated); + this.connection.off('file_created', this.onStreamDriveFileCreated); + this.connection.off('file_updated', this.onStreamDriveFileUpdated); + this.connection.off('folder_created', this.onStreamDriveFolderCreated); + this.connection.off('folder_updated', this.onStreamDriveFolderUpdated); + this.driveStream.dispose(this.connectionId); }); this.onStreamDriveFileCreated = file => { diff --git a/src/web/app/mobile/tags/drive.tag b/src/web/app/mobile/tags/drive.tag index 870a451acb..2c36c43ac5 100644 --- a/src/web/app/mobile/tags/drive.tag +++ b/src/web/app/mobile/tags/drive.tag @@ -172,7 +172,10 @@