Выглядит вот так:
Нажимаете "Add Note", появляется окно для ввода короткой заметки. Также можно нажать на "Add Note" под аватаром, то же самое, появится окошко для ввода заметки.
Сама заметка отображается под аватаром и в самом профиле пользователя
Сам скрипт
// ==UserScript==
// @name BitcoinTalk User Notes
// @version 0.2
// @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
// @grant GM_setValue
// @grant GM_getValue
// ==/UserScript==
(async function() {
'use strict';
const getValue = typeof GM_getValue === "undefined" ? GM.getValue : GM_getValue;
const setValue = typeof GM_setValue === "undefined" ? GM.setValue : GM_setValue;
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 getValue('notes') ?? '{}');
if (!notes) {
return null;
}
return notes[user];
};
const setUserNote = async (user, note) => {
const notes = JSON.parse(await getValue('notes') ?? '{}');
notes[user] = note;
await setValue('notes', JSON.stringify(notes ?? {}));
}
const texts = {
addNote: `📜 Add Note`,
withNote: note => `📜 ${note}`
};
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 if (note !== null) {
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');
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("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);
}
})();
Либо по ссылке, указанной вверху