Popmundo chat

Adds instant public chat boxes to locales, cities, social clubs and the community page

目前為 2021-08-25 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Popmundo chat
// @namespace    bheuv.dev
// @version      1.2
// @description  Adds instant public chat boxes to locales, cities, social clubs and the community page
// @author       Ian Parsons (105997)
// @match        https://*.popmundo.com/*
// @icon         https://www.google.com/s2/favicons?domain=popmundo.com
// @run-at       document-end
// @noframes
// ==/UserScript==

const version = '1.2';
const hostOrigin = "https://botmundo.bheuv.dev:3005";

(function() {
    'use strict';

    let parseCharacterData = function() {
        // This must be done to make the authenticated character known to the script
        try {
            if (window.location.href.indexOf('/ChooseCharacter') !== -1) {
                // The select character page discloses the character ids
                let content = document.getElementById('ppm-content');
                let buttons = content.querySelectorAll('input[type="submit"]');
                let characterMap = [];
    
                for (let i = 0, len = buttons.length; i < len; i++) {
                    let id = buttons[i].parentNode.parentNode.querySelector("div.idHolder").innerText;
                    let name = buttons[i].parentNode.parentNode.querySelector("h2 a").innerText;
                    characterMap[i] = id + ':' + name;
                }
    
                // Store the data for use on other pages
                window.localStorage.setItem('characterMap', characterMap.join(','));
            } else {
                let characterMap = window.localStorage.getItem('characterMap');
    
                if (! characterMap) {
                    // Character map is not available; cannot run the script
                    throw "Character map is unavailable!";
                } else {
                    characterMap = characterMap.split(',');
                }
    
                let dropdown = document.querySelector('#character-tools-character select');
    
                // Select all option elements in the dropdown
                let options = dropdown.querySelectorAll('option');
    
                if (characterMap.length > 0) {
                    if ((characterMap.length + 1) !== options.length) {
                        alert('Botmundo could not detect which character you are logged in as. Going to the character select page or logging out and back in may help to solve this problem.');
                    } else {
                        let temp = {};
    
                        for (let i = 0, len = characterMap.length; i < len; i++) {
                            let name = btoa(characterMap[i].split(':')[1]);
                            let id = characterMap[i].split(':')[0];
    
                            temp[name] = id;
                        }
    
                        characterMap = temp;
                    }
                }
    
                // Set attribute on each option
                for (let i = 0, len = options.length; i < len; i++) {
                    options[i].setAttribute('data-id', characterMap[btoa(options[i].innerHTML)]);
                }
    
                // Now find the authenticated character's id and attach it as data to the document body
                let selectedOption = dropdown.querySelector('option[selected]');
                let selectedValue = selectedOption.getAttribute('data-id');
    
                if (selectedValue && selectedValue !== 'undefined') {
                    document.body.dataset.character_name = selectedOption.innerText;
                    document.body.dataset.character_id = selectedValue;
                } else {
                    throw "Failed to parse character data from character select box!";
                }
            }
        } catch (e) {
            console.log("CharacterMap could not be found/built: " + e);
        }
    }

    if (! document.querySelector('body').dataset.character_id) {
        parseCharacterData();
    }
    
    const characterName = document.body.dataset.character_name;
    const characterIdentifier = document.body.dataset.character_id;

    const addStyle = function(style) {
        const styleEl = document.createElement('style');
        styleEl.textContent = style;
        document.head.append(styleEl);
    }
    
    // Resize property doesn't work on iframes in firefox - this is a workaround
    addStyle(`
        .resizer { 
            display:flex;
            margin:0;
            padding:0;
            resize:vertical;
            overflow:hidden 
        } 
        .resizer > .resized {
             flex-grow:1;
             margin:0;
             padding:0;
             border:0
        }
    `);

    const createChatBox = function(resourceType, resourceIdentifier, characterIdentifier, characterName, mountCallback, chatTitle)
    {
        if (!chatTitle) {
            chatTitle = 'Botmundo Chat';
        }

        const wrapper = document.createElement('div');
        wrapper.classList.add('box');
        wrapper.innerHTML = `<h2>${chatTitle}</h2>`;
        
        const resizer = document.createElement('div');
        resizer.classList.add('resizer');
        resizer.style.height = '400px';
        resizer.style.minHeight = '400px';

        const chatbox = document.createElement('iframe');
        chatbox.src = hostOrigin + '/chat.html';
        chatbox.style.border = '0';
        chatbox.style.width = '100%';
        chatbox.classList.add('resized');

        resizer.appendChild(chatbox);
        wrapper.appendChild(resizer);

        mountCallback(wrapper);

        const style = getComputedStyle(chatbox);

        chatbox.addEventListener('load', function() {
            

            this.contentWindow.postMessage({
                message: 'connect',
                character: {
                    identifier: characterIdentifier,
                    name: characterName
                },
                resource: {
                    identifier: resourceIdentifier,
                    type: resourceType
                },
                style: {
                    background: style.backgroundColor,
                    color: style.color
                },
                script: {
                    version: version
                }
            }, hostOrigin);
        });
        
        return wrapper;
    }

    if (document.querySelector('div.localeLogo')) {
        // Locale page
        const localeIdentifier = parseInt(document.querySelector('div.localeLogo .idHolder').innerText);
        createChatBox(
            'locale', 
            localeIdentifier, 
            characterIdentifier, 
            characterName, 
            (el) => { 
                document.querySelector("#ppm-content h1").insertAdjacentElement('afterend', el);
            },
            document.title.split(' - ')[1] + ' Chat'
        );
    }
    else if (document.location.href.endsWith('/World/Popmundo.aspx')) {
        // Community news / Welcome page
        createChatBox(
            'community', 
            0, 
            characterIdentifier, 
            characterName, 
            (el) => { 
                document.querySelector("#ctl00_cphLeftColumn_ctl00_divDefaultGreeting").insertAdjacentElement('afterend', el); 
            },
            'Global Chat'
        );
    } else if (document.querySelector("#ctl00_cphLeftColumn_ctl00_pnlCalendar")) {
        // City page
        const cityIdentifier = document.querySelector("#ctl00_cphRightColumn_ctl01_ddlCities").value;
        createChatBox(
            'city', 
            cityIdentifier, 
            characterIdentifier, 
            characterName, 
            (el) => {
                document.querySelector("#ppm-content h1").insertAdjacentElement('afterend', el)
            },
            document.title.split(' - ')[1] + ' Chat'
        );
    } else if (/SocialClub\/[0-9]+$/.test(document.location.href)) {
        // Social club
        const clubIdentifier = document.querySelector(".idHolder").innerText;

        createChatBox(
            'club', 
            clubIdentifier, 
            characterIdentifier, 
            characterName, 
            (el) => {
                document.querySelector("#ppm-content h1").insertAdjacentElement('afterend', el)
            },
            document.querySelector("#ppm-content h1").innerText + ' Chat'
        );
    }
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址