平时都在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
更新
  1. 保留每次存档✓
  2. 检查更新,因为有时间戳,非常方便
备选
  1. 管理存档
  2. 处理一下读缓存时的报错