mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +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" /> | ||||
|     </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" /> | ||||
| 
 | ||||
|       <p class="font-book pt-1.5" style="font-size: 0.9rem">Search</p> | ||||
| @ -82,6 +82,9 @@ export default { | ||||
|     showExperimentalFeatures() { | ||||
|       return this.$store.state.showExperimentalFeatures | ||||
|     }, | ||||
|     userIsAdminOrUp() { | ||||
|       return this.$store.getters['user/getIsAdminOrUp'] | ||||
|     }, | ||||
|     paramId() { | ||||
|       return this.$route.params ? this.$route.params.id || '' : '' | ||||
|     }, | ||||
|  | ||||
| @ -1,11 +1,11 @@ | ||||
| <template> | ||||
|   <div class="w-full h-full overflow-y-auto overflow-x-hidden px-4 py-6"> | ||||
|     <div class="w-full mb-4"> | ||||
|       <!-- <div class="flex items-center mb-4"> | ||||
|         <p v-if="autoDownloadEpisodes">Last new episode check {{ $formatDate(lastEpisodeCheck) }}</p> | ||||
|         <div class="flex-grow" /> | ||||
|         <ui-btn :loading="checkingNewEpisodes" @click="checkForNewEpisodes">Check for new episodes</ui-btn> | ||||
|       </div> --> | ||||
|       <div v-if="userIsAdminOrUp" class="flex items-end justify-end mb-4"> | ||||
|         <!-- <p v-if="autoDownloadEpisodes">Last new episode check {{ $formatDate(lastEpisodeCheck) }}</p> --> | ||||
|         <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 & Download New Episodes</ui-btn> | ||||
|       </div> | ||||
| 
 | ||||
|       <div v-if="episodes.length" class="w-full p-4 bg-primary"> | ||||
|         <p>Podcast Episodes</p> | ||||
| @ -51,10 +51,23 @@ export default { | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       checkingNewEpisodes: false | ||||
|       checkingNewEpisodes: false, | ||||
|       lastEpisodeCheckInput: null | ||||
|     } | ||||
|   }, | ||||
|   watch: { | ||||
|     lastEpisodeCheck: { | ||||
|       handler(newVal) { | ||||
|         if (newVal) { | ||||
|           this.setLastEpisodeCheckInput() | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     userIsAdminOrUp() { | ||||
|       return this.$store.getters['user/getIsAdminOrUp'] | ||||
|     }, | ||||
|     autoDownloadEpisodes() { | ||||
|       return !!this.media.autoDownloadEpisodes | ||||
|     }, | ||||
| @ -72,8 +85,22 @@ export default { | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     checkForNewEpisodes() { | ||||
|     async checkForNewEpisodes() { | ||||
|       if (this.$refs.lastCheckInput) { | ||||
|         this.$refs.lastCheckInput.blur() | ||||
|       } | ||||
|       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 | ||||
|         .$get(`/api/podcasts/${this.libraryItemId}/checknew`) | ||||
|         .then((response) => { | ||||
| @ -91,7 +118,13 @@ export default { | ||||
|           this.$toast.error(errorMsg) | ||||
|           this.checkingNewEpisodes = false | ||||
|         }) | ||||
|     }, | ||||
|     setLastEpisodeCheckInput() { | ||||
|       this.lastEpisodeCheckInput = this.lastEpisodeCheck ? this.$formatDate(this.lastEpisodeCheck, "yyyy-MM-dd'T'HH:mm") : null | ||||
|     } | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.setLastEpisodeCheckInput() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| @ -150,7 +150,8 @@ | ||||
|               <ui-icon-btn icon="collections_bookmark" class="mx-0.5" outlined @click="collectionsClick" /> | ||||
|             </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-tooltip> | ||||
|           </div> | ||||
| @ -210,6 +211,9 @@ export default { | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     userIsAdminOrUp() { | ||||
|       return this.$store.getters['user/getIsAdminOrUp'] | ||||
|     }, | ||||
|     isFile() { | ||||
|       return this.libraryItem.isFile | ||||
|     }, | ||||
|  | ||||
| @ -16,6 +16,7 @@ export const state = () => ({ | ||||
| 
 | ||||
| export const getters = { | ||||
|   getIsRoot: (state) => state.user && state.user.type === 'root', | ||||
|   getIsAdminOrUp: (state) => state.user && (state.user.type === 'admin' || state.user.type === 'root'), | ||||
|   getToken: (state) => { | ||||
|     return state.user ? state.user.token : null | ||||
|   }, | ||||
|  | ||||
| @ -124,7 +124,7 @@ class PodcastController { | ||||
|       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({ | ||||
|       episodes: newEpisodes || [] | ||||
|     }) | ||||
|  | ||||
| @ -208,8 +208,27 @@ class PodcastManager { | ||||
|     } | ||||
|     // Filter new and not already has
 | ||||
|     var newEpisodes = feed.episodes.filter(ep => ep.publishedAt > podcastLibraryItem.media.lastEpisodeCheck && !podcastLibraryItem.media.checkHasEpisodeByFeedUrl(ep.enclosure.url)) | ||||
|     // Max new episodes for safety = 2
 | ||||
|     newEpisodes = newEpisodes.slice(0, 2) | ||||
|     // Max new episodes for safety = 3
 | ||||
|     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 | ||||
|   } | ||||
| 
 | ||||
|  | ||||
| @ -79,7 +79,7 @@ class ServerSettings { | ||||
| 
 | ||||
|     this.backupSchedule = settings.backupSchedule || false | ||||
|     this.backupsToKeep = settings.backupsToKeep || 2 | ||||
|     this.maxBackupSize  = settings.maxBackupSize || 1 | ||||
|     this.maxBackupSize = settings.maxBackupSize || 1 | ||||
|     this.backupMetadataCovers = settings.backupMetadataCovers !== false | ||||
| 
 | ||||
|     this.loggerDailyLogsToKeep = settings.loggerDailyLogsToKeep || 7 | ||||
|  | ||||
| @ -30,6 +30,9 @@ class User { | ||||
|   get isRoot() { | ||||
|     return this.type === 'root' | ||||
|   } | ||||
|   get isAdmin() { | ||||
|     return this.type === 'admin' | ||||
|   } | ||||
|   get canDelete() { | ||||
|     return !!this.permissions.delete && this.isActive | ||||
|   } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user