gerdur 1.0.1 → 1.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/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gerdur",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "The crucial streaming module for dabox systems.",
5
5
  "author": "Christian",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -48,7 +48,7 @@
48
48
  "adm-zip": "^0.5.16",
49
49
  "chalk": "^4.1.2",
50
50
  "commander": "^9.5.0",
51
- "gerdur-core": "^1.0.3",
51
+ "gerdur-core": "^1.0.4",
52
52
  "dot-prop": "^6.0.1",
53
53
  "got": "^11.8.6",
54
54
  "gradient-string": "^2.0.2",
@@ -219,6 +219,32 @@ const startDownload = async (saveLayout, url, skipPrompt) => {
219
219
  const resolveFullPath = options.resolveFullPath ?? conf.get('playlist.resolveFullPath');
220
220
  const savedFiles = [];
221
221
  let m3u8 = [];
222
+ // One batched get_url for the whole selection instead of a request per track.
223
+ // Deezer returns the best licensed format, so pass an ordered preference list.
224
+ const QUALITY_PREF = {
225
+ '1': [1],
226
+ '128': [1],
227
+ '3': [3, 1],
228
+ '320': [3, 1],
229
+ '9': [9, 3, 1],
230
+ flac: [9, 3, 1],
231
+ };
232
+ const prefetchedUrls = new Map();
233
+ if (data.tracks.length > 1 && !process.env.SIMULATE) {
234
+ try {
235
+ const base = QUALITY_PREF[String(options.quality).toLowerCase()] ?? [3, 1];
236
+ const pref = fallbackQuality ? base : [base[0]];
237
+ const resolved = await (0, gerdur_core_1.resolveDownloadUrls)(data.tracks, pref);
238
+ resolved.forEach((r, i) => {
239
+ if (r) {
240
+ prefetchedUrls.set(data.tracks[i].SNG_ID, r);
241
+ }
242
+ });
243
+ }
244
+ catch {
245
+ // batch resolve failed wholesale — every track falls back to per-track resolution
246
+ }
247
+ }
222
248
  await queue.addAll(data.tracks.map((track, index) => {
223
249
  return async () => {
224
250
  const savedPath = await (0, download_track_1.default)({
@@ -233,6 +259,7 @@ const startDownload = async (saveLayout, url, skipPrompt) => {
233
259
  fallbackQuality,
234
260
  overwrite,
235
261
  message: `(${index}/${data.tracks.length})`,
262
+ prefetched: prefetchedUrls.get(track.SNG_ID) ?? null,
236
263
  });
237
264
  // Add to saved list
238
265
  if (savedPath) {
@@ -19,6 +19,18 @@ interface downloadTrackProps {
19
19
  isQualityFallback?: boolean;
20
20
  overwrite?: boolean;
21
21
  message?: string;
22
+ /**
23
+ * A download URL already resolved for this track by a batch `resolveDownloadUrls`
24
+ * pass. When set, the per-track `get_url` request and quality-fallback round-trips
25
+ * are skipped and `quality` is taken from the format Deezer actually granted.
26
+ * Falls through to the normal path when absent or `null` (track not in the batch).
27
+ */
28
+ prefetched?: {
29
+ trackUrl: string;
30
+ isEncrypted: boolean;
31
+ fileSize: number;
32
+ format: string;
33
+ } | null;
22
34
  }
23
- declare const downloadTrack: ({ track, quality, info, coverSizes, path, totalTracks, trackNumber, fallbackTrack, fallbackQuality, isFallback, isQualityFallback, overwrite, message, }: downloadTrackProps) => Promise<string | undefined>;
35
+ declare const downloadTrack: ({ track, quality, info, coverSizes, path, totalTracks, trackNumber, fallbackTrack, fallbackQuality, isFallback, isQualityFallback, overwrite, message, prefetched, }: downloadTrackProps) => Promise<string | undefined>;
24
36
  export default downloadTrack;
@@ -16,10 +16,17 @@ const util_2 = require("./util");
16
16
  const decrypt_1 = require("./decrypt");
17
17
  const pipeline = (0, util_1.promisify)(stream_1.default.pipeline);
18
18
  const simulate = process.env.SIMULATE;
19
- const downloadTrack = async ({ track, quality, info, coverSizes, path, totalTracks, trackNumber = true, fallbackTrack = true, fallbackQuality = true, isFallback = false, isQualityFallback = false, overwrite = false, message = '', }) => {
19
+ /** media-API format string -> gerdur's numeric quality */
20
+ const FORMAT_TO_QUALITY = { FLAC: 9, MP3_320: 3, MP3_256: 3, MP3_128: 1, MP3_64: 1 };
21
+ const downloadTrack = async ({ track, quality, info, coverSizes, path, totalTracks, trackNumber = true, fallbackTrack = true, fallbackQuality = true, isFallback = false, isQualityFallback = false, overwrite = false, message = '', prefetched = null, }) => {
20
22
  (0, log_update_1.default)(signale_1.default.pending(track.SNG_TITLE + ' by ' + track.ART_NAME + ' from ' + track.ALB_TITLE));
21
23
  try {
22
24
  let ext = '.mp3', fileSize = 0, downloaded = 0, coverSize = 500;
25
+ // A batch resolve already picked the best licensed format for this track —
26
+ // align `quality` with it so the extension, cover size and file size match.
27
+ if (prefetched && FORMAT_TO_QUALITY[prefetched.format]) {
28
+ quality = FORMAT_TO_QUALITY[prefetched.format];
29
+ }
23
30
  switch (quality) {
24
31
  case 1:
25
32
  case '1':
@@ -54,12 +61,17 @@ const downloadTrack = async ({ track, quality, info, coverSizes, path, totalTrac
54
61
  return savePath;
55
62
  }
56
63
  let trackData;
57
- try {
58
- trackData = await (0, gerdur_core_1.getTrackDownloadUrl)(track, quality);
64
+ if (prefetched) {
65
+ trackData = prefetched;
59
66
  }
60
- catch (err) {
61
- if (!(err instanceof gerdur_core_1.GeoBlocked) || !track.FALLBACK) {
62
- throw err;
67
+ else {
68
+ try {
69
+ trackData = await (0, gerdur_core_1.getTrackDownloadUrl)(track, quality);
70
+ }
71
+ catch (err) {
72
+ if (!(err instanceof gerdur_core_1.GeoBlocked) || !track.FALLBACK) {
73
+ throw err;
74
+ }
63
75
  }
64
76
  }
65
77
  if (!trackData) {
@@ -114,7 +126,13 @@ const downloadTrack = async ({ track, quality, info, coverSizes, path, totalTrac
114
126
  const bar = (0, util_2.progressBar)(fileSize, 40);
115
127
  const humanSizeTotal = (fileSize / 1024 / 1024).toFixed(2);
116
128
  let transferredLast = downloaded;
117
- await pipeline(got_1.default.stream(trackData.trackUrl, { responseType: 'buffer', headers }).on('downloadProgress', ({ transferred }) => {
129
+ await pipeline(got_1.default
130
+ .stream(trackData.trackUrl, {
131
+ responseType: 'buffer',
132
+ headers,
133
+ agent: { http: gerdur_core_1.httpAgent, https: gerdur_core_1.httpsAgent },
134
+ })
135
+ .on('downloadProgress', ({ transferred }) => {
118
136
  // Report download progress
119
137
  transferred += downloaded;
120
138
  if (transferred - transferredLast > 50000) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gerdur",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "The crucial streaming module for dabox systems.",
5
5
  "author": "Christian",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -48,7 +48,7 @@
48
48
  "adm-zip": "^0.5.16",
49
49
  "chalk": "^4.1.2",
50
50
  "commander": "^9.5.0",
51
- "gerdur-core": "^1.0.3",
51
+ "gerdur-core": "^1.0.4",
52
52
  "dot-prop": "^6.0.1",
53
53
  "got": "^11.8.6",
54
54
  "gradient-string": "^2.0.2",