梦汐 发表于 2023-7-12 10:21

哔哩哔哩 历史记录备份

哔哩哔哩自带的历史记录有效期只有三个月左右,写来自用的插件,功能大致就是下图,播放进度大于85%会在【TA的视频】里隐藏避免重复播放,更新了个云备份(代码里搜坚果云,改为自己的号后取消注释就行)

// ==UserScript==
// @name      哔哩哔哩 - 进度备份
// @namespace   Violentmonkey Scripts
// @match       *://*.bilibili.com/*
// @version   1.0
// @license   BSD
// @grant       GM_setValue
// @grant       GM_getValue
// @grant       GM_addStyle
// @grant       GM_listValues
// @run-at      document-start
// @grant       GM_xmlhttpRequest
// @grant       GM_getResourceText
// @require   https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.5.1.min.js
// @require   https://greasyfork.org/scripts/463081-webdav/code/webdav.js
// @noframes
// ==/UserScript==
(() => {
    const config = {
      "hide_watched_videos": true,//隐藏观看过的视频
      "backup_to_cloud": true
    };
    const rules = {
      "all": [".*://.*.bilibili.com.*", []],
      "home": [".*://www.bilibili.com(?:$|/$|/\\?.*)", ],//首页
      "video": [".*://www.bilibili.com/video/(*).*", ],//视频
      "sapce": [".*://space.bilibili.com/.*", ]//主页
    };
    (function () {
      for (type in rules) {
            var focus = rules
            var regexp = RegExp(focus, "i").exec(window.location.href)
            if (regexp != null) {
                console.log("\u9875\u9762\u7c7b\u578b", type, "|", "\u4f7f\u7528\u51fd\u6570", focus);
                for (let i = 0; i < focus.length; i++) {
                  focus.call(null, { regexp: regexp.slice(1,) })
                }
            }
      }
    }());
    //(new webdav("dav账号", "dav密码")).AutoBack('bilibili')//只能支持坚果云
    //----------------功能模块
    function RecordPlayTime() {//记录播放进度
      $(bind)
      function bind() {
            let window = unsafeWindow
            $('video,bwp-video').on("timeupdate", throttle(
                function () {
                  if ("__INITIAL_STATE__" in window) {
                        if ("bvid" in window.__INITIAL_STATE__) {
                            let bvid = window.__INITIAL_STATE__.bvid
                            let duration = parseInt(this.target.duration)
                            let currentTime = parseInt(this.target.currentTime)
                            let old = GM_getValue_local("history", bvid, false)
                            if (!old || old.p < currentTime) {
                              GM_setValue_local("history", bvid, { d: duration, p: currentTime })
                            } else {
                              //当前进度小于历史最大进度
                            }
                        }
                  }
                }, 1000
            ))
            $('video,bwp-video').on("ended",
                () => {
                  if ("bvid" in window.__INITIAL_STATE__) {
                        let PlayList = GM_getValue('PlayList', null)
                        let Index = PlayList.indexOf(window.__INITIAL_STATE__.bvid)
                        if (Index != -1) {
                            location.replace('https://www.bilibili.com/video/' + PlayList[++Index])
                        }
                  }
                }
            )
      }

    }
    function PlayProgressUI() {//进度条
      ObserveNewElements(".small-item.fakeDanmu-item", insert)
      window.onfocus = function (e) {
            $('.small-item.fakeDanmu-item').each(
                function () {
                  insert(this)
                }
            )
      }
      function insert(element) {
            var id = $(element).attr('data-aid')
            var history = GM_getValue_local("history", id, false)
            if (!!history) {//判断JSON是否为空
                var progress_ui = document.createElement('div');
                var Percent = getPercent(history.p, history.d)
                $(progress_ui).attr('class', 'progress').attr('style', 'top: 0px;position: absolute;width: 100%;height: 4px;background-color: #909090;').html(`<div id="content" style="width: ${Percent}%;height: 100%;background-color: #f00;"></div>`);
                $(element).find('.cover').append(progress_ui);
                if (config["hide_watched_videos"]) {//读取设置
                  if (Percent > 85) {
                        $(element).hide();
                        $(element).css('border', '1px solid #e9e9e9')
                  }
                }
            }
      }
    }
    function RemoveAdsHome() {
      $(
            function () {
                let observer = new MutationObserver((mutationsList, observer) => {
                  // 遍历每一个发生变化的 mutation
                  for (let mutation of mutationsList) {
                        // 检查新增元素
                        if (mutation.type === 'childList') {
                            // 遍历新增的节点和子节点
                            mutation.addedNodes.forEach(node => {
                              if ($(node).is('.bili-video-card.is-rcmd') || $(node).is('.feed-card')) {
                                    handleNode(node);
                              }
                            });
                        }
                  }
                });

                // 要监视的目标节点
                let targetNode = document.body;

                // 配置并启动 MutationObserver
                observer.observe(targetNode, { childList: true, subtree: true });

                // 处理新增的节点的函数
                function handleNode(node) {
                  if (node.marking) {
                        return null
                  }
                  let element = $(node).find("div>a")
                  if (!element.getAttribute('href').includes("www.bilibili.com")) {
                        node.marking = true
                        if ($(node.parentElement).is('.feed-card')) {
                            node.parentElement.parentElement.appendChild(node.parentElement);
                        } else {
                            node.parentElement.appendChild(node);
                        }
                        console.log("移除广告", node);
                  }
                }
                $('.bili-video-card.is-rcmd').each(function () {
                  handleNode(this)
                });
            }
      )
    }
    //----------------常用函数
    function throttle(fn, intvl, ...prm) {//节流
      let timer;
      let interval;
      return function (...args) {
            if (!timer) {
                timer = setTimeout(function () {
                  interval = intvl
                  fn.call(...args, ...prm)
                  timer = null;
                }, interval)
            }
      }
    }
    function formatTime(seconds) {//转换时间格式
      let minutes = Math.floor(seconds / 60);
      seconds = seconds % 60;
      return (minutes < 10 ? "0" : "") + minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
    }
    function getPercent(num, total) {//取百分比
      num = parseFloat(num);
      total = parseFloat(total);
      if (isNaN(num) || isNaN(total)) {
            return 0;
      }
      return total <= 0 ? "0%" : (Math.round(num / total * 10000) / 100.00);
    }
    function ObserveNewElements(selector, response, filter) {//selector,call(node,mutation),filterRepetition=true)
      'use strict';
      if (!!selector) {
            let config = {
                childList: true,
                subtree: true
            };
            const mutationCallback = (mutationsList) => {
                for (let mutation of mutationsList) {
                  let type = mutation.type;
                  if (type == "childList") {
                        if (mutation.addedNodes.length != 0) {
                            var New_node = []
                            for (let index = 0; index < mutation.addedNodes.length; index++) {
                              var Nodes = $(mutation.addedNodes)
                              for (let Tindex = 0; Tindex < Nodes.length; Tindex++) {
                                    if ($(Nodes).is(selector)) {
                                        New_node.push(Nodes)
                                    }
                              }
                              Nodes.find(selector).each(
                                    function () {
                                        New_node.push(this)
                                    }
                              )
                            }
                            if (New_node.length > 0) {
                              setTimeout((function (list) {
                                    for (let i = 0; i < list.length; i++) {
                                        if (filter) {
                                          if (list['OpenFilter']) {
                                                continue;
                                          } else {
                                                list['OpenFilter'] = true
                                          }
                                        }
                                        response.call(mutation, list, mutation)
                                    }
                              }(New_node)), 300)
                            }
                        }
                  }
                }
            };
            var observe = new MutationObserver(mutationCallback);
            observe.observe(document, config)
            return observe
      }
    }
    function GM_getValue_local(id, key, defaultValue) {
      var data = GM_getValue(id, {});
      return data || defaultValue;
    }
    function GM_setValue_local(id, key, value) {
      var data = GM_getValue(id, {});
      data = value;
      return GM_setValue(id, data);
    }
})();

beihuifengHE 发表于 2023-7-12 12:00

这代码怎么用啊,小白可以用吗{:17_1067:}

hwl19900304 发表于 2023-7-12 11:05

谢谢,这个功能很实用

a7226845a 发表于 2023-7-12 11:58

正需要就有了 谢谢

heptaspirit 发表于 2023-7-12 11:58

很实用的功能,谢谢分享

ocean2021 发表于 2023-7-12 12:06

{:1_893:}学习了,打开了思路

Blacksilkk 发表于 2023-7-12 12:23

学习到了,格局打开了{:1_918:}

leo580 发表于 2023-7-12 12:37

本帖最后由 leo580 于 2023-7-12 14:25 编辑

加载到,暴力猴后,保存提示。提示脚本不合适。

resetsix 发表于 2023-7-12 12:56

前来学习

7ommy 发表于 2023-7-13 10:05

怎么用啊 这个脚本
页: [1] 2
查看完整版本: 哔哩哔哩 历史记录备份