Nojima Cookie Sender

Gửi cookies về server local khi vào trang mypage hoặc cart

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Nojima Cookie Sender
// @namespace    http://tampermonkey.net/
// @version      1.5
// @description  Gửi cookies về server local khi vào trang mypage hoặc cart
// @author       You
// @match        https://online.nojima.co.jp/app/mypage/mypage/*
// @match        https://online.nojima.co.jp/app/mypage/mypage
// @match        https://online.nojima.co.jp/sp/app/mypage/mypage/*
// @match        https://online.nojima.co.jp/sp/app/mypage/mypage
// @match        https://online.nojima.co.jp/sp/app/cart/cart/*
// @match        https://online.nojima.co.jp/sp/app/cart/cart
// @grant        GM_xmlhttpRequest
// @grant        GM_getValue
// @grant        GM_setValue
// @connect      localhost
// @connect      127.0.0.1
// @connect      192.168.1.13
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

    // ====== CẤU HÌNH ======
    const SERVER_URL = 'http://192.168.1.13:3000/receive-cookies';
    const CHECK_INTERVAL = 2000; // Kiểm tra mỗi 2 giây
    const MAX_WAIT_TIME = 30000; // Đợi tối đa 30 giây

    // ====== HÀM UTILITY ======

    // Lưu trữ Set-Cookie headers
    let capturedSetCookies = [];
    let lastResponseHeaders = null;

    // Intercept fetch để lấy Set-Cookie headers
    const originalFetch = window.fetch;
    window.fetch = async function(...args) {
        const response = await originalFetch(...args);
        
        // Clone response để đọc headers
        const clonedResponse = response.clone();
        
        // Lấy Set-Cookie từ headers (nếu có)
        const setCookie = clonedResponse.headers.get('set-cookie');
        if (setCookie) {
            console.log('[Nojima] Phát hiện Set-Cookie header:', setCookie);
            capturedSetCookies.push({
                url: args[0],
                timestamp: new Date().toISOString(),
                setCookie: setCookie
            });
        }
        
        // Lưu headers
        lastResponseHeaders = Array.from(clonedResponse.headers.entries());
        
        return response;
    };

    // Intercept XMLHttpRequest để lấy Set-Cookie
    const originalXHROpen = XMLHttpRequest.prototype.open;
    const originalXHRSend = XMLHttpRequest.prototype.send;
    
    XMLHttpRequest.prototype.open = function(...args) {
        this._url = args[1];
        return originalXHROpen.apply(this, args);
    };
    
    XMLHttpRequest.prototype.send = function(...args) {
        this.addEventListener('load', function() {
            const setCookie = this.getResponseHeader('set-cookie');
            if (setCookie) {
                console.log('[Nojima] XHR Set-Cookie:', setCookie);
                capturedSetCookies.push({
                    url: this._url,
                    timestamp: new Date().toISOString(),
                    setCookie: setCookie
                });
            }
        });
        return originalXHRSend.apply(this, args);
    };

    // Lấy tất cả cookies hiện tại
    function getAllCookies() {
        const cookies = document.cookie.split(';').map(cookie => {
            const [name, ...rest] = cookie.trim().split('=');
            return {
                name: name,
                value: rest.join('=')
            };
        });
        return cookies;
    }

    // Lấy cookie cụ thể
    function getCookie(name) {
        const value = `; ${document.cookie}`;
        const parts = value.split(`; ${name}=`);
        if (parts.length === 2) return parts.pop().split(';').shift();
        return null;
    }

    // Parse Set-Cookie header thành array
    function parseSetCookieHeader(setCookieString) {
        if (!setCookieString) return [];
        
        // Split by comma nhưng chú ý không split trong expires date
        const cookies = [];
        let current = '';
        let inExpires = false;
        
        for (let i = 0; i < setCookieString.length; i++) {
            const char = setCookieString[i];
            
            if (char === ',' && !inExpires) {
                if (current.trim()) {
                    cookies.push(current.trim());
                }
                current = '';
            } else {
                current += char;
                if (setCookieString.substr(i, 8).toLowerCase() === 'expires=') {
                    inExpires = true;
                }
                if (char === ';') {
                    inExpires = false;
                }
            }
        }
        
        if (current.trim()) {
            cookies.push(current.trim());
        }
        
        return cookies;
    }

    // Kiểm tra có phải trang hợp lệ không (không bị redirect)
    function isValidPage() {
        const currentUrl = window.location.href;
        const isMypage = currentUrl.includes('/mypage/mypage'); // Bỏ /app/ để match cả /sp/app/mypage
        const isCart = currentUrl.includes('/sp/app/cart/cart');

        // Kiểm tra xem có bị redirect về login không
        if (currentUrl.includes('/login')) {
            console.log('[Nojima] Bị redirect về login - cookies không hợp lệ');
            return false;
        }

        // Kiểm tra xem có bị redirect về error không
        if (currentUrl.includes('/error')) {
            console.log('[Nojima] Bị redirect về error');
            return false;
        }

        // Nếu là mypage (cả desktop /app/ và mobile /sp/app/)
        if (isMypage) {
            const pageType = currentUrl.includes('/sp/') ? 'mypage (mobile)' : 'mypage (desktop)';
            console.log(`[Nojima] Đang ở trang ${pageType}`);
            
            // Kiểm tra có element đặc trưng
            const mypageElements = document.querySelector('[class*="mypage"], [id*="mypage"], .member-info, .user-info, body');
            
            // Hoặc kiểm tra title
            const titleCheck = document.title.includes('マイページ') || 
                              document.title.includes('mypage') || 
                              document.title.toLowerCase().includes('my page');
            
            return mypageElements !== null || titleCheck;
        }

        // Nếu là cart
        if (isCart) {
            console.log('[Nojima] Đang ở trang cart');
            const cartElements = document.querySelector('.cart-list, .cart-item, [class*="cart"], body');
            return cartElements !== null;
        }

        return false;
    }

    // Gửi cookies về server
    function sendCookiesToServer() {
        const cookies = getAllCookies();

        // Lấy các cookies quan trọng
        const importantCookies = {
            '_abck': getCookie('_abck'),
            'JSESSIONID': getCookie('JSESSIONID'),
            'bm_sz': getCookie('bm_sz'),
            'bm_sv': getCookie('bm_sv'),
            'bm_mi': getCookie('bm_mi')
        };

        // Parse Set-Cookie headers đã capture
        const parsedSetCookies = [];
        capturedSetCookies.forEach(item => {
            const parsed = parseSetCookieHeader(item.setCookie);
            parsed.forEach(cookie => {
                parsedSetCookies.push({
                    url: item.url,
                    timestamp: item.timestamp,
                    rawCookie: cookie,
                    // Parse name=value
                    name: cookie.split('=')[0],
                    value: cookie.split('=').slice(1).join('=').split(';')[0]
                });
            });
        });

        const data = {
            timestamp: new Date().toISOString(),
            url: window.location.href,
            cookies: cookies,
            importantCookies: importantCookies,
            userAgent: navigator.userAgent,
            cookieString: document.cookie,
            // Thêm Set-Cookie headers
            setCookieHeaders: capturedSetCookies,
            parsedSetCookies: parsedSetCookies,
            lastResponseHeaders: lastResponseHeaders
        };

        console.log('[Nojima] Đang gửi cookies về server (có Set-Cookie headers)...', data);

        // Gửi bằng GM_xmlhttpRequest (bypass CORS)
        GM_xmlhttpRequest({
            method: 'POST',
            url: SERVER_URL,
            headers: {
                'Content-Type': 'application/json'
            },
            data: JSON.stringify(data),
            onload: function(response) {
                if (response.status === 200) {
                    console.log('[Nojima] ✅ Đã gửi cookies thành công!');
                    console.log('[Nojima] Response:', response.responseText);

                    // Hiển thị thông báo trên trang
                    showNotification('✅ Cookies đã được gửi về server!', 'success');

                    // Lưu timestamp để tránh gửi lại quá nhanh
                    GM_setValue('lastSentTime', Date.now());
                } else {
                    console.error('[Nojima] ❌ Lỗi khi gửi cookies:', response.status, response.statusText);
                    showNotification('❌ Lỗi khi gửi cookies: ' + response.status, 'error');
                }
            },
            onerror: function(error) {
                console.error('[Nojima] ❌ Không thể kết nối đến server:', error);
                showNotification('❌ Không thể kết nối đến server local!', 'error');
            }
        });
    }

    // Hiển thị thông báo trên trang
    function showNotification(message, type = 'info') {
        // Tạo element notification
        const notification = document.createElement('div');
        notification.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            padding: 15px 20px;
            background-color: ${type === 'success' ? '#4CAF50' : type === 'error' ? '#f44336' : '#2196F3'};
            color: white;
            border-radius: 5px;
            box-shadow: 0 4px 6px rgba(0,0,0,0.1);
            z-index: 999999;
            font-family: Arial, sans-serif;
            font-size: 14px;
            max-width: 300px;
            animation: slideIn 0.3s ease-out;
        `;
        notification.textContent = message;

        // Thêm animation
        const style = document.createElement('style');
        style.textContent = `
            @keyframes slideIn {
                from {
                    transform: translateX(400px);
                    opacity: 0;
                }
                to {
                    transform: translateX(0);
                    opacity: 1;
                }
            }
        `;
        document.head.appendChild(style);

        document.body.appendChild(notification);

        // Tự động xóa sau 5 giây
        setTimeout(() => {
            notification.style.animation = 'slideOut 0.3s ease-out';
            setTimeout(() => notification.remove(), 300);
        }, 5000);
    }

    // ====== MAIN LOGIC ======

    function main() {
        console.log('[Nojima] Script đã load!');
        console.log('[Nojima] URL hiện tại:', window.location.href);

        // Kiểm tra xem đã gửi gần đây chưa (tránh spam)
        const lastSentTime = GM_getValue('lastSentTime', 0);
        const timeSinceLastSent = Date.now() - lastSentTime;

        if (timeSinceLastSent < 10000) { // 10 giây
            console.log('[Nojima] Vừa mới gửi cookies, bỏ qua lần này');
            showNotification('ℹ️ Vừa mới gửi cookies rồi', 'info');
            return;
        }

        let attempts = 0;
        const maxAttempts = MAX_WAIT_TIME / CHECK_INTERVAL;

        showNotification('⏳ Đang kiểm tra trang...', 'info');

        // Đợi và kiểm tra trang có load đầy đủ không
        const checkInterval = setInterval(() => {
            attempts++;

            console.log(`[Nojima] Kiểm tra lần ${attempts}/${maxAttempts}...`);

            if (isValidPage()) {
                console.log('[Nojima] ✅ Trang đã load thành công!');
                clearInterval(checkInterval);

                // Đợi thêm 2 giây để chắc chắn
                setTimeout(() => {
                    sendCookiesToServer();
                }, 2000);

            } else if (attempts >= maxAttempts) {
                console.log('[Nojima] ⏱️ Timeout - trang không hợp lệ hoặc bị redirect');
                clearInterval(checkInterval);
                showNotification('⚠️ Không thể xác nhận trang', 'error');
            }
        }, CHECK_INTERVAL);
    }

    // Chạy khi DOM ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', main);
    } else {
        main();
    }

})();