Onedrive图床Nodebb论坛插件开发
1. 前言
说到图床,真是一言难尽呀。找了半天发现没有一个完全令人满意。不谈是否能长远稳定,但就使用多少有些问题。
国内的很多图床限制太多,单张图片限制,总容量太小,流量限制,大多都没有api。
国外的图床限制少点儿,单张容量可达30m,不限流量,也有api可以满足需求,体验也不错。
但是最大的问题在于国内访问的速度是真慢,有的网络甚至无法访问。
至于为什么一定要api支持,因为我对可控性(control)和可移植性(portable)非常执念,通过api用脚本可以方便转移和部署。
因此想着用onedrive作为后端来搞个图床,顺便来diy个共享网盘。这种方法的好处是自己完全掌控,可以很方便的进行备份,迁移等操作。虽然api访问次数没有明说。
由于相关api开发教程不是很多,自己也踩了不少坑,onedrive的api对于新手不太友好,很多概念令人很费解,感觉有必要写个文章来梳理一下。
2 . Onedrive共享盘搭建方案
这部分倒是已经有现成的方案做的不错了,没必要重复造轮子了,我就直接用的FODI了。
由于我不会php,也不想装php环境,此处就没有考虑。为了练习node,以js语言为主。
FODI
这个非常界面非常清爽,但是功能不少:支持markdown,音视频图片等媒体文件在线预览,直链下载。而且配置起来也很方便,cloudflare worker单文件就行。
logi向导界面选择版本后点前往登录,然后把浏览器地址栏返回的地址复制到对应填表位置(页面本身是显示失败的),为了得到refresh token。之后将生成代码复制到worker里。
参数proxied表示用代理。注意网盘不能是空的,否则会报错。
ondrive-cf-index
还有另外一个框架是onedrive-cf-index,但是这个部署起来就麻烦多了。要自己去azure手动配置,多文件要用cf的命令行工具,我这里一直报错。而且还要去用firebase数据库。试了一下此方案放弃。
cuteone
cuteone, python引擎编写的,据说很强大的工具,可以多盘管理,还有用户权限管理相关的。
不过我没有尝试,但是看着不错,就放在这里参考了。
3. Onedrive以FODI为例图床搭建
这里以FODI为例来说明怎么改造成图床。其实最简单的方法,直接看其生成的链接,可直接用。
在cf worker上部署后是 xxx.yyy.workers.dev?file=/path/to/file
格式。
但是总觉得挺奇怪的,明明是静态资源却还要query,强迫症感觉很别扭。
因此我们用nginx加一层反向代理,通过rewrite或者set $args将静态资源改成查询的。
这样的好处是之后可以多网盘负载均衡,而且反向代理有点像符号链接,迁移网盘改个映射就行了。
1 | server { |
顺便一提,我不太喜欢直接修改源码,因为每次更新后都要merge,非常麻烦,我的原则尽量不在原来的上面直接改。多用间接的方案,比如插件或hook。
4. Onedrive api 分析
关于onedrive的api,可以来看onedrive文档,在nodejs环境下,可以用封装好的onedrive-api,引入 const odapi = require('onedrive-api')
auth
使用onedrive api之前必须要进行认证,认证流程如下图, 详见graph-oauth:
.1 进入azure将redirect_uri指向microsoft-graph-api-auth页面,并开启offline_access Files.Read Files.Read.All Files.Write Files.WriteAll权限,创建secret
.2 然后在microsoft-graph-api-auth填写client id, scope(权限)认证后, 填client secret即可得到accesstoken, refreshtoken。
access_token是临时的为了暂时共享,refresh_token长时有效来获取access_token
.3 用refreshtoken获取accesstoken(需要offline_access 权限,可省略redirect_uri)
1 | POST https://login.microsoftonline.com/common/oauth2/v2.0/token |
关于refresh_token的获取,或者用simple-oauth2来获取。
由于onedrive-api里面没有auth相关的用法,我们需要根据上述api和axios
自己来封装一下,如下:
1 | async function odauth(client_id, client_secret, refresh_token){ |
需要注意的是,这个api是用了application/x-www-form-urlencoded
格式,因此payload需要是get里的query字符串拼接格式
listChildren
1 | var res = await odapi.items.listChildren({ // 返回字目录数组,结果有name和id, webUrl |
createFolder
1 | odapi.items.createFolder({ // 同理也返回name,id和webUrl |
delete
1 | odapi.items.delete({ |
update
1 | odapi.items.update({ // 改名 |
download
1 | var fileStream = odapi.items.download({ // 全部下载 |
upload
1 | odapi.items.uploadSimple({ |
share
5. Nodebb onedrive 上传插件编写
熟悉了上述的api,我们终于可以编写论坛上传图到OneDrive的插件了!
思路是在触发filter:uploadImage
这个的时候将图片通过api上传的onedrive上面,
并await图片位置和nginx反向代理的地址返回给nodebb。
开发nodebb的插件还是挺费劲的,详见中文文档中的吐槽。说一下我的调试方法吧
mongodump
,mongoestore
克隆数据库到本地,不要在线上生产环境开发npm link
和nodebb dev
来观看日志慢慢调,各个变量用之前先打印看看- 报错非常不直观,一个拼写错误可能就使得插件无法加载,不能定位到出错点
详细代码见 nodebb-plugin-onedrive,最后来个插件截图吧~