@lzwme/m3u8-dl 1.6.0-0 → 1.7.0

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.
@@ -7,22 +7,45 @@ const fe_utils_1 = require("@lzwme/fe-utils");
7
7
  const video_parser_1 = require("../video-parser");
8
8
  const utils_1 = require("./utils");
9
9
  const fileSupportExtList = [
10
+ // video
10
11
  '.mp4',
11
12
  '.mkv',
12
13
  '.avi',
13
14
  '.mov',
14
15
  '.wmv',
15
16
  '.ts',
16
- '.exe',
17
- '.zip',
18
- '.rar',
19
- '.pdf',
17
+ // audio
18
+ '.mp3',
19
+ '.wav',
20
+ '.ogg',
21
+ '.m4a',
22
+ '.aac',
23
+ '.flac',
24
+ '.ape',
25
+ // document
20
26
  '.doc',
21
27
  '.docx',
22
28
  '.xls',
23
29
  '.xlsx',
24
30
  '.ppt',
25
31
  '.pptx',
32
+ '.pdf',
33
+ '.mobi',
34
+ '.epub',
35
+ // others
36
+ '.exe',
37
+ '.msi',
38
+ '.zip',
39
+ '.rar',
40
+ '.7z',
41
+ '.tar.gz',
42
+ '.tar.bz2',
43
+ '.tar.xz',
44
+ '.iso',
45
+ '.dmg',
46
+ '.pkg',
47
+ '.deb',
48
+ '.rpm',
26
49
  ];
27
50
  function formatOptions(url, opts) {
28
51
  const options = {
package/cjs/lib/i18n.d.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Shared i18n utility for backend (CLI, SDK, Server)
3
3
  */
4
4
  import type { AnyObject } from '@lzwme/fe-utils';
5
- type Locale = 'zh' | 'en';
5
+ type Locale = 'zh-CN' | 'en';
6
6
  export declare const LANG_CODES: Set<string>;
7
7
  /**
8
8
  * Detect language from OS or environment
package/cjs/lib/i18n.js CHANGED
@@ -9,7 +9,7 @@ exports.setLanguage = setLanguage;
9
9
  exports.getLanguage = getLanguage;
10
10
  exports.getLang = getLang;
11
11
  exports.t = t;
12
- exports.LANG_CODES = new Set(['zh', 'en']);
12
+ exports.LANG_CODES = new Set(['zh-CN', 'en']);
13
13
  let globalLang = null;
14
14
  /**
15
15
  * Detect language from OS or environment
@@ -18,17 +18,27 @@ function detectLanguage() {
18
18
  // Check environment variable first
19
19
  const envLang = process.env.M3U8DL_LANG || process.env.LANG;
20
20
  if (envLang) {
21
- const langCode = envLang.toLowerCase().split('-')[0].split('_')[0];
22
- if (exports.LANG_CODES.has(langCode)) {
23
- return langCode;
21
+ const langCode = envLang.toLowerCase();
22
+ // 支持 zh-CN, zh-TW, zh 等变体映射到 zh-CN
23
+ if (langCode.startsWith('zh')) {
24
+ return 'zh-CN';
25
+ }
26
+ const baseLangCode = langCode.split('-')[0].split('_')[0];
27
+ if (exports.LANG_CODES.has(baseLangCode)) {
28
+ return baseLangCode;
24
29
  }
25
30
  }
26
31
  // Try to detect from OS locale
27
32
  try {
28
33
  const osLocale = Intl.DateTimeFormat().resolvedOptions().locale;
29
- const langCode = osLocale.toLowerCase().split('-')[0];
30
- if (exports.LANG_CODES.has(langCode)) {
31
- return langCode;
34
+ const langCode = osLocale.toLowerCase();
35
+ // 支持 zh-CN, zh-TW 等变体映射到 zh-CN
36
+ if (langCode.startsWith('zh')) {
37
+ return 'zh-CN';
38
+ }
39
+ const baseLangCode = langCode.split('-')[0];
40
+ if (exports.LANG_CODES.has(baseLangCode)) {
41
+ return baseLangCode;
32
42
  }
33
43
  }
34
44
  catch {
@@ -53,8 +63,15 @@ function getLanguage() {
53
63
  * Get language from various sources
54
64
  */
55
65
  function getLang(lang) {
56
- if (lang && exports.LANG_CODES.has(lang)) {
57
- return lang;
66
+ if (lang) {
67
+ const normalizedLang = lang.toLowerCase();
68
+ // 支持向后兼容:将 zh 映射到 zh-CN
69
+ if (normalizedLang === 'zh' || normalizedLang.startsWith('zh')) {
70
+ return 'zh-CN';
71
+ }
72
+ if (exports.LANG_CODES.has(normalizedLang)) {
73
+ return normalizedLang;
74
+ }
58
75
  }
59
76
  if (globalLang) {
60
77
  return globalLang;
@@ -66,7 +83,9 @@ function getLang(lang) {
66
83
  */
67
84
  function t(key, lang, params) {
68
85
  const targetLang = getLang(lang);
69
- const translations = require(`../i18n/locales/${targetLang}.js`);
86
+ // zh-CN 映射到文件名 zh-CN.ts
87
+ const langFile = targetLang === 'zh-CN' ? 'zh-CN' : targetLang;
88
+ const translations = require(`../i18n/locales/${langFile}.js`);
70
89
  // Navigate through nested keys (e.g., 'cli.command.download.description')
71
90
  const keys = key.split('.');
72
91
  let value = translations.default || translations;
@@ -19,7 +19,7 @@ async function localPlay(m3u8Info) {
19
19
  const cacheFilepath = toLocalM3u8(m3u8Info);
20
20
  const filename = (0, node_path_1.basename)(cacheFilepath);
21
21
  const info = await createLocalServer((0, node_path_1.dirname)(cacheDir));
22
- const playUrl = `https://lzw.me/x/m3u8-player?url=${encodeURIComponent(`${info.origin}/${cacheDirname}/${filename}`)}`;
22
+ const playUrl = `https://m3u8-player.lzw.me?from=sdk&url=${encodeURIComponent(`${info.origin}/${cacheDirname}/${filename}`)}`;
23
23
  const cmd = `${process.platform === 'win32' ? 'start' : 'open'} ${playUrl}`;
24
24
  (0, fe_utils_1.execSync)(cmd);
25
25
  return info;
@@ -9,8 +9,8 @@ const node_path_1 = require("node:path");
9
9
  const fe_utils_1 = require("@lzwme/fe-utils");
10
10
  const helper_1 = require("@lzwme/fe-utils/cjs/common/helper");
11
11
  const console_log_colors_1 = require("console-log-colors");
12
- const i18n_js_1 = require("./i18n.js");
13
12
  const format_options_js_1 = require("./format-options.js");
13
+ const i18n_js_1 = require("./i18n.js");
14
14
  const local_play_js_1 = require("./local-play.js");
15
15
  const m3u8_convert_js_1 = require("./m3u8-convert.js");
16
16
  const parseM3u8_js_1 = require("./parseM3u8.js");
@@ -18,3 +18,5 @@ export declare function getLocation(url: string, method?: string): Promise<strin
18
18
  * 如果 headers 是字符串,会先将其解析为对象;如果 headers 为空,则返回空对象。
19
19
  */
20
20
  export declare function formatHeaders(headers: string | OutgoingHttpHeaders): Record<string, string>;
21
+ /** 异步检查文件是否存在 */
22
+ export declare function checkFileExists(filepath: string): Promise<boolean>;
package/cjs/lib/utils.js CHANGED
@@ -5,7 +5,9 @@ exports.isSupportFfmpeg = isSupportFfmpeg;
5
5
  exports.findFiles = findFiles;
6
6
  exports.getLocation = getLocation;
7
7
  exports.formatHeaders = formatHeaders;
8
+ exports.checkFileExists = checkFileExists;
8
9
  const node_fs_1 = require("node:fs");
10
+ const promises_1 = require("node:fs/promises");
9
11
  const node_path_1 = require("node:path");
10
12
  const fe_utils_1 = require("@lzwme/fe-utils");
11
13
  exports.request = new fe_utils_1.Request({
@@ -65,3 +67,15 @@ function formatHeaders(headers) {
65
67
  headers = Object.fromEntries(headers.split('\n').map(line => line.split(':').map(d => d.trim())));
66
68
  return (0, fe_utils_1.toLowcaseKeyObject)(headers);
67
69
  }
70
+ /** 异步检查文件是否存在 */
71
+ async function checkFileExists(filepath) {
72
+ try {
73
+ if (!filepath)
74
+ return false;
75
+ await (0, promises_1.access)(filepath, promises_1.constants.F_OK);
76
+ return true;
77
+ }
78
+ catch {
79
+ return false;
80
+ }
81
+ }
@@ -1,5 +1,5 @@
1
1
  import type { Express } from 'express';
2
- import type { Server } from 'ws';
2
+ import type { WebSocketServer } from 'ws';
3
3
  import type { M3u8DLOptions, M3u8DLProgressStats, M3u8WorkerPool, TsItemInfo } from '../types/m3u8.js';
4
4
  interface DLServerOptions {
5
5
  port?: number;
@@ -18,12 +18,18 @@ interface CacheItem extends Partial<M3u8DLProgressStats> {
18
18
  /** 格式化后实际下载使用的参数 */
19
19
  dlOptions?: M3u8DLOptions;
20
20
  status: 'pause' | 'resume' | 'done' | 'pending' | 'error';
21
+ /**
22
+ * 当前任务的 ts 信息
23
+ * @deprecated 下一版本将移除
24
+ */
21
25
  current?: TsItemInfo;
26
+ /** 当前任务的 ts 缓存目录 */
27
+ cacheDir?: string;
22
28
  workPoll?: M3u8WorkerPool;
23
29
  }
24
30
  export declare class DLServer {
25
31
  app: Express;
26
- wss: Server;
32
+ wss: WebSocketServer | null;
27
33
  /** DS 参数 */
28
34
  options: DLServerOptions;
29
35
  private serverInfo;
@@ -38,11 +44,12 @@ export declare class DLServer {
38
44
  private checkDLFileLaest;
39
45
  private checkDLFileTimer;
40
46
  private checkDLFileIsExists;
47
+ private checkItemStatus;
41
48
  dlCacheClone(): [string, CacheItem][];
42
49
  private cacheSaveTimer;
43
50
  saveCache(): void;
44
- private readConfig;
45
- saveConfig(config: M3u8DLOptions, configPath?: string): void;
51
+ private loadConfig;
52
+ saveConfig(config: M3u8DLOptions, configPath?: string): Promise<void>;
46
53
  private createApp;
47
54
  private startDownload;
48
55
  startNextPending(): void;