// ==UserScript== // @name CAI Unlisted Interactions // @namespace Violentmonkey Scripts // @match https://beta.character.ai/chat* // @grant none // @license MIT // @version 1.0 // @author A. Nonymous // @description View the interaction count of unlisted characters // @downloadURL https://update.greasyfork.icu/scripts/462589/CAI%20Unlisted%20Interactions.user.js // @updateURL https://update.greasyfork.icu/scripts/462589/CAI%20Unlisted%20Interactions.meta.js // ==/UserScript== 'use strict'; const CHARACTER_INFO_ENDPOINT = 'https://beta.character.ai/chat/character/info'; const INTERACTION_ICON = ' ' // Format the interaction count const formatInteractions = (count) => { if (count < 1000) { return count; } else if (count < 1000000) { return (count / 1000).toFixed(1).toString() + ' k'; } return (count / 1000000).toFixed(1).toString() + ' m'; }; // Display the interaction count at the top of the chat const displayInteractions = (count) => { let interactions = formatInteractions(count); let titleElements = document.getElementsByClassName('chattitle'); const tryAppend = () => { let titleElement = titleElements[0]; if (!titleElement) { // Probably should use mutation observers setTimeout(tryAppend, 500); return; } // Assemble the interaction counter let countSpan = document.createElement('span'); countSpan.className = 'text-secondary'; countSpan.innerHTML = INTERACTION_ICON; countSpan.appendChild(document.createTextNode(interactions)); countSpan.style.cssText = 'font-weight:400;font-size:12px;'; // Append it titleElement.appendChild(countSpan); }; tryAppend(); }; (() => { let originalOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url, async) { // Intercept requests to the character info endpoint if (url.startsWith(CHARACTER_INFO_ENDPOINT)) { this.addEventListener('load', () => { // Parse the character info and display an interaction counter if // the character is unlisted. let info = JSON.parse(this.responseText); if (info.character.visibility === 'UNLISTED') { displayInteractions(info.character.participant__num_interactions); } }); } originalOpen.apply(this, [method, url, async]); }; })();