2022-07-07 02:18:27 +02:00
|
|
|
const date = require('../libs/dateAndTime')
|
2023-07-05 01:14:44 +02:00
|
|
|
const uuidv4 = require("uuid").v4
|
|
|
|
const serverVersion = require('../../package.json').version
|
2022-03-16 01:28:54 +01:00
|
|
|
const BookMetadata = require('./metadata/BookMetadata')
|
|
|
|
const PodcastMetadata = require('./metadata/PodcastMetadata')
|
2022-05-27 02:09:46 +02:00
|
|
|
const DeviceInfo = require('./DeviceInfo')
|
2022-05-31 02:26:53 +02:00
|
|
|
const VideoMetadata = require('./metadata/VideoMetadata')
|
2021-11-06 02:24:02 +01:00
|
|
|
|
2022-03-16 00:57:15 +01:00
|
|
|
class PlaybackSession {
|
2021-11-06 02:24:02 +01:00
|
|
|
constructor(session) {
|
2021-11-13 02:43:16 +01:00
|
|
|
this.id = null
|
2021-11-06 02:24:02 +01:00
|
|
|
this.userId = null
|
2022-05-28 00:39:24 +02:00
|
|
|
this.libraryId = null
|
2022-03-16 00:57:15 +01:00
|
|
|
this.libraryItemId = null
|
2023-07-05 01:14:44 +02:00
|
|
|
this.bookId = null
|
2022-03-26 23:41:26 +01:00
|
|
|
this.episodeId = null
|
2022-03-18 01:10:47 +01:00
|
|
|
|
2022-03-16 00:57:15 +01:00
|
|
|
this.mediaType = null
|
|
|
|
this.mediaMetadata = null
|
2022-04-02 18:41:17 +02:00
|
|
|
this.chapters = null
|
2022-04-02 17:26:42 +02:00
|
|
|
this.displayTitle = null
|
|
|
|
this.displayAuthor = null
|
2022-03-26 17:59:34 +01:00
|
|
|
this.coverPath = null
|
2022-03-18 01:10:47 +01:00
|
|
|
this.duration = null
|
2022-03-16 00:57:15 +01:00
|
|
|
|
|
|
|
this.playMethod = null
|
2022-04-02 18:19:57 +02:00
|
|
|
this.mediaPlayer = null
|
2022-05-27 02:09:46 +02:00
|
|
|
this.deviceInfo = null
|
2023-07-05 01:14:44 +02:00
|
|
|
this.serverVersion = null
|
2021-11-13 02:43:16 +01:00
|
|
|
|
|
|
|
this.date = null
|
|
|
|
this.dayOfWeek = null
|
2021-11-06 02:24:02 +01:00
|
|
|
|
|
|
|
this.timeListening = null
|
2022-05-27 02:09:46 +02:00
|
|
|
this.startTime = null // media current time at start of playback
|
|
|
|
this.currentTime = 0 // Last current time set
|
|
|
|
|
2021-11-06 02:24:02 +01:00
|
|
|
this.startedAt = null
|
2022-03-16 00:57:15 +01:00
|
|
|
this.updatedAt = null
|
2021-11-06 02:24:02 +01:00
|
|
|
|
2022-03-18 01:10:47 +01:00
|
|
|
// Not saved in DB
|
|
|
|
this.lastSave = 0
|
|
|
|
this.audioTracks = []
|
2022-05-31 02:26:53 +02:00
|
|
|
this.videoTrack = null
|
2022-03-18 01:10:47 +01:00
|
|
|
this.stream = null
|
|
|
|
|
2021-11-06 02:24:02 +01:00
|
|
|
if (session) {
|
|
|
|
this.construct(session)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
toJSON() {
|
|
|
|
return {
|
2021-11-13 02:43:16 +01:00
|
|
|
id: this.id,
|
2021-11-06 02:24:02 +01:00
|
|
|
userId: this.userId,
|
2022-05-28 00:39:24 +02:00
|
|
|
libraryId: this.libraryId,
|
2022-03-16 00:57:15 +01:00
|
|
|
libraryItemId: this.libraryItemId,
|
2023-07-05 01:14:44 +02:00
|
|
|
bookId: this.bookId,
|
2022-03-26 23:41:26 +01:00
|
|
|
episodeId: this.episodeId,
|
2022-03-16 00:57:15 +01:00
|
|
|
mediaType: this.mediaType,
|
2023-04-09 01:01:24 +02:00
|
|
|
mediaMetadata: this.mediaMetadata?.toJSON() || null,
|
2022-04-02 18:41:17 +02:00
|
|
|
chapters: (this.chapters || []).map(c => ({ ...c })),
|
2022-04-02 17:26:42 +02:00
|
|
|
displayTitle: this.displayTitle,
|
|
|
|
displayAuthor: this.displayAuthor,
|
2022-03-26 17:59:34 +01:00
|
|
|
coverPath: this.coverPath,
|
2022-03-18 01:10:47 +01:00
|
|
|
duration: this.duration,
|
2022-03-16 00:57:15 +01:00
|
|
|
playMethod: this.playMethod,
|
2022-04-02 18:19:57 +02:00
|
|
|
mediaPlayer: this.mediaPlayer,
|
2023-04-09 01:01:24 +02:00
|
|
|
deviceInfo: this.deviceInfo?.toJSON() || null,
|
2023-07-05 01:14:44 +02:00
|
|
|
serverVersion: this.serverVersion,
|
2021-11-13 02:43:16 +01:00
|
|
|
date: this.date,
|
|
|
|
dayOfWeek: this.dayOfWeek,
|
2021-11-06 02:24:02 +01:00
|
|
|
timeListening: this.timeListening,
|
2022-05-27 02:09:46 +02:00
|
|
|
startTime: this.startTime,
|
|
|
|
currentTime: this.currentTime,
|
|
|
|
startedAt: this.startedAt,
|
2022-03-16 00:57:15 +01:00
|
|
|
updatedAt: this.updatedAt
|
2021-11-06 02:24:02 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-12 23:11:58 +02:00
|
|
|
/**
|
|
|
|
* Session data to send to clients
|
|
|
|
* @param {[oldLibraryItem]} libraryItem optional
|
|
|
|
* @returns {object}
|
|
|
|
*/
|
2022-03-26 17:59:34 +01:00
|
|
|
toJSONForClient(libraryItem) {
|
2022-03-18 01:10:47 +01:00
|
|
|
return {
|
|
|
|
id: this.id,
|
|
|
|
userId: this.userId,
|
2022-05-28 00:39:24 +02:00
|
|
|
libraryId: this.libraryId,
|
2022-03-18 01:10:47 +01:00
|
|
|
libraryItemId: this.libraryItemId,
|
2023-07-05 01:14:44 +02:00
|
|
|
bookId: this.bookId,
|
2022-03-26 23:41:26 +01:00
|
|
|
episodeId: this.episodeId,
|
2022-03-18 01:10:47 +01:00
|
|
|
mediaType: this.mediaType,
|
2023-04-09 01:01:24 +02:00
|
|
|
mediaMetadata: this.mediaMetadata?.toJSON() || null,
|
2022-04-02 18:41:17 +02:00
|
|
|
chapters: (this.chapters || []).map(c => ({ ...c })),
|
2022-04-02 17:26:42 +02:00
|
|
|
displayTitle: this.displayTitle,
|
|
|
|
displayAuthor: this.displayAuthor,
|
2022-03-26 17:59:34 +01:00
|
|
|
coverPath: this.coverPath,
|
2022-03-18 01:10:47 +01:00
|
|
|
duration: this.duration,
|
|
|
|
playMethod: this.playMethod,
|
2022-04-02 18:19:57 +02:00
|
|
|
mediaPlayer: this.mediaPlayer,
|
2023-04-09 01:01:24 +02:00
|
|
|
deviceInfo: this.deviceInfo?.toJSON() || null,
|
2023-07-05 01:14:44 +02:00
|
|
|
serverVersion: this.serverVersion,
|
2022-03-18 01:10:47 +01:00
|
|
|
date: this.date,
|
|
|
|
dayOfWeek: this.dayOfWeek,
|
|
|
|
timeListening: this.timeListening,
|
2022-05-27 02:09:46 +02:00
|
|
|
startTime: this.startTime,
|
|
|
|
currentTime: this.currentTime,
|
|
|
|
startedAt: this.startedAt,
|
2022-03-18 01:10:47 +01:00
|
|
|
updatedAt: this.updatedAt,
|
|
|
|
audioTracks: this.audioTracks.map(at => at.toJSON()),
|
2023-08-12 23:11:58 +02:00
|
|
|
videoTrack: this.videoTrack?.toJSON() || null,
|
|
|
|
libraryItem: libraryItem?.toJSONExpanded() || null
|
2022-03-18 01:10:47 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-06 02:24:02 +01:00
|
|
|
construct(session) {
|
2021-11-13 02:43:16 +01:00
|
|
|
this.id = session.id
|
2021-11-06 02:24:02 +01:00
|
|
|
this.userId = session.userId
|
2022-05-28 00:39:24 +02:00
|
|
|
this.libraryId = session.libraryId || null
|
2022-03-16 00:57:15 +01:00
|
|
|
this.libraryItemId = session.libraryItemId
|
2023-07-16 22:05:51 +02:00
|
|
|
this.bookId = session.bookId || null
|
2022-04-02 17:26:42 +02:00
|
|
|
this.episodeId = session.episodeId
|
|
|
|
this.mediaType = session.mediaType
|
2022-03-18 01:10:47 +01:00
|
|
|
this.duration = session.duration
|
2022-03-16 00:57:15 +01:00
|
|
|
this.playMethod = session.playMethod
|
2022-04-02 18:19:57 +02:00
|
|
|
this.mediaPlayer = session.mediaPlayer || null
|
2023-07-05 01:14:44 +02:00
|
|
|
|
2023-07-16 22:05:51 +02:00
|
|
|
// Temp do not store old IDs
|
|
|
|
if (this.libraryId?.startsWith('lib_')) {
|
|
|
|
this.libraryId = null
|
|
|
|
}
|
|
|
|
if (this.libraryItemId?.startsWith('li_') || this.libraryItemId?.startsWith('local_')) {
|
|
|
|
this.libraryItemId = null
|
|
|
|
}
|
|
|
|
if (this.episodeId?.startsWith('ep_') || this.episodeId?.startsWith('local_')) {
|
|
|
|
this.episodeId = null
|
|
|
|
}
|
|
|
|
|
2023-07-05 01:14:44 +02:00
|
|
|
if (session.deviceInfo instanceof DeviceInfo) {
|
|
|
|
this.deviceInfo = new DeviceInfo(session.deviceInfo.toJSON())
|
|
|
|
} else {
|
|
|
|
this.deviceInfo = new DeviceInfo(session.deviceInfo)
|
|
|
|
}
|
|
|
|
|
|
|
|
this.serverVersion = session.serverVersion
|
2022-04-02 18:41:17 +02:00
|
|
|
this.chapters = session.chapters || []
|
2022-03-16 00:57:15 +01:00
|
|
|
|
|
|
|
this.mediaMetadata = null
|
|
|
|
if (session.mediaMetadata) {
|
|
|
|
if (this.mediaType === 'book') {
|
|
|
|
this.mediaMetadata = new BookMetadata(session.mediaMetadata)
|
|
|
|
} else if (this.mediaType === 'podcast') {
|
|
|
|
this.mediaMetadata = new PodcastMetadata(session.mediaMetadata)
|
2022-05-31 02:26:53 +02:00
|
|
|
} else if (this.mediaType === 'video') {
|
|
|
|
this.mediaMetadata = new VideoMetadata(session.mediaMetadata)
|
2022-03-16 00:57:15 +01:00
|
|
|
}
|
|
|
|
}
|
2022-04-02 17:26:42 +02:00
|
|
|
this.displayTitle = session.displayTitle || ''
|
|
|
|
this.displayAuthor = session.displayAuthor || ''
|
2022-03-26 17:59:34 +01:00
|
|
|
this.coverPath = session.coverPath
|
2021-11-13 02:43:16 +01:00
|
|
|
this.date = session.date
|
|
|
|
this.dayOfWeek = session.dayOfWeek
|
2021-11-06 02:24:02 +01:00
|
|
|
|
|
|
|
this.timeListening = session.timeListening || null
|
2022-05-27 02:09:46 +02:00
|
|
|
this.startTime = session.startTime || 0
|
|
|
|
this.currentTime = session.currentTime || 0
|
|
|
|
|
2021-11-06 02:24:02 +01:00
|
|
|
this.startedAt = session.startedAt
|
2023-10-01 19:44:52 +02:00
|
|
|
this.updatedAt = session.updatedAt || session.startedAt
|
|
|
|
|
|
|
|
// Local playback sessions dont set this date field so set using updatedAt
|
|
|
|
if (!this.date && session.updatedAt) {
|
|
|
|
this.date = date.format(new Date(session.updatedAt), 'YYYY-MM-DD')
|
|
|
|
this.dayOfWeek = date.format(new Date(session.updatedAt), 'dddd')
|
|
|
|
}
|
2021-11-06 02:24:02 +01:00
|
|
|
}
|
|
|
|
|
2023-02-05 23:52:17 +01:00
|
|
|
get mediaItemId() {
|
|
|
|
if (this.episodeId) return `${this.libraryItemId}-${this.episodeId}`
|
|
|
|
return this.libraryItemId
|
|
|
|
}
|
|
|
|
|
2022-03-18 01:10:47 +01:00
|
|
|
get progress() { // Value between 0 and 1
|
|
|
|
if (!this.duration) return 0
|
|
|
|
return Math.max(0, Math.min(this.currentTime / this.duration, 1))
|
|
|
|
}
|
|
|
|
|
2023-04-09 01:01:24 +02:00
|
|
|
get deviceId() {
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.deviceInfo?.id
|
2023-04-09 01:01:24 +02:00
|
|
|
}
|
|
|
|
|
2023-02-04 20:23:13 +01:00
|
|
|
get deviceDescription() {
|
|
|
|
if (!this.deviceInfo) return 'No Device Info'
|
|
|
|
return this.deviceInfo.deviceDescription
|
|
|
|
}
|
|
|
|
|
2023-02-05 23:52:17 +01:00
|
|
|
get mediaProgressObject() {
|
|
|
|
return {
|
|
|
|
duration: this.duration,
|
|
|
|
currentTime: this.currentTime,
|
|
|
|
progress: this.progress,
|
|
|
|
lastUpdate: this.updatedAt
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-27 02:09:46 +02:00
|
|
|
setData(libraryItem, user, mediaPlayer, deviceInfo, startTime, episodeId = null) {
|
2023-07-05 01:14:44 +02:00
|
|
|
this.id = uuidv4()
|
2021-11-06 02:24:02 +01:00
|
|
|
this.userId = user.id
|
2022-05-28 00:39:24 +02:00
|
|
|
this.libraryId = libraryItem.libraryId
|
2022-03-16 00:57:15 +01:00
|
|
|
this.libraryItemId = libraryItem.id
|
2023-07-05 01:14:44 +02:00
|
|
|
this.bookId = episodeId ? null : libraryItem.media.id
|
2022-03-26 23:41:26 +01:00
|
|
|
this.episodeId = episodeId
|
2022-03-16 00:57:15 +01:00
|
|
|
this.mediaType = libraryItem.mediaType
|
|
|
|
this.mediaMetadata = libraryItem.media.metadata.clone()
|
2023-05-20 20:30:07 +02:00
|
|
|
this.chapters = libraryItem.media.getChapters(episodeId)
|
2022-04-02 17:26:42 +02:00
|
|
|
this.displayTitle = libraryItem.media.getPlaybackTitle(episodeId)
|
2022-04-18 00:52:06 +02:00
|
|
|
this.displayAuthor = libraryItem.media.getPlaybackAuthor()
|
2022-03-26 17:59:34 +01:00
|
|
|
this.coverPath = libraryItem.media.coverPath
|
2022-04-18 00:52:06 +02:00
|
|
|
|
|
|
|
if (episodeId) {
|
|
|
|
this.duration = libraryItem.media.getEpisodeDuration(episodeId)
|
|
|
|
} else {
|
|
|
|
this.duration = libraryItem.media.duration
|
|
|
|
}
|
2021-11-06 02:24:02 +01:00
|
|
|
|
2022-04-02 18:19:57 +02:00
|
|
|
this.mediaPlayer = mediaPlayer
|
2022-05-27 02:09:46 +02:00
|
|
|
this.deviceInfo = deviceInfo || new DeviceInfo()
|
2023-07-05 01:14:44 +02:00
|
|
|
this.serverVersion = serverVersion
|
2022-05-27 02:09:46 +02:00
|
|
|
|
2021-11-06 02:24:02 +01:00
|
|
|
this.timeListening = 0
|
2022-05-27 02:09:46 +02:00
|
|
|
this.startTime = startTime
|
|
|
|
this.currentTime = startTime
|
|
|
|
|
2022-03-18 01:10:47 +01:00
|
|
|
this.date = date.format(new Date(), 'YYYY-MM-DD')
|
|
|
|
this.dayOfWeek = date.format(new Date(), 'dddd')
|
2021-11-06 02:24:02 +01:00
|
|
|
this.startedAt = Date.now()
|
2022-03-16 00:57:15 +01:00
|
|
|
this.updatedAt = Date.now()
|
2021-11-13 02:43:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
addListeningTime(timeListened) {
|
2022-03-18 01:10:47 +01:00
|
|
|
if (!timeListened || isNaN(timeListened)) return
|
2021-11-13 02:43:16 +01:00
|
|
|
|
2022-03-18 01:10:47 +01:00
|
|
|
if (!this.date) {
|
|
|
|
// Set date info on first listening update
|
|
|
|
this.date = date.format(new Date(), 'YYYY-MM-DD')
|
|
|
|
this.dayOfWeek = date.format(new Date(), 'dddd')
|
2021-11-13 02:43:16 +01:00
|
|
|
}
|
2022-03-18 01:10:47 +01:00
|
|
|
|
2022-04-15 12:59:42 +02:00
|
|
|
this.timeListening += Number.parseFloat(timeListened)
|
2022-03-18 01:10:47 +01:00
|
|
|
this.updatedAt = Date.now()
|
2021-11-13 02:43:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// New date since start of listening session
|
|
|
|
checkDateRollover() {
|
|
|
|
if (!this.date) return false
|
|
|
|
return date.format(new Date(), 'YYYY-MM-DD') !== this.date
|
2021-11-06 02:24:02 +01:00
|
|
|
}
|
|
|
|
}
|
2022-03-16 00:57:15 +01:00
|
|
|
module.exports = PlaybackSession
|