Insert dungeon run time after the key count
当前为
// ==UserScript==
// @name Insert dungeon run time
// @namespace http://tampermonkey.net/
// @version 2025-11-27
// @description Insert dungeon run time after the key count
// @license MIT
// @author sentientmilk
// @match https://www.milkywayidle.com/*
// @icon https://www.milkywayidle.com/favicon.svg
// @grant unsafeWindow
// @run-at document-start
// ==/UserScript==
/*
Changelog
=========
v2025-11-26
- Initial version
v2025-11-26-1
- FIXED: Did not add time after the run
v2025-11-26-2
- FIXED: Selecting messages from other chats
v2025-11-27
- FIXED: 29m 60s
TODO
====================
*/
/*
Test by running in the console:
partyTabI = Array.from(document.querySelectorAll(`.Chat_tabsComponentContainer__3ZoKe .MuiButtonBase-root`)).findIndex((el) => el.textContent.includes("Party"));
d = (new Date()).toISOString();
handle({ type: "chat_message_received", message: { isSystemMessage: true, "chan": "/chat_channel_types/party", m: "systemChatMessage.partyKeyCount", t: d }});
document.querySelector(`.TabPanel_tabPanel__tXMJF:nth-child(${partyTabI + 1}) .ChatHistory_chatHistory__1EiG3`).insertAdjacentHTML("beforeend", `<div class="ChatMessage_chatMessage__2wev4 ChatMessage_systemMessage__3Jz9e"><span class="ChatMessage_timestamp__1iRZO">[${d}] </span><span>Key counts: test </div>`);
*/
(function() {
async function waitFnRepeatedFor (cond, callback) {
let notified = false;
return new Promise((resolve) => {
function check () {
const r = cond();
setTimeout(check, 1000/30); // Schedule first to allow the callback to throw
if (r && !notified) {
notified = true;
resolve();
if (callback) {
callback();
}
} else if (r && notified) {
// Skip, wait for cond to be false again
} else {
notified = false;
}
}
check();
});
}
let keyMessages = [];
function isOfInterest (message) {
/*
Example messages of interest:
{
"id": 46049453,
"chan": "/chat_channel_types/party",
"t": "2025-11-25T21:27:28.962922208Z",
"cId": 0,
"isSystemMessage": true,
"m": "systemChatMessage.partyBattleStarted",
"systemMetadata": "{\"actionHrid\":\"/actions/combat/enchanted_fortress\"}"
}
{
"id": 46049454,
"chan": "/chat_channel_types/party",
"t": "2025-11-25T21:27:28.971510704Z",
"cId": 0,
"isSystemMessage": true,
"m": "systemChatMessage.partyKeyCount",
"systemMetadata": "{\"keyCountString\":\"[OmegaShitsLurpa - 167] [sentientmilk - 216] [Kiyuwu - 72] [Metzli - 198] [Tank - 274] \"}"
}
*/
return message.chan == "/chat_channel_types/party"
&& message.isSystemMessage == true
&& (message.m == "systemChatMessage.partyBattleStarted" || message.m == "systemChatMessage.partyKeyCount");
}
function addDungeonRunTimes () {
if (!isPartySelected()) {
return;
}
const partyTabI = Array.from(document.querySelectorAll(`.Chat_tabsComponentContainer__3ZoKe .MuiButtonBase-root`)).findIndex((el) => el.textContent.includes("Party"));
const times = keyMessages.map((m, i, ms) => {
if (i == 0) {
return "first";
}
const p = ms[i-1];
if (m.m == "systemChatMessage.partyBattleStarted") {
return "start";
}
if (p.m == "systemChatMessage.partyBattleStarted") {
return "start-keys";
}
if (m.m == "systemChatMessage.partyKeyCount" && p.m == "systemChatMessage.partyKeyCount") {
const d = (+new Date(m.t)) - (+new Date(p.t));
return Math.floor(d/1000/60) + "m " + Math.floor(d/1000 % 60) + "s";
}
}).reverse();
const systemMessagesEls = Array.from(document.querySelectorAll(`.TabPanel_tabPanel__tXMJF:nth-child(${partyTabI + 1}) .ChatHistory_chatHistory__1EiG3 > .ChatMessage_systemMessage__3Jz9e`))
.filter((el) => el.textContent.includes("Key counts:") || el.textContent.includes("Battle started:"));
systemMessagesEls.reverse().forEach((el, i) => {
const t = times[i];
if (["first", "start", "start-keys"].includes(t)) {
return;
}
if (el.querySelector(".userscript-idrt")) {
return;
}
el.insertAdjacentHTML("beforeend", `<span class="userscript-idrt" style="color: orange"> ${t}</span>`);
});
}
function handle (message) {
if (message.type == "init_character_data") {
message.partyChatHistory.forEach((message2) => {
if (isOfInterest(message2)) {
keyMessages.push(message2);
}
});
}
if (message.type == "chat_message_received" && isOfInterest(message.message)) {
keyMessages.push(message.message);
setTimeout(addDungeonRunTimes, 100);
}
}
unsafeWindow.handle = handle;
const OriginalWebSocket = unsafeWindow.WebSocket;
const WrappedWebSocket = function (...args) {
const ws = new OriginalWebSocket(...args)
ws.addEventListener("message", function (e) {
const message = JSON.parse(e.data);
handle(message);
})
return ws;
};
unsafeWindow.WebSocket = WrappedWebSocket;
function isPartySelected () {
const selectedTabEl = document.querySelector(`.Chat_tabsComponentContainer__3ZoKe .MuiButtonBase-root[aria-selected="true"]`)
return selectedTabEl && selectedTabEl.textContent.includes("Party");
}
waitFnRepeatedFor(isPartySelected, addDungeonRunTimes);
})();