audiobookshelf/server/objects/UserAudiobookData.js
2021-12-01 19:07:03 -06:00

136 lines
3.5 KiB
JavaScript

const Logger = require('../Logger')
const AudioBookmark = require('./AudioBookmark')
class UserAudiobookData {
constructor(progress) {
this.audiobookId = null
this.totalDuration = null // seconds
this.progress = null // 0 to 1
this.currentTime = null // seconds
this.isRead = false
this.lastUpdate = null
this.startedAt = null
this.finishedAt = null
this.bookmarks = []
if (progress) {
this.construct(progress)
}
}
bookmarksToJSON() {
if (!this.bookmarks) return []
return this.bookmarks.filter((b) => {
if (!b.toJSON) {
Logger.error(`[UserAudiobookData] Invalid bookmark ${JSON.stringify(b)}`)
return false
}
return true
}).map(b => b.toJSON())
}
toJSON() {
return {
audiobookId: this.audiobookId,
totalDuration: this.totalDuration,
progress: this.progress,
currentTime: this.currentTime,
isRead: this.isRead,
lastUpdate: this.lastUpdate,
startedAt: this.startedAt,
finishedAt: this.finishedAt,
bookmarks: this.bookmarksToJSON()
}
}
construct(progress) {
this.audiobookId = progress.audiobookId
this.totalDuration = progress.totalDuration
this.progress = progress.progress
this.currentTime = progress.currentTime
this.isRead = !!progress.isRead
this.lastUpdate = progress.lastUpdate
this.startedAt = progress.startedAt
this.finishedAt = progress.finishedAt || null
if (progress.bookmarks) {
this.bookmarks = progress.bookmarks.map(b => new AudioBookmark(b))
} else {
this.bookmarks = []
}
}
updateProgressFromStream(stream) {
this.audiobookId = stream.audiobookId
this.totalDuration = stream.totalDuration
this.progress = stream.clientProgress
this.currentTime = stream.clientCurrentTime
this.lastUpdate = Date.now()
if (!this.startedAt) {
this.startedAt = Date.now()
}
// If has < 10 seconds remaining mark as read
var timeRemaining = this.totalDuration - this.currentTime
if (timeRemaining < 10) {
this.isRead = true
this.progress = 1
this.finishedAt = Date.now()
} else {
this.isRead = false
this.finishedAt = null
}
}
update(payload) {
var hasUpdates = false
for (const key in payload) {
if (payload[key] !== this[key]) {
if (key === 'isRead') {
if (!payload[key]) { // Updating to Not Read - Reset progress and current time
this.finishedAt = null
this.progress = 0
this.currentTime = 0
} else { // Updating to Read
if (!this.finishedAt) this.finishedAt = Date.now()
this.progress = 1
}
}
this[key] = payload[key]
hasUpdates = true
}
}
if (!this.startedAt) {
this.startedAt = Date.now()
}
if (hasUpdates) {
this.lastUpdate = Date.now()
}
return hasUpdates
}
checkBookmarkExists(time) {
return this.bookmarks.find(bm => bm.time === time)
}
createBookmark(time, title) {
var newBookmark = new AudioBookmark()
newBookmark.setData(time, title)
this.bookmarks.push(newBookmark)
return newBookmark
}
updateBookmark(time, title) {
var bookmark = this.bookmarks.find(bm => bm.time === time)
if (!bookmark) return false
bookmark.title = title
return bookmark
}
deleteBookmark(time) {
this.bookmarks = this.bookmarks.filter(bm => bm.time !== time)
}
}
module.exports = UserAudiobookData