// ==UserScript==
// @name        魔灯
// @namespace   Scripts
// @match       *://test2.adsdesk.cn/*
// @match       *://pre.adsdesk.cn/*
// @grant       none
// @version     1.0
// @author      mobvista
// @require     https://cdn.jsdelivr.net/npm/js-cookie@3.0.5/dist/js.cookie.min.js
// @require     https://cdn.jsdelivr.net/npm/watermark-package@2.1.2/dist/watermark.umd.min.js
// @description 2023/12/6 13:42:17
// ==/UserScript==
// noinspection JSUnresolvedReference

// 开启调试模式, 此模式会输出详尽日志
const debugMode = 1

const DOMAIN = '.adsdesk.cn'

const K_UC = 'uniqueCode'
const K_USER = 'user'
const K_TOKEN = 'token'

// 定时器ID
let watermarkTimerId
let logoutTimerId

(function () {
    'use strict';

    function start() {
        L('start 执行开始')

        let authToken = getQueryVariable('authToken');
        // 新登录
        if (authToken) {
            L('匹配到authToken, 准备执行登录. decodeAuthToken: ' + decodeURIComponent(authToken))

            const authData = JSON.parse(decodeURIComponent(authToken))

            Cookies.set(CN(K_UC), authData[K_UC])
            Cookies.set(CN(K_USER), authData[K_USER])
            modeng(authData[K_TOKEN], authData[K_UC])
        }

        // 已登录
        if (Cookies.get(CN(K_USER))) {
            L('匹配到模登用户, 准备添加监控. K_USER: ' + Cookies.get(CN(K_USER)))
            watermarkTimerId = setInterval( addWatermark, 1000)
            // 添加登出监控
            logoutTimerId = setInterval(addLogoutListener, 500)
            // 添加请求监控
            setTimeout(addRequestListener, 10)
        }
        L('start 执行完成')
    }

    start()
})()

function modeng(token, code) {
    // 如果未设置标识, 则先
    const flag = Cookies.get(code)
    if (flag === undefined) {
        Cookies.set(code, '1')
    }

    if (Cookies.get(code) === '1') {

        Cookies.set(K_TOKEN, token)
        Cookies.set(K_TOKEN, token, {domain: DOMAIN})

        // 1分钟后删除
        Cookies.set(code, '0', {
            expires: new Date(new Date().getTime() + 60000)
        })
        location.reload();
    }
}

// 添加水印
function addWatermark() {
    watermark.setWaterMark(
        {
            w_texts: ['模拟环境[' + Cookies.get(CN(K_USER)) + ']' + getNowTime()],
            w_options: {
                w_width: 310,
                w_height: 160,
                w_opacity: '0.21'
            }
        }
    )

    // 第一次时候会报错
    try {
        watermark.removeWatermark()
    } catch (e) {
    }
}

// 登录监控
function addLogoutListener() {
    // L('登出监控. K_TOKEN: ' + Cookies.get(K_TOKEN))
    // 登录凭证不存在了, 只有2种可能, 1:登录; 2:清理缓存, 此时需要把modeng信息清理掉
    if (!Cookies.get(K_TOKEN)) {
        L('登录操作, 清理modeng')
        Cookies.remove(CN(K_UC))
        Cookies.remove(CN(K_USER))

        watermark.removeWatermark()
        clearInterval(watermarkTimerId)
        clearInterval(logoutTimerId)
    }
}

const REQ_LOG_SAVE_URL = '/openapi/request_log/save'

// 请求监控
function addRequestListener() {
    L('添加请求监控')
    window.addEventListener('ajaxReadyStateChange', function (e) {
        const xhr = e.detail;

        // 不放在onload里会执行多次3次(状态变更事件会触发3次)
        xhr.onload = function () {
            L('触发请求监控')
            console.log('Request URL:', xhr.orignUrl);
            // console.log('Request Body:', xhr.body);
            // console.log('Response Body:', xhr.response);

            const optUser = Cookies.get(CN(K_USER))
            L("optUser: " + optUser)
            if (optUser) {
                const requestUrl = validUrl(xhr.orignUrl);
                L("requestUrl: " + requestUrl)
                if (requestUrl) {
                    const param = {
                        optUser,
                        'uniqueCode': Cookies.get(CN(K_UC)),
                        "authToken": '',
                        requestUrl,
                        "requestMethod": xhr.method,
                        "requestBody": xhr.body,
                        "responseCode": xhr.status,
                        "responseBody": xhr.response
                    }
                    sendLog(param)
                }
            }
        }
    })
}

// 发送日志
function sendLog(param) {
    const httpRequest = new XMLHttpRequest();
    // const sendLogUrl = (debugMode ? 'http://localhost/dev-api' : 'https://oms-api.adsdesk.cn') + REQ_LOG_SAVE_URL
    // 临时能调用的地址
    const sendLogUrl = 'https://oms-api.adsdesk.cn/openapi/adsdesk/request_log/save'
    httpRequest.open('POST', sendLogUrl, true);
    httpRequest.setRequestHeader("Content-type", "application/json");
    httpRequest.send(JSON.stringify(param));
}

//region 工具函数封装
function getQueryVariable(variable) {
    const query = window.location.search.substring(1)
    const vars = query.split("&")
    for (let i = 0; i < vars.length; i++) {
        const pair = vars[i].split("=")
        if (pair[0] === variable) {
            return pair[1]
        }
    }
    return false
}

function validUrl(fullUrl) {
    if (!fullUrl || fullUrl.indexOf(REQ_LOG_SAVE_URL) >= 0) {
        return false
    }
    if (fullUrl.indexOf('adsdesk.cn/adsdesk') < 0) {
        return false
    }
    fullUrl = fullUrl.replace("//", "$")
    return fullUrl.substring(fullUrl.indexOf("/") + 1);
}

function getNowTime() {
    const now = new Date();
    let year = now.getFullYear(),
        month = now.getMonth() + 1,
        date = now.getDate(),
        h = now.getHours(),
        m = now.getMinutes(),
        s = now.getSeconds()
    month = month < 10 ? '0' + month : month
    date = date < 10 ? '0' + date : date
    h = h < 10 ? '0' + h : h
    m = m < 10 ? '0' + m : m
    s = s < 10 ? '0' + s : s
    // return year + "-" + month + "-" + date + " " + h + ":" + m;
    return h + ":" + m + ":" + s;
}

function CN(name) {
    return 'modeng_' + name
}

function L(msg) {
    if (debugMode) {
        console.log(msg)
    }
}

//endregion

//region 监听HTTP请求
//(function(){})(): 表示立即执行, 注册全局代理对象(防止重写XMLHttpRequest时循环调用?)
;(function () {
    if (typeof window.CustomEvent === "function") return false;

    function CustomEvent(event, params) {
        params = params || {bubbles: false, cancelable: false, detail: undefined};
        const evt = document.createEvent('CustomEvent');
        evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
        return evt;
    }

    CustomEvent.prototype = window.Event.prototype;

    window.CustomEvent = CustomEvent;
})();
// 重写 XMLHttpRequest 全局拦截器
;(function () {
    function ajaxEventTrigger(event) {
        const ajaxEvent = new CustomEvent(event, {detail: this});
        window.dispatchEvent(ajaxEvent);
    }

    const oldXHR = window.XMLHttpRequest;

    function newXHR() {
        const realXHR = new oldXHR();

        // abort, error, load, loadstart, progress, timeout, loadend 可按需重写, 此处仅需要readystatechange
        realXHR.addEventListener('readystatechange', function () {
            ajaxEventTrigger.call(this, 'ajaxReadyStateChange');
        }, false);

        let send = realXHR.send;
        realXHR.send = function (...arg) {
            send.apply(realXHR, arg);
            realXHR.body = arg[0];
            ajaxEventTrigger.call(realXHR, 'ajaxSend');
        }

        let open = realXHR.open;
        realXHR.open = function (...arg) {
            open.apply(realXHR, arg)
            realXHR.method = arg[0];
            realXHR.orignUrl = arg[1];
            realXHR.async = arg[2];
            ajaxEventTrigger.call(realXHR, 'ajaxOpen');
        }

        let setRequestHeader = realXHR.setRequestHeader;
        realXHR.requestHeader = {};
        realXHR.setRequestHeader = function (name, value) {
            realXHR.requestHeader[name] = value;
            setRequestHeader.call(realXHR, name, value)
        }
        return realXHR;
    }

    window.XMLHttpRequest = newXHR;
})();
//endregion