Files

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});
}