B站已观看视频标记

bilibili已观看视频标记。无需手动标记。只对从安装脚本时间三个月前起的历史记录起效。

// ==UserScript==
// @name         B站已观看视频标记
// @namespace    http://tampermonkey.net/
// @version      0.1.1
// @description  bilibili已观看视频标记。无需手动标记。只对从安装脚本时间三个月前起的历史记录起效。
// @author       Kesdiael Ken
// @match        https://www.bilibili.com/*
// @match        https://search.bilibili.com/*
// @match        https://t.bilibili.com/*
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addStyle
// @require      https://code.jquery.com/jquery-2.1.4.min.js
// ==/UserScript==

(() => {
    'use strict';
    $(()=>{
        GM_addStyle(`
            .viewed-notice{
                z-index:9999;
                display:block;
                position:absolute;
                top:0px;
                left:0px;
                padding:3px 6px 3px 5px;
                background-color:rgba(0,0,0,.6);
                text-align:center;
                border-radius:0 0 10% 0
            }
            .viewed-notice span{
                color:white;
            }
        `);//已观看角标样式调整


        let url=location.href;
        let key=null;

        function checkurl()
        {
            if(url.match(/https:\/\/www\.bilibili\.com\/video/)){
                let bv=url.match(/(BV\w+)/)[1];
                GM_setValue(bv,true);
            }
        }//已观看视频url记录

        checkurl();

        $(document).on("click",()=>{
            let cnt=30;
            let offset=setInterval(()=>{
                if(url!=location.href){
                    url=location.href;
                    console.log("new url: "+url);
                    checkurl();
                    clearInterval(offset);
                }
                cnt--;
                if(!cnt)clearInterval(offset);
            },150);
        })//点击时检查是否观看了新视频

        function Img_hover(me,ml,mq,tg,itv,once1,once2,self){
            this.me=me;
            this.ml=ml;
            this.mq=mq;
            this.tg=tg;
            this.itv=itv;
            this.once1=once1;
            this.once2=once2;
            this.self=self;
        }

        function append_notice(ind,ele,linkplace,imgplace){
            if($(ele).find(".viewed-notice").length)return;
            let link=$(ele).find(linkplace);
            if(!link.length)return;
            link=link.attr("href");
            let bv=link.match(/(BV\w+)/)[1];
            if(GM_getValue(bv)){
                let img=$(ele).find(imgplace);
                if(!img.length)return;
                img.append(`
                    <div class="viewed-notice" id="${bv}">
                        <span> 已观看 </span>
                    </div>
                `);
                let me,ml,mq=1;
                let self=$(ele).find(`#${bv}`);
                let tot1=200,tot2=100;
                let itv=10,tg=0.7;
                tot1/=2;tot2/=2;
                let once1=(1-tg)/(tot1/itv),once2=(1-tg)/(tot2/itv);
                let imgobj=new Img_hover(me,ml,mq,tg,itv,once1,once2,self);
                img.mouseenter(()=>{
                    clearInterval(imgobj.me);clearInterval(imgobj.ml);
                    imgobj.me=setInterval(()=>{
                        if(imgobj.mq-imgobj.tg<0.001)clearInterval(imgobj.me);
                        else{
                            imgobj.self.fadeTo(imgobj.itv,imgobj.mq-imgobj.once1);
                            imgobj.mq-=imgobj.once1;
                        }
                    },imgobj.itv);
                });
                img.mouseleave(()=>{
                    clearInterval(imgobj.me);clearInterval(imgobj.ml);
                    imgobj.ml=setInterval(()=>{
                        if(1-imgobj.mq<0.001)clearInterval(imgobj.ml);
                        else{
                            imgobj.self.fadeTo(imgobj.itv,imgobj.mq+imgobj.once2);
                            imgobj.mq+=imgobj.once2;
                        }
                    },imgobj.itv);
                });
            }
        }//为视频预览加上已观看角标

        function render(){
            key=null;
            if($("ul .video-item").length)key=$("ul .video-item").eq(0).find("a.img-anchor").attr("href");
            if($(".rec-list .video-page-card").length)key=$(".rec-list .video-page-card").eq(0).find(".info>a").attr("href");
            $("ul .video-item").each((ind,ele)=>{
                append_notice(ind,ele,"a.img-anchor",".b-img");
                append_notice(ind,ele,"a.img-anchor",".lazy-img");
            });
            $(".rec-list .video-page-card").each((ind,ele)=>{
                append_notice(ind,ele,".info>a",".b-img");
                append_notice(ind,ele,".info>a",".lazy-img");
            });
        }//寻找所有已观看视频并加上角标
        req(0,0,"");
        render();
        let rendering=false;
        function render_when_load()
        {
            if(rendering)return;
            rendering=true;
            let cnt=40;
            let offset=setInterval(()=>{
                if($("ul .video-item").length && $("ul .video-item").eq(0).find("a.img-anchor").attr("href")!=key)
                {
                    render();
                    clearInterval(offset);
                    rendering=false;
                }
                if($(".rec-list .video-page-card").length && $(".rec-list .video-page-card").eq(0).find(".info>a").attr("href")!=key)
                {
                    render();
                    clearInterval(offset);
                    rendering=false;
                }
                cnt--;
                if(!cnt){
                    clearInterval(offset);
                    rendering=false;
                }
            },200);
        }//加载延迟执行
        $("input#search-keyword").on("keydown",(event)=>{
            if (event.keyCode==13)render_when_load();
        })//回车执行
        $(document).on("click",render_when_load);
        $(".rec-footer").on("click",()=>{
            setTimeout(render,200);
        })//视频推荐列表展开执行
        let scrolling=false;
        $(document).on("scroll",()=>{
            if(location.href.match(/https:\/\/www\.bilibili\.com\/video/)&&!scrolling){
                scrolling=true;
                render();
                setTimeout(()=>{scrolling=false;},100);
                console.log("scrolling detected");
            }
        });

        function wait(url){
            return new Promise(res=>{
                GM_xmlhttpRequest({
                    method:"GET",
                    url:url,
                    onload:(r)=>{
                        res(JSON.parse(r.response));
                    }
                });
            })
        }//请求20条历史记录
        async function req(max,view_at,business){
            let res=await wait(`https://api.bilibili.com/x/web-interface/history/cursor?max=${max}&view_at=${view_at}&business=${business}`);
            let data=res.data;
            max=data.cursor.max;
            view_at=data.cursor.view_at;
            business=data.cursor.business;
            console.log(data);

            let tf=false;
            data.list.forEach(ele => {
                let bv=ele.history.bvid;
                tf|=!GM_getValue(bv);
                GM_setValue(bv,true);
            });

            if(max&&tf)req(max,view_at,business);
            return;
        }//请求所有历史记录

        $(document).on("click",()=>{req(0,0,"");});

        setInterval(()=>{
            req(0,0,"");
            render();
        },20000);//每20秒更新一次

    });
})();