Skip to content

Instantly share code, notes, and snippets.

@kurojifusky
Created July 12, 2024 00:12
Show Gist options
  • Save kurojifusky/0a8e8c737630dbe558467a3f33775124 to your computer and use it in GitHub Desktop.
Save kurojifusky/0a8e8c737630dbe558467a3f33775124 to your computer and use it in GitHub Desktop.
A browser snippet for compiling a chat session - first draft
(() => {
// chat extractor
"use strict";
const __d = document;
/******************************************************************
* Helper functions
****************************************************************** */
const _forceArray = (e) => Array.from(e);
const _pick = (selector, target = __d) => target.querySelector(selector);
const _pickAll = (target = __d, selector, callback) => {
const domContents = target.querySelectorAll(selector);
if (!callback) return _forceArray(domContents);
let _protected$acc = [];
domContents.forEach((element, index) => {
_protected$acc.push(callback(element, _protected$acc, index));
});
return _protected$acc;
};
const _sanitizeStr = (str) => {
// Sometimes, the AI does some weird things to work around the
// tokenization limit, which is 2048 tokens for Character.AI
return str.replace("…", "...");
};
const _dialogParser = (paragraphNodes) => {
const nodeChildren = paragraphNodes.children;
if (nodeChildren.length > 1) {
// Iterate every <p> nodes available
const iteratedNodes = _forceArray(nodeChildren).map((node) => {
const nodeStr = node.textContent;
const nodeInnerEl = node.firstElementChild;
// Check if node has an <em> element to parse as an action indicator
if (nodeInnerEl && nodeInnerEl.tagName.toLowerCase() === "em")
return `*${nodeStr}*`;
return _sanitizeStr(nodeStr);
});
return iteratedNodes.join("\n");
}
return _sanitizeStr(paragraphNodes.textContent);
};
/******************************************************************
* Entry point
****************************************************************** */
const chatContainer = _pick("main.flex-1");
const chatMsgs = _pickAll(chatContainer, "div.group.relative", (e) => {
const chatNode = _pick("div.m-0.flex", e);
const isAIRecipient = _pick("div.rounded-2xl.text-sm", chatNode);
const chatRecipient = _pick(".text-small", chatNode);
const messageContent = _pick(".prose", chatNode);
return {
_recipent: chatRecipient.textContent,
content: _dialogParser(messageContent),
isAIRecipient: Boolean(isAIRecipient),
};
});
// All you have to do is, right-click, then click "Copy Object" and you're done lol
console.log(chatMsgs.reverse());
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment