Advertisement
samipote

Untitled

Aug 27th, 2023
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.50 KB | None | 0 0
  1. const express = require('express');
  2. const mongoose = require('mongoose');
  3. const cors = require('cors');
  4. const path = require('path');
  5. const methodOverride = require('method-override');
  6. const request = require('request');
  7. const restream = require('restream');
  8. const app = express();
  9. app.set('host', 'sportswatcher.ddns.net');
  10. const fs = require('fs');
  11. const fetch = require('node-fetch');
  12. app.use(express.json()); // Parse JSON bodies
  13. app.use(express.urlencoded({ extended: true })); // Parse URL-encoded bodies
  14. app.use(cors()); // Enable CORS
  15. app.use(methodOverride('_method')); // Enable method override
  16.  
  17. // Replace with your MongoDB connection string
  18. const connectionString = 'mongodb://localhost:27017/streaming';
  19.  
  20. // Connect to MongoDB
  21. mongoose
  22. .connect(connectionString, { useNewUrlParser: true, useUnifiedTopology: true })
  23. .then(() => {
  24. console.log('Connected to MongoDB');
  25. })
  26. .catch((error) => {
  27. console.error('Failed to connect to MongoDB', error);
  28. });
  29.  
  30. // Define a Mongoose schema for our Game model
  31. const gameSchema = new mongoose.Schema({
  32. title: String,
  33. streamLink: String,
  34. sport: String,
  35. });
  36.  
  37. // Create the Game model
  38. const Game = mongoose.model('Game', gameSchema);
  39.  
  40. // Serve static files from the public directory
  41. app.use(express.static(path.join(__dirname, 'public')));
  42.  
  43. const proxyAddress = 'http://localhost:8080/';
  44. process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
  45.  
  46. // A function that returns a modified URL for .ts and .wbp files
  47. function getSegmentURL(targetURL) {
  48. const baseURL = getBaseURL();
  49. return baseURL + 'segment/' + targetURL.replace('https://', '');
  50. }
  51.  
  52. // A function that returns a modified URL for .m3u8 files
  53. function getPlaylistURL(targetURL) {
  54. const baseURL = getBaseURL();
  55. return baseURL + 'proxy/' + targetURL.replace('https://', '');
  56. }
  57.  
  58. app.use('/proxy/', async (req, res, next) => {
  59. const fullURL = req.protocol + '://' + req.get('host') + req.originalUrl;
  60. const { pathname, search } = new URL(fullURL);
  61. console.log(`Received request for URL: ${fullURL}`);
  62. const targetURL = pathname.replace('/proxy/', 'https://') + search;
  63.  
  64. // Check if the request is for an m3u8 file
  65. if (path.extname(targetURL).toLowerCase() === '.m3u8') {
  66. try {
  67. const m3u8Response = await fetch(targetURL, {
  68. headers: {
  69. 'accept': '*/*',
  70. 'accept-encoding': 'gzip, deflate, br',
  71. 'origin': 'https://ddhwebcast4k.xyz',
  72. 'referer': 'https://ddhwebcast4k.xyz/',
  73. 'sec-fetch-mode': 'cors',
  74. 'sec-fetch-site': 'cross-site',
  75. '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',
  76. 'authority' : 'ddh1.cdndac.lol'
  77. }
  78. });
  79. let m3u8Content = await m3u8Response.text();
  80.  
  81. // Modify the .ts and .wbp URLs in the m3u8 content
  82. m3u8Content = m3u8Content.split('\n').map(line => {
  83. if (line.endsWith('.ts') || line.endsWith('.wbp')) {
  84. // Check if the segment link is relative or absolute
  85. if (line.startsWith('http')) {
  86. // Absolute link, use getSegmentURL function
  87. return getSegmentURL(line);
  88. } else {
  89. // Relative link, append to the targetURL's base path
  90. const basePath = targetURL.substring(0, targetURL.lastIndexOf('/') + 1);
  91. return getSegmentURL(basePath + line);
  92. }
  93. } else if (line.endsWith('.m3u8')) {
  94. // Check if the playlist link is relative or absolute
  95. if (line.startsWith('http')) {
  96. // Absolute link, use getPlaylistURL function
  97. return getPlaylistURL(line);
  98. } else {
  99. // Relative link, append to the targetURL's base path
  100. const basePath = targetURL.substring(0, targetURL.lastIndexOf('/') + 1);
  101. return getPlaylistURL(basePath + line);
  102. }
  103. } else {
  104. return line;
  105. }
  106. }).join('\n');
  107.  
  108. res.setHeader('Content-Type', 'application/x-mpegURL');
  109. res.setHeader('Access-Control-Allow-Origin', '*');
  110. res.send(m3u8Content);
  111. } catch (err) {
  112. console.error('Failed to fetch m3u8:', err.message);
  113. res.status(500).send('Proxy Error');
  114. }
  115. return;
  116. }
  117.  
  118. const proxyRequestOptions = {
  119. url: targetURL
  120. };
  121.  
  122. const proxyRequest = request(proxyRequestOptions);
  123.  
  124. proxyRequest.on('response', async function(sourceResponse) {
  125. // Diagnostic log to check the status code and the file extension
  126. console.log(`Status code: ${sourceResponse.statusCode}, File extension: ${path.extname(targetURL).toLowerCase()}`);
  127.  
  128. if (path.extname(targetURL).toLowerCase() === '.ts' && sourceResponse.statusCode >= 300 && sourceResponse.statusCode < 400) {
  129. const redirectTo = sourceResponse.headers['location'];
  130. console.log(`Redirection detected for ${targetURL} -> ${redirectTo}`);
  131.  
  132. // Diagnostic log to check the redirect location
  133. console.log(`Redirect detected to: ${redirectTo}`);
  134.  
  135. if (redirectTo && path.extname(redirectTo).toLowerCase() === '.js') {
  136. try {
  137. console.log('Attempting to fetch the .js video data...'); // Diagnostic log
  138. const jsResponse = await fetch(redirectTo);
  139. const videoData = await jsResponse.buffer();
  140. res.setHeader('Content-Type', 'video/MP2T');
  141. res.setHeader('Access-Control-Allow-Origin', '*');
  142. res.send(videoData);
  143. return;
  144. } catch (err) {
  145. console.error('Failed to fetch .js video data:', err.message);
  146. res.status(500).send('Proxy Error');
  147. return;
  148. }
  149. }
  150. }
  151.  
  152. Object.keys(sourceResponse.headers).forEach(headerKey => {
  153. res.setHeader(headerKey, sourceResponse.headers[headerKey]);
  154. });
  155.  
  156. let contentType = sourceResponse.headers['content-type'];
  157. if (!contentType || contentType === 'application/octet-stream') {
  158. const extname = path.extname(targetURL).toLowerCase();
  159. if (extname === '.m4s') {
  160. res.setHeader('Content-Type', 'application/dash+xml');
  161. } else if (extname === '.ts') {
  162. res.setHeader('Content-Type', 'video/MP2T');
  163. } else if (extname === '.wbp') {
  164. res.setHeader('Content-Type', 'video/webm');
  165. } else {
  166. res.setHeader('Content-Type', 'application/x-mpegURL');
  167. }
  168. }
  169.  
  170. res.setHeader('Access-Control-Allow-Origin', '*');
  171. sourceResponse.pipe(res);
  172. });
  173.  
  174. proxyRequest.on('error', function(err) {
  175. console.error('Proxy Error for URL:', targetURL, 'Error:', err.message);
  176. res.status(500).send('Proxy Error');
  177. });
  178.  
  179. res.on('error', (err) => {
  180. console.error('Error during response pipe:', err);
  181. });
  182. req.pipe(restream()).pipe(proxyRequest);
  183. });
  184.  
  185. // A new route for handling .ts and .wbp requests
  186. app.use('/segment/*', (req, res) => {
  187. const fullURL = req.protocol + '://' + req.get('host') + req.originalUrl;
  188. console.log(`Received request for URL: ${fullURL}`);
  189.  
  190. // Capture the segment path from the wildcard
  191. const segmentPath = req.params[0];
  192.  
  193. // Construct the targetURL with the captured segment path
  194. const targetURL = 'https://' + segmentPath;
  195.  
  196. // Create a proxyRequestOptions object with the headers copied from the original request
  197. const proxyRequestOptions = {
  198. url: targetURL,
  199. headers: {
  200. 'accept': '*/*',
  201. 'accept-encoding': 'gzip, deflate, br',
  202. 'origin': 'https://ddhwebcast4k.xyz',
  203. 'referer': 'https://ddhwebcast4k.xyz/',
  204. 'sec-fetch-mode': 'cors',
  205. 'sec-fetch-site': 'cross-site',
  206. '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',
  207. 'authority' : 'ddh1.cdndac.lol'
  208. }
  209. };
  210.  
  211. // Set the host header to match the target URL's host
  212. proxyRequestOptions.headers.host = new URL(targetURL).host;
  213.  
  214. const proxyRequest = request(proxyRequestOptions);
  215.  
  216. proxyRequest.on('response', function(sourceResponse) {
  217. Object.keys(sourceResponse.headers).forEach(headerKey => {
  218. res.setHeader(headerKey, sourceResponse.headers[headerKey]);
  219. });
  220. let contentType = sourceResponse.headers['content-type'];
  221. if (!contentType || contentType === 'application/octet-stream') {
  222. const extname = path.extname(targetURL).toLowerCase();
  223. if (extname === '.ts') {
  224. res.setHeader('Content-Type', 'video/MP2T');
  225. } else if (extname === '.wbp') {
  226. res.setHeader('Content-Type', 'video/webm'); // Assume webm format for .wbp files
  227. }
  228. }
  229. res.setHeader('Access-Control-Allow-Origin', '*');
  230. sourceResponse.pipe(res);
  231. });
  232. proxyRequest.on('error', function(err) {
  233. console.error('Proxy Error for URL:', targetURL, 'Error:', err.message);
  234. res.status(500).send('Proxy Error');
  235. });
  236. res.on('error', (err) => {
  237. console.error('Error during response pipe:', err);
  238. });
  239. req.pipe(restream()).pipe(proxyRequest);
  240. });
  241.  
  242. function getBaseURL() {
  243. return `http://${app.get('host')}/`;
  244. }
  245.  
  246. app.get('/', (req, res) => {
  247. res.render('main.ejs');
  248. });
  249.  
  250. // Route for serving the admin panel
  251. app.get('/admin', async (req, res) => {
  252. try {
  253. const games = await Game.find();
  254. res.render('admin.ejs', { videos: games });
  255. } catch (error) {
  256. res.status(500).send(error);
  257. }
  258. });
  259.  
  260. // Route for getting all games
  261. app.get('/games', async (req, res) => {
  262. try {
  263. const games = await Game.find();
  264. res.send(games);
  265. } catch (error) {
  266. res.status(500).send(error);
  267. }
  268. });
  269.  
  270. // Route for creating a new game
  271. app.post('/games', async (req, res) => {
  272. try {
  273. const game = new Game(req.body);
  274. await game.save();
  275. res.redirect('/admin');
  276. } catch (error) {
  277. res.status(500).send(error);
  278. }
  279. });
  280.  
  281. app.put('/games/:id', async (req, res) => {
  282. try {
  283. const { id } = req.params;
  284. const { title, streamLink, sport } = req.body;
  285. const updatedGame = await Game.findByIdAndUpdate(id, { title, streamLink, sport }, { new: true });
  286. res.redirect('/admin');
  287. } catch (error) {
  288. res.status(500).send(error);
  289. }
  290. });
  291.  
  292. // Route for deleting a game
  293. app.delete('/games/:id', async (req, res) => {
  294. try {
  295. await Game.deleteOne({ _id: req.params.id });
  296. res.redirect('/admin');
  297. } catch (error) {
  298. res.status(500).send(error);
  299. }
  300. });
  301.  
  302. // Start the server
  303. const port = process.env.PORT || 3000;
  304. app.listen(port, () => console.log(`Server running on port ${port}`));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement