forked from jpillora/node-torrent-cloud
-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.js
140 lines (123 loc) · 3.19 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//load server config
var config = require("./config.json");
//apply defaults from env
for(var k in config) {
if(k in process.env) {
config[k] = process.env[k];
}
}
//load submodules
var search = require("./lib/search");
var torrents = require("./lib/torrents");
var backend = require("./lib/backend");
var ws = require("./lib/ws");
var basicAuth = require('basic-auth-connect');
var bodyParser = require('body-parser');
var http = require('http');
var express = require('express');
var app = express();
var server = http.createServer(app);
var port = parseInt(process.argv[2], 10) ||
process.env.PORT ||
process.env.OPENSHIFT_NODEJS_PORT ||
3000;
var host = process.env.HOST ||
process.env.OPENSHIFT_NODEJS_IP ||
"0.0.0.0";
//global auth
var user = process.env.AUTH_USER || 'admin';
var password = process.env.AUTH_PASSWORD;
if(password)
app.use(basicAuth(user, password));
//hook http server
ws.install(server);
//all requests have JSON body
app.use(bodyParser.json());
//convert all of the given module's
//exposed functions into API endpoints
function api(name, module) {
Object.keys(module).forEach(function(key) {
var fn = module[key];
if(typeof fn !== "function")
return;
//dont call modules with request/response,
//instead call with 'body' and 'callback(err, data)'
var endpoint = '/api/'+name+'/'+key;
// console.log("POST %s -> %s.%s", endpoint, name, key);
app.post(endpoint, function (req, res) {
fn(req.body, function(err, data) {
if(err) {
res.status(400).send(err);
} else {
res.send(data || "OK");
}
});
});
});
}
//use all module methods as JSON POST endpoints
api('search', search);
api('torrents', torrents);
//TODO(@jpillora) in future, some storage backends may need
//custom APIs
//disallow crawling
app.get('/robots.txt', function(req, res) {
res.send("User-agent: *\nDisallow: /");
});
//modify configuration
// app.post('/config', function(req, res) {
// if(!req.body)
// return res.status(400).send("No body");
// var changed = false;
// for(var k in req.body) {
// var v = req.body[k];
// if(k in config && config[k] !== v) {
// config[k] = v;
// changed = true;
// }
// }
// if(changed) {
// update();
// }
// });
//expose static files
app.use('/', express.static(__dirname + '/static'));
var storedFiles = {};
//broadcast state on "update"
var update = function(newFiles) {
//optionally update stored files
if(newFiles)
storedFiles = newFiles;
//broadcast state
ws.broadcast({
config: config,
providers: search.providers,
torrents: torrents.list,
filesDownloading: torrents.filesDownloading,
uploads: storedFiles
});
};
search.on("update", update);
torrents.on("update", update);
//periodically scan for new stored files
function list() {
backend.list(function(err, files) {
if(!err) update(files);
});
}
setInterval(list, 15*60*1000);
list();
server.on("error", function(err) {
switch(err.code) {
case "EADDRINUSE":
console.error("Port %s is currently in use", port);
break;
default:
console.error("Failed to listen on %s:%s (%s)", host, port, err.toString());
}
process.exit(1);
});
//listen!
server.listen(port, host, function() {
console.log("listening on %s:%s...", host, port);
});