Greasy Fork

Greasy Fork is available in English.

摸鱼派聊天室

摸鱼派聊天室,防撤回、抢红包、自动清屏、一言、机器人聊天、自动+1、悬浮查看图片

当前为 2021-12-30 提交的版本,查看 最新版本

// ==UserScript==
// @name   摸鱼派聊天室
// @namespace    https://lemon-cxh.github.io/
// @version      1.8
// @description  摸鱼派聊天室,防撤回、抢红包、自动清屏、一言、机器人聊天、自动+1、悬浮查看图片
// @author       Lemon
// @match        https://pwl.icu/cr
// @icon         https://www.google.com/s2/favicons?domain=pwl.icu
// @connect      v1.hitokoto.cn
// @run-at       document-start
// @grant        unsafeWindow
// @grant        GM_xmlhttpRequest
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    const OPEN_PACKET_URL = 'https://pwl.icu/chat-room/red-packet/open';
    const HISTORY_MESSAGE_URL = 'https://pwl.icu/chat-room/more';
    const HITOKOTO_URL = 'https://v1.hitokoto.cn/?c=e&c=f&c=j';

    const REVOKE_ID = 'revokeCheckbox';
    var revokeEnable = false;
    const PLUS_ONE_ID = 'pulsOne';
    var plusOneEnable = false;
    var previousMessage = '';
    var previousPlusOneMessage = '';
    var redPacketAlertEnable = false;

    const MESSAGE_MAX = 30;
    var messageCount = 0;

    unsafeWindow.redPacketMap = new Map();

    function webSocketHook() {
        unsafeWindow.WebSocket = new Proxy(unsafeWindow.WebSocket, {
            construct(target, args) {
                let obj = new target(...args);
                return new Proxy(obj, proxyHandler);
            }
        })
    };

    function requestSend() {
        XMLHttpRequest.prototype.mySend = XMLHttpRequest.prototype.send;
        XMLHttpRequest.prototype.send = function(data) {
            this.addEventListener('load', function() {
                if (this.responseURL === OPEN_PACKET_URL) {
                    showMoney(this.response);
                    if (!redPacketAlertEnable) {
                        unsafeWindow.Util.closeAlert();
                    }
                    return;
                }
                if (-1 !== this.responseURL.indexOf(HISTORY_MESSAGE_URL)) {
                    queryRedPacketOnHistory(this.response);
                    return;
                }
            }, false);
            this.mySend.apply(this, arguments);
        }
    }

    function addMenu() {
        addImgMouseover();
        document.onreadystatechange = function(){
            if(document.readyState == 'complete'){
                let e = document.getElementById('redPacketBtn').parentNode.children[3];
                // 防撤回
                let revoke = document.createElement("button");
                revoke.setAttribute('style', 'margin-right: 6px');
                revoke.innerHTML = '<input id="' + REVOKE_ID + '" type="checkbox"/><span>防撤回</span>';
                e.insertBefore(revoke, e.firstChild);
                document.getElementById(REVOKE_ID).addEventListener( 'change', function() {
                    revokeEnable = this.checked;
                });
                //  自动加一
                let plusOne = document.createElement("button");
                plusOne.setAttribute('style', 'margin-right: 6px');
                plusOne.innerHTML = '<input id="' + PLUS_ONE_ID + '" type="checkbox"/><span>+1</span>';
                e.insertBefore(plusOne, e.firstChild);
                plusOne = document.getElementById(PLUS_ONE_ID);
                plusOne.checked = true;
                plusOne.addEventListener( 'change', function() {
                    plusOneEnable = this.checked;
                });
                //  红包提示
                let redPacketAlert = document.createElement("button");
                redPacketAlert.setAttribute('style', 'margin-right: 6px');
                redPacketAlert.innerHTML = '<input id ="redPacketAlertCheck" type="checkbox"/><span>红包详情</span>';
                e.insertBefore(redPacketAlert, e.firstChild);
                redPacketAlert = document.getElementById('redPacketAlertCheck');
                redPacketAlert.addEventListener( 'change', function() {
                    redPacketAlertEnable = this.checked;
                });
                // 一言
                e = document.getElementById('breezemoonInput').parentNode;
                let hitokoto = document.createElement("button");
                hitokoto.innerHTML = '一言';
                hitokoto.setAttribute('class', 'green');
                e.insertBefore(hitokoto, e.lastChild.nextSibling);
                hitokoto.onclick = () => sendHitokoto();
            }
        }
    }

    let proxyHandler = {
        get(target, property) {
            let value = target[property]
            if ((typeof value) === 'function') {
                value = value.bind(target)
            }
            return value
        },
        set(target, property, value) {
            if (property === 'onmessage') {
                let realOnMessage = value;
                value = function(event) {
                    analyzeMessage(event, realOnMessage);
                }
            }
            target[property] = value
            return value
        }
    };

    //  解析消息
    function analyzeMessage(event, realOnMessage) {
        var o = JSON.parse(event.data);
        switch (o.type) {
            case 'redPacketStatus':
                delayOpenRedPacket(o);
                realOnMessage(event);
                break;
            case 'revoke':
                if (revokeEnable) {
                    preventRevoke(o.oId);
                } else {
                   realOnMessage(event);
                }
                break;
            case 'msg':
                messageCount++;
                if (isRedPacketMessage(o.content)) {
                    delayOpenRedPacket(o);
                } else {
                    chat(o);
                }
                realOnMessage(event);
                clearChatRoom();
                break;
            default:
                realOnMessage(event);
        }
    };

    //  查询历史记录是否有红包
    function queryRedPacketOnHistory(data) {
        console.log('查询历史记录中是否有未领取红包');
        let o = JSON.parse(data);
        if (!o.data) {
            return;
        }
        o.data.forEach(e => {
            if (isRedPacketMessage(e.content) && notOpenRedPacket(e.content)) {
                openRedPacket(e.oId);
                console.log('历史消息中有未领取红包');
            }
        })
    }

    //  是否是红包信息
    function isRedPacketMessage(s) {
        return -1 !== s.indexOf('"msgType":"redPacket"');
    }

    //  是否还有未打开的红包
    function notOpenRedPacket(content) {
        let o = JSON.parse(content);
        return o.got < o.count && o.who.every(e => unsafeWindow.Label.currentUserName != e.userName);
    }

    function delayOpenRedPacket(oId) {
        if (unsafeWindow.ChatRoom) {
            setTimeout(() => {
                openRedPacket(oId);
            }, 3000 + Math.round(Math.random() * 100));
        }
    }

    //  弹窗提示抢红包信息
    function showMoney(data) {
        let o = JSON.parse(data);
        let usesrMoney = -1;
        o.who.forEach(e => {
            console.log(e.userName + ' 抢到了:' + e.userMoney + '积分');
            if (e.userName === unsafeWindow.Label.currentUserName) {
                usesrMoney = e.userMoney;
            }
        });
        console.log('____________________')
        usesrMoney > -1 ? notice('抢到了:' + usesrMoney + '积分') : notice('很遗憾没有抢到红包');
    }

    //   清屏
    function clearChatRoom() {
        if (messageCount > MESSAGE_MAX) {
            document.getElementById('chats').innerHTML='';
            unsafeWindow.ChatRoom.more();
            messageCount = 0;
        }
    }

    //  防撤回
    function preventRevoke(oId) {
        let source = document.getElementById('chatroom' + oId);
        if (!source) {
            return;
        }
        let href = source.firstElementChild.getAttribute('href');
        let child = document.createElement("div");
        child.setAttribute('style', 'color: rgb(50 50 50);margin-bottom: 10px;text-align: center;');
        child.innerHTML = '<span><a href="' + href + '" target="_blank">' + href.substring(8) + '</a>想要撤回消息</span>';
        source.parentNode.insertBefore(child, source);
        messageCount--;
    }

    function addImgMouseover() {
        var chatRoom = document.getElementById('chats');
        var observe = new MutationObserver(function (mutations,observe) {
            let chats = document.getElementById('chats').querySelectorAll('.chats__item');
            chats.forEach(chat => {
                let content = chat.querySelector('.vditor-reset');
                let imgs = content.querySelectorAll('img');
                imgs.forEach(e => {
                    if ('emoji' !== e.getAttribute('class')) {
                        imgMouseover(e, 'img_' + chat.getAttribute('id'), chat);
                    }
                })
            })
        });
        observe.observe(chatRoom,{ childList: true});
    }

    function imgMouseover(e, id, chatroom) {
        e.onmouseover = () => {
            let imgCard = document.getElementById(id);
            if (imgCard) {
                imgCard.style.display = 'block';
                return;
            }
            imgCard = document.createElement("div");
            imgCard.setAttribute('id', id);
            imgCard.setAttribute('style', 'position: absolute;left: 50%;transform: translate(-50%, -50%);z-index: 999;');
            let s = e.outerHTML;
            imgCard.innerHTML = s.slice(0, 4) + ' style="max-width: 600px;max-height: 500px"' + s.slice(4);
            chatroom.appendChild(imgCard);
        }
        e.onmouseout = () => {
            let imgCard = document.getElementById(id);
            if (imgCard) {
                imgCard.style.display = 'none';
            }
        }
    }

    //   判断消息内容
    function chat(o) {
        if (plusOneEnable) {
            if (previousMessage === o.md && previousMessage !== previousPlusOneMessage) {
                sendMessage(o.md);
                previousPlusOneMessage = o.md;
            }
            previousMessage = o.md;
            return;
        }
    }

    //  发送一言
    function sendHitokoto() {
        GM_xmlhttpRequest({
            method: "GET",
            url: HITOKOTO_URL,
            onload: function(response){
                if (response.status === 200) {
                    let o = JSON.parse(response.response);
                    document.getElementById('breezemoonInput').value = o.hitokoto;
                }
            },
            onerror: function(response){
                console.log("请求失败");
            }
        });
    }

    function sendMessage(s) {
        unsafeWindow.ChatRoom.editor.setValue(s);
        unsafeWindow.ChatRoom.send();
    }

    function notice(message) {
        unsafeWindow.Util.notice("success", 1500, message);
    }

    function openRedPacket(oId) {
        unsafeWindow.ChatRoom.unpackRedPacket(oId);
    }

    webSocketHook();
    requestSend();
    addMenu();
})();