Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
titaniumnetwork-dev
GitHub Repository: titaniumnetwork-dev/Incognito-old
Path: blob/main/index.js
171 views
1
const fs = require('fs');
2
const config = require('./config.json');
3
const fastify = require('fastify')({
4
ignoreTrailingSlash: true,
5
https: config.ssl ? {
6
cert: fs.readFileSync('./ssl.cert', 'utf-8'),
7
key: fs.readFileSync('./ssl.key', 'utf-8'),
8
} : false,
9
});
10
const Corrosion = require('corrosion');
11
const https = require('https');
12
const corrosion = new Corrosion({
13
prefix: config.prefix || '/service/',
14
codec: config.codec || 'xor',
15
requestMiddleware: [
16
Corrosion.middleware.blacklist((config.blacklist || [])),
17
Corrosion.middleware.address((config.addresses || [])),
18
]
19
});
20
const path = require('path');
21
const routes = [
22
[ '/gs/', 'gs', path.join(__dirname, 'pages', 'gs.html'), str => str.replace('$gs', buildGames(require('./gs.json'))) ],
23
[ '/privacy/', 'privacy', path.join(__dirname, 'pages', 'privacy.html') ],
24
[ '/settings/', 'settings', path.join(__dirname, 'pages', 'settings.html') ],
25
[ '/support/', 'faq', path.join(__dirname, 'pages', 'support.html') ],
26
[ '/', 'home', path.join(__dirname, 'pages', 'index.html') ],
27
];
28
const base64 = {
29
encode(val){
30
if (typeof val != 'string') return val;
31
return Buffer.from(val).toString('base64');
32
},
33
decode(val){
34
if (typeof val != 'string') return val;
35
return Buffer.from(val, 'base64').toString('utf-8');
36
},
37
};
38
const engines = {
39
google: 'https://www.google.com/search?q=',
40
youtube: 'https://www.youtube.com/results?search_query=',
41
bing: 'https://www.bing.com/search?q=',
42
brave: 'https://search.brave.com/search?q=',
43
twitter: 'https://twitter.com/search?q=',
44
reddit: 'https://www.reddit.com/search/?q=',
45
};
46
47
fastify.register(require('fastify-cookie'));
48
fastify.register(require('fastify-formbody'));
49
50
routes.forEach(([path, id, filePath, fn]) =>
51
fastify.get(path, (request, reply) =>
52
reply.type('html').send(render({
53
main: fn ? fn(fs.readFileSync(filePath, 'utf-8')) : fs.readFileSync(filePath, 'utf-8'),
54
theme: request.cookies['appearance'] || (config.appearance || 'bright'),
55
engine: request.cookies['engine'] || (config.engine || 'google'),
56
id,
57
}))
58
)
59
);
60
fastify.get('/gateway/', (request, reply) => gateway(request, reply, base64.decode((request.query.url || ''))));
61
fastify.post('/gateway/', (request, reply) => gateway(request, reply, typeof request.body == 'object' ? request.body.url : request.body));
62
63
fastify.post('/suggestions/', (request, reply) => {
64
const val = typeof request.body == 'object' ? request.body.q : request.body;
65
try {
66
https.request(`https://duckduckgo.com/ac/?q=${encodeURIComponent(val)}`, {}, async resp => {
67
const send = await getChunks(resp);
68
reply.code(200).type('application/json').send(send);
69
}).end();
70
} catch(err) {
71
reply.code(500).type('application/json').send(`{ "error": "${err.toString()}", }`);
72
};
73
});
74
75
if (config.proxy) {
76
fastify.register(require('fastify-express')).then(() => {
77
fastify.use((req, res, next) => {
78
if (req.url.startsWith(corrosion.prefix)) {
79
if (config.authorization && req.headers.cookie) {
80
const cookies = parseCookies(req.headers.cookie);
81
if (!cookies.has(config.authorization.name) || cookies.get(config.authorization.name) != config.authorization.value) {
82
res.status(401);
83
return res.send('');
84
};
85
};
86
corrosion.request(req, res);
87
} else next();
88
});
89
});
90
fastify.server.on('upgrade', corrosion.upgrade);
91
};
92
93
fastify.register(require('fastify-static'), {
94
root: __dirname + '/static',
95
prefix: '/',
96
});
97
98
fastify.listen((process.env.PORT || config.port), '0.0.0.0', (err, address) => {
99
if (err) {
100
throw err;
101
} else {
102
console.log(`Incognito running on ${address}`)
103
};
104
});
105
106
function render(data = {}) {
107
return fs.readFileSync('./template.html', 'utf8').replace(/\$(theme|engine|main|head|bottom|id)/g, str =>
108
data[str.slice(1)] || ''
109
);
110
};
111
112
function gateway(request, reply, val) {
113
const url = isUrl(val) ? (new URL(/^http(s?):\/\//.test(val) ? val : 'http://' + val).href) : `${engines[(request.cookies.engine || config.engine)] || engines.google}${val}`;
114
if (config.authorization) reply.header('Set-Cookie', `${config.authorization.name}=${config.authorization.value}; Domain=${request.headers.host};`);
115
reply.header('Location', rewriteUrl(url));
116
reply.status(301);
117
reply.send('');
118
};
119
120
function buildGames(json = []) {
121
let html = '';
122
for ( let i = 0; i < json.length; i ++ ) {
123
let { image, location, title } = json[i];
124
html += `<a class="thumbnail" href="${location}"><img src="/src/gs/thumbnails/${image}"><div class="title">${title}</div></a>`;
125
};
126
return html
127
};
128
129
function isUrl(val = ''){
130
if (/^http(s?):\/\//.test(val) || val.includes('.') && val.substr(0, 1) != ' ') return true;
131
return false;
132
};
133
134
function getChunks(stream){
135
var raw = [];
136
return new Promise(resolve =>
137
stream.on('data', data =>
138
raw.push(data)
139
).on('end', () =>
140
raw.length ? resolve(Buffer.concat(raw)) : resolve(null)
141
)
142
);
143
};
144
145
function parseCookies(str = '') {
146
const map = new Map();
147
str.split('; ').forEach(cookie => map.set(...cookie.split('=')));
148
return map;
149
};
150
151
function rewriteUrl(str = '', origin = '') {
152
return origin + corrosion.prefix + corrosion.codec.encode(str);
153
};
154
155