wavesconv 1.6.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.
package/README.md CHANGED
@@ -1,12 +1,10 @@
1
1
  <div align="center">
2
2
 
3
- <img src="https://raw.githubusercontent.com/idunnowhytf/wavesconvsite/main/docs/og.png" alt="WavesConverter" width="100%"/>
3
+ <img src="https://res.cloudinary.com/dyozzp82h/image/upload/v1780341159/Gemini_Generated_Image_ve6asxve6asxve6a-Photoroom_clfoi2.png" alt="WavesConverter" width="100%"/>
4
4
 
5
5
  <br/>
6
6
 
7
- <h1>
8
- <img src="https://img.shields.io/badge/WavesConverter-v1.2.0-7c3aed?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMiAxMyBRNCA3IDYgMTMgUTggMTkgMTAgMTMgUTEyIDcgMTQgMTMgUTE2IDE5IDE4IDEzIFEyMCA3IDIyIDEzIiBzdHJva2U9IiNjMDg0ZmMiIHN0cm9rZS13aWR0aD0iMi41IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz48L3N2Zz4=" alt="WavesConverter v1.2.0"/>
9
- </h1>
7
+
10
8
 
11
9
  **Download anything. Convert everything.**
12
10
 
@@ -15,9 +13,9 @@ converts any media file — all offline, no account needed, completely free.
15
13
 
16
14
  <br/>
17
15
 
18
- [![Download](https://img.shields.io/badge/⬇_Download-macOS_&_Windows-7c3aed?style=for-the-badge)](https://idunnowhytf.github.io/wavesconvsite/#download)
19
- [![Website](https://img.shields.io/badge/🌐_Website-wavesconverter-a855f7?style=for-the-badge)](https://idunnowhytf.github.io/wavesconvsite/)
20
- [![Releases](https://img.shields.io/github/v/release/idunnowhytf/wavesconvsite?style=for-the-badge&color=d946ef&label=Latest)](https://github.com/idunnowhytf/wavesconvsite/releases)
16
+ [![Download](https://img.shields.io/badge/⬇_Download-macOS_&_Windows-7c3aed?style=for-the-badge)](https://idunnowhytf.github.io/WavesConverter/#download)
17
+ [![Website](https://img.shields.io/badge/🌐_Website-wavesconverter-a855f7?style=for-the-badge)](https://idunnowhytf.github.io/WavesConverter/)
18
+ [![Releases](https://img.shields.io/github/v/release/idunnowhytf/WavesConverter?style=for-the-badge&color=d946ef&label=Latest)](https://github.com/idunnowhytf/WavesConverter/releases)
21
19
  [![License](https://img.shields.io/badge/License-ISC-6d28d9?style=for-the-badge)](LICENSE)
22
20
 
23
21
  <br/>
@@ -48,9 +46,9 @@ converts any media file — all offline, no account needed, completely free.
48
46
 
49
47
  | Platform | Link |
50
48
  |---|---|
51
- | 🍎 **macOS Apple Silicon** (M1/M2/M3/M4) | [WavesConverter-arm64.dmg](https://github.com/idunnowhytf/wavesconvsite/releases/latest/download/WavesConverter-1.0.0-arm64.dmg) |
52
- | 🍎 **macOS Intel** (x64) | [WavesConverter.dmg](https://github.com/idunnowhytf/wavesconvsite/releases/latest/download/WavesConverter-1.0.0.dmg) |
53
- | 🪟 **Windows 10+** (x64) | [WavesConverter-Setup.exe](https://github.com/idunnowhytf/wavesconvsite/releases/latest/download/WavesConverter.Setup.1.0.0.exe) |
49
+ | 🍎 **macOS Apple Silicon** (M1/M2/M3/M4) | [WavesConverter-arm64.dmg](https://github.com/idunnowhytf/WavesConverter/releases/latest/download/WavesConverter-1.0.0-arm64.dmg) |
50
+ | 🍎 **macOS Intel** (x64) | [WavesConverter.dmg](https://github.com/idunnowhytf/WavesConverter/releases/latest/download/WavesConverter-1.0.0.dmg) |
51
+ | 🪟 **Windows 10+** (x64) | [WavesConverter-Setup.exe](https://github.com/idunnowhytf/WavesConverter/releases/latest/download/WavesConverter.Setup.1.0.0.exe) |
54
52
 
55
53
  > **Windows users:** SmartScreen may show a warning since the app isn't signed with a paid certificate.
56
54
  > Click **"More info" → "Run anyway"** to proceed. The source code is fully open and auditable here.
@@ -144,19 +142,12 @@ wavesconvsite/
144
142
 
145
143
  ## 📋 Changelog
146
144
 
147
- See [**Releases →**](https://github.com/idunnowhytf/wavesconvsite/releases) for full version history.
148
-
149
- | Version | Highlights |
150
- |---|---|
151
- | **v1.2.0** | Batch paste for multiple URLs, ETA & speed display on downloads |
152
- | **v1.1.0** | Download history tab, keyboard shortcuts, native notifications, drag & drop, Windows support |
153
- | **v1.0.0** | Initial release — macOS only |
145
+ See [**Releases →**](https://github.com/idunnowhytf/WavesConverter/releases) for full version history.
154
146
 
155
- ---
156
147
 
157
148
  ## 🤝 Contributing
158
149
 
159
- Found a bug or have a feature idea? [Open an issue](https://github.com/idunnowhytf/wavesconvsite/issues) — all feedback welcome.
150
+ Found a bug or have a feature idea? [Open an issue](https://github.com/idunnowhytf/WavesConverter/issues) — all feedback welcome.
160
151
 
161
152
  ---
162
153
 
@@ -170,7 +161,7 @@ This tool is intended for downloading content you own or have permission to down
170
161
 
171
162
  <div align="center">
172
163
 
173
- **[Website](https://idunnowhytf.github.io/wavesconvsite/) · [Releases](https://github.com/idunnowhytf/wavesconvsite/releases) · [Docs](https://idunnowhytf.github.io/wavesconvsite/docs.html) · [Changelog](https://idunnowhytf.github.io/wavesconvsite/changelog.html)**
164
+ **[Website](https://idunnowhytf.github.io/WavesConverter/) · [Releases](https://github.com/idunnowhytf/WavesConverter/releases) · [Docs](https://idunnowhytf.github.io/WavesConverter/docs.html) · [Changelog](https://idunnowhytf.github.io/WavesConverter/changelog.html)**
174
165
 
175
166
  <br/>
176
167
 
package/cli.js CHANGED
@@ -72,7 +72,7 @@ async function cmdInfo(url, flags, color) {
72
72
  spin.start();
73
73
  let items;
74
74
  try {
75
- items = await engine.fetchInfo(url);
75
+ items = await engine.fetchInfo(url, { cookiesPath: process.env.WAVESCONVERTER_COOKIES || '' });
76
76
  spin.succeed(`${items.length} element(ów)`);
77
77
  } catch (e) {
78
78
  spin.fail(e.message);
@@ -101,8 +101,8 @@ async function cmdInfo(url, flags, color) {
101
101
  }
102
102
 
103
103
  async function cmdDownload(url, flags, color) {
104
- if (!engine.isYouTubeUrl(url)) {
105
- throw new Error('Nieprawidłowy URL YouTube: ' + url);
104
+ if (!engine.isSupportedMediaUrl(url)) {
105
+ throw new Error('Nieobsługiwany URL. Użyj linku YouTube lub Instagram (post / Reel / Stories).');
106
106
  }
107
107
 
108
108
  const setupSpin = new ui.Spinner('Przygotowanie yt-dlp', color);
@@ -125,7 +125,7 @@ async function cmdDownload(url, flags, color) {
125
125
  const metaSpin = new ui.Spinner('Wczytywanie metadanych', color);
126
126
  metaSpin.start();
127
127
  try {
128
- const items = await engine.fetchInfo(url);
128
+ const items = await engine.fetchInfo(url, { cookiesPath: process.env.WAVESCONVERTER_COOKIES || '' });
129
129
  if (items[0]) title = items[0].title || items[0].id || title;
130
130
  metaSpin.succeed(title.slice(0, 52) + (title.length > 52 ? '…' : ''));
131
131
  } catch (_) {
@@ -136,6 +136,8 @@ async function cmdDownload(url, flags, color) {
136
136
  id: 'cli-' + Date.now(),
137
137
  title,
138
138
  url,
139
+ platform: engine.getMediaPlatform(url),
140
+ cookiesPath: process.env.WAVESCONVERTER_COOKIES || '',
139
141
  audioOnly,
140
142
  outputFormat: format,
141
143
  quality: flags.quality || 'best',
@@ -29,17 +29,7 @@ function sessionToFlags(session) {
29
29
  }
30
30
 
31
31
  function extractYouTubeUrls(text) {
32
- const found = new Set();
33
- const re = /https?:\/\/(?:www\.)?(?:youtube\.com\/[^\s]+|youtu\.be\/[^\s]+)/gi;
34
- let m;
35
- while ((m = re.exec(text)) !== null) {
36
- found.add(m[0].replace(/[)\]},.;]+$/, ''));
37
- }
38
- const parts = text.trim().split(/\s+/).filter(Boolean);
39
- for (const p of parts) {
40
- if (engine.isYouTubeUrl(p)) found.add(p.replace(/[)\]},.;]+$/, ''));
41
- }
42
- return [...found];
32
+ return engine.extractMediaUrls(text);
43
33
  }
44
34
 
45
35
  function printSession(color, session) {
@@ -202,8 +192,8 @@ async function runInteractive(handlers, version, color) {
202
192
  case 'info':
203
193
  case 'i': {
204
194
  const url = arg || '';
205
- if (!url || !engine.isYouTubeUrl(url)) {
206
- ui.warn(color, 'Użyj: /info <url>');
195
+ if (!url || !engine.isSupportedMediaUrl(url)) {
196
+ ui.warn(color, 'Użyj: /info <url> (YouTube lub Instagram)');
207
197
  return;
208
198
  }
209
199
  await handlers.info(url, {}, color);
@@ -252,7 +242,7 @@ async function runInteractive(handlers, version, color) {
252
242
 
253
243
  const urls = extractYouTubeUrls(trimmed);
254
244
  if (!urls.length) {
255
- ui.warn(color, 'Nie wykryto linku YouTube. Wklej URL lub wpisz /help');
245
+ ui.warn(color, 'Nie wykryto linku YouTube/Instagram. Wklej URL lub wpisz /help');
256
246
  rl.resume();
257
247
  loop();
258
248
  return;
package/lib/engine.js CHANGED
@@ -3,6 +3,7 @@ const fs = require('fs');
3
3
  const os = require('os');
4
4
  const https = require('https');
5
5
  const { spawn, exec } = require('child_process');
6
+ const urls = require('./urls');
6
7
 
7
8
  const APP_FOLDER = 'waves-converter';
8
9
 
@@ -78,13 +79,25 @@ async function ensureYtDlp(onStatus) {
78
79
  return binFile;
79
80
  }
80
81
 
81
- function fetchInfo(url) {
82
+ function appendCookiesArgs(args, options = {}) {
83
+ const cookiesPath = options.cookiesPath;
84
+ if (cookiesPath && fs.existsSync(cookiesPath)) {
85
+ args.push('--cookies', cookiesPath);
86
+ }
87
+ }
88
+
89
+ function fetchInfo(url, options = {}) {
82
90
  const activeYtDlp = findYtDlp();
83
91
  if (!activeYtDlp) {
84
92
  return Promise.reject(new Error('yt-dlp nie znaleziony. Uruchom: wavesconv tools install'));
85
93
  }
94
+ if (!urls.isSupportedMediaUrl(url)) {
95
+ return Promise.reject(new Error('Nieobsługiwany link. Wklej URL YouTube lub Instagram (post, Reel, Stories).'));
96
+ }
86
97
  return new Promise((resolve, reject) => {
87
- const args = ['--dump-json', '--flat-playlist', '--no-warnings', url];
98
+ const args = ['--dump-json', '--flat-playlist', '--no-warnings'];
99
+ appendCookiesArgs(args, options);
100
+ args.push(url);
88
101
  let out = '';
89
102
  let err = '';
90
103
  const proc = spawn(activeYtDlp, args);
@@ -104,14 +117,20 @@ function fetchInfo(url) {
104
117
 
105
118
  function buildDownloadArgs(job) {
106
119
  const ffmpeg = findFfmpeg();
107
- const { url, outputFormat, quality, bitrate, outputDir, filename, audioOnly } = job;
120
+ const { url, outputFormat, quality, bitrate, outputDir, filename, audioOnly, cookiesPath } = job;
121
+ const platform = job.platform || urls.getMediaPlatform(url);
108
122
  const safeName = (filename || '%(title)s').replace(/[<>:"/\\|?*]/g, '_');
109
123
  const outTpl = path.join(outputDir, safeName + '.%(ext)s');
110
124
  const args = ['--no-warnings', '--newline'];
125
+ appendCookiesArgs(args, { cookiesPath });
111
126
  if (ffmpeg) args.push('--ffmpeg-location', path.dirname(ffmpeg));
112
127
  if (audioOnly) {
113
128
  args.push('-x', '--audio-format', outputFormat || 'mp3');
114
129
  if (bitrate) args.push('--audio-quality', bitrate.replace('k', '') + 'K');
130
+ } else if (platform === 'instagram') {
131
+ args.push('-f', 'best');
132
+ args.push('--merge-output-format', outputFormat || 'mp4');
133
+ if (bitrate) args.push('--postprocessor-args', `ffmpeg:-b:v ${bitrate}`);
115
134
  } else {
116
135
  const h = quality && quality !== 'best' ? quality.replace('p', '') : null;
117
136
  args.push('-f', h ? `bestvideo[height<=${h}]+bestaudio/best[height<=${h}]/best` : 'bestvideo+bestaudio/best');
@@ -282,7 +301,19 @@ function runConvert(job, callbacks = {}) {
282
301
  }
283
302
 
284
303
  function isYouTubeUrl(str) {
285
- return /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)\/.+/i.test((str || '').trim());
304
+ return urls.isYouTubeUrl(str);
305
+ }
306
+
307
+ function isSupportedMediaUrl(str) {
308
+ return urls.isSupportedMediaUrl(str);
309
+ }
310
+
311
+ function getMediaPlatform(str) {
312
+ return urls.getMediaPlatform(str);
313
+ }
314
+
315
+ function extractMediaUrls(text) {
316
+ return urls.extractMediaUrls(text);
286
317
  }
287
318
 
288
319
  function parseDeepLink(raw) {
@@ -343,6 +374,10 @@ module.exports = {
343
374
  runDownload,
344
375
  runConvert,
345
376
  isYouTubeUrl,
377
+ isSupportedMediaUrl,
378
+ getMediaPlatform,
379
+ extractMediaUrls,
380
+ getInstagramContentKind: urls.getInstagramContentKind,
346
381
  parseDeepLink,
347
382
  findDeepLinkInArgv,
348
383
  };
package/lib/urls.js ADDED
@@ -0,0 +1,67 @@
1
+ 'use strict';
2
+
3
+ const YOUTUBE_RE = /^(https?:\/\/)?(www\.)?(youtube\.com\/(watch(\?.*)?|shorts\/|playlist\?|embed\/|live\/)|youtu\.be\/|music\.youtube\.com\/)/i;
4
+ const INSTAGRAM_RE = /^(https?:\/\/)?(www\.)?instagram\.com\/(p\/|reel\/|reels\/|tv\/|stories\/)/i;
5
+ const INSTAGRAM_ANY_RE = /^(https?:\/\/)?(www\.)?instagram\.com\//i;
6
+
7
+ function normalizeUrl(str) {
8
+ return (str || '').trim().replace(/[)\]},.;]+$/g, '');
9
+ }
10
+
11
+ function getMediaPlatform(url) {
12
+ const u = normalizeUrl(url);
13
+ if (!u) return null;
14
+ if (YOUTUBE_RE.test(u) || /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)\/.+/i.test(u)) {
15
+ return 'youtube';
16
+ }
17
+ if (INSTAGRAM_ANY_RE.test(u) || /^(https?:\/\/)?(www\.)?instagr\.am\//i.test(u)) {
18
+ return 'instagram';
19
+ }
20
+ return null;
21
+ }
22
+
23
+ function isSupportedMediaUrl(url) {
24
+ return !!getMediaPlatform(url);
25
+ }
26
+
27
+ function isYouTubeUrl(url) {
28
+ return getMediaPlatform(url) === 'youtube';
29
+ }
30
+
31
+ function isInstagramUrl(url) {
32
+ return getMediaPlatform(url) === 'instagram';
33
+ }
34
+
35
+ function getInstagramContentKind(url) {
36
+ const u = normalizeUrl(url).toLowerCase();
37
+ if (u.includes('/stories/')) return 'story';
38
+ if (u.includes('/reel/') || u.includes('/reels/')) return 'reel';
39
+ if (u.includes('/p/') || u.includes('/tv/')) return 'post';
40
+ return 'post';
41
+ }
42
+
43
+ function extractMediaUrls(text) {
44
+ const found = new Set();
45
+ const raw = text || '';
46
+ const re = /https?:\/\/[^\s<>"']+/gi;
47
+ let m;
48
+ while ((m = re.exec(raw)) !== null) {
49
+ const cleaned = normalizeUrl(m[0]);
50
+ if (isSupportedMediaUrl(cleaned)) found.add(cleaned);
51
+ }
52
+ raw.split(/\s+/).filter(Boolean).forEach(part => {
53
+ const cleaned = normalizeUrl(part);
54
+ if (isSupportedMediaUrl(cleaned)) found.add(cleaned);
55
+ });
56
+ return [...found];
57
+ }
58
+
59
+ module.exports = {
60
+ normalizeUrl,
61
+ getMediaPlatform,
62
+ isSupportedMediaUrl,
63
+ isYouTubeUrl,
64
+ isInstagramUrl,
65
+ getInstagramContentKind,
66
+ extractMediaUrls,
67
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wavesconv",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "description": "CLI: pobieranie YouTube (yt-dlp) i konwersja mediów (ffmpeg) — WavesConverter",
5
5
  "main": "cli.js",
6
6
  "bin": {