// ==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'
);
}
})();