Add total moderators/admins in stats
This commit is contained in:
parent
bb7cb0d2fd
commit
0165786f65
|
@ -456,6 +456,12 @@ stats:
|
||||||
abuses:
|
abuses:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
|
total_moderators:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
total_admins:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
previews:
|
previews:
|
||||||
size: 500 # Max number of previews you want to cache
|
size: 500 # Max number of previews you want to cache
|
||||||
|
|
|
@ -454,6 +454,12 @@ stats:
|
||||||
abuses:
|
abuses:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
|
total_moderators:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
total_admins:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#
|
#
|
||||||
# From this point, almost all following keys can be overridden by the web interface
|
# From this point, almost all following keys can be overridden by the web interface
|
||||||
|
|
|
@ -10,6 +10,9 @@ export interface ServerStats extends ActivityPubMessagesSuccess, ActivityPubMess
|
||||||
totalWeeklyActiveUsers: number
|
totalWeeklyActiveUsers: number
|
||||||
totalMonthlyActiveUsers: number
|
totalMonthlyActiveUsers: number
|
||||||
|
|
||||||
|
totalModerators: number
|
||||||
|
totalAdmins: number
|
||||||
|
|
||||||
totalLocalVideos: number
|
totalLocalVideos: number
|
||||||
totalLocalVideoViews: number
|
totalLocalVideoViews: number
|
||||||
totalLocalVideoComments: number
|
totalLocalVideoComments: number
|
||||||
|
|
|
@ -56,7 +56,11 @@ describe('Test stats (excluding redundancy)', function () {
|
||||||
expect(data.totalLocalVideos).to.equal(1)
|
expect(data.totalLocalVideos).to.equal(1)
|
||||||
expect(data.totalLocalVideoViews).to.equal(1)
|
expect(data.totalLocalVideoViews).to.equal(1)
|
||||||
expect(data.totalLocalVideoFilesSize).to.equal(218910)
|
expect(data.totalLocalVideoFilesSize).to.equal(218910)
|
||||||
|
|
||||||
expect(data.totalUsers).to.equal(2)
|
expect(data.totalUsers).to.equal(2)
|
||||||
|
expect(data.totalModerators).to.equal(0)
|
||||||
|
expect(data.totalAdmins).to.equal(1)
|
||||||
|
|
||||||
expect(data.totalVideoComments).to.equal(1)
|
expect(data.totalVideoComments).to.equal(1)
|
||||||
expect(data.totalVideos).to.equal(1)
|
expect(data.totalVideos).to.equal(1)
|
||||||
expect(data.totalInstanceFollowers).to.equal(2)
|
expect(data.totalInstanceFollowers).to.equal(2)
|
||||||
|
@ -71,7 +75,11 @@ describe('Test stats (excluding redundancy)', function () {
|
||||||
expect(data.totalLocalVideos).to.equal(0)
|
expect(data.totalLocalVideos).to.equal(0)
|
||||||
expect(data.totalLocalVideoViews).to.equal(0)
|
expect(data.totalLocalVideoViews).to.equal(0)
|
||||||
expect(data.totalLocalVideoFilesSize).to.equal(0)
|
expect(data.totalLocalVideoFilesSize).to.equal(0)
|
||||||
|
|
||||||
expect(data.totalUsers).to.equal(1)
|
expect(data.totalUsers).to.equal(1)
|
||||||
|
expect(data.totalModerators).to.equal(0)
|
||||||
|
expect(data.totalAdmins).to.equal(1)
|
||||||
|
|
||||||
expect(data.totalVideoComments).to.equal(1)
|
expect(data.totalVideoComments).to.equal(1)
|
||||||
expect(data.totalVideos).to.equal(1)
|
expect(data.totalVideos).to.equal(1)
|
||||||
expect(data.totalInstanceFollowers).to.equal(1)
|
expect(data.totalInstanceFollowers).to.equal(1)
|
||||||
|
@ -85,7 +93,11 @@ describe('Test stats (excluding redundancy)', function () {
|
||||||
expect(data.totalLocalVideoComments).to.equal(0)
|
expect(data.totalLocalVideoComments).to.equal(0)
|
||||||
expect(data.totalLocalVideos).to.equal(0)
|
expect(data.totalLocalVideos).to.equal(0)
|
||||||
expect(data.totalLocalVideoViews).to.equal(0)
|
expect(data.totalLocalVideoViews).to.equal(0)
|
||||||
|
|
||||||
expect(data.totalUsers).to.equal(1)
|
expect(data.totalUsers).to.equal(1)
|
||||||
|
expect(data.totalModerators).to.equal(0)
|
||||||
|
expect(data.totalAdmins).to.equal(1)
|
||||||
|
|
||||||
expect(data.totalVideoComments).to.equal(1)
|
expect(data.totalVideoComments).to.equal(1)
|
||||||
expect(data.totalVideos).to.equal(1)
|
expect(data.totalVideos).to.equal(1)
|
||||||
expect(data.totalInstanceFollowing).to.equal(1)
|
expect(data.totalInstanceFollowing).to.equal(1)
|
||||||
|
@ -420,7 +432,9 @@ describe('Test stats (excluding redundancy)', function () {
|
||||||
await servers[0].run({
|
await servers[0].run({
|
||||||
stats: {
|
stats: {
|
||||||
registration_requests: { enabled: false },
|
registration_requests: { enabled: false },
|
||||||
abuses: { enabled: false }
|
abuses: { enabled: false },
|
||||||
|
total_admins: { enabled: false },
|
||||||
|
total_moderators: { enabled: false }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -433,6 +447,9 @@ describe('Test stats (excluding redundancy)', function () {
|
||||||
expect(data.totalAbuses).to.be.null
|
expect(data.totalAbuses).to.be.null
|
||||||
expect(data.totalAbusesProcessed).to.be.null
|
expect(data.totalAbusesProcessed).to.be.null
|
||||||
expect(data.averageAbuseResponseTimeMs).to.be.null
|
expect(data.averageAbuseResponseTimeMs).to.be.null
|
||||||
|
|
||||||
|
expect(data.totalAdmins).to.be.null
|
||||||
|
expect(data.totalModerators).to.be.null
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -369,6 +369,12 @@ const CONFIG = {
|
||||||
},
|
},
|
||||||
ABUSES: {
|
ABUSES: {
|
||||||
ENABLED: config.get<boolean>('stats.abuses.enabled')
|
ENABLED: config.get<boolean>('stats.abuses.enabled')
|
||||||
|
},
|
||||||
|
TOTAL_MODERATORS: {
|
||||||
|
ENABLED: config.get<boolean>('stats.total_moderators.enabled')
|
||||||
|
},
|
||||||
|
TOTAL_ADMINS: {
|
||||||
|
ENABLED: config.get<boolean>('stats.total_admins.enabled')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ADMIN: {
|
ADMIN: {
|
||||||
|
|
|
@ -49,7 +49,14 @@ class StatsManager {
|
||||||
async getStats () {
|
async getStats () {
|
||||||
const { totalLocalVideos, totalLocalVideoViews, totalVideos } = await VideoModel.getStats()
|
const { totalLocalVideos, totalLocalVideoViews, totalVideos } = await VideoModel.getStats()
|
||||||
const { totalLocalVideoComments, totalVideoComments } = await VideoCommentModel.getStats()
|
const { totalLocalVideoComments, totalVideoComments } = await VideoCommentModel.getStats()
|
||||||
const { totalUsers, totalDailyActiveUsers, totalWeeklyActiveUsers, totalMonthlyActiveUsers } = await UserModel.getStats()
|
const {
|
||||||
|
totalUsers,
|
||||||
|
totalDailyActiveUsers,
|
||||||
|
totalWeeklyActiveUsers,
|
||||||
|
totalMonthlyActiveUsers,
|
||||||
|
totalAdmins,
|
||||||
|
totalModerators
|
||||||
|
} = await UserModel.getStats()
|
||||||
const { totalInstanceFollowers, totalInstanceFollowing } = await ActorFollowModel.getStats()
|
const { totalInstanceFollowers, totalInstanceFollowing } = await ActorFollowModel.getStats()
|
||||||
const { totalLocalVideoFilesSize } = await VideoFileModel.getStats()
|
const { totalLocalVideoFilesSize } = await VideoFileModel.getStats()
|
||||||
const {
|
const {
|
||||||
|
@ -68,6 +75,14 @@ class StatsManager {
|
||||||
totalWeeklyActiveUsers,
|
totalWeeklyActiveUsers,
|
||||||
totalMonthlyActiveUsers,
|
totalMonthlyActiveUsers,
|
||||||
|
|
||||||
|
totalModerators: CONFIG.STATS.TOTAL_MODERATORS.ENABLED
|
||||||
|
? totalModerators
|
||||||
|
: null,
|
||||||
|
|
||||||
|
totalAdmins: CONFIG.STATS.TOTAL_ADMINS.ENABLED
|
||||||
|
? totalAdmins
|
||||||
|
: null,
|
||||||
|
|
||||||
totalLocalVideos,
|
totalLocalVideos,
|
||||||
totalLocalVideoViews,
|
totalLocalVideoViews,
|
||||||
totalLocalVideoComments,
|
totalLocalVideoComments,
|
||||||
|
|
|
@ -8,7 +8,8 @@ import {
|
||||||
VideoPlaylistType,
|
VideoPlaylistType,
|
||||||
type NSFWPolicyType,
|
type NSFWPolicyType,
|
||||||
type UserAdminFlagType,
|
type UserAdminFlagType,
|
||||||
type UserRoleType
|
type UserRoleType,
|
||||||
|
UserRole
|
||||||
} from '@peertube/peertube-models'
|
} from '@peertube/peertube-models'
|
||||||
import { TokensCache } from '@server/lib/auth/tokens-cache.js'
|
import { TokensCache } from '@server/lib/auth/tokens-cache.js'
|
||||||
import { LiveQuotaStore } from '@server/lib/live/index.js'
|
import { LiveQuotaStore } from '@server/lib/live/index.js'
|
||||||
|
@ -67,7 +68,7 @@ import { ActorFollowModel } from '../actor/actor-follow.js'
|
||||||
import { ActorImageModel } from '../actor/actor-image.js'
|
import { ActorImageModel } from '../actor/actor-image.js'
|
||||||
import { ActorModel } from '../actor/actor.js'
|
import { ActorModel } from '../actor/actor.js'
|
||||||
import { OAuthTokenModel } from '../oauth/oauth-token.js'
|
import { OAuthTokenModel } from '../oauth/oauth-token.js'
|
||||||
import { getAdminUsersSort, SequelizeModel, throwIfNotValid } from '../shared/index.js'
|
import { getAdminUsersSort, parseAggregateResult, SequelizeModel, throwIfNotValid } from '../shared/index.js'
|
||||||
import { VideoChannelModel } from '../video/video-channel.js'
|
import { VideoChannelModel } from '../video/video-channel.js'
|
||||||
import { VideoImportModel } from '../video/video-import.js'
|
import { VideoImportModel } from '../video/video-import.js'
|
||||||
import { VideoLiveModel } from '../video/video-live.js'
|
import { VideoLiveModel } from '../video/video-live.js'
|
||||||
|
@ -875,32 +876,31 @@ export class UserModel extends SequelizeModel<UserModel> {
|
||||||
return parseInt(total, 10)
|
return parseInt(total, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
static async getStats () {
|
static getStats () {
|
||||||
function getActiveUsers (days: number) {
|
const query = `SELECT ` +
|
||||||
const query = {
|
`COUNT(*) AS "totalUsers", ` +
|
||||||
where: {
|
`COUNT(*) FILTER (WHERE "lastLoginDate" > NOW() - INTERVAL '1d') AS "totalDailyActiveUsers", ` +
|
||||||
[Op.and]: [
|
`COUNT(*) FILTER (WHERE "lastLoginDate" > NOW() - INTERVAL '7d') AS "totalWeeklyActiveUsers", ` +
|
||||||
literal(`"lastLoginDate" > NOW() - INTERVAL '${days}d'`)
|
`COUNT(*) FILTER (WHERE "lastLoginDate" > NOW() - INTERVAL '30d') AS "totalMonthlyActiveUsers", ` +
|
||||||
]
|
`COUNT(*) FILTER (WHERE "lastLoginDate" > NOW() - INTERVAL '180d') AS "totalHalfYearActiveUsers", ` +
|
||||||
}
|
`COUNT(*) FILTER (WHERE "role" = ${UserRole.MODERATOR}) AS "totalModerators", ` +
|
||||||
|
`COUNT(*) FILTER (WHERE "role" = ${UserRole.ADMINISTRATOR}) AS "totalAdmins" ` +
|
||||||
|
`FROM "user"`
|
||||||
|
|
||||||
|
return UserModel.sequelize.query<any>(query, {
|
||||||
|
type: QueryTypes.SELECT,
|
||||||
|
raw: true
|
||||||
|
}).then(([ row ]) => {
|
||||||
|
return {
|
||||||
|
totalUsers: parseAggregateResult(row.totalUsers),
|
||||||
|
totalDailyActiveUsers: parseAggregateResult(row.totalDailyActiveUsers),
|
||||||
|
totalWeeklyActiveUsers: parseAggregateResult(row.totalWeeklyActiveUsers),
|
||||||
|
totalMonthlyActiveUsers: parseAggregateResult(row.totalMonthlyActiveUsers),
|
||||||
|
totalHalfYearActiveUsers: parseAggregateResult(row.totalHalfYearActiveUsers),
|
||||||
|
totalModerators: parseAggregateResult(row.totalModerators),
|
||||||
|
totalAdmins: parseAggregateResult(row.totalAdmins)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
return UserModel.unscoped().count(query)
|
|
||||||
}
|
|
||||||
|
|
||||||
const totalUsers = await UserModel.unscoped().count()
|
|
||||||
const totalDailyActiveUsers = await getActiveUsers(1)
|
|
||||||
const totalWeeklyActiveUsers = await getActiveUsers(7)
|
|
||||||
const totalMonthlyActiveUsers = await getActiveUsers(30)
|
|
||||||
const totalHalfYearActiveUsers = await getActiveUsers(180)
|
|
||||||
|
|
||||||
return {
|
|
||||||
totalUsers,
|
|
||||||
totalDailyActiveUsers,
|
|
||||||
totalWeeklyActiveUsers,
|
|
||||||
totalMonthlyActiveUsers,
|
|
||||||
totalHalfYearActiveUsers
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static autoComplete (search: string) {
|
static autoComplete (search: string) {
|
||||||
|
|
|
@ -8569,6 +8569,12 @@ components:
|
||||||
type: number
|
type: number
|
||||||
totalMonthlyActiveUsers:
|
totalMonthlyActiveUsers:
|
||||||
type: number
|
type: number
|
||||||
|
totalModerators:
|
||||||
|
type: number
|
||||||
|
description: "**PeerTube >= 6.1** Value is null if the admin disabled total moderators stats"
|
||||||
|
totalAdmins:
|
||||||
|
type: number
|
||||||
|
description: "**PeerTube >= 6.1** Value is null if the admin disabled total admins stats"
|
||||||
totalLocalVideos:
|
totalLocalVideos:
|
||||||
type: number
|
type: number
|
||||||
totalLocalVideoViews:
|
totalLocalVideoViews:
|
||||||
|
|
Loading…
Reference in New Issue