podcast-dl 9.0.0 → 9.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -85,7 +85,7 @@ Options that support templates allow users to specify a template for the generat
85
85
 
86
86
  - `episode_path`: The path to the downloaded episode.
87
87
  - `episode_path_base`: The path to the folder of the downloaded episode.
88
- - `episode_filname`: The filename of the episode.
88
+ - `episode_filename`: The filename of the episode.
89
89
  - `episode_filename_base`: The filename of the episode without its extension.
90
90
 
91
91
  ## Log Levels
package/bin/async.js CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  getLogMessageWithMarker,
13
13
  getShouldOutputProgressIndicator,
14
14
  } from "./logger.js";
15
- import { getArchiveFilename, getFilename } from "./naming.js";
15
+ import { getArchiveFilename, getItemFilename } from "./naming.js";
16
16
  import {
17
17
  getEpisodeAudioUrlAndExt,
18
18
  getArchiveKey,
@@ -68,12 +68,9 @@ const download = async (options) => {
68
68
  }
69
69
  };
70
70
 
71
- const expectedSize =
72
- headResponse &&
73
- headResponse.headers &&
74
- headResponse.headers["content-length"]
75
- ? parseInt(headResponse.headers["content-length"])
76
- : 0;
71
+ const expectedSize = headResponse?.headers?.["content-length"]
72
+ ? parseInt(headResponse.headers["content-length"])
73
+ : 0;
77
74
 
78
75
  logMessage(
79
76
  `Starting download${
@@ -156,6 +153,7 @@ let downloadItemsAsync = async ({
156
153
  bitrate,
157
154
  episodeTemplate,
158
155
  episodeDigits,
156
+ episodeSourceOrder,
159
157
  exec,
160
158
  feed,
161
159
  includeEpisodeMeta,
@@ -173,7 +171,7 @@ let downloadItemsAsync = async ({
173
171
  const marker = threads > 1 ? `[${threadIndex}] ${item.title}` : item.title;
174
172
  const logMessage = getLogMessageWithMarker(marker);
175
173
  const { url: episodeAudioUrl, ext: audioFileExt } =
176
- getEpisodeAudioUrlAndExt(item);
174
+ getEpisodeAudioUrlAndExt(item, episodeSourceOrder);
177
175
 
178
176
  if (!episodeAudioUrl) {
179
177
  hasErrors = true;
@@ -181,7 +179,7 @@ let downloadItemsAsync = async ({
181
179
  return;
182
180
  }
183
181
 
184
- const episodeFilename = getFilename({
182
+ const episodeFilename = getItemFilename({
185
183
  item,
186
184
  feed,
187
185
  url: episodeAudioUrl,
@@ -259,7 +257,7 @@ let downloadItemsAsync = async ({
259
257
 
260
258
  if (includeEpisodeMeta) {
261
259
  const episodeMetaExt = ".meta.json";
262
- const episodeMetaName = getFilename({
260
+ const episodeMetaName = getItemFilename({
263
261
  item,
264
262
  feed,
265
263
  url: episodeAudioUrl,
package/bin/bin.js CHANGED
@@ -25,7 +25,7 @@ import {
25
25
  logError,
26
26
  logErrorAndExit,
27
27
  } from "./logger.js";
28
- import { getFolderName, getSafeName } from "./naming.js";
28
+ import { getFolderName, getSimpleFilename } from "./naming.js";
29
29
  import { downloadItemsAsync } from "./async.js";
30
30
 
31
31
  setupCommander(commander, process.argv);
@@ -82,7 +82,7 @@ const main = async () => {
82
82
  }
83
83
 
84
84
  if (list) {
85
- if (feed.items && feed.items.length) {
85
+ if (feed?.items?.length) {
86
86
  const listFormat = typeof list === "boolean" ? "table" : list;
87
87
  logItemsList({
88
88
  type: listFormat,
@@ -123,12 +123,12 @@ const main = async () => {
123
123
 
124
124
  if (podcastImageUrl) {
125
125
  const podcastImageFileExt = getUrlExt(podcastImageUrl);
126
- const podcastImageName = `${
127
- feed.title ? `${feed.title}.image` : "image"
128
- }${podcastImageFileExt}`;
129
126
  const outputImagePath = _path.resolve(
130
127
  basePath,
131
- getSafeName(podcastImageName)
128
+ getSimpleFilename(
129
+ feed.title ? feed.title : "image",
130
+ feed.title ? `.image${podcastImageFileExt}` : podcastImageFileExt
131
+ )
132
132
  );
133
133
 
134
134
  try {
@@ -137,7 +137,12 @@ const main = async () => {
137
137
  archive,
138
138
  override,
139
139
  marker: podcastImageUrl,
140
- key: getArchiveKey({ prefix: archiveUrl, name: podcastImageName }),
140
+ key: getArchiveKey({
141
+ prefix: archiveUrl,
142
+ name: `${
143
+ feed.title ? `${feed.title}.image` : "image"
144
+ }${podcastImageFileExt}`,
145
+ }),
141
146
  outputPath: outputImagePath,
142
147
  url: podcastImageUrl,
143
148
  maxAttempts: attempts,
@@ -147,8 +152,13 @@ const main = async () => {
147
152
  }
148
153
  }
149
154
 
150
- const outputMetaName = `${feed.title ? `${feed.title}.meta` : "meta"}.json`;
151
- const outputMetaPath = _path.resolve(basePath, getSafeName(outputMetaName));
155
+ const outputMetaPath = _path.resolve(
156
+ basePath,
157
+ getSimpleFilename(
158
+ feed.title ? feed.title : "meta",
159
+ feed.title ? ".meta.json" : ".json"
160
+ )
161
+ );
152
162
 
153
163
  try {
154
164
  logMessage("\nSaving podcast metadata...");
@@ -156,7 +166,10 @@ const main = async () => {
156
166
  archive,
157
167
  override,
158
168
  feed,
159
- key: getArchiveKey({ prefix: archiveUrl, name: outputMetaName }),
169
+ key: getArchiveKey({
170
+ prefix: archiveUrl,
171
+ name: `${feed.title ? `${feed.title}.meta` : "meta"}.json`,
172
+ }),
160
173
  outputPath: outputMetaPath,
161
174
  });
162
175
  } catch (error) {
@@ -206,6 +219,7 @@ const main = async () => {
206
219
  bitrate,
207
220
  episodeTemplate,
208
221
  episodeDigits,
222
+ episodeSourceOrder,
209
223
  exec,
210
224
  feed,
211
225
  includeEpisodeMeta,
package/bin/commander.js CHANGED
@@ -4,7 +4,7 @@ import { logErrorAndExit } from "./logger.js";
4
4
 
5
5
  export const setupCommander = (commander, argv) => {
6
6
  commander
7
- .version("9.0.0")
7
+ .version("9.0.2")
8
8
  .option("--url <string>", "url to podcast rss feed")
9
9
  .option(
10
10
  "--out-dir <path>",
@@ -41,7 +41,7 @@ export const setupCommander = (commander, argv) => {
41
41
 
42
42
  return parsed;
43
43
  },
44
- "enclosure,link"
44
+ [AUDIO_ORDER_TYPES.enclosure, AUDIO_ORDER_TYPES.link]
45
45
  )
46
46
  .option("--include-meta", "write out podcast metadata to json")
47
47
  .option(
package/bin/naming.js CHANGED
@@ -2,16 +2,22 @@ import filenamify from "filenamify";
2
2
  import dayjs from "dayjs";
3
3
 
4
4
  const INVALID_CHAR_REPLACE = "_";
5
- const MAX_LENGTH_FILENAME = 255;
5
+ const MAX_LENGTH_FILENAME = process.env.MAX_LENGTH_FILENAME
6
+ ? parseInt(process.env.MAX_LENGTH_FILENAME)
7
+ : 255;
6
8
 
7
- const getSafeName = (name) => {
9
+ const getSafeName = (name, maxLength = MAX_LENGTH_FILENAME) => {
8
10
  return filenamify(name, {
9
11
  replacement: INVALID_CHAR_REPLACE,
10
- maxLength: MAX_LENGTH_FILENAME,
12
+ maxLength,
11
13
  });
12
14
  };
13
15
 
14
- const getFilename = ({ item, ext, url, feed, template, width }) => {
16
+ const getSimpleFilename = (name, ext = "") => {
17
+ return `${getSafeName(name, MAX_LENGTH_FILENAME - (ext?.length ?? 0))}${ext}`;
18
+ };
19
+
20
+ const getItemFilename = ({ item, ext, url, feed, template, width }) => {
15
21
  const episodeNum = feed.items.length - item._originalIndex;
16
22
  const formattedPubDate = item.pubDate
17
23
  ? dayjs(new Date(item.pubDate)).format("YYYYMMDD")
@@ -24,7 +30,7 @@ const getFilename = ({ item, ext, url, feed, template, width }) => {
24
30
  ["url", url],
25
31
  ["podcast_title", feed.title || ""],
26
32
  ["podcast_link", feed.link || ""],
27
- ["duration", (item.itunes && item.itunes.duration) || ""],
33
+ ["duration", item.itunes?.duration || ""],
28
34
  ];
29
35
 
30
36
  let name = template;
@@ -37,8 +43,7 @@ const getFilename = ({ item, ext, url, feed, template, width }) => {
37
43
  : name.replace(replaceRegex, "");
38
44
  });
39
45
 
40
- name = `${name}${ext}`;
41
- return getSafeName(name);
46
+ return getSimpleFilename(name, ext);
42
47
  };
43
48
 
44
49
  const getFolderName = ({ feed, template }) => {
@@ -70,4 +75,10 @@ const getArchiveFilename = ({ pubDate, name, ext }) => {
70
75
  return `${baseName}${ext}`;
71
76
  };
72
77
 
73
- export { getArchiveFilename, getFilename, getFolderName, getSafeName };
78
+ export {
79
+ getArchiveFilename,
80
+ getFolderName,
81
+ getItemFilename,
82
+ getSafeName,
83
+ getSimpleFilename,
84
+ };
package/bin/util.js CHANGED
@@ -6,7 +6,7 @@ import util from "util";
6
6
  import { exec } from "child_process";
7
7
 
8
8
  import { logErrorAndExit, logMessage } from "./logger.js";
9
- import { getArchiveFilename, getFilename } from "./naming.js";
9
+ import { getArchiveFilename, getItemFilename } from "./naming.js";
10
10
 
11
11
  const execWithPromise = util.promisify(exec);
12
12
 
@@ -185,7 +185,7 @@ const getItemsToDownload = ({
185
185
  }),
186
186
  });
187
187
 
188
- const episodeImageName = getFilename({
188
+ const episodeImageName = getItemFilename({
189
189
  item,
190
190
  feed,
191
191
  url: episodeAudioUrl,
@@ -377,7 +377,7 @@ const AUDIO_ORDER_TYPES = {
377
377
 
378
378
  const getEpisodeAudioUrlAndExt = (
379
379
  { enclosure, link },
380
- order = [AUDIO_ORDER_TYPES.link, AUDIO_ORDER_TYPES.enclosure]
380
+ order = [AUDIO_ORDER_TYPES.enclosure, AUDIO_ORDER_TYPES.link]
381
381
  ) => {
382
382
  for (const source of order) {
383
383
  if (source === AUDIO_ORDER_TYPES.link && link && getIsAudioUrl(link)) {
@@ -399,15 +399,15 @@ const getEpisodeAudioUrlAndExt = (
399
399
  };
400
400
 
401
401
  const getImageUrl = ({ image, itunes }) => {
402
- if (image && image.url) {
402
+ if (image?.url) {
403
403
  return image.url;
404
404
  }
405
405
 
406
- if (image && image.link) {
406
+ if (image?.link) {
407
407
  return image.link;
408
408
  }
409
409
 
410
- if (itunes && itunes.image) {
410
+ if (itunes?.image) {
411
411
  return itunes.image;
412
412
  }
413
413
 
@@ -469,14 +469,12 @@ const runFfmpeg = async ({
469
469
  if (addMp3Metadata) {
470
470
  const album = feed.title || "";
471
471
  const title = item.title || "";
472
- const artist =
473
- item.itunes && item.itunes.author
474
- ? item.itunes.author
475
- : item.author || "";
476
- const track =
477
- item.itunes && item.itunes.episode
478
- ? item.itunes.episode
479
- : `${feed.items.length - itemIndex}`;
472
+ const artist = item?.itunes?.author
473
+ ? item.itunes.author
474
+ : item.author || "";
475
+ const track = item?.itunes?.episode
476
+ ? item.itunes.episode
477
+ : `${feed.items.length - itemIndex}`;
480
478
  const date = item.pubDate
481
479
  ? dayjs(new Date(item.pubDate)).format("YYYY-MM-DD")
482
480
  : "";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "podcast-dl",
3
- "version": "9.0.0",
3
+ "version": "9.0.2",
4
4
  "description": "A CLI for downloading podcasts.",
5
5
  "type": "module",
6
6
  "bin": "./bin/bin.js",
@@ -51,7 +51,7 @@
51
51
  "command-exists": "^1.2.9",
52
52
  "commander": "^5.1.0",
53
53
  "dayjs": "^1.8.25",
54
- "filenamify": "^4.1.0",
54
+ "filenamify": "^6.0.0",
55
55
  "global-agent": "^3.0.0",
56
56
  "got": "^11.0.2",
57
57
  "p-limit": "^4.0.0",