listBox.clientHeight && setting.noScrollBar) {
listBox.style = 'overflow-y: auto;align-content: flex-start;width: calc(100% + 20px) !important';
}
else {
listBox.style = 'overflow-y: auto;align-content: flex-start;width: 100% !important';
}
}
setting.setListWidth();
new MutationObserver(setting.setListWidth).observe(listBox,{childList:true});
}
//获取推荐视频数据
function getRecommend () {
let loadingDiv;
listBox.insertAdjacentElement('afterBegin',loadingDiv=element.getLoadingDiv('recommend'));
GM_xmlhttpRequest({
method: 'GET',anonymous:true,
url: 'https://app.bilibili.com/x/feed/index?appkey=1d8b6e7d45233436&build=1&mobi_app=android&idx='
+ (Date.now()/1000).toFixed(0) + (setting.accessKey?'&access_key='+setting.accessKey:''),
headers:{'user-agent':'Mozilla/5.0 BiliDroid/5.24.0 (bbcallen@gmail.com)'},
onload: res=>{
try {
const rep = JSON.parse(res.response);
if (rep.code!=0){
loadingDiv.firstChild.innerText = `请求app首页失败 code ${rep.code}msg ${rep.message}`;
return console.error('请求app首页失败',rep);
}
setting.pushHistory(rep.data);
updateRecommend(rep.data);
loadingDiv.style.display = 'none';
} catch (e){
loadingDiv.firstChild.innerText = `请求app首页发生错误 ${e}`;
console.error(e,'请求app首页发生错误');
}
},
onerror: e=>{
loadingDiv.firstChild.innerText = `请求app首页发生错误 ${e}`;
console.error(e,'请求app首页发生错误');
}
});
}
//旧版创建视频卡
function createOldRecommend(data) {
return element._c({
nodeType:'div',
className:'spread-module',
childs:[{
nodeType:'a',target:'_blank',
onmouseenter: data.goto=='av'&&tools.preview,
onmouseleave: data.goto=='av'&&tools.preview,
onmousemove: data.goto=='av'&&tools.preview,
href:data.goto=='av'?`/video/av${data.param}`:data.uri,
dataset:{
tag_id:data.tag?data.tag.tag_id:'',
id:data.param,goto:data.goto,mid:data.mid,rid:data.tid
},
childs:[
{
nodeType:'div',className:'pic',
childs:[
``,
``,
``,
``,
`${data.tname||data.badge}`,
data.duration&&`${tools.formatNumber(data.duration,'time')}`||'',
data.goto=='av'?{
nodeType:'div',
dataset:{aid:data.param},title:'稍后再看',
className:'watch-later-trigger w-later',
onclick:tools.watchLater
}:'',
(data.dislike_reasons&&setting.accessKey)?{
nodeType:'div',innerText:'X',
className:'dislike-botton',
childs:[{
nodeType:'div',
className:'dislike-list',
childs:data.dislike_reasons.map(reason=>({
nodeType:'div',
dataset:{reason_id:reason.reason_id},
innerText:reason.reason_name,
title:`提交因为【${reason.reason_name}】不喜欢`,
onclick:dislike,
}))
}]
}:''
]
},
`${data.title}
`,
`${tools.formatNumber(data.play)}`
+`${tools.formatNumber(data.danmaku)}`
]
}]
})
}
//新版创建视频卡
function createNewRecommend(data) {
return element._c({
nodeType:'div',style:'display:block',
className:'video-card-common',
childs:[
{
nodeType:'div',className:'card-pic',
onmouseenter: data.goto=='av'&&tools.preview,
onmouseleave: data.goto=='av'&&tools.preview,
onmousemove: data.goto=='av'&&tools.preview,
dataset:{
tag_id:data.tag?data.tag.tag_id:'',
id:data.param,goto:data.goto,mid:data.mid,rid:data.tid
},
childs:[
``
+ `
`
+ `
${tools.formatNumber(data.play)}`
+(data.like&&`${tools.formatNumber(data.like)}
`||'
')
+ `${data.duration&&tools.formatNumber(data.duration,'time')||''}
`,
`
`,
``,
`${data.tname||data.badge}`,
data.goto=='av'?{
nodeType:'div',
dataset:{aid:data.param},title:'稍后再看',
className:'watch-later-video van-watchlater black',
onclick:tools.watchLater
}:'',
(data.dislike_reasons&&setting.accessKey)?{
nodeType:'div',innerText:'X',
className:'dislike-botton',
childs:[{
nodeType:'div',
className:'dislike-list',
childs:data.dislike_reasons.map(reason=>({
nodeType:'div',
dataset:{reason_id:reason.reason_id},
innerText:reason.reason_name,
title:`提交因为【${reason.reason_name}】不喜欢`,
onclick:dislike,
}))
}]
}:''
]
},
`${data.title}`,
`${data.name||data.badge}`,
]
})
}
//显示推荐视频
function updateRecommend (datas){
const point = listBox.firstChild;
datas.forEach(data=>{
const recommend = element.isNew?createNewRecommend(data):createOldRecommend(data);
recommends.push(point.insertAdjacentElement('beforeBegin',recommend));
});
//移除多余的显示内容
while(setting.pageLimit && recommends.length>setting.pageLimit) listBox.removeChild(recommends.shift());
listBox.scrollTop = 0;
scrollBox.scrollTop = 0;
}
//提交不喜欢视频,视频数据提前绑定在页面元素上
function dislike (ev) {
let target=ev.target,parent=target.parentNode;
let cancel;
let url = `https://app.bilibili.com/x/feed/dislike`;
if (parent.className!='dislike-list'){
cancel = true;
let deep = 1;
while(!parent.dataset.id&&deep++<4){
target = parent;
parent=target.parentNode;
}
if (!parent.dataset.id){
tools.toast('请求撤销稍后再看失败:页面元素异常',ev);
return false;
}
url += `/cancel`;
}else{
parent = parent.parentNode.parentNode;
if(!element.isNew) parent = parent.parentNode;
}
url += `?appkey=1d8b6e7d45233436&build=5000000&goto=${parent.dataset.goto}&id=${parent.dataset.id}&mid=${parent.dataset.mid}`
+`&reason_id=${target.dataset.reason_id}&rid=${parent.dataset.rid}&tag_id=${parent.dataset.tag_id}`;
if (setting.accessKey) url += '&access_key='+ setting.accessKey;
const handleCover = ()=>{
if (cancel){
parent.removeChild(target);
}else{
const cover = document.createElement('div');
cover.className = 'dislike-cover';
cover.dataset.reason_id = target.dataset.reason_id;
cover.innerHTML = `
提交成功,但愿服务器以后少给点这种东西。
点击撤销操作`;
cover.onclick = dislike;
parent.appendChild(cover);
}
};
//console.log(url);
GM_xmlhttpRequest({
method: 'GET',url,anonymous:true,
headers:{'user-agent':'Mozilla/5.0 BiliDroid/5.24.0 (bbcallen@gmail.com)'},
onload: res=>{
try {
const par = JSON.parse(res.response);
if (par.code == 0){
handleCover();
}else if((par.code==-101 && par.message=='账号未登录')){
setting.storageAccessKey(undefined);
tools.toast(`未获取授权或者授权失效,请点击设置重新获取授权`);
}
else{
tools.toast(`请求不喜欢错误 code ${par.code}msg ${par.message}`,{par,url});
}
} catch (e){
tools.toast(`请求不喜欢发生错错误${e}`,e);
}
},
onerror: e=>{
tools.toast(`请求不喜欢发生错误`,e);
}
});
return false;
}
}
//全站排行榜
function InitRanking(){
let rankingAll;
if(element.isNew) {
//……直接把旧版的排行修一修搬过来用吧
rankingAll = element.mainDiv.querySelector('.rank-list');
element._s(rankingAll,{
className:'sec-rank report-wrap-module zone-rank rank-list',
innerHTML:`
查看更多`
});
}
else {
rankingAll = element.mainDiv.querySelector('#ranking_douga');
}
rankingAll.id = 'ranking-all';
const rankingHead = rankingAll.querySelector('.rank-head');
rankingHead.firstChild.innerText = '全站排行';
const tab = rankingHead.querySelector('.bili-tab.rank-tab');
const dropDown = rankingHead.querySelector('.bili-dropdown.rank-dropdown');
const warp = rankingAll.querySelector('.rank-list-wrap');
let type, day = setting.rankingDay;
const loading = element.getLoadingDiv();
const configs = [
{
dataLink: 'https://api.bilibili.com/x/web-interface/ranking/v2?rid=0&type=all',
link: 'https://www.bilibili.com/v/popular/rank/all',
list: warp.firstChild
},
{
dataLink: 'https://api.bilibili.com/x/web-interface/popular?ps=50&pn=',
link: 'https://www.bilibili.com/v/popular/all',
list: warp.lastChild
}
];
const detail = {};
//20121203旧排行彻底失效,删除日期选项
rankingAll.lastChild.style = dropDown.style = 'display: none;';
rankingHead.firstChild.style = 'display: none';
tab.style = 'font-size: 16px;';
tab.children[0].dataset.type = 0;
tab.children[0].textContent = '全站排行';
tab.children[0].addEventListener('mouseover',update);
tab.children[1].dataset.type = 1;
tab.children[1].textContent = '综合热门';
tab.children[1].addEventListener('mouseover',update);
configs[1].list.addEventListener('scroll',handleScroll);
// 更多
const more = element._c({
nodeType:'a',style:'float: right;background: white;',
target: '_blank', href: '',
innerHTML: '更多',
className:'more more-link',
parent: rankingHead
});
//创建一个显示详情的浮窗
detail.div = element._c({
nodeType:'div',style:'display:none',
className:'spread-module video-info-module',
onmouseenter: ()=> (detail.div.style.display = 'block'),
onmouseleave: ()=> (detail.div.style.display = 'none'),
});
warp.insertBefore(detail.div,warp.lastChild);
//更新显示详情浮窗内容
function updateDetail(data,offsetTop){
element._s(detail.div,{
style: `display:"none";left:${rankingAll.offsetLeft}px;top:${offsetTop}px;`,
innerHTML:['',
].join(''),
childs:[
`${data.title}`,
{
nodeType:'div',
className:'clearfix v-data',
childs:[
{nodeType:'div',style:'display: inline-block;width:160px',
childs:[{
nodeType:'a',target:'_blank',
href: '/video/av'+data.aid,
onmouseenter: tools.preview,
onmouseleave: tools.preview,
onmousemove: tools.preview,
dataset:{id:data.aid},
childs:[
{
nodeType:'div',className:'pic',
childs:[
``,
``,
``,
``,
//`${data.tname||data.badge}`,
{
nodeType:'div',
dataset:{aid:data.aid},title:'稍后再看',
className:'watch-later-trigger w-later watch-later-video van-watchlater black',
onclick:tools.watchLater
},
]
},
]
}]},
{
nodeType:'div',
style:'display: inline-block;vertical-align: top;width: 130px;margin-left:3px',
childs:[
''+
`${data.owner&&data.owner.name||data.author}`,
''+
`${tools.formatNumber(data.stat&&data.stat.view||data.play)}`,
''+
`${tools.formatNumber(data.stat&&data.stat.danmaku||data.video_review)}`,
''+
`${tools.formatNumber(data.stat&&data.stat.coin||data.coins)}`,
`时长:${tools.formatNumber(data.duration,'time')}`,
`${data.score||data.pts?'综合评分:':''}${data.score||data.pts?tools.formatNumber(data.score||data.pts):data.rcmd_reason&&data.rcmd_reason.content}`,
]
},
]
}
]
});
};
//将排行数据显示到指定目标中
function showData(target,data){
while(target.lastChild) target.removeChild(target.lastChild);;
target.appendChild(loading);
for (let i = 0;i{item.classList.add('show-detail'); if (img){img.innerHTML = `
`;img=undefined;}},
onmouseleave: ()=>i!=0&&item.classList.remove('show-detail'),
childs:[
{
nodeType:'i',className:'ri-num',innerText:i+1,
onmouseenter: (ev)=> updateDetail(itemData,ev.pageY),
onmouseleave: ()=> (detail.div.style.display = 'none'),
},
{
nodeType:'a', target:"_blank",
href:`/video/av${itemData.aid}/`,
title:`${itemData.title}\r\n播放:${tools.formatNumber(itemData.stat&&itemData.stat.view||itemData.play)} | ${tools.formatNumber(itemData.duration, 'time')} | UP: ${itemData.owner&&itemData.owner.name||itemData.author}`,
className:'ri-info-wrap clearfix',
childs:[
(i==0?``:(
img = element._c({nodeType:'div',className: "lazy-img ri-preview",}))),
`${itemData.title}
${itemData.owner&&itemData.owner.name||itemData.author}
`,
{
nodeType:'div',title:'添加到稍后再看',
dataset:{aid:itemData.aid},className:"watch-later-trigger w-later watch-later-video van-watchlater black",
onclick:tools.watchLater
}
]
}
],
parent:target
});
}
};
let page = 1;
function handleScroll() {
if (warp.lastChild.scrollHeight - warp.lastChild.scrollTop == warp.lastChild.clientHeight) {
if (++page <= 10) {
handleData(page);
}
}
}
//获取/缓存/调用显示数据
async function handleData(page=''){
const config = configs[type];
let dataPromise;
loading.firstChild.innerText = '正在加载...';
config.list.appendChild(loading);
if (config.data && !page) {
dataPromise = Promise.resolve(config.data);
}
else {
dataPromise = fetch(configs[type].dataLink+page,{credentials:'include'}).then(res=>res.json()).then(res=>{
if (res.code!=0) throw `请求排行榜失败 code ${res.code}msg ${res.message}`;
if (!config.data) config.data = [];
config.data.push(...res.data.list);
if (res.data.no_more) configs[1].list.removeEventListener('scroll',handleScroll);
return config.data;
});
}
dataPromise.then((data)=>{
showData(config.list, data);
config.list.removeChild(loading);
}).catch(e=>{
loading.firstChild.innerText = `请求排行榜发生错误 ${e}`;
console.error('请求排行榜发生错误',e);
});;
};
//处理排行榜切换事件,调用获取并显示数据
function update(ev){
//console.log(ev);
if (ev.target.dataset.type==type) return;
type = ev.target.dataset.type;
setting.setRankingType(type);
tab.children[type].classList.add('on');
tab.children[1-type].classList.remove('on');
type != warp.classList.contains('show-origin') && warp.classList.toggle('show-origin');
//rankingAll.lastChild.href = `/ranking/${type==1?'all':'origin'}/0/0/${day}/`;
more.href = configs[type].link;
handleData();
};
if (setting.noRanking) {
//document.getElementById('ranking-all').style = 'display: none';
} else {
update({target:{dataset:{type:setting.rankingType}}});
}
}
//设置,包含设置变量以及设置窗口和对应的方法
const setting = {
dialog:undefined,
historyData:JSON.parse(GM_getValue('historyRecommend','[]')),
historyLimit:isNaN(+GM_getValue('historyLimit'))?10:+GM_getValue('historyLimit'),
pageLimit:+GM_getValue('pageLimit')||0,
autoFreshCount:isNaN(+GM_getValue('autoFreshCount'))?1:+GM_getValue('autoFreshCount'),
hotkey: (()=>{
let key = GM_getValue('hotkey');
if (!key) return '';
return key;
})(),
manualFreshCount:(()=>{
var mfc = GM_getValue('manualFreshCount',1);
if (isNaN(mfc)||mfc<1) mfc = 1;
return mfc;
})(),
boxHeight:+GM_getValue('boxHeight')||2,
noScrollBar:!!GM_getValue('noScrollBar'),
reduceHeight:!!GM_getValue('reduceHeight',0),
rankingDays:{1:'昨天',3:'三日',7:'一周'},
rankingDay: (()=>{
var rd = GM_getValue('rankingDay',3);
if (rd!=1&&rd!=3&&rd!=7) rd = 3;
return rd;
})(),
rankingType: GM_getValue('rankingType', 0),
setRankingType(value) {
if (this.rankingType == value) return;
GM_setValue('rankingType', this.rankingType = value);
},
noRanking: GM_getValue('noRanking'),
setNoRanking(value){
GM_setValue('noRanking', this.noRanking = value);
this.setStyle();
if (!value) {
document.querySelector(`#ranking-all .bili-tab-item[data-type="${this.rankingType}"]`).dispatchEvent(new Event('mouseover'));
}
},
noRankingWidth: GM_getValue('noRankingWidth'),
setNoRankingWidth(value){
GM_setValue('noRankingWidth', this.noRankingWidth = value);
this.setStyle();
},
forceWidth: GM_getValue('forceWidth'),
setForceWidth(value){
GM_setValue('forceWidth', this.forceWidth = value);
this.setStyle();
},
accessKey:GM_getValue('biliAppHomeKey'),
storageAccessKey(key){
if(key) {
GM_setValue('biliAppHomeKey',this.accessKey = key);
}
else {
delete this.accessKey;
GM_deleteValue('biliAppHomeKey');
}
},
pushHistory(data){
this.historyData.unshift(...data);
},
saveHistory(){
while(this.historyData.length>this.historyLimit) this.historyData.pop();
GM_setValue('historyRecommend',JSON.stringify(this.historyData));
},
setHistoryLimit(limit){
GM_setValue('historyLimit',this.historyLimit = +limit);
},
setPageLimit(limit){
GM_setValue('pageLimit',this.pageLimit = +limit);
},
setAutoFreshCount(count){
GM_setValue('autoFreshCount',this.autoFreshCount = +count);
},
setManualFreshCount(target){
var count = +target.value;
if (count<1) count = target.value = 1;
GM_setValue('manualFreshCount',this.manualFreshCount = +count);
},
setBoxHeight(line){
GM_setValue('boxHeight',this.boxHeight=+line);
this.setStyle();
},
setScrollBar(status){
GM_setValue('noScrollBar',this.noScrollBar=+status);
this.setStyle();
},
setReduceHeight(status){
GM_setValue('reduceHeight',this.reduceHeight=+status);
this.setStyle();
},
setHotkey(ev){
ev.preventDefault();
const key = ev.key;
if(key=='Backspace' || key == 'Delete' || key == ' ') {
this.hotkey = ev.target.value = '';
if (this.freshHotkey) this.freshHotkey = document.removeEventListener('keydown', this.freshHotkey);
}
else {
this.hotkey = ev.target.value = ev.key.toUpperCase();
if (!this.freshHotkey) document.addEventListener('keydown', this.freshHotkey = ev=>this.freshHotkeyHandler(ev));
}
GM_setValue('hotkey', this.hotkey);
},
freshHotkeyHandler(ev) {
if (ev.target instanceof HTMLInputElement) return;
if (ev.key.toUpperCase() == this.hotkey) {
document.querySelector('#bili_report_douga .btn-change > i').click();
}
},
init(){
this.setStyle();
if (!!this.hotkey) document.addEventListener('keydown', this.freshHotkey = ev=>this.freshHotkeyHandler(ev));
},
setStyle(){
if(!this.styleDiv) {
this.styleDiv = element._c({
nodeType:'style',
parent:document.head
});
}
let html = '';
if(this.noScrollBar) {
//不显示滚动条情况下,将内层容器宽度设置为比外层宽度多一个滚动条,则滚动条位置会溢出被遮挡
html += '#ranking-all .rank-list-wrap{width:calc(200% + 40px)}'
+ '#ranking-all .rank-list-wrap.show-origin{margin-left:calc(-100% - 20px)}'
;
//左侧推荐容器本同理,但因为新版弹性布局如果没有滚动条内容会伸展到超出可视范围,需针对设置
}
else {
//显示滚动条情况下,排行榜容器维持原样式,内层容器自带滚动条。
//左侧推荐容器将内层高度设置为弹性,则外层容器固定高度下如果内容超出会显示滚动条。
html += '#recommend #recommend-list{height:unset!important;}';
}
if (this.noRanking) {
html += '#ranking-all{display: none !important}';
}
if (this.noRanking && this.noRankingWidth) {
html += '#recommend .card-list>.zone-list-box.storey-box, #recommend .zone-module>.l-con{width: 100% !important;}';
}
const reduceHeight = this.reduceHeight? ' - 12px' : '';
//设置推荐容器宽高
if (element.isNew) {
html +=
`#recommend .storey-box, #ranking-all ul.rank-list{height:calc(404px / 2 * ${this.boxHeight} ${reduceHeight})}`
+ `@media screen and (max-width: 1438px) { #recommend .storey-box, #ranking-all ul.rank-list{height:calc(364px / 2 * ${this.boxHeight} ${reduceHeight})} }`;
if(this.setListWidth) {
//新版的推荐容器宽度针对设置,该方法由初始化推荐容器的方法自行构造,真是深井冰的一团糟乱调用
this.setListWidth();
}
}
else {
//旧版因为固定间隔布局的原因,无论滚动条在内还是在外是否显示均需要维持比外层多一个滚动条宽度
html += `#recommend .storey-box {height:calc(336px / 2 * ${this.boxHeight}${reduceHeight})}`
+ `#ranking-all ul.rank-list{height:calc(336px / 2 * ${this.boxHeight}${reduceHeight} - 16px)}`
+ '#recommend #recommend-list{width:calc(100% + 20px)!important;}';
}
if (this.forceWidth) {
//强制加宽低分辨率
html += `
@media screen and (max-width: 1654px) {
.b-footer-wrap .zone-list-box .live-card:nth-child(n+9):nth-child(-n+10),
.b-footer-wrap .zone-list-box .video-card-common:nth-child(n+9):nth-child(-n+10),
.b-wrap .zone-list-box .live-card:nth-child(n+9):nth-child(-n+10),
.b-wrap .zone-list-box .video-card-common:nth-child(n+9):nth-child(-n+10),
.b-footer-wrap .manga-list-box .manga-card:nth-child(n+9):nth-child(-n+10),
.b-wrap .manga-list-box .manga-card:nth-child(n+9):nth-child(-n+10),
.b-footer-wrap .extension .video-card-common:nth-child(5),
.b-wrap .extension .video-card-common:nth-child(5),
.b-footer-wrap .rcmd-box-wrap>.rcmd-box .video-card-reco:nth-child(n+7):nth-child(-n+8),
.b-wrap .rcmd-box-wrap>.rcmd-box .video-card-reco:nth-child(n+7):nth-child(-n+8),
.b-footer-wrap .recommend-box .video-card-reco:nth-child(n+7):nth-child(-n+8),
.b-wrap .recommend-box .video-card-reco:nth-child(n+7):nth-child(-n+8){
display:block !important;
}
.b-wrap .rcmd-box-wrap>.rcmd-box {
width: 690px !important;
}
.b-footer-wrap .recommend-box, .b-wrap .recommend-box {
width: 717px !important;
}
.b-footer-wrap .extension, .b-wrap .extension,
.b-footer-wrap .zone-list-box, .b-wrap .zone-list-box,
.b-footer-wrap .manga-list-box, .b-wrap .manga-list-box {
width: 880px !important;
}
.b-footer-wrap .elevator, .b-wrap .elevator {
margin-left: 602px !important;
}
.b-footer-wrap .zone-list-box .time-line-card, .b-wrap .zone-list-box .time-line-card {
width: 210px !important;
margin: 0 5px 13px 0!important;
}
.b-wrap {
width: 1150px !important;
}
.b-footer-wrap .zone-list-box .article-card, .b-wrap .zone-list-box .article-card {
width: 440px;
}
.van-popper[x-placement^=top] {
top: 208px !important;
}
.van-popper[x-placement^=top] .popper__arrow {
top: -6px;
border-width: 6px !important;
border-color: transparent !important;
border-bottom-color: #ebeef5 !important;
border-top-width: 0 !important;
}
.van-popper[x-placement^=top] .popper__arrow:after {
bottom: 3px;
top: 1px;
}
.van-popper[x-placement^=top] .popper__arrow:after {
border-top-color: transparent !important;
border-bottom-color: #fff;
border-top-width: 0 !important;
border-bottom-width: 6px !important;
}
/*旧版*/
.bili-wrapper { width: 1160px !important; }
.bili-wrapper .l-con { width:900px !important; }
.elevator-module { margin-left: 590px !important;}
}
`;
}
this.styleDiv.innerHTML = html;
},
show(){
if(this.dialog) return document.body.appendChild(this.dialog);
this.dialog = element._c({
nodeType:'div',
id:'biliAppHomeSetting',
style:'position: fixed;top: 0;bottom: 0;left: 0;right: 0;background: rgba(0,0,0,0.4);z-index: 10000;',
childs:[{
nodeType:'div',
style:'width:400px;right:0;left:0;position:absolute;padding:20px;background:#fff;border-radius:8px;margin:auto;transform:translate(0,50%);box-sizing:content-box',
childs:[
'',
{
nodeType:'h2',innerText:'APP首页推荐设置',
style:"font-size: 20px;color: #4fc1e9;font-weight: 400;",
childs: [{
nodeType:'span',innerText:'X',
style:"float:right;cursor: pointer;",
onclick:()=>document.body.removeChild(this.dialog)
}]
},
/*
{
nodeType:'div',style:'margin: 10px 0;',
childs: [
'',
`(?)`,
{
nodeType:'select',
style:'vertical-align: top',
onchange:({target})=>GM_setValue('rankingDay',(this.rankingDay = target.value)),
childs:Object.entries(this.rankingDays).map(([day,text])=>({
nodeType:'option',value:day,innerText:text,
})),
value:this.rankingDay
}
]
},
*/
{
nodeType:'div',style:'margin: 10px 0;',
childs: [
'',
`(?)`,
{
nodeType:'input',type:'number',value:this.historyLimit,min:0,step:10,
onchange:({target})=>this.setHistoryLimit(target.value),
style:'width:50px'
},
]
},
{
nodeType:'div',style:'margin: 10px 0;',
childs: [
'',
`(?)`,
{
nodeType:'input',type:'number',value:this.pageLimit,min:0,step:10,
onchange:({target})=>this.setPageLimit(+target.value),
style:'width:50px'
}
]
},
{
nodeType:'div',style:'margin: 10px 0;',
childs: [
'',
'(?)',
{
nodeType:'input',type:'number',value:this.autoFreshCount,min:0,step:1,
onchange:({target})=>this.setAutoFreshCount(+target.value),
style:'width:50px'
}
]
},
{
nodeType:'div',style:'margin: 10px 0;',
childs: [
'',
'(?)',
{
nodeType:'input',type:'number',value:this.manualFreshCount,min:1,step:1,
onchange:({target})=>this.setManualFreshCount(target),
style:'width:50px'
}
]
},
{
nodeType:'div',style:'margin: 10px 0;',
childs: [
'',
'(?)',
{
nodeType:'input',type:'number',value:this.boxHeight,min:2,step:2,
onchange:({target})=>this.setBoxHeight(+target.value),
style:'width:50px'
}
]
},
{
nodeType:'div',style:'margin: 10px 0;',
childs: [
'',
'(?)',
{
nodeType:'input',value:this.hotkey,
onkeydown:ev => this.setHotkey(ev),
style:'width:50px'
}
]
},
{
nodeType:'div',style:'margin: 10px 0;',
childs: [
'',
'(?)',
{
nodeType:'input',type:'checkbox',checked:this.reduceHeight,
onchange:({target})=>this.setReduceHeight(target.checked),
style:'vertical-align: bottom',
},
]
},
{
nodeType:'div',style:'margin: 10px 0;',
childs: [
'',
'(?)',
{
nodeType:'input',type:'checkbox',checked:this.noRanking,
onchange:({target})=>this.setNoRanking(target.checked),
style:'vertical-align: bottom',
},
]
},
{
nodeType:'div',style:'margin: 10px 0;',
childs: [
'',
'(?)',
{
nodeType:'input',type:'checkbox',checked:this.noScrollBar,
onchange:({target})=>this.setScrollBar(target.checked),
style:'vertical-align: bottom',
},
]
},
{
nodeType:'div',style:'margin: 10px 0;',
childs: [
'',
'(?)',
{
nodeType:'input',type:'checkbox',checked:this.noRankingWidth,
onchange:({target})=>this.setNoRankingWidth(target.checked),
style:'vertical-align: bottom',
},
]
},
{
nodeType:'div',style:'margin: 10px 0;',
childs: [
'',
'(?)',
{
nodeType:'input',type:'checkbox',checked:this.forceWidth,
onchange:({target})=>this.setForceWidth(target.checked),
style:'vertical-align: bottom',
},
]
},
{
nodeType:'div',style:'margin: 10px 0;',
},
{
nodeType:'div',style:'margin: 10px 0;',
childs: [
'',
`(?)`,
{
nodeType:'button',
style:'padding:0 15px;height:30px;background:#4fc1e9;color:white;border-radius:5px;border:none;cursor:pointer;',
innerText:this.accessKey?'删除授权':'获取授权',
onclick:({target})=>this.handleKey(target)
},
]
},
{
nodeType:'div',
childs:[
'github问题反馈',
`当前版本:${GM_info.script.version}`
]
}
]
}],
parent:document.body
});
},
handleKey(target){
if (target.innerText === '删除授权') {
this.storageAccessKey(undefined);
target.innerText = '获取授权';
tools.toast('删除授权成功');
return;
}
else {
if (!confirm('提示!此脚本当前使用扫码登陆接口获取授权,确认获取授权你将收到一条你当前地址扫码登陆的记录,如果有不信任请点击取消,自行检查源码或者删除此脚本。')){
return;
}
target.innerText = '获取中...';
target.style['pointer-events'] = 'none';
new BilibiliToken().getToken().then(res=>{
if (res?.access_token) {
this.storageAccessKey(res.access_token);
tools.toast('获取授权成功');
target.innerText = '删除授权';
//document.body.contains(iframe) && document.body.removeChild(iframe);
}
else {
throw({tip:'获取授权失败',msg:'没有获得匹配的密钥',data:res});
}
}).catch(error=> {
target.innerText = '获取授权';
tools.toast(`${error.tip}:${error.msg}`,error);
}).then(()=>{
target.style['pointer-events'] = 'unset';
});
}
}
};
//页面元素助手,包含克隆的一个未初始化版块和创建、设置页面元素的简单封装
const element = {
mainDiv:(()=>{
try{
return document.querySelector('#bili_douga').cloneNode(true);
}catch(e){
return undefined;
}
})(),
getLoadingDiv(target){
return this._c({
nodeType:'div',style:target=='recommend'?'padding:0;width:100%;height:unset;text-align: center;':'text-align: center;',
className:target=='recommend'?'load-state spread-module':'load-state',
innerHTML:'正在加载...'
});
},
_c(config){
if(config instanceof Array) return config.map(item=>this._c(item));
const item = document.createElement(config.nodeType);
return this._s(item,config);
},
_s(item,config){
for(const i in config){
if(i=='nodeType') continue;
if(i=='childs' && config.childs instanceof Array) {
config.childs.forEach(child=>{
if(child instanceof HTMLElement) item.appendChild(child);
else if (typeof(child)=='string') item.insertAdjacentHTML('beforeend',child);
else item.appendChild(this._c(child));
});
}
else if(i=='parent') {
config.parent.appendChild(item);
}
else if(config[i] instanceof Object && item[i]){
Object.entries(config[i]).forEach(([k,v])=>{
item[i][k] = v;
});
}
else{
item[i] = config[i];
}
}
return item;
}
};
//一些通用模块
const tools = {
token:(()=>{
try{
return document.cookie.match(/bili_jct=([0-9a-fA-F]{32})/)[1];
}catch(e){
console.error('添加APP首页推荐找不到token,请检查是否登录');
return undefined;
}
})(),
imgType:(()=>{
try{
return 0==document.createElement('canvas').toDataURL("image/webp").indexOf("data:image/webp")?'webp':'jpg';
}catch(e){
return 'jpg';
}
})(),
toast(msg,error){
if(error) console.error(msg,error);
const div = element._c({
nodeType:'div',
style:'position: fixed;top: 50%;left: 50%;z-index: 999999;padding: 12px 24px;font-size: 14px;'
+'width: 240px; margin-left: -120px;background: #ffb243;color: #fff;border-radius: 6px;',
innerHTML:msg,
parent:document.body
});
setTimeout(()=>document.body.removeChild(div),2000);
return false;
},
formatNumber (input,format='number'){
if (format=='time'){
let second = input%60;
let minute = Math.floor(input/60);
let hour;
if (minute>60){
hour = Math.floor(minute/60);
minute = minute%60;
}
if (second<10) second='0'+second;
if (minute<10) minute='0'+minute;
return hour?`${hour}:${minute}:${second}`:`${minute}:${second}`;
}else{
return input>9999?`${(input/10000).toFixed(1)}万`:input||0;
}
},
watchLater (ev){
const target = ev.target;
const req = new XMLHttpRequest();
const action = target.classList.contains('added')?'del':'add';
req.open('POST','//api.bilibili.com/x/v2/history/toview/'+action);
req.withCredentials = true;
req.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=UTF-8');
req.onload = res=>{
try{
var list = JSON.parse(res.target.response);
if (list.code!=0){
tools.toast(`请求稍后再看错误 code ${list.code}msg:${list.message}`,{list,target});
return;
}
target.classList.toggle('added');
target.title = target.classList.contains('added')?'移除稍后再看':'稍后再看';
}catch(e){
tools.toast('请求稍后再看发生错误',e);
}
};
req.send(`aid=${target.dataset.aid}&csrf=${tools.token}`);
return false;
},
//视频预览……做得挺深井冰的……
previewImage (pv,target,width) {
if(!pv||!target||!target.cover) return;
let pWidth = target.parentNode.offsetWidth, data = target.cover,
percent = +width/pWidth,
index = Math.floor(percent*data.index.length),
url = data.image[Math.floor(index/data.img_x_len/data.img_y_len)],
size = pWidth * data.img_x_len,
y = Math.floor(index/data.img_x_len) * -pWidth/data.img_x_size * data.img_y_size,
x = (index % target.cover.img_x_len) * -pWidth;
if(pv.classList.contains('van-framepreview')) {
if(pv.classList.contains('ranking')) y += 10;
pv.style = `background-image: url(${url}); background-position: ${x}px ${y}px; background-size: ${size}px;opacity:1;`;
pv.innerHTML = `
`;
}
else {
pv.innerHTML = ``
+ `
`
}
},
previewDanmu (target,status) {
if(!target||!target.data||!target.data.length||!target.previewDanmu) return;
clearInterval(target.timmer);
if(status) {
target.previewDanmu();
target.timmer = setInterval(target.previewDanmu, 2.5*1000);
}
else {
target.style.opacity = 0;
}
},
preview (ev){
if(!ev.target) return;
let deep = 1,target = ev.target;
while(!target.dataset.id&&deep++<4){
target=target.parentNode;
}
const pv = target.querySelector('.cover-preview-module'),
danmu = target.querySelector('.danmu-module');
if(!pv||!danmu) return;
if(ev.type=='mouseenter') {
target.timmer = setTimeout(()=>{
if(!target.timmer) return;
pv.classList.add('show');
danmu.classList.add('show');
if(!target.cover) {
fetch(`//api.bilibili.com/pvideo?aid=${target.dataset.id}&_=${Date.now()}`)
.then(res=>res.json())
.then(d=>(target.cover = d.data))
.then(()=>fetch(`//api.bilibili.com/x/v2/dm/ajax?aid=${target.dataset.id}&_=${Date.now()}`))
.then(res=>res.json())
.then(d=>{
danmu.data = d.data;
danmu.count = 0;
danmu.previewDanmu = function (){
danmu.style.opacity = 1;
if(danmu.count%danmu.data.length==0) {
danmu.count = 0;
danmu.innerHTML = danmu.data.map((item,i)=>`${item}
`).join('');
}
const item = danmu.children[danmu.count++];
if(!item) return;
item.style = `left: -${item.offsetWidth}px; transition: left 5s linear 0s;`;
};
if(!target.timmer) return;
tools.previewImage(pv,target,ev.offsetX);
tools.previewDanmu(danmu, true);
delete target.timmer;
});
}
else {
tools.previewImage(pv,target,ev.offsetX);
tools.previewDanmu(danmu, true);
delete target.timmer;
}
},100);
}
else if(ev.type=='mouseleave') {
clearTimeout(target.timmer);
delete target.timmer;
pv.classList.remove('show');
if(pv.classList.contains('van-framepreview')) {
pv.style.opacity = 0;
}
danmu.classList.remove('show');
tools.previewDanmu(danmu, false);
}
else {
if(!target.cover) return;
tools.previewImage(pv,target,ev.offsetX);
}
}
};
//初始化
function init() {
if (document.querySelector('.international-home')) {
element.isNew = 1;
} else if (document.querySelector('#i_cecream')) {
element.isNew = 2;
throw 'Bilibili APP首页脚本目前尚未适配新版主页,点击https://github.com/indefined/UserScripts/issues/76 查看详情';
}
try{
setting.init();
InitRecommend();
window.addEventListener("beforeunload", ()=>setting.saveHistory());
InitRanking();
}catch(e){
console.error(e);
}
}
if (element.mainDiv){
init();
}
else if (location.pathname == "/apphome") {
document.head.insertAdjacentHTML('beforeend',`
`);
document.getElementById('internationalHeader').insertAdjacentHTML('afterend', `
`);
document.title = "Bilibili App 首页推荐";
element.mainDiv = document.querySelector('#bili_douga');
init();
}
else if (document.querySelector('#i_cecream')) {
element.isNew = 2;
throw 'Bilibili APP首页脚本未适配新版主页,请使用 https://greasyfork.org/zh-CN/scripts/443530-bilibili-app-recommend 代替';
}
else {
if(document.head.querySelector('link[href*=home]')) {
setting.setStyle();
//console.log('observe');
new MutationObserver((mutations,observer)=>{
//console.log(mutations)
for(const mutation of mutations){
for (const node of mutation.addedNodes) {
if(node.id=='bili_douga' || node.className=='bili-grid') {
observer.disconnect();
element.mainDiv = node.cloneNode(true);
init();
return;
}
}
}
}).observe(document.body,{
childList: true,
subtree: true,
});
}
}
})();