diff --git a/client/components/modals/libraries/LibrarySettings.vue b/client/components/modals/libraries/LibrarySettings.vue
index 53eb2650..4712d6a2 100644
--- a/client/components/modals/libraries/LibrarySettings.vue
+++ b/client/components/modals/libraries/LibrarySettings.vue
@@ -49,6 +49,9 @@
+
+
+
@@ -69,7 +72,8 @@ export default {
skipMatchingMediaWithAsin: false,
skipMatchingMediaWithIsbn: false,
audiobooksOnly: false,
- hideSingleBookSeries: false
+ hideSingleBookSeries: false,
+ podcastSearchRegion: 'us'
}
},
computed: {
@@ -85,6 +89,9 @@ export default {
isBookLibrary() {
return this.mediaType === 'book'
},
+ isPodcastLibrary() {
+ return this.mediaType === 'podcast'
+ },
providers() {
if (this.mediaType === 'podcast') return this.$store.state.scanners.podcastProviders
return this.$store.state.scanners.providers
@@ -99,7 +106,8 @@ export default {
skipMatchingMediaWithAsin: !!this.skipMatchingMediaWithAsin,
skipMatchingMediaWithIsbn: !!this.skipMatchingMediaWithIsbn,
audiobooksOnly: !!this.audiobooksOnly,
- hideSingleBookSeries: !!this.hideSingleBookSeries
+ hideSingleBookSeries: !!this.hideSingleBookSeries,
+ podcastSearchRegion: this.podcastSearchRegion
}
}
},
@@ -113,6 +121,7 @@ export default {
this.skipMatchingMediaWithIsbn = !!this.librarySettings.skipMatchingMediaWithIsbn
this.audiobooksOnly = !!this.librarySettings.audiobooksOnly
this.hideSingleBookSeries = !!this.librarySettings.hideSingleBookSeries
+ this.podcastSearchRegion = this.librarySettings.podcastSearchRegion || 'us'
}
},
mounted() {
diff --git a/client/pages/library/_library/podcast/search.vue b/client/pages/library/_library/podcast/search.vue
index 3be851ce..4ca3fe7d 100644
--- a/client/pages/library/_library/podcast/search.vue
+++ b/client/pages/library/_library/podcast/search.vue
@@ -86,6 +86,9 @@ export default {
},
streamLibraryItem() {
return this.$store.state.streamLibraryItem
+ },
+ librarySettings() {
+ return this.$store.getters['libraries/getCurrentLibrarySettings']
}
},
methods: {
@@ -151,7 +154,12 @@ export default {
async submitSearch(term) {
this.processing = true
this.termSearched = ''
- let results = await this.$axios.$get(`/api/search/podcast?term=${encodeURIComponent(term)}`).catch((error) => {
+
+ const searchParams = new URLSearchParams({
+ term,
+ country: this.librarySettings?.podcastSearchRegion || 'us'
+ })
+ let results = await this.$axios.$get(`/api/search/podcast?${searchParams.toString()}`).catch((error) => {
console.error('Search request failed', error)
return []
})
diff --git a/client/plugins/i18n.js b/client/plugins/i18n.js
index 39eb7a09..d7fc972e 100644
--- a/client/plugins/i18n.js
+++ b/client/plugins/i18n.js
@@ -29,6 +29,18 @@ Vue.prototype.$languageCodeOptions = Object.keys(languageCodeMap).map(code => {
}
})
+// iTunes search API uses ISO 3166 country codes: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
+const podcastSearchRegionMap = {
+ 'us': { label: 'United States' },
+ 'cn': { label: '中国' }
+}
+Vue.prototype.$podcastSearchRegionOptions = Object.keys(podcastSearchRegionMap).map(code => {
+ return {
+ text: podcastSearchRegionMap[code].label,
+ value: code
+ }
+})
+
Vue.prototype.$languageCodes = {
default: defaultCode,
current: defaultCode,
diff --git a/client/strings/cs.json b/client/strings/cs.json
index d7afc3e9..3ab713ef 100644
--- a/client/strings/cs.json
+++ b/client/strings/cs.json
@@ -396,6 +396,7 @@
"LabelPlayMethod": "Metoda přehrávání",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasty",
+ "LabelPodcastSearchRegion": "Oblast vyhledávání podcastu",
"LabelPodcastType": "Typ podcastu",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Předpony, které se mají ignorovat (nerozlišují se malá a velká písmena)",
diff --git a/client/strings/da.json b/client/strings/da.json
index 5b6d826e..d456cd51 100644
--- a/client/strings/da.json
+++ b/client/strings/da.json
@@ -396,6 +396,7 @@
"LabelPlayMethod": "Afspilningsmetode",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
+ "LabelPodcastSearchRegion": "Podcast søgeområde",
"LabelPodcastType": "Podcast type",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Præfikser der skal ignoreres (skal ikke skelne mellem store og små bogstaver)",
diff --git a/client/strings/de.json b/client/strings/de.json
index 47a26467..ff8e991a 100644
--- a/client/strings/de.json
+++ b/client/strings/de.json
@@ -396,6 +396,7 @@
"LabelPlayMethod": "Abspielmethode",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
+ "LabelPodcastSearchRegion": "Podcast-Suchregion",
"LabelPodcastType": "Podcast Typ",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Zu ignorierende(s) Vorwort(e) (Groß- und Kleinschreibung wird nicht berücksichtigt)",
diff --git a/client/strings/en-us.json b/client/strings/en-us.json
index eb30c519..8c58093a 100644
--- a/client/strings/en-us.json
+++ b/client/strings/en-us.json
@@ -396,6 +396,7 @@
"LabelPlayMethod": "Play Method",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
+ "LabelPodcastSearchRegion": "Podcast search region",
"LabelPodcastType": "Podcast Type",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Prefixes to Ignore (case insensitive)",
diff --git a/client/strings/es.json b/client/strings/es.json
index 56876087..f2714c00 100644
--- a/client/strings/es.json
+++ b/client/strings/es.json
@@ -396,6 +396,7 @@
"LabelPlayMethod": "Método de Reproducción",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
+ "LabelPodcastSearchRegion": "Región de búsqueda de podcasts",
"LabelPodcastType": "Tipo Podcast",
"LabelPort": "Puerto",
"LabelPrefixesToIgnore": "Prefijos para Ignorar (no distingue entre mayúsculas y minúsculas.)",
diff --git a/client/strings/fr.json b/client/strings/fr.json
index 7e1f358c..3f04fab8 100644
--- a/client/strings/fr.json
+++ b/client/strings/fr.json
@@ -396,6 +396,7 @@
"LabelPlayMethod": "Méthode d’écoute",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
+ "LabelPodcastSearchRegion": "Région de recherche de podcasts",
"LabelPodcastType": "Type de Podcast",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Préfixes à Ignorer (Insensible à la Casse)",
diff --git a/client/strings/gu.json b/client/strings/gu.json
index 6f3cdbb9..daa923db 100644
--- a/client/strings/gu.json
+++ b/client/strings/gu.json
@@ -396,6 +396,7 @@
"LabelPlayMethod": "Play Method",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
+ "LabelPodcastSearchRegion": "પોડકાસ્ટ શોધ પ્રદેશ",
"LabelPodcastType": "Podcast Type",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Prefixes to Ignore (case insensitive)",
diff --git a/client/strings/hi.json b/client/strings/hi.json
index 25b8e7a5..a59b43ec 100644
--- a/client/strings/hi.json
+++ b/client/strings/hi.json
@@ -396,6 +396,7 @@
"LabelPlayMethod": "Play Method",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
+ "LabelPodcastSearchRegion": "पॉडकास्ट खोज क्षेत्र",
"LabelPodcastType": "Podcast Type",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Prefixes to Ignore (case insensitive)",
diff --git a/client/strings/hr.json b/client/strings/hr.json
index f15d2065..6e105ca2 100644
--- a/client/strings/hr.json
+++ b/client/strings/hr.json
@@ -396,6 +396,7 @@
"LabelPlayMethod": "Vrsta reprodukcije",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
+ "LabelPodcastSearchRegion": "Područje pretrage podcasta",
"LabelPodcastType": "Podcast Type",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Prefiksi za ignorirati (mala i velika slova nisu bitna)",
diff --git a/client/strings/it.json b/client/strings/it.json
index be12bb51..53394481 100644
--- a/client/strings/it.json
+++ b/client/strings/it.json
@@ -396,6 +396,7 @@
"LabelPlayMethod": "Metodo di riproduzione",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
+ "LabelPodcastSearchRegion": "Area di ricerca podcast",
"LabelPodcastType": "Tipo di Podcast",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Suffissi da ignorare (specificando maiuscole e minuscole)",
diff --git a/client/strings/lt.json b/client/strings/lt.json
index add5c575..f98d5aee 100644
--- a/client/strings/lt.json
+++ b/client/strings/lt.json
@@ -396,6 +396,7 @@
"LabelPlayMethod": "Grojimo metodas",
"LabelPodcast": "Tinklalaidė",
"LabelPodcasts": "Tinklalaidės",
+ "LabelPodcastSearchRegion": "Podcast paieškos regionas",
"LabelPodcastType": "Tinklalaidės tipas",
"LabelPort": "Prievadas",
"LabelPrefixesToIgnore": "Ignoruojami priešdėliai (didžiosios/mažosios nesvarbu)",
diff --git a/client/strings/nl.json b/client/strings/nl.json
index bc4974e3..1c1ffa1b 100644
--- a/client/strings/nl.json
+++ b/client/strings/nl.json
@@ -396,6 +396,7 @@
"LabelPlayMethod": "Afspeelwijze",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
+ "LabelPodcastSearchRegion": "Podcast zoekregio",
"LabelPodcastType": "Podcasttype",
"LabelPort": "Poort",
"LabelPrefixesToIgnore": "Te negeren voorzetsels (ongeacht hoofdlettergebruik)",
diff --git a/client/strings/no.json b/client/strings/no.json
index 72d3eed4..432115df 100644
--- a/client/strings/no.json
+++ b/client/strings/no.json
@@ -396,6 +396,7 @@
"LabelPlayMethod": "Avspillingsmetode",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcaster",
+ "LabelPodcastSearchRegion": "Podcast-søkeområde",
"LabelPodcastType": "Podcast type",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Prefiks som skal ignoreres (skiller ikke mellom store og små bokstaver)",
diff --git a/client/strings/pl.json b/client/strings/pl.json
index 8db18059..7f0e4497 100644
--- a/client/strings/pl.json
+++ b/client/strings/pl.json
@@ -396,6 +396,7 @@
"LabelPlayMethod": "Metoda odtwarzania",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasty",
+ "LabelPodcastSearchRegion": "Obszar wyszukiwania podcastów",
"LabelPodcastType": "Podcast Type",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Ignorowane prefiksy (wielkość liter nie ma znaczenia)",
diff --git a/client/strings/pt-br.json b/client/strings/pt-br.json
index 148d53d5..cd4e9cab 100644
--- a/client/strings/pt-br.json
+++ b/client/strings/pt-br.json
@@ -40,8 +40,8 @@
"ButtonLookup": "Procurar",
"ButtonManageTracks": "Gerenciar Faixas",
"ButtonMapChapterTitles": "Designar Títulos de Capítulos",
- "ButtonitensAllAuthors": "Consultar Todos os Autores",
- "ButtonitensBooks": "Consultar Livros",
+ "ButtonMatchAllAuthors": "Consultar Todos os Autores",
+ "ButtonMatchBooks": "Consultar Livros",
"ButtonNevermind": "Cancelar",
"ButtonNextChapter": "Próximo Capítulo",
"ButtonOk": "Ok",
@@ -57,7 +57,7 @@
"ButtonPurgeMediaProgress": "Apagar o Progresso nas Mídias",
"ButtonQueueAddItem": "Adicionar à Lista",
"ButtonQueueRemoveItem": "Remover da Lista",
- "ButtonQuickitens": "Consulta rápida",
+ "ButtonQuickMatch": "Consulta rápida",
"ButtonRead": "Ler",
"ButtonRemove": "Remover",
"ButtonRemoveAll": "Remover Todos",
@@ -133,9 +133,9 @@
"HeaderLogin": "Login",
"HeaderLogs": "Logs",
"HeaderManageGenres": "Gerenciar Gêneros",
- "HeaderManageetiquetas": "Gerenciar Etiquetas",
+ "HeaderManageTags": "Gerenciar Etiquetas",
"HeaderMapDetails": "Designar Detalhes",
- "Headeritens": "Consultar",
+ "HeaderMatch": "Consultar",
"HeaderMetadataOrderOfPrecedence": "Ordem de Prioridade dos Metadados",
"HeaderMetadataToEmbed": "Metadados a Serem Incluídos",
"HeaderNewAccount": "Nova Conta",
@@ -396,6 +396,7 @@
"LabelPlayMethod": "Método de Reprodução",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
+ "LabelPodcastSearchRegion": "Podcast search region",
"LabelPodcastType": "Tipo de Podcast",
"LabelPort": "Porta",
"LabelPrefixesToIgnore": "Prefixos para Ignorar (sem distinção entre maiúsculas e minúsculas)",
@@ -764,4 +765,4 @@
"ToastSocketFailedToConnect": "Falha na conexão do socket",
"ToastUserDeleteFailed": "Falha ao apagar usuário",
"ToastUserDeleteSuccess": "Usuário apagado"
-}
+}
\ No newline at end of file
diff --git a/client/strings/ru.json b/client/strings/ru.json
index 49d67fbe..3657b596 100644
--- a/client/strings/ru.json
+++ b/client/strings/ru.json
@@ -396,6 +396,7 @@
"LabelPlayMethod": "Метод воспроизведения",
"LabelPodcast": "Подкаст",
"LabelPodcasts": "Подкасты",
+ "LabelPodcastSearchRegion": "Регион поиска подкастов",
"LabelPodcastType": "Тип подкаста",
"LabelPort": "Порт",
"LabelPrefixesToIgnore": "Игнорируемые префиксы (без учета регистра)",
diff --git a/client/strings/sv.json b/client/strings/sv.json
index 3cf645b5..986f2c4b 100644
--- a/client/strings/sv.json
+++ b/client/strings/sv.json
@@ -396,6 +396,7 @@
"LabelPlayMethod": "Spelläge",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
+ "LabelPodcastSearchRegion": "Podcast-sökområde",
"LabelPodcastType": "Podcasttyp",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Prefix att ignorera (skiftlägesokänsligt)",
diff --git a/client/strings/zh-cn.json b/client/strings/zh-cn.json
index 17b3cd6a..fd7fe290 100644
--- a/client/strings/zh-cn.json
+++ b/client/strings/zh-cn.json
@@ -396,6 +396,7 @@
"LabelPlayMethod": "播放方法",
"LabelPodcast": "播客",
"LabelPodcasts": "播客",
+ "LabelPodcastSearchRegion": "播客搜索地区",
"LabelPodcastType": "播客类型",
"LabelPort": "端口",
"LabelPrefixesToIgnore": "忽略的前缀 (不区分大小写)",
diff --git a/server/controllers/SearchController.js b/server/controllers/SearchController.js
index 34d65e3c..213d23e1 100644
--- a/server/controllers/SearchController.js
+++ b/server/controllers/SearchController.js
@@ -43,12 +43,15 @@ class SearchController {
*/
async findPodcasts(req, res) {
const term = req.query.term
+ const country = req.query.country || 'us'
if (!term) {
Logger.error('[SearchController] Invalid request query param "term" is required')
return res.status(400).send('Invalid request query param "term" is required')
}
- const results = await PodcastFinder.search(term)
+ const results = await PodcastFinder.search(term, {
+ country
+ })
res.json(results)
}
diff --git a/server/finders/PodcastFinder.js b/server/finders/PodcastFinder.js
index 52fec15c..abaf02ac 100644
--- a/server/finders/PodcastFinder.js
+++ b/server/finders/PodcastFinder.js
@@ -6,10 +6,16 @@ class PodcastFinder {
this.iTunesApi = new iTunes()
}
+ /**
+ *
+ * @param {string} term
+ * @param {{country:string}} options
+ * @returns {Promise}
+ */
async search(term, options = {}) {
if (!term) return null
Logger.debug(`[iTunes] Searching for podcast with term "${term}"`)
- var results = await this.iTunesApi.searchPodcasts(term, options)
+ const results = await this.iTunesApi.searchPodcasts(term, options)
Logger.debug(`[iTunes] Podcast search for "${term}" returned ${results.length} results`)
return results
}
diff --git a/server/objects/settings/LibrarySettings.js b/server/objects/settings/LibrarySettings.js
index 10ee19e0..b070ff79 100644
--- a/server/objects/settings/LibrarySettings.js
+++ b/server/objects/settings/LibrarySettings.js
@@ -10,6 +10,7 @@ class LibrarySettings {
this.audiobooksOnly = false
this.hideSingleBookSeries = false // Do not show series that only have 1 book
this.metadataPrecedence = ['folderStructure', 'audioMetatags', 'nfoFile', 'txtFiles', 'opfFile', 'absMetadata']
+ this.podcastSearchRegion = 'us'
if (settings) {
this.construct(settings)
@@ -30,6 +31,7 @@ class LibrarySettings {
// Added in v2.4.5
this.metadataPrecedence = ['folderStructure', 'audioMetatags', 'nfoFile', 'txtFiles', 'opfFile', 'absMetadata']
}
+ this.podcastSearchRegion = settings.podcastSearchRegion || 'us'
}
toJSON() {
@@ -41,7 +43,8 @@ class LibrarySettings {
autoScanCronExpression: this.autoScanCronExpression,
audiobooksOnly: this.audiobooksOnly,
hideSingleBookSeries: this.hideSingleBookSeries,
- metadataPrecedence: [...this.metadataPrecedence]
+ metadataPrecedence: [...this.metadataPrecedence],
+ podcastSearchRegion: this.podcastSearchRegion
}
}
diff --git a/server/providers/iTunes.js b/server/providers/iTunes.js
index 39f36ab2..05a661b5 100644
--- a/server/providers/iTunes.js
+++ b/server/providers/iTunes.js
@@ -2,16 +2,46 @@ const axios = require('axios')
const Logger = require('../Logger')
const htmlSanitizer = require('../utils/htmlSanitizer')
+/**
+ * @typedef iTunesSearchParams
+ * @property {string} term
+ * @property {string} country
+ * @property {string} media
+ * @property {string} entity
+ * @property {number} limit
+ */
+
+/**
+ * @typedef iTunesPodcastSearchResult
+ * @property {string} id
+ * @property {string} artistId
+ * @property {string} title
+ * @property {string} artistName
+ * @property {string} description
+ * @property {string} descriptionPlain
+ * @property {string} releaseDate
+ * @property {string[]} genres
+ * @property {string} cover
+ * @property {string} feedUrl
+ * @property {string} pageUrl
+ * @property {boolean} explicit
+ */
+
class iTunes {
constructor() { }
- // https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/iTuneSearchAPI/Searching.html
+ /**
+ * @see https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/iTuneSearchAPI/Searching.html
+ *
+ * @param {iTunesSearchParams} options
+ * @returns {Promise