B站动态自动归档
平时都在B站上看视频并随手用B站动态记笔记,留下思维线索。 需要一个js小工具把随手发在B站的笔记自动摘抄下来, 包括笔记不幸被吞的情况,最好也能及时抄录。 ……现成的看来没有,自己写吧。
抄录
a=[...document.querySelectorAll('.bili-rich-text__content>span')]
console.log(a.length)
console.assert(a.length==13)
a.forEach(a=>a.style='color:silver')
a.map(a=>a.innerHTML)
3
a=[...document.querySelectorAll('.bili-dyn-item__main')]
a=a.map(a=>{
a.style='background:gray';
return[a.querySelector('.bili-dyn-time').innerHTML.trim(),
a.querySelector('.bili-rich-text__content').innerHTML]})
///本地保存
localStorage.archives=JSON.stringify(a)
b=JSON.parse(localStorage.archives)
解析日期
d=new Date().setHours(0,0,0,0)
new Date().toLocaleDateString()
a=JSON.parse(localStorage.archives)
a=a.map(a=>{
a.style='background:gray';
return[a.querySelector('.bili-dyn-time').innerHTML.trim(),
a.querySelector('.bili-rich-text__content').innerHTML]})
///本地保存
localStorage.archives2=JSON.stringify(a)
b=JSON.parse(localStorage.archives2)
从fetch缓存建立初始档
loadCache=async(a)=>{
a=await fetch(a,{mode:'same-origin',cache:'only-if-cached'})
.then(a=>{
if(a.ok){console.log('Cached')}else if(a.status==504){console.log('Not cached')}
return a
})
.catch(error=>console.error(error))
return(await a.json()).data
}
extract=(a)=>
[a.items.map(a=>{
b=a.modules.module_dynamic.desc
b={text:b.text,b:b.rich_text_nodes[0].text,c:b.rich_text_nodes[0].orig_text}
console.assert(b.text==b.b&&b.b==b.c||b.text=='[给心心][给心心][给心心]',b)
return[b.text,a.modules.module_author.pub_ts]
}),a.offset]
nextPg=offset=>window.location.href.replace('offset=&',`offset=${offset}&`)
async function*load(offset=''){
a=await loadCache(nextPg(offset)).catch(()=>'return')
if(a=='return')return
var[a,offset]=extract(a)
yield*await a
yield*load(offset)
}
//确认ts都是unique
checkTsUnique=items=>(new Set(items.map(([_,ts])=>ts)).size)==items.length
a=[];for await(i of load())a.push(i)
console.assert(checkTsUnique(a))
k='archive_'+Math.round(Date.now()/1000)
localStorage[k]=JSON.stringify(a)
localStorage
生成Jekyll文件
loadLatestRaw=()=>localStorage[localStorage.key(0)]
formatFiles=async a=>{
groupBy=(x,f)=>x.reduce((a,b,i)=>((a[f(b,i,x)]||=[]).push(b),a),{})
const name=d=>`${d.getFullYear()-2000}-${d.getMonth()+1}-${d.getDate()}-.md`
file=a=>`---\ntweets: |-\n ${a.replaceAll('\n','\n ')}\n---\n{{page.tweets}}`
a=JSON.parse(a)
a=groupBy(a,([_,d])=>name(new Date(d*1000)))
b=[];for await(i of Object.keys(a))b.push([i,a[i]])
a=b.map(([d,items])=>[d,items.map(([a,_])=>a).join('\n\n')])
return a.map(([a,b])=>[a,file(b)])
}
///生成界面,按每天复制文件名和内容
build=a=>{
input=a=>`<input value=\'${a}\'></input>`
tag=(name,a)=>`<${name}>${a}</${name}>`;div=a=>tag('div',a);pre=a=>tag('pre',a)
textarea=a=>tag('textarea',a)
template=([file,content])=>textarea(file)+textarea(content)
a=a.map(template).join('')
reload=html=>{document.write(html);document.close();return document}
a=reload(a)
a.querySelectorAll('textarea').forEach(a=>{
a.readOnly=true;a.style.width='100%';a.style.resize='none'
a.rows=1;a.style.height="";a.style.height=a.scrollHeight+"px"
copy=t=>navigator.clipboard.writeText(t).then(()=>new Notification('✓ '+t),()=>new Notification('×'))
a.onfocus=(()=>copy(a.value))
})
}
// a=loadLatestRaw();a=await formatFiles(a)
// build(a)
///检查更新
checkStorage=()=>{
a=Object.keys(localStorage)
prefix='archive_';console.assert(a.every(a=>a.startsWith(prefix)))
console.assert(isLatestOnTop=JSON.stringify(a.toSorted().reverse())==JSON.stringify(a))
}
checkStorage()
getNew=async()=>{
var[a,old]=Object.values(localStorage)
var[a,old]=[await formatFiles(a),await formatFiles(old)]
// for(a of a)console.log(a,isNew=!old.some(b=>a[0]==b[0]&&a[1]==b[1]))
function*takeWhile(xs,fn){for (let x of xs)if (fn(x))yield x;else break}
a=takeWhile(a,a=>isNew=!old.some(b=>a[0]==b[0]&&a[1]==b[1]))
return[...a]
}
await getNew()
TODO
更新
- 保留每次存档✓
- 检查更新,因为有时间戳,非常方便
备选
- 管理存档
- 处理一下读缓存时的报错