peertube-plugin-static-files-light
Version:
PeerTube Plugin zum Hochladen und Verwalten statischer Dateien mit Admin-Statistiken (einfache Version)
223 lines (191 loc) • 6.9 kB
JavaScript
class StatsRoutes {
constructor(peertubeHelpers, settingsManager) {
this.peertubeHelpers = peertubeHelpers;
this.settingsManager = settingsManager;
}
async checkStatsAccess(req, res, next) {
try {
const user = await this.peertubeHelpers.user.getAuthUser(res);
if (!user || (user.role !== 0 && user.role !== 1)) {
return res.status(403).json({
status: "failure",
message: "Sie haben keine Berechtigung für Statistiken"
});
}
req.user = user;
next();
} catch (error) {
res.status(401).json({
status: "failure",
message: "Authentifizierung erforderlich"
});
}
}
async getInstanceStats(req, res) {
try {
const { from, to, groupBy } = req.query;
// Используем встроенный Date вместо moment
const now = new Date();
const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
let usersCount = 0;
let usersThisMonth = 0;
let videosCount = 0;
let videosThisMonth = 0;
let openAbusesCount = 0;
let videoViewsStats = [];
try {
// Users count
let request = await this.peertubeHelpers.database.query(
'SELECT COUNT(*) AS "count" FROM "user"',
{ type: "SELECT" }
);
if (request && request.length > 0) {
usersCount = parseInt(request[0].count) || 0;
}
// Users this month
request = await this.peertubeHelpers.database.query(
'SELECT COUNT(*) AS "count" FROM "user" WHERE "createdAt" > $dat',
{
type: "SELECT",
bind: { dat: startOfMonth.toISOString() }
}
);
if (request && request.length > 0) {
usersThisMonth = parseInt(request[0].count) || 0;
}
// Videos count
request = await this.peertubeHelpers.database.query(
'SELECT COUNT(*) AS "count" FROM "video" WHERE "remote" = $remote',
{
type: "SELECT",
bind: { remote: false }
}
);
if (request && request.length > 0) {
videosCount = parseInt(request[0].count) || 0;
}
// Videos this month
request = await this.peertubeHelpers.database.query(
'SELECT COUNT(*) AS "count" FROM "video" WHERE "createdAt" > $dat AND "remote" = $remote',
{
type: "SELECT",
bind: {
dat: startOfMonth.toISOString(),
remote: false
}
}
);
if (request && request.length > 0) {
videosThisMonth = parseInt(request[0].count) || 0;
}
// Open abuse count
request = await this.peertubeHelpers.database.query(
'SELECT COUNT(*) AS "count" FROM "abuse" WHERE "state" = $state',
{
type: "SELECT",
bind: { state: 1 }
}
);
if (request && request.length > 0) {
openAbusesCount = parseInt(request[0].count) || 0;
}
// Video views stats - только если запрашиваются
if (from && to) {
videoViewsStats = await this.getVideoViewsStats(from, to, groupBy);
}
} catch (dbError) {
this.peertubeHelpers.logger.error('Database query error:', dbError);
// Возвращаем пустые данные вместо ошибки
}
res.json({
status: "success",
data: {
usersCount,
usersThisMonth,
videosCount,
videosThisMonth,
openAbusesCount,
videoViewsStats
}
});
} catch (error) {
this.peertubeHelpers.logger.error('Stats error:', error);
res.status(500).json({
status: "failure",
message: "Fehler beim Laden der Statistiken"
});
}
}
async getVideoViewsStats(from, to, groupBy = 'day') {
try {
const fromDate = new Date(from);
const toDate = new Date(to);
// Проверяем валидность дат
if (isNaN(fromDate.getTime()) || isNaN(toDate.getTime())) {
return [];
}
const request = await this.peertubeHelpers.database.query(
'SELECT "videoId", "views", "startDate" FROM "videoView" WHERE "startDate" >= $start AND "startDate" <= $end AND "videoId" IN (SELECT "id" FROM "video" WHERE "remote" = $remote) ORDER BY "startDate"',
{
type: "SELECT",
bind: {
start: fromDate.toISOString(),
end: toDate.toISOString(),
remote: false
}
}
);
if (!request || request.length === 0) {
return [];
}
return this.groupVideoViewsStats(request, groupBy);
} catch (error) {
this.peertubeHelpers.logger.error('Video views stats error:', error);
return [];
}
}
groupVideoViewsStats(request, groupBy) {
const groupedStats = {};
for (const videoView of request) {
const date = new Date(videoView.startDate);
let dateKey;
// Упрощенная группировка без moment
switch (groupBy) {
case 'month':
dateKey = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;
break;
case 'year':
dateKey = `${date.getFullYear()}`;
break;
default: // day
dateKey = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
}
const videoKey = videoView.videoId;
if (!groupedStats[dateKey]) {
groupedStats[dateKey] = {};
}
if (!groupedStats[dateKey][videoKey]) {
groupedStats[dateKey][videoKey] = { views: 0 };
}
groupedStats[dateKey][videoKey].views += parseInt(videoView.views) || 0;
}
// Преобразуем в массив и сортируем
const videoViewsStats = Object.keys(groupedStats)
.sort() // Простая сортировка строк (работает для формата YYYY-MM-DD)
.map(dateKey => ({
date: dateKey,
items: Object.keys(groupedStats[dateKey]).map(videoKey => ({
videoId: parseInt(videoKey),
views: groupedStats[dateKey][videoKey].views
}))
}));
return videoViewsStats;
}
registerRoutes(router) {
router.get('/admin/stats',
this.checkStatsAccess.bind(this),
this.getInstanceStats.bind(this)
);
}
}
module.exports = StatsRoutes;