GitHub Copilot automatically obtains GHU

Automatically fill and submit GitHub device authorization code, and handle confirmation page by form submission after fully loaded.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name         GitHub Copilot automatically obtains GHU
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Automatically fill and submit GitHub device authorization code, and handle confirmation page by form submission after fully loaded.
// @author       NingMengGuoRou
// @match        https://github.com/login/device*
// @grant        GM_xmlhttpRequest
// @license MIT
// ==/UserScript==

(function() {
    'use strict';
//   const fetchTokenUrl = '改成你自己的http(s)://ip:端口';
  const fetchTokenUrl = 'https://xxxx:9191';
    async function getUserCode() {
        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: "GET",
                url: fetchTokenUrl+"/get_user_code",
                onload: function(response) {
                    try {
                        const data = JSON.parse(response.responseText);
                        if (data.user_code) {
                            resolve(data.user_code);
                        } else {
                            reject("Failed to get user code");
                        }
                    } catch (e) {
                        reject(e.toString());
                    }
                },
                onerror: function(error) {
                    reject(error.toString());
                }
            });
        });
    }
    function waitForElement(selector, delay = 50, maxAttempts = 20) {
        return new Promise((resolve, reject) => {
            let attempts = 0;
            const interval = setInterval(() => {
                const element = document.querySelector(selector);
                attempts++;
                if (element) {
                    clearInterval(interval);
                    resolve(element);
                } else if (attempts >= maxAttempts) {
                    clearInterval(interval);
                    reject(new Error(`Element ${selector} not found`));
                }
            }, delay);
        });
    }
    async function fillAndSubmitCode() {
        try {
            const userCode = await getUserCode();
            const codeParts = userCode.split('-');
            if (codeParts.length !== 2) {
                console.error("Invalid user code format.");
                return;
            }
            for (let i = 0; i < codeParts[0].length; i++) {
                waitForElement(`#user-code-${i}`).then(el => el.value = codeParts[0][i]);
            }
            for (let i = 0; i < codeParts[1].length; i++) {
                waitForElement(`#user-code-${i + 5}`).then(el => el.value = codeParts[1][i]);
            }
            waitForElement('input[type="submit"][name="commit"]').then(button => setTimeout(() => button.click(), 1000));
        } catch (error) {
            console.error(error);
        }
    }
    // function autoSubmitFormOnConfirmation() {
    //     const observer = new MutationObserver((mutations, obs) => {
    //         const form = document.querySelector('form');
    //         if (form) {
    //             const authorizeButton = form.querySelector('button[name="authorize"][value="1"]');
    //             if (authorizeButton) {
    //                 setTimeout(() => {
    //                     form.submit();
    //                     obs.disconnect();
    //                 }, 1000);
    //             }
    //         }
    //     });
    //     observer.observe(document.body, { childList: true, subtree: true });
    // }
    function autoSubmitFormOnConfirmation() {
      console.log("--------------------------------------------------------")
          window.addEventListener('load', () => {
            waitForElement('form[action="/login/device/authorize"] button[name="authorize"][value="1"]')
                .then(button => setTimeout(() => button.click(), 1000))
                .catch(error => console.error(error));
        });
    }
    if (window.location.pathname.includes('/login/device')) {
        fillAndSubmitCode();
    }
    if (window.location.pathname.includes('/login/device/confirmation')) {
        autoSubmitFormOnConfirmation();
    }
    if (window.location.pathname.includes('/login/device/success')) {
      // Add a delay before executing the GM_xmlhttpRequest call
setTimeout(function() {
    GM_xmlhttpRequest({
        method: 'GET',
        url: fetchTokenUrl+"/success",
        onload: function(response) {
            try {
                const data = JSON.parse(response.responseText);
                console.log(data);
                if (data.token) {
                    const message = document.createElement('div');
                    message.style.position = 'fixed';
                    message.style.left = '0';
                    message.style.top = '0'; // Changed from bottom to top
                    message.style.width = '100%';
                    message.style.backgroundColor = 'green';
                    message.style.color = 'white';
                    message.style.textAlign = 'center';
                    message.style.padding = '10px';
                    message.style.fontSize = '20px';
                    message.style.zIndex = '1000'; // Ensure it's on top of other elements
                    message.innerText = 'Authorization successful! You can now close this window GHU:'+data.token;
                    document.body.appendChild(message);
                } else {
                    console.error("Token fetch error: ", data.error);
                }
            } catch (e) {
                console.error("Response parsing error: ", e);
            }
        },
        onerror: function(error) {
            console.error("Request failed: ", error);
        }
    });
}, 1000); // Delay set to 5000 milliseconds (5 seconds)
    }
})();