b站视频导出markdown文件
// ==UserScript==
// @name b站视频导出markdown文件
// @namespace https://bbs.tampermonkey.net.cn/
// @version 0.2.0
// @description 用于大模型RAG
// @author 口吃者
// @match https://www.bilibili.com/video/*
// @require https://scriptcat.org/lib/2691/1.0.0/sweetalert2.all.min-11.15.10.js
// @require https://scriptcat.org/lib/2724/1.0.0/js%20%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8E%8B%E7%BC%A9%E5%BA%93-LZString.js
// @grant GM.setValue
// @grant GM.getValue
// @grant GM.deleteValue
// @grant unsafeWindow
// @grant GM_xmlhttpRequest
// @run-at document-body
// @license MIT
// ==/UserScript==
(async function () {
'use strict';
class RequestMonitor {
constructor() {
// 预编译正则表达式提升匹配性能
this._patterns = new Map(); // Map<RegExp, Processor>
// 使用WeakMap防止内存泄漏
this.pendingRequests = new WeakMap();
// 缓存已验证的URL
this._urlCache = {
monitored: new Set(),
ignored: new Set()
};
// 性能统计
this.stats = {
total: 0,
processed: 0,
errors: 0
};
this._initHooks();
}
/* pattern:正则表达式(只要满足其一就会进行监听处理),processor:处理器函数(对满足的每一个pattern进行processor处理,一对多) */
registerHandler(pattern, processor) {
const regex = new RegExp(pattern);
this._patterns.set(regex, processor);
return this; // 支持链式调用
}
_initHooks() {
// 保存原生方法引用
const nativeFetch = unsafeWindow.fetch;
const nativeXHROpen = XMLHttpRequest.prototype.open;
const nativeXHRSend = XMLHttpRequest.prototype.send;
const self = this;
// Hook XHR open方法捕获URL
XMLHttpRequest.prototype.open = function (method, url) {
this._requestURL = url;
return nativeXHROpen.apply(this, arguments);
};
// Hook XHR send
XMLHttpRequest.prototype.send = function (body) {
const xhr = this;
const url = xhr._requestURL || '';
// 前置检查
if (!self._shouldMonitor(url)) {
return nativeXHRSend.apply(this, arguments);
}
const requestKey = {};
self.pendingRequests.set(xhr, requestKey);
self.stats.total++;
// 添加事件监听
xhr.addEventListener('load', () => self._handleXHRResponse(xhr, requestKey));
xhr.addEventListener('error', () => self._cleanup(xhr));
nativeXHRSend.apply(this, arguments);
};
// Hook Fetch
unsafeWindow.fetch = async (input, init) => {
const url = typeof input === 'string' ? input : input.url;
if (!self._shouldMonitor(url)) {
return nativeFetch(input, init);
}
const requestKey = {};
self.pendingRequests.set(requestKey, true);
self.stats.total++;
try {
const response = await nativeFetch(input, init);
self._handleFetchResponse(url, response.clone(), requestKey);
return response;
} catch (error) {
self.stats.errors++;
self._cleanup(requestKey);
throw error;
}
};
}
_shouldMonitor(url) {
if (this._urlCache.monitored.has(url)) return true;
if (this._urlCache.ignored.has(url)) return false;
for (const [regex] of this._patterns) {
if (regex.test(url)) {
this._urlCache.monitored.add(url);
return true;
}
}
this._urlCache.ignored.add(url);
return false;
}
async _handleXHRResponse(xhr, requestKey) {
try {
const data = await this._parseResponse(xhr.response);
await this._processData(xhr._requestURL, data);
this.stats.processed++;
} catch (error) {
this.stats.errors++;
console.error('XHR处理失败:', error);
} finally {
this._cleanup(xhr);
}
}
async _handleFetchResponse(url, response, requestKey) {
try {
const data = await this._parseResponse(await response.text());
await this._processData(url, data);
this.stats.processed++;
} catch (error) {
this.stats.errors++;
console.error('Fetch处理失败:', error);
} finally {
this._cleanup(requestKey);
}
}
async _processData(url, rawData) {
for (const [regex, processor] of this._patterns) {
if (regex.test(url)) {
await processor(rawData);
break; // 仅匹配第一个处理器
}
}
}
async _parseResponse(data) {
try {
return JSON.parse(data);
} catch {
return data;
}
}
_cleanup(target) {
this.pendingRequests.delete(target);
// 定期清理缓存防止内存增长
if (this._urlCache.monitored.size > 1000) {
this._urlCache.monitored.clear();
}
}
// 调试方法
printStats() {
console.table({
'总请求数': this.stats.total,
'已处理请求': this.stats.processed,
'当前挂起请求': this.pendingRequests.size,
'错误数量': this.stats.errors,
'缓存命中率': `${(this.stats.processed / this.stats.total * 100).toFixed(1)}%`
});
}
}
// storage-manager.js
class StorageManager {
constructor(options = {}) {
// 配置参数
this.namespace = options.namespace || 'defaultStorage';
this.chunkSize = options.chunkSize || 500; // 每个分片最大记录数
this.maxChunks = options.maxChunks || 10; // 最大保留分片数
this.autoCleanThreshold = options.autoCleanThreshold || 5 * 1024 * 1024; // 5MB自动清理阈值
this.compression = options.compression !== false; // 默认启用压缩 明确设置为 false 时,this.compression 才会被设置为 false
// 状态跟踪
this.currentChunk = 1;
this.totalRecords = 0;
this.lastCleanTime = 0;
}
// ======================== 核心接口 ========================
// 静态工厂方法
static async createInstance(options = {}) {
const instance = new StorageManager(options);
await instance.init();
return instance;
}
/* 状态跟踪属性赋值 */
async init() {
await this._loadIndex();
return this;
}
async save(data) {
// 1. 获取当前分片
let chunk = await this._getCurrentChunk();
// 2. 检查分片容量
if (chunk.length >= this.chunkSize) {
// 更新状态跟踪属性
await this._rotateChunk();
chunk = [];
}
// 3. 添加数据
chunk.push(data);
this.totalRecords++;
// 4. 保存分片
await this._saveChunk(chunk);
// 5. 自动清理检查
// await this._autoCleanCheck();
}
async loadAll() {
const chunks = [];
for (let i = 1; i <= this.maxChunks; i++) {
const chunk = await this._getChunk(i);
if (chunk) chunks.push(...chunk);
}
// return this._deduplicate(chunks);
return chunks;
}
async clear() {
for (let i = 1; i <= this.maxChunks; i++) {
await GM.deleteValue(this._chunkKey(i));
}
await this._saveIndex({ currentChunk: 1, totalRecords: 0 });
}
// ======================== 内部方法 ========================
async _loadIndex() {
const index = await GM.getValue(this._indexKey(), '{}');
const { currentChunk = 1, totalRecords = 0 } = JSON.parse(index);
this.currentChunk = currentChunk;
this.totalRecords = totalRecords;
}
async _saveIndex() {
const index = JSON.stringify({
currentChunk: this.currentChunk,
totalRecords: this.totalRecords,
lastCleanTime: this.lastCleanTime
});
await GM.setValue(this._indexKey(), index);
}
async _getCurrentChunk() {
return await this._getChunk(this.currentChunk) || [];
}
async _rotateChunk() {
this.currentChunk = (this.currentChunk % this.maxChunks) + 1;
await this._saveIndex();
}
async _saveChunk(chunk) {
const data = this.compression
? LZString.compressToUTF16(JSON.stringify(chunk))
: JSON.stringify(chunk);
await GM.setValue(
this._chunkKey(this.currentChunk),
data
);
}
async _getChunk(number) {
const data = await GM.getValue(this._chunkKey(number));
if (!data) return null;
try {
return JSON.parse(
this.compression
? LZString.decompressFromUTF16(data)
: data
);
} catch (e) {
console.error('分片数据解析失败:', e);
return null;
}
}
async _autoCleanCheck() {
// 按时间清理(每10分钟)
if (Date.now() - this.lastCleanTime > 600_000) {
await this.cleanOldChunks();
return;
}
// 按容量清理
const size = await this._estimateStorageSize();
if (size > this.autoCleanThreshold) {
await this.cleanOldChunks();
this.maxChunks = Math.max(3, Math.floor(this.maxChunks * 0.8));
}
}
async cleanOldChunks() {
const oldest = this.currentChunk > this.maxChunks
? this.currentChunk - this.maxChunks
: 1;
for (let i = 1; i <= oldest; i++) {
await GM.deleteValue(this._chunkKey(i));
}
this.lastCleanTime = Date.now();
await this._saveIndex();
}
async _estimateStorageSize() {
let total = 0;
for (let i = 1; i <= this.maxChunks; i++) {
const data = await GM.getValue(this._chunkKey(i));
total += data ? data.length : 0;
}
return total;
}
_deduplicate(data) {
const seen = new Set();
return data.filter(item => {
const key = item.id || JSON.stringify(item);
return seen.has(key) ? false : seen.add(key);
});
}
// ======================== 工具方法 ========================
_indexKey() {
return `${this.namespace}_index`;
}
_chunkKey(number) {
return `${this.namespace}_chunk_${number}`;
}
// ======================== 调试接口 ========================
async printStats() {
const size = await this._estimateStorageSize();
console.log(`[StorageManager 状态报告]
命名空间: ${this.namespace}
当前分片: ${this.currentChunk}/${this.maxChunks}
总记录数: ${this.totalRecords}
预估存储: ${(size / 1024).toFixed(1)}KB
最后清理: ${new Date(this.lastCleanTime).toLocaleTimeString()}
压缩状态: ${this.compression ? '启用' : '关闭'}
`);
}
}
class BExportTool {
constructor({videoTitle, videoAuthor, videoIntro, videoSubtitle, videoComments}) {
this.videoTitle = videoTitle;
this.videoAuthor = videoAuthor;
this.videoIntro = videoIntro;
this.videoSubtitle = videoSubtitle;
this.videoComments = videoComments;
}
// 新增 Markdown 导出方法
exportDsMarkdownData() { // 注意方法名驼峰式命名
if (!this.markdownData) {
console.error('No Markdown data to export');
return;
}
// 创建标准 Markdown Blob(指定 MIME 类型)
const blob = new Blob([this.markdownData], {
type: 'text/markdown;charset=utf-8' // 或使用 text/plain
});
// 生成带时间戳的文件名(示例:chat_history_12345_20230815.md)
const timestamp = new Date().toISOString().slice(0, 10).replace(/-/g, '');
const filename = `Bilibili_${timestamp}.md`;
// 创建并触发下载链接
const url = URL.createObjectURL(blob);
const anchor = document.createElement('a');
anchor.href = url;
anchor.download = filename;
anchor.style.display = 'none';
document.body.appendChild(anchor);
anchor.click();
// 清理资源
document.body.removeChild(anchor);
URL.revokeObjectURL(url);
}
toMarkdown() {
// 处理标题和作者
const titleSection = `## ${this.videoTitle}`;
const authorSection = `作者 ${this.videoAuthor}`;
// 处理视频简介
const introSection = `### 视频简介\n${this.videoIntro}`;
// 处理视频文案
const subtitleSection = `### 视频文案\n${this.videoSubtitle}`;
// 处理评论部分
const commentItems = this.videoComments.map((comment, index) => {
return `${index + 1}. 用户名:${comment.author}\n 点赞数${comment.likes}\n 评论内容:${comment.content}`;
}).join('\n');
const commentSection = `### 评论\n${commentItems}`;
this.markdownData = [
titleSection,
authorSection,
introSection,
subtitleSection,
commentSection
].join('\n');
// 合并所有部分
return this.markdownData;
}
}
const storageComment = await StorageManager.createInstance({
namespace: 'commentData',
chunkSize: 1000,
maxChunks: 20
});
const monitorTest = new RequestMonitor();
var commentRpId = new Set();
var videoDetails = {
videoTitle: '',
videoIntroduction: '',
upName: ''
};
var fetchPageParams;
//补环境参数
var ct = "wbi_img_urls";
var e = {
"oid": "113402018078283",
"type": 1,
"mode": 3,
"pagination_str": "{\"offset\":\"{\\\"type\\\":1,\\\"direction\\\":1,\\\"data\\\":{\\\"pn\\\":2}}\"}",
"plat": 1,
"web_location": 1315875
};
monitorTest.registerHandler('x/v2/reply/wbi/main', async data => {
try {
//是否第一次获取评论 判断StorageManager的totalRecords是否为0
if (storageComment.totalRecords === 0) {
let hasMatch = Array.from(monitorTest._urlCache.monitored).filter(element => element.includes('x/v2/reply/wbi/main'));
fetchPageParams = getUrlComponent(hasMatch[0]);
let pagination_str = {
offset: data.data.cursor.pagination_reply.next_offset
};
fetchPageParams["pagination_str"] = JSON.stringify(pagination_str);
e["pagination_str"] = JSON.stringify(pagination_str);
e["oid"] = fetchPageParams["oid"];
e["web_location"] = fetchPageParams['web_location'];
var ltFucRes = lt(e);
fetchPageParams["w_rid"] = ltFucRes["w_rid"];
fetchPageParams["wts"] = ltFucRes["wts"];
}
const replies = data.data.replies;
for (let i = 0; i < replies.length; i++) {
const reply = replies[i];
const rpId = reply.rpid;
const rpContent = reply.content.message;
const rpName = reply.member.uname;
const rpLike = reply.like;
if (commentRpId.has(rpId)) {
continue;
}
await storageComment.save({ "author": rpName, "content": rpContent, "likes": rpLike });
commentRpId.add(rpId);
}
} catch (e) {
console.log(e);
}
});
monitorTest.registerHandler('x/player/wbi/v2', async data => {
try {
await GM.deleteValue('subTitleUrl');
await GM.setValue('subTitleUrl', data.data.subtitle.subtitles[0].subtitle_url);
} catch (e) {
console.log(e);
}
});
window.addEventListener('load', addPanel);
window.addEventListener('load', async () => {
// 重置所有值
await storageComment.clear();
videoDetails.videoIntroduction = document.querySelector('#v_desc > div > span')?.textContent;
videoDetails.upName = removeSpacesAndNewlines(document.querySelector('div.up-detail-top > a.up-name')?.textContent);
videoDetails.videoTitle = document.querySelector('#viewbox_report > div.video-info-title > div > h1')?.textContent;
});
function addPanel() {
function genButton(text, foo, id, fooParams = {}) {
let b = document.createElement('button');
b.textContent = text;
b.style.verticalAlign = 'inherit';
// 使用箭头函数创建闭包来保存 fooParams 并传递给 foo
b.addEventListener('click', () => {
foo.call(b, ...Object.values(fooParams)); // 使用 call 方法确保 this 指向按钮对象
});
if (id) { b.id = id };
return b;
}
function changeRangeDynamics() {
const value = parseInt(this.value, 10);
// 只能通过 DOM 方法改变
document.querySelector('#swal-range > output').textContent = value;
}
async function openPanelFunc() {
var swalRangeValue = 20;
const { value: formValues } = await Swal.fire({
title: "<strong>Select Number</strong>",
showCancelButton: true,
draggable: true,
cancelButtonText: 'cancel',
confirmButtonText: 'export',
confirmButtonColor: "#FFD700",
cancelButtonColor: "#8FBC8F",
//class="swal2-range" swalalert框架可能会对其有特殊处理,导致其内标签的id声明失效
html: `
<ul>
<li>saved comments:<i> - </i></li>
<li>subtitle present:<i> yes </i></li>
</ul>
<div class="swal2-range" id="swal-range" style="display: flex;">
<input type="range" min="0" max="300" step="20" value="20">
<output>${swalRangeValue}</output>
</div>
`,
focusConfirm: false,
didOpen: async () => {
const swalRange = document.querySelector('#swal-range input');
const commentsNumber = document.querySelector('#swal2-html-container>ul>li:nth-child(1)>i');
const ifSubtitle = document.querySelector('#swal2-html-container>ul>li:nth-child(2)>i');
const subtitleUrl = await GM.getValue('subTitleUrl', '');
commentsNumber.textContent = storageComment.totalRecords;
ifSubtitle.textContent = subtitleUrl ? 'yes' : 'no';
swalRange.addEventListener('input', changeRangeDynamics);
},
willClose: () => {
// 在关闭前清除事件监听器以防止内存泄漏
const swalRange = document.querySelector('#swal-range input');
swalRange.removeEventListener('input', changeRangeDynamics);
},
preConfirm: () => {
swalRangeValue = document.querySelector('#swal-range > output').textContent;
return [
swalRangeValue
];
}
});
if (formValues) {
getAllCommentsAndExport(formValues[0]);
}
}
let myButton = genButton('BExport', openPanelFunc, 'BExport');
document.body.appendChild(myButton);
var css_text = `
#BExport {
position: fixed;
color: rgb(211, 67, 235);
top: 30%;
left: -20px;/* 初始状态下左半部分隐藏 */
transform: translateY(-50%);
z-index: 1000; /* 确保按钮在最前面 */
padding: 10px 24px;
border-radius: 5px;
cursor: pointer;
border: 0;
background-color: white;
box-shadow: rgb(0 0 0 / 5%) 0 0 8px;
letter-spacing: 1.5px;
text-transform: uppercase;
font-size: 9px;
transition: all 0.5s ease;
}
#BExport:hover {
left: 0%; /* 鼠标悬停时完整显示 */
letter-spacing: 3px;
background-image: linear-gradient(to top, #fad0c4 0%, #fad0c4 1%, #ffd1ff 100%);
box-shadow: rgba(211, 67, 235, 0.7) 0px 7px 29px 0px; /* 更柔和的紫色阴影,带透明度 */
}
#BExport:active {
letter-spacing: 3px;
background-image: linear-gradient(to top, #fad0c4 0%, #fad0c4 1%, #ffd1ff 100%);
box-shadow: rgba(211, 67, 235, 0.5) 0px 0px 0px 0px; /* 活动状态下的阴影,保持一致性 */
transition: 100ms;
}
`
GMaddStyle(css_text);
}
function GMaddStyle(css) {
var myStyle = document.createElement('style');
myStyle.textContent = css;
var doc = document.head || document.documentElement;
doc.appendChild(myStyle);
}
function removeSpacesAndNewlines(str) {
// 使用正则表达式匹配所有空格和换行符,并替换为空字符串
return str.replace(/[\s\r\n]+/g, '');
}
async function fetchNextPageData(comment_params) {
const finalUrl = getFinalCommentUrl(comment_params);
const response = await fetch(finalUrl, {
headers: {
'origin': 'https://www.bilibili.com'
},
credentials: 'include' // 明确指定携带cookies
});
return await response.json();
}
async function fetchSubtitle() {
const subtitleUrl = await GM.getValue('subTitleUrl', '');
if (subtitleUrl) {
const response = await fetch('https://' + subtitleUrl, {
headers: {
'origin': 'https://www.bilibili.com'
},
credentials: 'include' // 明确指定携带cookies
});
return response.json();
} else {
return '';
}
}
function sendGetRequestWithGM(url) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'GET',
url: url,
headers: {
'Content-Type': 'application/json'
},
onload: function (response) {
resolve(JSON.parse(response.responseText));
},
onerror: function (error) {
reject(error);
}
});
});
}
function getFinalCommentUrl(params) {
// 指定参数的顺序
const orderKeys = ["oid", "type", "mode", "plat", "web_location", "pagination_str", "w_rid", "wts"];
// 按照指定顺序构建参数列表
const orderedParams = orderKeys
.filter(key => params.hasOwnProperty(key))
.map(key => key === 'pagination_str'
? `${key}=${encodeURIComponent(params[key])}`
: `${key}=${params[key]}`);
// 构建新的URL
const newUrl = 'https://api.bilibili.com/x/v2/reply/wbi/main?' + orderedParams.join('&');
return newUrl;
};
function getUrlComponent(targetUrl) {
// 提取查询字符串部分
const queryString = targetUrl.split('?')[1];
// 定义正则表达式来匹配参数
const regex = /([^&=]+)=([^&]*)/g;
// 创建一个对象来存储参数
const params = {};
let match;
while ((match = regex.exec(queryString)) !== null) {
const key = decodeURIComponent(match[1]);
const value = decodeURIComponent(match[2]);
params[key] = value;
}
return params;
};
function extractContentsToString(dataArray) {
return dataArray
.map(item => item.content || '') // 安全提取content,防止undefined
.join(';'); // 默认用空字符串连接,可按需改为换行符\n或其他分隔符
}
async function getAllCommentsAndExport(targetAmount) {
try {
while (storageComment.totalRecords < targetAmount) {
const commentData = await fetchNextPageData(fetchPageParams);
const replies = commentData.data.replies;
if (!replies || replies.length === 0) {
break;
}
for (let i = 0; i < replies.length; i++) {
const reply = replies[i];
const rpId = reply.rpid;
const rpContent = reply.content.message;
const rpName = reply.member.uname;
const rpLike = reply.like;
if (commentRpId.has(rpId)) {
continue;
}
await storageComment.save({ "author": rpName, "content": rpContent, "likes": rpLike });
commentRpId.add(rpId);
}
}
const subtitleUrl = await GM.getValue('subTitleUrl', '');
let subtitleData;
if (subtitleUrl) {
let subtitleDataJson = await sendGetRequestWithGM('https://' + subtitleUrl);
subtitleData = extractContentsToString(subtitleDataJson.body);
}
const videoComments = await storageComment.loadAll();
const bExportTool = new BExportTool({
"videoTitle": videoDetails.videoTitle,
"videoAuthor": videoDetails.upName,
"videoIntro": videoDetails.videoIntroduction,
"videoSubtitle": subtitleData,
"videoComments": videoComments
});
bExportTool.toMarkdown();
bExportTool.exportDsMarkdownData();
} catch (error) {
console.error('Error:', error);
}
}
/* 补环境 */
const t_stringToBytes = function (e) {
return n_stringToBytes(unescape(encodeURIComponent(e)))
};
const n_stringToBytes = function (e) {
for (var t = [], r = 0; r < e.length; r++)
t.push(255 & e.charCodeAt(r));
return t
};
const e_bytesToWords = function (e) {
for (var t = [], r = 0, n = 0; r < e.length; r++,
n += 8)
t[n >>> 5] |= e[r] << 24 - n % 32;
return t
};
const o_ff = function (e, t, r, n, o, i, a) {
var u = e + (t & r | ~t & n) + (o >>> 0) + a;
return (u << i | u >>> 32 - i) + t
};
const o_gg = function (e, t, r, n, o, i, a) {
var u = e + (t & n | r & ~n) + (o >>> 0) + a;
return (u << i | u >>> 32 - i) + t
};
const o_hh = function (e, t, r, n, o, i, a) {
var u = e + (t ^ r ^ n) + (o >>> 0) + a;
return (u << i | u >>> 32 - i) + t
};
const o_ii = function (e, t, r, n, o, i, a) {
var u = e + (r ^ (t | ~n)) + (o >>> 0) + a;
return (u << i | u >>> 32 - i) + t
};
const t_rotl = function (e, t) {
return e << t | e >>> 32 - t
};
const e_endian = function (e) {
if (e.constructor == Number)
return 16711935 & t_rotl(e, 8) | 4278255360 & t_rotl(e, 24);
for (var r = 0; r < e.length; r++)
e[r] = e_endian(e[r]);
return e
};
const o = function o(i, a) {
i.constructor == String ? i = a && "binary" === a.encoding ? n_stringToBytes(i) : t_stringToBytes(i) : r(i) ? i = Array.prototype.slice.call(i, 0) : Array.isArray(i) || i.constructor === Uint8Array || (i = i.toString());
for (var u = e_bytesToWords(i), s = 8 * i.length, c = 1732584193, l = -271733879, f = -1732584194, d = 271733878, p = 0; p < u.length; p++)
u[p] = 16711935 & (u[p] << 8 | u[p] >>> 24) | 4278255360 & (u[p] << 24 | u[p] >>> 8);
u[s >>> 5] |= 128 << s % 32,
u[14 + (s + 64 >>> 9 << 4)] = s;
var h = o_ff
, y = o_gg
, v = o_hh
, b = o_ii;
for (p = 0; p < u.length; p += 16) {
var m = c
, w = l
, g = f
, x = d;
c = h(c, l, f, d, u[p + 0], 7, -680876936),
d = h(d, c, l, f, u[p + 1], 12, -389564586),
f = h(f, d, c, l, u[p + 2], 17, 606105819),
l = h(l, f, d, c, u[p + 3], 22, -1044525330),
c = h(c, l, f, d, u[p + 4], 7, -176418897),
d = h(d, c, l, f, u[p + 5], 12, 1200080426),
f = h(f, d, c, l, u[p + 6], 17, -1473231341),
l = h(l, f, d, c, u[p + 7], 22, -45705983),
c = h(c, l, f, d, u[p + 8], 7, 1770035416),
d = h(d, c, l, f, u[p + 9], 12, -1958414417),
f = h(f, d, c, l, u[p + 10], 17, -42063),
l = h(l, f, d, c, u[p + 11], 22, -1990404162),
c = h(c, l, f, d, u[p + 12], 7, 1804603682),
d = h(d, c, l, f, u[p + 13], 12, -40341101),
f = h(f, d, c, l, u[p + 14], 17, -1502002290),
c = y(c, l = h(l, f, d, c, u[p + 15], 22, 1236535329), f, d, u[p + 1], 5, -165796510),
d = y(d, c, l, f, u[p + 6], 9, -1069501632),
f = y(f, d, c, l, u[p + 11], 14, 643717713),
l = y(l, f, d, c, u[p + 0], 20, -373897302),
c = y(c, l, f, d, u[p + 5], 5, -701558691),
d = y(d, c, l, f, u[p + 10], 9, 38016083),
f = y(f, d, c, l, u[p + 15], 14, -660478335),
l = y(l, f, d, c, u[p + 4], 20, -405537848),
c = y(c, l, f, d, u[p + 9], 5, 568446438),
d = y(d, c, l, f, u[p + 14], 9, -1019803690),
f = y(f, d, c, l, u[p + 3], 14, -187363961),
l = y(l, f, d, c, u[p + 8], 20, 1163531501),
c = y(c, l, f, d, u[p + 13], 5, -1444681467),
d = y(d, c, l, f, u[p + 2], 9, -51403784),
f = y(f, d, c, l, u[p + 7], 14, 1735328473),
c = v(c, l = y(l, f, d, c, u[p + 12], 20, -1926607734), f, d, u[p + 5], 4, -378558),
d = v(d, c, l, f, u[p + 8], 11, -2022574463),
f = v(f, d, c, l, u[p + 11], 16, 1839030562),
l = v(l, f, d, c, u[p + 14], 23, -35309556),
c = v(c, l, f, d, u[p + 1], 4, -1530992060),
d = v(d, c, l, f, u[p + 4], 11, 1272893353),
f = v(f, d, c, l, u[p + 7], 16, -155497632),
l = v(l, f, d, c, u[p + 10], 23, -1094730640),
c = v(c, l, f, d, u[p + 13], 4, 681279174),
d = v(d, c, l, f, u[p + 0], 11, -358537222),
f = v(f, d, c, l, u[p + 3], 16, -722521979),
l = v(l, f, d, c, u[p + 6], 23, 76029189),
c = v(c, l, f, d, u[p + 9], 4, -640364487),
d = v(d, c, l, f, u[p + 12], 11, -421815835),
f = v(f, d, c, l, u[p + 15], 16, 530742520),
c = b(c, l = v(l, f, d, c, u[p + 2], 23, -995338651), f, d, u[p + 0], 6, -198630844),
d = b(d, c, l, f, u[p + 7], 10, 1126891415),
f = b(f, d, c, l, u[p + 14], 15, -1416354905),
l = b(l, f, d, c, u[p + 5], 21, -57434055),
c = b(c, l, f, d, u[p + 12], 6, 1700485571),
d = b(d, c, l, f, u[p + 3], 10, -1894986606),
f = b(f, d, c, l, u[p + 10], 15, -1051523),
l = b(l, f, d, c, u[p + 1], 21, -2054922799),
c = b(c, l, f, d, u[p + 8], 6, 1873313359),
d = b(d, c, l, f, u[p + 15], 10, -30611744),
f = b(f, d, c, l, u[p + 6], 15, -1560198380),
l = b(l, f, d, c, u[p + 13], 21, 1309151649),
c = b(c, l, f, d, u[p + 4], 6, -145523070),
d = b(d, c, l, f, u[p + 11], 10, -1120210379),
f = b(f, d, c, l, u[p + 2], 15, 718787259),
l = b(l, f, d, c, u[p + 9], 21, -343485551),
c = c + m >>> 0,
l = l + w >>> 0,
f = f + g >>> 0,
d = d + x >>> 0
}
return e_endian([c, l, f, d])
};
function ft(e) {
return e.substring(e.lastIndexOf("/") + 1, e.length).split(".")[0]
};
const e_wordsToBytes = function (e) {
for (var t = [], r = 0; r < 32 * e.length; r += 8)
t.push(e[r >>> 5] >>> 24 - r % 32 & 255);
return t
};
const e_bytesToHex = function (e) {
for (var t = [], r = 0; r < e.length; r++)
t.push((e[r] >>> 4).toString(16)),
t.push((15 & e[r]).toString(16));
return t.join("")
};
const at = function (t, r) {
if (null == t)
throw new Error("Illegal argument " + t);
var i = e_wordsToBytes(o(t, r));
return r && r.asBytes ? i : r && r.asString ? n.bytesToString(i) : e_bytesToHex(i)
};
function lt(e) {
var t, r, n = function (e) {
var t;
if (e.useAssignKey)
return {
imgKey: e.wbiImgKey,
subKey: e.wbiSubKey
};
var r = (null === (t = function (e) {
try {
return localStorage.getItem(e)
} catch (e) {
return null
}
}(ct)) || void 0 === t ? void 0 : t.split("-")) || []
, n = r[0]
, o = r[1]
, i = n ? ft(n) : e.wbiImgKey
, a = o ? ft(o) : e.wbiSubKey;
return {
imgKey: i,
subKey: a
}
}(arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {
wbiImgKey: "",
wbiSubKey: ""
}), o = n.imgKey, i = n.subKey;
if (o && i) {
for (var a = (t = o + i,
r = [],
[46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49, 33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40, 61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11, 36, 20, 34, 44, 52].forEach((function (e) {
t.charAt(e) && r.push(t.charAt(e))
}
)),
r.join("").slice(0, 32)), u = Math.round(Date.now() / 1e3), s = Object.assign({}, e, {
wts: u
}), c = Object.keys(s).sort(), l = [], f = /[!'()*]/g, d = 0; d < c.length; d++) {
var p = c[d]
, h = s[p];
h && "string" == typeof h && (h = h.replace(f, "")),
null != h && l.push("".concat(encodeURIComponent(p), "=").concat(encodeURIComponent(h)))
}
var y = l.join("&");
return {
w_rid: at(y + a),
wts: u.toString()
}
}
return null
};
})();