278 lines
5.8 KiB
TypeScript
278 lines
5.8 KiB
TypeScript
import $ from 'cafy';
|
|
import Stats, { IStats } from '../../../models/stats';
|
|
import getParams from '../get-params';
|
|
|
|
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
|
|
|
|
function migrateStats(stats: IStats[]) {
|
|
stats.forEach(stat => {
|
|
if (stat.network == null) {
|
|
stat.network = {
|
|
requests: 0,
|
|
totalTime: 0,
|
|
incomingBytes: 0,
|
|
outgoingBytes: 0
|
|
};
|
|
}
|
|
|
|
const isOldData =
|
|
stat.users.local.inc == null ||
|
|
stat.users.local.dec == null ||
|
|
stat.users.remote.inc == null ||
|
|
stat.users.remote.dec == null ||
|
|
stat.notes.local.inc == null ||
|
|
stat.notes.local.dec == null ||
|
|
stat.notes.remote.inc == null ||
|
|
stat.notes.remote.dec == null ||
|
|
stat.drive.local.incCount == null ||
|
|
stat.drive.local.decCount == null ||
|
|
stat.drive.local.incSize == null ||
|
|
stat.drive.local.decSize == null ||
|
|
stat.drive.remote.incCount == null ||
|
|
stat.drive.remote.decCount == null ||
|
|
stat.drive.remote.incSize == null ||
|
|
stat.drive.remote.decSize == 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 = {
|
|
desc: {
|
|
'ja-JP': 'インスタンスの統計を取得します。'
|
|
},
|
|
|
|
params: {
|
|
limit: $.num.optional.range(1, 100).note({
|
|
default: 30,
|
|
desc: {
|
|
'ja-JP': '最大数'
|
|
}
|
|
}),
|
|
}
|
|
};
|
|
|
|
export default (params: any) => new Promise(async (res, rej) => {
|
|
const [ps, psErr] = getParams(meta, params);
|
|
if (psErr) throw psErr;
|
|
|
|
const daysRange = ps.limit;
|
|
const hoursRange = ps.limit;
|
|
|
|
const now = new Date();
|
|
const y = now.getFullYear();
|
|
const m = now.getMonth();
|
|
const d = now.getDate();
|
|
const h = now.getHours();
|
|
|
|
const [statsPerDay, statsPerHour] = await Promise.all([
|
|
Stats.find({
|
|
span: 'day',
|
|
date: {
|
|
$gt: new Date(y, m, d - daysRange)
|
|
}
|
|
}, {
|
|
sort: {
|
|
date: -1
|
|
},
|
|
fields: {
|
|
_id: 0
|
|
}
|
|
}),
|
|
Stats.find({
|
|
span: 'hour',
|
|
date: {
|
|
$gt: new Date(y, m, d, h - hoursRange)
|
|
}
|
|
}, {
|
|
sort: {
|
|
date: -1
|
|
},
|
|
fields: {
|
|
_id: 0
|
|
}
|
|
}),
|
|
]);
|
|
|
|
// 後方互換性のため
|
|
migrateStats(statsPerDay);
|
|
migrateStats(statsPerHour);
|
|
|
|
const format = (src: IStats[], span: 'day' | 'hour') => {
|
|
const chart: Array<Omit<Omit<IStats, '_id'>, 'span'>> = [];
|
|
|
|
const range =
|
|
span == 'day' ? daysRange :
|
|
span == 'hour' ? hoursRange :
|
|
null;
|
|
|
|
for (let i = (range - 1); i >= 0; i--) {
|
|
const current =
|
|
span == 'day' ? new Date(y, m, d - i) :
|
|
span == 'hour' ? new Date(y, m, d, h - i) :
|
|
null;
|
|
|
|
const stat = src.find(s => s.date.getTime() == current.getTime());
|
|
|
|
if (stat) {
|
|
chart.unshift(stat);
|
|
} else { // 隙間埋め
|
|
const mostRecent = src.find(s => s.date.getTime() < current.getTime());
|
|
if (mostRecent) {
|
|
chart.unshift({
|
|
date: current,
|
|
users: {
|
|
local: {
|
|
total: mostRecent.users.local.total,
|
|
inc: 0,
|
|
dec: 0
|
|
},
|
|
remote: {
|
|
total: mostRecent.users.remote.total,
|
|
inc: 0,
|
|
dec: 0
|
|
}
|
|
},
|
|
notes: {
|
|
local: {
|
|
total: mostRecent.notes.local.total,
|
|
inc: 0,
|
|
dec: 0,
|
|
diffs: {
|
|
normal: 0,
|
|
reply: 0,
|
|
renote: 0
|
|
}
|
|
},
|
|
remote: {
|
|
total: mostRecent.notes.remote.total,
|
|
inc: 0,
|
|
dec: 0,
|
|
diffs: {
|
|
normal: 0,
|
|
reply: 0,
|
|
renote: 0
|
|
}
|
|
}
|
|
},
|
|
drive: {
|
|
local: {
|
|
totalCount: mostRecent.drive.local.totalCount,
|
|
totalSize: mostRecent.drive.local.totalSize,
|
|
incCount: 0,
|
|
incSize: 0,
|
|
decCount: 0,
|
|
decSize: 0
|
|
},
|
|
remote: {
|
|
totalCount: mostRecent.drive.remote.totalCount,
|
|
totalSize: mostRecent.drive.remote.totalSize,
|
|
incCount: 0,
|
|
incSize: 0,
|
|
decCount: 0,
|
|
decSize: 0
|
|
}
|
|
},
|
|
network: {
|
|
requests: 0,
|
|
totalTime: 0,
|
|
incomingBytes: 0,
|
|
outgoingBytes: 0
|
|
}
|
|
});
|
|
} else {
|
|
chart.unshift({
|
|
date: current,
|
|
users: {
|
|
local: {
|
|
total: 0,
|
|
inc: 0,
|
|
dec: 0
|
|
},
|
|
remote: {
|
|
total: 0,
|
|
inc: 0,
|
|
dec: 0
|
|
}
|
|
},
|
|
notes: {
|
|
local: {
|
|
total: 0,
|
|
inc: 0,
|
|
dec: 0,
|
|
diffs: {
|
|
normal: 0,
|
|
reply: 0,
|
|
renote: 0
|
|
}
|
|
},
|
|
remote: {
|
|
total: 0,
|
|
inc: 0,
|
|
dec: 0,
|
|
diffs: {
|
|
normal: 0,
|
|
reply: 0,
|
|
renote: 0
|
|
}
|
|
}
|
|
},
|
|
drive: {
|
|
local: {
|
|
totalCount: 0,
|
|
totalSize: 0,
|
|
incCount: 0,
|
|
incSize: 0,
|
|
decCount: 0,
|
|
decSize: 0
|
|
},
|
|
remote: {
|
|
totalCount: 0,
|
|
totalSize: 0,
|
|
incCount: 0,
|
|
incSize: 0,
|
|
decCount: 0,
|
|
decSize: 0
|
|
}
|
|
},
|
|
network: {
|
|
requests: 0,
|
|
totalTime: 0,
|
|
incomingBytes: 0,
|
|
outgoingBytes: 0
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
chart.forEach(x => {
|
|
delete (x as any).span;
|
|
});
|
|
|
|
return chart;
|
|
};
|
|
|
|
res({
|
|
perDay: format(statsPerDay, 'day'),
|
|
perHour: format(statsPerHour, 'hour')
|
|
});
|
|
});
|