ghbounty 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +124 -0
- package/dist/display.d.ts +42 -0
- package/dist/display.d.ts.map +1 -0
- package/dist/display.js +249 -0
- package/dist/display.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +190 -0
- package/dist/index.js.map +1 -0
- package/dist/notifier.d.ts +21 -0
- package/dist/notifier.d.ts.map +1 -0
- package/dist/notifier.js +75 -0
- package/dist/notifier.js.map +1 -0
- package/dist/parser.d.ts +27 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +138 -0
- package/dist/parser.js.map +1 -0
- package/dist/scanner.d.ts +45 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +204 -0
- package/dist/scanner.js.map +1 -0
- package/dist/store.d.ts +54 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +107 -0
- package/dist/store.js.map +1 -0
- package/package.json +33 -0
- package/src/display.ts +284 -0
- package/src/index.ts +251 -0
- package/src/notifier.ts +96 -0
- package/src/parser.ts +185 -0
- package/src/scanner.ts +275 -0
- package/src/store.ts +139 -0
- package/tsconfig.json +19 -0
package/README.md
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# ghbounty
|
|
2
|
+
|
|
3
|
+
A GitHub bounty aggregator CLI. Find and track open bounties across GitHub repositories.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g ghbounty
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or run directly:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx ghbounty scan
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Setup
|
|
18
|
+
|
|
19
|
+
Set a GitHub token for higher API rate limits (optional but recommended):
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
export GITHUB_TOKEN=ghp_your_token_here
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
### Scan for bounties
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Find all open bounties
|
|
31
|
+
ghbounty scan
|
|
32
|
+
|
|
33
|
+
# Filter by minimum amount and language
|
|
34
|
+
ghbounty scan --min 200 --lang typescript
|
|
35
|
+
|
|
36
|
+
# Deep scan (multiple search strategies, finds more results)
|
|
37
|
+
ghbounty scan --deep
|
|
38
|
+
|
|
39
|
+
# Sort by comments (popular/competitive bounties)
|
|
40
|
+
ghbounty scan --sort comments
|
|
41
|
+
|
|
42
|
+
# Output as JSON for scripting
|
|
43
|
+
ghbounty scan --json
|
|
44
|
+
|
|
45
|
+
# Show detailed info for each bounty
|
|
46
|
+
ghbounty scan --detail
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Watch mode
|
|
50
|
+
|
|
51
|
+
Continuously monitor for new bounties with desktop notifications:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Default: check every 5 minutes
|
|
55
|
+
ghbounty watch
|
|
56
|
+
|
|
57
|
+
# Check every 60 seconds for TypeScript bounties over $500
|
|
58
|
+
ghbounty watch --min 500 --lang typescript --interval 60
|
|
59
|
+
|
|
60
|
+
# Quiet mode: only desktop notifications, no console output
|
|
61
|
+
ghbounty watch --quiet
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Stats
|
|
65
|
+
|
|
66
|
+
Track your bounty hunting activity:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# View stats dashboard
|
|
70
|
+
ghbounty stats
|
|
71
|
+
|
|
72
|
+
# Export stats as JSON
|
|
73
|
+
ghbounty stats --json
|
|
74
|
+
|
|
75
|
+
# Reset all stats
|
|
76
|
+
ghbounty stats --reset
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Open a bounty
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
ghbounty open https://github.com/org/repo/issues/123
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## How it works
|
|
86
|
+
|
|
87
|
+
1. **Scan** — Searches GitHub Issues API for bounty-labeled issues (`bounty`, `reward`, `bug bounty`, etc.)
|
|
88
|
+
2. **Parse** — Extracts dollar amounts from issue titles, labels, and bodies using pattern matching
|
|
89
|
+
3. **Enrich** — Fetches repository metadata (language, etc.) for each result
|
|
90
|
+
4. **Display** — Renders a formatted table sorted by bounty value
|
|
91
|
+
5. **Notify** — Sends macOS desktop notifications for new bounties in watch mode
|
|
92
|
+
6. **Track** — Persists scan history and stats to `~/.ghbounty/`
|
|
93
|
+
|
|
94
|
+
## Filters
|
|
95
|
+
|
|
96
|
+
| Flag | Description | Example |
|
|
97
|
+
|------|-------------|---------|
|
|
98
|
+
| `--min <n>` | Minimum bounty amount (USD) | `--min 200` |
|
|
99
|
+
| `--max <n>` | Maximum bounty amount (USD) | `--max 5000` |
|
|
100
|
+
| `--lang <lang>` | Programming language | `--lang rust` |
|
|
101
|
+
| `--sort <field>` | Sort by: `created`, `updated`, `comments` | `--sort comments` |
|
|
102
|
+
| `--limit <n>` | Max results | `--limit 50` |
|
|
103
|
+
| `--deep` | Multi-strategy scan | `--deep` |
|
|
104
|
+
|
|
105
|
+
## Data storage
|
|
106
|
+
|
|
107
|
+
Stats and seen-bounty tracking are stored in `~/.ghbounty/`:
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
~/.ghbounty/
|
|
111
|
+
stats.json — scan history & aggregated stats
|
|
112
|
+
seen.json — URLs of previously seen bounties (for watch mode)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Dependencies
|
|
116
|
+
|
|
117
|
+
- **commander** — CLI framework
|
|
118
|
+
- Node.js built-in `fetch` (Node 18+)
|
|
119
|
+
|
|
120
|
+
Zero other runtime dependencies.
|
|
121
|
+
|
|
122
|
+
## License
|
|
123
|
+
|
|
124
|
+
MIT
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* display.ts — Table output formatting for bounty data.
|
|
3
|
+
*/
|
|
4
|
+
import type { BountyIssue } from "./scanner.js";
|
|
5
|
+
/**
|
|
6
|
+
* Render a table of bounties.
|
|
7
|
+
*/
|
|
8
|
+
export declare function renderTable(bounties: BountyIssue[]): string;
|
|
9
|
+
/**
|
|
10
|
+
* Render a summary header.
|
|
11
|
+
*/
|
|
12
|
+
export declare function renderSummary(bounties: BountyIssue[], elapsed: number): string;
|
|
13
|
+
/**
|
|
14
|
+
* Render a detailed view of a single bounty.
|
|
15
|
+
*/
|
|
16
|
+
export declare function renderBountyDetail(bounty: BountyIssue): string;
|
|
17
|
+
/**
|
|
18
|
+
* Render stats dashboard.
|
|
19
|
+
*/
|
|
20
|
+
export declare function renderStats(stats: {
|
|
21
|
+
totalScans: number;
|
|
22
|
+
totalBountiesFound: number;
|
|
23
|
+
totalValueTracked: number;
|
|
24
|
+
topLanguages: {
|
|
25
|
+
lang: string;
|
|
26
|
+
count: number;
|
|
27
|
+
}[];
|
|
28
|
+
topRepos: {
|
|
29
|
+
repo: string;
|
|
30
|
+
count: number;
|
|
31
|
+
}[];
|
|
32
|
+
lastScanAt: string | null;
|
|
33
|
+
}): string;
|
|
34
|
+
export declare function getSpinnerFrame(tick: number): string;
|
|
35
|
+
/**
|
|
36
|
+
* Render a "no results" message.
|
|
37
|
+
*/
|
|
38
|
+
export declare function renderNoResults(options?: {
|
|
39
|
+
language?: string;
|
|
40
|
+
minAmount?: number;
|
|
41
|
+
}): string;
|
|
42
|
+
//# sourceMappingURL=display.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../src/display.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAmHhD;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,CA6B3D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,WAAW,EAAE,EACvB,OAAO,EAAE,MAAM,GACd,MAAM,CAqBR;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAgB9D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAChD,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5C,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,GAAG,MAAM,CA8BT;AAOD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CA0B3F"}
|
package/dist/display.js
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* display.ts — Table output formatting for bounty data.
|
|
3
|
+
*/
|
|
4
|
+
const COLUMNS = [
|
|
5
|
+
{
|
|
6
|
+
header: "Amount",
|
|
7
|
+
key: "amountFormatted",
|
|
8
|
+
width: 10,
|
|
9
|
+
align: "right",
|
|
10
|
+
formatter: (v) => colorAmount(v),
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
header: "Repository",
|
|
14
|
+
key: "repo",
|
|
15
|
+
width: 30,
|
|
16
|
+
formatter: (v) => truncate(v, 30),
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
header: "Title",
|
|
20
|
+
key: "title",
|
|
21
|
+
width: 45,
|
|
22
|
+
formatter: (v) => truncate(v, 45),
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
header: "Lang",
|
|
26
|
+
key: "language",
|
|
27
|
+
width: 12,
|
|
28
|
+
formatter: (v) => v || "—",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
header: "Comments",
|
|
32
|
+
key: "comments",
|
|
33
|
+
width: 8,
|
|
34
|
+
align: "right",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
header: "Updated",
|
|
38
|
+
key: "updatedAt",
|
|
39
|
+
width: 12,
|
|
40
|
+
formatter: (v) => formatRelativeDate(v),
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
// ANSI color codes
|
|
44
|
+
const COLORS = {
|
|
45
|
+
reset: "\x1b[0m",
|
|
46
|
+
bold: "\x1b[1m",
|
|
47
|
+
dim: "\x1b[2m",
|
|
48
|
+
green: "\x1b[32m",
|
|
49
|
+
yellow: "\x1b[33m",
|
|
50
|
+
cyan: "\x1b[36m",
|
|
51
|
+
white: "\x1b[37m",
|
|
52
|
+
bgGreen: "\x1b[42m",
|
|
53
|
+
red: "\x1b[31m",
|
|
54
|
+
magenta: "\x1b[35m",
|
|
55
|
+
underline: "\x1b[4m",
|
|
56
|
+
};
|
|
57
|
+
function c(color, text) {
|
|
58
|
+
return `${COLORS[color]}${text}${COLORS.reset}`;
|
|
59
|
+
}
|
|
60
|
+
function colorAmount(amount) {
|
|
61
|
+
if (amount === "TBD")
|
|
62
|
+
return c("dim", amount);
|
|
63
|
+
const num = parseInt(amount.replace(/[$,]/g, ""));
|
|
64
|
+
if (num >= 1000)
|
|
65
|
+
return c("green", c("bold", amount));
|
|
66
|
+
if (num >= 500)
|
|
67
|
+
return c("green", amount);
|
|
68
|
+
if (num >= 100)
|
|
69
|
+
return c("yellow", amount);
|
|
70
|
+
return amount;
|
|
71
|
+
}
|
|
72
|
+
function truncate(str, maxLen) {
|
|
73
|
+
if (!str)
|
|
74
|
+
return "";
|
|
75
|
+
if (str.length <= maxLen)
|
|
76
|
+
return str;
|
|
77
|
+
return str.slice(0, maxLen - 1) + "\u2026";
|
|
78
|
+
}
|
|
79
|
+
function formatRelativeDate(dateStr) {
|
|
80
|
+
const date = new Date(dateStr);
|
|
81
|
+
const now = new Date();
|
|
82
|
+
const diffMs = now.getTime() - date.getTime();
|
|
83
|
+
const diffMins = Math.floor(diffMs / 60000);
|
|
84
|
+
const diffHours = Math.floor(diffMins / 60);
|
|
85
|
+
const diffDays = Math.floor(diffHours / 24);
|
|
86
|
+
if (diffMins < 1)
|
|
87
|
+
return "just now";
|
|
88
|
+
if (diffMins < 60)
|
|
89
|
+
return `${diffMins}m ago`;
|
|
90
|
+
if (diffHours < 24)
|
|
91
|
+
return `${diffHours}h ago`;
|
|
92
|
+
if (diffDays < 7)
|
|
93
|
+
return `${diffDays}d ago`;
|
|
94
|
+
if (diffDays < 30)
|
|
95
|
+
return `${Math.floor(diffDays / 7)}w ago`;
|
|
96
|
+
if (diffDays < 365)
|
|
97
|
+
return `${Math.floor(diffDays / 30)}mo ago`;
|
|
98
|
+
return `${Math.floor(diffDays / 365)}y ago`;
|
|
99
|
+
}
|
|
100
|
+
function pad(str, width, align = "left") {
|
|
101
|
+
// Strip ANSI codes for length calculation
|
|
102
|
+
const stripped = str.replace(/\x1b\[[0-9;]*m/g, "");
|
|
103
|
+
const diff = width - stripped.length;
|
|
104
|
+
if (diff <= 0)
|
|
105
|
+
return str;
|
|
106
|
+
if (align === "right")
|
|
107
|
+
return " ".repeat(diff) + str;
|
|
108
|
+
if (align === "center") {
|
|
109
|
+
const left = Math.floor(diff / 2);
|
|
110
|
+
return " ".repeat(left) + str + " ".repeat(diff - left);
|
|
111
|
+
}
|
|
112
|
+
return str + " ".repeat(diff);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Render a table of bounties.
|
|
116
|
+
*/
|
|
117
|
+
export function renderTable(bounties) {
|
|
118
|
+
const lines = [];
|
|
119
|
+
const sep = " ";
|
|
120
|
+
// Header
|
|
121
|
+
const headerLine = COLUMNS.map((col) => c("bold", pad(col.header, col.width, col.align))).join(sep);
|
|
122
|
+
lines.push(headerLine);
|
|
123
|
+
// Separator
|
|
124
|
+
const separatorLine = COLUMNS.map((col) => "\u2500".repeat(col.width)).join(sep);
|
|
125
|
+
lines.push(c("dim", separatorLine));
|
|
126
|
+
// Rows
|
|
127
|
+
for (const bounty of bounties) {
|
|
128
|
+
const cells = COLUMNS.map((col) => {
|
|
129
|
+
let value = bounty[col.key];
|
|
130
|
+
if (col.formatter) {
|
|
131
|
+
value = col.formatter(value, bounty);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
value = String(value ?? "");
|
|
135
|
+
}
|
|
136
|
+
return pad(value, col.width, col.align);
|
|
137
|
+
});
|
|
138
|
+
lines.push(cells.join(sep));
|
|
139
|
+
}
|
|
140
|
+
return lines.join("\n");
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Render a summary header.
|
|
144
|
+
*/
|
|
145
|
+
export function renderSummary(bounties, elapsed) {
|
|
146
|
+
const totalBounties = bounties.length;
|
|
147
|
+
const withAmount = bounties.filter((b) => b.amount !== null);
|
|
148
|
+
const totalValue = withAmount.reduce((sum, b) => sum + (b.amount || 0), 0);
|
|
149
|
+
const avgValue = withAmount.length > 0 ? Math.round(totalValue / withAmount.length) : 0;
|
|
150
|
+
const topAmount = withAmount.length > 0 ? withAmount[0].amount : 0;
|
|
151
|
+
const lines = [
|
|
152
|
+
"",
|
|
153
|
+
c("bold", c("cyan", " ghbounty") + " — GitHub Bounty Scanner"),
|
|
154
|
+
c("dim", ` Scanned in ${(elapsed / 1000).toFixed(1)}s`),
|
|
155
|
+
"",
|
|
156
|
+
` ${c("bold", String(totalBounties))} bounties found | ` +
|
|
157
|
+
`Total: ${c("green", c("bold", "$" + totalValue.toLocaleString()))} | ` +
|
|
158
|
+
`Avg: ${c("yellow", "$" + avgValue.toLocaleString())} | ` +
|
|
159
|
+
`Top: ${c("green", c("bold", "$" + topAmount.toLocaleString()))}`,
|
|
160
|
+
"",
|
|
161
|
+
];
|
|
162
|
+
return lines.join("\n");
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Render a detailed view of a single bounty.
|
|
166
|
+
*/
|
|
167
|
+
export function renderBountyDetail(bounty) {
|
|
168
|
+
const lines = [
|
|
169
|
+
"",
|
|
170
|
+
c("bold", ` ${bounty.title}`),
|
|
171
|
+
` ${c("dim", bounty.repo)} #${bounty.id}`,
|
|
172
|
+
"",
|
|
173
|
+
` Amount: ${colorAmount(bounty.amountFormatted)}`,
|
|
174
|
+
` Author: ${bounty.author}`,
|
|
175
|
+
` Language: ${bounty.language || "Unknown"}`,
|
|
176
|
+
` Labels: ${bounty.labels.join(", ") || "none"}`,
|
|
177
|
+
` Comments: ${bounty.comments}`,
|
|
178
|
+
` Updated: ${formatRelativeDate(bounty.updatedAt)}`,
|
|
179
|
+
` URL: ${c("underline", c("cyan", bounty.url))}`,
|
|
180
|
+
"",
|
|
181
|
+
];
|
|
182
|
+
return lines.join("\n");
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Render stats dashboard.
|
|
186
|
+
*/
|
|
187
|
+
export function renderStats(stats) {
|
|
188
|
+
const lines = [
|
|
189
|
+
"",
|
|
190
|
+
c("bold", c("cyan", " ghbounty") + " — Your Bounty Hunting Stats"),
|
|
191
|
+
"",
|
|
192
|
+
` Total scans: ${c("bold", String(stats.totalScans))}`,
|
|
193
|
+
` Bounties found: ${c("bold", String(stats.totalBountiesFound))}`,
|
|
194
|
+
` Value tracked: ${c("green", c("bold", "$" + stats.totalValueTracked.toLocaleString()))}`,
|
|
195
|
+
` Last scan: ${stats.lastScanAt ? formatRelativeDate(stats.lastScanAt) : "never"}`,
|
|
196
|
+
"",
|
|
197
|
+
];
|
|
198
|
+
if (stats.topLanguages.length > 0) {
|
|
199
|
+
lines.push(c("bold", " Top Languages:"));
|
|
200
|
+
for (const { lang, count } of stats.topLanguages.slice(0, 5)) {
|
|
201
|
+
const bar = "\u2588".repeat(Math.min(count, 20));
|
|
202
|
+
lines.push(` ${pad(lang, 15)} ${c("cyan", bar)} ${count}`);
|
|
203
|
+
}
|
|
204
|
+
lines.push("");
|
|
205
|
+
}
|
|
206
|
+
if (stats.topRepos.length > 0) {
|
|
207
|
+
lines.push(c("bold", " Top Repositories:"));
|
|
208
|
+
for (const { repo, count } of stats.topRepos.slice(0, 5)) {
|
|
209
|
+
lines.push(` ${pad(truncate(repo, 35), 37)} ${c("yellow", String(count))} bounties`);
|
|
210
|
+
}
|
|
211
|
+
lines.push("");
|
|
212
|
+
}
|
|
213
|
+
return lines.join("\n");
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Render a spinner frame for loading states.
|
|
217
|
+
*/
|
|
218
|
+
const SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
219
|
+
export function getSpinnerFrame(tick) {
|
|
220
|
+
return SPINNER_FRAMES[tick % SPINNER_FRAMES.length];
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Render a "no results" message.
|
|
224
|
+
*/
|
|
225
|
+
export function renderNoResults(options) {
|
|
226
|
+
const lines = [
|
|
227
|
+
"",
|
|
228
|
+
c("yellow", " No bounties found matching your criteria."),
|
|
229
|
+
"",
|
|
230
|
+
];
|
|
231
|
+
if (options?.language || options?.minAmount) {
|
|
232
|
+
lines.push(c("dim", " Active filters:"));
|
|
233
|
+
if (options.language) {
|
|
234
|
+
lines.push(c("dim", ` Language: ${options.language}`));
|
|
235
|
+
}
|
|
236
|
+
if (options.minAmount) {
|
|
237
|
+
lines.push(c("dim", ` Min amount: $${options.minAmount}`));
|
|
238
|
+
}
|
|
239
|
+
lines.push("");
|
|
240
|
+
lines.push(c("dim", " Try broadening your search criteria."));
|
|
241
|
+
lines.push("");
|
|
242
|
+
}
|
|
243
|
+
lines.push(c("dim", " Tips:"));
|
|
244
|
+
lines.push(c("dim", " - Set GITHUB_TOKEN for higher API rate limits"));
|
|
245
|
+
lines.push(c("dim", " - Try: ghbounty scan --deep for broader search"));
|
|
246
|
+
lines.push("");
|
|
247
|
+
return lines.join("\n");
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=display.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display.js","sourceRoot":"","sources":["../src/display.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;GAIG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ghbounty — GitHub Bounty Aggregator CLI
|
|
4
|
+
*
|
|
5
|
+
* Find and track bounties across GitHub repositories.
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from "commander";
|
|
8
|
+
import { scanBounties, deepScan } from "./scanner.js";
|
|
9
|
+
import { notifyBatchBounties } from "./notifier.js";
|
|
10
|
+
import { renderTable, renderSummary, renderNoResults, renderStats, renderBountyDetail, getSpinnerFrame, } from "./display.js";
|
|
11
|
+
import { recordScan, getFormattedStats, loadSeenBounties, saveSeenBounties, resetStats, } from "./store.js";
|
|
12
|
+
const program = new Command();
|
|
13
|
+
program
|
|
14
|
+
.name("ghbounty")
|
|
15
|
+
.description("GitHub bounty aggregator — find and track bounties across GitHub")
|
|
16
|
+
.version("1.0.0");
|
|
17
|
+
// ─── scan command ───────────────────────────────────────────────────────────
|
|
18
|
+
program
|
|
19
|
+
.command("scan")
|
|
20
|
+
.description("Scan GitHub for open bounty issues")
|
|
21
|
+
.option("--min <amount>", "Minimum bounty amount in USD", parseInt)
|
|
22
|
+
.option("--max <amount>", "Maximum bounty amount in USD", parseInt)
|
|
23
|
+
.option("--lang <language>", "Filter by programming language")
|
|
24
|
+
.option("--sort <field>", "Sort by: created, updated, comments", "updated")
|
|
25
|
+
.option("--limit <n>", "Max results to show", parseInt)
|
|
26
|
+
.option("--deep", "Deep scan with multiple search strategies")
|
|
27
|
+
.option("--json", "Output as JSON")
|
|
28
|
+
.option("--detail", "Show detailed view of each bounty")
|
|
29
|
+
.action(async (opts) => {
|
|
30
|
+
const startTime = Date.now();
|
|
31
|
+
// Show scanning indicator
|
|
32
|
+
process.stdout.write("\n Scanning GitHub for bounties");
|
|
33
|
+
const spinnerInterval = setInterval(() => {
|
|
34
|
+
const frame = getSpinnerFrame(Math.floor(Date.now() / 100));
|
|
35
|
+
process.stdout.write(`\r ${frame} Scanning GitHub for bounties...`);
|
|
36
|
+
}, 100);
|
|
37
|
+
try {
|
|
38
|
+
const scanOpts = {
|
|
39
|
+
minAmount: opts.min,
|
|
40
|
+
maxAmount: opts.max,
|
|
41
|
+
language: opts.lang,
|
|
42
|
+
sort: opts.sort,
|
|
43
|
+
limit: opts.limit || 30,
|
|
44
|
+
};
|
|
45
|
+
let bounties;
|
|
46
|
+
if (opts.deep) {
|
|
47
|
+
bounties = await deepScan(scanOpts);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
bounties = await scanBounties(scanOpts);
|
|
51
|
+
}
|
|
52
|
+
clearInterval(spinnerInterval);
|
|
53
|
+
process.stdout.write("\r" + " ".repeat(60) + "\r"); // Clear spinner line
|
|
54
|
+
const elapsed = Date.now() - startTime;
|
|
55
|
+
if (bounties.length === 0) {
|
|
56
|
+
console.log(renderNoResults({ language: opts.lang, minAmount: opts.min }));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// Record stats
|
|
60
|
+
const totalValue = bounties
|
|
61
|
+
.filter((b) => b.amount !== null)
|
|
62
|
+
.reduce((sum, b) => sum + (b.amount || 0), 0);
|
|
63
|
+
recordScan(bounties.length, totalValue, bounties.map((b) => b.language), bounties.map((b) => b.repo));
|
|
64
|
+
if (opts.json) {
|
|
65
|
+
console.log(JSON.stringify(bounties, null, 2));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
console.log(renderSummary(bounties, elapsed));
|
|
69
|
+
if (opts.detail) {
|
|
70
|
+
for (const bounty of bounties) {
|
|
71
|
+
console.log(renderBountyDetail(bounty));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
console.log(renderTable(bounties));
|
|
76
|
+
}
|
|
77
|
+
console.log(`\n \x1b[2mTip: Use --detail for full info, or --json for machine-readable output\x1b[0m\n`);
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
clearInterval(spinnerInterval);
|
|
81
|
+
process.stdout.write("\r" + " ".repeat(60) + "\r");
|
|
82
|
+
console.error(`\n \x1b[31mError:\x1b[0m ${err.message}\n`);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
// ─── watch command ──────────────────────────────────────────────────────────
|
|
87
|
+
program
|
|
88
|
+
.command("watch")
|
|
89
|
+
.description("Continuously monitor for new bounties with desktop notifications")
|
|
90
|
+
.option("--min <amount>", "Minimum bounty amount in USD", parseInt)
|
|
91
|
+
.option("--lang <language>", "Filter by programming language")
|
|
92
|
+
.option("--interval <seconds>", "Check interval in seconds (default: 300)", parseInt)
|
|
93
|
+
.option("--quiet", "Only notify, don't print to console")
|
|
94
|
+
.action(async (opts) => {
|
|
95
|
+
const intervalSec = opts.interval || 300;
|
|
96
|
+
const seen = loadSeenBounties();
|
|
97
|
+
console.log(`\n \x1b[1m\x1b[36mghbounty\x1b[0m — Watch Mode`);
|
|
98
|
+
console.log(` Checking every ${intervalSec}s for new bounties...`);
|
|
99
|
+
if (opts.lang)
|
|
100
|
+
console.log(` Language filter: ${opts.lang}`);
|
|
101
|
+
if (opts.min)
|
|
102
|
+
console.log(` Min amount: $${opts.min}`);
|
|
103
|
+
console.log(` Press Ctrl+C to stop.\n`);
|
|
104
|
+
const check = async () => {
|
|
105
|
+
const timestamp = new Date().toLocaleTimeString();
|
|
106
|
+
try {
|
|
107
|
+
const bounties = await scanBounties({
|
|
108
|
+
minAmount: opts.min,
|
|
109
|
+
language: opts.lang,
|
|
110
|
+
limit: 50,
|
|
111
|
+
});
|
|
112
|
+
const newBounties = bounties.filter((b) => !seen.has(b.url));
|
|
113
|
+
if (newBounties.length > 0) {
|
|
114
|
+
// Mark as seen
|
|
115
|
+
for (const b of newBounties) {
|
|
116
|
+
seen.add(b.url);
|
|
117
|
+
}
|
|
118
|
+
saveSeenBounties(seen);
|
|
119
|
+
// Record stats
|
|
120
|
+
const totalValue = newBounties
|
|
121
|
+
.filter((b) => b.amount !== null)
|
|
122
|
+
.reduce((sum, b) => sum + (b.amount || 0), 0);
|
|
123
|
+
recordScan(newBounties.length, totalValue, newBounties.map((b) => b.language), newBounties.map((b) => b.repo));
|
|
124
|
+
// Notify
|
|
125
|
+
await notifyBatchBounties(newBounties);
|
|
126
|
+
if (!opts.quiet) {
|
|
127
|
+
console.log(` \x1b[32m[${timestamp}]\x1b[0m ${newBounties.length} new bounties found!`);
|
|
128
|
+
console.log(renderTable(newBounties));
|
|
129
|
+
console.log();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
if (!opts.quiet) {
|
|
134
|
+
process.stdout.write(`\r \x1b[2m[${timestamp}] No new bounties. Next check in ${intervalSec}s...\x1b[0m`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
console.error(`\n \x1b[31m[${timestamp}] Error: ${err.message}\x1b[0m`);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
// Initial check
|
|
143
|
+
await check();
|
|
144
|
+
// Periodic checks
|
|
145
|
+
setInterval(check, intervalSec * 1000);
|
|
146
|
+
});
|
|
147
|
+
// ─── stats command ──────────────────────────────────────────────────────────
|
|
148
|
+
program
|
|
149
|
+
.command("stats")
|
|
150
|
+
.description("Show your bounty hunting statistics")
|
|
151
|
+
.option("--reset", "Reset all stats")
|
|
152
|
+
.option("--json", "Output as JSON")
|
|
153
|
+
.action((opts) => {
|
|
154
|
+
if (opts.reset) {
|
|
155
|
+
resetStats();
|
|
156
|
+
console.log("\n \x1b[32mStats reset successfully.\x1b[0m\n");
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const stats = getFormattedStats();
|
|
160
|
+
if (opts.json) {
|
|
161
|
+
console.log(JSON.stringify(stats, null, 2));
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
console.log(renderStats(stats));
|
|
165
|
+
});
|
|
166
|
+
// ─── open command (bonus utility) ───────────────────────────────────────────
|
|
167
|
+
program
|
|
168
|
+
.command("open <url>")
|
|
169
|
+
.description("Open a bounty URL in your browser")
|
|
170
|
+
.action((url) => {
|
|
171
|
+
import("node:child_process").then(({ execSync }) => {
|
|
172
|
+
try {
|
|
173
|
+
if (process.platform === "darwin") {
|
|
174
|
+
execSync(`open "${url}"`);
|
|
175
|
+
}
|
|
176
|
+
else if (process.platform === "linux") {
|
|
177
|
+
execSync(`xdg-open "${url}"`);
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
execSync(`start "${url}"`);
|
|
181
|
+
}
|
|
182
|
+
console.log(`\n Opened: ${url}\n`);
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
console.log(`\n Could not open browser. URL: ${url}\n`);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
program.parse();
|
|
190
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* notifier.ts — macOS desktop notifications via osascript.
|
|
3
|
+
*/
|
|
4
|
+
import type { BountyIssue } from "./scanner.js";
|
|
5
|
+
/**
|
|
6
|
+
* Send a macOS desktop notification.
|
|
7
|
+
*/
|
|
8
|
+
export declare function notify(title: string, message: string, subtitle?: string): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Notify about a new bounty found.
|
|
11
|
+
*/
|
|
12
|
+
export declare function notifyNewBounty(bounty: BountyIssue): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Notify about multiple new bounties.
|
|
15
|
+
*/
|
|
16
|
+
export declare function notifyBatchBounties(bounties: BountyIssue[]): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Notify about a scan completion.
|
|
19
|
+
*/
|
|
20
|
+
export declare function notifyScanComplete(count: number, totalValue: number): Promise<void>;
|
|
21
|
+
//# sourceMappingURL=notifier.d.ts.map
|