Skip to content
This repository has been archived by the owner on May 14, 2022. It is now read-only.

大佬有空可以加上阿里云盘 #21

Open
naicfeng opened this issue Mar 19, 2021 · 2 comments
Open

大佬有空可以加上阿里云盘 #21

naicfeng opened this issue Mar 19, 2021 · 2 comments
Labels
enhancement New feature or request

Comments

@naicfeng
Copy link

官方网页端完全就像公开API一样呀。

refresh_token保存在localstorage,和onedrive一样可以无限获取access_token
post
https://websv.aliyundrive.com/token/refresh {RefreshToken: RefreshToken}

目前还不限速,完美

@naicfeng
Copy link
Author

const { axios, RTError, IDHelper, _P } = require('../utils/node');
const logger = require('../utils/logger');
const op = require('../core/op');

const { PAGE_SIZE } = require('../conf/sys-config');

function filter(e) {

    const r = {
        type: 1,
        name: e.name,
        time: e.updated_at,
        id: e.file_id,
    };

    if (e.type !== 'folder') {
        r.type = 0;
        r.mime = e.content_type;
        r.size = Number(e.size);
        r.url = e.download_url;
        r.thumbnail = e.thumbnail;
    }

    return r;
}

class Aliyundrive extends IDHelper {
    static async build(config) {
        const g = new Aliyundrive(config);
        await g.refreshToken();
        g.service.defaults.headers.common.Authorization = 'Bearer ' + g.access_token;
        return g;
    }

    constructor({ refresh_token, root }) {
        super(root);
        this.oauth = Object.assign({}, Aliyundrive.oauth2s[0], { refresh_token });
        const service = axios.create({ baseURL: this.oauth.api_url });
        service.interceptors.response.use(
            (response) => response.data,
            (err) => {
                if (err.response && err.response.data && err.response.data.error) {
                    if (err.response.status === 404) {
                        return Promise.reject(new RTError(404, 'ItemNotExist'));
                    } else {
                        const d = err.response.data.error;
                        return Promise.reject(new RTError(400, 'ModuleError', d.message || d));
                    }
                }
                return Promise.reject(err);
            }
        );
        this.service = service;
    }

    async refreshToken() {
        if(op.config.cache && op.config.cache[this.oauth.refresh_token] && op.config.cache[this.oauth.refresh_token].exptime > Date.now()){
            this.access_token = op.config.cache[this.oauth.refresh_token].access_token;
            this.drive_id = op.config.cache[this.oauth.refresh_token].drive_id;
            logger.info('use refresh_token cache');
            return op.config.cache[this.oauth.refresh_token];
        }
        const data = await this.service.post(
            this.oauth.refresh_url,
            new URLSearchParams({
                refresh_token: this.oauth.refresh_token
            })
        );
        this.access_token = data.access_token;
        this.drive_id = data.default_drive_id
        //cache
        let exptime = Date.now() + Number(data.expires_in * 1000);
        let cache_key = this.oauth.refresh_token;
        if(!op.config.cache)op.config['cache'] = {};
        op.config.cache[cache_key] = {access_token:this.access_token,exptime:exptime,drive_id:this.drive_id};
        op.saveConfig();
//        logger.log('aliyun drive access_token:' + data.access_token);
        return data;
    }

    async itemInfo(id) {
        return this.service
            .post('file/get', {
                "drive_id": this.drive_id,
                "file_id": id,
            })
            .then(filter);
    }

    async fetchList(parentId, pageToken) {
        const params = {
            "drive_id": this.drive_id,
            "fields": '*',
            "order_by": 'updated_at',
            "order_direction": 'DESC',
            "parent_file_id": parentId?parentId:this.root,
            "limit": 3000,//PAGE_SIZE,
            "next_marker": pageToken
        };

        return this.service.post('file/list', params).then((data) => ({
            list: data.items.map(filter),
            next: data.next_marker,
        }));
    }

}

Aliyundrive.oauth2s = [
    {
        api_url: 'https://api.aliyundrive.com/v2/',
        refresh_url: 'https://websv.aliyundrive.com/token/refresh',
    },
];

module.exports = {
    params() {
        return [_P('refresh_token', '', '登录后在Local Storage获取', 7, '', true, true), _P('root', '', '根目录ID,使用根目录填root', 7, '', false, true)];
    },
    async handle(config, data, cache, ctx) {
        if ((cache.etime || 0) < Date.now()) {
            if (!config.root) {
                config.root = 'root';
            }
            if (!config.refresh_token) {
                throw new RTError(400, 'ConfigError', { fields: ['refresh_token'] });
            }

            cache.$g = await Aliyundrive.build(config);

            cache.etime = Date.now() + 3600 * 1000;
        }
        return this.ls(data, cache, ctx);
    },
    async ls({ path, id, page }, { $g }, ctx) {
        if (path.endsWith('/')) {
            if (path !=='/' && !id)throw new RTError(400, '非法请求', { msg: '访问当前页面需要携带 id 参数' });
            const { list, next } = await $g.fetchList(id, page);
            if (list.length === 0) {
                const e = await $g.itemInfo(id);
                if (e.type === 0) {
                    throw new RTError(400, 'ItemIsFile');
                }
            }
            ctx.respondList(list, next);
        } else {
            const e = await $g.itemInfo(id);
            ctx.respondOne(e);
        }
    },
};

自行适配了aliyundrive,目前存在的问题

  1. 阿里云盘自带翻页key,但是不知道如何使用(直接获取3000条记录,放进cache翻页)
  2. 所有路径都是以parent_file_id形式记录,无法直接用路径获取(没有找到相应api),所以访问必须附带id
  3. 由于以上问题,导致navsParent链接无法直接访问
  4. cf worker网络访问阿里云的api可能会超时

演示见:https://dev.cuojue.workers.dev/

@ukuq
Copy link
Owner

ukuq commented Apr 25, 2021

参考了大佬的主题,增加了alidrive,支持分页、子目录挂载

demo: https://onepoint.onesrc.workers.dev/alidrive/

受限于 referrer,视频、图片可能无法预览,但可以正常下载

如果想要预览,可以参考 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants