Add:Abridged book detail, parse from audible, abridged book filter #1408

This commit is contained in:
advplyr 2023-03-22 18:05:43 -05:00
parent 7181df0479
commit fd58df4729
20 changed files with 78 additions and 17 deletions

View File

@ -185,6 +185,11 @@ export default {
value: 'tracks',
sublist: true
},
{
text: this.$strings.LabelAbridged,
value: 'abridged',
sublist: false
},
{
text: this.$strings.ButtonIssues,
value: 'issues',

View File

@ -164,13 +164,20 @@
<p v-if="mediaMetadata.releaseDate" class="text-xs ml-1 text-white text-opacity-60">{{ $strings.LabelCurrently }} {{ mediaMetadata.releaseDate || '' }}</p>
</div>
</div>
<div v-if="selectedMatchOrig.explicit != null" class="flex items-center py-2">
<div v-if="selectedMatchOrig.explicit != null" class="flex items-center pb-2" :class="{ 'pt-2': mediaMetadata.explicit == null }">
<ui-checkbox v-model="selectedMatchUsage.explicit" checkbox-bg="bg" @input="checkboxToggled" />
<div class="flex-grow ml-4">
<ui-checkbox v-model="selectedMatch.explicit" :label="$strings.LabelExplicit" checkbox-bg="primary" border-color="gray-600" label-class="pl-2 text-base font-semibold" />
<div class="flex-grow ml-4" :class="{ 'pt-4': mediaMetadata.explicit != null }">
<ui-checkbox v-model="selectedMatch.explicit" :label="$strings.LabelExplicit" :disabled="!selectedMatchUsage.explicit" :checkbox-bg="!selectedMatchUsage.explicit ? 'bg' : 'primary'" border-color="gray-600" label-class="pl-2 text-base font-semibold" />
<p v-if="mediaMetadata.explicit != null" class="text-xs ml-1 text-white text-opacity-60">{{ $strings.LabelCurrently }} {{ mediaMetadata.explicit ? 'Explicit (checked)' : 'Not Explicit (unchecked)' }}</p>
</div>
</div>
<div v-if="selectedMatchOrig.abridged != null" class="flex items-center pb-2" :class="{ 'pt-2': mediaMetadata.abridged == null }">
<ui-checkbox v-model="selectedMatchUsage.abridged" checkbox-bg="bg" @input="checkboxToggled" />
<div class="flex-grow ml-4" :class="{ 'pt-4': mediaMetadata.abridged != null }">
<ui-checkbox v-model="selectedMatch.abridged" :label="$strings.LabelAbridged" :disabled="!selectedMatchUsage.abridged" :checkbox-bg="!selectedMatchUsage.abridged ? 'bg' : 'primary'" border-color="gray-600" label-class="pl-2 text-base font-semibold" />
<p v-if="mediaMetadata.abridged != null" class="text-xs ml-1 text-white text-opacity-60">{{ $strings.LabelCurrently }} {{ mediaMetadata.abridged ? 'Abridged (checked)' : 'Unabridged (unchecked)' }}</p>
</div>
</div>
<div class="flex items-center justify-end py-2">
<ui-btn color="success" type="submit">{{ $strings.ButtonSubmit }}</ui-btn>
@ -216,6 +223,7 @@ export default {
explicit: true,
asin: true,
isbn: true,
abridged: true,
// Podcast specific
itunesPageUrl: true,
itunesId: true,
@ -360,6 +368,7 @@ export default {
explicit: true,
asin: true,
isbn: true,
abridged: true,
// Podcast specific
itunesPageUrl: true,
itunesId: true,
@ -476,7 +485,6 @@ export default {
} else if (key === 'narrator') {
updatePayload.metadata.narrators = this.selectedMatch[key].split(',').map((v) => v.trim())
} else if (key === 'genres') {
// updatePayload.metadata.genres = this.selectedMatch[key].split(',').map((v) => v.trim())
updatePayload.metadata.genres = [...this.selectedMatch[key]]
} else if (key === 'tags') {
updatePayload.tags = this.selectedMatch[key].split(',').map((v) => v.trim())

View File

@ -4,7 +4,7 @@
<input v-model="selected" :disabled="disabled" type="checkbox" class="opacity-0 absolute" :class="!disabled ? 'cursor-pointer' : ''" />
<svg v-if="selected" class="fill-current pointer-events-none" :class="svgClass" viewBox="0 0 20 20"><path d="M0 11l2-2 5 5L18 3l2 2L7 18z" /></svg>
</div>
<div v-if="label" class="select-none text-gray-100" :class="labelClassname">{{ label }}</div>
<div v-if="label" class="select-none" :class="[labelClassname, disabled ? 'text-gray-400' : 'text-gray-100']">{{ label }}</div>
</label>
</template>

View File

@ -50,7 +50,7 @@
</div>
<div class="flex flex-wrap mt-2 -mx-1">
<div class="w-full md:w-1/2 px-1">
<div class="w-full md:w-1/4 px-1">
<ui-text-input-with-label ref="publisherInput" v-model="details.publisher" :label="$strings.LabelPublisher" />
</div>
<div class="w-1/2 md:w-1/4 px-1 mt-2 md:mt-0">
@ -61,6 +61,11 @@
<ui-checkbox v-model="details.explicit" :label="$strings.LabelExplicit" checkbox-bg="primary" border-color="gray-600" label-class="pl-2 text-base font-semibold" />
</div>
</div>
<div class="flex-grow px-1 pt-6 mt-2 md:mt-0">
<div class="flex justify-center">
<ui-checkbox v-model="details.abridged" :label="$strings.LabelAbridged" checkbox-bg="primary" border-color="gray-600" label-class="pl-2 text-base font-semibold" />
</div>
</div>
</div>
</form>
</div>
@ -89,7 +94,8 @@ export default {
isbn: null,
asin: null,
genres: [],
explicit: false
explicit: false,
abridged: false
},
newTags: []
}
@ -271,6 +277,7 @@ export default {
this.details.isbn = this.mediaMetadata.isbn || null
this.details.asin = this.mediaMetadata.asin || null
this.details.explicit = !!this.mediaMetadata.explicit
this.details.abridged = !!this.mediaMetadata.abridged
this.newTags = [...(this.media.tags || [])]
},
submitForm() {

View File

@ -124,6 +124,14 @@
{{ sizePretty }}
</div>
</div>
<div v-if="isBook" class="flex py-0.5">
<div class="w-32">
<span class="text-white text-opacity-60 uppercase text-sm">{{ $strings.LabelAbridged }}</span>
</div>
<div>
{{ isAbridged ? 'Yes' : 'No' }}
</div>
</div>
</div>
<div class="hidden md:block flex-grow" />
</div>
@ -319,7 +327,10 @@ export default {
return this.libraryItem.isInvalid
},
isExplicit() {
return this.mediaMetadata.explicit || false
return !!this.mediaMetadata.explicit
},
isAbridged() {
return !!this.mediaMetadata.abridged
},
invalidAudioFiles() {
if (!this.isBook) return []

View File

@ -155,6 +155,7 @@
"HeaderUpdateLibrary": "Bibliothek aktualisieren",
"HeaderUsers": "Benutzer",
"HeaderYourStats": "Eigene Statistiken",
"LabelAbridged": "Abridged",
"LabelAccountType": "Kontoart",
"LabelAccountTypeAdmin": "Admin",
"LabelAccountTypeGuest": "Gast",
@ -420,6 +421,7 @@
"LabelTracksMultiTrack": "Mehrfachdatei",
"LabelTracksSingleTrack": "Einzeldatei",
"LabelType": "Typ",
"LabelUnabridged": "Unabridged",
"LabelUnknown": "Unbekannt",
"LabelUpdateCover": "Titelbild aktualisieren",
"LabelUpdateCoverHelp": "Erlaube das Überschreiben bestehender Titelbilder für die ausgewählten Hörbücher wenn eine Übereinstimmung gefunden wird",

View File

@ -155,6 +155,7 @@
"HeaderUpdateLibrary": "Update Library",
"HeaderUsers": "Users",
"HeaderYourStats": "Your Stats",
"LabelAbridged": "Abridged",
"LabelAccountType": "Account Type",
"LabelAccountTypeAdmin": "Admin",
"LabelAccountTypeGuest": "Guest",
@ -420,6 +421,7 @@
"LabelTracksMultiTrack": "Multi-track",
"LabelTracksSingleTrack": "Single-track",
"LabelType": "Type",
"LabelUnabridged": "Unabridged",
"LabelUnknown": "Unknown",
"LabelUpdateCover": "Update Cover",
"LabelUpdateCoverHelp": "Allow overwriting of existing covers for the selected books when a match is located",
@ -636,4 +638,4 @@
"ToastSocketFailedToConnect": "Socket failed to connect",
"ToastUserDeleteFailed": "Failed to delete user",
"ToastUserDeleteSuccess": "User deleted"
}
}

View File

@ -155,6 +155,7 @@
"HeaderUpdateLibrary": "Actualizar Biblioteca",
"HeaderUsers": "Usuarios",
"HeaderYourStats": "Tus Estáticas",
"LabelAbridged": "Abridged",
"LabelAccountType": "Tipo de Cuenta",
"LabelAccountTypeAdmin": "Administrador",
"LabelAccountTypeGuest": "Invitado",
@ -420,6 +421,7 @@
"LabelTracksMultiTrack": "Multi-track",
"LabelTracksSingleTrack": "Single-track",
"LabelType": "Tipo",
"LabelUnabridged": "Unabridged",
"LabelUnknown": "Desconocido",
"LabelUpdateCover": "Actualizar Portada",
"LabelUpdateCoverHelp": "Permitir sobrescribir portadas existentes de los libros seleccionados cuando sean encontrados.",

View File

@ -155,6 +155,7 @@
"HeaderUpdateLibrary": "Mettre à jour la bibliothèque",
"HeaderUsers": "Utilisateurs",
"HeaderYourStats": "Vos statistiques",
"LabelAbridged": "Abridged",
"LabelAccountType": "Type de compte",
"LabelAccountTypeAdmin": "Admin",
"LabelAccountTypeGuest": "Invité",
@ -420,6 +421,7 @@
"LabelTracksMultiTrack": "Piste multiple",
"LabelTracksSingleTrack": "Piste simple",
"LabelType": "Type",
"LabelUnabridged": "Unabridged",
"LabelUnknown": "Inconnu",
"LabelUpdateCover": "Mettre à jour la couverture",
"LabelUpdateCoverHelp": "Autoriser la mise à jour de la couverture existante lorsquune correspondance est trouvée",

View File

@ -155,6 +155,7 @@
"HeaderUpdateLibrary": "Aktualiziraj biblioteku",
"HeaderUsers": "Korinici",
"HeaderYourStats": "Tvoja statistika",
"LabelAbridged": "Abridged",
"LabelAccountType": "Vrsta korisničkog računa",
"LabelAccountTypeAdmin": "Administrator",
"LabelAccountTypeGuest": "Gost",
@ -420,6 +421,7 @@
"LabelTracksMultiTrack": "Multi-track",
"LabelTracksSingleTrack": "Single-track",
"LabelType": "Tip",
"LabelUnabridged": "Unabridged",
"LabelUnknown": "Nepoznato",
"LabelUpdateCover": "Aktualiziraj Cover",
"LabelUpdateCoverHelp": "Dozvoli postavljanje novog covera za odabrane knjige nakon što je match pronađen.",

View File

@ -155,6 +155,7 @@
"HeaderUpdateLibrary": "Aggiorna Libreria",
"HeaderUsers": "Utenti",
"HeaderYourStats": "Statistiche Personali",
"LabelAbridged": "Abridged",
"LabelAccountType": "Tipo di Account",
"LabelAccountTypeAdmin": "Admin",
"LabelAccountTypeGuest": "Ospite",
@ -420,6 +421,7 @@
"LabelTracksMultiTrack": "Multi-traccia",
"LabelTracksSingleTrack": "Traccia-singola",
"LabelType": "Tipo",
"LabelUnabridged": "Unabridged",
"LabelUnknown": "Sconosciuto",
"LabelUpdateCover": "Aggiornamento Cover",
"LabelUpdateCoverHelp": "Consenti la sovrascrittura delle copertine esistenti per i libri selezionati quando viene trovata una corrispondenza",
@ -636,4 +638,4 @@
"ToastSocketFailedToConnect": "Socket non riesce a connettersi",
"ToastUserDeleteFailed": "Errore eliminazione utente",
"ToastUserDeleteSuccess": "Utente eliminato"
}
}

View File

@ -155,6 +155,7 @@
"HeaderUpdateLibrary": "Zaktualizuj bibliotekę",
"HeaderUsers": "Użytkownicy",
"HeaderYourStats": "Twoje statystyki",
"LabelAbridged": "Abridged",
"LabelAccountType": "Typ konta",
"LabelAccountTypeAdmin": "Administrator",
"LabelAccountTypeGuest": "Gość",
@ -420,6 +421,7 @@
"LabelTracksMultiTrack": "Multi-track",
"LabelTracksSingleTrack": "Single-track",
"LabelType": "Typ",
"LabelUnabridged": "Unabridged",
"LabelUnknown": "Nieznany",
"LabelUpdateCover": "Zaktalizuj odkładkę",
"LabelUpdateCoverHelp": "Umożliwienie nadpisania istniejących okładek dla wybranych książek w przypadku znalezienia dopasowania",

View File

@ -155,6 +155,7 @@
"HeaderUpdateLibrary": "Обновить библиотеку",
"HeaderUsers": "Пользователи",
"HeaderYourStats": "Ваша статистика",
"LabelAbridged": "Abridged",
"LabelAccountType": "Тип учетной записи",
"LabelAccountTypeAdmin": "Администратор",
"LabelAccountTypeGuest": "Гость",
@ -420,6 +421,7 @@
"LabelTracksMultiTrack": "Мультитрек",
"LabelTracksSingleTrack": "Один трек",
"LabelType": "Тип",
"LabelUnabridged": "Unabridged",
"LabelUnknown": "Неизвестно",
"LabelUpdateCover": "Обновить обложку",
"LabelUpdateCoverHelp": "Позволяет перезаписывать существующие обложки для выбранных книг если будут найдены",

View File

@ -155,6 +155,7 @@
"HeaderUpdateLibrary": "更新媒体库",
"HeaderUsers": "用户",
"HeaderYourStats": "你的统计数据",
"LabelAbridged": "Abridged",
"LabelAccountType": "帐户类型",
"LabelAccountTypeAdmin": "管理员",
"LabelAccountTypeGuest": "来宾",
@ -420,6 +421,7 @@
"LabelTracksMultiTrack": "多轨",
"LabelTracksSingleTrack": "单轨",
"LabelType": "类型",
"LabelUnabridged": "Unabridged",
"LabelUnknown": "未知",
"LabelUpdateCover": "更新封面",
"LabelUpdateCoverHelp": "找到匹配项时允许覆盖所选书籍存在的封面",

View File

@ -17,6 +17,7 @@ class BookMetadata {
this.asin = null
this.language = null
this.explicit = false
this.abridged = false
if (metadata) {
this.construct(metadata)
@ -38,6 +39,7 @@ class BookMetadata {
this.asin = metadata.asin
this.language = metadata.language
this.explicit = !!metadata.explicit
this.abridged = !!metadata.abridged
}
toJSON() {
@ -55,7 +57,8 @@ class BookMetadata {
isbn: this.isbn,
asin: this.asin,
language: this.language,
explicit: this.explicit
explicit: this.explicit,
abridged: this.abridged
}
}
@ -76,7 +79,8 @@ class BookMetadata {
isbn: this.isbn,
asin: this.asin,
language: this.language,
explicit: this.explicit
explicit: this.explicit,
abridged: this.abridged
}
}
@ -100,7 +104,8 @@ class BookMetadata {
authorName: this.authorName,
authorNameLF: this.authorNameLF,
narratorName: this.narratorName,
seriesName: this.seriesName
seriesName: this.seriesName,
abridged: this.abridged
}
}

View File

@ -19,7 +19,7 @@ class Audible {
}
cleanResult(item) {
const { title, subtitle, asin, authors, narrators, publisherName, summary, releaseDate, image, genres, seriesPrimary, seriesSecondary, language, runtimeLengthMin } = item
const { title, subtitle, asin, authors, narrators, publisherName, summary, releaseDate, image, genres, seriesPrimary, seriesSecondary, language, runtimeLengthMin, formatType } = item
const series = []
if (seriesPrimary) {
@ -54,7 +54,8 @@ class Audible {
language: language ? language.charAt(0).toUpperCase() + language.slice(1) : null,
duration: runtimeLengthMin && !isNaN(runtimeLengthMin) ? Number(runtimeLengthMin) : 0,
region: item.region || null,
rating: item.rating || null
rating: item.rating || null,
abridged: formatType === 'abridged'
}
}

View File

@ -793,7 +793,7 @@ class Scanner {
async quickMatchBookBuildUpdatePayload(libraryItem, matchData, options) {
// Update media metadata if not set OR overrideDetails flag
const detailKeysToUpdate = ['title', 'subtitle', 'description', 'narrator', 'publisher', 'publishedYear', 'genres', 'tags', 'language', 'explicit', 'asin', 'isbn']
const detailKeysToUpdate = ['title', 'subtitle', 'description', 'narrator', 'publisher', 'publishedYear', 'genres', 'tags', 'language', 'explicit', 'abridged', 'asin', 'isbn']
const updatePayload = {}
updatePayload.metadata = {}

View File

@ -121,6 +121,10 @@ const bookMetadataMapper = {
explicit: {
to: (m) => m.explicit ? 'Y' : 'N',
from: (v) => v && v.toLowerCase() == 'y'
},
abridged: {
to: (m) => m.abridged ? 'Y' : 'N',
from: (v) => v && v.toLowerCase() == 'y'
}
}

View File

@ -108,7 +108,7 @@ module.exports.reqSupportsWebp = (req) => {
module.exports.areEquivalent = areEquivalent
module.exports.copyValue = (val) => {
if (!val) return null
if (!val) return val === false ? false : null
if (!this.isObject(val)) return val
if (Array.isArray(val)) {

View File

@ -67,6 +67,8 @@ module.exports = {
filtered = filtered.filter(li => li.hasIssues)
} else if (filterBy === 'feed-open') {
filtered = filtered.filter(li => feedsArray.some(feed => feed.entityId === li.id))
} else if (filterBy === 'abridged') {
filtered = filtered.filter(li => !!li.media.metadata?.abridged)
}
return filtered