// ==UserScript== // @name Bilibili 轴Man小助手 // @namespace http://tampermonkey.net/ // @version 0.3 // @description 将评论区的轴转换至Bilibili的笔记,实现手机可点的特性 // @author as042971 // @include *://www.bilibili.com/video/av* // @include *://www.bilibili.com/video/BV* // @license MIT // @grant none // @esversion 8 // @downloadURL none // ==/UserScript== (function() { 'use strict'; // 设置 useIndent = true 会在文本前增加缩进 const useIndent = false; // 设置 useNewLine = true 会在文本后增加空行 const useNewLine = false; const wait1s = function () { return new Promise(resolve => { setTimeout(() => { resolve(); }, 1000); }); }; const waitforComponent = async function(name) { while (true) { let component = document.querySelector(name); if (component) { return component; } await wait1s(); } } const markTime = async function (loc, time) { let comment = document.querySelector('.con ').childNodes[1]; let seeker = document.createElement('a'); seeker.className = 'video-seek'; seeker.setAttribute('data-p', '-1'); seeker.setAttribute('data-time', String(time)); comment.appendChild(seeker); seeker.click(); document.querySelector('.ql-tag-btn').click(); await wait1s(); // 人工将时间戳置底 let editor = document.querySelector('.ql-editor'); editor.appendChild(editor.childNodes[loc]); // 清除多出来的那一个 editor.removeChild(editor.childNodes[loc]); }; const insertText = function (text) { let editor = document.querySelector('.ql-editor'); let insertItem = document.createElement('p'); if (useIndent) { text = ' ' + text; } const insertTxt = document.createTextNode(text); insertItem.appendChild(insertTxt); editor.appendChild(insertItem); }; const parseTime = function (timeStr) { const timePart = timeStr.split(":"); if (timePart.length == 3) { return parseInt(timePart[0]) * 3600 + parseInt(timePart[1]) * 60 + parseInt(timePart[2]); } else { return parseInt(timePart[0]) * 60 + parseInt(timePart[1]); } }; const handleTimeline = async function (inputStr) { let editor = document.querySelector('.ql-editor'); const loc = editor.childNodes.length - 1; // h:mm:ss 型时间 const timeRegex = /^(\d{1})\:([0-5]{1}\d{1})\:([0-5]{1}\d{1})$/; // mm:ss 型时间 const timeRegex2 = /^([0-5]{1}\d{1})\:([0-5]{1}\d{1})$/; // 通过换行分隔 const inputStrList = inputStr.split(/[(\r\n)\r\n]+/); for (let i = 0; i < inputStrList.length; i++) { let inputStrItem = inputStrList[i]; let nonTimeStr = ''; // 通过空格分隔 const inputPart = inputStrItem.split(' '); for (let j = 0; j < inputPart.length; j++) { let part = inputPart[j]; if (part) { if (timeRegex.test(part) || timeRegex2.test(part)) { // 这是一个时间戳 // 结束上一次的非时间戳内容 if (nonTimeStr != '') { insertText(nonTimeStr); if (useNewLine) { insertText(''); } nonTimeStr = ''; } // 标记这个时间戳 const time = parseTime(part); await markTime(loc, time); } else { if (nonTimeStr != '') { nonTimeStr += ' '; } nonTimeStr += part; } } } if (nonTimeStr != '') { insertText(nonTimeStr); if (useNewLine) { insertText(''); } } } }; let app = document.getElementById('app'); let observerOptions = { childList: true, attributes: false, subtree: false }; let injected = false; let commentLoad = false; let observer = new MutationObserver(async (mutation_records) => { if (injected) { return; } for (let i = 0; i < mutation_records.length; i++) { const record = mutation_records[i]; for (let j = 0; j < record.addedNodes.length; j++) { if (injected) { return; } const node = record.addedNodes[j]; if (node.className == 'resizable-component bili-note active-note') { let rawTimeline = document.createElement('textarea'); rawTimeline.setAttribute('id', 'inject-timeline'); rawTimeline.setAttribute('rows', '1'); rawTimeline.oninput = async function () { let data = rawTimeline.value; rawTimeline.value = ""; rawTimeline.setAttribute('disabled', 'disabled'); rawTimeline.setAttribute('placeholder', '处理中,请稍后...'); await handleTimeline(data); rawTimeline.removeAttribute('disabled'); rawTimeline.setAttribute('placeholder', '处理完毕,请换P或直接发表'); }; node.insertBefore(rawTimeline, node.childNodes[3]); rawTimeline.setAttribute('disabled', 'disabled'); rawTimeline.setAttribute('placeholder', '请向下滑动加载评论区'); await waitforComponent('.con '); commentLoad = true; rawTimeline.removeAttribute('disabled'); rawTimeline.setAttribute('placeholder', '将光标移动至文末空行后,将轴粘贴至这里...'); injected = true; } } } }); observer.observe(app, observerOptions); })();