Microsoft Teams Auto Hangup Timer

Adds a small floating countdown timer in Microsoft Teams that automatically clicks the hang-up button when the time runs out.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name         Microsoft Teams Auto Hangup Timer
// @namespace    https://greasyfork.org/users/your-username
// @version      1.0
// @description  Adds a small floating countdown timer in Microsoft Teams that automatically clicks the hang-up button when the time runs out.
// @author       artur0527rg
// @match        https://teams.microsoft.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=microsoft.com
// @run-at       document-end
// @license      MIT
// @grant        none
// ==/UserScript==

/*
    🧑 Author: artur0527rg
    🌐 GitHub: https://github.com/artur0527rg
*/

(function() {
    'use strict';

    function createOverlay(onFinishCallback) {
        const container = document.createElement('div');
        container.timerInterval = null;

        Object.assign(container.style, {
            position: 'fixed',
            display: 'flex',
            bottom: '10px',
            right: '10px',
            backgroundColor: '#4f52b2',
            borderRadius: '4px',
            padding: '10px',
            gap: '5px',
            alignItems: 'center',
            zIndex: 99999
        });

        const hours = document.createElement('input');
        Object.assign(hours, {
            type: 'text',
            inputMode: 'numeric',
            value: '01',
        });
        Object.assign(hours.style, {
            all: 'unset',
            borderBottom: '1px solid white',
            color: 'white',
            width: '30px',
            fontSize: '18px',
            textAlign: 'center'
        });

        hours.addEventListener('change', (e) => {
            let raw = (e.target.value || '').replace(/\D/g, '');
            let h = parseInt(raw, 10);
            if (isNaN(h)) h = 0;
            if (h > 23) h = 23;
            e.target.value = h.toString().padStart(2, '0');
        });

        const divider1 = document.createElement('span');
        divider1.textContent = ':';
        divider1.style.color = 'white';
        divider1.style.fontSize = '18px';

        const minutes = document.createElement('input');
        Object.assign(minutes, {
            type: 'text',
            inputMode: 'numeric',
            value: '30',
        });
        Object.assign(minutes.style, {
            all: 'unset',
            borderBottom: '1px solid white',
            color: 'white',
            width: '35px',
            fontSize: '18px',
            textAlign: 'center'
        });

        minutes.addEventListener('change', (e) => {
            let raw = (e.target.value || '').replace(/\D/g, '');
            let m = parseInt(raw, 10);
            if (isNaN(m)) m = 0;
            if (m > 59) m = 59;
            e.target.value = m.toString().padStart(2, '0');
        });

        const divider2 = document.createElement('span');
        divider2.textContent = ':';
        divider2.style.color = 'white';
        divider2.style.fontSize = '18px';

        const seconds = document.createElement('input');
        Object.assign(seconds, {
            type: 'text',
            inputMode: 'numeric',
            value: '00',
        });
        Object.assign(seconds.style, {
            all: 'unset',
            borderBottom: '1px solid white',
            color: 'white',
            width: '35px',
            fontSize: '18px',
            textAlign: 'center'
        });

        seconds.addEventListener('change', (e) => {
            let raw = (e.target.value || '').replace(/\D/g, '');
            let s = parseInt(raw, 10);
            if (isNaN(s)) s = 0;
            if (s > 59) s = 59;
            e.target.value = s.toString().padStart(2, '0');
        });

        const button = document.createElement('button');
        button.textContent = 'Start';
        Object.assign(button.style, {
            all: 'unset',
            border: '1px solid white',
            borderRadius: '4px',
            color: 'white',
            fontSize: '16px',
            padding: '5px 10px',
            cursor: 'pointer'
        });

        let isRunning = false;

        button.addEventListener('click', () => {
            if (!isRunning) {
                // Prevent double click
                if (container.timerInterval) {
                    clearInterval(container.timerInterval);
                    container.timerInterval = null;
                }

                let h = parseInt(hours.value) || 0;
                let m = parseInt(minutes.value) || 0;
                let s = parseInt(seconds.value) || 0;
                let totalSeconds = h * 3600 + m * 60 + s ;

                if (totalSeconds <= 0) return alert('Введите корректное время!');

                isRunning = true;
                button.textContent = 'Stop';
                hours.disabled = true;
                minutes.disabled = true;
                seconds.disabled = true;

                container.timerInterval = setInterval(() => {
                    totalSeconds--;
                    if (totalSeconds < 0) totalSeconds = 0;

                    const newHours = Math.floor(totalSeconds / 3600);
                    const newMinutes = Math.floor((totalSeconds % 3600) / 60);
                    const newSeconds = totalSeconds % 60;

                    hours.value = newHours.toString().padStart(2, '0');
                    minutes.value = newMinutes.toString().padStart(2, '0');
                    seconds.value = newSeconds.toString().padStart(2, '0');

                    if (totalSeconds < 10) {
                        container.style.backgroundColor = totalSeconds % 2 === 0 ? '#b24f4f' : '#4f52b2';
                    }

                    if (totalSeconds <= 0) {
                        clearInterval(container.timerInterval);
                        isRunning = false;
                        button.textContent = 'Start';
                        hours.disabled = false;
                        minutes.disabled = false;
                        seconds.disabled = false;
                        container.style.backgroundColor = '#4f52b2';

                        if (typeof onFinishCallback === 'function') {
                            onFinishCallback();
                        }
                    }
                }, 1000);
            } else {
                clearInterval(container.timerInterval);
                container.timerInterval = null;
                isRunning = false;
                button.textContent = 'Start';
                hours.disabled = false;
                minutes.disabled = false;
                seconds.disabled = false;
                container.style.backgroundColor = '#4f52b2';
            }
        });

        container.append(hours, divider1, minutes, divider2, seconds, button);
        document.body.appendChild(container);
        return container;
    }


    // Main function to run the script logic
    function main() {
        let overlay = null;

        function checkButton() {
            const btn = document.querySelector('#hangup-button');
            console.log(btn);
            if (btn) {
                if (!overlay) {
                    overlay = createOverlay(() => {
                        if (document.body.contains(btn)) btn.click();
                    });
                }
            } else {
                if (overlay) {
                    if (overlay.timerInterval) clearInterval(overlay.timerInterval);
                    overlay.remove();
                    overlay = null;
                }
            }
        }

        // Проверяем сразу на случай, если кнопка уже есть
        checkButton();

        // Далее проверяем каждые 5 секунд
        setInterval(checkButton, 5000);
    }

    main();
})();