Skip to content

Instantly share code, notes, and snippets.

@selimtan
Created January 17, 2025 20:17
Show Gist options
  • Save selimtan/aa6963bdee07ff2b66342b8496968598 to your computer and use it in GitHub Desktop.
Save selimtan/aa6963bdee07ff2b66342b8496968598 to your computer and use it in GitHub Desktop.
const express = require('express');
const axios = require('axios');
const app = express();
async function curlRequest(url) {
try {
const response = await axios.get(url);
return response.data;
} catch (error) {
if (error.response) {
return null;
} else {
return null;
}
}
}
app.get('/m3u', async (req, res) => {
const { url, username, password, unwanted_groups = '' } = req.query;
if (!url || !username || !password) {
return res.status(400).send("Missing url, username, or password");
}
const unwantedGroups = unwanted_groups.split(',').map(group => group.trim());
const mainurlJson = await curlRequest(`${url}/player_api.php?username=${username}&password=${password}`);
if (!mainurlJson) {
return res.status(503).send("Unable to connect to the server. There might be an SSL certificate issue. Please check your URL and try again.");
}
let mainurlRaw = mainurlJson;
/* try {
mainurlRaw = JSON.parse(mainurlJson);
} catch (error) {
return res.status(500).send("Invalid response data from the server");
} */
if (!mainurlRaw.user_info || !mainurlRaw.server_info) {
return res.status(400).send("Invalid response data");
}
const livechannelJson = await curlRequest(`${url}/player_api.php?username=${username}&password=${password}&action=get_live_streams`);
if (!livechannelJson) {
return res.status(503).send("Failed to retrieve live streams. There might be a connection issue.");
}
let livechannelRaw;
try {
livechannelRaw = livechannelJson;
} catch (error) {
return res.status(500).send("Invalid live streams data from the server");
}
if (!Array.isArray(livechannelRaw)) {
return res.status(500).send("Invalid live streams data");
}
const categoryJson = await curlRequest(`${url}/player_api.php?username=${username}&password=${password}&action=get_live_categories`);
if (!categoryJson) {
return res.status(503).send("Failed to retrieve live categories. There might be a connection issue.");
}
let categoryRaw;
try {
categoryRaw = categoryJson;
} catch (error) {
return res.status(500).send("Invalid live categories data from the server");
}
if (!Array.isArray(categoryRaw)) {
return res.status(500).send("Invalid live categories data");
}
const { user_info, server_info } = mainurlRaw;
const serverUrl = `http://${server_info.url}:${server_info.port}`;
const fullUrl = `${serverUrl}/live/${user_info.username}/${user_info.password}/`;
const categoryName = {};
categoryRaw.forEach(cat => {
categoryName[cat.category_id] = cat.category_name;
});
let m3uPlaylist = "#EXTM3U\n";
livechannelRaw.forEach(channel => {
if (channel.stream_type === 'live') {
const groupTitle = categoryName[channel.category_id] || "Uncategorized";
//if (!unwantedGroups.some(unwantedGroup => groupTitle.toLowerCase().includes(unwantedGroup.toLowerCase()))) {
const logoUrl = channel.stream_icon || '';
m3uPlaylist += `#EXTINF:0 tvg-name="${channel.name}" group-title="${groupTitle}" tvg-logo="${logoUrl}",${channel.name}\n`;
m3uPlaylist += `${fullUrl}${channel.stream_id}.ts\n`;
// }
}
});
res.setHeader("Content-Disposition", "attachment; filename=LiveStream.m3u");
res.setHeader("Content-Type", "audio/x-scpls");
res.send(m3uPlaylist);
});
app.get('/movie', async (req, res) => {
const { url, username, password, unwanted_groups = '' } = req.query;
if (!url || !username || !password) {
return res.status(400).send("Missing url, username, or password");
}
const unwantedGroups = unwanted_groups.split(',').map(group => group.trim());
const mainurlJson = await curlRequest(`${url}/player_api.php?username=${username}&password=${password}`);
if (!mainurlJson) {
return res.status(503).send("Unable to connect to the server. There might be an SSL certificate issue. Please check your URL and try again.");
}
let mainurlRaw = mainurlJson;
if (!mainurlRaw.user_info || !mainurlRaw.server_info) {
return res.status(400).send("Invalid response data");
}
const livechannelJson = await curlRequest(`${url}/player_api.php?username=${username}&password=${password}&action=get_vod_streams`);
if (!livechannelJson) {
return res.status(503).send("Failed to retrieve VOD streams. There might be a connection issue.");
}
let livechannelRaw = livechannelJson;
if (!Array.isArray(livechannelRaw)) {
return res.status(500).send("Invalid VOD streams data");
}
const categoryJson = await curlRequest(`${url}/player_api.php?username=${username}&password=${password}&action=get_vod_categories`);
if (!categoryJson) {
return res.status(503).send("Failed to retrieve VOD categories. There might be a connection issue.");
}
let categoryRaw = categoryJson;
if (!Array.isArray(categoryRaw)) {
return res.status(500).send("Invalid VOD categories data");
}
const { user_info, server_info } = mainurlRaw;
const serverUrl = `http://${server_info.url}:${server_info.port}`;
const fullUrl = `${serverUrl}/movie/${user_info.username}/${user_info.password}/`;
const categoryName = {};
categoryRaw.forEach(cat => {
categoryName[cat.category_id] = cat.category_name;
});
let m3uPlaylist = "#EXTM3U\n";
livechannelRaw.forEach(channel => {
if (channel.stream_type === 'movie') {
const groupTitle = categoryName[channel.category_id] || "Uncategorized";
//if (!unwantedGroups.some(unwantedGroup => groupTitle.toLowerCase().includes(unwantedGroup.toLowerCase()))) {
const logoUrl = channel.stream_icon || '';
m3uPlaylist += `#EXTINF:0 tvg-name="${groupTitle} - ${channel.name}" group-title="${groupTitle}" tvg-logo="${logoUrl}",${groupTitle} - ${channel.name}\n`;
m3uPlaylist += `${fullUrl}${channel.stream_id}.${channel.container_extension}\n`;
// }
}
});
res.setHeader("Content-Disposition", "attachment; filename=Movies.m3u");
res.setHeader("Content-Type", "audio/x-scpls");
res.send(m3uPlaylist);
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment