-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.js
160 lines (134 loc) · 4.45 KB
/
server.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
const express = require('express');
const path = require('path');
const fs = require('fs');
const { exec, spawn } = require('child_process');
const { channel } = require('diagnostics_channel');
require('dotenv').config();
const app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
const PORT = process.env.PORT;
const URL = process.env.URL;
const SOUT= `${process.env.SOUT}/stream`;
const filePath = path.join(__dirname, `${process.env.FILE}`);
let vlcProcess;
let currentChannel = '';
let channelId;
let list1;
let list2;
let master = [];
function parseM3U(file, p_handle) {
let handle = p_handle
const lines = file.split(/\r?\n/);
if ( !lines[0].startsWith('#EXTM3U') ) {
throw new Error('Invalid M3U file: Missing #EXTM3U header');
}
let list = [];
let currentItem = null;
for ( const line of lines ) {
if ( line.startsWith('#EXTINF') ) {
// Extract metadata after #EXTINF:
const metadata = line.substring(8).trim();
// Parse `tvg-ID`
const tvgIdMatch = metadata.match(/tvg-ID="(.*?)"/);
const tvgId = tvgIdMatch ? tvgIdMatch[1] : null;
// Parse `tvg-name`
const tvgNameMatch = metadata.match(/tvg-name="(.*?)"/);
const tvgName = tvgNameMatch ? tvgNameMatch[1] : null;
// Parse `tvg-logo`
const tvgLogoMatch = metadata.match(/tvg-logo="(.*?)"/);
const tvgLogo = tvgLogoMatch ? tvgLogoMatch[1] : null;
// Parse `group-title`
const groupTitleMatch = metadata.match(/group-title="(.*?)"/);
const groupTitle = groupTitleMatch ? groupTitleMatch[1] : null;
// Parse channel name (text after last comma)
const nameMatch = metadata.match(/,(.*)$/);
let name = nameMatch ? nameMatch[1] : null;
if (name) {
name = name.substring(4);
}
currentItem = {
tvg: {
id: tvgId,
name: tvgName,
logo: tvgLogo,
},
group: groupTitle,
name,
id: null,
};
} else if ( line.startsWith('http') && currentItem ) {
const url = line.trim();
const id = url.match(/\/(\d+)$/);
currentItem.id = id ? id[1] : null;
if( handle == "handle1" && currentItem.group.startsWith("Group A")) {
list.push(currentItem);
}
if ( handle == "handle2" && currentItem.group.startsWith("Group B")) {
list.push(currentItem)
}
currentItem = null;
}
}
return list;
}
// Read Channels
fs.readFile(filePath, 'utf8', (err, data) => {
if ( err ) {
console.error('Error reading the file:', err.message);
return;
}
try {
list1 = parseM3U(data, "handle1");
list2 = parseM3U(data, "handle2");
master.push(...list1);
master.push(...list2);
} catch ( error ) {
console.error('Error parsing M3U:', error.message);
}
});
// Route to display main page
app.get('/', (req, res) => {
let out = SOUT
let channel = currentChannel
try {
res.render('index', {
SOUT: out,
channel: channel,
list_1: list1,
list_2: list2
});
} catch (error) {
console.error('Error parsing:', error);
res.status(500).send('Internal Server Error');
}
});
// Route to handle individual channel clicks
app.get('/channel/:id', (req, res) => {
channelId = req.params.id;
const streamUrl = URL + channelId;
const selectedChannel = master.find(channel => channel.id === channelId);
currentChannel = selectedChannel.name + " || " + selectedChannel.group;
if(vlcProcess) {
vlcProcess.kill();
}
vlcProcess = spawn('cvlc', [
`${streamUrl}`,
'--sout', '#standard{access=http, mux=ts, dst=:8001}',
'--sout-keep',
]);
console.log('VLC process started with PID:', vlcProcess.pid);
res.redirect('/vlc');
});
app.get('/vlc/kill', (req, res) => {
if(vlcProcess) {
vlcProcess.kill();
currentChannel = "";
}
res.redirect('/vlc');
});
// Start the server
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});