@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.
- package/README.md +20 -15
- package/bin/buzz.js +87 -26
- 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 #
|
|
18
|
-
buzz
|
|
19
|
-
buzz
|
|
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** |
|
|
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**:
|
|
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
|
|
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
|
|
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
|
|
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 #
|
|
43
|
-
buzz
|
|
44
|
-
buzz
|
|
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
|
-
-
|
|
48
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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:
|
|
109
|
-
*
|
|
110
|
-
*
|
|
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
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
|
274
|
+
: PLATFORM === 'win32' ? 'Windows SetThreadExecutionState + Mouse'
|
|
213
275
|
: 'Linux xdotool';
|
|
214
276
|
|
|
215
277
|
if (durationMs) {
|
|
216
|
-
|
|
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
|
}
|