@brozarti/spincome 0.1.5 → 0.1.6
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/dist/display.js +9 -4
- package/dist/hook.js +8 -2
- package/package.json +1 -1
- package/src/display.ts +26 -21
- package/src/hook.ts +10 -4
package/dist/display.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.renderEarnings = renderEarnings;
|
|
3
4
|
exports.renderAd = renderAd;
|
|
4
5
|
const R = "\x1b[0m";
|
|
5
6
|
const B = "\x1b[1m";
|
|
@@ -7,7 +8,6 @@ const DIM = "\x1b[2m";
|
|
|
7
8
|
const GREEN = "\x1b[32m";
|
|
8
9
|
const BRIGHT_GREEN = "\x1b[92m";
|
|
9
10
|
const CYAN = "\x1b[36m";
|
|
10
|
-
const YELLOW = "\x1b[33m";
|
|
11
11
|
const WHITE = "\x1b[97m";
|
|
12
12
|
const BG = "\x1b[48;5;234m";
|
|
13
13
|
const W = 62;
|
|
@@ -21,8 +21,13 @@ function box(content, visibleLen) {
|
|
|
21
21
|
function ruler() {
|
|
22
22
|
return `${DIM}${"─".repeat(W)}${R}`;
|
|
23
23
|
}
|
|
24
|
+
// Compact earnings ticker -- shown every tool call
|
|
25
|
+
function renderEarnings(sessionCents) {
|
|
26
|
+
const sessionDollars = (sessionCents / 100000).toFixed(4);
|
|
27
|
+
return `\n ${B}${GREEN}$${R} ${B}spincome${R} ${DIM}→${R} ${BRIGHT_GREEN}$${sessionDollars}${R} ${DIM}this session${R}\n`;
|
|
28
|
+
}
|
|
29
|
+
// Full ad box -- shown every Nth call
|
|
24
30
|
function renderAd(ad, earnedCents, sessionCents, context) {
|
|
25
|
-
// earnedCents and sessionCents are stored in milli-cents (1 unit = $0.00001)
|
|
26
31
|
const earnedDollars = (earnedCents / 100000).toFixed(4);
|
|
27
32
|
const sessionDollars = (sessionCents / 100000).toFixed(4);
|
|
28
33
|
const contextTag = context?.fileExt
|
|
@@ -34,13 +39,13 @@ function renderAd(ad, earnedCents, sessionCents, context) {
|
|
|
34
39
|
const headlineLine = `${B}${WHITE}${ad.headline}${R}`;
|
|
35
40
|
const bodyLine = `${DIM}${ad.body}${R}`;
|
|
36
41
|
const ctaLine = `${CYAN}${ad.cta}${R} ${DIM}${ad.clickUrl}${R}`;
|
|
37
|
-
const earnLine = `${BRIGHT_GREEN}+$${earnedDollars} earned${R} ${DIM}session
|
|
42
|
+
const earnLine = `${BRIGHT_GREEN}+$${earnedDollars} earned${R} ${DIM}session: ${GREEN}$${sessionDollars}${R}`;
|
|
38
43
|
const footerLine = `${DIM}spincome · /disable to opt out${R}`;
|
|
39
44
|
const sponsorLen = `Sponsored · ${ad.advertiser}${contextTag}`.length;
|
|
40
45
|
const headlineLen = ad.headline.length;
|
|
41
46
|
const bodyLen = ad.body.length;
|
|
42
47
|
const ctaLen = `${ad.cta} ${ad.clickUrl}`.length;
|
|
43
|
-
const earnLen = `+$${earnedDollars} earned session
|
|
48
|
+
const earnLen = `+$${earnedDollars} earned session: $${sessionDollars}`.length;
|
|
44
49
|
const footerLen = `spincome · /disable to opt out`.length;
|
|
45
50
|
return [
|
|
46
51
|
"",
|
package/dist/hook.js
CHANGED
|
@@ -10,6 +10,7 @@ const config_js_1 = require("./config.js");
|
|
|
10
10
|
const session_js_1 = require("./session.js");
|
|
11
11
|
const animate_js_1 = require("./animate.js");
|
|
12
12
|
const path_1 = __importDefault(require("path"));
|
|
13
|
+
const AD_EVERY_N = 10; // show full ad every 10th impression
|
|
13
14
|
function extractContext(payload) {
|
|
14
15
|
const toolName = payload.tool_name ?? undefined;
|
|
15
16
|
const filePath = payload.tool_input?.file_path ??
|
|
@@ -35,12 +36,17 @@ async function main() {
|
|
|
35
36
|
// empty or malformed stdin
|
|
36
37
|
}
|
|
37
38
|
const context = extractContext(payload);
|
|
38
|
-
// Fetch ad and record impression concurrently, animate while waiting
|
|
39
39
|
const ad = await (0, ad_js_1.fetchAd)(context);
|
|
40
40
|
if (!ad)
|
|
41
41
|
process.exit(0);
|
|
42
42
|
const earnedCents = await (0, animate_js_1.animateWhileLoading)((0, ad_js_1.recordImpression)(ad.id, config.developerKey, ad.actualCpmCents, context));
|
|
43
43
|
const session = (0, session_js_1.addToSession)(earnedCents);
|
|
44
|
-
|
|
44
|
+
// Every 10th impression show the full ad, otherwise just the earnings ticker
|
|
45
|
+
if (session.impressions % AD_EVERY_N === 0) {
|
|
46
|
+
process.stdout.write((0, display_js_1.renderAd)(ad, earnedCents, session.totalCents, context));
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
process.stdout.write((0, display_js_1.renderEarnings)(session.totalCents));
|
|
50
|
+
}
|
|
45
51
|
}
|
|
46
52
|
main().catch(() => process.exit(0));
|
package/package.json
CHANGED
package/src/display.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import type { Ad } from "./ad.js";
|
|
2
2
|
|
|
3
|
-
const R
|
|
4
|
-
const B
|
|
5
|
-
const DIM
|
|
6
|
-
const GREEN
|
|
3
|
+
const R = "\x1b[0m";
|
|
4
|
+
const B = "\x1b[1m";
|
|
5
|
+
const DIM = "\x1b[2m";
|
|
6
|
+
const GREEN = "\x1b[32m";
|
|
7
7
|
const BRIGHT_GREEN = "\x1b[92m";
|
|
8
|
-
const CYAN
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const BG = "\x1b[48;5;234m";
|
|
8
|
+
const CYAN = "\x1b[36m";
|
|
9
|
+
const WHITE = "\x1b[97m";
|
|
10
|
+
const BG = "\x1b[48;5;234m";
|
|
12
11
|
|
|
13
12
|
const W = 62;
|
|
14
13
|
|
|
@@ -25,8 +24,14 @@ function ruler(): string {
|
|
|
25
24
|
return `${DIM}${"─".repeat(W)}${R}`;
|
|
26
25
|
}
|
|
27
26
|
|
|
27
|
+
// Compact earnings ticker -- shown every tool call
|
|
28
|
+
export function renderEarnings(sessionCents: number): string {
|
|
29
|
+
const sessionDollars = (sessionCents / 100000).toFixed(4);
|
|
30
|
+
return `\n ${B}${GREEN}$${R} ${B}spincome${R} ${DIM}→${R} ${BRIGHT_GREEN}$${sessionDollars}${R} ${DIM}this session${R}\n`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Full ad box -- shown every Nth call
|
|
28
34
|
export function renderAd(ad: Ad, earnedCents: number, sessionCents: number, context?: { toolName?: string; fileExt?: string }): string {
|
|
29
|
-
// earnedCents and sessionCents are stored in milli-cents (1 unit = $0.00001)
|
|
30
35
|
const earnedDollars = (earnedCents / 100000).toFixed(4);
|
|
31
36
|
const sessionDollars = (sessionCents / 100000).toFixed(4);
|
|
32
37
|
|
|
@@ -36,19 +41,19 @@ export function renderAd(ad: Ad, earnedCents: number, sessionCents: number, cont
|
|
|
36
41
|
? ` · ${context.toolName}`
|
|
37
42
|
: "";
|
|
38
43
|
|
|
39
|
-
const sponsorLine
|
|
40
|
-
const headlineLine
|
|
41
|
-
const bodyLine
|
|
42
|
-
const ctaLine
|
|
43
|
-
const earnLine
|
|
44
|
-
const footerLine
|
|
44
|
+
const sponsorLine = `${DIM}Sponsored · ${ad.advertiser}${contextTag}${R}`;
|
|
45
|
+
const headlineLine = `${B}${WHITE}${ad.headline}${R}`;
|
|
46
|
+
const bodyLine = `${DIM}${ad.body}${R}`;
|
|
47
|
+
const ctaLine = `${CYAN}${ad.cta}${R} ${DIM}${ad.clickUrl}${R}`;
|
|
48
|
+
const earnLine = `${BRIGHT_GREEN}+$${earnedDollars} earned${R} ${DIM}session: ${GREEN}$${sessionDollars}${R}`;
|
|
49
|
+
const footerLine = `${DIM}spincome · /disable to opt out${R}`;
|
|
45
50
|
|
|
46
|
-
const sponsorLen
|
|
47
|
-
const headlineLen
|
|
48
|
-
const bodyLen
|
|
49
|
-
const ctaLen
|
|
50
|
-
const earnLen
|
|
51
|
-
const footerLen
|
|
51
|
+
const sponsorLen = `Sponsored · ${ad.advertiser}${contextTag}`.length;
|
|
52
|
+
const headlineLen = ad.headline.length;
|
|
53
|
+
const bodyLen = ad.body.length;
|
|
54
|
+
const ctaLen = `${ad.cta} ${ad.clickUrl}`.length;
|
|
55
|
+
const earnLen = `+$${earnedDollars} earned session: $${sessionDollars}`.length;
|
|
56
|
+
const footerLen = `spincome · /disable to opt out`.length;
|
|
52
57
|
|
|
53
58
|
return [
|
|
54
59
|
"",
|
package/src/hook.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { fetchAd, recordImpression, type AdContext } from "./ad.js";
|
|
4
|
-
import { renderAd } from "./display.js";
|
|
4
|
+
import { renderEarnings, renderAd } from "./display.js";
|
|
5
5
|
import { readConfig } from "./config.js";
|
|
6
6
|
import { addToSession } from "./session.js";
|
|
7
7
|
import { animateWhileLoading } from "./animate.js";
|
|
8
8
|
import path from "path";
|
|
9
9
|
|
|
10
|
+
const AD_EVERY_N = 10; // show full ad every 10th impression
|
|
11
|
+
|
|
10
12
|
interface HookPayload {
|
|
11
13
|
tool_name?: string;
|
|
12
14
|
tool_input?: {
|
|
@@ -43,8 +45,6 @@ async function main() {
|
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
const context = extractContext(payload);
|
|
46
|
-
|
|
47
|
-
// Fetch ad and record impression concurrently, animate while waiting
|
|
48
48
|
const ad = await fetchAd(context);
|
|
49
49
|
if (!ad) process.exit(0);
|
|
50
50
|
|
|
@@ -53,7 +53,13 @@ async function main() {
|
|
|
53
53
|
);
|
|
54
54
|
|
|
55
55
|
const session = addToSession(earnedCents);
|
|
56
|
-
|
|
56
|
+
|
|
57
|
+
// Every 10th impression show the full ad, otherwise just the earnings ticker
|
|
58
|
+
if (session.impressions % AD_EVERY_N === 0) {
|
|
59
|
+
process.stdout.write(renderAd(ad, earnedCents, session.totalCents, context));
|
|
60
|
+
} else {
|
|
61
|
+
process.stdout.write(renderEarnings(session.totalCents));
|
|
62
|
+
}
|
|
57
63
|
}
|
|
58
64
|
|
|
59
65
|
main().catch(() => process.exit(0));
|