I created something, what do you think?



P.S: This is stored locally and only works with TamperMonkey (and GreaseMonkey + forks probably).
// ==UserScript==
// @name BitcoinTalk User Notes
// @version 0.1
// @description Adds an note field to each user on BitcoinTalk
// @author TryNinja
// @match https://bitcointalk.org/index.php?topic=*
// @match https://bitcointalk.org/index.php?action=profile;u=*
// @icon https://www.google.com/s2/favicons?sz=64&domain=bitcointalk.org
// @grant GM_setValue
// @grant GM_getValue
// ==/UserScript==
(async function() {
'use strict';
const getParentNodeNth = (element, num) => {
let parent = element;
for (let i = 0; i < num; i++) {
if (parent.parentNode) {
parent = parent.parentNode;
}
}
return parent;
};
const getUserNote = async (user) => {
const notes = JSON.parse(await GM_getValue('notes') ?? {});
if (!notes) {
return null;
}
return notes[user];
};
const setUserNote = async (user, note) => {
const notes = JSON.parse(await GM_getValue('notes') ?? {});
notes[user] = note;
await GM_setValue('notes', JSON.stringify(notes));
}
const texts = {
addNote: `<span style="cursor: pointer; font-weight: bold">📜 Add Note</a>`,
withNote: note => `<span style="cursor: pointer; font-weight: bold"><b>📜</b> ${note}</span>`
};
const addNote = async (user, element) => {
const note = prompt('Input the note (empty to remove):');
await setUserNote(user, note);
if (note) {
element.innerHTML = texts.withNote(note);
} else {
element.innerHTML = texts.addNote;
}
}
if (window.location.href.match(/topic=\d+/)) {
const targets = [...document.querySelectorAll('td.poster_info div a:last-child')].filter(e => window.getComputedStyle(getParentNodeNth(e, 11)).display !== 'none');
await Promise.allSettled(targets.map(async target => {
const [_, userId] = [...target.parentNode.parentNode.childNodes].find(childNode => childNode.innerHTML).innerHTML.match(/u=(\d+)/);
const noteDiv = document.createElement("div");
const note = await getUserNote(userId);
if (!note) {
noteDiv.innerHTML = texts.addNote;
} else {
noteDiv.innerHTML = texts.withNote(note);
}
target.before(noteDiv);
noteDiv.addEventListener("click", () => addNote(userId, noteDiv), false);
}));
} else if (window.location.href.match(/profile;u=\d+/)) {
const [_, userId] = window.location.href.match(/u=(\d+)/);
const target = getParentNodeNth(document.querySelector("#bodyarea table tr td tbody tr:nth-child(2) tr:last-child").parentNode, 1);
const noteDiv = document.createElement("tr");
const note = await getUserNote(userId);
if (!note) {
noteDiv.innerHTML = texts.addNote;
} else {
noteDiv.innerHTML = texts.withNote(note);
}
target.before(noteDiv);
noteDiv.addEventListener("click", () => addNote(userId, noteDiv), false);
}
})();