584 lines
26 KiB
JavaScript
584 lines
26 KiB
JavaScript
|
|
var quote = String.fromCharCode(39)
|
|
var list_playlist = []
|
|
var result_search = []
|
|
|
|
|
|
|
|
var socket = io('https://iptv.mrk.ovh', {
|
|
secure: true,
|
|
rejectUnauthorized: false // Only for self-signed certificates
|
|
});
|
|
|
|
socket.on('connect', function() {
|
|
$('#sidClient').val(socket.id)
|
|
console.log("client connected sid = " + $('#sidClient').val())
|
|
});
|
|
|
|
|
|
socket.on('communication', function(data) {
|
|
console.log('communication', data)
|
|
// RECEPTION RETURN WARNING
|
|
if (data['typeCommand'] == 'warning') {
|
|
$('#warning').html(data['payload'])
|
|
$('#warning').show('slow')
|
|
setTimeout(() => { $('#warning').hide('slow') }, 5000);
|
|
}
|
|
})
|
|
|
|
|
|
$(window).on('scroll resize', lazyLoad);
|
|
|
|
// INITIALISAITON DES TABS
|
|
$('#tab_home').show()
|
|
update_list_playlist()
|
|
//get_search_channel()
|
|
$('#tab_search').hide()
|
|
$('#tab_playlist').hide()
|
|
$('#tab_devices').hide()
|
|
|
|
|
|
// CLICK TAB HOME
|
|
$('#display_tab_home').click(function(){
|
|
var triggerTab = new bootstrap.Tab($('#display_tab_home'));
|
|
triggerTab.show();
|
|
$('#tab_home').show()
|
|
$('#tab_search').hide()
|
|
$('#tab_playlist').hide()
|
|
$('#tab_devices').hide()
|
|
get_search_channel()
|
|
})
|
|
|
|
|
|
// CLICK TAB PLAYLIST
|
|
$('#display_tab_playlist').click(function(){
|
|
var triggerTab = new bootstrap.Tab($('#display_tab_playlist'));
|
|
triggerTab.show();
|
|
$('#tab_home').hide()
|
|
$('#tab_search').hide()
|
|
$('#tab_playlist').show()
|
|
$('#tab_devices').hide()
|
|
})
|
|
|
|
// CLICK TAB DEVICES
|
|
$('#display_tab_devices').click(function(){
|
|
var triggerTab = new bootstrap.Tab($('#display_tab_devices'));
|
|
triggerTab.show();
|
|
$('#tab_home').hide()
|
|
$('#tab_search').hide()
|
|
$('#tab_playlist').hide()
|
|
$('#tab_devices').show()
|
|
|
|
})
|
|
|
|
// CLICK TAB SEARCH
|
|
$('#display_tab_search').click(function(){
|
|
var triggerTab = new bootstrap.Tab($('#display_tab_devices'));
|
|
triggerTab.show();
|
|
$('#tab_home').hide()
|
|
$('#tab_search').show()
|
|
$('#tab_playlist').hide()
|
|
$('#tab_devices').hide()
|
|
|
|
})
|
|
|
|
// UPDATE TAB DEVICES
|
|
updateListDevices()
|
|
setInterval(updateListDevices, 10000)
|
|
|
|
|
|
$('#btn_search').click(function(){
|
|
get_search_channel($('#input_search').val())
|
|
})
|
|
|
|
$('#btn_initdb').click(function(){
|
|
$.get('init_db').done(function(data){
|
|
window.location.href = "/"
|
|
})
|
|
})
|
|
|
|
|
|
function isInViewport(element) {
|
|
const rect = element[0].getBoundingClientRect();
|
|
return (
|
|
rect.top >= 0 &&
|
|
rect.left >= 0 &&
|
|
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
|
|
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
|
|
);
|
|
}
|
|
|
|
function lazyLoad() {
|
|
$('.lazy').each(function () {
|
|
const img = $(this);
|
|
if (isInViewport(img) && !img.hasClass('loaded')) {
|
|
img.attr('src', img.data('src')); // Load the image
|
|
img.on('load', function () {
|
|
img.addClass('loaded'); // Add loaded class for fade-in
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
// DISPLAY CHANNELS
|
|
function displayResult() {
|
|
|
|
$('#listChannels').show()
|
|
|
|
if ($('#typeDisplay').val() == 'list') html = '<ul class="list-group">'
|
|
else html = '<div class="d-flex flex-wrap">'
|
|
result_search.forEach(element => {
|
|
var id_channel = element['id_channel']
|
|
var name_channel = element['Name']
|
|
var url_channel = element['url']
|
|
var url_channel_macos = url_channel.replace("http://", 'rtmp://')
|
|
//url_channel_macos = url_channel.replace("https://", 'rtmp://')
|
|
if ($('#typeDisplay').val() == 'list') {
|
|
html += `<li data-url_channel="${url_channel}" data-name_channel="${name_channel}" class="btn_play_media lineTable_device list-group-item"><img src="get_logo?id_channel=${id_channel}" style="height:30px"> <span class="p-3">${name_channel}</span></li>`
|
|
} else {
|
|
html += `<div data-id_channel="${id_channel}" class="m-2 card" style="width: 18rem;"> \
|
|
<img class="card-img-top mx-auto d-block mt-2" src="get_logo?id_channel=${id_channel}" alt="Card image cap" style='width:100px'> \
|
|
<div class="card-body"> \
|
|
<p class="btn_play_media card-text">${name_channel}</p> \
|
|
<button data-display_url="${url_channel}" class="btn_display_url btn btn-info">url</button> \
|
|
<a class="btn btn-primary" href="vlc://${url_channel_macos}">vlc ios</a> \
|
|
</div> \
|
|
</div>`
|
|
}
|
|
})
|
|
if ($('#typeDisplay').val() == 'list') html += '</ul>'
|
|
else html += '</div>'
|
|
$('#listChannels').html(html)
|
|
|
|
$('.btn_play_media').click(function(){
|
|
var name = $(this).data('name_channel')
|
|
var url = $(this).data('url_channel')
|
|
console.log('play media', name, url)
|
|
socket.emit('communication', {fromSidDevice : $('#sidClient').val(), toSidDevice: $('#sidDevice').val(), typeCommand : "on", payload: {name:name, url:url}, "packet":0});
|
|
})
|
|
$('.btn_display_url').click(function() {
|
|
var url = $(this).data('display_url')
|
|
alert(url)
|
|
})
|
|
|
|
}
|
|
|
|
// GET RESULT SEARCH
|
|
function get_search_channel() {
|
|
var keyword = $('#input_search').val()
|
|
if (keyword.length>0) {
|
|
$.post('list_channel', {keyword:encodeURIComponent(keyword)}).done(function(data){
|
|
$('#list_channels').html('')
|
|
var html =''
|
|
console.log(data)
|
|
result_search = JSON.parse(data)
|
|
displayResult()
|
|
lazyLoad();
|
|
})
|
|
}
|
|
}
|
|
|
|
// UPDATE LIST PLAYLIST
|
|
function update_list_playlist() {
|
|
|
|
$.get('get_list_playlists').done(function(data){
|
|
console.log(data)
|
|
$('#list_playlist').html('')
|
|
var html = '<table class="table"> \
|
|
<thead>\
|
|
<tr>\
|
|
<th scope="col">#</th>\
|
|
<th scope="col">Title</th>\
|
|
<th scope="col">End Date</th>\
|
|
<th scope="col">Num channels</th>\
|
|
<th scope="col"></th>\
|
|
<th scope="col"></th>\
|
|
<!--<th scope="col">Sid</th>-->\
|
|
</tr>\
|
|
</thead>\
|
|
<tbody>'
|
|
|
|
|
|
var dataJSON = JSON.parse(data)
|
|
//list_playlist = dataJSON
|
|
|
|
for (var i=0;i<dataJSON.length;i++) {
|
|
console.log(dataJSON[i])
|
|
var id_playlist = dataJSON[i].id_playlist
|
|
var state_playlist = dataJSON[i].activation
|
|
console.log('state playlist', state_playlist)
|
|
var html_state = ''
|
|
if (state_playlist == 1) {
|
|
html_state = 'class="btn btn-secondary btn-sm" >Active'
|
|
} else {
|
|
html_state = 'class="btn btn-outline-secondary btn-sm" >Inactive'
|
|
}
|
|
html += `<tr class="lineTable_device" id="zone_${dataJSON[i].title_playlist}">\
|
|
<th scope="row">${i.toString()}</th>\
|
|
<td>${dataJSON[i].title_playlist}</td>\
|
|
<td>${dataJSON[i].date_end_playlist}</td>\
|
|
<td>${dataJSON[i].num_channels}</td>\
|
|
<!--<td style="color:darkblue" id="zone_edit_playlist_${id_playlist}"><div class="d-flex flex-row"><div><i class="fas fa-edit"></i></div><div class="d-none d-lg-block" style="margin-left: 5px;">Edit</div></div></td>-->\
|
|
<td style="color:red" data-param1="id_playlist" id="zone_delete_playlist_${id_playlist}"><div class="d-flex flex-row"><div><i class="fas fa-trash-alt"></i></div><div class="d-none d-lg-block" style="margin-left: 5px;">Delete</div></div></td>\
|
|
<!--<td>'+dataJSON[i].id_playlist+'</td>-->\
|
|
<input id="state_activation_${id_playlist}" type="hidden" val=""> \
|
|
<td><div id="btn_activation_playlist_${id_playlist}" ${html_state}</div></td>\
|
|
</tr>`
|
|
|
|
}
|
|
html += ' </tbody></table>'
|
|
$('#list_playlist').html(html)
|
|
|
|
|
|
for (var i=0;i<dataJSON.length;i++) {
|
|
var id_playlist = dataJSON[i].id_playlist
|
|
var element = $('#zone_delete_playlist_'+id_playlist)
|
|
var state_playlist = dataJSON[i].activation
|
|
$("#state_activation_"+id_playlist).val(state_playlist)
|
|
|
|
|
|
element.click(function(){
|
|
var idp = $(this).attr('id').replace("zone_delete_playlist_", "")
|
|
console.log('delete playlist ' + idp)
|
|
$('#id_playlist_to_action').val(idp)
|
|
$('#modal_confirmation').modal('show')
|
|
})
|
|
|
|
$('#btn_activation_playlist_'+id_playlist).click(function(){
|
|
update_state_playlist(this)
|
|
})
|
|
}
|
|
|
|
function update_state_playlist(element) {
|
|
var id = $(element).attr('id').replace("btn_activation_playlist_", "");
|
|
console.log('change state from ' + $("#state_activation_"+id).val())
|
|
if ($("#state_activation_"+id).val() == "1") {
|
|
console.log('desactivate ' + id)
|
|
$.get('activation_playlist', {activation:0, id_playlist:id}).done(function(data){
|
|
var id_data = data['id_playlist']
|
|
$("#state_activation_"+id).val(0)
|
|
console.log(data)
|
|
$("#btn_activation_playlist_"+id).addClass("btn-outline-secondary")
|
|
$("#btn_activation_playlist_"+id).removeClass("btn-secondary")
|
|
$("#btn_activation_playlist_"+id).html("Inactive")
|
|
})
|
|
|
|
} else {
|
|
console.log('activate ' + id)
|
|
$.get('activation_playlist', {activation:1, id_playlist:id}).done(function(data){
|
|
var id_data = data['id_playlist']
|
|
console.log(data)
|
|
$("#state_activation_"+id_data).val(1)
|
|
$("#btn_activation_playlist_"+id_data).addClass("btn-secondary")
|
|
$("#btn_activation_playlist_"+id_data).removeClass("btn-outline-secondary")
|
|
$("#btn_activation_playlist_"+id_data).html("Active")
|
|
|
|
})
|
|
}
|
|
}
|
|
|
|
})
|
|
}
|
|
|
|
|
|
// UPDATE LIST DEVICES
|
|
function updateListDevices() {
|
|
|
|
$.get('list_devices').done(function (data) {
|
|
console.log('Data received')
|
|
var html = '<table class="table"> \
|
|
<thead>\
|
|
<tr>\
|
|
<th scope="col">#</th>\
|
|
<th scope="col">Device</th>\
|
|
<th scope="col">LastDateTime</th>\
|
|
<!--<th scope="col">Sid</th>-->\
|
|
<th scope="col">Channel</th>\
|
|
</tr>\
|
|
</thead>\
|
|
<tbody>'
|
|
|
|
var html2 = ''
|
|
var html3 = ''
|
|
|
|
var dataJSON = JSON.parse(data)
|
|
|
|
for (var i=0;i<dataJSON.length;i++) {
|
|
var sid_device = dataJSON[i].sid
|
|
var timestamp = dataJSON[i].last_datetime
|
|
var actualTS = Math.floor(Date.now() / 1000)
|
|
var delta = actualTS - timestamp
|
|
var status = ''
|
|
//var media = '<div class="alert alert-primary" role="alert">' + dataJSON[i].mediaRunning + '</div>'
|
|
var media = '<span class="badge bg-success">'+dataJSON[i].mediaRunning+'</span>'
|
|
if (delta < 60) {
|
|
status = '<span style="color: green;">Online</span>'
|
|
status2 = '#ebfaeb'
|
|
}
|
|
if (delta > 86400) {
|
|
status = '<span style="color: SlateBlue;">Offline</span>'
|
|
status2 = '#e6e6ff'
|
|
}
|
|
if ((delta > 60) && (delta <= 86400)) {
|
|
status = '<span style="color: red;">' + Math.floor(delta / 60).toString() + ' min</span>'
|
|
status2 = '#ffe6e6'
|
|
}
|
|
|
|
html += `<tr class="lineTable_device" data-name_device="${dataJSON[i].name}" data-sid_device="${sid_device}" >\
|
|
<th scope="row">${i.toString()}</th>\
|
|
<td>${dataJSON[i].name}</td>\
|
|
<td>${status}</td>\
|
|
<td>${media}</td>\
|
|
<!--<td>'+dataJSON[i].sid+'</td>-->\
|
|
</tr>`
|
|
|
|
html2 += '<li id="btn_select_device_'+dataJSON[i].id_device+'" data-param1="'+dataJSON[i].id_device+'" data-param2="'+dataJSON[i].name+'" data-param3="'+dataJSON[i].sid+'"><a class="dropdown-item" href="#">'+dataJSON[i].name+'</a></li>'
|
|
|
|
html3 += '<div id="btn_select_device_card_'+dataJSON[i].id_device+'" data-param1="'+dataJSON[i].id_device+'" data-param2="'+dataJSON[i].name+'" data-param3="'+dataJSON[i].sid+'" class="card card_device" style="background-color:'+status2+'"> \
|
|
<div class="card-body"> \
|
|
<p class="card-text"><div class="d-flex justify-content-between"> \
|
|
<div>'+dataJSON[i].name+'</div> \
|
|
<div><i class="fas fa-trash-alt"></i></div></div></p> \
|
|
<p class="card-text">'+status+'</p> \
|
|
<p class="card-text">'+media+'</p> \
|
|
</div> \
|
|
</div>'
|
|
}
|
|
html += ' </tbody></table>'
|
|
$('#listDevices').html(html)
|
|
//$('#list_device_home').html(html2)
|
|
//$('#zone_device_main').html(html3)
|
|
|
|
function configure_current_device(element) {
|
|
const id_device = $(element).data('param1');
|
|
const name_device = $(element).data('param2');
|
|
const sid = $(element).data('param3');
|
|
console.log(id_device, name_device)
|
|
$('#id_device').val(id_device)
|
|
$('#sidDevice').val(sid)
|
|
$('#btn_select_device').html(name_device)
|
|
}
|
|
|
|
for (var i=0;i<dataJSON.length;i++) {
|
|
$('#btn_select_device_'+dataJSON[i].id_device).click(function(){
|
|
configure_current_device(this)
|
|
})
|
|
$("#btn_select_device_card_"+dataJSON[i].id_device).click(function(){
|
|
configure_current_device(this)
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
}
|
|
|
|
$(document).on("click", ".lineTable_device", function() {
|
|
var sid = $(this).data('sid_device')
|
|
var name_device = $(this).data('name_device')
|
|
console.log("sid",sid)
|
|
$('#NameDevice').html(name_device)
|
|
$('#sidDevice').val(sid)
|
|
getChannelRunning()
|
|
channelInterval = setInterval(getChannelRunning, 5000)
|
|
})
|
|
|
|
function getChannelRunning() {
|
|
socket.emit('communication', {fromSidDevice : $('#sidClient').val(), toSidDevice: $('#sidDevice').val(), typeCommand : "getChannelRunning", payload: '', "packet":0});
|
|
}
|
|
|
|
|
|
// CLICK TAB HOME
|
|
$('#display_tab_home').click(function(){
|
|
var triggerTab = new bootstrap.Tab($('#display_tab_home'));
|
|
triggerTab.show();
|
|
$('#tab_home').show()
|
|
$('#tab_search').hide()
|
|
$('#tab_playlist').hide()
|
|
})
|
|
// CLICK TAB SEARCH
|
|
$('#display_tab_search').click(function(){
|
|
var triggerTab = new bootstrap.Tab($('#display_tab_search'));
|
|
triggerTab.show();
|
|
$('#tab_home').hide()
|
|
$('#tab_search').show()
|
|
$('#tab_playlist').hide()
|
|
})
|
|
|
|
|
|
// CLICK ADD PLAYLIST
|
|
$('#btn_configure_playlist').click(function(){
|
|
$('#modal_add_playlist').modal('show')
|
|
})
|
|
|
|
// Check valid URL
|
|
function isValidURL(string) {
|
|
var pattern = new RegExp('^(https?:\\/\\/)?' + // Protocol
|
|
'((([a-zA-Z0-9\\-]+\\.)+[a-zA-Z]{2,})|' + // Domain name
|
|
'localhost|' + // OR localhost
|
|
'\\d{1,3}(\\.\\d{1,3}){3})' + // OR IPv4
|
|
'(\\:\\d+)?' + // Optional port
|
|
'(\\/[-a-zA-Z0-9@:%._\\+~#=]*)*' + // Path
|
|
'(\\?[;&a-zA-Z0-9@:%._\\+~#=]*)?' + // Query string
|
|
'(\\#[-a-zA-Z0-9@:%._\\+~#=]*)?$', 'i'); // Fragment locator
|
|
return pattern.test(string);
|
|
}
|
|
|
|
// Update filemame
|
|
$("#file-input").on("change", function () {
|
|
$("#fileName").val(this.files[0]?.name || "No file selected.");
|
|
});
|
|
|
|
|
|
|
|
// CLICK BTN btn_confirmation_delete_playlist
|
|
$('#btn_confirmation_delete_playlist').click(function(){
|
|
$.post('delete_playlist', {id_playlist : $('#id_playlist_to_action').val() }).done(function(data){
|
|
console.log(data)
|
|
update_list_playlist()
|
|
$('#modal_confirmation').modal('hide')
|
|
|
|
})
|
|
})
|
|
|
|
|
|
// CLICK UPLOAD FILE PLAYLIST
|
|
$("#upload-button").click(function () {
|
|
|
|
// Validation form
|
|
var validation_date = false
|
|
if ($('#playlist_end_date').val()) validation_date = true; else validation_date = false;
|
|
if (!validation_date) {
|
|
$('#playlist_end_date').addClass('is-invalid');
|
|
$('#playlist_end_date').removeClass('is-valid');
|
|
} else {
|
|
$('#playlist_end_date').addClass('is-valid');
|
|
$('#playlist_end_date').removeClass('is-invalid');
|
|
}
|
|
|
|
var validation_url = isValidURL($('#playlist_url').val())
|
|
if (!validation_url) {
|
|
$('#playlist_url').addClass('is-invalid');
|
|
$('#playlist_url').removeClass('is-valid');
|
|
} else {
|
|
$('#playlist_url').addClass('is-valid');
|
|
$('#playlist_url').removeClass('is-invalid');
|
|
}
|
|
|
|
var validation_title = !($('#playlist_title').val().trim() === '')
|
|
if (!validation_title) {
|
|
$('#playlist_title').addClass('is-invalid');
|
|
$('#playlist_title').removeClass('is-valid');
|
|
} else {
|
|
$('#playlist_title').addClass('is-valid');
|
|
$('#playlist_title').removeClass('is-invalid');
|
|
}
|
|
|
|
if ((validation_title) && (validation_date) && (validation_url)) {
|
|
|
|
const file = $("#file-input")[0].files[0];
|
|
if (!file) {
|
|
$('#add_playlist_alert').html('<div class="alert alert-danger" role="alert">Please select a file</div>')
|
|
return;
|
|
}
|
|
|
|
const formData = new FormData();
|
|
formData.append("file", file);
|
|
|
|
const xhr = new XMLHttpRequest();
|
|
xhr.open("POST", "/upload", true);
|
|
|
|
// Update progress bar
|
|
xhr.upload.onprogress = function (event) {
|
|
if (event.lengthComputable) {
|
|
const percentComplete = Math.round((event.loaded / event.total) * 100);
|
|
$("#progress-bar").val(percentComplete);
|
|
$("#progress-text").text(percentComplete + "%");
|
|
}
|
|
};
|
|
|
|
xhr.onloadstart = function () {
|
|
$("#progress-container").show();
|
|
};
|
|
|
|
xhr.onload = function () {
|
|
if (xhr.status === 200) {
|
|
$('#add_playlist_alert').html('<div class="alert alert-success" role="alert">Upload successful!</div>')
|
|
var response =JSON.parse(xhr.response)
|
|
id_playlist = response['id_playlist']
|
|
if (response.status == 'ok') {
|
|
|
|
$.post('analyse_m3u_file', {'id_playlist':id_playlist,
|
|
'title':$('#playlist_title').val(),
|
|
'url':$('#playlist_url').val(),
|
|
'date_end':$('#playlist_end_date').val(),
|
|
'filename':$("#fileName").val()}).done(function(data){
|
|
|
|
var num_channel = data.num_channel
|
|
if (num_channel>0) {
|
|
$('#add_playlist_alert').html('<div class="alert alert-success" role="alert">Num channel : '+String(num_channel)+'</div>')
|
|
} else {
|
|
$('#add_playlist_alert').html('<div class="alert alert-danger" role="alert">No channel in the file</div>')
|
|
}
|
|
update_list_playlist()
|
|
$('#modal_add_playlist').modal('hide')
|
|
|
|
})
|
|
}
|
|
|
|
} else {
|
|
$('#add_playlist_alert').html('<div class="alert alert-danger" role="alert">Upload failed!</div>')
|
|
}
|
|
$("#progress-container").hide();
|
|
};
|
|
|
|
xhr.onerror = function () {
|
|
alert("An error occurred while uploading.");
|
|
$("#progress-container").hide();
|
|
};
|
|
|
|
xhr.send(formData);
|
|
}
|
|
|
|
});
|
|
|
|
|
|
$("#typeDisplay").change(function(){
|
|
console.log($("#typeDisplay").val())
|
|
displayResult()
|
|
})
|
|
|
|
$('#btn_display_player').click(function () {
|
|
if($('#player').css('display') == 'none'){
|
|
$('#player').show('slow');
|
|
$('#valRange').html='0'
|
|
$('#Range').val(0)
|
|
} else {
|
|
$('#player').hide('slow');
|
|
}
|
|
})
|
|
|
|
$(".dropdown-submenu .dropdown-toggle").on("click", function (e) {
|
|
e.preventDefault(); // Prevent link from navigating
|
|
e.stopPropagation(); // Prevent closing the whole dropdown
|
|
|
|
let $submenu = $(this).next(".dropdown-menu");
|
|
|
|
// Toggle the submenu visibility
|
|
$(".dropdown-submenu .dropdown-menu").not($submenu).removeClass("show"); // Close other submenus
|
|
$submenu.toggleClass("show");
|
|
});
|
|
|
|
// Close submenus when clicking outside
|
|
$(document).on("click", function (e) {
|
|
if (!$(e.target).closest(".dropdown-submenu").length) {
|
|
$(".dropdown-submenu .dropdown-menu").removeClass("show");
|
|
}
|
|
});
|
|
|
|
function off(){
|
|
console.log('OFF ',$('#sidDevice').val(), $('#sidClient').val())
|
|
socket.emit('communication', {fromSidDevice : $('#sidClient').val(), toSidDevice: $('#sidDevice').val(), typeCommand : "off", payload: 0, "packet":0});
|
|
}
|
|
|
|
|
|
|