mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2024-12-20 19:06:06 +01:00
Merge pull request #1536 from mfcar/addSeasonInfo
Adding podcast type, season and episode info to the feed
This commit is contained in:
commit
859a53e79a
@ -29,10 +29,13 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-wrap">
|
||||
<div class="w-full md:w-1/2 p-2">
|
||||
<div class="md:w-1/4 p-2">
|
||||
<ui-dropdown :label="$strings.LabelPodcastType" v-model="podcast.type" :items="podcastTypes" small />
|
||||
</div>
|
||||
<div class="md:w-1/4 p-2">
|
||||
<ui-text-input-with-label v-model="podcast.language" :label="$strings.LabelLanguage" />
|
||||
</div>
|
||||
<div class="flex-grow px-1 pt-6">
|
||||
<div class="md:w-1/4 px-2 pt-7">
|
||||
<ui-checkbox v-model="podcast.explicit" :label="$strings.LabelExplicit" checkbox-bg="primary" border-color="gray-600" label-class="pl-2 text-base font-semibold" />
|
||||
</div>
|
||||
</div>
|
||||
@ -92,7 +95,8 @@ export default {
|
||||
itunesArtistId: '',
|
||||
autoDownloadEpisodes: false,
|
||||
language: '',
|
||||
explicit: false
|
||||
explicit: false,
|
||||
type: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -150,6 +154,9 @@ export default {
|
||||
selectedFolderPath() {
|
||||
if (!this.selectedFolder) return ''
|
||||
return this.selectedFolder.fullPath
|
||||
},
|
||||
podcastTypes() {
|
||||
return this.$store.state.globals.podcastTypes || []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@ -181,7 +188,8 @@ export default {
|
||||
itunesId: this.podcast.itunesId,
|
||||
itunesArtistId: this.podcast.itunesArtistId,
|
||||
language: this.podcast.language,
|
||||
explicit: this.podcast.explicit
|
||||
explicit: this.podcast.explicit,
|
||||
type: this.podcast.type
|
||||
},
|
||||
autoDownloadEpisodes: this.podcast.autoDownloadEpisodes
|
||||
}
|
||||
@ -218,6 +226,7 @@ export default {
|
||||
this.podcast.itunesArtistId = this._podcastData.artistId || ''
|
||||
this.podcast.language = this._podcastData.language || this.feedMetadata.language || ''
|
||||
this.podcast.autoDownloadEpisodes = false
|
||||
this.podcast.type = this._podcastData.type || this.feedMetadata.type || 'episodic'
|
||||
|
||||
this.podcast.explicit = this._podcastData.explicit || this.feedMetadata.explicit === 'yes' || this.feedMetadata.explicit == 'true'
|
||||
if (this.folderItems[0]) {
|
||||
|
@ -8,7 +8,7 @@
|
||||
<ui-text-input-with-label v-model="newEpisode.episode" :label="$strings.LabelEpisode" />
|
||||
</div>
|
||||
<div class="w-1/5 p-1">
|
||||
<ui-text-input-with-label v-model="newEpisode.episodeType" :label="$strings.LabelEpisodeType" />
|
||||
<ui-dropdown v-model="newEpisode.episodeType" :label="$strings.LabelEpisodeType" :items="episodeTypes" small />
|
||||
</div>
|
||||
<div class="w-2/5 p-1">
|
||||
<ui-text-input-with-label v-model="pubDateInput" @input="updatePubDate" type="datetime-local" :label="$strings.LabelPubDate" />
|
||||
@ -89,6 +89,9 @@ export default {
|
||||
},
|
||||
enclosureUrl() {
|
||||
return this.enclosure.url
|
||||
},
|
||||
episodeTypes() {
|
||||
return this.$store.state.globals.episodeTypes || []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@ -146,4 +149,4 @@ export default {
|
||||
},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
@ -39,6 +39,11 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex mt-2 -mx-1">
|
||||
<div class="w-1/4 px-1">
|
||||
<ui-dropdown :label="$strings.LabelPodcastType" v-model="details.type" :items="podcastTypes" small class="max-w-52" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
@ -65,7 +70,8 @@ export default {
|
||||
itunesId: null,
|
||||
itunesArtistId: null,
|
||||
explicit: false,
|
||||
language: null
|
||||
language: null,
|
||||
type: null
|
||||
},
|
||||
newTags: []
|
||||
}
|
||||
@ -93,6 +99,9 @@ export default {
|
||||
},
|
||||
filterData() {
|
||||
return this.$store.state.libraries.filterData || {}
|
||||
},
|
||||
podcastTypes() {
|
||||
return this.$store.state.globals.podcastTypes || []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@ -219,6 +228,7 @@ export default {
|
||||
this.details.itunesArtistId = this.mediaMetadata.itunesArtistId || ''
|
||||
this.details.language = this.mediaMetadata.language || ''
|
||||
this.details.explicit = !!this.mediaMetadata.explicit
|
||||
this.details.type = this.mediaMetadata.type || 'episodic'
|
||||
|
||||
this.newTags = [...(this.media.tags || [])]
|
||||
},
|
||||
@ -228,4 +238,4 @@ export default {
|
||||
},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
@ -37,6 +37,15 @@ export const state = () => ({
|
||||
value: 'yyyy-MM-dd'
|
||||
}
|
||||
],
|
||||
podcastTypes: [
|
||||
{ text: 'Episodic', value: 'episodic' },
|
||||
{ text: 'Serial', value: 'serial' }
|
||||
],
|
||||
episodeTypes: [
|
||||
{ text: 'Full', value: 'full' },
|
||||
{ text: 'Trailer', value: 'trailer' },
|
||||
{ text: 'Bonus', value: 'bonus' }
|
||||
],
|
||||
libraryIcons: ['database', 'audiobookshelf', 'books-1', 'books-2', 'book-1', 'microphone-1', 'microphone-3', 'radio', 'podcast', 'rss', 'headphones', 'music', 'file-picture', 'rocket', 'power', 'star', 'heart']
|
||||
})
|
||||
|
||||
@ -169,4 +178,4 @@ export const mutations = {
|
||||
state.selectedMediaItems.push(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -301,6 +301,7 @@
|
||||
"LabelPlayMethod": "Abspielmethode",
|
||||
"LabelPodcast": "Podcast",
|
||||
"LabelPodcasts": "Podcasts",
|
||||
"LabelPodcastType": "Podcast Type",
|
||||
"LabelPrefixesToIgnore": "Zu ignorierende(s) Vorwort(e) (Groß- und Kleinschreibung wird nicht berücksichtigt)",
|
||||
"LabelProgress": "Fortschritt",
|
||||
"LabelProvider": "Anbieter",
|
||||
|
@ -301,6 +301,7 @@
|
||||
"LabelPlayMethod": "Play Method",
|
||||
"LabelPodcast": "Podcast",
|
||||
"LabelPodcasts": "Podcasts",
|
||||
"LabelPodcastType": "Podcast Type",
|
||||
"LabelPrefixesToIgnore": "Prefixes to Ignore (case insensitive)",
|
||||
"LabelProgress": "Progress",
|
||||
"LabelProvider": "Provider",
|
||||
|
@ -301,6 +301,7 @@
|
||||
"LabelPlayMethod": "Play Method",
|
||||
"LabelPodcast": "Podcast",
|
||||
"LabelPodcasts": "Podcasts",
|
||||
"LabelPodcastType": "Podcast Type",
|
||||
"LabelPrefixesToIgnore": "Prefixes to Ignore (case insensitive)",
|
||||
"LabelProgress": "Progress",
|
||||
"LabelProvider": "Provider",
|
||||
@ -616,4 +617,4 @@
|
||||
"ToastSocketFailedToConnect": "Socket failed to connect",
|
||||
"ToastUserDeleteFailed": "Failed to delete user",
|
||||
"ToastUserDeleteSuccess": "User deleted"
|
||||
}
|
||||
}
|
||||
|
@ -301,6 +301,7 @@
|
||||
"LabelPlayMethod": "Méthode d'écoute",
|
||||
"LabelPodcast": "Podcast",
|
||||
"LabelPodcasts": "Podcasts",
|
||||
"LabelPodcastType": "Podcast Type",
|
||||
"LabelPrefixesToIgnore": "Préfixes à Ignorer (Insensible à la Casse)",
|
||||
"LabelProgress": "Progression",
|
||||
"LabelProvider": "Fournisseur",
|
||||
@ -616,4 +617,4 @@
|
||||
"ToastSocketFailedToConnect": "Échec de la connexion WebSocket",
|
||||
"ToastUserDeleteFailed": "Échec de la suppression de l'utilisateur",
|
||||
"ToastUserDeleteSuccess": "Utilisateur supprimé"
|
||||
}
|
||||
}
|
||||
|
@ -301,6 +301,7 @@
|
||||
"LabelPlayMethod": "Vrsta reprodukcije",
|
||||
"LabelPodcast": "Podcast",
|
||||
"LabelPodcasts": "Podcasts",
|
||||
"LabelPodcastType": "Podcast Type",
|
||||
"LabelPrefixesToIgnore": "Prefiksi za ignorirati (mala i velika slova nisu bitna)",
|
||||
"LabelProgress": "Napredak",
|
||||
"LabelProvider": "Dobavljač",
|
||||
@ -616,4 +617,4 @@
|
||||
"ToastSocketFailedToConnect": "Socket failed to connect",
|
||||
"ToastUserDeleteFailed": "Neuspješno brisanje korisnika",
|
||||
"ToastUserDeleteSuccess": "Korisnik obrisan"
|
||||
}
|
||||
}
|
||||
|
@ -301,6 +301,7 @@
|
||||
"LabelPlayMethod": "Metodo di riproduzione",
|
||||
"LabelPodcast": "Podcast",
|
||||
"LabelPodcasts": "Podcasts",
|
||||
"LabelPodcastType": "Podcast Type",
|
||||
"LabelPrefixesToIgnore": "Suffissi da ignorare (specificando maiuscole e minuscole)",
|
||||
"LabelProgress": "Cominciati",
|
||||
"LabelProvider": "Provider",
|
||||
@ -616,4 +617,4 @@
|
||||
"ToastSocketFailedToConnect": "Socket non riesce a connettersi",
|
||||
"ToastUserDeleteFailed": "Errore eliminazione utente",
|
||||
"ToastUserDeleteSuccess": "Utente eliminato"
|
||||
}
|
||||
}
|
||||
|
@ -301,6 +301,7 @@
|
||||
"LabelPlayMethod": "Metoda odtwarzania",
|
||||
"LabelPodcast": "Podcast",
|
||||
"LabelPodcasts": "Podcasty",
|
||||
"LabelPodcastType": "Podcast Type",
|
||||
"LabelPrefixesToIgnore": "Ignorowane prefiksy (wielkość liter nie ma znaczenia)",
|
||||
"LabelProgress": "Postęp",
|
||||
"LabelProvider": "Dostawca",
|
||||
@ -616,4 +617,4 @@
|
||||
"ToastSocketFailedToConnect": "Poączenie z serwerem nie powiodło się",
|
||||
"ToastUserDeleteFailed": "Nie udało się usunąć użytkownika",
|
||||
"ToastUserDeleteSuccess": "Użytkownik usunięty"
|
||||
}
|
||||
}
|
||||
|
@ -301,6 +301,7 @@
|
||||
"LabelPlayMethod": "Метод Воспроизведения",
|
||||
"LabelPodcast": "Подкаст",
|
||||
"LabelPodcasts": "Подкасты",
|
||||
"LabelPodcastType": "Podcast Type",
|
||||
"LabelPrefixesToIgnore": "Игнорируемые Префиксы (без учета регистра)",
|
||||
"LabelProgress": "Прогресс",
|
||||
"LabelProvider": "Провайдер",
|
||||
@ -616,4 +617,4 @@
|
||||
"ToastSocketFailedToConnect": "Не удалось подключить сокет",
|
||||
"ToastUserDeleteFailed": "Не удалось удалить пользователя",
|
||||
"ToastUserDeleteSuccess": "Пользователь удален"
|
||||
}
|
||||
}
|
||||
|
@ -301,6 +301,7 @@
|
||||
"LabelPlayMethod": "播放方法",
|
||||
"LabelPodcast": "播客",
|
||||
"LabelPodcasts": "播客",
|
||||
"LabelPodcastType": "Podcast Type",
|
||||
"LabelPrefixesToIgnore": "忽略的前缀 (不区分大小写)",
|
||||
"LabelProgress": "进度",
|
||||
"LabelProvider": "供应商",
|
||||
@ -616,4 +617,4 @@
|
||||
"ToastSocketFailedToConnect": "网络连接失败",
|
||||
"ToastUserDeleteFailed": "删除用户失败",
|
||||
"ToastUserDeleteSuccess": "用户已删除"
|
||||
}
|
||||
}
|
||||
|
@ -106,6 +106,8 @@ class Feed {
|
||||
this.meta.feedUrl = feedUrl
|
||||
this.meta.link = `${serverAddress}/item/${libraryItem.id}`
|
||||
this.meta.explicit = !!mediaMetadata.explicit
|
||||
this.meta.type = mediaMetadata.type
|
||||
this.meta.language = mediaMetadata.language
|
||||
|
||||
this.episodes = []
|
||||
if (isPodcast) { // PODCAST EPISODES
|
||||
@ -142,6 +144,8 @@ class Feed {
|
||||
this.meta.author = author
|
||||
this.meta.imageUrl = media.coverPath ? `${this.serverAddress}/feed/${this.slug}/cover` : `${this.serverAddress}/Logo.png`
|
||||
this.meta.explicit = !!mediaMetadata.explicit
|
||||
this.meta.type = mediaMetadata.type
|
||||
this.meta.language = mediaMetadata.language
|
||||
|
||||
this.episodes = []
|
||||
if (isPodcast) { // PODCAST EPISODES
|
||||
@ -333,4 +337,4 @@ class Feed {
|
||||
return author
|
||||
}
|
||||
}
|
||||
module.exports = Feed
|
||||
module.exports = Feed
|
||||
|
@ -14,6 +14,9 @@ class FeedEpisode {
|
||||
this.author = null
|
||||
this.explicit = null
|
||||
this.duration = null
|
||||
this.season = null
|
||||
this.episode = null
|
||||
this.episodeType = null
|
||||
|
||||
this.libraryItemId = null
|
||||
this.episodeId = null
|
||||
@ -35,6 +38,9 @@ class FeedEpisode {
|
||||
this.author = episode.author
|
||||
this.explicit = episode.explicit
|
||||
this.duration = episode.duration
|
||||
this.season = episode.season
|
||||
this.episode = episode.episode
|
||||
this.episodeType = episode.episodeType
|
||||
this.libraryItemId = episode.libraryItemId
|
||||
this.episodeId = episode.episodeId || null
|
||||
this.trackIndex = episode.trackIndex || 0
|
||||
@ -52,6 +58,9 @@ class FeedEpisode {
|
||||
author: this.author,
|
||||
explicit: this.explicit,
|
||||
duration: this.duration,
|
||||
season: this.season,
|
||||
episode: this.episode,
|
||||
episodeType: this.episodeType,
|
||||
libraryItemId: this.libraryItemId,
|
||||
episodeId: this.episodeId,
|
||||
trackIndex: this.trackIndex,
|
||||
@ -77,6 +86,9 @@ class FeedEpisode {
|
||||
this.author = meta.author
|
||||
this.explicit = mediaMetadata.explicit
|
||||
this.duration = episode.duration
|
||||
this.season = episode.season
|
||||
this.episode = episode.episode
|
||||
this.episodeType = episode.episodeType
|
||||
this.libraryItemId = libraryItem.id
|
||||
this.episodeId = episode.id
|
||||
this.trackIndex = 0
|
||||
@ -144,9 +156,12 @@ class FeedEpisode {
|
||||
{ 'itunes:summary': this.description || '' },
|
||||
{
|
||||
"itunes:explicit": !!this.explicit
|
||||
}
|
||||
},
|
||||
{"itunes:episodeType": this.episodeType},
|
||||
{"itunes:season": this.season},
|
||||
{"itunes:episode": this.episode}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
module.exports = FeedEpisode
|
||||
module.exports = FeedEpisode
|
||||
|
@ -7,6 +7,8 @@ class FeedMeta {
|
||||
this.feedUrl = null
|
||||
this.link = null
|
||||
this.explicit = null
|
||||
this.type = null
|
||||
this.language = null
|
||||
|
||||
if (meta) {
|
||||
this.construct(meta)
|
||||
@ -21,6 +23,8 @@ class FeedMeta {
|
||||
this.feedUrl = meta.feedUrl
|
||||
this.link = meta.link
|
||||
this.explicit = meta.explicit
|
||||
this.type = meta.type
|
||||
this.language = meta.language
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
@ -31,7 +35,9 @@ class FeedMeta {
|
||||
imageUrl: this.imageUrl,
|
||||
feedUrl: this.feedUrl,
|
||||
link: this.link,
|
||||
explicit: this.explicit
|
||||
explicit: this.explicit,
|
||||
type: this.type,
|
||||
language: this.language
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,16 +49,17 @@ class FeedMeta {
|
||||
feed_url: this.feedUrl,
|
||||
site_url: this.link,
|
||||
image_url: this.imageUrl,
|
||||
language: 'en',
|
||||
custom_namespaces: {
|
||||
'itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd',
|
||||
'psc': 'http://podlove.org/simple-chapters',
|
||||
'podcast': 'https://podcastindex.org/namespace/1.0'
|
||||
},
|
||||
custom_elements: [
|
||||
{ 'language': this.language || 'en' },
|
||||
{ 'author': this.author || 'advplyr' },
|
||||
{ 'itunes:author': this.author || 'advplyr' },
|
||||
{ 'itunes:summary': this.description || '' },
|
||||
{ 'itunes:type': this.type },
|
||||
{
|
||||
'itunes:image': {
|
||||
_attr: {
|
||||
@ -73,4 +80,4 @@ class FeedMeta {
|
||||
}
|
||||
}
|
||||
}
|
||||
module.exports = FeedMeta
|
||||
module.exports = FeedMeta
|
||||
|
@ -117,7 +117,7 @@ class PodcastEpisode {
|
||||
this.enclosure = data.enclosure ? { ...data.enclosure } : null
|
||||
this.season = data.season || ''
|
||||
this.episode = data.episode || ''
|
||||
this.episodeType = data.episodeType || ''
|
||||
this.episodeType = data.episodeType || 'full'
|
||||
this.publishedAt = data.publishedAt || 0
|
||||
this.addedAt = Date.now()
|
||||
this.updatedAt = Date.now()
|
||||
@ -165,4 +165,4 @@ class PodcastEpisode {
|
||||
return cleanStringForSearch(this.title).includes(query)
|
||||
}
|
||||
}
|
||||
module.exports = PodcastEpisode
|
||||
module.exports = PodcastEpisode
|
||||
|
@ -15,6 +15,7 @@ class PodcastMetadata {
|
||||
this.itunesArtistId = null
|
||||
this.explicit = false
|
||||
this.language = null
|
||||
this.type = null
|
||||
|
||||
if (metadata) {
|
||||
this.construct(metadata)
|
||||
@ -34,6 +35,7 @@ class PodcastMetadata {
|
||||
this.itunesArtistId = metadata.itunesArtistId
|
||||
this.explicit = metadata.explicit
|
||||
this.language = metadata.language || null
|
||||
this.type = metadata.type || 'episodic'
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
@ -49,7 +51,8 @@ class PodcastMetadata {
|
||||
itunesId: this.itunesId,
|
||||
itunesArtistId: this.itunesArtistId,
|
||||
explicit: this.explicit,
|
||||
language: this.language
|
||||
language: this.language,
|
||||
type: this.type
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,7 +70,8 @@ class PodcastMetadata {
|
||||
itunesId: this.itunesId,
|
||||
itunesArtistId: this.itunesArtistId,
|
||||
explicit: this.explicit,
|
||||
language: this.language
|
||||
language: this.language,
|
||||
type: this.type
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,6 +116,7 @@ class PodcastMetadata {
|
||||
this.itunesArtistId = mediaMetadata.itunesArtistId || null
|
||||
this.explicit = !!mediaMetadata.explicit
|
||||
this.language = mediaMetadata.language || null
|
||||
this.type = mediaMetadata.type || null
|
||||
if (mediaMetadata.genres && mediaMetadata.genres.length) {
|
||||
this.genres = [...mediaMetadata.genres]
|
||||
}
|
||||
@ -132,4 +137,4 @@ class PodcastMetadata {
|
||||
return hasUpdates
|
||||
}
|
||||
}
|
||||
module.exports = PodcastMetadata
|
||||
module.exports = PodcastMetadata
|
||||
|
@ -899,7 +899,7 @@ class Scanner {
|
||||
description: episodeToMatch.description || '',
|
||||
enclosure: episodeToMatch.enclosure || null,
|
||||
episode: episodeToMatch.episode || '',
|
||||
episodeType: episodeToMatch.episodeType || '',
|
||||
episodeType: episodeToMatch.episodeType || 'full',
|
||||
season: episodeToMatch.season || '',
|
||||
pubDate: episodeToMatch.pubDate || '',
|
||||
publishedAt: episodeToMatch.publishedAt
|
||||
@ -993,4 +993,4 @@ class Scanner {
|
||||
return MediaFileScanner.probeAudioFileWithTone(audioFile)
|
||||
}
|
||||
}
|
||||
module.exports = Scanner
|
||||
module.exports = Scanner
|
||||
|
@ -46,7 +46,8 @@ function extractPodcastMetadata(channel) {
|
||||
categories: extractCategories(channel),
|
||||
feedUrl: null,
|
||||
description: null,
|
||||
descriptionPlain: null
|
||||
descriptionPlain: null,
|
||||
type: null
|
||||
}
|
||||
|
||||
if (channel['itunes:new-feed-url']) {
|
||||
@ -61,7 +62,7 @@ function extractPodcastMetadata(channel) {
|
||||
metadata.descriptionPlain = htmlSanitizer.stripAllTags(rawDescription)
|
||||
}
|
||||
|
||||
var arrayFields = ['title', 'language', 'itunes:explicit', 'itunes:author', 'pubDate', 'link']
|
||||
var arrayFields = ['title', 'language', 'itunes:explicit', 'itunes:author', 'pubDate', 'link', 'itunes:type']
|
||||
arrayFields.forEach((key) => {
|
||||
var cleanKey = key.split(':').pop()
|
||||
metadata[cleanKey] = extractFirstArrayItem(channel, key)
|
||||
@ -258,4 +259,4 @@ module.exports.findMatchingEpisodesInFeed = (feed, searchTitle) => {
|
||||
}
|
||||
})
|
||||
return matches.sort((a, b) => a.levenshtein - b.levenshtein)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user