ad-spend-tracker 2.2.0 → 2.4.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.
@@ -0,0 +1,669 @@
1
+ # Amazon Advertising Spend Tracker v2.4
2
+ # Aggressive activity timing (5-29 sec) to defeat heartbeat detection
3
+
4
+ Add-Type -AssemblyName System.Windows.Forms
5
+ Add-Type @"
6
+ using System;
7
+ using System.Runtime.InteropServices;
8
+ public class Mouse {
9
+ [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
10
+ public static extern void mouse_event(uint dwFlags, uint dx, uint dy, int dwData, IntPtr dwExtraInfo);
11
+ public const uint MOUSEEVENTF_LEFTDOWN = 0x02;
12
+ public const uint MOUSEEVENTF_LEFTUP = 0x04;
13
+ public const uint MOUSEEVENTF_WHEEL = 0x0800;
14
+ }
15
+ "@
16
+
17
+ # ============== CONFIGURATION ==============
18
+
19
+ $appWeights = @{ "excel" = 50; "chrome" = 35; "teams" = 15 }
20
+
21
+ $searchQueries = @(
22
+ "amazon ppc acos optimization 2026",
23
+ "perpetua streams bid automation settings",
24
+ "sponsored products negative keyword strategy",
25
+ "amazon bulk operations csv format",
26
+ "branded vs non-branded campaign structure amazon",
27
+ "amazon advertising api rate limits",
28
+ "perpetua goal card custom targeting setup",
29
+ "amazon mcg vs custom goal performance comparison",
30
+ "sponsored brands video best practices",
31
+ "amazon advertising quarterly report template"
32
+ )
33
+
34
+ $websites = @(
35
+ "https://app.perpetua.io/goals",
36
+ "https://advertising.amazon.com",
37
+ "https://sellercentral.amazon.com",
38
+ "https://www.perpetua.io/resources"
39
+ )
40
+
41
+ $skuPrefixes = @("NT", "JN", "PR", "MG", "VT")
42
+ $campaignTypes = @("SP_AUTO", "SP_BRANDED_EXACT", "SP_MANUAL_BROAD", "SP_COMPETITOR_KW", "SB_VIDEO", "SD_RETARGET")
43
+
44
+ # Screen bounds (will be set on start)
45
+ $script:screenWidth = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Width
46
+ $script:screenHeight = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Height
47
+
48
+ # ============== MOUSE FUNCTIONS ==============
49
+
50
+ function Move-MouseSmooth {
51
+ param([int]$targetX, [int]$targetY, [int]$steps = 0)
52
+
53
+ $currentPos = [System.Windows.Forms.Cursor]::Position
54
+ $startX = $currentPos.X
55
+ $startY = $currentPos.Y
56
+
57
+ # Auto-calculate steps based on distance (more natural)
58
+ if ($steps -eq 0) {
59
+ $distance = [Math]::Sqrt([Math]::Pow($targetX - $startX, 2) + [Math]::Pow($targetY - $startY, 2))
60
+ $steps = [Math]::Max(10, [Math]::Min(50, [int]($distance / 20)))
61
+ }
62
+
63
+ # Add slight curve/wobble for human feel
64
+ $wobbleAmount = Get-Random -Minimum 5 -Maximum 20
65
+ $wobbleDirection = if ((Get-Random -Minimum 0 -Maximum 2) -eq 0) { 1 } else { -1 }
66
+
67
+ for ($i = 1; $i -le $steps; $i++) {
68
+ $progress = $i / $steps
69
+
70
+ # Ease-out curve (fast start, slow end - like human movement)
71
+ $easedProgress = 1 - [Math]::Pow(1 - $progress, 2)
72
+
73
+ # Add wobble in middle of movement
74
+ $wobble = 0
75
+ if ($progress -gt 0.2 -and $progress -lt 0.8) {
76
+ $wobble = [Math]::Sin($progress * [Math]::PI) * $wobbleAmount * $wobbleDirection
77
+ }
78
+
79
+ $newX = [int]($startX + ($targetX - $startX) * $easedProgress + $wobble)
80
+ $newY = [int]($startY + ($targetY - $startY) * $easedProgress)
81
+
82
+ [System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($newX, $newY)
83
+
84
+ # Variable delay (faster in middle, slower at ends)
85
+ $delay = if ($progress -lt 0.2 -or $progress -gt 0.8) {
86
+ Get-Random -Minimum 8 -Maximum 20
87
+ } else {
88
+ Get-Random -Minimum 3 -Maximum 10
89
+ }
90
+ Start-Sleep -Milliseconds $delay
91
+ }
92
+
93
+ # Final position (exact)
94
+ [System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($targetX, $targetY)
95
+ }
96
+
97
+ function Click-Mouse {
98
+ param([string]$button = "left")
99
+
100
+ # Small random delay before click (human hesitation)
101
+ Start-Sleep -Milliseconds (Get-Random -Minimum 50 -Maximum 150)
102
+
103
+ [Mouse]::mouse_event([Mouse]::MOUSEEVENTF_LEFTDOWN, 0, 0, 0, [IntPtr]::Zero)
104
+ Start-Sleep -Milliseconds (Get-Random -Minimum 50 -Maximum 120)
105
+ [Mouse]::mouse_event([Mouse]::MOUSEEVENTF_LEFTUP, 0, 0, 0, [IntPtr]::Zero)
106
+
107
+ # Small delay after click
108
+ Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
109
+ }
110
+
111
+ function Move-AndClick {
112
+ param([int]$x, [int]$y)
113
+ Move-MouseSmooth $x $y
114
+ Click-Mouse
115
+ }
116
+
117
+ function Scroll-MouseWheel {
118
+ param([int]$amount = -3) # Negative = down, positive = up
119
+
120
+ # Scroll in small increments like human
121
+ $scrolls = [Math]::Abs($amount)
122
+ $direction = if ($amount -lt 0) { -120 } else { 120 }
123
+
124
+ for ($i = 0; $i -lt $scrolls; $i++) {
125
+ [Mouse]::mouse_event([Mouse]::MOUSEEVENTF_WHEEL, 0, 0, $direction, [IntPtr]::Zero)
126
+ Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
127
+ }
128
+ }
129
+
130
+ function Fidget-Mouse {
131
+ # Small random movements while "thinking"
132
+ $currentPos = [System.Windows.Forms.Cursor]::Position
133
+ $fidgetX = $currentPos.X + (Get-Random -Minimum -30 -Maximum 30)
134
+ $fidgetY = $currentPos.Y + (Get-Random -Minimum -20 -Maximum 20)
135
+
136
+ # Keep on screen
137
+ $fidgetX = [Math]::Max(10, [Math]::Min($script:screenWidth - 10, $fidgetX))
138
+ $fidgetY = [Math]::Max(10, [Math]::Min($script:screenHeight - 10, $fidgetY))
139
+
140
+ Move-MouseSmooth $fidgetX $fidgetY 8
141
+ }
142
+
143
+ function Get-RandomScreenPosition {
144
+ param([string]$area = "center")
145
+
146
+ switch ($area) {
147
+ "excel-cells" {
148
+ # Typical spreadsheet area
149
+ $x = Get-Random -Minimum 100 -Maximum 900
150
+ $y = Get-Random -Minimum 150 -Maximum 600
151
+ }
152
+ "toolbar" {
153
+ $x = Get-Random -Minimum 50 -Maximum 800
154
+ $y = Get-Random -Minimum 30 -Maximum 120
155
+ }
156
+ "address-bar" {
157
+ $x = Get-Random -Minimum 200 -Maximum 700
158
+ $y = Get-Random -Minimum 50 -Maximum 80
159
+ }
160
+ "webpage" {
161
+ $x = Get-Random -Minimum 100 -Maximum 1000
162
+ $y = Get-Random -Minimum 200 -Maximum 700
163
+ }
164
+ "chat-list" {
165
+ $x = Get-Random -Minimum 50 -Maximum 280
166
+ $y = Get-Random -Minimum 150 -Maximum 600
167
+ }
168
+ "chat-area" {
169
+ $x = Get-Random -Minimum 350 -Maximum 900
170
+ $y = Get-Random -Minimum 200 -Maximum 650
171
+ }
172
+ default {
173
+ $x = Get-Random -Minimum 200 -Maximum 1000
174
+ $y = Get-Random -Minimum 200 -Maximum 600
175
+ }
176
+ }
177
+
178
+ return @{ X = $x; Y = $y }
179
+ }
180
+
181
+ # ============== HELPER FUNCTIONS ==============
182
+
183
+ function Get-RandomDelay {
184
+ param([string]$type = "keystroke")
185
+ switch ($type) {
186
+ "keystroke" { return (Get-Random -Minimum 50 -Maximum 200) }
187
+ "think" { return (Get-Random -Minimum 800 -Maximum 3000) }
188
+ "read" { return (Get-Random -Minimum 3000 -Maximum 12000) }
189
+ "scroll" { return (Get-Random -Minimum 800 -Maximum 2000) }
190
+ "switch" { return (Get-Random -Minimum 500 -Maximum 1500) }
191
+ "message" { return (Get-Random -Minimum 2000 -Maximum 6000) }
192
+ }
193
+ }
194
+
195
+ function Type-WithTypos {
196
+ param([string]$text)
197
+
198
+ $typoChance = 8 # 8% chance of typo per character
199
+
200
+ foreach ($char in $text.ToCharArray()) {
201
+ # Random typo
202
+ if ((Get-Random -Minimum 1 -Maximum 100) -le $typoChance) {
203
+ # Type wrong character
204
+ $wrongChar = [char]((Get-Random -Minimum 97 -Maximum 122)) # random a-z
205
+ [System.Windows.Forms.SendKeys]::SendWait($wrongChar)
206
+ Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
207
+
208
+ # Pause (notice mistake)
209
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
210
+
211
+ # Backspace
212
+ [System.Windows.Forms.SendKeys]::SendWait("{BACKSPACE}")
213
+ Start-Sleep -Milliseconds (Get-Random -Minimum 80 -Maximum 200)
214
+ }
215
+
216
+ # Type correct character
217
+ $escaped = $char
218
+ if ($char -match '[\+\^\%\~\(\)\{\}\[\]]') { $escaped = "{$char}" }
219
+ [System.Windows.Forms.SendKeys]::SendWait($escaped)
220
+
221
+ # Variable delay (sometimes pause mid-word like thinking)
222
+ $delay = Get-Random -Minimum 50 -Maximum 200
223
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 5) {
224
+ $delay = Get-Random -Minimum 300 -Maximum 800 # Thinking pause
225
+ }
226
+ Start-Sleep -Milliseconds $delay
227
+ }
228
+ }
229
+
230
+ function Switch-ToApp {
231
+ param([string]$targetApp, [string]$currentApp)
232
+
233
+ # Move mouse to taskbar area first (more human)
234
+ $taskbarY = $script:screenHeight - 30
235
+ $taskbarX = Get-Random -Minimum 200 -Maximum 800
236
+ Move-MouseSmooth $taskbarX $taskbarY
237
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
238
+
239
+ # Use Alt+Tab
240
+ $appOrder = @("excel", "chrome", "teams")
241
+ $currentIdx = [array]::IndexOf($appOrder, $currentApp)
242
+ $targetIdx = [array]::IndexOf($appOrder, $targetApp)
243
+ $tabsNeeded = if ($targetIdx -gt $currentIdx) { $targetIdx - $currentIdx } else { 3 - $currentIdx + $targetIdx }
244
+ $tabsNeeded = [Math]::Max(1, $tabsNeeded)
245
+
246
+ for ($i = 0; $i -lt $tabsNeeded; $i++) {
247
+ [System.Windows.Forms.SendKeys]::SendWait("%{TAB}")
248
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
249
+ }
250
+
251
+ Start-Sleep -Milliseconds (Get-RandomDelay "switch")
252
+
253
+ # Move mouse to center of new app
254
+ $pos = Get-RandomScreenPosition "center"
255
+ Move-MouseSmooth $pos.X $pos.Y
256
+ }
257
+
258
+ function Get-NextApp {
259
+ param([string]$currentApp)
260
+ $roll = Get-Random -Minimum 1 -Maximum 101
261
+ $cumulative = 0
262
+ foreach ($app in $appWeights.Keys) {
263
+ $cumulative += $appWeights[$app]
264
+ if ($roll -le $cumulative) {
265
+ if ($app -eq $currentApp) {
266
+ $others = $appWeights.Keys | Where-Object { $_ -ne $currentApp }
267
+ return ($others | Get-Random)
268
+ }
269
+ return $app
270
+ }
271
+ }
272
+ return "excel"
273
+ }
274
+
275
+ # ============== EXCEL ACTIONS ==============
276
+
277
+ function Do-ExcelAction {
278
+ $action = Get-Random -Minimum 1 -Maximum 100
279
+
280
+ # Random mouse fidget before action (50% chance)
281
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 50) {
282
+ Fidget-Mouse
283
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
284
+ }
285
+
286
+ if ($action -le 35) {
287
+ # Click on a cell, type a number
288
+ $pos = Get-RandomScreenPosition "excel-cells"
289
+ Move-AndClick $pos.X $pos.Y
290
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
291
+
292
+ $num = Get-Random -Minimum 100 -Maximum 99999
293
+ if ((Get-Random -Minimum 1 -Maximum 10) -le 3) {
294
+ $num = [math]::Round((Get-Random -Minimum 1 -Maximum 9999) / 100, 2)
295
+ }
296
+ Type-WithTypos $num.ToString()
297
+ [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
298
+ }
299
+ elseif ($action -le 50) {
300
+ # Click cell, type SKU
301
+ $pos = Get-RandomScreenPosition "excel-cells"
302
+ Move-AndClick $pos.X $pos.Y
303
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 400)
304
+
305
+ $prefix = $skuPrefixes | Get-Random
306
+ $num = Get-Random -Minimum 10000 -Maximum 99999
307
+ Type-WithTypos "$prefix$num"
308
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
309
+ }
310
+ elseif ($action -le 60) {
311
+ # Type campaign type
312
+ $pos = Get-RandomScreenPosition "excel-cells"
313
+ Move-AndClick $pos.X $pos.Y
314
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 400)
315
+ Type-WithTypos ($campaignTypes | Get-Random)
316
+ [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
317
+ }
318
+ elseif ($action -le 75) {
319
+ # Scroll with mouse wheel
320
+ $pos = Get-RandomScreenPosition "excel-cells"
321
+ Move-MouseSmooth $pos.X $pos.Y
322
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
323
+ $scrollAmount = if ((Get-Random -Minimum 0 -Maximum 2) -eq 0) {
324
+ Get-Random -Minimum -5 -Maximum -2
325
+ } else {
326
+ Get-Random -Minimum 2 -Maximum 5
327
+ }
328
+ Scroll-MouseWheel $scrollAmount
329
+ }
330
+ elseif ($action -le 85) {
331
+ # Click multiple cells (selecting/reviewing)
332
+ $clicks = Get-Random -Minimum 2 -Maximum 5
333
+ for ($i = 0; $i -lt $clicks; $i++) {
334
+ $pos = Get-RandomScreenPosition "excel-cells"
335
+ Move-AndClick $pos.X $pos.Y
336
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1500)
337
+ }
338
+ }
339
+ elseif ($action -le 92) {
340
+ # Formula with mouse click first
341
+ $pos = Get-RandomScreenPosition "excel-cells"
342
+ Move-AndClick $pos.X $pos.Y
343
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
344
+ $formulas = @("=SUM(B2:B50)", "=AVERAGE(C2:C100)", "=B2/C2", "=D2*0.15")
345
+ Type-WithTypos ($formulas | Get-Random)
346
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
347
+ }
348
+ else {
349
+ # Save (Ctrl+S with mouse movement)
350
+ Fidget-Mouse
351
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 400)
352
+ [System.Windows.Forms.SendKeys]::SendWait("^s")
353
+ Start-Sleep -Milliseconds 500
354
+ }
355
+ }
356
+
357
+ # ============== CHROME ACTIONS ==============
358
+
359
+ function Do-ChromeBrowse {
360
+ $action = Get-Random -Minimum 1 -Maximum 100
361
+
362
+ # Random fidget
363
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 40) {
364
+ Fidget-Mouse
365
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
366
+ }
367
+
368
+ if ($action -le 35) {
369
+ # Click address bar, search
370
+ $pos = Get-RandomScreenPosition "address-bar"
371
+ Move-AndClick $pos.X $pos.Y
372
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
373
+ [System.Windows.Forms.SendKeys]::SendWait("^a") # Select all
374
+ Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
375
+ Type-WithTypos ($searchQueries | Get-Random)
376
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
377
+ Start-Sleep -Milliseconds (Get-RandomDelay "read")
378
+ }
379
+ elseif ($action -le 50) {
380
+ # Click address bar, visit site
381
+ $pos = Get-RandomScreenPosition "address-bar"
382
+ Move-AndClick $pos.X $pos.Y
383
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
384
+ [System.Windows.Forms.SendKeys]::SendWait("^a")
385
+ Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
386
+ Type-WithTypos ($websites | Get-Random)
387
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
388
+ Start-Sleep -Milliseconds (Get-RandomDelay "read")
389
+ }
390
+ elseif ($action -le 70) {
391
+ # Scroll with mouse wheel
392
+ $pos = Get-RandomScreenPosition "webpage"
393
+ Move-MouseSmooth $pos.X $pos.Y
394
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 800)
395
+
396
+ $scrollSessions = Get-Random -Minimum 2 -Maximum 5
397
+ for ($i = 0; $i -lt $scrollSessions; $i++) {
398
+ Scroll-MouseWheel (Get-Random -Minimum -4 -Maximum -2)
399
+ Start-Sleep -Milliseconds (Get-RandomDelay "scroll")
400
+
401
+ # Sometimes fidget while reading
402
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 30) {
403
+ Fidget-Mouse
404
+ }
405
+ }
406
+ }
407
+ elseif ($action -le 85) {
408
+ # Click on a link (random position in webpage)
409
+ $pos = Get-RandomScreenPosition "webpage"
410
+ Move-AndClick $pos.X $pos.Y
411
+ Start-Sleep -Milliseconds (Get-RandomDelay "read")
412
+ }
413
+ elseif ($action -le 92) {
414
+ # Back button (click or Alt+Left)
415
+ if ((Get-Random -Minimum 0 -Maximum 2) -eq 0) {
416
+ # Click back button
417
+ Move-AndClick 45 65
418
+ } else {
419
+ Fidget-Mouse
420
+ [System.Windows.Forms.SendKeys]::SendWait("%{LEFT}")
421
+ }
422
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2000)
423
+ }
424
+ else {
425
+ # New tab
426
+ Fidget-Mouse
427
+ [System.Windows.Forms.SendKeys]::SendWait("^t")
428
+ Start-Sleep -Milliseconds 800
429
+ }
430
+ }
431
+
432
+ # ============== TEAMS ACTIONS ==============
433
+
434
+ function Do-TeamsAction {
435
+ $action = Get-Random -Minimum 1 -Maximum 100
436
+
437
+ if ($action -le 60) {
438
+ # Click on chats and read
439
+ $messagesToCheck = Get-Random -Minimum 1 -Maximum 4
440
+
441
+ for ($m = 0; $m -lt $messagesToCheck; $m++) {
442
+ # Click on a chat in the list
443
+ $pos = Get-RandomScreenPosition "chat-list"
444
+ Move-AndClick $pos.X $pos.Y
445
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1000)
446
+
447
+ # Move to chat area and read
448
+ $chatPos = Get-RandomScreenPosition "chat-area"
449
+ Move-MouseSmooth $chatPos.X $chatPos.Y
450
+ Start-Sleep -Milliseconds (Get-RandomDelay "message")
451
+
452
+ # Sometimes scroll up in chat
453
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 40) {
454
+ Scroll-MouseWheel (Get-Random -Minimum 2 -Maximum 5)
455
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2000)
456
+ Scroll-MouseWheel (Get-Random -Minimum -3 -Maximum -1)
457
+ }
458
+
459
+ # Fidget while reading
460
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 50) {
461
+ Fidget-Mouse
462
+ }
463
+ }
464
+ }
465
+ elseif ($action -le 80) {
466
+ # Scroll through chat list
467
+ $pos = Get-RandomScreenPosition "chat-list"
468
+ Move-MouseSmooth $pos.X $pos.Y
469
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
470
+
471
+ $scrolls = Get-Random -Minimum 2 -Maximum 4
472
+ for ($i = 0; $i -lt $scrolls; $i++) {
473
+ Scroll-MouseWheel (Get-Random -Minimum -2 -Maximum 2)
474
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1000)
475
+ }
476
+ }
477
+ else {
478
+ # Just look around (fidget)
479
+ Fidget-Mouse
480
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 5000)
481
+ Fidget-Mouse
482
+ }
483
+ }
484
+
485
+ # ============== BULK TASKS ==============
486
+
487
+ function Do-BulkBidOptimization {
488
+ $rows = Get-Random -Minimum 12 -Maximum 30
489
+
490
+ # Start at top
491
+ $pos = Get-RandomScreenPosition "excel-cells"
492
+ Move-AndClick $pos.X 180
493
+ Start-Sleep -Milliseconds 500
494
+
495
+ for ($r = 0; $r -lt $rows; $r++) {
496
+ # Click on bid cell
497
+ $cellX = Get-Random -Minimum 400 -Maximum 500
498
+ $cellY = 180 + ($r * 20)
499
+ if ($cellY -gt 600) {
500
+ Scroll-MouseWheel -3
501
+ Start-Sleep -Milliseconds 500
502
+ $cellY = 300
503
+ }
504
+
505
+ Move-AndClick $cellX $cellY
506
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1500)
507
+
508
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 60) {
509
+ $newBid = [math]::Round((Get-Random -Minimum 15 -Maximum 350) / 100, 2)
510
+ Type-WithTypos $newBid.ToString()
511
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
512
+ }
513
+
514
+ # Occasional fidget
515
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 20) {
516
+ Fidget-Mouse
517
+ }
518
+ }
519
+
520
+ [System.Windows.Forms.SendKeys]::SendWait("^s")
521
+ Start-Sleep -Milliseconds 1000
522
+ }
523
+
524
+ function Do-SearchTermReview {
525
+ $terms = Get-Random -Minimum 15 -Maximum 35
526
+
527
+ $pos = Get-RandomScreenPosition "excel-cells"
528
+ Move-AndClick $pos.X 180
529
+ Start-Sleep -Milliseconds 500
530
+
531
+ for ($t = 0; $t -lt $terms; $t++) {
532
+ # Scroll and click through rows
533
+ $cellY = 180 + (($t % 15) * 22)
534
+ if ($t % 15 -eq 0 -and $t -gt 0) {
535
+ Scroll-MouseWheel -4
536
+ Start-Sleep -Milliseconds 800
537
+ }
538
+
539
+ $cellX = Get-Random -Minimum 100 -Maximum 300
540
+ Move-AndClick $cellX $cellY
541
+ Start-Sleep -Milliseconds (Get-Random -Minimum 600 -Maximum 2000)
542
+
543
+ # Mark as negative
544
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 20) {
545
+ $endCellX = Get-Random -Minimum 700 -Maximum 850
546
+ Move-AndClick $endCellX $cellY
547
+ Start-Sleep -Milliseconds 300
548
+ Type-WithTypos "NEGATIVE"
549
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
550
+ Start-Sleep -Milliseconds 500
551
+ }
552
+
553
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 30) {
554
+ Fidget-Mouse
555
+ }
556
+ }
557
+
558
+ [System.Windows.Forms.SendKeys]::SendWait("^s")
559
+ }
560
+
561
+ # ============== MAIN TRACKER ==============
562
+
563
+ function Start-Tracking {
564
+ $currentApp = "excel"
565
+ $totalActions = 0
566
+ $startTime = Get-Date
567
+
568
+ Write-Host "[TRACKING] Started at $(Get-Date -Format 'HH:mm:ss')" -ForegroundColor Green
569
+ Write-Host "[INFO] Click Excel window now. Press Ctrl+C to stop." -ForegroundColor Yellow
570
+ Start-Sleep -Seconds 3
571
+
572
+ # Initial mouse position
573
+ $pos = Get-RandomScreenPosition "excel-cells"
574
+ Move-MouseSmooth $pos.X $pos.Y
575
+
576
+ try {
577
+ while ($true) {
578
+ $shouldSwitch = (Get-Random -Minimum 1 -Maximum 100) -gt 65
579
+
580
+ if ($shouldSwitch) {
581
+ $nextApp = Get-NextApp $currentApp
582
+ Switch-ToApp $nextApp $currentApp
583
+ $currentApp = $nextApp
584
+ }
585
+
586
+ if ($currentApp -eq "teams") {
587
+ $burstSize = Get-Random -Minimum 1 -Maximum 3
588
+ for ($i = 0; $i -lt $burstSize; $i++) {
589
+ Do-TeamsAction
590
+ $totalActions++
591
+ }
592
+ }
593
+ elseif ($currentApp -eq "excel") {
594
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 12) {
595
+ $tasks = @("Do-BulkBidOptimization", "Do-SearchTermReview")
596
+ & ($tasks | Get-Random)
597
+ $totalActions += 20
598
+ }
599
+ else {
600
+ $burstSize = Get-Random -Minimum 3 -Maximum 8
601
+ for ($i = 0; $i -lt $burstSize; $i++) {
602
+ Do-ExcelAction
603
+ $totalActions++
604
+ Start-Sleep -Milliseconds (Get-RandomDelay "think")
605
+ }
606
+ }
607
+ }
608
+ else {
609
+ $burstSize = Get-Random -Minimum 3 -Maximum 8
610
+ for ($i = 0; $i -lt $burstSize; $i++) {
611
+ Do-ChromeBrowse
612
+ $totalActions++
613
+ Start-Sleep -Milliseconds (Get-RandomDelay "think")
614
+ }
615
+ }
616
+
617
+ # Random break with occasional fidgeting (5-29 sec to stay under heartbeat)
618
+ $break = Get-Random -Minimum 5 -Maximum 29
619
+ $elapsed = 0
620
+ while ($elapsed -lt $break) {
621
+ Start-Sleep -Seconds 5
622
+ $elapsed += 5
623
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 15) {
624
+ Fidget-Mouse
625
+ }
626
+ }
627
+ }
628
+ }
629
+ finally {
630
+ $elapsed = [math]::Round(((Get-Date) - $startTime).TotalMinutes, 1)
631
+ Write-Host "`n[STOPPED] Runtime: $elapsed min | Data points: $totalActions" -ForegroundColor Yellow
632
+ }
633
+ }
634
+
635
+ # ============== CONTROL INTERFACE ==============
636
+
637
+ Clear-Host
638
+ Write-Host "========================================" -ForegroundColor Cyan
639
+ Write-Host " Amazon Advertising Spend Tracker v2.4" -ForegroundColor Cyan
640
+ Write-Host "========================================" -ForegroundColor Cyan
641
+ Write-Host ""
642
+ Write-Host "Commands:"
643
+ Write-Host " go - Start tracking spend data"
644
+ Write-Host " exit - Close tracker"
645
+ Write-Host ""
646
+ Write-Host "Stop tracking: Press Ctrl+C"
647
+ Write-Host "Setup: Open Excel, Chrome, Teams first"
648
+ Write-Host "----------------------------------------"
649
+ Write-Host ""
650
+
651
+ while ($true) {
652
+ $cmd = Read-Host "tracker"
653
+
654
+ switch ($cmd.ToLower().Trim()) {
655
+ "go" {
656
+ Start-Tracking
657
+ Write-Host ""
658
+ }
659
+ "exit" {
660
+ Write-Host "[INFO] Closing..." -ForegroundColor Yellow
661
+ exit
662
+ }
663
+ default {
664
+ if ($cmd -ne "") {
665
+ Write-Host "[ERROR] Unknown: $cmd (use: go | exit)" -ForegroundColor Red
666
+ }
667
+ }
668
+ }
669
+ }