├── .gitignore
├── app.js
├── config.json
├── list.html
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | debug.html
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 | # Coverage directory used by tools like istanbul
13 | coverage
14 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
15 | .grunt
16 | # node-waf configuration
17 | .lock-wscript
18 | # Compiled binary addons (http://nodejs.org/api/addons.html)
19 | build/Release
20 | # Dependency directory
21 | node_modules
22 | # Optional npm cache directory
23 | .npm
24 | # Optional REPL history
25 | .node_repl_history
26 | .DS_Store
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var logger = require('morgan');
3 | var superagent = require('superagent');
4 | var bodyParser = require('body-parser');
5 | var fs = require('fs');
6 | var app = express();
7 |
8 | var Cache = {};
9 | setInterval(() => {
10 | Object.keys(Cache).forEach((key) => {
11 | var obj = Cache[key];
12 | obj.time--;
13 | if(obj.time <= 0) delete Cache[key];
14 | });
15 | }, 1000);
16 |
17 | app.use(logger('dev'));
18 | app.use(bodyParser.urlencoded({ extended: false }))
19 | app.use(bodyParser.json())
20 | app.use((req, res, next) => {
21 | req.config = require('./config.json');
22 | req.getApiData = (url, data, callback) => {
23 | if(req.config.accessToken.trim() == '') return callback('请先绑定189电信账号');
24 |
25 | data['app_id'] = req.config.appKey
26 | data['access_token'] = req.config.accessToken;
27 |
28 | superagent.get(url).query(data).timeout(1000 * 10).end((err, res) => {
29 | if(err) return callback(err);
30 | try {
31 | callback(null, JSON.parse(res.text));
32 | } catch (error) {
33 | callback(error);
34 | }
35 | });
36 | }
37 |
38 | req.setCache = (key, obj, time) => {
39 | Cache[key] = {time: time, data: obj}
40 | }
41 | req.getCache = (key) => {
42 | return Cache[key] ? Cache[key] : null;
43 | }
44 |
45 | next();
46 | });
47 |
48 | // OAuth 重定向
49 | app.get('/auth', (req, res) => {
50 | var args = `response_type=token&app_id=${req.config.appKey}&app_secret=${req.config.appSecret}&redirect_uri=${req.config.callbackUrl}`;
51 | var authUrl = `https://oauth.api.189.cn/emp/oauth2/v3/authorize?${args}`;
52 | res.send(`跳转至天翼云`);
53 | });
54 |
55 | // OAuth 回调
56 | app.get('/authCallback/', (req, res) => {
57 | if(req.config.accessToken != '') return res.send('请先删除config.json accessToken值');
58 |
59 | var accessToken = req.query.access_token || '';
60 | var res_code = req.query.res_code || -1;
61 |
62 | if(accessToken == '' || res_code == -1) return res.send('回调参数不正确');
63 |
64 | if(res_code != 0) return res.send('认证失败 错误代码:' + res_code);
65 |
66 | req.config.accessToken = accessToken;
67 |
68 | fs.writeFile('config.json', JSON.stringify(req.config, null, 4), 'utf8', (err) => {
69 | res.send(`Save Status: ${err || '保存配置成功'}
Access Token: ${accessToken}`);
70 | });
71 | });
72 |
73 | app.get('/', (req, res) => {
74 | fs.readFile('./list.html', 'utf8', (err, data) => {
75 | if(err) return res.status(503).send(`can't render html.`);
76 | res.send(data);
77 | });
78 | });
79 |
80 | app.get('/link/:fileId', (req, res) => {
81 | var fileId = req.params.fileId;
82 | var cache = req.getCache(fileId);
83 | if(cache){
84 | res.set('Link-Cache', 'Hit ' + cache.time);
85 | return res.redirect(cache.data);
86 | }
87 | req.getApiData('http://api.189.cn/ChinaTelecom/getFileDownloadUrl.action', {fileId: fileId}, (err, result) => {
88 | if(err) return res.status(503).send(err);
89 | // 天翼云盘真实链接并不会立即过期,也许要过1天? 或者100年?
90 | // 反正这里配置文件里默认缓存60分钟 因为我就试了60分钟 懒得试了 但是证实60分钟+还是有效的
91 | // 如果电信修改了 请自行修改 config -> linkCacheTime
92 | if(req.config.linkCache) req.setCache(fileId, result.fileDownloadUrl, req.config.linkCacheTime);
93 | res.set('Link-Cache', 'Miss');
94 | res.redirect(result.fileDownloadUrl);
95 | });
96 | });
97 |
98 | app.get('/folder/', (req, res) => {
99 | // 天翼云API出现问题,会暴露全部文件夹和文件 所以在此加入设置默认文件夹ID
100 | req.getApiData('http://api.189.cn/ChinaTelecom/listFiles.action', req.config.defaultFolder == -1 ? {} : {folderId: req.config.defaultFolder}, (err, result) => {
101 | if(err) return res.status(503).send(err);
102 | res.json(result);
103 | })
104 | });
105 |
106 | app.get('/folder/:folderId', (req, res) => {
107 | var folderId = req.params.folderId;
108 | req.getApiData('http://api.189.cn/ChinaTelecom/listFiles.action', {folderId: folderId}, (err, result) => {
109 | if(err) return res.status(503).send(err);
110 | res.json(result);
111 | })
112 | });
113 |
114 | app.listen(require('./config.json').port, (error) => {
115 | if(error) return console.error('监听端口发生错误:', error);
116 | console.log('服务已开启 监听端口:' + require('./config.json').port);
117 | });
118 |
--------------------------------------------------------------------------------
/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "port" : 3000,
3 | "appKey": "123",
4 | "appSecret": "123",
5 | "callbackUrl": "http://123.123/authCallback",
6 | "accessToken": "",
7 | "linkCache" : true,
8 | "linkCacheTime": 3600,
9 | "defaultFolder": -1
10 | }
--------------------------------------------------------------------------------
/list.html:
--------------------------------------------------------------------------------
1 |
2 |