mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-08-04 10:14:36 +02:00
Add:Year in review card for server stats #2373
This commit is contained in:
parent
68d36522b1
commit
2738402aac
8 changed files with 414 additions and 48 deletions
118
server/utils/queries/adminStats.js
Normal file
118
server/utils/queries/adminStats.js
Normal file
|
@ -0,0 +1,118 @@
|
|||
const Sequelize = require('sequelize')
|
||||
const Database = require('../../Database')
|
||||
const PlaybackSession = require('../../models/PlaybackSession')
|
||||
const fsExtra = require('../../libs/fsExtra')
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
*
|
||||
* @param {number} year YYYY
|
||||
* @returns {Promise<PlaybackSession[]>}
|
||||
*/
|
||||
async getListeningSessionsForYear(year) {
|
||||
const sessions = await Database.playbackSessionModel.findAll({
|
||||
where: {
|
||||
createdAt: {
|
||||
[Sequelize.Op.gte]: `${year}-01-01`,
|
||||
[Sequelize.Op.lt]: `${year + 1}-01-01`
|
||||
}
|
||||
}
|
||||
})
|
||||
return sessions
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} year YYYY
|
||||
* @returns {Promise<number>}
|
||||
*/
|
||||
async getNumAuthorsAddedForYear(year) {
|
||||
const count = await Database.authorModel.count({
|
||||
where: {
|
||||
createdAt: {
|
||||
[Sequelize.Op.gte]: `${year}-01-01`,
|
||||
[Sequelize.Op.lt]: `${year + 1}-01-01`
|
||||
}
|
||||
}
|
||||
})
|
||||
return count
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} year YYYY
|
||||
* @returns {Promise<import('../../models/Book')[]>}
|
||||
*/
|
||||
async getBooksAddedForYear(year) {
|
||||
const books = await Database.bookModel.findAll({
|
||||
attributes: ['id', 'title', 'coverPath', 'duration', 'createdAt'],
|
||||
where: {
|
||||
createdAt: {
|
||||
[Sequelize.Op.gte]: `${year}-01-01`,
|
||||
[Sequelize.Op.lt]: `${year + 1}-01-01`
|
||||
}
|
||||
},
|
||||
include: {
|
||||
model: Database.libraryItemModel,
|
||||
attributes: ['id', 'mediaId', 'mediaType', 'size'],
|
||||
required: true
|
||||
},
|
||||
order: Database.sequelize.random()
|
||||
})
|
||||
return books
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} year YYYY
|
||||
*/
|
||||
async getStatsForYear(year) {
|
||||
const booksAdded = await this.getBooksAddedForYear(year)
|
||||
|
||||
let totalBooksAddedSize = 0
|
||||
let totalBooksAddedDuration = 0
|
||||
const booksWithCovers = []
|
||||
|
||||
for (const book of booksAdded) {
|
||||
// Grab first 25 that have a cover
|
||||
if (book.coverPath && !booksWithCovers.includes(book.libraryItem.id) && booksWithCovers.length < 25 && await fsExtra.pathExists(book.coverPath)) {
|
||||
booksWithCovers.push(book.libraryItem.id)
|
||||
}
|
||||
if (book.duration && !isNaN(book.duration)) {
|
||||
totalBooksAddedDuration += book.duration
|
||||
}
|
||||
if (book.libraryItem.size && !isNaN(book.libraryItem.size)) {
|
||||
totalBooksAddedSize += book.libraryItem.size
|
||||
}
|
||||
}
|
||||
|
||||
const numAuthorsAdded = await this.getNumAuthorsAddedForYear(year)
|
||||
|
||||
const listeningSessions = await this.getListeningSessionsForYear(year)
|
||||
let totalListeningTime = 0
|
||||
for (const listeningSession of listeningSessions) {
|
||||
totalListeningTime += (listeningSession.timeListening || 0)
|
||||
}
|
||||
|
||||
// Stats for total books, size and duration for everything added this year or earlier
|
||||
const [totalStatResultsRow] = await Database.sequelize.query(`SELECT SUM(li.size) AS totalSize, SUM(b.duration) AS totalDuration, COUNT(*) AS totalItems FROM libraryItems li, books b WHERE b.id = li.mediaId AND li.mediaType = 'book' AND li.createdAt < ":nextYear-01-01";`, {
|
||||
replacements: {
|
||||
nextYear: year + 1
|
||||
}
|
||||
})
|
||||
const totalStatResults = totalStatResultsRow[0]
|
||||
|
||||
return {
|
||||
numListeningSessions: listeningSessions.length,
|
||||
numBooksAdded: booksAdded.length,
|
||||
numAuthorsAdded,
|
||||
totalBooksAddedSize,
|
||||
totalBooksAddedDuration: Math.round(totalBooksAddedDuration),
|
||||
booksAddedWithCovers: booksWithCovers,
|
||||
totalBooksSize: totalStatResults?.totalSize || 0,
|
||||
totalBooksDuration: totalStatResults?.totalDuration || 0,
|
||||
totalListeningTime,
|
||||
numBooks: totalStatResults?.totalItems || 0
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,9 +18,6 @@ module.exports = {
|
|||
createdAt: {
|
||||
[Sequelize.Op.gte]: `${year}-01-01`,
|
||||
[Sequelize.Op.lt]: `${year + 1}-01-01`
|
||||
},
|
||||
timeListening: {
|
||||
[Sequelize.Op.gt]: 5
|
||||
}
|
||||
},
|
||||
include: {
|
||||
|
@ -66,10 +63,11 @@ module.exports = {
|
|||
},
|
||||
|
||||
/**
|
||||
* @param {string} userId
|
||||
* @param {import('../../objects/user/User')} user
|
||||
* @param {number} year YYYY
|
||||
*/
|
||||
async getStatsForYear(userId, year) {
|
||||
async getStatsForYear(user, year) {
|
||||
const userId = user.id
|
||||
const listeningSessions = await this.getUserListeningSessionsForYear(userId, year)
|
||||
|
||||
let totalBookListeningTime = 0
|
||||
|
@ -84,8 +82,8 @@ module.exports = {
|
|||
const booksWithCovers = []
|
||||
|
||||
for (const ls of listeningSessions) {
|
||||
// Grab first 16 that have a cover
|
||||
if (ls.mediaItem?.coverPath && !booksWithCovers.includes(ls.mediaItem.libraryItem.id) && booksWithCovers.length < 16 && await fsExtra.pathExists(ls.mediaItem.coverPath)) {
|
||||
// Grab first 25 that have a cover
|
||||
if (ls.mediaItem?.coverPath && !booksWithCovers.includes(ls.mediaItem.libraryItem.id) && booksWithCovers.length < 25 && await fsExtra.pathExists(ls.mediaItem.coverPath)) {
|
||||
booksWithCovers.push(ls.mediaItem.libraryItem.id)
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue