mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2024-12-20 19:06:06 +01:00
Add:Check for new episodes manual check and update last check time, Update:Adding new podcasts and downloading podcast episodes restricted to admin users
This commit is contained in:
parent
8abda14e0f
commit
4185807da4
@ -52,7 +52,7 @@
|
|||||||
<div v-show="isAuthorsPage" class="h-full w-0.5 bg-yellow-400 absolute top-0 left-0" />
|
<div v-show="isAuthorsPage" class="h-full w-0.5 bg-yellow-400 absolute top-0 left-0" />
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
|
|
||||||
<nuxt-link v-if="isPodcastLibrary" :to="`/library/${currentLibraryId}/podcast/search`" class="w-full h-20 flex flex-col items-center justify-center text-white text-opacity-80 border-b border-primary border-opacity-70 hover:bg-primary cursor-pointer relative" :class="isPodcastSearchPage ? 'bg-primary bg-opacity-80' : 'bg-bg bg-opacity-60'">
|
<nuxt-link v-if="isPodcastLibrary && userIsAdminOrUp" :to="`/library/${currentLibraryId}/podcast/search`" class="w-full h-20 flex flex-col items-center justify-center text-white text-opacity-80 border-b border-primary border-opacity-70 hover:bg-primary cursor-pointer relative" :class="isPodcastSearchPage ? 'bg-primary bg-opacity-80' : 'bg-bg bg-opacity-60'">
|
||||||
<icons-podcast-svg class="w-6 h-6" />
|
<icons-podcast-svg class="w-6 h-6" />
|
||||||
|
|
||||||
<p class="font-book pt-1.5" style="font-size: 0.9rem">Search</p>
|
<p class="font-book pt-1.5" style="font-size: 0.9rem">Search</p>
|
||||||
@ -82,6 +82,9 @@ export default {
|
|||||||
showExperimentalFeatures() {
|
showExperimentalFeatures() {
|
||||||
return this.$store.state.showExperimentalFeatures
|
return this.$store.state.showExperimentalFeatures
|
||||||
},
|
},
|
||||||
|
userIsAdminOrUp() {
|
||||||
|
return this.$store.getters['user/getIsAdminOrUp']
|
||||||
|
},
|
||||||
paramId() {
|
paramId() {
|
||||||
return this.$route.params ? this.$route.params.id || '' : ''
|
return this.$route.params ? this.$route.params.id || '' : ''
|
||||||
},
|
},
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="w-full h-full overflow-y-auto overflow-x-hidden px-4 py-6">
|
<div class="w-full h-full overflow-y-auto overflow-x-hidden px-4 py-6">
|
||||||
<div class="w-full mb-4">
|
<div class="w-full mb-4">
|
||||||
<!-- <div class="flex items-center mb-4">
|
<div v-if="userIsAdminOrUp" class="flex items-end justify-end mb-4">
|
||||||
<p v-if="autoDownloadEpisodes">Last new episode check {{ $formatDate(lastEpisodeCheck) }}</p>
|
<!-- <p v-if="autoDownloadEpisodes">Last new episode check {{ $formatDate(lastEpisodeCheck) }}</p> -->
|
||||||
<div class="flex-grow" />
|
<ui-text-input-with-label ref="lastCheckInput" v-model="lastEpisodeCheckInput" :disabled="checkingNewEpisodes" type="datetime-local" label="Look for new episodes after this date" class="max-w-xs mr-2" />
|
||||||
<ui-btn :loading="checkingNewEpisodes" @click="checkForNewEpisodes">Check for new episodes</ui-btn>
|
<ui-btn :loading="checkingNewEpisodes" @click="checkForNewEpisodes">Check & Download New Episodes</ui-btn>
|
||||||
</div> -->
|
</div>
|
||||||
|
|
||||||
<div v-if="episodes.length" class="w-full p-4 bg-primary">
|
<div v-if="episodes.length" class="w-full p-4 bg-primary">
|
||||||
<p>Podcast Episodes</p>
|
<p>Podcast Episodes</p>
|
||||||
@ -51,10 +51,23 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
checkingNewEpisodes: false
|
checkingNewEpisodes: false,
|
||||||
|
lastEpisodeCheckInput: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
lastEpisodeCheck: {
|
||||||
|
handler(newVal) {
|
||||||
|
if (newVal) {
|
||||||
|
this.setLastEpisodeCheckInput()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
userIsAdminOrUp() {
|
||||||
|
return this.$store.getters['user/getIsAdminOrUp']
|
||||||
|
},
|
||||||
autoDownloadEpisodes() {
|
autoDownloadEpisodes() {
|
||||||
return !!this.media.autoDownloadEpisodes
|
return !!this.media.autoDownloadEpisodes
|
||||||
},
|
},
|
||||||
@ -72,8 +85,22 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
checkForNewEpisodes() {
|
async checkForNewEpisodes() {
|
||||||
|
if (this.$refs.lastCheckInput) {
|
||||||
|
this.$refs.lastCheckInput.blur()
|
||||||
|
}
|
||||||
this.checkingNewEpisodes = true
|
this.checkingNewEpisodes = true
|
||||||
|
const lastEpisodeCheck = new Date(this.lastEpisodeCheckInput).valueOf()
|
||||||
|
|
||||||
|
// If last episode check changed then update it first
|
||||||
|
if (lastEpisodeCheck && lastEpisodeCheck !== this.lastEpisodeCheck) {
|
||||||
|
var updateResult = await this.$axios.$patch(`/api/items/${this.libraryItemId}/media`, { lastEpisodeCheck }).catch((error) => {
|
||||||
|
console.error('Failed to update', error)
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
console.log('updateResult', updateResult)
|
||||||
|
}
|
||||||
|
|
||||||
this.$axios
|
this.$axios
|
||||||
.$get(`/api/podcasts/${this.libraryItemId}/checknew`)
|
.$get(`/api/podcasts/${this.libraryItemId}/checknew`)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
@ -91,7 +118,13 @@ export default {
|
|||||||
this.$toast.error(errorMsg)
|
this.$toast.error(errorMsg)
|
||||||
this.checkingNewEpisodes = false
|
this.checkingNewEpisodes = false
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
setLastEpisodeCheckInput() {
|
||||||
|
this.lastEpisodeCheckInput = this.lastEpisodeCheck ? this.$formatDate(this.lastEpisodeCheck, "yyyy-MM-dd'T'HH:mm") : null
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.setLastEpisodeCheckInput()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
@ -150,7 +150,8 @@
|
|||||||
<ui-icon-btn icon="collections_bookmark" class="mx-0.5" outlined @click="collectionsClick" />
|
<ui-icon-btn icon="collections_bookmark" class="mx-0.5" outlined @click="collectionsClick" />
|
||||||
</ui-tooltip>
|
</ui-tooltip>
|
||||||
|
|
||||||
<ui-tooltip v-if="isPodcast" text="Find Episodes" direction="top">
|
<!-- Only admin or root user can download new episodes -->
|
||||||
|
<ui-tooltip v-if="isPodcast && userIsAdminOrUp" text="Find Episodes" direction="top">
|
||||||
<ui-icon-btn icon="search" class="mx-0.5" :loading="fetchingRSSFeed" outlined @click="findEpisodesClick" />
|
<ui-icon-btn icon="search" class="mx-0.5" :loading="fetchingRSSFeed" outlined @click="findEpisodesClick" />
|
||||||
</ui-tooltip>
|
</ui-tooltip>
|
||||||
</div>
|
</div>
|
||||||
@ -210,6 +211,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
userIsAdminOrUp() {
|
||||||
|
return this.$store.getters['user/getIsAdminOrUp']
|
||||||
|
},
|
||||||
isFile() {
|
isFile() {
|
||||||
return this.libraryItem.isFile
|
return this.libraryItem.isFile
|
||||||
},
|
},
|
||||||
|
@ -16,6 +16,7 @@ export const state = () => ({
|
|||||||
|
|
||||||
export const getters = {
|
export const getters = {
|
||||||
getIsRoot: (state) => state.user && state.user.type === 'root',
|
getIsRoot: (state) => state.user && state.user.type === 'root',
|
||||||
|
getIsAdminOrUp: (state) => state.user && (state.user.type === 'admin' || state.user.type === 'root'),
|
||||||
getToken: (state) => {
|
getToken: (state) => {
|
||||||
return state.user ? state.user.token : null
|
return state.user ? state.user.token : null
|
||||||
},
|
},
|
||||||
|
@ -124,7 +124,7 @@ class PodcastController {
|
|||||||
return res.status(500).send('Podcast has no rss feed url')
|
return res.status(500).send('Podcast has no rss feed url')
|
||||||
}
|
}
|
||||||
|
|
||||||
var newEpisodes = await this.podcastManager.checkPodcastForNewEpisodes(libraryItem)
|
var newEpisodes = await this.podcastManager.checkAndDownloadNewEpisodes(libraryItem)
|
||||||
res.json({
|
res.json({
|
||||||
episodes: newEpisodes || []
|
episodes: newEpisodes || []
|
||||||
})
|
})
|
||||||
|
@ -208,8 +208,27 @@ class PodcastManager {
|
|||||||
}
|
}
|
||||||
// Filter new and not already has
|
// Filter new and not already has
|
||||||
var newEpisodes = feed.episodes.filter(ep => ep.publishedAt > podcastLibraryItem.media.lastEpisodeCheck && !podcastLibraryItem.media.checkHasEpisodeByFeedUrl(ep.enclosure.url))
|
var newEpisodes = feed.episodes.filter(ep => ep.publishedAt > podcastLibraryItem.media.lastEpisodeCheck && !podcastLibraryItem.media.checkHasEpisodeByFeedUrl(ep.enclosure.url))
|
||||||
// Max new episodes for safety = 2
|
// Max new episodes for safety = 3
|
||||||
newEpisodes = newEpisodes.slice(0, 2)
|
newEpisodes = newEpisodes.slice(0, 3)
|
||||||
|
return newEpisodes
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkAndDownloadNewEpisodes(libraryItem) {
|
||||||
|
const lastEpisodeCheckDate = new Date(libraryItem.media.lastEpisodeCheck || 0)
|
||||||
|
Logger.info(`[PodcastManager] checkAndDownloadNewEpisodes for "${libraryItem.media.metadata.title}" - Last episode check: ${lastEpisodeCheckDate}`)
|
||||||
|
var newEpisodes = await this.checkPodcastForNewEpisodes(libraryItem)
|
||||||
|
if (newEpisodes.length) {
|
||||||
|
Logger.info(`[PodcastManager] Found ${newEpisodes.length} new episodes for podcast "${libraryItem.media.metadata.title}" - starting download`)
|
||||||
|
this.downloadPodcastEpisodes(libraryItem, newEpisodes)
|
||||||
|
} else {
|
||||||
|
Logger.info(`[PodcastManager] No new episodes found for podcast "${libraryItem.media.metadata.title}"`)
|
||||||
|
}
|
||||||
|
|
||||||
|
libraryItem.media.lastEpisodeCheck = Date.now()
|
||||||
|
libraryItem.updatedAt = Date.now()
|
||||||
|
await this.db.updateLibraryItem(libraryItem)
|
||||||
|
this.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||||
|
|
||||||
return newEpisodes
|
return newEpisodes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ class ServerSettings {
|
|||||||
|
|
||||||
this.backupSchedule = settings.backupSchedule || false
|
this.backupSchedule = settings.backupSchedule || false
|
||||||
this.backupsToKeep = settings.backupsToKeep || 2
|
this.backupsToKeep = settings.backupsToKeep || 2
|
||||||
this.maxBackupSize = settings.maxBackupSize || 1
|
this.maxBackupSize = settings.maxBackupSize || 1
|
||||||
this.backupMetadataCovers = settings.backupMetadataCovers !== false
|
this.backupMetadataCovers = settings.backupMetadataCovers !== false
|
||||||
|
|
||||||
this.loggerDailyLogsToKeep = settings.loggerDailyLogsToKeep || 7
|
this.loggerDailyLogsToKeep = settings.loggerDailyLogsToKeep || 7
|
||||||
|
@ -30,6 +30,9 @@ class User {
|
|||||||
get isRoot() {
|
get isRoot() {
|
||||||
return this.type === 'root'
|
return this.type === 'root'
|
||||||
}
|
}
|
||||||
|
get isAdmin() {
|
||||||
|
return this.type === 'admin'
|
||||||
|
}
|
||||||
get canDelete() {
|
get canDelete() {
|
||||||
return !!this.permissions.delete && this.isActive
|
return !!this.permissions.delete && this.isActive
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user