@xiaoxionga/buzz 2.0.1 → 2.2.0

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 (3) hide show
  1. package/README.md +20 -15
  2. package/bin/buzz.js +87 -26
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -14,35 +14,40 @@ npm install -g @xiaoxionga/buzz
14
14
 
15
15
  ```bash
16
16
  buzz # Keep awake indefinitely (Ctrl+C to stop)
17
- buzz 20 # Keep awake for 20 minutes
18
- buzz 2 # Keep awake for 2 hours
19
- buzz 1.5 # Keep awake for 1.5 hours (90 min)
17
+ buzz 20 # 20 minutes (default unit)
18
+ buzz 2h # 2 hours
19
+ buzz 30s # 30 seconds
20
+ buzz 1.5h # 90 minutes
20
21
  buzz stop # Stop any running buzz
21
22
  buzz status # Check if buzz is running
22
23
  buzz help # Show help
23
24
  ```
24
25
 
26
+ ## Duration Format
27
+
28
+ Default unit is **minutes**. Add a suffix to override:
29
+
30
+ | Input | Meaning |
31
+ |-------|---------|
32
+ | `buzz 30` | 30 **minutes** |
33
+ | `buzz 5min` | 5 **minutes** |
34
+ | `buzz 2h` | 2 **hours** |
35
+ | `buzz 1.5h` | 1.5 hours = 90 minutes |
36
+ | `buzz 30s` | 30 **seconds** |
37
+ | `buzz` | ∞ (until Ctrl+C) |
38
+
25
39
  ## How It Works
26
40
 
27
41
  | Platform | Method | Install needed? | Admin needed? |
28
42
  |----------|--------|:---------------:|:-------------:|
29
43
  | **macOS** | `caffeinate -i` (built-in) | ❌ | ❌ |
30
- | **Windows** | PowerShell `SendKeys F15` (built-in) | ❌ | ❌ |
44
+ | **Windows** | `SetThreadExecutionState` + mouse jiggle (built-in) | ❌ | ❌ |
31
45
  | **Linux** | `xdotool` (pre-installed on most distros) | maybe | ❌ |
32
46
 
33
47
  - **macOS**: Uses Apple's built-in `caffeinate` — not even a mouse jiggle, just cleanly blocks idle sleep.
34
- - **Windows**: Presses F15 every 30 seconds via PowerShell. No app binds to F15, so it's completely harmless.
48
+ - **Windows**: Triple strategy `SetThreadExecutionState` (official Windows API, same as YouTube/PowerPoint use to prevent screen sleep) + mouse jiggle 1px every 30s + F15 keystroke as backup. Corporate lock screen policies that ignore synthetic keystrokes are handled by the real mouse movement.
35
49
  - **Linux**: Moves mouse 1px via `xdotool`.
36
50
 
37
- ## Duration Format
38
-
39
- | Input | Meaning |
40
- |-------|---------|
41
- | `buzz 30` | 30 **minutes** (numbers ≥ 10 = minutes) |
42
- | `buzz 5` | 5 **hours** (numbers < 10 = hours) |
43
- | `buzz 0.5` | 0.5 hours = 30 minutes |
44
- | `buzz 1.5` | 1.5 hours = 90 minutes |
45
-
46
51
  ## Why buzz?
47
52
 
48
53
  - **Zero dependencies** — `package.json` has no `dependencies` field. Nothing to break.
@@ -54,7 +59,7 @@ buzz help # Show help
54
59
 
55
60
  ```bash
56
61
  # Weekend crunch time
57
- buzz 3 # 3 hours of uninterrupted focus
62
+ buzz 3h # 3 hours of uninterrupted focus
58
63
 
59
64
  # Quick meeting
60
65
  buzz 30 # 30 minutes
package/bin/buzz.js CHANGED
@@ -27,25 +27,28 @@ Keep your screen awake by simulating input.
27
27
 
28
28
  USAGE:
29
29
  buzz Keep awake indefinitely (Ctrl+C to stop)
30
- buzz 20 Keep awake for 20 minutes
31
- buzz 1.5 Keep awake for 1.5 hours (90 min)
30
+ buzz 20 Keep awake for 20 minutes (default unit)
31
+ buzz 2h Keep awake for 2 hours
32
+ buzz 30s Keep awake for 30 seconds
33
+ buzz 1.5h Keep awake for 1.5 hours (90 min)
32
34
  buzz stop Stop any running buzz
33
35
  buzz status Check if buzz is running
34
36
  buzz help Show this help
35
37
 
36
38
  PLATFORMS:
37
39
  macOS Uses 'caffeinate' (built-in, zero install)
38
- Windows Uses PowerShell SendKeys (built-in, zero install)
40
+ Windows Uses SetThreadExecutionState + mouse jiggle (built-in, zero install)
39
41
  Linux Uses xdotool (if available)
40
42
 
41
43
  EXAMPLES:
42
- buzz 30 # Stay awake for 30 min
43
- buzz 2 # Stay awake for 2 hours
44
- buzz # Stay awake until you Ctrl+C
44
+ buzz 30 # 30 minutes
45
+ buzz 2h # 2 hours
46
+ buzz 90 # 90 minutes
47
+ buzz # until Ctrl+C
45
48
 
46
49
  TIPS:
47
- - Numbers >= 10 are treated as minutes
48
- - Numbers < 10 are treated as hours
50
+ - Default unit is minutes: buzz 5 = 5 minutes
51
+ - Suffixes: s (seconds), min (minutes), h (hours)
49
52
  - No npm dependencies required!
50
53
  `;
51
54
 
@@ -80,12 +83,34 @@ function formatDuration(ms) {
80
83
  }
81
84
 
82
85
  function parseDuration(arg) {
83
- const num = parseFloat(arg);
86
+ // Formats: "20" = 20min, "2h" = 2h, "30s" = 30s, "5min" = 5min, "1.5h" = 90min
87
+ const match = arg.match(/^(\d+(?:\.\d+)?)\s*(h|hour|hours|m|min|mins|minute|minutes|s|sec|secs|second|seconds)?$/i);
88
+ if (!match) return null;
89
+
90
+ const num = parseFloat(match[1]);
84
91
  if (isNaN(num) || num <= 0) return null;
85
- // >= 10 → minutes, < 10 → hours
86
- return num >= 10
87
- ? num * 60 * 1000
88
- : num * 60 * 60 * 1000;
92
+
93
+ const unit = (match[2] || 'min').toLowerCase();
94
+
95
+ if (unit.startsWith('h')) return num * 60 * 60 * 1000; // hours
96
+ if (unit.startsWith('s')) return num * 1000; // seconds
97
+ return num * 60 * 1000; // minutes (default)
98
+ }
99
+
100
+ function humanDuration(ms) {
101
+ if (ms < 60000) {
102
+ const s = Math.round(ms / 1000);
103
+ return `${s} second${s > 1 ? 's' : ''}`;
104
+ }
105
+ if (ms < 3600000) {
106
+ const m = Math.round(ms / 60000);
107
+ return `${m} minute${m > 1 ? 's' : ''}`;
108
+ }
109
+ const h = ms / 3600000;
110
+ if (h === Math.floor(h)) return `${h} hour${h > 1 ? 's' : ''}`;
111
+ // e.g. 90 min → show as "90 minutes" not "1.5 hours"
112
+ const m = Math.round(ms / 60000);
113
+ return `${m} minute${m > 1 ? 's' : ''}`;
89
114
  }
90
115
 
91
116
  // ─── Platform-specific jiggler ───
@@ -105,19 +130,56 @@ function startCaffeinate(durationMs) {
105
130
  }
106
131
 
107
132
  /**
108
- * Windows: use PowerShell SendKeys to press F15 every 30s.
109
- * F15 is harmless — no app binds to it.
110
- * Zero install, zero admin.
133
+ * Windows: triple strategy SetThreadExecutionState + mouse jiggle + F15
134
+ *
135
+ * Many corporate Windows policies ignore synthetic keystrokes (F15).
136
+ * The robust approach is:
137
+ * 1. SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED)
138
+ * — the official Windows API to prevent sleep (same as YouTube/PowerPoint do)
139
+ * 2. Move mouse 1px via .NET Cursor.Position — universally recognized as "activity"
140
+ * 3. F15 via SendKeys as backup
141
+ *
142
+ * All via PowerShell — zero install, zero admin.
111
143
  */
112
144
  function jiggleWindows() {
113
- // Single PowerShell invocation that loops every 30s
114
145
  const psScript = `
115
- $wsh = New-Object -ComObject WScript.Shell
116
- while ($true) {
117
- Start-Sleep -Seconds 30
118
- $wsh.SendKeys('{F15}')
119
- }
120
- `;
146
+ # 1. Load Windows Forms for mouse control
147
+ Add-Type -AssemblyName System.Windows.Forms
148
+
149
+ # 2. Call SetThreadExecutionState to prevent display sleep
150
+ Add-Type -TypeDefinition @"
151
+ using System;
152
+ using System.Runtime.InteropServices;
153
+ public class PowerUtil {
154
+ [DllImport("kernel32.dll")]
155
+ public static extern uint SetThreadExecutionState(uint esFlags);
156
+
157
+ public const uint ES_CONTINUOUS = 0x80000000;
158
+ public const uint ES_SYSTEM_REQUIRED = 0x00000001;
159
+ public const uint ES_DISPLAY_REQUIRED = 0x00000002;
160
+ }
161
+ "@
162
+
163
+ # Prevent display from turning off and system from sleeping
164
+ [PowerUtil]::SetThreadExecutionState(
165
+ [PowerUtil]::ES_CONTINUOUS -bor [PowerUtil]::ES_SYSTEM_REQUIRED -bor [PowerUtil]::ES_DISPLAY_REQUIRED
166
+ )
167
+
168
+ # 3. Loop: jiggle mouse + press F15
169
+ $wsh = New-Object -ComObject WScript.Shell
170
+ while ($true) {
171
+ Start-Sleep -Seconds 30
172
+
173
+ # Move mouse 1px then back — most reliable "activity" signal
174
+ $pos = [System.Windows.Forms.Cursor]::Position
175
+ [System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($pos.X + 1, $pos.Y)
176
+ Start-Sleep -Milliseconds 50
177
+ [System.Windows.Forms.Cursor]::Position = $pos
178
+
179
+ # Also press F15 as backup
180
+ try { $wsh.SendKeys('{F15}') } catch {}
181
+ }
182
+ `;
121
183
  // This runs as a detached child
122
184
  const child = spawn('powershell.exe', [
123
185
  '-NoProfile', '-NonInteractive', '-Command', psScript
@@ -209,12 +271,11 @@ function cmdRun(durationMs) {
209
271
  console.log(BEE);
210
272
 
211
273
  const platformLabel = PLATFORM === 'darwin' ? 'macOS caffeinate'
212
- : PLATFORM === 'win32' ? 'Windows SendKeys'
274
+ : PLATFORM === 'win32' ? 'Windows SetThreadExecutionState + Mouse'
213
275
  : 'Linux xdotool';
214
276
 
215
277
  if (durationMs) {
216
- const mins = Math.round(durationMs / 60000);
217
- console.log(`🐝 buzz started! Keeping awake for ${mins} minutes.`);
278
+ console.log(`🐝 buzz started! Keeping awake for ${humanDuration(durationMs)}.`);
218
279
  } else {
219
280
  console.log(`🐝 buzz started! Keeping awake indefinitely.`);
220
281
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xiaoxionga/buzz",
3
- "version": "2.0.1",
3
+ "version": "2.2.0",
4
4
  "description": "🐝 Keep your screen awake — zero dependencies, no admin required",
5
5
  "main": "bin/buzz.js",
6
6
  "bin": {