山野莽夫

  • 归档
    • 随笔
    • 建站资源
    • 分享
    • 代码
  • 地球物理学
    • 专业课
    • 概念解释
  • 计算机
  • 互联网
  • 教程
  • 规划
  • 实验室
    • 珍藏的软件
    • 贴吧云签到
    • A1账号自助申请
山野莽夫
小学生的挣扎的点点滴滴
  1. 首页
  2. 互联网
  3. 正文

使用CloudFlare Workers 零成本部署 OneDrive 文件列表程序FODI(Fast OneDrive Index)

2020年2月20日 8539点热度 0人点赞 8条评论

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

国际版访问如下网址:

https://service-36wivxsc-1256127833.ap-hongkong.apigateway.myqcloud.com/release/scf_onedrive_filelistor

点击 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”,不必理会;

标签: cf cf worker cloudflare CloudFlare Workers FODI onedrive
最后更新:2020年5月6日

小菜菜

菜鸟

打赏 点赞
< 上一篇
下一篇 >

文章评论

  • lisaooo

    发现同济的edu 获取不了refresh_token~

    2020年5月5日
    回复
    • 小菜菜

      @lisaooo 同济的账号应该没开api吧。另外同济的是不是世纪互联的啊。

      2020年5月5日
      回复
      • lisaooo

        @小菜菜 同济是世纪互联。
        成功了,要点世纪互联版token获取连接才行
        https://567899.xyz/fodi.html

        2020年5月6日
        回复
        • 小菜菜

          @lisaooo 同济的真香啊,还给开API

          2020年5月6日
          回复
          • lisaooo

            @小菜菜 试了下FODI感觉一般。还是退回用Zfile啦
            https://odrive.peter173.cf/

            2020年5月6日
          • 小菜菜

            @lisaooo 简洁到不可描述,要想使用还是需要有点前端知识,自己在开发下

            2020年5月6日
  • jacob

    把引导页(位于front-end文件夹中的index.html)( 链接为文件的Github地址)部署到你的服务器上,当然也可以部署到Github Pages中,这儿可操作性太强了,我就不再描述了。然后需要修改文件中的SCF_GATEWAY。
    这怎么操作

    2020年5月7日
    回复
    • 小菜菜

      @jacob 静态文件丢到随便一个服务器上就行了,我记得截图很清楚的

      2020年5月7日
      回复
  • razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
    取消回复

    此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据。

    联系方式

    QQ群 | TG群 | 邮箱

    最新 热点 随机
    最新 热点 随机
    Azure Student 微软云 学生订阅 免费12个月用量避坑注意点集合 MP3音频文件格式详细解析 python按固定采样点个数分割wav格式音频 愉快使用谷歌免费人工智能平台colab,训练你的神经网络模型,为你的学术生活添砖加瓦 华为云版轻量应用服务器-云耀云服务器简单体验评测 Cloudflare 免费CDN自定义节点ip之自选cloudflare 高速节点ip工具分享
    贪吃蛇C语言代码 层速度,平均速度,叠加速度,均方根速度的关系 地震分析软件SAC 华硕A450JF、R409JF、X450JF安装黑苹果 1.5.1文件复制 扁平化ppt模板-3
    标签聚合
    地震学程序 c语言 onedrive 虚拟机 ppt 模板 宝塔面板 wordpress
    最近评论
    小菜菜 发布于 7 个月前(11月24日) 这玩意已经废了,成收割工具了,不能再用了。
    eamon 发布于 8 个月前(11月07日) 我一年不用了才发现这个休眠管理费每月15,一共扣了我135元,然后我消费还消费不了,我宁愿消费掉也不...
    magic 发布于 12 个月前(07月03日) 请问账号不注销会有什么影响吗?
    magic 发布于 12 个月前(07月01日) 我想问一下 如果不注销账号就留着会怎么样
    qwp6601 发布于 1 年前(06月04日) 有没有方法改为bing

    COPYRIGHT © 2021 shanyemangfu.com. ALL RIGHTS RESERVED.

    Theme Kratos Made By Seaton Jiang

    蜀ICP备15031791号-2