Skip to content

Instantly share code, notes, and snippets.

@erseco
Last active January 24, 2025 11:28
Show Gist options
  • Save erseco/5ff0850ecff7c8ea16a9862e473b5dea to your computer and use it in GitHub Desktop.
Save erseco/5ff0850ecff7c8ea16a9862e473b5dea to your computer and use it in GitHub Desktop.
sicher
// ==UserScript==
// @name Auto Fichaje SICHO
// @namespace https://gobiernodecanarias.net/
// @version 1.3
// @description Shows a floating panel to automate fichaje after detecting #thBienvenidaMensaje
// @match https://www3.gobiernodecanarias.net/aplicaciones/SICHO/*
// @updateURL https://gist.github.com/erseco/5ff0850ecff7c8ea16a9862e473b5dea/raw/6bae071265187149a84a8cf183074738fe164733/sicher.user.js
// @downloadURL https://gist.github.com/erseco/5ff0850ecff7c8ea16a9862e473b5dea/raw/6bae071265187149a84a8cf183074738fe164733/sicher.user.js
// @grant none
// ==/UserScript==
(function() {
'use strict';
/**
* Detect if the user is on a mobile device by checking the user agent.
* This is a simple (and not always perfect) approach.
*/
function isMobileDevice() {
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
}
/**
* Creates and injects the floating panel in the DOM.
*/
function createFichajePanel() {
const container = document.createElement('div');
container.id = 'autoFichajePanel';
// Position it at the bottom-right
container.style.position = 'fixed';
container.style.bottom = '20px';
container.style.right = '20px';
container.style.zIndex = '99999';
container.style.backgroundColor = '#f0f0f0';
container.style.border = '2px solid #333';
container.style.padding = '10px';
container.style.fontFamily = 'sans-serif';
container.style.boxShadow = '2px 2px 6px rgba(0,0,0,0.2)';
// Slightly bigger for desktop, even bigger if mobile
if (isMobileDevice()) {
// If it's mobile, let's give it a bigger width
container.style.width = '300px';
} else {
// Slightly bigger than 220px for desktop
container.style.width = '260px';
}
// Close (X) button
const closeBtn = document.createElement('span');
closeBtn.textContent = '✖';
closeBtn.style.cursor = 'pointer';
closeBtn.style.float = 'right';
closeBtn.style.fontSize = '16px';
closeBtn.style.marginBottom = '6px';
closeBtn.addEventListener('click', () => {
container.remove();
});
container.appendChild(closeBtn);
// Title
const titleEl = document.createElement('p');
titleEl.textContent = '¿Desea fichar automáticamente?';
titleEl.style.margin = '0';
titleEl.style.fontWeight = 'bold';
titleEl.style.clear = 'both';
container.appendChild(titleEl);
// Buttons
const buttonsWrapper = document.createElement('div');
buttonsWrapper.style.marginTop = '8px';
buttonsWrapper.innerHTML = `
<button id="ficharNowBtn">Fichar 🚀</button>
<button id="olvidoBtn">Olvido 😅</button>
<button id="falloBtn">Fallo ⚡</button>
`;
container.appendChild(buttonsWrapper);
// Manual date/time selection
const dateTimeSection = document.createElement('div');
dateTimeSection.id = 'dateTimeSection';
dateTimeSection.style.marginTop = '12px';
dateTimeSection.style.display = 'none';
dateTimeSection.innerHTML = `
<label for="fichajeDate" style="display:block; margin-bottom:4px;">Select a date:</label>
<input type="date" id="fichajeDate" style="margin-bottom:8px; width:150px;">
<label for="fichajeTime" style="display:block; margin-bottom:4px;">Select a time:</label>
<input type="time" id="fichajeTime" style="margin-bottom:8px; width:150px;">
<button id="submitManualFicha" style="display:block; margin-top:6px;">Submit</button>
`;
container.appendChild(dateTimeSection);
document.body.appendChild(container);
}
/**
* Show or hide the date/time manual selection.
* @param {boolean} show - Whether to show the date/time block.
*/
function toggleDateTimeSection(show) {
const section = document.getElementById('dateTimeSection');
if (section) {
section.style.display = show ? 'block' : 'none';
}
}
/**
* Opens "Mis permisos e incidencias" by clicking #celdaIconosPrimera_8, if found.
*/
function openMisPermisosIncidencias() {
const misIncidenciasBtn = document.getElementById('celdaIconosPrimera_8');
if (misIncidenciasBtn) {
misIncidenciasBtn.click();
} else {
alert('Could not find "Mis permisos e incidencias" button.');
}
}
/**
* Chooses either "1.A - ENTRADA" or "2.A - SALIDA" depending on hour (before or after 11).
*/
function selectConceptByTime(dateObj) {
const hour = dateObj.getHours();
let textToSelect = (hour < 11) ? '1.A - ENTRADA' : '2.A - SALIDA';
const selectConcept = document.getElementById('principal.menuConstructor.objMisIncidencias.selectorIncidencias.comboIncidencias.objPintaCombo');
if (selectConcept) {
const options = selectConcept.querySelectorAll('option');
let foundOption = false;
options.forEach(opt => {
if (opt.textContent.trim() === textToSelect) {
opt.selected = true;
foundOption = true;
}
});
selectConcept.dispatchEvent(new Event('change', { bubbles: true }));
if (!foundOption) {
alert('Could not find the option: ' + textToSelect);
}
} else {
alert('Could not find the Concept select box.');
}
}
/**
* Selects hour & minute in #Horas and #Minutos (if they exist).
*/
function selectHourMinute(dateObj) {
const hour = dateObj.getHours().toString().padStart(2, '0');
const minute = dateObj.getMinutes().toString().padStart(2, '0');
const selectHour = document.getElementById('Horas');
if (selectHour) {
const hourOpt = selectHour.querySelector(`option[value="${hour}"]`);
if (hourOpt) {
hourOpt.selected = true;
selectHour.dispatchEvent(new Event('change', { bubbles: true }));
}
}
const selectMin = document.getElementById('Minutos');
if (selectMin) {
const minOpt = selectMin.querySelector(`option[value="${minute}"]`);
if (minOpt) {
minOpt.selected = true;
selectMin.dispatchEvent(new Event('change', { bubbles: true }));
}
}
}
/**
* Selects the day in the calendar by matching the date in the title (DD/MM/YYYY).
*/
function selectDay(dateObj) {
const dayNumber = dateObj.getDate().toString();
const month = (dateObj.getMonth() + 1).toString().padStart(2, '0');
const year = dateObj.getFullYear().toString();
const desiredTitlePart = dayNumber + '/' + month + '/' + year;
const dayCells = document.querySelectorAll('td.dia');
let found = false;
dayCells.forEach(cell => {
const numeroDia = cell.getAttribute('numero-dia');
const title = cell.getAttribute('title');
if (numeroDia === dayNumber && title && title.includes(desiredTitlePart)) {
cell.click();
found = true;
}
});
if (!found) {
alert('Could not find day ' + desiredTitlePart + ' in the calendar.');
}
}
/**
* Clicks the "Solicitar" button if available.
*/
function clickSolicitar() {
const solicitarBtn = document.getElementById('principal.menuConstructor.objMisIncidencias.selectorIncidencias.botonSolicitar.btn');
if (solicitarBtn) {
solicitarBtn.click();
} else {
alert('Could not find the "Solicitar" button.');
}
}
/**
* Selects a cause by its numeric value.
*/
function selectCause(causeValue) {
const causeSelect = document.getElementById('principal.menuConstructor.objMisIncidencias.ventanaCausa.comboCausa.objPintaCombo');
if (causeSelect) {
const opts = causeSelect.querySelectorAll('option');
let foundOption = false;
opts.forEach(opt => {
if (opt.value === causeValue) {
opt.selected = true;
foundOption = true;
}
});
causeSelect.dispatchEvent(new Event('change', { bubbles: true }));
if (!foundOption) {
alert('Could not find cause option: ' + causeValue);
}
} else {
alert('Could not find the cause select box.');
}
}
/**
* Clicks the final "Aceptar" button.
*/
function clickAceptarCausa() {
const aceptarBtn = document.getElementById('principal.menuConstructor.objMisIncidencias.ventanaCausa.botonAceptar.btn');
if (aceptarBtn) {
aceptarBtn.click();
alert('Fichaje sent. If everything is correct, the system will record it.');
} else {
alert('Could not find the "Aceptar" button for the cause.');
}
}
/**
* Main function that simulates the entire "fichar" process.
* (Here we do NOT call clickAceptarCausa, for testing.)
*/
function doFichaje(causeValue, dateObj) {
openMisPermisosIncidencias();
// Simple timeouts for demonstration
setTimeout(() => {
selectDay(dateObj);
}, 4500);
setTimeout(() => {
selectConceptByTime(dateObj);
}, 1500);
setTimeout(() => {
selectHourMinute(dateObj);
}, 3000);
setTimeout(() => {
clickSolicitar();
}, 6000);
setTimeout(() => {
selectCause(causeValue);
}, 7500);
// Uncomment for final confirmation if needed:
// setTimeout(() => {
// clickAceptarCausa();
// }, 9000);
}
let manualCause = null;
/**
* Sets up button event listeners.
*/
function setupEventListeners() {
const ficharNowBtn = document.getElementById('ficharNowBtn');
if (ficharNowBtn) {
ficharNowBtn.addEventListener('click', function() {
const now = new Date();
const causeValue = '114283907'; // INSTRUCCIONES_FICHAJE_DGFP
doFichaje(causeValue, now);
});
}
const olvidoBtn = document.getElementById('olvidoBtn');
if (olvidoBtn) {
olvidoBtn.addEventListener('click', function() {
manualCause = '2220603'; // OLVIDO
toggleDateTimeSection(true);
});
}
const falloBtn = document.getElementById('falloBtn');
if (falloBtn) {
falloBtn.addEventListener('click', function() {
manualCause = '2220605'; // FALLO ELÉCTRICO
toggleDateTimeSection(true);
});
}
// "Submit" for manual date/time
const submitManual = document.getElementById('submitManualFicha');
if (submitManual) {
submitManual.addEventListener('click', function() {
const dateInput = document.getElementById('fichajeDate');
const timeInput = document.getElementById('fichajeTime');
if (!dateInput.value || !timeInput.value) {
alert('Please provide both date and time.');
return;
}
const combinedDate = new Date(dateInput.value + ' ' + timeInput.value + ':00');
toggleDateTimeSection(false);
doFichaje(manualCause, combinedDate);
});
}
}
/**
* Wait for the #thBienvenidaMensaje element, then create the panel and set up listeners.
*/
function waitForBienvenidaMensaje() {
const el = document.getElementById('thBienvenidaMensaje');
if (el) {
createFichajePanel();
setupEventListeners();
} else {
// If not found, retry after 1 second
setTimeout(waitForBienvenidaMensaje, 1000);
}
}
// Start checking for the #thBienvenidaMensaje element
waitForBienvenidaMensaje();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment