2020506 谢谢评论大佬,更新一下世纪互联的问题。世纪互联需要专门的链接获取refresh_token。在下方更新。
这也是忽然而产生的一个想法。最近hk服务器到期,需要迁移自己以前搭建的olaindex和pyone。但是现实不是那么美好,自己已经没有闲置服务器可以用了,我也不想再购买新服务器,因为好多东西,瞎折腾也免不了吃灰的厄运。既花了钱,也没能够增强自己的技术。于是便想着有没有免费的方法。
其实还有Heroku这个工具可以部署onelist。但是我记得用cf可以部署goindex这种谷歌网盘的列表程序。虽然cf已经被玩坏了,cf搭建goindex已经没有速度了。但是onedrive国内可以直接访问,那么就不需要经过cf,应该可以保证一定的速度。那么是不是cf可以部署onedrive的列表程序呢?有了想法,立马去百度 and google 了一下,终于找到了一个程序FODI这个程序,是支持使用云函数部署的。
FODI( Fast OneDrive Index )
- 接近秒速列表;
- 指定展示路径;
- 特定文件夹加密;
- 无需服务器免费部署;
- 基本文本、图片、音视频和 Office 三件套预览;
FODI 程序的开源地址如下:
https://github.com/vcheckzen/FODI
但是官网不知什么原因,作者并没有维护。那个部署步骤已经没办法看了。但是幸运的是,vircloud大佬已经写了一个教程,把基本步骤已经写明,于是,我参考大佬的教程,来造这个轮子。
一、获取refresh_token
国际版访问如下网址:
点击 Get a refresh_token ,然后使用你的office365账户登录
如果你是世纪互联(国内版onedrive)(比如同济大学的)请访问如下链接:
https://service-gzs9xkdm-1256127833.ap-hongkong.apigateway.myqcloud.com/release/onedrive-token-cn
登录完成后你发现又返回原来的界面。然后需要把地址栏的链接中
.../?authorization_code&code=...
为
.../authorization_code?code=...
并重新访问,修改完后如下。
复制返回的 refresh_token
存储下来。
二、cloudflare后台操作
1.进入cf workers后台,选择新建worker
2.复制如下代码,到worker编辑器中
/**
* IS_CN: 如果为世纪互联版本,请将 0 改为 1
* EXPOSE_PATH:暴露路径,如全盘展示请留空,否则按 '/媒体/音乐' 的格式填写
* ONEDRIVE_REFRESHTOKEN: refresh_token
*/
const IS_CN = 0;
const EXPOSE_PATH = ""
const ONEDRIVE_REFRESHTOKEN = ""
async function handleRequest(request) {
let requestPath
let querySplited
let queryString = request.url.split('?')[1]
if (queryString) {
querySplited = queryString.split('=')
}
if (querySplited && querySplited[0] === 'file') {
const file = querySplited[1]
const fileName = file.split('/').pop();
requestPath = file.replace('/' + fileName, '')
const url = await fetchFiles(requestPath, fileName)
return Response.redirect(url, 302)
} else {
const { headers } = request
const contentType = headers.get('content-type')
let body={}
if (contentType && contentType.includes('form')) {
const formData = await request.formData()
for (let entry of formData.entries()) {
body[entry[0]] = entry[1]
}
}
requestPath = body ? body['?path'] : '';
const files = await fetchFiles(requestPath, null, body.passwd);
return new Response(files, {
headers: {
'content-type': 'application/json; charset=utf-8',
'Access-Control-Allow-Origin': '*'
}
})
}
}
addEventListener('fetch', event => {
return event.respondWith(handleRequest(event.request))
})
const clientId = [
'4da3e7f2-bf6d-467c-aaf0-578078f0bf7c',
'04c3ca0b-8d07-4773-85ad-98b037d25631'
]
const clientSecret = [
'7/+ykq2xkfx:.DWjacuIRojIaaWL0QI6',
'h8@B7kFVOmj0+8HKBWeNTgl@pU/z4yLB'
]
const oauthHost = [
'https://login.microsoftonline.com',
'https://login.partner.microsoftonline.cn'
]
const apiHost = [
'https://graph.microsoft.com',
'https://microsoftgraph.chinacloudapi.cn'
]
const OAUTH = {
'redirectUri': 'https://scfonedrive.github.io',
'refreshToken': ONEDRIVE_REFRESHTOKEN,
'clientId': clientId[IS_CN],
'clientSecret': clientSecret[IS_CN],
'oauthUrl': oauthHost[IS_CN] + '/common/oauth2/v2.0/',
'apiUrl': apiHost[IS_CN] + '/v1.0/me/drive/root',
'scope': apiHost[IS_CN] + '/Files.ReadWrite.All offline_access'
}
async function gatherResponse(response) {
const { headers } = response
const contentType = headers.get('content-type')
if (contentType.includes('application/json')) {
return await response.json()
} else if (contentType.includes('application/text')) {
return await response.text()
} else if (contentType.includes('text/html')) {
return await response.text()
} else {
return await response.text()
}
}
async function getContent(url) {
const response = await fetch(url)
const result = await gatherResponse(response)
return result
}
async function getContentWithHeaders(url, headers) {
const response = await fetch(url, { headers: headers })
const result = await gatherResponse(response)
return result
}
async function fetchFormData(url, data) {
const formdata = new FormData();
for (const key in data) {
if (data.hasOwnProperty(key)) {
formdata.append(key, data[key])
}
}
const requestOptions = {
method: 'POST',
body: formdata
};
const response = await fetch(url, requestOptions)
const result = await gatherResponse(response)
return result
}
async function fetchAccessToken() {
url = OAUTH['oauthUrl'] + 'token'
data = {
'client_id': OAUTH['clientId'],
'client_secret': OAUTH['clientSecret'],
'grant_type': 'refresh_token',
'requested_token_use': 'on_behalf_of',
'refresh_token': OAUTH['refreshToken']
}
const result = await fetchFormData(url, data)
return result.access_token
}
async function fetchFiles(path, fileName, passwd) {
if (!path || path === '/') {
if (EXPOSE_PATH === '') {
path = ''
} else {
path = ':' + EXPOSE_PATH
}
} else {
if (EXPOSE_PATH === '') {
path = ':' + path
} else {
path = ':' + EXPOSE_PATH + path
}
}
const accessToken = await fetchAccessToken()
const uri = OAUTH.apiUrl + encodeURI(path) + '?expand=children(select=name,size,parentReference,lastModifiedDateTime,@microsoft.graph.downloadUrl)'
const body = await getContentWithHeaders(uri, {
Authorization: 'Bearer ' + accessToken
})
if (fileName) {
let thisFile = null
body.children.forEach(file => {
if (file.name === decodeURIComponent(fileName)) {
thisFile = file['@microsoft.graph.downloadUrl']
return
}
})
return thisFile
} else {
let files = []
let encrypted = false
for (let i = 0; i < body.children.length; i++) {
const file = body.children[i]
if (file.name === '.password') {
const PASSWD = await getContent(file['@microsoft.graph.downloadUrl'])
if (PASSWD !== passwd) {
encrypted = true;
break
} else {
continue
}
}
files.push({
name: file.name,
size: file.size,
time: file.lastModifiedDateTime,
url: file['@microsoft.graph.downloadUrl']
})
}
let parent
if (body.children.length) {
parent = body.children[0].parentReference.path
} else {
parent = body.parentReference.path
}
parent = parent.split(':').pop().replace(EXPOSE_PATH, '') || '/'
parent = decodeURIComponent(parent)
if (encrypted) {
return JSON.stringify({ parent: parent, files: [], encrypted: true })
} else {
return JSON.stringify({ parent: parent, files: files })
}
}
}
代码就是程序根目录中back-end-cf文件夹中的index.js(链接是文件Github地址)中的内容。然后把保存的 refresh_token 在指定位置修改,至于是不是世纪互联,和想展示哪个目录,请按程序注释修改。
保存生成
然后为如下界面
然后回到主界面
可以改称自己认为比较好的名,亦可以不改。记住这个域名。
三、部署程序主页
把引导页(位于front-end文件夹中的index.html)( 链接为文件的Github地址)部署到你的服务器上,当然也可以部署到Github Pages中,这儿可操作性太强了,我就不再描述了。然后需要修改文件中的SCF_GATEWAY。
这儿地址要加上https。
然后访问这个文件就可以,就可以看到这个页面了。这个页面是真的简洁,哈哈哈。没想到的简洁。打开要等几秒,才会显示内容。
几点小注意:(摘自vircloud.net)
- 支持加密,在需加密的文件夹中新增 .password 文件,编码为 UTF8NoBOM ,内容为密码即可;
- 后端实际上返回的是
json
,所以前端其实是可以自己做一个的。 - 内容传输时使用的地址是 OneDrive 官方地址,所以速度还是有保证的;
- Worker 部署完是无法 GET 方式访问的,会提示“Error 1101 Worker threw exception”,不必理会;
文章评论
发现同济的edu 获取不了refresh_token~
@lisaooo 同济的账号应该没开api吧。另外同济的是不是世纪互联的啊。
@小菜菜 同济是世纪互联。
成功了,要点世纪互联版token获取连接才行
https://567899.xyz/fodi.html
@lisaooo 同济的真香啊,还给开API
@小菜菜 试了下FODI感觉一般。还是退回用Zfile啦
https://odrive.peter173.cf/
@lisaooo 简洁到不可描述,要想使用还是需要有点前端知识,自己在开发下
把引导页(位于front-end文件夹中的index.html)( 链接为文件的Github地址)部署到你的服务器上,当然也可以部署到Github Pages中,这儿可操作性太强了,我就不再描述了。然后需要修改文件中的SCF_GATEWAY。
这怎么操作
@jacob 静态文件丢到随便一个服务器上就行了,我记得截图很清楚的