// ==UserScript== // @name Bilibili UP Notes // @name:zh-CN 哔哩哔哩UP主备注 // @namespace ckylin-script-bilibili-up-notes // @version v0.4 // @description A simple script to add notes to Bilibili UPs. // @description:zh-CN 一个可以给哔哩哔哩UP主添加备注的脚本。 // @author CKylinMC // @match https://*.bilibili.com/* // @grant unsafeWindow // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_listValues // @grant GM_addStyle // @license Apache-2.0 // @run-at document-end // @icon https://www.bilibili.com/favicon.ico // @require https://update.greasyfork.icu/scripts/564901/1747775/CKUI.js // @downloadURL none // ==/UserScript== (function (unsafeWindow, document) { // #region helpers if (typeof (GM_addStyle) === 'undefined') { unsafeWindow.GM_addStyle = function (css) { const style = document.createElement('style'); style.textContent = css; document.head.appendChild(style); } } const logger = { log(...args) { console.log('[BiliUPNotes]', ...args); }, error(...args) { console.error('[BiliUPNotes]', ...args); }, warn(...args) { console.warn('[BiliUPNotes]', ...args); }, } const pages = { isPlayPage() { return unsafeWindow.location.pathname.startsWith('/video/') || unsafeWindow.location.pathname.startsWith('/list/'); }, isProfilePage() { return unsafeWindow.location.hostname.startsWith('space.bilibili.com'); } } const runtime = { cardtaskId: null, uptaskId: null }; const selectors = { markup: { symbolclass: '.ckupnotes-symbol', idclass: '.ckupnotes-identifier' }, card: { root: 'div.bili-user-profile', avatar: 'picture.b-img__inner>img', avatarLink: 'a.bili-user-profile-view__avatar', infoRoot: 'div.bili-user-profile-view__info', userName: 'a.bili-user-profile-view__info__uname', bodyRoot: 'div.bili-user-profil1e__info__body', signBox: 'div.bili-user-profile-view__info__signature', footerRoot: 'div.bili-user-profile-view__info__footer', button: 'div.bili-user-profile-view__info__button' }, cardModern: { shadowRoot: 'bili-user-profile', avatarLink: 'a#avatar', avatar: 'img#face', bodyBox: 'div#body', userNameBox: 'div#title', userName: 'a#name', bodyRoot: 'div#content', signBox: 'div#sign', footerRoot: 'div#action', }, userCard: { root: 'div.usercard-wrap', avatarLink: 'a.face', avatar: 'img.bili-avatar-img', bodyRoot: 'div.info', nameBox: 'div.user', userName: 'a.name', signBox: 'div.sign', footerRoot: 'div.btn-box' }, play: { upInfoBox: 'div.up-info-container', upAvatar: 'img.bili-avatar-img', upAvatarLink: 'a.up-avatar', upDetailBox: 'div.up-detail', upName: 'a.up-name', upDesc: 'div.up-description', upBtnBox: 'div.upinfo-btn-panel', upDetailTopBox: 'div.up-detail-top' }, profile: { sidebarBox: 'div.aside', dynamicSidebarBox: 'div.space-dynamic__right' } }; class Utils{ static _c(name) { return "ckupnotes-" + name; } static wait(ms = 0) { return new Promise(resolve => setTimeout(resolve, ms)); } static $(selector, root = document) { return root.querySelector(selector); } static $all(selector, root = document) { return Array.from(root.querySelectorAll(selector)); } static $child(parent, selector) { if (typeof parent === 'string') { return document.querySelector(parent+' '+selector); } return parent.querySelector(selector); } static $childAll(parent, selector) { if (typeof parent === 'string') { return Array.from(document.querySelectorAll(parent+' '+selector)); } return Array.from(parent.querySelectorAll(selector)); } static waitForElementFirstAppearForever(selector, root = document) { return new Promise(resolve => { const element = root.querySelector(selector); if (element) { resolve(element); return; } const observer = new MutationObserver(mutations => { for (const mutation of mutations) { for (const node of mutation.addedNodes) { if (!(node instanceof HTMLElement)) continue; const el = node.matches(selector) ? node : node.querySelector(selector); if (el) { resolve(el); observer.disconnect(); return; } } } }); observer.observe(root, { childList: true, subtree: true }); }); } static registerOnElementAttrChange(element, attr, callback) { const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { if (mutation.type === 'attributes' && mutation.attributeName === attr) { callback(mutation); } }); }); observer.observe(element, { attributes: true }); return observer; } static registerOnElementContentChange(element, callback) { const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { if (mutation.type === 'characterData') { callback(mutation); } }); }); observer.observe(element, { characterData: true, subtree: true }); return observer; } static get ui() { return unsafeWindow.ckui; } static get currentUid() { if (pages.isProfilePage()) { const match = unsafeWindow.location.pathname.match(/\/space\.bilibili\.com\/(\d+)/); if (match) { return match[1]; } else { const uid = document.querySelector('.vui_icon.sic-fsp-uid_line.icon')?.nextSibling?.textContent || null; return uid; } } // on play page if(pages.isPlayPage()) { const upAvatarLink = Utils.$(selectors.play.upAvatarLink); if (upAvatarLink) { const link = upAvatarLink.getAttribute('href') || ''; const match2 = link.match(/\/space\.bilibili\.com\/(\d+)/); if (match2) { return match2[1]; } } } return null; } } // #endregion helpers // #region cores class UPNotesManager { static getAliasForUID(uid, fallback = null) { return GM_getValue(`upalias_${uid}`, fallback); } static setAliasForUID(uid, alias) { GM_setValue(`upalias_${uid}`, alias); } static deleteAliasForUID(uid) { GM_deleteValue(`upalias_${uid}`); } static getNotesForUID(uid, fallback = null) { return GM_getValue(`upnotes_${uid}`, fallback); } static setNotesForUID(uid, notes) { GM_setValue(`upnotes_${uid}`, notes); } static deleteNotesForUID(uid) { GM_deleteValue(`upnotes_${uid}`); } static callUIForEditing(uid, displayName="", closeCallback = null) { const currentAlias = this.getAliasForUID(uid) || ''; const currentNotes = this.getNotesForUID(uid) || ''; const form = Utils.ui.form() .input({ label: 'UP 别名', name: 'alias', placeholder: '请输入 UP 别名', value: currentAlias }) .textarea({ label: 'UP 备注', name: 'notes', placeholder: '请输入 UP 备注', value: currentNotes }) .button({ label: '保存', primary: true, onClick: (values) => { const newAlias = values.alias.trim(); const newNotes = values.notes.trim(); if (newAlias) { this.setAliasForUID(uid, newAlias); } else { this.deleteAliasForUID(uid); } if (newNotes) { this.setNotesForUID(uid, newNotes); } else { this.deleteNotesForUID(uid); } Utils.ui.success('保存成功'); floatWindow.close(); if (closeCallback) { closeCallback(); } } }) .button({ label: '取消', onClick: () => { floatWindow.close(); } }); const floatWindow = Utils.ui.floatWindow({ title: `编辑备注 ${displayName} (UID: ${uid})`, content: form.render(), width: '450px', shadow: true }); floatWindow.show(); floatWindow.moveToMouse?.(); } static callUIForRemoving(uid, displayName="") { Utils.ui.confirm( `确定要删除 ${displayName} (UID: ${uid}) 的 UP 备注吗?`,'确认删除 UP 备注' ).then(res => { if (res) { this.deleteAliasForUID(uid); this.deleteNotesForUID(uid); Utils.ui.success('删除成功'); } }); } } // #endregion cores // #region integrations class FoManPlugin_Provider{ static hasAlias(uid) { return UPNotesManager.getAliasForUID(uid, null) !== null; } static getAlias(uid, fallback = null) { return UPNotesManager.getAliasForUID(uid, fallback); } static setAlias(uid, alias) { UPNotesManager.setAliasForUID(uid, alias); } static removeAlias(uid) { UPNotesManager.deleteAliasForUID(uid); } } class FoManPlugin_Actions{ static async setFor(uid, displayName = null) { UPNotesManager.callUIForEditing(uid, displayName); } static async removeFor(uid, displayName = null) { UPNotesManager.callUIForRemoving(uid, displayName); } } // #endregion integrations // #region onAnyPage function injectCssOnAnyPage() { GM_addStyle(` .ckupnotes-usercard-btn{ border: 1px solid var(--text3); color: var(--text2); background-color: transparent; } .ckupnotes-usercard-btn:hover{ color: var(--brand_blue); border-color: var(--brand_blue); } `); } function registerOnAnyPage() { logger.log('Registering UP Card observer on any page...'); injectCssOnAnyPage(); Utils.waitForElementFirstAppearForever(selectors.card.root).then(onFirstCardShown); Utils.waitForElementFirstAppearForever(selectors.cardModern.shadowRoot).then(onFirstModernCardShown); Utils.waitForElementFirstAppearForever(selectors.userCard.root).then(onFirstUserCardShown); } function onFirstCardShown(cardElement) { logger.log('First UP Card note appeared.'); onCardShown(cardElement); Utils.registerOnElementAttrChange( cardElement, 'style', () => { if (!cardElement.style.display || cardElement.style.display !== 'none') { onCardShown(cardElement); } } ); } function onFirstModernCardShown(cardElement) { logger.log('First Modern UP Card note appeared.'); Utils.registerOnElementAttrChange(cardElement, 'style', () => { if (!cardElement.style.display || cardElement.style.display !== 'none') { onModernCardShown(); } }); } function onFirstUserCardShown(cardElement) { logger.log('First User Card note appeared.'); Utils.registerOnElementAttrChange(cardElement, 'style', () => { if (!cardElement.style.display || cardElement.style.display !== 'none') { onUserCardShown(); } }); } async function onCardShown() { const thisCardTaskId = (''+Date.now()) + Math.random(); try { runtime.cardtaskId = thisCardTaskId; const cardElement = Utils.$(selectors.card.root); const cardBody = Utils.$child(cardElement, selectors.card.bodyRoot); if (!cardBody) { return; } await Utils.wait(150); // 等待内容加载 const els = Utils.$childAll(cardElement, selectors.markup.idclass); els.forEach(element => { element.remove(); }); if(runtime.cardtaskId !== thisCardTaskId) { logger.log('A newer card task has started, aborting this one.(note)'); return; } const avatarLinkEl = Utils.$child(cardElement, selectors.card.avatarLink); const link = avatarLinkEl?.getAttribute('href') || ''; // value = `//space.bilibili.com/652239032/dynamic` // extract UID const match = link.match(/\/space\.bilibili\.com\/(\d+)/); if (!match) return logger.log('UID not found in avatar link, aborting.(note)'); const uid = match[1]; logger.log(`Extracted UID: ${uid} (note)`); let alias = UPNotesManager.getAliasForUID(uid) || ''; let notes = UPNotesManager.getNotesForUID(uid) || ''; logger.log(`UP Card Shown - UID: ${uid}, Alias: ${alias}, Notes: ${notes}`); const userNameEl = Utils.$child(cardElement, selectors.card.userName); const username = userNameEl.textContent || ''; if (alias) { const span = document.createElement('span'); span.classList.add(selectors.markup.symbolclass.replace(".", ""), selectors.markup.idclass.replace(".", "")); span.textContent = ` (${alias})`; userNameEl.appendChild(span); } else { logger.log('No alias found.(note)'); } const bodyRootEl = Utils.$child(cardElement, selectors.card.bodyRoot); if (notes) { const notesEl = document.createElement('div'); notesEl.classList.add(selectors.card.signBox.replace("div.", ""), selectors.markup.idclass.replace(".", "")); notesEl.style.marginTop = '4px'; notesEl.style.fontStyle = 'italic'; notesEl.textContent = notes; bodyRootEl.appendChild(notesEl); logger.log('Notes added to UP Card.(note)'); } else { logger.log('No notes found.(note)'); } const footerRootEl = Utils.$child(cardElement, selectors.card.footerRoot); if (footerRootEl) { const btn = document.createElement('div'); btn.classList.add(selectors.card.button.replace("div.", ""), selectors.markup.idclass.replace(".", "")); btn.textContent = '编辑备注'; btn.style.cursor = 'pointer'; btn.style.marginLeft = '8px'; footerRootEl.appendChild(btn); btn.addEventListener('click', () => { UPNotesManager.callUIForEditing(uid, username); }); } } finally { if(runtime.cardtaskId === thisCardTaskId) runtime.cardtaskId = null; } } async function onModernCardShown() { const cardElement = Utils.$(selectors.cardModern.shadowRoot); if (!cardElement) return; const shadowroot = cardElement.shadowRoot;; if (!shadowroot) return; const thisCardTaskId = ('' + Date.now()) + Math.random(); try { runtime.cardtaskId = thisCardTaskId; await Utils.wait(150); // wait for content load if (runtime.cardtaskId !== thisCardTaskId) { logger.log('A newer card task has started, aborting this one.(modern)'); return; } const els = Utils.$childAll(shadowroot, selectors.markup.idclass); els.forEach(element => { element.remove(); }); const avatarLinkEl = Utils.$child(shadowroot, selectors.cardModern.avatarLink); const link = avatarLinkEl?.getAttribute('href') || ''; const match = link.match(/\/space\.bilibili\.com\/(\d+)/); if (!match) return logger.log('UID not found in avatar link, aborting.(modern)'); const uid = match[1]; logger.log(`Extracted UID: ${uid} (modern)`); let alias = UPNotesManager.getAliasForUID(uid) || ''; let notes = UPNotesManager.getNotesForUID(uid) || ''; logger.log(`Modern UP Card Shown - UID: ${uid}, Alias: ${alias}, Notes: ${notes}`); const userNameEl = Utils.$child(shadowroot, selectors.cardModern.userName); const username = userNameEl?.textContent || ''; if (alias) { const span = document.createElement('span'); span.classList.add(selectors.markup.symbolclass.replace(".", ""), selectors.markup.idclass.replace(".", "")); span.textContent = ` (${alias})`; userNameEl.appendChild(span); } else { logger.log('No alias found.(modern)'); } const bodyRootEl = Utils.$child(shadowroot, selectors.cardModern.bodyRoot); if (notes) { const notesEl = document.createElement('div'); notesEl.classList.add(selectors.cardModern.signBox.replace("div.", ""), selectors.markup.idclass.replace(".", "")); notesEl.style.marginTop = '4px'; notesEl.style.fontStyle = 'italic'; notesEl.textContent = notes; bodyRootEl.appendChild(notesEl); logger.log('Notes added to Modern UP Card.(modern)'); } else { logger.log('No notes found.(modern)'); } const footerRootEl = Utils.$child(shadowroot, selectors.cardModern.footerRoot); if (footerRootEl) { const btn = document.createElement('button'); btn.classList.add(selectors.markup.idclass.replace(".", "")); btn.textContent = '编辑备注'; btn.style.cursor = 'pointer'; btn.style.marginLeft = '8px'; footerRootEl.appendChild(btn); btn.addEventListener('click', () => { UPNotesManager.callUIForEditing(uid, username); }); } } finally { if (runtime.cardtaskId === thisCardTaskId) runtime.cardtaskId = null; } } async function onUserCardShown() { const cardElement = Utils.$(selectors.userCard.root); if (!cardElement) return; const thisCardTaskId = ('' + Date.now()) + Math.random(); try { runtime.cardtaskId = thisCardTaskId; await Utils.wait(300); // wait for content load if (runtime.cardtaskId !== thisCardTaskId) { logger.log('A newer card task has started, aborting this one.(usercard)'); return; } const els = Utils.$childAll(cardElement, selectors.markup.idclass); els.forEach(element => { element.remove(); }); logger.log('Processing User Card...(usercard)\n', cardElement.innerHTML); const userNameLink = Utils.$child(cardElement, selectors.userCard.userName); const link = userNameLink?.getAttribute('href') || ''; const match = link.match(/\/space\.bilibili\.com\/(\d+)/); if (!match) return logger.log('UID not found in avatar link, aborting.(usercard)'); const uid = match[1]; logger.log(`Extracted UID: ${uid} (usercard)`); let alias = UPNotesManager.getAliasForUID(uid) || ''; let notes = UPNotesManager.getNotesForUID(uid) || ''; logger.log(`User Card Shown - UID: ${uid}, Alias: ${alias}, Notes: ${notes}`); const userNameEl = Utils.$child(cardElement, selectors.userCard.userName); const displayName = userNameEl?.textContent || ''; if (alias) { const span = document.createElement('span'); span.classList.add(selectors.markup.symbolclass.replace(".", ""), selectors.markup.idclass.replace(".", "")); span.textContent = ` (${alias})`; userNameEl.appendChild(span); } else { logger.log('No alias found.(usercard)'); } const bodyRootEl = Utils.$child(cardElement, selectors.userCard.bodyRoot); if (notes) { const notesEl = document.createElement('div'); notesEl.classList.add(selectors.userCard.signBox.replace("div.", ""), selectors.markup.idclass.replace(".", "")); notesEl.style.marginTop = '4px'; notesEl.style.fontStyle = 'italic'; notesEl.textContent = notes; bodyRootEl.appendChild(notesEl); logger.log('Notes added to User Card.(usercard)'); } else { logger.log('No notes found.(usercard)'); } const footerRootEl = Utils.$child(cardElement, selectors.userCard.footerRoot); if (footerRootEl) { const btn = document.createElement('div'); btn.classList.add('ckupnotes-usercard-btn', selectors.markup.idclass.replace(".", "")); btn.textContent = '备注'; btn.style.cursor = 'pointer'; btn.style.padding = '3px 6px'; btn.style.borderRadius = '3px'; footerRootEl.appendChild(btn); btn.addEventListener('click', () => { UPNotesManager.callUIForEditing(uid, displayName); }); } } finally { if (runtime.cardtaskId === thisCardTaskId) runtime.cardtaskId = null; } } // #endregion onAnyPage // #region playpage function injectCssOnPlayPage() { GM_addStyle(` .ckupnotes-play-up-btn { margin-left: 2px; color: var(--text2); font-size: 13px; transition: color .3s; flex-shrink: 0; } .ckupnotes-play-up-btn:hover { color: var(--brand_blue); } `); } function registerOnPlayPage() { logger.log('Registering UP Info Box observer on play page...'); injectCssOnPlayPage(); Utils.waitForElementFirstAppearForever(selectors.play.upInfoBox).then(onFirstTimeUpInfoBoxShown); } function onFirstTimeUpInfoBoxShown() { logger.log('First UP Info Box appeared on play page.'); onUpInfoBoxShown(); Utils.registerOnElementContentChange( Utils.$(selectors.play.upInfoBox), () => { onUpInfoBoxShown(); } ); } async function onUpInfoBoxShown() { logger.log('UP Info Box shown on play page.'); const thisUpTaskId = ('' + Date.now()) + Math.random(); try { runtime.uptaskId = thisUpTaskId; await Utils.wait(1000); // wait for content load if (runtime.uptaskId !== thisUpTaskId) { logger.log('A newer UP task has started, aborting this one.(play)'); return; } const upInfoBox = Utils.$(selectors.play.upInfoBox); const els = Utils.$all(selectors.markup.idclass, upInfoBox); els.forEach(element => { element.remove(); }); const upAvatarLinkEl = Utils.$(selectors.play.upAvatarLink, upInfoBox); const link = upAvatarLinkEl?.getAttribute('href') || ''; const match = link.match(/\/space\.bilibili\.com\/(\d+)/); if (!match) return logger.log('UID not found in avatar link, aborting.(play)'); const uid = match[1]; logger.log(`Extracted UID: ${uid} (play)`); let alias = UPNotesManager.getAliasForUID(uid) || ''; let notes = UPNotesManager.getNotesForUID(uid) || ''; logger.log(`UP Info Box Shown - UID: ${uid}, Alias: ${alias}, Notes: ${notes}`); const upNameEl = Utils.$(selectors.play.upName, upInfoBox); const username = upNameEl.textContent || ''; if (alias) { const span = document.createElement('span'); span.classList.add(selectors.markup.symbolclass.replace(".", ""), selectors.markup.idclass.replace(".", "")); span.textContent = ` (${alias})`; upNameEl.appendChild(span); } else { logger.log('No alias found.(play)'); } const upDescEl = Utils.$(selectors.play.upDesc, upInfoBox); if (notes) { const notesEl = document.createElement('div'); notesEl.classList.add(selectors.markup.symbolclass.replace(".", ""), selectors.markup.idclass.replace(".", "")); notesEl.style.marginTop = '4px'; notesEl.style.fontStyle = 'italic'; notesEl.textContent = notes; upDescEl.appendChild(notesEl); logger.log('Notes added to UP Info Box.(play)'); } else { logger.log('No notes found.(play)'); } const upDetailTopBoxEl = Utils.$(selectors.play.upDetailTopBox, upInfoBox); if (upDetailTopBoxEl) { const btn = document.createElement('div'); btn.classList.add('ckupnotes-play-up-btn', selectors.markup.idclass.replace(".", "")); btn.textContent = '编辑备注'; btn.style.cursor = 'pointer'; btn.style.marginLeft = '8px'; upDetailTopBoxEl.appendChild(btn); btn.addEventListener('click', () => { UPNotesManager.callUIForEditing(uid, username, ()=>onUpInfoBoxShown()); }); } } finally { if (runtime.uptaskId === thisUpTaskId) runtime.uptaskId = null; } } // #endregion playpage // #region userprofilepage function injectCssOnUserProfilePage() { GM_addStyle(` .ckupnotes-profile-aside-card { background-color: var(--bg2); border-radius: 6px; width: 100%; padding: 20px 16px 24px; } .ckupnotes-profile-aside-card-line{ margin: 4px 0; } .ckupnotes-profile-aside-card-button{ width: 100%; margin-top: 12px; padding: 4px 0; border: 1px solid var(--text3); color: var(--text2); background-color: transparent; cursor: pointer; } .ckupnotes-profile-aside-card-button:hover{ color: var(--brand_blue); border-color: var(--brand_blue); } `); } function registerOnUserProfilePage() { logger.log('Registering User Profile Page observer...'); injectCssOnUserProfilePage(); Utils.waitForElementFirstAppearForever(selectors.profile.sidebarBox).then(injectOnSidebarBox); Utils.waitForElementFirstAppearForever(selectors.profile.dynamicSidebarBox).then(injectOnDynamicSidebarBox); } async function injectOnSidebarBox(sidebarBox) { logger.log('User Profile Page sidebar box appeared.'); await Utils.wait(200); // wait for content load const uid = Utils.currentUid; if (!uid) { logger.warn('Cannot extract UID on profile page, aborting.'); return; } const alias = UPNotesManager.getAliasForUID(uid) || ''; const notes = UPNotesManager.getNotesForUID(uid) || ''; const username = Utils.$('div.nickname')?.textContent || ''; const existingCard = Utils.$('.ckupnotes-profile-aside-card', sidebarBox); if (existingCard) { existingCard.remove(); } const card = document.createElement('div'); card.classList.add('ckupnotes-profile-aside-card'); const title = document.createElement('div'); title.textContent = 'UP 备注信息'; title.style.fontSize = '16px'; title.style.fontWeight = 'bold'; card.appendChild(title); const aliasLine = document.createElement('div'); aliasLine.classList.add('ckupnotes-profile-aside-card-line'); aliasLine.textContent = `别名: ${alias || '无'}`; card.appendChild(aliasLine); const notesLine = document.createElement('div'); notesLine.classList.add('ckupnotes-profile-aside-card-line'); notesLine.textContent = `备注: ${notes || '无'}`; card.appendChild(notesLine); const editButton = document.createElement('button'); editButton.classList.add('ckupnotes-profile-aside-card-button'); editButton.textContent = '编辑备注'; editButton.addEventListener('click', () => { UPNotesManager.callUIForEditing(uid, username, ()=>injectOnSidebarBox(sidebarBox)); }); card.appendChild(editButton); const wrap = document.createElement('div'); wrap.classList.add('home-aside-section'); wrap.appendChild(card); sidebarBox.prepend(wrap); } async function injectOnDynamicSidebarBox(sidebarBox) { logger.log('User Profile Page sidebar box appeared.'); await Utils.wait(200); // wait for content load const uid = Utils.currentUid; if (!uid) { logger.warn('Cannot extract UID on profile page, aborting.'); return; } const alias = UPNotesManager.getAliasForUID(uid) || ''; const notes = UPNotesManager.getNotesForUID(uid) || ''; const username = Utils.$('div.nickname')?.textContent || ''; const existingCard = Utils.$('.ckupnotes-profile-aside-card', sidebarBox); if (existingCard) { existingCard.remove(); } const card = document.createElement('div'); card.classList.add('ckupnotes-profile-aside-card'); const title = document.createElement('div'); title.textContent = 'UP 备注信息'; title.style.fontSize = '16px'; title.style.fontWeight = 'bold'; card.appendChild(title); const aliasLine = document.createElement('div'); aliasLine.classList.add('ckupnotes-profile-aside-card-line'); aliasLine.textContent = `别名: ${alias || '无'}`; card.appendChild(aliasLine); const notesLine = document.createElement('div'); notesLine.classList.add('ckupnotes-profile-aside-card-line'); notesLine.textContent = `备注: ${notes || '无'}`; card.appendChild(notesLine); const editButton = document.createElement('button'); editButton.classList.add('ckupnotes-profile-aside-card-button'); editButton.textContent = '编辑备注'; editButton.addEventListener('click', () => { UPNotesManager.callUIForEditing(uid, username, ()=>injectOnDynamicSidebarBox(sidebarBox)); }); card.appendChild(editButton); const wrap = document.createElement('div'); wrap.classList.add('dynamic-aside-section'); wrap.appendChild(card); sidebarBox.prepend(wrap); } // #endregion userprofilepage // #region init function init() { logger.log('Initializing Bilibili UP Notes script...'); // 注册任意页面事件 registerOnAnyPage(); // 注册播放页面事件 if (pages.isPlayPage()) { registerOnPlayPage(); } // 注册个人主页事件 if (pages.isProfilePage()) { registerOnUserProfilePage(); } try { if(typeof(unsafeWindow.FoManPlugins) === 'undefined') { unsafeWindow.FoManPlugins = {}; } unsafeWindow.FoManPlugins.UpAlias = { provider: FoManPlugin_Provider, actions: FoManPlugin_Actions } }catch(e) { logger.error('Failed to register as FoMan plugin:', e); } Utils.ui?.trackMouseEvent?.(); logger.log('Bilibili UP Notes script initialized.'); } init(); // #endregion init }) (unsafeWindow,document);