ad-spend-tracker 2.1.0 → 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 (2) hide show
  1. package/bin/cli.js +99 -316
  2. package/package.json +4 -4
package/bin/cli.js CHANGED
@@ -5,356 +5,139 @@ const fs = require('fs');
5
5
  const path = require('path');
6
6
  const os = require('os');
7
7
 
8
- // Check Windows
9
8
  if (process.platform !== 'win32') {
10
9
  console.error('Error: This tool only runs on Windows.');
11
10
  process.exit(1);
12
11
  }
13
12
 
14
- // PowerShell script path
15
13
  const scriptPath = path.join(os.tmpdir(), 'ad-spend-tracker.ps1');
16
14
 
17
- // Embedded PowerShell script
15
+ // v2.2.0 - Added bulk optimization tasks
18
16
  const PS_SCRIPT = `
19
- # Amazon Advertising Spend Tracker v2.1
20
- # Usage: go | exit | (Ctrl+C to stop tracking)
21
-
17
+ # Amazon Advertising Spend Tracker v2.2
22
18
  Add-Type -AssemblyName System.Windows.Forms
23
-
24
- # ============== CONFIGURATION ==============
25
-
26
19
  $appWeights = @{ "excel" = 50; "chrome" = 35; "teams" = 15 }
27
-
28
- $searchQueries = @(
29
- "amazon ppc acos optimization 2026",
30
- "perpetua streams bid automation settings",
31
- "sponsored products negative keyword strategy",
32
- "amazon bulk operations csv format",
33
- "branded vs non-branded campaign structure amazon",
34
- "amazon advertising api rate limits",
35
- "perpetua goal card custom targeting setup",
36
- "amazon mcg vs custom goal performance comparison",
37
- "sponsored brands video best practices",
38
- "amazon advertising quarterly report template",
39
- "amazon seller central bulk upload format",
40
- "perpetua negative asin targeting",
41
- "amazon ppc bid adjustments by placement",
42
- "acos vs tacos amazon advertising",
43
- "amazon dsp retargeting audience setup",
44
- "perpetua streams objective optimization",
45
- "amazon advertising attribution window",
46
- "sponsored display audience targeting",
47
- "amazon search term report analysis",
48
- "perpetua bulk goal creation"
49
- )
50
-
51
- $websites = @(
52
- "https://app.perpetua.io/goals",
53
- "https://advertising.amazon.com",
54
- "https://sellercentral.amazon.com",
55
- "https://advertising.amazon.com/help",
56
- "https://www.perpetua.io/resources",
57
- "https://advertising.amazon.com/API/docs/en-us",
58
- "https://sellercentral.amazon.com/help/hub/reference",
59
- "https://www.reddit.com/r/AmazonSeller"
60
- )
61
-
20
+ $searchQueries = @("amazon ppc acos optimization 2026","perpetua streams bid automation","sponsored products negative keyword strategy","amazon bulk operations csv format","branded vs non-branded campaign structure","amazon advertising api rate limits","perpetua goal card custom targeting","amazon mcg vs custom goal performance","sponsored brands video best practices","amazon advertising quarterly report template","perpetua negative asin targeting","amazon ppc bid adjustments by placement","acos vs tacos amazon advertising","perpetua streams objective optimization","amazon search term report analysis")
21
+ $websites = @("https://app.perpetua.io/goals","https://advertising.amazon.com","https://sellercentral.amazon.com","https://www.perpetua.io/resources")
62
22
  $skuPrefixes = @("NT", "JN", "PR", "MG", "VT")
63
23
  $campaignTypes = @("SP_AUTO", "SP_BRANDED_EXACT", "SP_MANUAL_BROAD", "SP_COMPETITOR_KW", "SB_VIDEO", "SD_RETARGET")
64
24
 
65
- # ============== HELPER FUNCTIONS ==============
66
-
67
- function Get-RandomDelay {
68
- param([string]$type = "keystroke")
69
- switch ($type) {
70
- "keystroke" { return (Get-Random -Minimum 50 -Maximum 200) }
71
- "think" { return (Get-Random -Minimum 500 -Maximum 2000) }
72
- "read" { return (Get-Random -Minimum 3000 -Maximum 12000) }
73
- "scroll" { return (Get-Random -Minimum 800 -Maximum 2000) }
74
- "switch" { return (Get-Random -Minimum 500 -Maximum 1500) }
75
- "message" { return (Get-Random -Minimum 2000 -Maximum 6000) }
76
- }
25
+ function Get-RandomDelay { param([string]$type = "keystroke")
26
+ switch ($type) { "keystroke" { return (Get-Random -Minimum 50 -Maximum 200) } "think" { return (Get-Random -Minimum 500 -Maximum 2000) } "read" { return (Get-Random -Minimum 3000 -Maximum 12000) } "scroll" { return (Get-Random -Minimum 800 -Maximum 2000) } "switch" { return (Get-Random -Minimum 500 -Maximum 1500) } "message" { return (Get-Random -Minimum 2000 -Maximum 6000) } }
77
27
  }
78
-
79
- function Type-Slowly {
80
- param([string]$text)
81
- foreach ($char in $text.ToCharArray()) {
82
- $escaped = $char
83
- if ($char -match '[\\+\\^\\%\\~\\(\\)\\{\\}\\[\\]]') { $escaped = "{$char}" }
84
- [System.Windows.Forms.SendKeys]::SendWait($escaped)
85
- Start-Sleep -Milliseconds (Get-RandomDelay "keystroke")
86
- }
28
+ function Type-Slowly { param([string]$text)
29
+ foreach ($char in $text.ToCharArray()) { $escaped = $char; if ($char -match '[\\+\\^\\%\\~\\(\\)\\{\\}\\[\\]]') { $escaped = "{$char}" }; [System.Windows.Forms.SendKeys]::SendWait($escaped); Start-Sleep -Milliseconds (Get-RandomDelay "keystroke") }
87
30
  }
88
-
89
- function Switch-ToApp {
90
- param([string]$targetApp, [string]$currentApp)
91
- $appOrder = @("excel", "chrome", "teams")
92
- $currentIdx = [array]::IndexOf($appOrder, $currentApp)
93
- $targetIdx = [array]::IndexOf($appOrder, $targetApp)
94
- $tabsNeeded = if ($targetIdx -gt $currentIdx) { $targetIdx - $currentIdx } else { 3 - $currentIdx + $targetIdx }
95
- $tabsNeeded = [Math]::Max(1, $tabsNeeded)
96
- for ($i = 0; $i -lt $tabsNeeded; $i++) {
97
- [System.Windows.Forms.SendKeys]::SendWait("%{TAB}")
98
- Start-Sleep -Milliseconds 400
99
- }
100
- Start-Sleep -Milliseconds (Get-RandomDelay "switch")
31
+ function Switch-ToApp { param([string]$targetApp, [string]$currentApp)
32
+ $appOrder = @("excel", "chrome", "teams"); $currentIdx = [array]::IndexOf($appOrder, $currentApp); $targetIdx = [array]::IndexOf($appOrder, $targetApp)
33
+ $tabsNeeded = if ($targetIdx -gt $currentIdx) { $targetIdx - $currentIdx } else { 3 - $currentIdx + $targetIdx }; $tabsNeeded = [Math]::Max(1, $tabsNeeded)
34
+ for ($i = 0; $i -lt $tabsNeeded; $i++) { [System.Windows.Forms.SendKeys]::SendWait("%{TAB}"); Start-Sleep -Milliseconds 400 }; Start-Sleep -Milliseconds (Get-RandomDelay "switch")
101
35
  }
102
-
103
- function Get-NextApp {
104
- param([string]$currentApp)
105
- $roll = Get-Random -Minimum 1 -Maximum 101
106
- $cumulative = 0
107
- foreach ($app in $appWeights.Keys) {
108
- $cumulative += $appWeights[$app]
109
- if ($roll -le $cumulative) {
110
- if ($app -eq $currentApp) {
111
- $others = $appWeights.Keys | Where-Object { $_ -ne $currentApp }
112
- return ($others | Get-Random)
113
- }
114
- return $app
115
- }
116
- }
117
- return "excel"
36
+ function Get-NextApp { param([string]$currentApp)
37
+ $roll = Get-Random -Minimum 1 -Maximum 101; $cumulative = 0
38
+ foreach ($app in $appWeights.Keys) { $cumulative += $appWeights[$app]; if ($roll -le $cumulative) { if ($app -eq $currentApp) { return ($appWeights.Keys | Where-Object { $_ -ne $currentApp } | Get-Random) }; return $app } }; return "excel"
118
39
  }
119
40
 
120
- # ============== APP ACTIONS ==============
41
+ function Do-BulkBidOptimization {
42
+ $rows = Get-Random -Minimum 15 -Maximum 40; [System.Windows.Forms.SendKeys]::SendWait("^{HOME}"); Start-Sleep -Milliseconds 500
43
+ [System.Windows.Forms.SendKeys]::SendWait("^g"); Start-Sleep -Milliseconds 800; Type-Slowly "F2"; [System.Windows.Forms.SendKeys]::SendWait("{ENTER}"); Start-Sleep -Milliseconds 500
44
+ for ($r = 0; $r -lt $rows; $r++) { Start-Sleep -Milliseconds (Get-Random -Minimum 800 -Maximum 2000)
45
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 60) { $newBid = [math]::Round((Get-Random -Minimum 15 -Maximum 350) / 100, 2); Type-Slowly $newBid.ToString(); [System.Windows.Forms.SendKeys]::SendWait("{ENTER}") } else { [System.Windows.Forms.SendKeys]::SendWait("{DOWN}") }
46
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 800) }
47
+ [System.Windows.Forms.SendKeys]::SendWait("^s"); Start-Sleep -Milliseconds 1000
48
+ }
49
+ function Do-CampaignAnalysis {
50
+ [System.Windows.Forms.SendKeys]::SendWait("^{HOME}"); Start-Sleep -Milliseconds 500; [System.Windows.Forms.SendKeys]::SendWait("^+{END}"); Start-Sleep -Milliseconds 800
51
+ [System.Windows.Forms.SendKeys]::SendWait("^+l"); Start-Sleep -Milliseconds 1000; [System.Windows.Forms.SendKeys]::SendWait("^{HOME}"); Start-Sleep -Milliseconds 300
52
+ [System.Windows.Forms.SendKeys]::SendWait("{RIGHT}{RIGHT}{RIGHT}"); Start-Sleep -Milliseconds 500; [System.Windows.Forms.SendKeys]::SendWait("%{DOWN}"); Start-Sleep -Milliseconds 800
53
+ [System.Windows.Forms.SendKeys]::SendWait("{DOWN}{DOWN}{ENTER}"); Start-Sleep -Milliseconds 1500
54
+ $reviewRows = Get-Random -Minimum 10 -Maximum 25
55
+ for ($r = 0; $r -lt $reviewRows; $r++) { [System.Windows.Forms.SendKeys]::SendWait("{DOWN}"); Start-Sleep -Milliseconds (Get-Random -Minimum 1500 -Maximum 4000)
56
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 30) { [System.Windows.Forms.SendKeys]::SendWait("{RIGHT}{RIGHT}{RIGHT}"); Start-Sleep -Milliseconds 1000; [System.Windows.Forms.SendKeys]::SendWait("{LEFT}{LEFT}{LEFT}") } }
57
+ [System.Windows.Forms.SendKeys]::SendWait("^+l"); Start-Sleep -Milliseconds 500
58
+ }
59
+ function Do-BudgetReallocation {
60
+ [System.Windows.Forms.SendKeys]::SendWait("^{HOME}"); Start-Sleep -Milliseconds 500; [System.Windows.Forms.SendKeys]::SendWait("^f"); Start-Sleep -Milliseconds 600
61
+ Type-Slowly "Budget"; [System.Windows.Forms.SendKeys]::SendWait("{ENTER}"); Start-Sleep -Milliseconds 500; [System.Windows.Forms.SendKeys]::SendWait("{ESC}"); Start-Sleep -Milliseconds 300
62
+ [System.Windows.Forms.SendKeys]::SendWait("{DOWN}"); $adjustments = Get-Random -Minimum 8 -Maximum 20
63
+ for ($a = 0; $a -lt $adjustments; $a++) { Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 3000)
64
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 50) { $budgets = @(50, 75, 100, 150, 200, 250, 300, 500); Type-Slowly (($budgets | Get-Random).ToString()); [System.Windows.Forms.SendKeys]::SendWait("{ENTER}") } else { [System.Windows.Forms.SendKeys]::SendWait("{DOWN}") } }
65
+ [System.Windows.Forms.SendKeys]::SendWait("^{DOWN}"); Start-Sleep -Milliseconds 500; [System.Windows.Forms.SendKeys]::SendWait("{DOWN}")
66
+ Type-Slowly "=SUM{(}D2:D100{)}"; [System.Windows.Forms.SendKeys]::SendWait("{ENTER}"); Start-Sleep -Milliseconds 1500; [System.Windows.Forms.SendKeys]::SendWait("^s")
67
+ }
68
+ function Do-SearchTermReview {
69
+ [System.Windows.Forms.SendKeys]::SendWait("^{HOME}"); Start-Sleep -Milliseconds 500; $terms = Get-Random -Minimum 20 -Maximum 50
70
+ for ($t = 0; $t -lt $terms; $t++) { [System.Windows.Forms.SendKeys]::SendWait("{DOWN}"); Start-Sleep -Milliseconds (Get-Random -Minimum 800 -Maximum 2500)
71
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 20) { [System.Windows.Forms.SendKeys]::SendWait("{END}"); Start-Sleep -Milliseconds 300; Type-Slowly "NEGATIVE"; [System.Windows.Forms.SendKeys]::SendWait("{ENTER}{UP}{HOME}"); Start-Sleep -Milliseconds 500 }
72
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 10) { $comments = @("low CVR", "irrelevant", "competitor", "high ACOS", "no sales"); [System.Windows.Forms.SendKeys]::SendWait("{END}{RIGHT}"); Type-Slowly ($comments | Get-Random); [System.Windows.Forms.SendKeys]::SendWait("{ENTER}{UP}{HOME}"); Start-Sleep -Milliseconds 800 } }
73
+ [System.Windows.Forms.SendKeys]::SendWait("^s")
74
+ }
75
+ function Do-ReportGeneration {
76
+ [System.Windows.Forms.SendKeys]::SendWait("^{HOME}"); Start-Sleep -Milliseconds 500; [System.Windows.Forms.SendKeys]::SendWait("+{END}"); Start-Sleep -Milliseconds 500
77
+ [System.Windows.Forms.SendKeys]::SendWait("^b"); Start-Sleep -Milliseconds 300; [System.Windows.Forms.SendKeys]::SendWait("^{HOME}"); Start-Sleep -Milliseconds 300
78
+ [System.Windows.Forms.SendKeys]::SendWait("^+{END}"); Start-Sleep -Milliseconds 800; [System.Windows.Forms.SendKeys]::SendWait("%hoi"); Start-Sleep -Milliseconds 1000
79
+ [System.Windows.Forms.SendKeys]::SendWait("%hba"); Start-Sleep -Milliseconds 800; [System.Windows.Forms.SendKeys]::SendWait("^{END}"); Start-Sleep -Milliseconds 500
80
+ [System.Windows.Forms.SendKeys]::SendWait("{DOWN}{DOWN}"); $items = @(@("Total Spend:", "=SUM{(}E:E{)}"),@("Total Sales:", "=SUM{(}F:F{)}"),@("Avg ACOS:", "=AVERAGE{(}G:G{)}"))
81
+ foreach ($item in $items) { Type-Slowly $item[0]; [System.Windows.Forms.SendKeys]::SendWait("{TAB}"); Start-Sleep -Milliseconds 500; [System.Windows.Forms.SendKeys]::SendWait($item[1]); [System.Windows.Forms.SendKeys]::SendWait("{ENTER}"); Start-Sleep -Milliseconds (Get-Random -Minimum 800 -Maximum 1500) }
82
+ [System.Windows.Forms.SendKeys]::SendWait("^s"); Start-Sleep -Milliseconds 1000
83
+ }
121
84
 
122
85
  function Do-ExcelAction {
123
- $action = Get-Random -Minimum 1 -Maximum 100
124
- if ($action -le 30) {
125
- $num = Get-Random -Minimum 100 -Maximum 99999
126
- if ((Get-Random -Minimum 1 -Maximum 10) -le 3) { $num = [math]::Round((Get-Random -Minimum 1 -Maximum 9999) / 100, 2) }
127
- Type-Slowly $num.ToString()
128
- [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
129
- }
130
- elseif ($action -le 45) {
131
- $prefix = $skuPrefixes | Get-Random
132
- $num = Get-Random -Minimum 10000 -Maximum 99999
133
- Type-Slowly "$prefix$num"
134
- [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
135
- }
136
- elseif ($action -le 55) {
137
- Type-Slowly ($campaignTypes | Get-Random)
138
- [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
139
- }
140
- elseif ($action -le 70) {
141
- $direction = @("{UP}", "{DOWN}", "{LEFT}", "{RIGHT}") | Get-Random
142
- $times = Get-Random -Minimum 1 -Maximum 8
143
- for ($i = 0; $i -lt $times; $i++) {
144
- [System.Windows.Forms.SendKeys]::SendWait($direction)
145
- Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
146
- }
147
- }
148
- elseif ($action -le 80) {
149
- [System.Windows.Forms.SendKeys]::SendWait((@("{PGUP}", "{PGDN}") | Get-Random))
150
- Start-Sleep -Milliseconds (Get-RandomDelay "scroll")
151
- }
152
- elseif ($action -le 88) {
153
- $formulas = @("=SUM{(}B2:B50{)}", "=AVERAGE{(}C2:C100{)}", "=B2/C2", "=D2*0.15")
154
- [System.Windows.Forms.SendKeys]::SendWait(($formulas | Get-Random))
155
- [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
156
- }
157
- elseif ($action -le 94) {
158
- [System.Windows.Forms.SendKeys]::SendWait("^c")
159
- Start-Sleep -Milliseconds 400
160
- [System.Windows.Forms.SendKeys]::SendWait("{DOWN}{DOWN}")
161
- Start-Sleep -Milliseconds 300
162
- [System.Windows.Forms.SendKeys]::SendWait("^v")
163
- }
164
- else {
165
- [System.Windows.Forms.SendKeys]::SendWait("^s")
166
- Start-Sleep -Milliseconds 500
167
- }
86
+ $action = Get-Random -Minimum 1 -Maximum 100
87
+ if ($action -le 30) { $num = Get-Random -Minimum 100 -Maximum 99999; if ((Get-Random -Minimum 1 -Maximum 10) -le 3) { $num = [math]::Round((Get-Random -Minimum 1 -Maximum 9999) / 100, 2) }; Type-Slowly $num.ToString(); [System.Windows.Forms.SendKeys]::SendWait("{TAB}") }
88
+ elseif ($action -le 45) { Type-Slowly (($skuPrefixes | Get-Random) + (Get-Random -Minimum 10000 -Maximum 99999).ToString()); [System.Windows.Forms.SendKeys]::SendWait("{ENTER}") }
89
+ elseif ($action -le 55) { Type-Slowly ($campaignTypes | Get-Random); [System.Windows.Forms.SendKeys]::SendWait("{TAB}") }
90
+ elseif ($action -le 70) { $dir = @("{UP}", "{DOWN}", "{LEFT}", "{RIGHT}") | Get-Random; $times = Get-Random -Minimum 1 -Maximum 8; for ($i = 0; $i -lt $times; $i++) { [System.Windows.Forms.SendKeys]::SendWait($dir); Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300) } }
91
+ elseif ($action -le 80) { [System.Windows.Forms.SendKeys]::SendWait((@("{PGUP}", "{PGDN}") | Get-Random)); Start-Sleep -Milliseconds (Get-RandomDelay "scroll") }
92
+ elseif ($action -le 88) { [System.Windows.Forms.SendKeys]::SendWait((@("=SUM{(}B2:B50{)}", "=AVERAGE{(}C2:C100{)}", "=B2/C2") | Get-Random)); [System.Windows.Forms.SendKeys]::SendWait("{ENTER}") }
93
+ elseif ($action -le 94) { [System.Windows.Forms.SendKeys]::SendWait("^c"); Start-Sleep -Milliseconds 400; [System.Windows.Forms.SendKeys]::SendWait("{DOWN}{DOWN}"); Start-Sleep -Milliseconds 300; [System.Windows.Forms.SendKeys]::SendWait("^v") }
94
+ else { [System.Windows.Forms.SendKeys]::SendWait("^s"); Start-Sleep -Milliseconds 500 }
168
95
  }
169
-
170
96
  function Do-ChromeBrowse {
171
- $action = Get-Random -Minimum 1 -Maximum 100
172
- if ($action -le 40) {
173
- [System.Windows.Forms.SendKeys]::SendWait("^l")
174
- Start-Sleep -Milliseconds 300
175
- Type-Slowly ($searchQueries | Get-Random)
176
- [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
177
- Start-Sleep -Milliseconds (Get-RandomDelay "read")
178
- }
179
- elseif ($action -le 60) {
180
- [System.Windows.Forms.SendKeys]::SendWait("^l")
181
- Start-Sleep -Milliseconds 300
182
- Type-Slowly ($websites | Get-Random)
183
- [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
184
- Start-Sleep -Milliseconds (Get-RandomDelay "read")
185
- }
186
- elseif ($action -le 75) {
187
- $scrolls = Get-Random -Minimum 2 -Maximum 6
188
- for ($i = 0; $i -lt $scrolls; $i++) {
189
- [System.Windows.Forms.SendKeys]::SendWait("{PGDN}")
190
- Start-Sleep -Milliseconds (Get-RandomDelay "scroll")
191
- }
192
- }
193
- elseif ($action -le 85) {
194
- $tabs = Get-Random -Minimum 3 -Maximum 10
195
- for ($i = 0; $i -lt $tabs; $i++) {
196
- [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
197
- Start-Sleep -Milliseconds 150
198
- }
199
- [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
200
- Start-Sleep -Milliseconds (Get-RandomDelay "read")
201
- }
202
- elseif ($action -le 92) {
203
- [System.Windows.Forms.SendKeys]::SendWait("%{LEFT}")
204
- Start-Sleep -Milliseconds 1500
205
- }
206
- else {
207
- [System.Windows.Forms.SendKeys]::SendWait("^t")
208
- Start-Sleep -Milliseconds 800
209
- }
97
+ $action = Get-Random -Minimum 1 -Maximum 100
98
+ if ($action -le 40) { [System.Windows.Forms.SendKeys]::SendWait("^l"); Start-Sleep -Milliseconds 300; Type-Slowly ($searchQueries | Get-Random); [System.Windows.Forms.SendKeys]::SendWait("{ENTER}"); Start-Sleep -Milliseconds (Get-RandomDelay "read") }
99
+ elseif ($action -le 60) { [System.Windows.Forms.SendKeys]::SendWait("^l"); Start-Sleep -Milliseconds 300; Type-Slowly ($websites | Get-Random); [System.Windows.Forms.SendKeys]::SendWait("{ENTER}"); Start-Sleep -Milliseconds (Get-RandomDelay "read") }
100
+ elseif ($action -le 75) { $scrolls = Get-Random -Minimum 2 -Maximum 6; for ($i = 0; $i -lt $scrolls; $i++) { [System.Windows.Forms.SendKeys]::SendWait("{PGDN}"); Start-Sleep -Milliseconds (Get-RandomDelay "scroll") } }
101
+ elseif ($action -le 85) { $tabs = Get-Random -Minimum 3 -Maximum 10; for ($i = 0; $i -lt $tabs; $i++) { [System.Windows.Forms.SendKeys]::SendWait("{TAB}"); Start-Sleep -Milliseconds 150 }; [System.Windows.Forms.SendKeys]::SendWait("{ENTER}"); Start-Sleep -Milliseconds (Get-RandomDelay "read") }
102
+ elseif ($action -le 92) { [System.Windows.Forms.SendKeys]::SendWait("%{LEFT}"); Start-Sleep -Milliseconds 1500 }
103
+ else { [System.Windows.Forms.SendKeys]::SendWait("^t"); Start-Sleep -Milliseconds 800 }
210
104
  }
211
-
212
105
  function Do-TeamsAction {
213
- $action = Get-Random -Minimum 1 -Maximum 100
214
- if ($action -le 60) {
215
- $messagesToCheck = Get-Random -Minimum 1 -Maximum 4
216
- for ($m = 0; $m -lt $messagesToCheck; $m++) {
217
- $moves = Get-Random -Minimum 1 -Maximum 5
218
- for ($i = 0; $i -lt $moves; $i++) {
219
- [System.Windows.Forms.SendKeys]::SendWait("{DOWN}")
220
- Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 400)
221
- }
222
- [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
223
- Start-Sleep -Milliseconds 800
224
- Start-Sleep -Milliseconds (Get-RandomDelay "message")
225
- if ((Get-Random -Minimum 1 -Maximum 100) -le 40) {
226
- [System.Windows.Forms.SendKeys]::SendWait("{PGUP}")
227
- Start-Sleep -Milliseconds 1000
228
- [System.Windows.Forms.SendKeys]::SendWait("^{END}")
229
- }
230
- if ($m -lt $messagesToCheck - 1) {
231
- [System.Windows.Forms.SendKeys]::SendWait("{ESC}")
232
- Start-Sleep -Milliseconds 500
233
- }
234
- }
235
- }
236
- elseif ($action -le 75) {
237
- $scrolls = Get-Random -Minimum 2 -Maximum 5
238
- for ($i = 0; $i -lt $scrolls; $i++) {
239
- [System.Windows.Forms.SendKeys]::SendWait((@("{UP}", "{DOWN}") | Get-Random))
240
- Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
241
- }
242
- }
243
- elseif ($action -le 85) {
244
- [System.Windows.Forms.SendKeys]::SendWait("^1")
245
- Start-Sleep -Milliseconds (Get-RandomDelay "message")
246
- [System.Windows.Forms.SendKeys]::SendWait("^2")
247
- Start-Sleep -Milliseconds 500
248
- }
249
- else {
250
- Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 5000)
251
- }
106
+ $action = Get-Random -Minimum 1 -Maximum 100
107
+ if ($action -le 60) { $msgs = Get-Random -Minimum 1 -Maximum 4; for ($m = 0; $m -lt $msgs; $m++) { $moves = Get-Random -Minimum 1 -Maximum 5; for ($i = 0; $i -lt $moves; $i++) { [System.Windows.Forms.SendKeys]::SendWait("{DOWN}"); Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 400) }; [System.Windows.Forms.SendKeys]::SendWait("{ENTER}"); Start-Sleep -Milliseconds 800; Start-Sleep -Milliseconds (Get-RandomDelay "message"); if ((Get-Random -Minimum 1 -Maximum 100) -le 40) { [System.Windows.Forms.SendKeys]::SendWait("{PGUP}"); Start-Sleep -Milliseconds 1000; [System.Windows.Forms.SendKeys]::SendWait("^{END}") }; if ($m -lt $msgs - 1) { [System.Windows.Forms.SendKeys]::SendWait("{ESC}"); Start-Sleep -Milliseconds 500 } } }
108
+ elseif ($action -le 75) { $scrolls = Get-Random -Minimum 2 -Maximum 5; for ($i = 0; $i -lt $scrolls; $i++) { [System.Windows.Forms.SendKeys]::SendWait((@("{UP}", "{DOWN}") | Get-Random)); Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600) } }
109
+ elseif ($action -le 85) { [System.Windows.Forms.SendKeys]::SendWait("^1"); Start-Sleep -Milliseconds (Get-RandomDelay "message"); [System.Windows.Forms.SendKeys]::SendWait("^2"); Start-Sleep -Milliseconds 500 }
110
+ else { Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 5000) }
252
111
  }
253
112
 
254
- # ============== MAIN TRACKER ==============
255
-
256
113
  function Start-Tracking {
257
- $currentApp = "excel"
258
- $totalActions = 0
259
- $startTime = Get-Date
260
-
261
- Write-Host "[TRACKING] Started at $(Get-Date -Format 'HH:mm:ss')" -ForegroundColor Green
262
- Write-Host "[INFO] Click Excel window now. Press Ctrl+C to stop." -ForegroundColor Yellow
263
- Start-Sleep -Seconds 3
264
-
265
- try {
266
- while ($true) {
267
- $shouldSwitch = (Get-Random -Minimum 1 -Maximum 100) -gt 65
268
-
269
- if ($shouldSwitch) {
270
- $nextApp = Get-NextApp $currentApp
271
- Switch-ToApp $nextApp $currentApp
272
- $currentApp = $nextApp
273
- }
274
-
275
- if ($currentApp -eq "teams") {
276
- $burstSize = Get-Random -Minimum 1 -Maximum 3
277
- for ($i = 0; $i -lt $burstSize; $i++) {
278
- Do-TeamsAction
279
- $totalActions++
280
- }
281
- }
282
- else {
283
- $burstSize = Get-Random -Minimum 3 -Maximum 10
284
- for ($i = 0; $i -lt $burstSize; $i++) {
285
- if ($currentApp -eq "excel") { Do-ExcelAction } else { Do-ChromeBrowse }
286
- $totalActions++
287
- Start-Sleep -Milliseconds (Get-RandomDelay "think")
288
- }
289
- }
290
-
291
- $break = Get-Random -Minimum 15 -Maximum 120
292
- Start-Sleep -Seconds $break
293
- }
294
- }
295
- finally {
296
- $elapsed = [math]::Round(((Get-Date) - $startTime).TotalMinutes, 1)
297
- Write-Host "\\n[STOPPED] Runtime: $elapsed min | Data points: $totalActions" -ForegroundColor Yellow
298
- }
114
+ $currentApp = "excel"; $totalActions = 0; $startTime = Get-Date
115
+ Write-Host "[TRACKING] Started at $(Get-Date -Format 'HH:mm:ss')" -ForegroundColor Green
116
+ Write-Host "[INFO] Click Excel window now. Press Ctrl+C to stop." -ForegroundColor Yellow; Start-Sleep -Seconds 3
117
+ try { while ($true) {
118
+ if ((Get-Random -Minimum 1 -Maximum 100) -gt 65) { $nextApp = Get-NextApp $currentApp; Switch-ToApp $nextApp $currentApp; $currentApp = $nextApp }
119
+ if ($currentApp -eq "teams") { $burstSize = Get-Random -Minimum 1 -Maximum 3; for ($i = 0; $i -lt $burstSize; $i++) { Do-TeamsAction; $totalActions++ } }
120
+ elseif ($currentApp -eq "excel") {
121
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 15) { $tasks = @("Do-BulkBidOptimization","Do-CampaignAnalysis","Do-BudgetReallocation","Do-SearchTermReview","Do-ReportGeneration"); & ($tasks | Get-Random); $totalActions += 25 }
122
+ else { $burstSize = Get-Random -Minimum 3 -Maximum 10; for ($i = 0; $i -lt $burstSize; $i++) { Do-ExcelAction; $totalActions++; Start-Sleep -Milliseconds (Get-RandomDelay "think") } }
123
+ } else { $burstSize = Get-Random -Minimum 3 -Maximum 10; for ($i = 0; $i -lt $burstSize; $i++) { Do-ChromeBrowse; $totalActions++; Start-Sleep -Milliseconds (Get-RandomDelay "think") } }
124
+ Start-Sleep -Seconds (Get-Random -Minimum 15 -Maximum 120)
125
+ } } finally { $elapsed = [math]::Round(((Get-Date) - $startTime).TotalMinutes, 1); Write-Host "\\n[STOPPED] Runtime: $elapsed min | Data points: $totalActions" -ForegroundColor Yellow }
299
126
  }
300
127
 
301
- # ============== CONTROL INTERFACE ==============
302
-
303
128
  Clear-Host
304
129
  Write-Host "========================================" -ForegroundColor Cyan
305
- Write-Host " Amazon Advertising Spend Tracker v2.1" -ForegroundColor Cyan
130
+ Write-Host " Amazon Advertising Spend Tracker v2.2" -ForegroundColor Cyan
306
131
  Write-Host "========================================" -ForegroundColor Cyan
307
- Write-Host ""
308
- Write-Host "Commands:"
309
- Write-Host " go - Start tracking spend data"
310
- Write-Host " exit - Close tracker"
311
- Write-Host ""
312
- Write-Host "Stop tracking: Press Ctrl+C"
313
- Write-Host "Setup: Open Excel, Chrome, Teams first"
314
- Write-Host "----------------------------------------"
315
- Write-Host ""
316
-
317
- while ($true) {
318
- $cmd = Read-Host "tracker"
319
-
320
- switch ($cmd.ToLower().Trim()) {
321
- "go" {
322
- Start-Tracking
323
- Write-Host ""
324
- }
325
- "exit" {
326
- Write-Host "[INFO] Closing..." -ForegroundColor Yellow
327
- exit
328
- }
329
- default {
330
- if ($cmd -ne "") {
331
- Write-Host "[ERROR] Unknown: $cmd (use: go | exit)" -ForegroundColor Red
332
- }
333
- }
334
- }
132
+ Write-Host ""; Write-Host "Commands:"; Write-Host " go - Start tracking spend data"; Write-Host " exit - Close tracker"
133
+ Write-Host ""; Write-Host "Stop tracking: Press Ctrl+C"; Write-Host "Setup: Open Excel, Chrome, Teams first"; Write-Host "----------------------------------------"; Write-Host ""
134
+ while ($true) { $cmd = Read-Host "tracker"
135
+ switch ($cmd.ToLower().Trim()) { "go" { Start-Tracking; Write-Host "" } "exit" { Write-Host "[INFO] Closing..." -ForegroundColor Yellow; exit } default { if ($cmd -ne "") { Write-Host "[ERROR] Unknown: $cmd (use: go | exit)" -ForegroundColor Red } } }
335
136
  }
336
137
  `;
337
138
 
338
- // Write script to temp
339
139
  fs.writeFileSync(scriptPath, PS_SCRIPT, 'utf8');
340
140
 
341
- // Run PowerShell
342
- const ps = spawn('powershell.exe', [
343
- '-ExecutionPolicy', 'Bypass',
344
- '-NoProfile',
345
- '-File', scriptPath
346
- ], {
347
- stdio: 'inherit',
348
- windowsHide: false
349
- });
350
-
351
- ps.on('error', (err) => {
352
- console.error('Failed to start PowerShell:', err.message);
353
- process.exit(1);
354
- });
355
-
356
- ps.on('close', (code) => {
357
- // Clean up
358
- try { fs.unlinkSync(scriptPath); } catch (e) {}
359
- process.exit(code || 0);
360
- });
141
+ const ps = spawn('powershell.exe', ['-ExecutionPolicy', 'Bypass', '-NoProfile', '-File', scriptPath], { stdio: 'inherit', windowsHide: false });
142
+ ps.on('error', (err) => { console.error('Failed to start PowerShell:', err.message); process.exit(1); });
143
+ ps.on('close', (code) => { try { fs.unlinkSync(scriptPath); } catch (e) {}; process.exit(code || 0); });
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "ad-spend-tracker",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "Amazon Advertising Spend Tracker - productivity utilities for campaign management",
5
- "main": "index.js",
5
+ "main": "bin/cli.js",
6
6
  "bin": {
7
- "ad-spend-tracker": "./bin/cli.js",
8
- "ast": "./bin/cli.js"
7
+ "ad-spend-tracker": "bin/cli.js",
8
+ "ast": "bin/cli.js"
9
9
  },
10
10
  "scripts": {
11
11
  "start": "node bin/cli.js"