Skip to content

Commit

Permalink
support google drive api
Browse files Browse the repository at this point in the history
  • Loading branch information
reruin committed Sep 12, 2019
1 parent 71430f2 commit 4a4fb73
Show file tree
Hide file tree
Showing 9 changed files with 563 additions and 292 deletions.
12 changes: 8 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ node_js:
cache:
directories:
- node_modules
script:
- npm run lint
- npm run test-cov
- npm run bench
install:
- npm install
before_script:
- npm install -g pm2
# script:
# - npm run lint
# - npm run test-cov
# - npm run bench
16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,30 @@ windows挂载webdav可读取文件最大为50M,请[参考](https://answers.mic
#### FileSystem(内置)
提供对本地文件系统的访问。挂载标示```fs```,id为 文件路径,统一使用linux的路径,例如 windows D盘 为 ```/d/```。
#### ShareListDrive(内置)
ShareListDrive是ShareList内置的一种虚拟文件系统,使用yaml构建。以```sld```作为后缀保存。参考[example/ShareListDrive.sld](example)。
ShareListDrive是ShareList内置的一种虚拟文件系统,使用yaml构建。以```sld```作为后缀保存。参考[example/ShareListDrive.sld](example/ShareListDrive.sld)。
#### BasicAuth(内置)
提供基础文件夹加密方式。
#### GoogleDrive
提供对GoogleDrive的访问。挂载标示:```gd```,分享文件夹ID作为路径。
#### GoogleDrive API
GoogleDrive API版挂载插件。挂载标示:```gda```。
支持的挂载标示:
```文件(夹)id->应用ID|应用机钥|refresh_token```
```文件(夹)id->应用ID|应用机钥```
```文件(夹)id```
```/```
ShareList会根据填写的标识,自动开启挂载向导,按指示操作即可。
特别提示:若不填写应用ID|应用机钥,向导将使用 [QuickStart](https://developers.google.com/drive/api/v3/quickstart/nodejs) 生成匿名应用,在授权验证过程中会出现```This app isn't verified.```,请以此点击```Advanced > Go to {Project Name} (unsafe).```即可出现正常的交互问询页面。
#### OneDrive
提供对OneDrive的访问。挂载标示```od```,分享文件夹ID作为路径。
#### ~~OneDrive For Business~~
~~提供对OneDrive Business的访问。挂载标示odb,分享的url作为路径。~~
#### OneDrive API
OneDrive API版挂载插件。挂载标示:```oda```。
路径比较复杂: ```OneDrive路径->应用ID|应用机钥|回调地址|refresh_token```
挂载标示: ```OneDrive路径->应用ID|应用机钥|回调地址|refresh_token```
如果没有能力组织以上标示,也没关系,只需要录入```路径```,ShareList将会在首次访对应地址时,开启挂载向导,按指示操作即可。
例如,需要挂载onedrive的 /abc/123目录,只需输入 ```/abc/123``` 即可。
Expand Down
19 changes: 13 additions & 6 deletions app/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const db = createFiledb(configPath , {raw:true} , {
preview_enable : 1,

webdav_path : '/webdav/',
//目录刷新时间 15分钟
//目录刷新时间 15分钟getDrive
max_age_dir: 15 * 60 * 1000,
//外链 10分钟
max_age_file: 5 * 60 * 1000,
Expand Down Expand Up @@ -49,20 +49,21 @@ const setRuntime = (key , value) => {
runtime[key] = value
}

const saveDrive = (value) => {
const name = decodeURIComponent(runtime.req.path.replace(/^\//g,''))
const saveDrive = (value , name) => {
if(!name) name = decodeURIComponent(runtime.req.path.replace(/^\//g,''))

const path = getPath()
console.log('save' , name , value)
let hit = path.find( i => i.name == name)
if(hit){
hit.path = value
db.save(path)
}
}

//获取当前路径drive
const getDrive = () => {
const path = getPath()
const name = decodeURIComponent(runtime.req.path.replace(/^\//g,''))
const name = decodeURIComponent(runtime.req.path.replace(/^\//g,'').split('/')[0])
const hit = path.find( i => i.name == name)
if(hit){
return hit.path
Expand All @@ -71,4 +72,10 @@ const getDrive = () => {
}
}

module.exports = { getConfig , getAllConfig, save , installed , getPath , setRuntime , getRuntime , saveDrive , getDrive , getSkin }
//获取使用特定协议的drive
const getDrives = (protocols) => {
const path = getPath()
return path.filter(i => protocols.includes(i.path.split(':')[0]))
}

module.exports = { getConfig , getAllConfig, save , installed , getPath , setRuntime , getRuntime , saveDrive , getDrive , getSkin , getDrives }
142 changes: 103 additions & 39 deletions app/services/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,39 @@ const { sendFile , sendHTTPFile ,sendStream, getFile, getHTTPFile } = require('.

const assign = (...rest) => Object.assign(...rest)

let driveMap = new Map()
const driveMap = new Map()

let driveMountableMap = new Map()
const driveMountableMap = new Map()

let formatMap = new Map()
const formatMap = new Map()

let authMap = new Map()
const authMap = new Map()

let previewMap = new Map()
const previewMap = new Map()

let resources = {}
const resources = {}

let resourcesCount = 0
const whenReadyHandlers = []

const whenReady = (handler) => {
if(ready) {
return Promise.resolve(handler())
}else{
return new Promise((resolve,reject) => {
whenReadyHandlers.push( () => {
resolve(handler())
})
})
}
}

var ready = false

var resourcesCount = 0

/*
* 根据文件id获取详情
*/
const getSource = async (id , driverName) => {
if(driveMap.has(driverName)){
let vendor = getDrive(driverName)
Expand All @@ -42,24 +61,29 @@ const getSource = async (id , driverName) => {
}

//和getSource类似 file | stream | url
const getStream = async (ctx , url ,type, protocol , data) => {
/*
* 根据文件id获取详情
*/
const getStream = async (ctx , id ,type, protocol , data) => {
if(type === 'file'){
return await sendFile(ctx , url)
return await sendFile(ctx , id)
}
else if(type === 'stream'){
let vendor = getDrive(protocol)
if(vendor && vendor.stream){
return await sendStream(ctx , url , vendor.stream , data);
return await sendStream(ctx , id , vendor.stream , data);
}
}
else{
return await sendHTTPFile(ctx , url , data)
return await sendHTTPFile(ctx , id , data)
}

return false
}

// 获取数据预览
/*
* 获取文件可预览数据
* @params data { name , ext , url }
*/
const getPreview = async (data) => {
let ext = data.ext
let name = previewMap.get(ext)
Expand All @@ -71,29 +95,56 @@ const isPreviewable = async (data) => {
return previewMap.has(data.ext)
}

const helper = {
isArray : isArray,
isObject: isObject,
datetime:format.datetime,
request:http,
querystring:querystring,
base64:base64,
cache:cache,
getSource: getSource,
getConfig : config.getConfig,
getRandomIP:getRandomIP,
retrieveSize : format.retrieveByte,
saveDrive : config.saveDrive,
getDrive : config.getDrive,
getRuntime:config.getRuntime
const sandboxCache = (id) => {
return {
get(key , ...rest){
return cache.get(`@${id}_${key}` , ...rest)
},
set(key , ...rest){
cache.set(`@${id}_${key}` , ...rest)
}
}
}

const setPrivateConfig = (name) => ( path ) => {

}
const getHelpers = (id) => {
return {
isArray : isArray,
isObject: isObject,
datetime:format.datetime,
request:http,
querystring:querystring,
base64:base64,
cache:sandboxCache(id),
getSource: getSource,
getConfig : config.getConfig,
getRandomIP:getRandomIP,
retrieveSize : format.retrieveByte,
getDrive : config.getDrive,
getRuntime:config.getRuntime,

saveDrive : (path , name) => {
let resource = resources[id]
if( resource && resource.drive && resource.drive.protocols){
let drives = config.getDrives(resource.drive.protocols).map(i => i.name)
if( drives.includes(name) ) config.saveDrive(path , name)
}
},

const load = (options) => {
getDrives : () => {
return whenReady( () => {
let resource = resources[id]
if( resource && resource.drive && resource.drive.protocols){
return ( config.getDrives(resource.drive.protocols) )
}
})
}
}
}

/**
* 加载插件
*/
const load = (options) => {
const dir = options.dir
const dirs = options.dirs

Expand All @@ -119,13 +170,11 @@ const load = (options) => {

const pluginName = name.split('.').slice(0,-1).join('.')
const type = name.split('.')[0]

const resource = require(filepath)(helper)
const id = 'plugin_' + pluginName
const resource = require(filepath)(getHelpers(id))

console.log('Load Plugins: ',pluginName)

const id = 'plugin_' + resourcesCount++

resources[id] = resource

if( resource.auth ){
Expand Down Expand Up @@ -158,20 +207,32 @@ const load = (options) => {
}
}

for(let i = whenReadyHandlers.length ; i-- ; ){
whenReadyHandlers[i].call()
whenReadyHandlers.splice(i,1)
}
ready = true
}


/**
* 根据扩展名获取可处理的驱动
*/
const getDrive = (ext) => {
let id = driveMap.get(ext)
return resources[id].drive
}

/**
* 根据扩展名获取格式化工具
*/
const getFormater = (ext) => {
let name = formatMap.get(ext)
return name ? resources[name].format[ext] : null
}

//更新文件详情数据
/**
* 更新文件详情数据
*/
const updateFile = async (file) => {
if(file.type != 'folder'){
file.type = getFileType(file.ext)
Expand All @@ -187,7 +248,9 @@ const updateFile = async (file) => {
return file
}

// 用于更新目录数据
/**
* 更新文件目录数据
*/
const updateFolder = (folder) => {
let parentType = folder.protocol
if(!folder.children) return folder
Expand Down Expand Up @@ -255,6 +318,7 @@ const updateFolder = (folder) => {
}



/*
* 调用解析器处理
*/
Expand Down
2 changes: 1 addition & 1 deletion app/services/sharelist.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class ShareList {
}
// file /a/b/c.jpg
else {
resp = await vendor.file(hit.id, hit)
resp = await vendor.file(hit.id, { query, req : config.getRuntime('req') ,paths: diff(paths, full_paths), data: hit })
// console.log( resp )
// 最终输出时更新文件操作
await updateFile(resp)
Expand Down
4 changes: 4 additions & 0 deletions app/utils/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ http.post = (url, form, opts) => {
params.url = url
params.form = form
params.method = 'POST'
if (debug) {
params.proxy = 'http://127.0.0.1:1087'
//console.log('DEBUG:', params)
}
return new Promise(function(resolve, reject) {
request(params, function(error, response, body) {
if (!error && response.statusCode == 200) {
Expand Down
Loading

0 comments on commit 4a4fb73

Please sign in to comment.