@@ -3,6 +3,7 @@ import { downloadedEpisodes } from "./store";
33import { DownloadPathTemplateEngine } from "./TemplateEngine" ;
44import type { Episode } from "./types/Episode" ;
55import getUrlExtension from "./utility/getUrlExtension" ;
6+ import getExtensionFromContentType from "./utility/getExtensionFromContentType" ;
67
78function getErrorMessage ( error : unknown ) : string {
89 return error instanceof Error ? error . message : String ( error ) ;
@@ -74,18 +75,11 @@ export default async function downloadEpisodeWithNotice(
7475 } ,
7576 } ) ;
7677
77- const fileExtension = await detectAudioFileExtension ( blob ) ;
78- if ( ! fileExtension ) {
79- update ( ( bodyEl ) => {
80- bodyEl . createEl ( "p" , {
81- text : `Could not determine file extension for downloaded file. Blob: ${ blob . size } bytes.` ,
82- } ) ;
83- } ) ;
78+ const inferredExtension = await inferFileExtensionFromDownload ( episode , blob ) ;
79+ const normalizedType = ( blob . type ?? "" ) . toLowerCase ( ) ;
80+ const typeAppearsAudio = normalizedType === "" || normalizedType . includes ( "audio" ) ;
8481
85- throw new Error ( "Could not determine file extension" ) ;
86- }
87-
88- if ( ! blob . type . contains ( "audio" ) && ! fileExtension ) {
82+ if ( ! typeAppearsAudio && ! inferredExtension ) {
8983 update ( ( bodyEl ) => {
9084 bodyEl . createEl ( "p" , {
9185 text : `Downloaded file is not an audio file. It is of type "${ blob . type } ". Blob: ${ blob . size } bytes.` ,
@@ -95,6 +89,8 @@ export default async function downloadEpisodeWithNotice(
9589 throw new Error ( "Not an audio file" ) ;
9690 }
9791
92+ const fileExtension = inferredExtension ?? "mp3" ;
93+
9894 try {
9995 update ( ( bodyEl ) => bodyEl . createEl ( "p" , { text : "Creating file..." } ) ) ;
10096
@@ -179,6 +175,23 @@ async function createEpisodeFile({
179175 downloadedEpisodes . addEpisode ( episode , filePath , blob . size ) ;
180176}
181177
178+ async function inferFileExtensionFromDownload (
179+ episode : Episode ,
180+ blob : Blob ,
181+ ) : Promise < string | null > {
182+ const signatureExtension = await detectAudioFileExtension ( blob ) ;
183+ if ( signatureExtension ) {
184+ return signatureExtension ;
185+ }
186+
187+ const urlExtension = getUrlExtension ( episode . streamUrl ) ;
188+ if ( urlExtension ) {
189+ return urlExtension ;
190+ }
191+
192+ return getExtensionFromContentType ( blob . type ) ;
193+ }
194+
182195export async function downloadEpisode (
183196 episode : Episode ,
184197 downloadPathTemplate : string ,
@@ -223,11 +236,10 @@ async function getFileExtension(url: string): Promise<string> {
223236 const response = await fetch ( url , { method : "HEAD" } ) ;
224237 const contentType = response . headers . get ( "content-type" ) ;
225238
226- if ( contentType ?. includes ( "audio/mpeg" ) ) return "mp3" ;
227- if ( contentType ?. includes ( "audio/mp4" ) ) return "m4a" ;
228- if ( contentType ?. includes ( "audio/ogg" ) ) return "ogg" ;
229- if ( contentType ?. includes ( "audio/wav" ) ) return "wav" ;
230- if ( contentType ?. includes ( "audio/x-m4a" ) ) return "m4a" ;
239+ const extensionFromContentType = getExtensionFromContentType ( contentType ) ;
240+ if ( extensionFromContentType ) {
241+ return extensionFromContentType ;
242+ }
231243
232244 // Default to mp3 if we can't determine the type
233245 return "mp3" ;
0 commit comments