Ruloaooa commited on
Commit
9e3c54f
·
verified ·
1 Parent(s): 86eafbe

Create scraper.js

Browse files
Files changed (1) hide show
  1. scraper.js +120 -0
scraper.js ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require("axios");
2
+
3
+ class LoveTik {
4
+ constructor() {
5
+ this.base = "https://lovetik.com";
6
+ this.api = "https://lovetik.com/api/ajax";
7
+ this.headers = {
8
+ "user-agent": "Postify/1.0.0",
9
+ origin: this.base,
10
+ referer: `${this.base}/`,
11
+ "x-requested-with": "XMLHttpRequest",
12
+ "content-type": "application/x-www-form-urlencoded; charset=UTF-8"
13
+ };
14
+ }
15
+
16
+ validLink(url) {
17
+ if (!url || typeof url !== "string") {
18
+ throw new Error("Link tidak valid.");
19
+ }
20
+ const regex =
21
+ /^(https?:\/\/)?(www\.)?(tiktok\.com|vt\.tiktok\.com)\/(@[\w.-]+\/video\/\d+|\w+)/;
22
+ if (!regex.test(url)) {
23
+ throw new Error("Link tidak sesuai format TikTok.");
24
+ }
25
+ return true;
26
+ }
27
+
28
+ async search(url) {
29
+ this.validLink(url);
30
+ const res = await axios.post(
31
+ `${this.api}/search`,
32
+ `query=${encodeURIComponent(url)}`,
33
+ { headers: this.headers }
34
+ );
35
+ return res.data;
36
+ }
37
+
38
+ async convert(cData) {
39
+ const res = await axios.post(
40
+ `${this.api}/convert`,
41
+ `c_data=${encodeURIComponent(cData)}`,
42
+ { headers: this.headers }
43
+ );
44
+ return res.data;
45
+ }
46
+
47
+ clean(text) {
48
+ return text ? text.replace(/<\/?b>/g, "").trim() : null;
49
+ }
50
+
51
+ process(output) {
52
+ const result = {
53
+ videoId: output?.vid,
54
+ cover: output?.cover,
55
+ description: output?.desc,
56
+ author: {
57
+ username: output?.author,
58
+ nickname: output?.author_name,
59
+ avatar: output?.author_a
60
+ },
61
+ media: {
62
+ images: output?.images?.map(url => ({ url })) || [],
63
+ videos: [],
64
+ audios: []
65
+ }
66
+ };
67
+
68
+ output?.links?.forEach(link => {
69
+ const type = this.clean(link.t);
70
+
71
+ const base = {
72
+ type: type || "Unknown",
73
+ format: link.ft,
74
+ url: link.a
75
+ };
76
+
77
+ if (type?.includes("MP4") || type?.includes("Video")) {
78
+ result.media.videos.push({
79
+ ...base,
80
+ size: link.s,
81
+ converting: !!link.c,
82
+ c: link.c
83
+ });
84
+ } else if (type?.includes("MP3") || type?.includes("Audio")) {
85
+ result.media.audios.push({
86
+ ...base,
87
+ title: link.s,
88
+ converting: !!link.c,
89
+ c: link.c
90
+ });
91
+ }
92
+ });
93
+
94
+ return result;
95
+ }
96
+
97
+ async download(url) {
98
+ this.validLink(url);
99
+
100
+ const output = await this.search(url);
101
+ const result = this.process(output);
102
+
103
+ const medias = [...result.media.videos, ...result.media.audios];
104
+
105
+ await Promise.all(
106
+ medias.map(async m => {
107
+ if (m.converting && m.c) {
108
+ const res = await this.convert(m.c);
109
+ m.url = res.link;
110
+ delete m.converting;
111
+ delete m.c;
112
+ }
113
+ })
114
+ );
115
+
116
+ return result;
117
+ }
118
+ }
119
+
120
+ module.exports = LoveTik;