@heavstaltech/api 1.0.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/dist/index.mjs ADDED
@@ -0,0 +1,586 @@
1
+ import axios3 from 'axios';
2
+ import * as cheerio3 from 'cheerio';
3
+ import ytdl from '@distube/ytdl-core';
4
+ import yts from 'yt-search';
5
+ import FormData from 'form-data';
6
+ import https from 'https';
7
+
8
+ // src/dl/tiktok.ts
9
+
10
+ // src/types.ts
11
+ var AUTHOR = {
12
+ name: "HEAVSTAL TECH",
13
+ source: "https://heavstal-tech.vercel.app"
14
+ };
15
+
16
+ // src/dl/tiktok.ts
17
+ var USER_AGENTS = [
18
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",
19
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36",
20
+ "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36",
21
+ "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1"
22
+ ];
23
+ var getRandomHeaders = () => ({
24
+ "User-Agent": USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length)],
25
+ "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
26
+ "Accept": "application/json, text/javascript, */*; q=0.01"
27
+ });
28
+ var cleanText = (str) => str ? str.replace(/(<br?\s?\/?>)/gi, " \n").replace(/(<([^>]+)>)/gi, "").trim() : "";
29
+ var cleanUrl = (url) => url ? url.replace("https:", "http:") : "";
30
+ var lovetikFallback = async (url) => {
31
+ try {
32
+ const { data } = await axios3.post(
33
+ "https://lovetik.com/api/ajax/search",
34
+ new URLSearchParams({ query: url }),
35
+ { headers: getRandomHeaders() }
36
+ );
37
+ if (!data.links) throw new Error("Lovetik: No links found");
38
+ return {
39
+ author: AUTHOR,
40
+ status: true,
41
+ title: cleanText(data.desc),
42
+ cover: cleanUrl(data.cover),
43
+ no_watermark: cleanUrl(data.links.find((l) => l.a && !l.s)?.a),
44
+ // Usually the first link is No WM
45
+ watermark: cleanUrl(data.links.find((l) => l.s?.includes("Watermark"))?.a),
46
+ music: cleanUrl(data.links.find((l) => l.t?.includes("Audio"))?.a),
47
+ author_name: cleanText(data.author),
48
+ views: "N/A"
49
+ };
50
+ } catch (error) {
51
+ throw new Error(`Fallback Failed: ${error.message}`);
52
+ }
53
+ };
54
+ var tiktok = async (input) => {
55
+ return new Promise(async (resolve, reject) => {
56
+ try {
57
+ const isUrl = input.match(/tiktok\.com/i);
58
+ let data;
59
+ try {
60
+ if (isUrl) {
61
+ const apiUrl = `https://www.tikwm.com/api/?url=${encodeURIComponent(input)}`;
62
+ const response = await axios3.get(apiUrl, { headers: getRandomHeaders() });
63
+ if (response.data.code !== 0) throw new Error("Private video or Invalid URL");
64
+ data = response.data.data;
65
+ } else {
66
+ const apiUrl = `https://www.tikwm.com/api/feed/search`;
67
+ const response = await axios3.post(
68
+ apiUrl,
69
+ new URLSearchParams({
70
+ keywords: input,
71
+ count: "1",
72
+ cursor: "0",
73
+ HD: "1"
74
+ }),
75
+ { headers: { ...getRandomHeaders(), "Cookie": "current_language=en" } }
76
+ );
77
+ if (!response.data.data?.videos || response.data.data.videos.length === 0) {
78
+ throw new Error(`No results found for: ${input}`);
79
+ }
80
+ data = response.data.data.videos[0];
81
+ }
82
+ const result = {
83
+ author: AUTHOR,
84
+ status: true,
85
+ title: data.title,
86
+ cover: data.cover,
87
+ origin_cover: data.origin_cover,
88
+ no_watermark: data.play,
89
+ watermark: data.wmplay,
90
+ music: data.music,
91
+ views: data.play_count,
92
+ likes: data.digg_count,
93
+ comments: data.comment_count,
94
+ shares: data.share_count,
95
+ downloads: data.download_count
96
+ };
97
+ resolve(result);
98
+ } catch (primaryError) {
99
+ if (isUrl) {
100
+ console.warn("Primary TikTok API failed, switching to fallback...");
101
+ const fallbackData = await lovetikFallback(input);
102
+ resolve(fallbackData);
103
+ } else {
104
+ throw primaryError;
105
+ }
106
+ }
107
+ } catch (error) {
108
+ reject({
109
+ author: AUTHOR,
110
+ status: false,
111
+ message: error.message || "TikTok processing failed"
112
+ });
113
+ }
114
+ });
115
+ };
116
+ var tiktokSlide = async (url) => {
117
+ try {
118
+ const response = await axios3.post("https://api.ttsave.app/", {
119
+ id: url,
120
+ hash: "1e3a27c51eb6370b0db6f9348a481d69",
121
+ mode: "slide",
122
+ locale: "en",
123
+ loading_indicator_url: "https://ttsave.app/images/slow-down.gif",
124
+ unlock_url: "https://ttsave.app/en/unlock"
125
+ }, {
126
+ headers: getRandomHeaders()
127
+ });
128
+ const $ = cheerio3.load(response.data);
129
+ const $element = $("div.flex.flex-col.items-center.justify-center.mt-2.mb-5");
130
+ if ($element.length === 0) throw new Error("Slide not found or service unavailable");
131
+ const statsDiv = $element.find("div.flex.flex-row.items-center.justify-center");
132
+ return {
133
+ author: AUTHOR,
134
+ status: true,
135
+ uniqueId: $element.find("input#unique-id").attr("value"),
136
+ title: $element.find("div.flex.flex-row.items-center.justify-center h2").text().trim(),
137
+ profileImage: $element.find("a").first().find("img").attr("src"),
138
+ profileUrl: $element.find("a").first().attr("href"),
139
+ hashtags: $element.find("p.text-gray-600").text().split(" ").filter(Boolean),
140
+ likes: statsDiv.eq(0).find("span").text().trim(),
141
+ comments: statsDiv.eq(1).find("span").text().trim(),
142
+ shares: statsDiv.eq(2).find("span").text().trim(),
143
+ downloads: statsDiv.eq(3).find("span").text().trim(),
144
+ views: statsDiv.eq(4).find("span").text().trim()
145
+ };
146
+ } catch (error) {
147
+ return {
148
+ author: AUTHOR,
149
+ status: false,
150
+ title: "Error",
151
+ views: error.message
152
+ };
153
+ }
154
+ };
155
+ var USER_AGENTS2 = [
156
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",
157
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36",
158
+ "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36",
159
+ "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1"
160
+ ];
161
+ var getRandomHeaders2 = () => ({
162
+ "User-Agent": USER_AGENTS2[Math.floor(Math.random() * USER_AGENTS2.length)],
163
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
164
+ "Accept-Language": "en-US,en;q=0.5",
165
+ "Accept-Encoding": "gzip, deflate, br",
166
+ "Connection": "keep-alive"
167
+ });
168
+ var fbdl = async (url) => {
169
+ return new Promise(async (resolve, reject) => {
170
+ try {
171
+ const { data } = await axios3.post(
172
+ "https://getmyfb.com/process",
173
+ new URLSearchParams({
174
+ id: url,
175
+ locale: "en"
176
+ }),
177
+ {
178
+ headers: {
179
+ ...getRandomHeaders2(),
180
+ "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
181
+ "Cookie": "PHPSESSID=mtkljtmk74aiej5h6d846gjbo4; __cflb=04dToeZfC9vebXjRcJCMjjSQh5PprejufZXs2vHCt5; _token=K5Qobnj4QvoYKeLCW6uk"
182
+ //s
183
+ }
184
+ }
185
+ );
186
+ const $ = cheerio3.load(data);
187
+ const results = [];
188
+ const title = $("div.results-item-text").eq(0).text().trim();
189
+ const thumbnail = $(".results-item-image-wrapper img").attr("src") || "";
190
+ $("a.btn-download").each((i, el) => {
191
+ const link = $(el).attr("href");
192
+ if (link) {
193
+ results.push({
194
+ author: AUTHOR,
195
+ status: true,
196
+ type: "video",
197
+ title: title || "Facebook Video",
198
+ thumbnail,
199
+ url: link
200
+ });
201
+ }
202
+ });
203
+ if (results.length === 0) {
204
+ const singleLink = $("a").attr("href");
205
+ if (singleLink && singleLink.startsWith("http")) {
206
+ results.push({
207
+ author: AUTHOR,
208
+ status: true,
209
+ type: "video",
210
+ title,
211
+ thumbnail,
212
+ url: singleLink
213
+ });
214
+ } else {
215
+ reject(new Error("No Facebook video found (Private or Invalid URL)"));
216
+ return;
217
+ }
218
+ }
219
+ resolve(results);
220
+ } catch (error) {
221
+ reject({
222
+ author: AUTHOR,
223
+ status: false,
224
+ message: error.message || "Facebook Download Failed"
225
+ });
226
+ }
227
+ });
228
+ };
229
+ var igdl = async (url) => {
230
+ return new Promise(async (resolve, reject) => {
231
+ try {
232
+ const initialResponse = await axios3.get("https://indown.io/", {
233
+ headers: getRandomHeaders2()
234
+ });
235
+ const _$ = cheerio3.load(initialResponse.data);
236
+ const referer = _$("input[name=referer]").val();
237
+ const locale = _$("input[name=locale]").val();
238
+ const _token = _$("input[name=_token]").val();
239
+ const cookies = initialResponse.headers["set-cookie"]?.join(" ") || "";
240
+ if (!_token) throw new Error("Failed to fetch Instagram token");
241
+ const { data } = await axios3.post(
242
+ "https://indown.io/download",
243
+ new URLSearchParams({
244
+ link: url,
245
+ referer,
246
+ locale,
247
+ _token
248
+ }),
249
+ {
250
+ headers: {
251
+ ...getRandomHeaders2(),
252
+ "Content-Type": "application/x-www-form-urlencoded",
253
+ "Cookie": cookies,
254
+ "Origin": "https://indown.io",
255
+ "Referer": "https://indown.io/"
256
+ }
257
+ }
258
+ );
259
+ const $ = cheerio3.load(data);
260
+ const result = [];
261
+ $("video").each(function() {
262
+ const $$ = $(this);
263
+ const src = $$.find("source").attr("src");
264
+ const poster = $$.attr("poster");
265
+ if (src) {
266
+ result.push({
267
+ author: AUTHOR,
268
+ status: true,
269
+ type: "video",
270
+ thumbnail: poster,
271
+ url: src
272
+ });
273
+ }
274
+ });
275
+ $("img.img-fluid").each(function() {
276
+ const $$ = $(this);
277
+ const src = $$.attr("src");
278
+ if (src) {
279
+ result.push({
280
+ author: AUTHOR,
281
+ status: true,
282
+ type: "image",
283
+ thumbnail: src,
284
+ url: src
285
+ });
286
+ }
287
+ });
288
+ if (result.length === 0) {
289
+ $(".btn-group a").each((i, el) => {
290
+ const link = $(el).attr("href");
291
+ if (link && link !== "#") {
292
+ result.push({
293
+ author: AUTHOR,
294
+ status: true,
295
+ type: "video",
296
+ url: link
297
+ });
298
+ }
299
+ });
300
+ }
301
+ if (result.length === 0) {
302
+ const errorMsg = $(".alert-danger").text().trim();
303
+ reject(new Error(errorMsg || "No media found. Account might be private."));
304
+ } else {
305
+ resolve(result);
306
+ }
307
+ } catch (error) {
308
+ reject({
309
+ author: AUTHOR,
310
+ status: false,
311
+ message: error.message || "Instagram Download Failed"
312
+ });
313
+ }
314
+ });
315
+ };
316
+ var search = async (query) => {
317
+ return new Promise(async (resolve, reject) => {
318
+ try {
319
+ const result = await yts(query);
320
+ if (!result.all || result.all.length === 0) {
321
+ return reject(new Error("No results found on YouTube."));
322
+ }
323
+ const data = result.all.map((item) => {
324
+ return {
325
+ type: item.type,
326
+ url: item.url,
327
+ title: item.title,
328
+ description: item.description,
329
+ image: item.image,
330
+ thumbnail: item.thumbnail,
331
+ seconds: item.seconds,
332
+ timestamp: item.timestamp,
333
+ views: item.views,
334
+ ago: item.ago,
335
+ author: item.author ? {
336
+ name: item.author.name,
337
+ url: item.author.url
338
+ } : void 0
339
+ };
340
+ });
341
+ resolve(data);
342
+ } catch (error) {
343
+ reject({
344
+ message: error.message || "YouTube Search Failed"
345
+ });
346
+ }
347
+ });
348
+ };
349
+ var ytmp3 = async (url) => {
350
+ return new Promise(async (resolve, reject) => {
351
+ try {
352
+ if (!ytdl.validateURL(url)) {
353
+ throw new Error("Invalid YouTube URL");
354
+ }
355
+ const info = await ytdl.getInfo(url);
356
+ const format = ytdl.chooseFormat(info.formats, {
357
+ quality: "highestaudio",
358
+ filter: "audioonly"
359
+ });
360
+ if (!format) throw new Error("No audio stream found");
361
+ const result = {
362
+ author: AUTHOR,
363
+ title: info.videoDetails.title,
364
+ thumbnail: info.videoDetails.thumbnails[info.videoDetails.thumbnails.length - 1].url,
365
+ // Highest res
366
+ channel: info.videoDetails.ownerChannelName,
367
+ published: info.videoDetails.publishDate,
368
+ views: info.videoDetails.viewCount,
369
+ duration: info.videoDetails.lengthSeconds,
370
+ url: format.url
371
+ };
372
+ resolve(result);
373
+ } catch (error) {
374
+ reject({
375
+ author: AUTHOR,
376
+ status: false,
377
+ message: error.message || "YouTube MP3 Failed"
378
+ });
379
+ }
380
+ });
381
+ };
382
+ var ytmp4 = async (url) => {
383
+ return new Promise(async (resolve, reject) => {
384
+ try {
385
+ if (!ytdl.validateURL(url)) {
386
+ throw new Error("Invalid YouTube URL");
387
+ }
388
+ const info = await ytdl.getInfo(url);
389
+ const format = ytdl.chooseFormat(info.formats, {
390
+ quality: "highest",
391
+ filter: (f) => f.hasAudio === true && f.hasVideo === true && f.container === "mp4"
392
+ });
393
+ const finalFormat = format || ytdl.chooseFormat(info.formats, {
394
+ quality: "highest",
395
+ filter: (f) => f.hasAudio === true && f.hasVideo === true
396
+ });
397
+ if (!finalFormat) throw new Error("No video stream found");
398
+ const result = {
399
+ author: AUTHOR,
400
+ title: info.videoDetails.title,
401
+ thumbnail: info.videoDetails.thumbnails[info.videoDetails.thumbnails.length - 1].url,
402
+ channel: info.videoDetails.ownerChannelName,
403
+ published: info.videoDetails.publishDate,
404
+ views: info.videoDetails.viewCount,
405
+ duration: info.videoDetails.lengthSeconds,
406
+ url: finalFormat.url
407
+ };
408
+ resolve(result);
409
+ } catch (error) {
410
+ reject({
411
+ author: AUTHOR,
412
+ status: false,
413
+ message: error.message || "YouTube MP4 Failed"
414
+ });
415
+ }
416
+ });
417
+ };
418
+ var play = async (query, type = "mp3") => {
419
+ try {
420
+ const searchResults = await yts(query);
421
+ const videos = searchResults.all.filter((v) => v.type === "video");
422
+ if (videos.length === 0) {
423
+ throw new Error(`No video results found for: ${query}`);
424
+ }
425
+ const firstVideo = videos[0];
426
+ if (type === "mp4") {
427
+ return await ytmp4(firstVideo.url);
428
+ } else {
429
+ return await ytmp3(firstVideo.url);
430
+ }
431
+ } catch (error) {
432
+ throw new Error(`Play Failed: ${error.message}`);
433
+ }
434
+ };
435
+ var HEADERS = {
436
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",
437
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
438
+ };
439
+ var ignoreSSL = new https.Agent({
440
+ rejectUnauthorized: false,
441
+ servername: "inferenceengine.vyro.ai"
442
+ });
443
+ var ssweb = async (url, device = "desktop") => {
444
+ return new Promise(async (resolve, reject) => {
445
+ try {
446
+ const baseURL = "https://www.screenshotmachine.com";
447
+ const param = { url, device, cacheLimit: 0 };
448
+ const { data, headers } = await axios3.post(
449
+ `${baseURL}/capture.php`,
450
+ new URLSearchParams(param),
451
+ {
452
+ headers: { "content-type": "application/x-www-form-urlencoded; charset=UTF-8", "User-Agent": HEADERS["User-Agent"] }
453
+ }
454
+ );
455
+ if (data.status !== "success") throw new Error("Screenshot generation failed");
456
+ const cookies = headers["set-cookie"]?.join("") || "";
457
+ const imageResponse = await axios3.get(`${baseURL}/${data.link}`, {
458
+ headers: { "cookie": cookies, "User-Agent": HEADERS["User-Agent"] },
459
+ responseType: "arraybuffer"
460
+ });
461
+ resolve(imageResponse.data);
462
+ } catch (error) {
463
+ reject(new Error(`SSWeb Failed: ${error.message}`));
464
+ }
465
+ });
466
+ };
467
+ var remini = async (imageUrl, method = "enhance") => {
468
+ return new Promise(async (resolve, reject) => {
469
+ try {
470
+ const validMethods = ["enhance", "recolor", "dehaze"];
471
+ const selectedMethod = validMethods.includes(method) ? method : "enhance";
472
+ const imgBuffer = await axios3.get(imageUrl, { responseType: "arraybuffer" });
473
+ const form = new FormData();
474
+ form.append("model_version", 1, {
475
+ header: { "Content-Transfer-Encoding": "binary", "contentType": "multipart/form-data; charset=utf-8" }
476
+ });
477
+ form.append("image", Buffer.from(imgBuffer.data), {
478
+ filename: "enhance_image_body.jpg",
479
+ contentType: "image/jpeg"
480
+ });
481
+ const url = `https://inferenceengine.vyro.ai/${selectedMethod}`;
482
+ const response = await axios3.post(url, form, {
483
+ headers: {
484
+ ...form.getHeaders(),
485
+ "User-Agent": "okhttp/4.9.3",
486
+ "Connection": "Keep-Alive",
487
+ "Accept-Encoding": "gzip"
488
+ },
489
+ responseType: "arraybuffer",
490
+ httpsAgent: ignoreSSL
491
+ });
492
+ resolve(response.data);
493
+ } catch (error) {
494
+ reject(new Error(`Remini Failed: ${error.message}`));
495
+ }
496
+ });
497
+ };
498
+ var styleText = async (text) => {
499
+ return new Promise(async (resolve, reject) => {
500
+ try {
501
+ const { data } = await axios3.get(`http://qaz.wtf/u/convert.cgi?text=${encodeURIComponent(text)}`);
502
+ const $ = cheerio3.load(data);
503
+ const result = [];
504
+ $("table > tbody > tr").each((i, el) => {
505
+ const name = $(el).find("td").first().text().trim();
506
+ const styled = $(el).find("td").eq(1).text().trim();
507
+ if (name && styled) {
508
+ result.push({ author: AUTHOR, name, result: styled });
509
+ }
510
+ });
511
+ resolve(result);
512
+ } catch (error) {
513
+ reject(new Error(`StyleText Failed: ${error.message}`));
514
+ }
515
+ });
516
+ };
517
+ var wattpad = async (query) => {
518
+ try {
519
+ const { data } = await axios3.get(`https://www.wattpad.com/search/${encodeURIComponent(query)}`, { headers: HEADERS });
520
+ const $ = cheerio3.load(data);
521
+ const results = [];
522
+ $(".story-card").each((i, el) => {
523
+ const title = $(el).find(".story-title").text().trim();
524
+ const image = $(el).find(".cover img").attr("src");
525
+ const link = "https://www.wattpad.com" + $(el).find("a.story-card-data").attr("href");
526
+ const reads = $(el).find(".read-count").text().trim();
527
+ if (title) results.push({ author: AUTHOR, title, image, link, reads });
528
+ });
529
+ if (results.length === 0) {
530
+ $("div.cover").each((i, el) => {
531
+ results.push({ author: AUTHOR, image: $(el).find("img").attr("src") });
532
+ });
533
+ }
534
+ return results;
535
+ } catch (error) {
536
+ throw new Error(`Wattpad Failed: ${error.message}`);
537
+ }
538
+ };
539
+ var chords = async (query) => {
540
+ try {
541
+ const searchUrl = `https://www.gitagram.com/?s=${encodeURIComponent(query).replace(/%20/g, "+")}`;
542
+ const { data } = await axios3.get(searchUrl, { headers: HEADERS });
543
+ const $ = cheerio3.load(data);
544
+ const firstResultUrl = $("table.table > tbody > tr").eq(0).find("td").eq(0).find("a").eq(0).attr("href");
545
+ if (!firstResultUrl) throw new Error("No chords found");
546
+ const songPage = await axios3.get(firstResultUrl, { headers: HEADERS });
547
+ const $song = cheerio3.load(songPage.data);
548
+ const $hcontent = $song("div.hcontent");
549
+ const artist = $hcontent.find("div > a > span.subtitle").text().trim();
550
+ const title = $hcontent.find("h1.title").text().trim();
551
+ const content = $song("div.content > pre").text().trim();
552
+ return { author: AUTHOR, title, artist, url: firstResultUrl, chord: content };
553
+ } catch (error) {
554
+ throw new Error(`Chords Failed: ${error.message}`);
555
+ }
556
+ };
557
+
558
+ // src/index.ts
559
+ var downloader = {
560
+ tiktok,
561
+ tiktokSlide,
562
+ igdl,
563
+ fbdl,
564
+ ytmp3,
565
+ ytmp4,
566
+ play
567
+ };
568
+ var search2 = {
569
+ youtube: search,
570
+ wattpad,
571
+ chords
572
+ };
573
+ var tools = {
574
+ ssweb,
575
+ remini,
576
+ styleText
577
+ };
578
+ var index_default = {
579
+ downloader,
580
+ search: search2,
581
+ tools
582
+ };
583
+
584
+ export { AUTHOR, chords, index_default as default, downloader, fbdl, igdl, play, remini, search2 as search, ssweb, styleText, tiktok, tiktokSlide, tools, wattpad, search as ytSearch, ytmp3, ytmp4 };
585
+ //# sourceMappingURL=index.mjs.map
586
+ //# sourceMappingURL=index.mjs.map