ad-spend-tracker 2.1.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/bin/cli.js +99 -316
- package/package.json +1 -1
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
|
-
//
|
|
15
|
+
// v2.2.0 - Added bulk optimization tasks
|
|
18
16
|
const PS_SCRIPT = `
|
|
19
|
-
# Amazon Advertising Spend Tracker v2.
|
|
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
|
-
$
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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
|
-
|
|
104
|
-
|
|
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
|
-
|
|
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
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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.
|
|
130
|
+
Write-Host " Amazon Advertising Spend Tracker v2.2" -ForegroundColor Cyan
|
|
306
131
|
Write-Host "========================================" -ForegroundColor Cyan
|
|
307
|
-
Write-Host ""
|
|
308
|
-
Write-Host "
|
|
309
|
-
|
|
310
|
-
Write-Host "
|
|
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
|
-
|
|
342
|
-
|
|
343
|
-
|
|
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); });
|