-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
170 lines (162 loc) · 4.14 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// Imports
const { default: axios } = require("axios");
const cookieParser = require("set-cookie-parser");
// Define Constants
/** @type {Record<import(".").EVideoLengths, string>} */
const V_DURATIONS = {
any: "",
short: "",
medium: "",
long: "",
feature: "",
};
/** @type {Record<import(".").EVideoSortings, string} */
const V_SORTINGS = {
relevance: "",
newest: "",
oldest: "",
};
// Export Functions
/**
*
* @param {string} possibleLink
* @returns {boolean}
*/
function isBitchuteLink(possibleLink) {
try {
// Check if is a link
const link = new URL(possibleLink);
// Check if is from bitchute domain
return link.hostname.endsWith(".bitchute.com");
} catch (err) {
// Check Invalid URL
if (err instanceof TypeError && err.code === "ERR_INVALID_URL")
return false;
// Error Not Identified -> Throw It
throw err;
}
}
async function fetchCookies() {
// Resquest Home Page of Bitchute
const response = await axios({
method: "GET",
baseURL: "https://www.bitchute.com",
url: "/",
});
/** @type {Array<string>} Fetch Cookie from Response */
const setCookies = response.headers["set-cookie"];
// Parse Cookies
const cookies = cookieParser(setCookies, { map: true });
// Return Cookies
return cookies;
}
/**
*
* @param {string} topic
* @param {import(".").EVideoLengths} [duration]
* @param {import(".").EVideoSortings} [sorting]
* @param {import("set-cookie-parser").CookieMap | Promise<import("set-cookie-parser").CookieMap>} [cookies]
*/
async function searchVideo(
topic,
duration = "any",
sorting = "relevance",
cookies = fetchCookies()
) {
// Fetch Needed Cookies
const { __cfduid: cfduid, csrftoken: csrf } =
cookies instanceof Promise ? await cookies : cookies;
// Make Request on Bitchute API
/** @type {import("axios").AxiosResponse<import(".").IVideoSearchResult>} */
const response = await axios({
method: "POST",
baseURL: "https://www.bitchute.com",
url: "/api/search/list/",
data: new URLSearchParams({
csrfmiddlewaretoken: csrf.value,
query: topic,
kind: "video",
duration: V_DURATIONS[duration],
sort: V_SORTINGS[sorting],
page: 0,
}).toString(),
headers: {
Cookie: ""
.concat(`${cfduid.name}=${cfduid.value};`)
.concat(`${csrf.name}=${csrf.value}`),
Referer: "https://www.bitchute.com/search/?".concat(
new URLSearchParams({
query: topic,
kind: "video",
duration: V_DURATIONS[duration],
sort: V_SORTINGS[sorting],
})
),
},
});
// Get Content
const searchResults = response.data;
// Check if Sucessful Search
if (!searchResults.success)
throw new Error(
"Result data not sucessful\n".concat(JSON.stringify(searchResults))
);
// Return Video List
return searchResults.results;
}
/**
*
* @param {string} publicPath
* @param {import("set-cookie-parser").CookieMap | Promise<import("set-cookie-parser").CookieMap>} [cookies]
*/
async function getVideoPrivateLink(publicPath, cookies = fetchCookies()) {
// Fetch Needed Cookies
const { __cfduid: cfduid, csrftoken: csrf } =
cookies instanceof Promise ? await cookies : cookies;
// Make Request on Bitchute API
/** @type {import("axios").AxiosResponse<string>} */
const response = await axios({
method: "GET",
baseURL: "https://www.bitchute.com",
url: publicPath,
headers: {
Cookie: ""
.concat(`${cfduid.name}=${cfduid.value};`)
.concat(`${csrf.name}=${csrf.value}`),
Referer: "https://www.bitchute.com/",
},
});
// Get HTML Content
const pageContent = response.data;
// User Regex to Extract Private Link
const privateLink = new RegExp(
`<source src="(?<pLink>[a-zA-Z0-9\\-_\\.~:/]+)" type="video/mp4" />`
).exec(pageContent).groups.pLink;
// Return Link
return privateLink;
}
/**
*
* @param {string} privateLink
*/
async function getVideoStream(privateLink) {
// Request Video on BitChute
const response = await axios({
method: "GET",
url: privateLink,
responseType: "stream",
});
// Extract Video Stream
/** @type {import("stream").Readable} */
const videoStream = response.data;
// Return Stream
return videoStream;
}
// Export Module Functions
module.exports = {
isBitchuteLink,
fetchCookies,
searchVideo,
getVideoPrivateLink,
getVideoStream,
};