diff --git a/server/controllers/StatsController.js b/server/controllers/StatsController.js deleted file mode 100644 index 32ed19734..000000000 --- a/server/controllers/StatsController.js +++ /dev/null @@ -1,75 +0,0 @@ -const { Request, Response, NextFunction } = require('express') -const Logger = require('../Logger') - -const adminStats = require('../utils/queries/adminStats') - -/** - * @typedef RequestUserObject - * @property {import('../models/User')} user - * - * @typedef {Request & RequestUserObject} RequestWithUser - */ - -class StatsController { - constructor() {} - - /** - * GET: /api/stats/server - * Currently not in use - * - * @param {RequestWithUser} req - * @param {Response} res - */ - async getServerStats(req, res) { - Logger.debug('[StatsController] getServerStats') - const totalSize = await adminStats.getTotalSize() - const numAudioFiles = await adminStats.getNumAudioFiles() - - res.json({ - books: { - ...totalSize.books, - numAudioFiles: numAudioFiles.numBookAudioFiles - }, - podcasts: { - ...totalSize.podcasts, - numAudioFiles: numAudioFiles.numPodcastAudioFiles - }, - total: { - ...totalSize.total, - numAudioFiles: numAudioFiles.numAudioFiles - } - }) - } - - /** - * GET: /api/stats/year/:year - * - * @param {RequestWithUser} req - * @param {Response} res - */ - async getAdminStatsForYear(req, res) { - const year = Number(req.params.year) - if (isNaN(year) || year < 2000 || year > 9999) { - Logger.error(`[StatsController] Invalid year "${year}"`) - return res.status(400).send('Invalid year') - } - const stats = await adminStats.getStatsForYear(year) - res.json(stats) - } - - /** - * - * @param {RequestWithUser} req - * @param {Response} res - * @param {NextFunction} next - */ - async middleware(req, res, next) { - if (!req.user.isAdminOrUp) { - Logger.error(`[StatsController] Non-admin user "${req.user.username}" attempted to access stats route`) - return res.sendStatus(403) - } - - next() - } -} -module.exports = new StatsController() diff --git a/server/routers/ApiRouter.js b/server/routers/ApiRouter.js index ecb1555f1..78a5291d3 100644 --- a/server/routers/ApiRouter.js +++ b/server/routers/ApiRouter.js @@ -33,7 +33,8 @@ const RSSFeedController = require('../controllers/RSSFeedController') const CustomMetadataProviderController = require('../controllers/CustomMetadataProviderController') const MiscController = require('../controllers/MiscController') const ShareController = require('../controllers/ShareController') -const StatsController = require('../controllers/StatsController') + +const { getTitleIgnorePrefix } = require('../utils/index') class ApiRouter { constructor(Server) { @@ -319,12 +320,6 @@ class ApiRouter { this.router.post('/share/mediaitem', ShareController.createMediaItemShare.bind(this)) this.router.delete('/share/mediaitem/:id', ShareController.deleteMediaItemShare.bind(this)) - // - // Stats Routes - // - this.router.get('/stats/year/:year', StatsController.middleware.bind(this), StatsController.getAdminStatsForYear.bind(this)) - this.router.get('/stats/server', StatsController.middleware.bind(this), StatsController.getServerStats.bind(this)) - // // Misc Routes // @@ -343,6 +338,7 @@ class ApiRouter { this.router.get('/auth-settings', MiscController.getAuthSettings.bind(this)) this.router.patch('/auth-settings', MiscController.updateAuthSettings.bind(this)) this.router.post('/watcher/update', MiscController.updateWatchedPath.bind(this)) + this.router.get('/stats/year/:year', MiscController.getAdminStatsForYear.bind(this)) this.router.get('/logger-data', MiscController.getLoggerData.bind(this)) } diff --git a/server/utils/queries/adminStats.js b/server/utils/queries/adminStats.js index 3184fbe38..9d7f572a3 100644 --- a/server/utils/queries/adminStats.js +++ b/server/utils/queries/adminStats.js @@ -167,51 +167,5 @@ module.exports = { topNarrators, topGenres } - }, - - /** - * Get total file size and number of items for books and podcasts - * - * @typedef {Object} SizeObject - * @property {number} totalSize - * @property {number} numItems - * - * @returns {Promise<{books: SizeObject, podcasts: SizeObject, total: SizeObject}}>} - */ - async getTotalSize() { - const [mediaTypeStats] = await Database.sequelize.query(`SELECT li.mediaType, SUM(li.size) AS totalSize, COUNT(*) AS numItems FROM libraryItems li group by li.mediaType;`) - const bookStats = mediaTypeStats.find((m) => m.mediaType === 'book') - const podcastStats = mediaTypeStats.find((m) => m.mediaType === 'podcast') - - return { - books: { - totalSize: bookStats?.totalSize || 0, - numItems: bookStats?.numItems || 0 - }, - podcasts: { - totalSize: podcastStats?.totalSize || 0, - numItems: podcastStats?.numItems || 0 - }, - total: { - totalSize: (bookStats?.totalSize || 0) + (podcastStats?.totalSize || 0), - numItems: (bookStats?.numItems || 0) + (podcastStats?.numItems || 0) - } - } - }, - - /** - * Get total number of audio files for books and podcasts - * - * @returns {Promise<{numBookAudioFiles: number, numPodcastAudioFiles: number, numAudioFiles: number}>} - */ - async getNumAudioFiles() { - const [numBookAudioFilesRow] = await Database.sequelize.query(`SELECT SUM(json_array_length(b.audioFiles)) AS numAudioFiles FROM books b;`) - const numBookAudioFiles = numBookAudioFilesRow[0]?.numAudioFiles || 0 - const numPodcastAudioFiles = await Database.podcastEpisodeModel.count() - return { - numBookAudioFiles, - numPodcastAudioFiles, - numAudioFiles: numBookAudioFiles + numPodcastAudioFiles - } } }