From e31a2f7e55bb96d661945d0475cc5cc678c0eb18 Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 23 Aug 2018 14:56:39 +0900 Subject: Fix bug: Check following request existance --- src/services/following/requests/cancel.ts | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/services') diff --git a/src/services/following/requests/cancel.ts b/src/services/following/requests/cancel.ts index b0b574da58..26e4544d5c 100644 --- a/src/services/following/requests/cancel.ts +++ b/src/services/following/requests/cancel.ts @@ -12,6 +12,15 @@ export default async function(followee: IUser, follower: IUser) { deliver(follower as ILocalUser, content, followee.inbox); } + const request = await FollowRequest.findOne({ + followeeId: followee._id, + followerId: follower._id + }); + + if (request == null) { + throw 'request not found'; + } + await FollowRequest.remove({ followeeId: followee._id, followerId: follower._id -- cgit v1.2.3-freya From 8fc1e07136d5ee203cbd1a1bc2ec00dfeb0e8cf0 Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 23 Aug 2018 15:40:24 +0900 Subject: 1時間単位での集計を追加 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cli/migration/8.0.0.js | 144 ++++++++++++++++++++++++++++++++ package.json | 2 +- src/models/stats.ts | 2 + src/server/api/endpoints/admin/chart.ts | 2 + src/services/update-chart.ts | 106 +++++++++++++---------- 5 files changed, 212 insertions(+), 44 deletions(-) create mode 100644 cli/migration/8.0.0.js (limited to 'src/services') diff --git a/cli/migration/8.0.0.js b/cli/migration/8.0.0.js new file mode 100644 index 0000000000..fd6cb24525 --- /dev/null +++ b/cli/migration/8.0.0.js @@ -0,0 +1,144 @@ +const { default: Stats } = require('../../built/models/stats'); +const { default: User } = require('../../built/models/user'); +const { default: Note } = require('../../built/models/note'); +const { default: DriveFile } = require('../../built/models/drive-file'); + +const now = new Date(); +const y = now.getFullYear(); +const m = now.getMonth(); +const d = now.getDate(); +const h = now.getHours(); +const date = new Date(y, m, d, h); + +async function main() { + await Stats.update({}, { + $set: { + span: 'day' + } + }, { + multi: true + }); + + const localUsersCount = await User.count({ + host: null + }); + + const remoteUsersCount = await User.count({ + host: { $ne: null } + }); + + const localNotesCount = await Note.count({ + '_user.host': null + }); + + const remoteNotesCount = await Note.count({ + '_user.host': { $ne: null } + }); + + const localDriveFilesCount = await DriveFile.count({ + 'metadata._user.host': null + }); + + const remoteDriveFilesCount = await DriveFile.count({ + 'metadata._user.host': { $ne: null } + }); + + const localDriveFilesSize = await DriveFile + .aggregate([{ + $match: { + 'metadata._user.host': null, + 'metadata.deletedAt': { $exists: false } + } + }, { + $project: { + length: true + } + }, { + $group: { + _id: null, + usage: { $sum: '$length' } + } + }]) + .then(aggregates => { + if (aggregates.length > 0) { + return aggregates[0].usage; + } + return 0; + }); + + const remoteDriveFilesSize = await DriveFile + .aggregate([{ + $match: { + 'metadata._user.host': { $ne: null }, + 'metadata.deletedAt': { $exists: false } + } + }, { + $project: { + length: true + } + }, { + $group: { + _id: null, + usage: { $sum: '$length' } + } + }]) + .then(aggregates => { + if (aggregates.length > 0) { + return aggregates[0].usage; + } + return 0; + }); + + await Stats.insert({ + date: date, + span: 'hour', + users: { + local: { + total: localUsersCount, + diff: 0 + }, + remote: { + total: remoteUsersCount, + diff: 0 + } + }, + notes: { + local: { + total: localNotesCount, + diff: 0, + diffs: { + normal: 0, + reply: 0, + renote: 0 + } + }, + remote: { + total: remoteNotesCount, + diff: 0, + diffs: { + normal: 0, + reply: 0, + renote: 0 + } + } + }, + drive: { + local: { + totalCount: localDriveFilesCount, + totalSize: localDriveFilesSize, + diffCount: 0, + diffSize: 0 + }, + remote: { + totalCount: remoteDriveFilesCount, + totalSize: remoteDriveFilesSize, + diffCount: 0, + diffSize: 0 + } + } + }); + + console.log('done'); +} + +main(); diff --git a/package.json b/package.json index 03f63a029d..077d30b96a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "misskey", "author": "syuilo ", - "version": "7.4.1", + "version": "8.0.0", "clientVersion": "1.0.8790", "codename": "nighthike", "main": "./built/index.js", diff --git a/src/models/stats.ts b/src/models/stats.ts index 7bff475c63..c481c3196e 100644 --- a/src/models/stats.ts +++ b/src/models/stats.ts @@ -10,6 +10,8 @@ export interface IStats { date: Date; + span: 'day' | 'hour'; + /** * ユーザーに関する統計 */ diff --git a/src/server/api/endpoints/admin/chart.ts b/src/server/api/endpoints/admin/chart.ts index a0566b11f5..c351c7167d 100644 --- a/src/server/api/endpoints/admin/chart.ts +++ b/src/server/api/endpoints/admin/chart.ts @@ -14,6 +14,7 @@ export default (params: any) => new Promise(async (res, rej) => { const d = now.getDate(); const stats = await Stats.find({ + span: 'day', date: { $gt: new Date(y - 1, m, d) } @@ -44,6 +45,7 @@ export default (params: any) => new Promise(async (res, rej) => { } else { chart.unshift({ date: day, + span: 'day', users: { local: { total: 0, diff --git a/src/services/update-chart.ts b/src/services/update-chart.ts index 6b69adbdc3..0a0f58bb92 100644 --- a/src/services/update-chart.ts +++ b/src/services/update-chart.ts @@ -5,49 +5,59 @@ import { IDriveFile } from '../models/drive-file'; type Omit = Pick>; -async function getTodayStats(): Promise { +async function getCurrentStats(span: 'day' | 'hour'): Promise { const now = new Date(); const y = now.getFullYear(); const m = now.getMonth(); const d = now.getDate(); - const today = new Date(y, m, d); + const h = now.getHours(); - // 今日の統計 - const todayStats = await Stats.findOne({ - date: today + const current = + span == 'day' ? new Date(y, m, d) : + span == 'hour' ? new Date(y, m, d, h) : + null; + + // 現在(今日または今のHour)の統計 + const currentStats = await Stats.findOne({ + span: span, + date: current }); - // 日付が変わってから、初めてのチャート更新なら - if (todayStats == null) { + if (currentStats) { + return currentStats; + } else { + // 集計期間が変わってから、初めてのチャート更新なら // 最も最近の統計を持ってくる + // * 例えば集計期間が「日」である場合で考えると、 // * 昨日何もチャートを更新するような出来事がなかった場合は、 - // 統計がそもそも作られずドキュメントが存在しないということがあり得るため、 - // 「昨日の」と決め打ちせずに「もっとも最近の」とします - const mostRecentStats = await Stats.findOne({}, { + // * 統計がそもそも作られずドキュメントが存在しないということがあり得るため、 + // * 「昨日の」と決め打ちせずに「もっとも最近の」とします + const mostRecentStats = await Stats.findOne({ + span: span + }, { sort: { date: -1 } }); - // 統計が存在しなかったら - // * Misskeyインスタンスを建てて初めてのチャート更新時など - if (mostRecentStats == null) { - // 空の統計を作成 + if (mostRecentStats) { + // 現在の統計を初期挿入 const data: Omit = { - date: today, + span: span, + date: current, users: { local: { - total: 0, + total: mostRecentStats.users.local.total, diff: 0 }, remote: { - total: 0, + total: mostRecentStats.users.remote.total, diff: 0 } }, notes: { local: { - total: 0, + total: mostRecentStats.notes.local.total, diff: 0, diffs: { normal: 0, @@ -56,7 +66,7 @@ async function getTodayStats(): Promise { } }, remote: { - total: 0, + total: mostRecentStats.notes.remote.total, diff: 0, diffs: { normal: 0, @@ -67,14 +77,14 @@ async function getTodayStats(): Promise { }, drive: { local: { - totalCount: 0, - totalSize: 0, + totalCount: mostRecentStats.drive.local.totalCount, + totalSize: mostRecentStats.drive.local.totalSize, diffCount: 0, diffSize: 0 }, remote: { - totalCount: 0, - totalSize: 0, + totalCount: mostRecentStats.drive.remote.totalCount, + totalSize: mostRecentStats.drive.remote.totalSize, diffCount: 0, diffSize: 0 } @@ -85,22 +95,26 @@ async function getTodayStats(): Promise { return stats; } else { - // 今日の統計を初期挿入 - const data: Omit = { - date: today, + // 統計が存在しなかったら + // * Misskeyインスタンスを建てて初めてのチャート更新時など + + // 空の統計を作成 + const emptyStat: Omit = { + span: span, + date: current, users: { local: { - total: mostRecentStats.users.local.total, + total: 0, diff: 0 }, remote: { - total: mostRecentStats.users.remote.total, + total: 0, diff: 0 } }, notes: { local: { - total: mostRecentStats.notes.local.total, + total: 0, diff: 0, diffs: { normal: 0, @@ -109,7 +123,7 @@ async function getTodayStats(): Promise { } }, remote: { - total: mostRecentStats.notes.remote.total, + total: 0, diff: 0, diffs: { normal: 0, @@ -120,36 +134,42 @@ async function getTodayStats(): Promise { }, drive: { local: { - totalCount: mostRecentStats.drive.local.totalCount, - totalSize: mostRecentStats.drive.local.totalSize, + totalCount: 0, + totalSize: 0, diffCount: 0, diffSize: 0 }, remote: { - totalCount: mostRecentStats.drive.remote.totalCount, - totalSize: mostRecentStats.drive.remote.totalSize, + totalCount: 0, + totalSize: 0, diffCount: 0, diffSize: 0 } } }; - const stats = await Stats.insert(data); + const stats = await Stats.insert(emptyStat); return stats; } - } else { - return todayStats; } } -async function update(inc: any) { - const stats = await getTodayStats(); +function update(inc: any) { + getCurrentStats('day').then(stats => { + Stats.findOneAndUpdate({ + _id: stats._id + }, { + $inc: inc + }); + }); - await Stats.findOneAndUpdate({ - _id: stats._id - }, { - $inc: inc + getCurrentStats('hour').then(stats => { + Stats.findOneAndUpdate({ + _id: stats._id + }, { + $inc: inc + }); }); } -- cgit v1.2.3-freya From fc180f030f666815c932a8e42751c6a2fa00a2f6 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 24 Aug 2018 08:35:01 +0900 Subject: Fix bug --- src/services/drive/add-file.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/services') diff --git a/src/services/drive/add-file.ts b/src/services/drive/add-file.ts index b090d56cee..a60d1acbbe 100644 --- a/src/services/drive/add-file.ts +++ b/src/services/drive/add-file.ts @@ -40,7 +40,7 @@ async function save(path: string, name: string, type: string, hash: string, size const thumbnailKey = `${config.drive.prefix}/${uuid.v4()}/${name}.thumbnail.jpg`; const baseUrl = config.drive.baseUrl - || `${ config.drive.config.secure ? 'https' : 'http' }://${ config.drive.config.endPoint }${ config.drive.config.port ? ':' + config.drive.config.port : '' }/${ config.drive.bucket }`; + || `${ config.drive.config.useSSL ? 'https' : 'http' }://${ config.drive.config.endPoint }${ config.drive.config.port ? ':' + config.drive.config.port : '' }/${ config.drive.bucket }`; await minio.putObject(config.drive.bucket, key, fs.createReadStream(path), size, { 'Content-Type': type, -- cgit v1.2.3-freya From 9502586c8b8c925f5c664d002ac82a1b24e37275 Mon Sep 17 00:00:00 2001 From: mei23 Date: Fri, 24 Aug 2018 14:52:53 +0900 Subject: ActivityPub Renote/Replyで 対象Noteを添付しないようにする MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/services/note/create.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/services') diff --git a/src/services/note/create.ts b/src/services/note/create.ts index d8f0f57b63..268bfa5bbe 100644 --- a/src/services/note/create.ts +++ b/src/services/note/create.ts @@ -239,8 +239,8 @@ export default async (user: IUser, data: Option, silent = false) => new Promise< async function renderActivity(data: Option, note: INote) { const content = data.renote && data.text == null - ? renderAnnounce(data.renote.uri ? data.renote.uri : await renderNote(data.renote), note) - : renderCreate(await renderNote(note)); + ? renderAnnounce(data.renote.uri ? data.renote.uri : `${config.url}/notes/${data.renote._id}`, note) + : renderCreate(await renderNote(note, false)); return packAp(content); } -- cgit v1.2.3-freya From 7b6e55047f0bdf02ba0cafd5b90147737a75b556 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 25 Aug 2018 08:35:41 +0900 Subject: #2460 --- .../app/desktop/views/pages/admin/admin.chart.vue | 206 ++++++++++++++++++--- src/models/stats.ts | 106 ++++++++--- src/server/api/endpoints/chart.ts | 77 ++++++-- src/services/update-chart.ts | 88 +++++---- 4 files changed, 374 insertions(+), 103 deletions(-) (limited to 'src/services') diff --git a/src/client/app/desktop/views/pages/admin/admin.chart.vue b/src/client/app/desktop/views/pages/admin/admin.chart.vue index 89e61d4c74..4310ce03d6 100644 --- a/src/client/app/desktop/views/pages/admin/admin.chart.vue +++ b/src/client/app/desktop/views/pages/admin/admin.chart.vue @@ -55,10 +55,10 @@ export default Vue.extend({ case 'local-notes': return this.notesChart('local'); case 'remote-notes': return this.notesChart('remote'); case 'notes-total': return this.notesTotalChart(); - case 'drive': return this.driveChart(false); - case 'drive-total': return this.driveChart(true); - case 'drive-files': return this.driveFilesChart(false); - case 'drive-files-total': return this.driveFilesChart(true); + case 'drive': return this.driveChart(); + case 'drive-total': return this.driveTotalChart(); + case 'drive-files': return this.driveFilesChart(); + case 'drive-files-total': return this.driveFilesTotalChart(); } }, stats(): any[] { @@ -81,7 +81,7 @@ export default Vue.extend({ normal: type == 'local' ? x.notes.local.diffs.normal : type == 'remote' ? x.notes.remote.diffs.normal : x.notes.local.diffs.normal + x.notes.remote.diffs.normal, reply: type == 'local' ? x.notes.local.diffs.reply : type == 'remote' ? x.notes.remote.diffs.reply : x.notes.local.diffs.reply + x.notes.remote.diffs.reply, renote: type == 'local' ? x.notes.local.diffs.renote : type == 'remote' ? x.notes.remote.diffs.renote : x.notes.local.diffs.renote + x.notes.remote.diffs.renote, - all: type == 'local' ? x.notes.local.diff : type == 'remote' ? x.notes.remote.diff : x.notes.local.diff + x.notes.remote.diff + all: type == 'local' ? (x.notes.local.inc + -x.notes.local.dec) : type == 'remote' ? (x.notes.remote.inc + -x.notes.remote.dec) : (x.notes.local.inc + -x.notes.local.dec) + (x.notes.remote.inc + -x.notes.remote.dec) })); return [{ @@ -152,7 +152,7 @@ export default Vue.extend({ return [{ datasets: [{ - label: 'Notes', + label: 'Combined', fill: false, borderColor: '#555', borderWidth: 2, @@ -161,7 +161,7 @@ export default Vue.extend({ lineTension: 0, data: data.map(x => ({ t: x.date, y: x.remoteCount + x.localCount })) }, { - label: 'Remote Notes', + label: 'Remote', fill: true, backgroundColor: 'rgba(65, 221, 222, 0.1)', borderColor: '#41ddde', @@ -170,7 +170,7 @@ export default Vue.extend({ lineTension: 0, data: data.map(x => ({ t: x.date, y: x.remoteCount })) }, { - label: 'Local Notes', + label: 'Local', fill: true, backgroundColor: 'rgba(246, 88, 79, 0.1)', borderColor: '#f6584f', @@ -203,13 +203,13 @@ export default Vue.extend({ usersChart(total: boolean): any { const data = this.stats.slice().reverse().map(x => ({ date: new Date(x.date), - localCount: total ? x.users.local.total : x.users.local.diff, - remoteCount: total ? x.users.remote.total : x.users.remote.diff + localCount: total ? x.users.local.total : (x.users.local.inc + -x.users.local.dec), + remoteCount: total ? x.users.remote.total : (x.users.remote.inc + -x.users.remote.dec) })); return [{ datasets: [{ - label: 'Users', + label: 'Combined', fill: false, borderColor: '#555', borderWidth: 2, @@ -218,7 +218,7 @@ export default Vue.extend({ lineTension: 0, data: data.map(x => ({ t: x.date, y: x.remoteCount + x.localCount })) }, { - label: 'Remote Users', + label: 'Remote', fill: true, backgroundColor: 'rgba(65, 221, 222, 0.1)', borderColor: '#41ddde', @@ -227,7 +227,7 @@ export default Vue.extend({ lineTension: 0, data: data.map(x => ({ t: x.date, y: x.remoteCount })) }, { - label: 'Local Users', + label: 'Local', fill: true, backgroundColor: 'rgba(246, 88, 79, 0.1)', borderColor: '#f6584f', @@ -257,16 +257,93 @@ export default Vue.extend({ }]; }, - driveChart(total: boolean): any { + driveChart(): any { const data = this.stats.slice().reverse().map(x => ({ date: new Date(x.date), - localSize: total ? x.drive.local.totalSize : x.drive.local.diffSize, - remoteSize: total ? x.drive.remote.totalSize : x.drive.remote.diffSize + localInc: x.drive.local.incSize, + localDec: -x.drive.local.decSize, + remoteInc: x.drive.remote.incSize, + remoteDec: -x.drive.remote.decSize, })); return [{ datasets: [{ - label: 'Drive Usage', + label: 'All', + fill: false, + borderColor: '#555', + borderWidth: 2, + borderDash: [4, 4], + pointBackgroundColor: '#fff', + lineTension: 0, + data: data.map(x => ({ t: x.date, y: x.localInc + x.localDec + x.remoteInc + x.remoteDec })) + }, { + label: 'Remote +', + fill: true, + backgroundColor: 'rgba(65, 221, 222, 0.1)', + borderColor: '#41ddde', + borderWidth: 2, + pointBackgroundColor: '#fff', + lineTension: 0, + data: data.map(x => ({ t: x.date, y: x.remoteInc })) + }, { + label: 'Remote -', + fill: true, + backgroundColor: 'rgba(65, 221, 222, 0.1)', + borderColor: '#41ddde', + borderWidth: 2, + pointBackgroundColor: '#fff', + lineTension: 0, + data: data.map(x => ({ t: x.date, y: x.remoteDec })) + }, { + label: 'Local +', + fill: true, + backgroundColor: 'rgba(246, 88, 79, 0.1)', + borderColor: '#f6584f', + borderWidth: 2, + pointBackgroundColor: '#fff', + lineTension: 0, + data: data.map(x => ({ t: x.date, y: x.localInc })) + }, { + label: 'Local -', + fill: true, + backgroundColor: 'rgba(246, 88, 79, 0.1)', + borderColor: '#f6584f', + borderWidth: 2, + pointBackgroundColor: '#fff', + lineTension: 0, + data: data.map(x => ({ t: x.date, y: x.localDec })) + }] + }, { + scales: { + yAxes: [{ + ticks: { + callback: value => { + return Vue.filter('bytes')(value); + } + } + }] + }, + tooltips: { + callbacks: { + label: (tooltipItem, data) => { + const label = data.datasets[tooltipItem.datasetIndex].label || ''; + return `${label}: ${Vue.filter('bytes')(tooltipItem.yLabel)}`; + } + } + } + }]; + }, + + driveTotalChart(): any { + const data = this.stats.slice().reverse().map(x => ({ + date: new Date(x.date), + localSize: x.drive.local.totalSize, + remoteSize: x.drive.remote.totalSize + })); + + return [{ + datasets: [{ + label: 'Combined', fill: false, borderColor: '#555', borderWidth: 2, @@ -275,7 +352,7 @@ export default Vue.extend({ lineTension: 0, data: data.map(x => ({ t: x.date, y: x.remoteSize + x.localSize })) }, { - label: 'Remote Drive Usage', + label: 'Remote', fill: true, backgroundColor: 'rgba(65, 221, 222, 0.1)', borderColor: '#41ddde', @@ -284,7 +361,7 @@ export default Vue.extend({ lineTension: 0, data: data.map(x => ({ t: x.date, y: x.remoteSize })) }, { - label: 'Local Drive Usage', + label: 'Local', fill: true, backgroundColor: 'rgba(246, 88, 79, 0.1)', borderColor: '#f6584f', @@ -314,25 +391,102 @@ export default Vue.extend({ }]; }, - driveFilesChart(total: boolean): any { + driveFilesChart(): any { const data = this.stats.slice().reverse().map(x => ({ date: new Date(x.date), - localCount: total ? x.drive.local.totalCount : x.drive.local.diffCount, - remoteCount: total ? x.drive.remote.totalCount : x.drive.remote.diffCount + localInc: x.drive.local.incCount, + localDec: -x.drive.local.decCount, + remoteInc: x.drive.remote.incCount, + remoteDec: -x.drive.remote.decCount })); return [{ datasets: [{ - label: 'Drive Files', + label: 'All', fill: false, borderColor: '#555', borderWidth: 2, borderDash: [4, 4], pointBackgroundColor: '#fff', lineTension: 0, - data: data.map(x => ({ t: x.date, y: x.remoteCount + x.localCount })) + data: data.map(x => ({ t: x.date, y: x.localInc + x.localDec + x.remoteInc + x.remoteDec })) + }, { + label: 'Remote +', + fill: true, + backgroundColor: 'rgba(65, 221, 222, 0.1)', + borderColor: '#41ddde', + borderWidth: 2, + pointBackgroundColor: '#fff', + lineTension: 0, + data: data.map(x => ({ t: x.date, y: x.remoteInc })) + }, { + label: 'Remote -', + fill: true, + backgroundColor: 'rgba(65, 221, 222, 0.1)', + borderColor: '#41ddde', + borderWidth: 2, + pointBackgroundColor: '#fff', + lineTension: 0, + data: data.map(x => ({ t: x.date, y: x.remoteDec })) + }, { + label: 'Local +', + fill: true, + backgroundColor: 'rgba(246, 88, 79, 0.1)', + borderColor: '#f6584f', + borderWidth: 2, + pointBackgroundColor: '#fff', + lineTension: 0, + data: data.map(x => ({ t: x.date, y: x.localInc })) + }, { + label: 'Local -', + fill: true, + backgroundColor: 'rgba(246, 88, 79, 0.1)', + borderColor: '#f6584f', + borderWidth: 2, + pointBackgroundColor: '#fff', + lineTension: 0, + data: data.map(x => ({ t: x.date, y: x.localDec })) + }] + }, { + scales: { + yAxes: [{ + ticks: { + callback: value => { + return Vue.filter('number')(value); + } + } + }] + }, + tooltips: { + callbacks: { + label: (tooltipItem, data) => { + const label = data.datasets[tooltipItem.datasetIndex].label || ''; + return `${label}: ${Vue.filter('number')(tooltipItem.yLabel)}`; + } + } + } + }]; + }, + + driveFilesTotalChart(): any { + const data = this.stats.slice().reverse().map(x => ({ + date: new Date(x.date), + localCount: x.drive.local.totalCount, + remoteCount: x.drive.remote.totalCount, + })); + + return [{ + datasets: [{ + label: 'Combined', + fill: false, + borderColor: '#555', + borderWidth: 2, + borderDash: [4, 4], + pointBackgroundColor: '#fff', + lineTension: 0, + data: data.map(x => ({ t: x.date, y: x.localCount + x.remoteCount })) }, { - label: 'Remote Drive Files', + label: 'Remote', fill: true, backgroundColor: 'rgba(65, 221, 222, 0.1)', borderColor: '#41ddde', @@ -341,7 +495,7 @@ export default Vue.extend({ lineTension: 0, data: data.map(x => ({ t: x.date, y: x.remoteCount })) }, { - label: 'Local Drive Files', + label: 'Local', fill: true, backgroundColor: 'rgba(246, 88, 79, 0.1)', borderColor: '#f6584f', diff --git a/src/models/stats.ts b/src/models/stats.ts index c481c3196e..3041d3852b 100644 --- a/src/models/stats.ts +++ b/src/models/stats.ts @@ -8,8 +8,14 @@ export default Stats; export interface IStats { _id: mongo.ObjectID; + /** + * 集計日時 + */ date: Date; + /** + * 集計期間 + */ span: 'day' | 'hour'; /** @@ -18,26 +24,36 @@ export interface IStats { users: { local: { /** - * この日時点での、ローカルのユーザーの総計 + * 集計期間時点での、全ユーザー数 (ローカル) */ total: number; /** - * ローカルのユーザー数の前日比 + * 増加したユーザー数 (ローカル) + */ + inc: number; + + /** + * 減少したユーザー数 (ローカル) */ - diff: number; + dec: number; }; remote: { /** - * この日時点での、リモートのユーザーの総計 + * 集計期間時点での、全ユーザー数 (リモート) */ total: number; /** - * リモートのユーザー数の前日比 + * 増加したユーザー数 (リモート) */ - diff: number; + inc: number; + + /** + * 減少したユーザー数 (リモート) + */ + dec: number; }; }; @@ -47,28 +63,33 @@ export interface IStats { notes: { local: { /** - * この日時点での、ローカルの投稿の総計 + * 集計期間時点での、全投稿数 (ローカル) */ total: number; /** - * ローカルの投稿数の前日比 + * 増加した投稿数 (ローカル) */ - diff: number; + inc: number; + + /** + * 減少した投稿数 (ローカル) + */ + dec: number; diffs: { /** - * ローカルの通常の投稿数の前日比 + * 通常の投稿数の差分 (ローカル) */ normal: number; /** - * ローカルのリプライの投稿数の前日比 + * リプライの投稿数の差分 (ローカル) */ reply: number; /** - * ローカルのRenoteの投稿数の前日比 + * Renoteの投稿数の差分 (ローカル) */ renote: number; }; @@ -76,28 +97,33 @@ export interface IStats { remote: { /** - * この日時点での、リモートの投稿の総計 + * 集計期間時点での、全投稿数 (リモート) */ total: number; /** - * リモートの投稿数の前日比 + * 増加した投稿数 (リモート) + */ + inc: number; + + /** + * 減少した投稿数 (リモート) */ - diff: number; + dec: number; diffs: { /** - * リモートの通常の投稿数の前日比 + * 通常の投稿数の差分 (リモート) */ normal: number; /** - * リモートのリプライの投稿数の前日比 + * リプライの投稿数の差分 (リモート) */ reply: number; /** - * リモートのRenoteの投稿数の前日比 + * Renoteの投稿数の差分 (リモート) */ renote: number; }; @@ -110,46 +136,66 @@ export interface IStats { drive: { local: { /** - * この日時点での、ローカルのドライブファイル数の総計 + * 集計期間時点での、全ドライブファイル数 (ローカル) */ totalCount: number; /** - * この日時点での、ローカルのドライブファイルサイズの総計 + * 集計期間時点での、全ドライブファイルの合計サイズ (ローカル) */ totalSize: number; /** - * ローカルのドライブファイル数の前日比 + * 増加したドライブファイル数 (ローカル) + */ + incCount: number; + + /** + * 増加したドライブ使用量 (ローカル) + */ + incSize: number; + + /** + * 減少したドライブファイル数 (ローカル) */ - diffCount: number; + decCount: number; /** - * ローカルのドライブファイルサイズの前日比 + * 減少したドライブ使用量 (ローカル) */ - diffSize: number; + decSize: number; }; remote: { /** - * この日時点での、リモートのドライブファイル数の総計 + * 集計期間時点での、全ドライブファイル数 (リモート) */ totalCount: number; /** - * この日時点での、リモートのドライブファイルサイズの総計 + * 集計期間時点での、全ドライブファイルの合計サイズ (リモート) */ totalSize: number; /** - * リモートのドライブファイル数の前日比 + * 増加したドライブファイル数 (リモート) + */ + incCount: number; + + /** + * 増加したドライブ使用量 (リモート) + */ + incSize: number; + + /** + * 減少したドライブファイル数 (リモート) */ - diffCount: number; + decCount: number; /** - * リモートのドライブファイルサイズの前日比 + * 減少したドライブ使用量 (リモート) */ - diffSize: number; + decSize: number; }; }; } diff --git a/src/server/api/endpoints/chart.ts b/src/server/api/endpoints/chart.ts index da3476f067..514bacaa84 100644 --- a/src/server/api/endpoints/chart.ts +++ b/src/server/api/endpoints/chart.ts @@ -2,6 +2,31 @@ import Stats, { IStats } from '../../../models/stats'; type Omit = Pick>; +function migrateStats(stats: IStats[]) { + stats.forEach(stat => { + const isOldData = stat.users.local.inc == null; + + if (!isOldData) return; + + stat.users.local.inc = (stat as any).users.local.diff; + stat.users.local.dec = 0; + stat.users.remote.inc = (stat as any).users.remote.diff; + stat.users.remote.dec = 0; + stat.notes.local.inc = (stat as any).notes.local.diff; + stat.notes.local.dec = 0; + stat.notes.remote.inc = (stat as any).notes.remote.diff; + stat.notes.remote.dec = 0; + stat.drive.local.incCount = (stat as any).drive.local.diffCount; + stat.drive.local.decCount = 0; + stat.drive.local.incSize = (stat as any).drive.local.diffSize; + stat.drive.local.decSize = 0; + stat.drive.remote.incCount = (stat as any).drive.remote.diffCount; + stat.drive.remote.decCount = 0; + stat.drive.remote.incSize = (stat as any).drive.remote.diffSize; + stat.drive.remote.decSize = 0; + }); +} + export const meta = { }; @@ -44,6 +69,10 @@ export default (params: any) => new Promise(async (res, rej) => { }), ]); + // 後方互換性のため + migrateStats(statsPerDay); + migrateStats(statsPerHour); + const format = (src: IStats[], span: 'day' | 'hour') => { const chart: Array, 'span'>> = []; @@ -70,17 +99,20 @@ export default (params: any) => new Promise(async (res, rej) => { users: { local: { total: mostRecent.users.local.total, - diff: 0 + inc: 0, + dec: 0 }, remote: { total: mostRecent.users.remote.total, - diff: 0 + inc: 0, + dec: 0 } }, notes: { local: { total: mostRecent.notes.local.total, - diff: 0, + inc: 0, + dec: 0, diffs: { normal: 0, reply: 0, @@ -89,7 +121,8 @@ export default (params: any) => new Promise(async (res, rej) => { }, remote: { total: mostRecent.notes.remote.total, - diff: 0, + inc: 0, + dec: 0, diffs: { normal: 0, reply: 0, @@ -101,14 +134,18 @@ export default (params: any) => new Promise(async (res, rej) => { local: { totalCount: mostRecent.drive.local.totalCount, totalSize: mostRecent.drive.local.totalSize, - diffCount: 0, - diffSize: 0 + incCount: 0, + incSize: 0, + decCount: 0, + decSize: 0 }, remote: { totalCount: mostRecent.drive.remote.totalCount, totalSize: mostRecent.drive.remote.totalSize, - diffCount: 0, - diffSize: 0 + incCount: 0, + incSize: 0, + decCount: 0, + decSize: 0 } } }); @@ -118,17 +155,20 @@ export default (params: any) => new Promise(async (res, rej) => { users: { local: { total: 0, - diff: 0 + inc: 0, + dec: 0 }, remote: { total: 0, - diff: 0 + inc: 0, + dec: 0 } }, notes: { local: { total: 0, - diff: 0, + inc: 0, + dec: 0, diffs: { normal: 0, reply: 0, @@ -137,7 +177,8 @@ export default (params: any) => new Promise(async (res, rej) => { }, remote: { total: 0, - diff: 0, + inc: 0, + dec: 0, diffs: { normal: 0, reply: 0, @@ -149,14 +190,18 @@ export default (params: any) => new Promise(async (res, rej) => { local: { totalCount: 0, totalSize: 0, - diffCount: 0, - diffSize: 0 + incCount: 0, + incSize: 0, + decCount: 0, + decSize: 0 }, remote: { totalCount: 0, totalSize: 0, - diffCount: 0, - diffSize: 0 + incCount: 0, + incSize: 0, + decCount: 0, + decSize: 0 } } }); diff --git a/src/services/update-chart.ts b/src/services/update-chart.ts index 0a0f58bb92..1f8da6be9f 100644 --- a/src/services/update-chart.ts +++ b/src/services/update-chart.ts @@ -48,17 +48,20 @@ async function getCurrentStats(span: 'day' | 'hour'): Promise { users: { local: { total: mostRecentStats.users.local.total, - diff: 0 + inc: 0, + dec: 0 }, remote: { total: mostRecentStats.users.remote.total, - diff: 0 + inc: 0, + dec: 0 } }, notes: { local: { total: mostRecentStats.notes.local.total, - diff: 0, + inc: 0, + dec: 0, diffs: { normal: 0, reply: 0, @@ -67,7 +70,8 @@ async function getCurrentStats(span: 'day' | 'hour'): Promise { }, remote: { total: mostRecentStats.notes.remote.total, - diff: 0, + inc: 0, + dec: 0, diffs: { normal: 0, reply: 0, @@ -79,14 +83,18 @@ async function getCurrentStats(span: 'day' | 'hour'): Promise { local: { totalCount: mostRecentStats.drive.local.totalCount, totalSize: mostRecentStats.drive.local.totalSize, - diffCount: 0, - diffSize: 0 + incCount: 0, + incSize: 0, + decCount: 0, + decSize: 0 }, remote: { totalCount: mostRecentStats.drive.remote.totalCount, totalSize: mostRecentStats.drive.remote.totalSize, - diffCount: 0, - diffSize: 0 + incCount: 0, + incSize: 0, + decCount: 0, + decSize: 0 } } }; @@ -105,17 +113,20 @@ async function getCurrentStats(span: 'day' | 'hour'): Promise { users: { local: { total: 0, - diff: 0 + inc: 0, + dec: 0 }, remote: { total: 0, - diff: 0 + inc: 0, + dec: 0 } }, notes: { local: { total: 0, - diff: 0, + inc: 0, + dec: 0, diffs: { normal: 0, reply: 0, @@ -124,7 +135,8 @@ async function getCurrentStats(span: 'day' | 'hour'): Promise { }, remote: { total: 0, - diff: 0, + inc: 0, + dec: 0, diffs: { normal: 0, reply: 0, @@ -136,14 +148,18 @@ async function getCurrentStats(span: 'day' | 'hour'): Promise { local: { totalCount: 0, totalSize: 0, - diffCount: 0, - diffSize: 0 + incCount: 0, + incSize: 0, + decCount: 0, + decSize: 0 }, remote: { totalCount: 0, totalSize: 0, - diffCount: 0, - diffSize: 0 + incCount: 0, + incSize: 0, + decCount: 0, + decSize: 0 } } }; @@ -174,46 +190,56 @@ function update(inc: any) { } export async function updateUserStats(user: IUser, isAdditional: boolean) { - const amount = isAdditional ? 1 : -1; const origin = isLocalUser(user) ? 'local' : 'remote'; const inc = {} as any; - inc[`users.${origin}.total`] = amount; - inc[`users.${origin}.diff`] = amount; + inc[`users.${origin}.total`] = isAdditional ? 1 : -1; + if (isAdditional) { + inc[`users.${origin}.inc`] = 1; + } else { + inc[`users.${origin}.dec`] = 1; + } await update(inc); } export async function updateNoteStats(note: INote, isAdditional: boolean) { - const amount = isAdditional ? 1 : -1; const origin = isLocalUser(note._user) ? 'local' : 'remote'; const inc = {} as any; - inc[`notes.${origin}.total`] = amount; - inc[`notes.${origin}.diff`] = amount; + inc[`notes.${origin}.total`] = isAdditional ? 1 : -1; + + if (isAdditional) { + inc[`notes.${origin}.inc`] = 1; + } else { + inc[`notes.${origin}.dec`] = 1; + } if (note.replyId != null) { - inc[`notes.${origin}.diffs.reply`] = amount; + inc[`notes.${origin}.diffs.reply`] = isAdditional ? 1 : -1; } else if (note.renoteId != null) { - inc[`notes.${origin}.diffs.renote`] = amount; + inc[`notes.${origin}.diffs.renote`] = isAdditional ? 1 : -1; } else { - inc[`notes.${origin}.diffs.normal`] = amount; + inc[`notes.${origin}.diffs.normal`] = isAdditional ? 1 : -1; } await update(inc); } export async function updateDriveStats(file: IDriveFile, isAdditional: boolean) { - const amount = isAdditional ? 1 : -1; - const size = isAdditional ? file.length : -file.length; const origin = isLocalUser(file.metadata._user) ? 'local' : 'remote'; const inc = {} as any; - inc[`drive.${origin}.totalCount`] = amount; - inc[`drive.${origin}.diffCount`] = amount; - inc[`drive.${origin}.totalSize`] = size; - inc[`drive.${origin}.diffSize`] = size; + inc[`drive.${origin}.totalCount`] = isAdditional ? 1 : -1; + inc[`drive.${origin}.totalSize`] = isAdditional ? file.length : -file.length; + if (isAdditional) { + inc[`drive.${origin}.incCount`] = 1; + inc[`drive.${origin}.incSize`] = file.length; + } else { + inc[`drive.${origin}.decCount`] = 1; + inc[`drive.${origin}.decSize`] = file.length; + } await update(inc); } -- cgit v1.2.3-freya From 4e8033d5a40f0908b37bf679b0cd823d0393459f Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 25 Aug 2018 10:28:09 +0900 Subject: Fix bug --- src/services/drive/add-file.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/services') diff --git a/src/services/drive/add-file.ts b/src/services/drive/add-file.ts index a60d1acbbe..1da0f49a24 100644 --- a/src/services/drive/add-file.ts +++ b/src/services/drive/add-file.ts @@ -116,7 +116,8 @@ async function deleteOldFile(user: IRemoteUser) { const oldFile = await DriveFile.findOne({ _id: { $nin: [user.avatarId, user.bannerId] - } + }, + 'metadata.userId': user._id }, { sort: { _id: 1 -- cgit v1.2.3-freya From ffcb2f755c2d20e62272212905c7d2ca795e4c3d Mon Sep 17 00:00:00 2001 From: mei23 Date: Sat, 25 Aug 2018 14:12:44 +0900 Subject: Send actor in CreateNote, Announce --- src/remote/activitypub/renderer/announce.ts | 1 + src/remote/activitypub/renderer/create.ts | 16 ++++++++++++---- src/services/note/create.ts | 2 +- 3 files changed, 14 insertions(+), 5 deletions(-) (limited to 'src/services') diff --git a/src/remote/activitypub/renderer/announce.ts b/src/remote/activitypub/renderer/announce.ts index 6d5a67b5c3..f6276ade04 100644 --- a/src/remote/activitypub/renderer/announce.ts +++ b/src/remote/activitypub/renderer/announce.ts @@ -6,6 +6,7 @@ export default (object: any, note: INote) => { return { id: `${config.url}/notes/${note._id}`, + actor: `${config.url}/users/${note.userId}`, type: 'Announce', published: note.createdAt.toISOString(), to: ['https://www.w3.org/ns/activitystreams#Public'], diff --git a/src/remote/activitypub/renderer/create.ts b/src/remote/activitypub/renderer/create.ts index b8bf98a655..42b36195ff 100644 --- a/src/remote/activitypub/renderer/create.ts +++ b/src/remote/activitypub/renderer/create.ts @@ -1,4 +1,12 @@ -export default (object: any) => ({ - type: 'Create', - object -}); +import config from '../../../config'; +import { INote } from '../../../models/note'; + +export default (object: any, note: INote) => { + return { + id: `${config.url}/notes/${note._id}/activity`, + actor: `${config.url}/users/${note.userId}`, + type: 'Create', + published: note.createdAt.toISOString(), + object + }; +}; diff --git a/src/services/note/create.ts b/src/services/note/create.ts index 268bfa5bbe..63e3557828 100644 --- a/src/services/note/create.ts +++ b/src/services/note/create.ts @@ -240,7 +240,7 @@ export default async (user: IUser, data: Option, silent = false) => new Promise< async function renderActivity(data: Option, note: INote) { const content = data.renote && data.text == null ? renderAnnounce(data.renote.uri ? data.renote.uri : `${config.url}/notes/${data.renote._id}`, note) - : renderCreate(await renderNote(note, false)); + : renderCreate(await renderNote(note, false), note); return packAp(content); } -- cgit v1.2.3-freya From a39aaf6eb1fb4da308f6a187aec42fce035574af Mon Sep 17 00:00:00 2001 From: mei23 Date: Sat, 25 Aug 2018 14:46:47 +0900 Subject: Send actor in Undo Follow --- src/remote/activitypub/renderer/undo.ts | 6 +++++- src/services/following/delete.ts | 2 +- src/services/following/requests/cancel.ts | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'src/services') diff --git a/src/remote/activitypub/renderer/undo.ts b/src/remote/activitypub/renderer/undo.ts index 4498409a57..bf90a3f281 100644 --- a/src/remote/activitypub/renderer/undo.ts +++ b/src/remote/activitypub/renderer/undo.ts @@ -1,4 +1,8 @@ -export default (object: any) => ({ +import config from '../../../config'; +import { ILocalUser, IUser } from "../../../models/user"; + +export default (object: any, user: ILocalUser | IUser) => ({ type: 'Undo', + actor: `${config.url}/users/${user._id}`, object }); diff --git a/src/services/following/delete.ts b/src/services/following/delete.ts index 8a9f739bd4..7c285e9eac 100644 --- a/src/services/following/delete.ts +++ b/src/services/following/delete.ts @@ -56,7 +56,7 @@ export default async function(follower: IUser, followee: IUser) { } if (isLocalUser(follower) && isRemoteUser(followee)) { - const content = pack(renderUndo(renderFollow(follower, followee))); + const content = pack(renderUndo(renderFollow(follower, followee), follower)); deliver(follower, content, followee.inbox); } } diff --git a/src/services/following/requests/cancel.ts b/src/services/following/requests/cancel.ts index 26e4544d5c..9655a95f04 100644 --- a/src/services/following/requests/cancel.ts +++ b/src/services/following/requests/cancel.ts @@ -8,7 +8,7 @@ import { publishUserStream } from '../../../stream'; export default async function(followee: IUser, follower: IUser) { if (isRemoteUser(followee)) { - const content = pack(renderUndo(renderFollow(follower, followee))); + const content = pack(renderUndo(renderFollow(follower, followee), follower)); deliver(follower as ILocalUser, content, followee.inbox); } -- cgit v1.2.3-freya From ac474f388439ec09cd4429e4ebba9b89365a2b79 Mon Sep 17 00:00:00 2001 From: mei23 Date: Sat, 25 Aug 2018 14:52:35 +0900 Subject: Send actor in Delete --- src/remote/activitypub/renderer/delete.ts | 6 +++++- src/services/note/delete.ts | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src/services') diff --git a/src/remote/activitypub/renderer/delete.ts b/src/remote/activitypub/renderer/delete.ts index f468a22e24..2a4e70e25e 100644 --- a/src/remote/activitypub/renderer/delete.ts +++ b/src/remote/activitypub/renderer/delete.ts @@ -1,4 +1,8 @@ -export default (object: any) => ({ +import config from '../../../config'; +import { ILocalUser } from "../../../models/user"; + +export default (object: any, user: ILocalUser) => ({ type: 'Delete', + actor: `${config.url}/users/${user._id}`, object }); diff --git a/src/services/note/delete.ts b/src/services/note/delete.ts index d444b13a8b..d0e2b12b41 100644 --- a/src/services/note/delete.ts +++ b/src/services/note/delete.ts @@ -32,7 +32,7 @@ export default async function(user: IUser, note: INote) { //#region ローカルの投稿なら削除アクティビティを配送 if (isLocalUser(user)) { - const content = pack(renderDelete(await renderNote(note))); + const content = pack(renderDelete(await renderNote(note), user)); const followings = await Following.find({ followeeId: user._id, -- cgit v1.2.3-freya