-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.cjs
More file actions
129 lines (107 loc) · 4.34 KB
/
server.cjs
File metadata and controls
129 lines (107 loc) · 4.34 KB
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
const express = require('express');
const cors = require('cors');
const fs = require('fs');
const path = require('path');
const { exec } = require('child_process');
const app = express();
const PORT = 3001;
app.use(cors());
app.use(express.json());
const PROFILES_PATH = process.env.FILTRE_PROFILES_PATH || path.join(__dirname, 'profiles.json');
const SESSION_PATH = process.env.FILTRE_SESSION_PATH || path.join(__dirname, 'session.json');
const getProfiles = () => JSON.parse(fs.readFileSync(PROFILES_PATH, 'utf8'));
const getSession = () => JSON.parse(fs.readFileSync(SESSION_PATH, 'utf8'));
const saveSession = (data) => fs.writeFileSync(SESSION_PATH, JSON.stringify(data, null, 2));
app.get('/api/profiles', (req, res) => res.json(getProfiles()));
app.post('/api/profiles', (req, res) => {
fs.writeFileSync(PROFILES_PATH, JSON.stringify(req.body, null, 2));
res.json({ success: true });
});
app.get('/api/session', (req, res) => res.json(getSession()));
app.post('/api/session/start', (req, res) => {
const { profile, durationMinutes } = req.body;
const sites = getProfiles()[profile] || [];
const session = { active: true, endTime: Date.now() + durationMinutes * 60000, profile, paused: false, remainingSeconds: durationMinutes * 60 };
updateHosts(sites, true, (err) => {
if (err) return res.status(500).json({ error: err.message });
saveSession(session);
res.json(session);
});
});
app.post('/api/session/stop', (req, res) => {
updateHosts([], false, (err) => {
if (err) return res.status(500).json({ error: err.message });
const session = { active: false, endTime: null, profile: null };
saveSession(session);
res.json(session);
});
});
app.post('/api/session/pause', (req, res) => {
const sessionData = getSession();
updateHosts([], false, (err) => {
if (err) return res.status(500).json({ error: err.message });
const session = { ...sessionData, paused: true };
saveSession(session);
res.json(session);
});
});
app.post('/api/session/resume', (req, res) => {
const sessionData = getSession();
const sites = getProfiles()[sessionData.profile] || [];
updateHosts(sites, true, (err) => {
if (err) return res.status(500).json({ error: err.message });
const session = { ...sessionData, paused: false };
saveSession(session);
res.json(session);
});
});
function updateHosts(sites, block, callback) {
const HOSTS_FILE = '/etc/hosts';
const START_MARKER = '# filtre-blocklist start';
const END_MARKER = '# filtre-blocklist end';
const performWrite = () => {
try {
const currentContent = fs.readFileSync(HOSTS_FILE, 'utf8');
const regex = new RegExp(`\\n?\\n?${START_MARKER}[\\s\\S]*?${END_MARKER}`, 'g');
let newContent = currentContent.replace(regex, '').trim();
if (block && sites.length > 0) {
newContent += `\n\n${START_MARKER}\n`;
sites.forEach(site => {
newContent += `0.0.0.0 ${site}\n0.0.0.0 www.${site}\n:: ${site}\n:: www.${site}\n`;
});
newContent += `${END_MARKER}\n`;
} else {
newContent += `\n`;
}
const tempFile = `/tmp/filtre_h_write_${Date.now()}`;
fs.writeFileSync(tempFile, newContent);
exec(`cat "${tempFile}" > "${HOSTS_FILE}" && rm "${tempFile}"`, (err) => {
if (err) return callback(new Error("Permission denied. Try restarting the app."));
exec("dscacheutil -flushcache; killall -HUP mDNSResponder", () => callback(null));
});
} catch (err) {
callback(err);
}
};
fs.access(HOSTS_FILE, fs.constants.W_OK, (err) => {
if (!err) return performWrite();
exec("stat -f%Su /dev/console", (userErr, stdout) => {
const username = stdout.trim();
if (!username) return callback(new Error("Could not detect system user."));
const setupCmd = `osascript -e 'do shell script "chmod +a \\"user:${username} allow read,write,append\\" ${HOSTS_FILE}" with administrator privileges'`;
exec(setupCmd, (setupErr) => {
if (setupErr) return callback(new Error("Administrator privileges required for the first time."));
performWrite();
});
});
});
}
app.post('/api/quit', (req, res) => {
updateHosts([], false, () => {
res.json({ success: true });
setTimeout(() => process.exit(0), 200);
});
});
app.listen(PORT, () => {
console.log(`Backend server running at http://localhost:${PORT}`);
});