Bc DGLAB

Connects to the DGLAB via official API.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name Bc DGLAB
// @description Connects to the DGLAB via official API.
// @version Preview 4
// @namespace awaqwq_huzpsb
// @match *://*/*BondageClub*
// @grant GM_registerMenuCommand
// @license WTFPL
// ==/UserScript==

function loadScript(url, callback) {
    const script = document.createElement("script");
    script.type = "text/javascript";
    script.src = url;

    script.onload = function () {
        callback();
    };

    script.onerror = function () {
        alert("加载依赖失败,请检查网络连接!");
        window.location.reload();
    };

    document.head.appendChild(script);
}


var wsConn = null;
var connected = false;
var connectionId = null;
var targetWSId = null;

var limitA = 0;
var limitB = 0;
var nowA = 0;
var nowB = 0;

var taskEndA = 0;
var taskEndB = 0;

function sendWsMsg(messageObj) {
    messageObj.clientId = connectionId;
    messageObj.targetId = targetWSId;
    if (!messageObj.hasOwnProperty('type'))
        messageObj.type = "msg";
    wsConn.send(JSON.stringify((messageObj)));
}

function connectWs() {
    {
        const floatingImage = document.getElementById("floatingImage");
        if (floatingImage) {
            alert("请直接使用右下角的二维码连接设备!");
            return;
        }
        if (connected) {
            alert("已连接设备,请勿重复连接!");
            return;
        }
    }


    wsConn = new WebSocket("wss://ws.dungeon-lab.cn/");
    wsConn.onclose = function () {
        const floatingImage = document.getElementById("floatingImage");
        if (floatingImage) {
            floatingImage.remove();
        }
        connected = false;
        alert("连接已断开,请重新连接设备!");
    };

    wsConn.onmessage = function (event) {
        let message = null;
        try {
            message = JSON.parse(event.data);
        } catch (e) {
            console.log("收到设备回传:", event.data);
            return;
        }
        console.log("收到中继回传:", message);

        switch (message.type) {
            case 'bind':
                if (!message.targetId) {
                    connectionId = message.clientId;
                    const connectionUrl = "https://www.dungeon-lab.com/app-download.php#DGLAB-SOCKET#wss://ws.dungeon-lab.cn/" + connectionId;
                    const floatingImage = document.createElement("div");
                    floatingImage.id = "floatingImage";
                    floatingImage.style.position = "fixed";
                    floatingImage.style.width = "220px";
                    floatingImage.style.height = "220px";
                    floatingImage.style.bottom = "0";
                    floatingImage.style.right = "0";
                    floatingImage.style.zIndex = "1000";
                    floatingImage.style.backgroundColor = "darkgray";
                    document.body.appendChild(floatingImage);

                    const realImageDiv = document.createElement("div");
                    realImageDiv.style.margin = "10px";
                    realImageDiv.style.width = "200px";
                    realImageDiv.style.height = "200px";
                    floatingImage.appendChild(realImageDiv);


                    new QRCode(realImageDiv, {
                        text: connectionUrl,
                        width: 200,
                        height: 200,
                    });
                } else {
                    connected = true;
                    const floatingImage = document.getElementById("floatingImage");
                    if (floatingImage) {
                        floatingImage.remove();
                    }
                    targetWSId = message.targetId;
                }
                break;
            case 'break':
            case 'error':
                wsConn.close();
                break;
            case 'msg':
                // 定义一个空数组来存储结果
                const result = [];
                if (message.message.includes("strength")) {
                    const numbers = message.message.match(/\d+/g).map(Number);
                    result.push({type: "strength", numbers});

                    console.log("channel-a:", numbers[0]);
                    console.log("channel-b:", numbers[1]);
                    console.log("limit-a:", numbers[2]);
                    limitA = numbers[2];
                    console.log("limit-b:", numbers[3]);
                    limitB = numbers[3];
                }
                break;
            default:
                break;
        }
    };
}

const waveData = {
    "1": `["0A0A0A0A00000000","0A0A0A0A0A0A0A0A","0A0A0A0A14141414","0A0A0A0A1E1E1E1E","0A0A0A0A28282828","0A0A0A0A32323232","0A0A0A0A3C3C3C3C","0A0A0A0A46464646","0A0A0A0A50505050","0A0A0A0A5A5A5A5A","0A0A0A0A64646464"]`,
    "2": `["0A0A0A0A00000000","0D0D0D0D0F0F0F0F","101010101E1E1E1E","1313131332323232","1616161641414141","1A1A1A1A50505050","1D1D1D1D64646464","202020205A5A5A5A","2323232350505050","262626264B4B4B4B","2A2A2A2A41414141"]`,
    "3": `["4A4A4A4A64646464","4545454564646464","4040404064646464","3B3B3B3B64646464","3636363664646464","3232323264646464","2D2D2D2D64646464","2828282864646464","2323232364646464","1E1E1E1E64646464","1A1A1A1A64646464"]`
}

function setStrength(strength, channel) {
    if (!connected) {
        alert("请先连接设备!");
        return;
    }
    sendWsMsg({type: 4, message: `strength-${channel === 'A' ? 1 : 2}+2+${strength}`})
}

function play(waveId, duration, channel) {
    if (!connected) {
        alert("请先连接设备!");
        return;
    }
    const wave = waveData[waveId];
    if (!wave) {
        alert("无效的波形ID!");
        return;
    }
    sendWsMsg({type: "clientMsg", message: `${channel}:${wave}`, time: duration, channel: channel})
}


loadScript("https://cdn.bootcdn.net/ajax/libs/qrcodejs/1.0.0/qrcode.min.js", function () {
    connectWs();
});

GM_registerMenuCommand('重新连接设备', function () {
    if (wsConn) {
        wsConn.close();
    }
    connectWs();
})

function respond(msg) {
    const parts = msg.split(' ');
    if (parts[0] === '郊狼') {
        if (!connected) {
            return 'Bot故障:设备未连接。请先连接设备。';
        }
        if (parts.length < 2) {
            return '参数缺失。请输入“郊狼 帮助”查看帮助。';
        }
        const timeStamp = Math.floor(Date.now() / 1000);
        switch (parts[1]) {
            case '强度': {
                if (parts.length < 4) {
                    return '错误的语法。正确格式为“郊狼 强度 通道 数值”。';
                }
                let limit = 0;
                if (parts[2] === 'A') {
                    limit = limitA;
                } else if (parts[2] === 'B') {
                    limit = limitB;
                } else {
                    return '无效的通道。请使用“A”或“B”。';
                }
                const strength = parseInt(parts[3]);
                if (isNaN(strength) || strength < 0 || strength > limit) {
                    return `强度值必须在0到${limit}之间。`;
                }
                if (parts[2] === 'A') {
                    nowA = strength;
                } else {
                    nowB = strength;
                }
                setStrength(strength, parts[2]);
                return `已设置强度为 ${strength}。请不要忘了调整波形。`;
            }
            case '波形': {
                if (parts.length < 4) {
                    return '错误的语法。正确格式为“郊狼 波形 通道 波形ID 持续时间(秒)”。';
                }
                let now = 0;
                if (parts[2] === 'A') {
                    now = nowA;
                } else if (parts[2] === 'B') {
                    now = nowB;
                } else {
                    return '无效的通道。请使用“A”或“B”。';
                }
                if (!now) {
                    return `不能在通道强度为0时播放波形。请先设置强度。`;
                }
                const waveId = parts[3];
                if (!waveData[waveId]) {
                    return '无效的波形ID。可用波形ID:1, 2, 3。';
                }
                const duration = parseInt(parts[4]);
                if (isNaN(duration) || duration <= 0) {
                    return '持续时间必须是正整数。';
                }
                if (parts[2] === 'A') {
                    taskEndA = timeStamp + duration;
                } else if (parts[2] === 'B') {
                    taskEndB = timeStamp + duration;
                }
                play(waveId, duration, parts[2]);
                return `已在通道${parts[2]}播放波形${waveId},持续时间为${duration}秒。`;
            }
            case '状态':
                return `当前状态:\n` +
                    `通道A - 强度:${nowA},上限:${limitA},正在输出波形:${taskEndA > timeStamp ? '是' : '否'}\n` +
                    `通道B - 强度:${nowB},上限:${limitB},正在输出波形:${taskEndB > timeStamp ? '是' : '否'}`;
            case '帮助':
                return '郊狼bot命令列表:[强度] [波形] [状态] [帮助]\n' +
                    '如果你也想加入测试,请检查aw酱的bio...并不需要安装插件以外的什么东西,支持手机端。'
            default:
                return '未知命令。请输入“郊狼 帮助”查看帮助。';
        }
    }
    return null
}

ChatRoomMessageDisplay0 = ChatRoomMessageDisplay;
ChatRoomMessageDisplay = function (data, msg, SenderCharacter, metadata) {
    ChatRoomMessageDisplay0(data, msg, SenderCharacter, metadata);
    awHandleBot(SenderCharacter, msg);
}

AwBotLast = '';
awHandleBot = function (sender, message) {
    const msgAndSender = message + sender.Name;
    if (AwBotLast !== msgAndSender) {
        AwBotLast = msgAndSender;
        let response = respond(message);
        if (response) {
            ServerSend('ChatRoomChat', {
                Content: response,
                Type: 'Chat',
                Target: sender.MemberNumber,
            })
        }
    }
}

ChatRoomNotificationRaiseChatJoin = function (p) {
    ServerSend('ChatRoomChat', {
        Content: p.Name + ',你好!本房间是aw酱的郊狼bot插件测试房间,输入“郊狼 帮助”即可查看帮助。她把自己捆了,没法跟你聊天...',
        Type: 'Chat',
        Target: p.MemberNumber,
    })
    return true
}