forked from onestay/CR-Unblocker-Server
-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.js
132 lines (121 loc) · 3.69 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
// ==== DECLARATIONS ==== //
const express = require('express');
const request = require('request');
const helmet = require('helmet');
const app = express();
const knownVersions = ['1.0', '1.1'];
// ==== FUNCTIONS ==== //
/**
* Set the options for querying CR
* @param {Response} query Query from the url
* @return {Object} Options for the query to CR
*/
function setOptions(query) {
let options = {
url: 'https://api.crunchyroll.com/start_session.0.json',
qs: {
version: '1.0', // eslint-disable-line
access_token: 'Scwg9PRRZ19iVwD', // eslint-disable-line
device_type: 'com.crunchyroll.crunchyroid', // eslint-disable-line
device_id: generateId() // eslint-disable-line
}
};
if (query.auth) {
options.qs.auth = query.auth;
}
return options;
}
/**
* Generate a random 32 character long device ID
* @return {String} Generated device ID
*/
function generateId() {
let id = '';
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (var i = 0; i < 32; i++) {
id += possible.charAt(Math.floor(Math.random() * possible.length));
}
return id;
}
/**
* Emit a negative reply containing an error message
* @param {Object} res Reply object
* @param {String} err Error message
*/
function replyError(res, err) {
res.status(500).send({
message: err,
code: 'error',
error: true
});
}
/**
* Emit a positive reply containing data
* @param {Object} res Reply object
* @param {Object} data Object containing the requested payload
*/
function replySuccess(res, data) {
res.status(200).send(data);
}
// ==== ROUTING ==== //
// support for reverse proxy
app.enable('trust proxy');
app.disable('view cache');
// use the middleware
app.use(helmet());
app.use(helmet.noCache());
app.get('/start_session', (req, res) => {
// default version if none specified: 1.0
let version = req.query.version;
if (version === undefined) {
version = '1.0';
}
// validate version against whitelist
if (knownVersions.indexOf(version) === -1) {
replyError(res, 'Invalid API version specified.');
return;
}
// parse version into object containing minor and major version
let split = version.split('.');
version = { major: parseInt(split[0]) || 0, minor: parseInt(split[1]) || 0 };
if (version.major === 1) {
if (version.minor <= 0 && req.query.auth) {
// version <= 1.0: only start_session without logging in is supported
replyError(res, 'Logging in with an auth token is disabled in this version.');
return;
} else if (version.minor >= 1 && req.query.auth && !req.query.user_id) {
// version >= 1.1: logging in with auth token requires user_id to match
replyError(res, 'Logging in with an auth token requires the user_id parameter.');
return;
}
let options = setOptions(req.query);
request(options, (error, response, body) => {
try {
let data = JSON.parse(body);
if (data.error) {
replySuccess(res, data);
} else if (req.query.auth && data.data.user !== null && data.data.user.user_id !== req.query.user_id) {
// if auth is specified, require that user_id matches
replyError(res, 'Invalid user_id specified.');
} else {
replySuccess(res, data);
}
} catch (e) {
replyError(res, 'There was an error with the response from the crunchyroll server');
console.log(`Error in parsing the response: ${e}`);
}
}).on('error', error => {
console.log(`Error fetching ${options.url}: ${error}`);
replyError(res, error);
});
}
});
app.get('*', (req, res) => {
replyError(res, 'Invalid API endpoint.');
});
// process.env.PORT lets the port be set by Heroku
var port = process.env.PORT || 3001; // eslint-disable-line
app.listen(port, () => {
console.log(`Listening on port ${port}`);
});
module.exports = app;