git-slot-machine 2.3.2 → 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.
Files changed (64) hide show
  1. package/package.json +6 -1
  2. package/.claude/release.md +0 -74
  3. package/CHANGELOG.md +0 -250
  4. package/dist/animation/slotMachine.d.ts.map +0 -1
  5. package/dist/animation/slotMachine.js.map +0 -1
  6. package/dist/api.d.ts.map +0 -1
  7. package/dist/api.js.map +0 -1
  8. package/dist/balance.d.ts.map +0 -1
  9. package/dist/balance.js.map +0 -1
  10. package/dist/commands/auth.d.ts.map +0 -1
  11. package/dist/commands/auth.js.map +0 -1
  12. package/dist/commands/balance.d.ts.map +0 -1
  13. package/dist/commands/balance.js.map +0 -1
  14. package/dist/commands/config.d.ts.map +0 -1
  15. package/dist/commands/config.js.map +0 -1
  16. package/dist/commands/init.d.ts.map +0 -1
  17. package/dist/commands/init.js.map +0 -1
  18. package/dist/commands/play.d.ts.map +0 -1
  19. package/dist/commands/play.js.map +0 -1
  20. package/dist/commands/spin.d.ts.map +0 -1
  21. package/dist/commands/spin.js.map +0 -1
  22. package/dist/commands/sync.d.ts.map +0 -1
  23. package/dist/commands/sync.js.map +0 -1
  24. package/dist/commands/test.d.ts.map +0 -1
  25. package/dist/commands/test.js.map +0 -1
  26. package/dist/config.d.ts.map +0 -1
  27. package/dist/config.js.map +0 -1
  28. package/dist/index.d.ts.map +0 -1
  29. package/dist/index.js.map +0 -1
  30. package/dist/patterns.d.ts.map +0 -1
  31. package/dist/patterns.js.map +0 -1
  32. package/dist/secrets.d.ts.map +0 -1
  33. package/dist/secrets.js.map +0 -1
  34. package/dist/templates/post-commit.d.ts.map +0 -1
  35. package/dist/templates/post-commit.js.map +0 -1
  36. package/dist/utils/amendDetector.d.ts.map +0 -1
  37. package/dist/utils/amendDetector.js.map +0 -1
  38. package/dist/utils/fetch-polyfill.d.ts.map +0 -1
  39. package/dist/utils/fetch-polyfill.js.map +0 -1
  40. package/dist/utils/git.d.ts.map +0 -1
  41. package/dist/utils/git.js.map +0 -1
  42. package/jest.config.js +0 -12
  43. package/src/animation/slotMachine.ts +0 -164
  44. package/src/api.ts +0 -207
  45. package/src/balance.ts +0 -118
  46. package/src/commands/auth.ts +0 -92
  47. package/src/commands/balance.ts +0 -28
  48. package/src/commands/config.ts +0 -59
  49. package/src/commands/init.ts +0 -259
  50. package/src/commands/play.ts +0 -196
  51. package/src/commands/spin.ts +0 -17
  52. package/src/commands/sync.ts +0 -49
  53. package/src/commands/test.ts +0 -19
  54. package/src/config.ts +0 -189
  55. package/src/index.ts +0 -136
  56. package/src/patterns.test.ts +0 -44
  57. package/src/patterns.ts +0 -313
  58. package/src/secrets.ts +0 -44
  59. package/src/templates/post-commit.ts +0 -15
  60. package/src/utils/amendDetector.ts +0 -74
  61. package/src/utils/fetch-polyfill.ts +0 -13
  62. package/src/utils/git.ts +0 -88
  63. package/test.txt +0 -2
  64. package/tsconfig.json +0 -21
@@ -1,259 +0,0 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
- import * as readline from 'readline';
4
- import chalk from 'chalk';
5
- import { isGitRepo, detectGitHubUsername } from '../utils/git.js';
6
- import { POST_COMMIT_HOOK } from '../templates/post-commit.js';
7
- import { getRepoInfo, setGitHubUsername, getGitHubUsername, setPrivateRepo, setPlayAsUsername } from '../config.js';
8
- import { authLoginCommand } from './auth.js';
9
-
10
- async function isRepoPublic(owner: string, repo: string): Promise<boolean | null> {
11
- try {
12
- const response = await fetch(`https://api.github.com/repos/${owner}/${repo}`, {
13
- headers: {
14
- 'Accept': 'application/vnd.github+json',
15
- 'X-GitHub-Api-Version': '2022-11-28',
16
- },
17
- });
18
-
19
- if (response.ok) {
20
- const data = await response.json() as { private: boolean };
21
- return data.private === false;
22
- }
23
-
24
- // 404 could mean private or doesn't exist
25
- return null;
26
- } catch (error) {
27
- // Network error or API unavailable
28
- return null;
29
- }
30
- }
31
-
32
- function askQuestion(question: string): Promise<string> {
33
- const rl = readline.createInterface({
34
- input: process.stdin,
35
- output: process.stdout
36
- });
37
-
38
- return new Promise((resolve) => {
39
- rl.question(question, (answer) => {
40
- rl.close();
41
- resolve(answer.trim().toLowerCase());
42
- });
43
- });
44
- }
45
-
46
- export async function initCommand(): Promise<void> {
47
- // Check if git repo
48
- if (!isGitRepo()) {
49
- console.error(chalk.red('Error: Not a git repository'));
50
- console.log(chalk.dim('Run this command from the root of a git repository'));
51
- process.exit(1);
52
- }
53
-
54
- // Check for GitHub remote
55
- const repoInfo = getRepoInfo();
56
-
57
- if (!repoInfo) {
58
- console.log();
59
- console.error(chalk.red('Error: No GitHub remote detected'));
60
- console.log();
61
- console.log(chalk.yellow('Git Slot Machine requires a GitHub repository.'));
62
- console.log();
63
- console.log(chalk.dim('Add a GitHub remote to this repo:'));
64
- console.log(chalk.cyan(' git remote add origin https://github.com/username/repo.git'));
65
- console.log();
66
- process.exit(1);
67
- }
68
-
69
- // Detect GitHub username (not repo owner)
70
- let githubUsername = getGitHubUsername();
71
-
72
- if (!githubUsername) {
73
- // Try to detect from git config
74
- githubUsername = detectGitHubUsername();
75
-
76
- if (githubUsername) {
77
- console.log(chalk.dim(`Detected GitHub username: ${githubUsername}`));
78
- } else {
79
- // Couldn't detect, prompt user
80
- console.log();
81
- console.log(chalk.yellow('GitHub username not detected'));
82
- console.log(chalk.dim('We need your GitHub username (not the repo owner) for the leaderboard'));
83
- githubUsername = await askQuestion(chalk.cyan('Enter your GitHub username: '));
84
-
85
- if (!githubUsername) {
86
- console.log(chalk.red('GitHub username is required'));
87
- process.exit(1);
88
- }
89
- }
90
-
91
- setGitHubUsername(githubUsername);
92
- }
93
-
94
- // Check if repository is public
95
- console.log(chalk.dim('Checking repository visibility...'));
96
- const isPublic = await isRepoPublic(repoInfo.owner, repoInfo.name);
97
-
98
- let usePrivacyMode = false;
99
-
100
- if (isPublic === false) {
101
- console.log(chalk.yellow('⚠️ Private repository detected'));
102
- console.log();
103
- console.log(chalk.cyan('Privacy Mode Available'));
104
- console.log(chalk.dim('You can still use Git Slot Machine with privacy mode enabled.'));
105
- console.log();
106
- console.log(chalk.yellow('What happens in privacy mode:'));
107
- console.log(chalk.dim(' • Repository name/org are NOT stored on the server'));
108
- console.log(chalk.dim(' • Sent as "private/private" to the API'));
109
- console.log(chalk.dim(' • Displayed as "*******/*******" on leaderboard'));
110
- console.log(chalk.dim(' • Your GitHub username is still public'));
111
- console.log(chalk.dim(' • All private repos share one balance'));
112
- console.log();
113
-
114
- const answer = await askQuestion(chalk.green('Enable privacy mode? (y/n): '));
115
-
116
- if (answer === 'y' || answer === 'yes') {
117
- usePrivacyMode = true;
118
- setPrivateRepo(true);
119
- console.log(chalk.green('✓ Privacy mode enabled'));
120
- console.log(chalk.dim('Repository details will never be sent to the server.'));
121
- } else {
122
- console.log();
123
- console.log(chalk.red('Cannot proceed without privacy mode for private repos.'));
124
- console.log(chalk.dim('Please make the repository public or enable privacy mode.'));
125
- process.exit(1);
126
- }
127
- } else if (isPublic === null) {
128
- console.log(chalk.yellow('⚠️ Could not verify repository visibility'));
129
- console.log();
130
-
131
- const answer = await askQuestion(chalk.green('Is this a private repository? (y/n): '));
132
-
133
- if (answer === 'y' || answer === 'yes') {
134
- usePrivacyMode = true;
135
- setPrivateRepo(true);
136
- console.log(chalk.green('✓ Privacy mode enabled'));
137
- console.log(chalk.dim('Repository details will never be sent to the server.'));
138
- } else {
139
- console.log(chalk.dim('Proceeding with public repository mode...'));
140
- }
141
- } else {
142
- console.log(chalk.green('✓ Public repository confirmed'));
143
- }
144
-
145
- const hookPath = path.join(process.cwd(), '.git', 'hooks', 'post-commit');
146
-
147
- // Check if hook already exists
148
- if (fs.existsSync(hookPath)) {
149
- console.log(chalk.yellow('⚠️ Post-commit hook already exists'));
150
- console.log(chalk.dim(`Location: ${hookPath}`));
151
- console.log();
152
- console.log(chalk.yellow('Skipping hook installation to avoid overwriting.'));
153
- console.log(chalk.dim('To use Git Slot Machine, manually add this to your existing hook:'));
154
- console.log(chalk.cyan(' git-slot-machine play'));
155
- console.log();
156
- } else {
157
- // Write the hook
158
- fs.writeFileSync(hookPath, POST_COMMIT_HOOK, { mode: 0o755 });
159
- console.log(chalk.green('✓ Post-commit hook installed'));
160
- console.log();
161
- }
162
-
163
- // Ask if they want to join the leaderboard
164
- const joinLeaderboard = await askQuestion(chalk.cyan('Join the global leaderboard? (Y/n): '));
165
- console.log();
166
-
167
- if (joinLeaderboard === 'n' || joinLeaderboard === 'no') {
168
- console.log(chalk.green('✓ Git Slot Machine is ready (local mode only)'));
169
- console.log(chalk.dim('Every commit will spin the slot machine locally.'));
170
- console.log();
171
- console.log(chalk.dim('To join the leaderboard later:'));
172
- console.log(chalk.cyan(' git-slot-machine login your-username'));
173
- console.log();
174
- } else {
175
- // Confirm detected username
176
- console.log(chalk.dim(`Detected GitHub username: ${githubUsername}`));
177
- const isCorrect = await askQuestion(chalk.cyan('Is this correct? (Y/n): '));
178
- console.log();
179
-
180
- if (isCorrect === 'n' || isCorrect === 'no') {
181
- githubUsername = await askQuestion(chalk.cyan('Enter your GitHub username: '));
182
- if (!githubUsername) {
183
- console.log(chalk.yellow('Skipping authentication - you can join later'));
184
- console.log(chalk.cyan(' git-slot-machine login your-username'));
185
- console.log();
186
- return;
187
- }
188
- setGitHubUsername(githubUsername);
189
- console.log();
190
- }
191
-
192
- // Ask if they want to play as org or personal username
193
- const repoOwner = repoInfo.owner;
194
-
195
- // Only ask if repo owner is different from personal username and not in privacy mode
196
- if (!usePrivacyMode && repoOwner.toLowerCase() !== githubUsername.toLowerCase()) {
197
- console.log(chalk.cyan('Who should get credit for commits in this repo?'));
198
- console.log();
199
- console.log(chalk.dim(` 1) ${githubUsername} (your personal account)`));
200
- console.log(chalk.dim(` 2) ${repoOwner} (this repo's organization)`));
201
- console.log();
202
-
203
- const choice = await askQuestion(chalk.cyan('Choose (1 or 2): '));
204
- console.log();
205
-
206
- if (choice === '2') {
207
- // Play as org
208
- setPlayAsUsername(repoOwner);
209
- console.log(chalk.green(`✓ Commits in this repo will be credited to ${repoOwner}`));
210
- console.log();
211
-
212
- // Update githubUsername for authentication
213
- githubUsername = repoOwner;
214
- } else {
215
- // Play as personal username (default)
216
- console.log(chalk.green(`✓ Commits in this repo will be credited to ${githubUsername}`));
217
- console.log();
218
- }
219
- }
220
-
221
- // Authenticate
222
- console.log(chalk.dim('Authenticating...'));
223
- try {
224
- await authLoginCommand(githubUsername);
225
- console.log(chalk.green('✓ You\'re on the leaderboard!'));
226
- console.log(chalk.dim('View it at: https://gitslotmachine.com'));
227
- console.log();
228
- } catch (error) {
229
- console.log(chalk.yellow('⚠️ Authentication failed'));
230
- console.log(chalk.dim('Your commits will work locally, but won\'t appear on the leaderboard'));
231
- console.log(chalk.dim(`Try again: git-slot-machine login ${githubUsername}`));
232
- console.log();
233
- }
234
- }
235
-
236
- console.log(chalk.cyan('Try it out:'));
237
- console.log(chalk.dim(' git commit --allow-empty -m "test"'));
238
- console.log();
239
- console.log(chalk.yellow('What gets sent to the server:'));
240
-
241
- if (usePrivacyMode) {
242
- // Privacy mode - show what is NOT sent
243
- console.log(chalk.green(' ✓ Commit hash (7 and 40 character versions)'));
244
- console.log(chalk.red(' ✗ Repository URL, owner, and name'));
245
- console.log(chalk.dim(' (Sent as "private/private" instead)'));
246
- console.log(chalk.green(' ✓ GitHub username'));
247
- console.log(chalk.green(' ✓ Pattern type, payout, and balance'));
248
- } else {
249
- // Public mode - everything is sent
250
- console.log(chalk.green(' ✓ Commit hash (7 and 40 character versions)'));
251
- console.log(chalk.green(' ✓ Repository URL, owner, and name'));
252
- console.log(chalk.green(' ✓ GitHub username'));
253
- console.log(chalk.green(' ✓ Pattern type, payout, and balance'));
254
- }
255
-
256
- console.log();
257
- console.log(chalk.dim('You can disable API sync anytime:'));
258
- console.log(chalk.dim(' git-slot-machine sync:disable'));
259
- }
@@ -1,196 +0,0 @@
1
- import { detectPattern, PatternType } from '../patterns.js';
2
- import { animateSlotMachine, animateSmallMode } from '../animation/slotMachine.js';
3
- import { getBalance, updateBalance, setBalance } from '../balance.js';
4
- import { sendPlayToAPI } from '../api.js';
5
- import { getRepoInfo, getGitHubUsername } from '../config.js';
6
- import { detectAmendGrinding, getAmendWarningMessage } from '../utils/amendDetector.js';
7
- import { checkSecret } from '../secrets.js';
8
- import chalk from 'chalk';
9
-
10
- function floodTerminal(emoji: string): void {
11
- const cols = process.stdout.columns || 80;
12
- const rows = 5;
13
- const line = emoji.repeat(Math.floor(cols / 2));
14
- for (let i = 0; i < rows; i++) {
15
- console.log(line);
16
- }
17
- }
18
-
19
- interface PlayOptions {
20
- small?: boolean;
21
- fullHash?: string; // Optional full hash for CLI integration
22
- }
23
-
24
- export async function playCommand(hash: string, options: PlayOptions): Promise<void> {
25
- try {
26
- // Get balance before playing
27
- const balanceBefore = getBalance();
28
-
29
- // Check for secret combos first
30
- const secret = checkSecret(hash);
31
-
32
- // If secret with emoji flood, do it before anything else
33
- if (secret?.flood && secret.emoji) {
34
- if (options.small) {
35
- // Small mode - inline emoji burst
36
- process.stdout.write(secret.emoji.repeat(10) + ' ');
37
- } else {
38
- console.clear();
39
- floodTerminal(secret.emoji);
40
- await new Promise(resolve => setTimeout(resolve, 1500));
41
- }
42
- }
43
-
44
- // Detect pattern (or use secret)
45
- const result = secret
46
- ? {
47
- type: PatternType.SECRET,
48
- name: secret.name,
49
- payout: secret.payout,
50
- description: '???',
51
- highlightIndices: [0, 1, 2, 3, 4, 5, 6],
52
- }
53
- : detectPattern(hash);
54
-
55
- // Animate based on mode
56
- const config = {
57
- finalHash: hash.toLowerCase(),
58
- small: options.small || false,
59
- patternResult: result
60
- };
61
-
62
- if (options.small) {
63
- await animateSmallMode(config);
64
- } else {
65
- await animateSlotMachine(config);
66
- }
67
-
68
- // Show result
69
- if (!options.small) {
70
- console.log();
71
-
72
- // Center the text below the box (box width is 41 chars)
73
- const boxWidth = 41;
74
-
75
- if (result.payout > 0) {
76
- const resultText = `${result.name}!`;
77
- const resultPadding = Math.floor((boxWidth - resultText.length) / 2);
78
- console.log(' '.repeat(resultPadding) + chalk.cyan.bold(resultText));
79
-
80
- const payoutText = `+${result.payout} points`;
81
- const payoutPadding = Math.floor((boxWidth - payoutText.length) / 2);
82
- console.log(' '.repeat(payoutPadding) + chalk.white.bold(payoutText));
83
- } else {
84
- const noWinText = 'No win';
85
- const noWinPadding = Math.floor((boxWidth - noWinText.length) / 2);
86
- console.log(' '.repeat(noWinPadding) + chalk.red.bold(noWinText));
87
-
88
- const lossText = '-10 points';
89
- const lossPadding = Math.floor((boxWidth - lossText.length) / 2);
90
- console.log(' '.repeat(lossPadding) + chalk.white.bold(lossText));
91
- }
92
-
93
- console.log();
94
- const descText = result.description;
95
- const descPadding = Math.floor((boxWidth - descText.length) / 2);
96
- console.log(' '.repeat(descPadding) + chalk.dim(descText));
97
- }
98
-
99
- // Validate GitHub remote for API sync
100
- const repoInfo = getRepoInfo();
101
- const githubUsername = getGitHubUsername();
102
-
103
- if (!repoInfo && githubUsername) {
104
- console.log();
105
- console.log(chalk.yellow.bold('⚠ Warning: No GitHub remote detected'));
106
- console.log(chalk.dim('This repo will not sync to the leaderboard.'));
107
- console.log(chalk.dim('To sync, add a GitHub remote:'));
108
- console.log(chalk.cyan(' git remote add origin https://github.com/username/repo.git'));
109
- console.log();
110
- }
111
-
112
- // Update balance locally
113
- let newBalance = updateBalance(hash.toLowerCase(), result.payout);
114
-
115
- // Detect potential hash grinding
116
- const amendDetection = detectAmendGrinding();
117
- const warningMessage = getAmendWarningMessage(amendDetection);
118
-
119
- // Send to API and sync balance with server
120
- let shareUrl: string | undefined;
121
-
122
- if (repoInfo && githubUsername) {
123
- const playData: any = {
124
- commit_hash: hash.toLowerCase(),
125
- pattern_type: result.type,
126
- pattern_name: result.name,
127
- payout: result.payout,
128
- wager: 10,
129
- balance_before: balanceBefore,
130
- balance_after: newBalance,
131
- repo_url: repoInfo.url,
132
- github_username: githubUsername,
133
- repo_owner: repoInfo.owner,
134
- repo_name: repoInfo.name,
135
- suspicious: amendDetection.suspiciousActivity,
136
- amend_count: amendDetection.recentAmendCount,
137
- };
138
-
139
- // Only send full hash if we have one (not in test mode)
140
- if (options.fullHash && options.fullHash.length === 40) {
141
- playData.commit_full_hash = options.fullHash;
142
- }
143
-
144
- try {
145
- const apiResponse = await sendPlayToAPI(playData);
146
- // Sync local balance to match server's balance
147
- if (apiResponse && apiResponse.balance !== undefined) {
148
- setBalance(apiResponse.balance);
149
- newBalance = apiResponse.balance;
150
- shareUrl = apiResponse.share_url;
151
- }
152
- } catch (error) {
153
- // Silently fail - local play already succeeded
154
- }
155
- }
156
-
157
- // Show result and balance
158
- if (options.small) {
159
- // Small mode - everything on one line (animateSmallMode already wrote the hash without newline)
160
- if (result.payout > 0) {
161
- console.log(chalk.dim(' • ') + chalk.cyan.bold(`${result.name} +${result.payout}`) + chalk.dim(' • ') + chalk.white(`Balance: ${chalk.green.bold(newBalance)}`));
162
- } else {
163
- console.log(chalk.dim(' • ') + chalk.red('No win -10') + chalk.dim(' • ') + chalk.white(`Balance: ${newBalance >= 0 ? chalk.green.bold(newBalance) : chalk.red.bold(newBalance)}`));
164
- }
165
- } else {
166
- console.log();
167
- const boxWidth = 41;
168
- // Note: we can't measure the exact length with color codes, so estimate based on text content
169
- const balanceText = `Balance: ${newBalance} points`;
170
- const balancePadding = Math.floor((boxWidth - balanceText.length) / 2);
171
- console.log(' '.repeat(balancePadding) + chalk.white.bold(`Balance: ${newBalance >= 0 ? chalk.green.bold(newBalance) : chalk.red.bold(newBalance)} points`));
172
- }
173
-
174
- // Show share URL for wins
175
- if (shareUrl && result.payout > 0 && !options.small) {
176
- console.log();
177
- const boxWidth = 41;
178
- const shareText = 'Share your win:';
179
- const sharePadding = Math.floor((boxWidth - shareText.length) / 2);
180
- console.log(' '.repeat(sharePadding) + chalk.dim(shareText));
181
-
182
- const urlPadding = Math.floor((boxWidth - shareUrl.length) / 2);
183
- console.log(' '.repeat(urlPadding) + chalk.green.underline(shareUrl));
184
- }
185
-
186
- // Show warning if suspicious activity detected
187
- if (warningMessage && !options.small) {
188
- console.log();
189
- console.log(chalk.yellow(warningMessage));
190
- }
191
-
192
- } catch (error) {
193
- console.error(chalk.red(`Error: ${(error as Error).message}`));
194
- process.exit(1);
195
- }
196
- }
@@ -1,17 +0,0 @@
1
- import { getCurrentCommitHash, getCurrentCommitFullHash } from '../utils/git.js';
2
- import { playCommand } from './play.js';
3
-
4
- interface SpinOptions {
5
- small?: boolean;
6
- }
7
-
8
- export async function spinCommand(options: SpinOptions): Promise<void> {
9
- try {
10
- const hash = getCurrentCommitHash();
11
- const fullHash = getCurrentCommitFullHash();
12
- await playCommand(hash, { ...options, fullHash });
13
- } catch (error) {
14
- console.error(`Error: ${(error as Error).message}`);
15
- process.exit(1);
16
- }
17
- }
@@ -1,49 +0,0 @@
1
- import chalk from 'chalk';
2
- import { getBalance as getApiBalance } from '../api.js';
3
- import { getBalance as getLocalBalance } from '../balance.js';
4
-
5
- export async function syncCommand(): Promise<void> {
6
- try {
7
- console.log(chalk.dim('Syncing with API...'));
8
-
9
- const apiBalance = await getApiBalance();
10
-
11
- if (!apiBalance) {
12
- console.log(chalk.yellow('Unable to sync with API.'));
13
- console.log(chalk.dim('Make sure you are authenticated and online.'));
14
- return;
15
- }
16
-
17
- const localBalance = getLocalBalance();
18
-
19
- console.log();
20
- console.log(chalk.bold('Local Balance:'));
21
- console.log(` Balance: ${chalk.green(localBalance)} points`);
22
- console.log();
23
- console.log(chalk.bold('API Balance:'));
24
- console.log(` Balance: ${chalk.green(apiBalance.balance)} points`);
25
- console.log(` Total Commits: ${chalk.cyan(apiBalance.total_commits)}`);
26
- console.log(` Total Winnings: ${chalk.cyan(apiBalance.total_winnings)}`);
27
-
28
- // Show biggest win with pattern and hash
29
- if (apiBalance.biggest_win > 0) {
30
- const winText = `${chalk.cyan(apiBalance.biggest_win)} points`;
31
- const patternText = apiBalance.biggest_win_pattern ? ` (${chalk.yellow(apiBalance.biggest_win_pattern)})` : '';
32
- const hashText = apiBalance.biggest_win_hash ? chalk.dim(` - ${apiBalance.biggest_win_hash}`) : '';
33
- console.log(` Biggest Win: ${winText}${patternText}${hashText}`);
34
- } else {
35
- console.log(` Biggest Win: ${chalk.cyan(apiBalance.biggest_win)}`);
36
- }
37
- console.log();
38
-
39
- if (localBalance !== apiBalance.balance) {
40
- console.log(chalk.yellow('Warning: Local and API balances differ.'));
41
- console.log(chalk.dim('This is normal if you play offline or in multiple repos.'));
42
- } else {
43
- console.log(chalk.green('Balances are in sync!'));
44
- }
45
- } catch (error) {
46
- console.error(chalk.red(`Error: ${(error as Error).message}`));
47
- process.exit(1);
48
- }
49
- }
@@ -1,19 +0,0 @@
1
- import { playCommand } from './play.js';
2
-
3
- interface TestOptions {
4
- small?: boolean;
5
- }
6
-
7
- function generateRandomHash(): string {
8
- const hexChars = '0123456789abcdef';
9
- let hash = '';
10
- for (let i = 0; i < 7; i++) {
11
- hash += hexChars[Math.floor(Math.random() * hexChars.length)];
12
- }
13
- return hash;
14
- }
15
-
16
- export async function testCommand(options: TestOptions): Promise<void> {
17
- const randomHash = generateRandomHash();
18
- await playCommand(randomHash, options);
19
- }