libroadcast-cli 2.3.0 → 2.4.1
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 +8 -0
- package/dist/cmd/delay.js +19 -26
- package/dist/cmd/fixSchedule.js +22 -29
- package/dist/cmd/login.js +30 -37
- package/dist/cmd/period.js +17 -24
- package/dist/cmd/push.js +26 -33
- package/dist/cmd/pushFilterID.js +134 -0
- package/dist/cmd/score.js +19 -26
- package/dist/cmd/setLichessGames.js +13 -20
- package/dist/cmd/setPGN.js +19 -26
- package/dist/cmd/setPGNMulti.js +23 -30
- package/dist/cmd/startsPrevious.js +14 -21
- package/dist/index.js +23 -28
- package/dist/utils/colors.js +12 -14
- package/dist/utils/commandHandler.js +56 -63
- package/dist/utils/credentials.js +16 -23
- package/dist/utils/getInfoBroadcast.js +6 -14
- package/dist/utils/help.js +108 -104
- package/package.json +4 -3
|
@@ -1,41 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const score_1 = require("../cmd/score");
|
|
20
|
-
const push_1 = require("../cmd/push");
|
|
21
|
-
const login_1 = require("../cmd/login");
|
|
22
|
-
const credentials_1 = require("./credentials");
|
|
1
|
+
import { argv } from "node:process";
|
|
2
|
+
import createClient from "openapi-fetch";
|
|
3
|
+
import cl from "./colors.js";
|
|
4
|
+
const __dirname = import.meta.dirname;
|
|
5
|
+
import { readFileSync } from "node:fs";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import { delayCommand } from "../cmd/delay.js";
|
|
8
|
+
import { setPGNCommand } from "../cmd/setPGN.js";
|
|
9
|
+
import { setPGNMultiCommand } from "../cmd/setPGNMulti.js";
|
|
10
|
+
import { setLichessGamesCommand } from "../cmd/setLichessGames.js";
|
|
11
|
+
import { fixScheduleCommand } from "../cmd/fixSchedule.js";
|
|
12
|
+
import { startsPreviousCommand } from "../cmd/startsPrevious.js";
|
|
13
|
+
import { periodCommand } from "../cmd/period.js";
|
|
14
|
+
import { scoreCommand } from "../cmd/score.js";
|
|
15
|
+
import { pushCommand } from "../cmd/push.js";
|
|
16
|
+
import { pushFilterIDCommand } from "../cmd/pushFilterID.js";
|
|
17
|
+
import { loginCommand } from "../cmd/login.js";
|
|
18
|
+
import { getStoredCredentials } from "./credentials.js";
|
|
23
19
|
const getToken = () => {
|
|
24
|
-
const stored =
|
|
20
|
+
const stored = getStoredCredentials();
|
|
25
21
|
return stored?.lichessToken;
|
|
26
22
|
};
|
|
27
23
|
const getDomain = () => {
|
|
28
|
-
const stored =
|
|
24
|
+
const stored = getStoredCredentials();
|
|
29
25
|
if (stored?.lichessDomain) {
|
|
30
26
|
return stored.lichessDomain.replace(/\/$/, "") + "/";
|
|
31
27
|
}
|
|
32
28
|
return "https://lichess.org/";
|
|
33
29
|
};
|
|
34
|
-
|
|
30
|
+
export const LICHESS_TOKEN = getToken();
|
|
35
31
|
const LICHESS_DOMAIN = getDomain();
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
var Command;
|
|
32
|
+
export const args = argv.slice(2);
|
|
33
|
+
export const packageJson = JSON.parse(readFileSync(join(__dirname, "../../package.json"), "utf-8"));
|
|
34
|
+
export var Command;
|
|
39
35
|
(function (Command) {
|
|
40
36
|
Command["Login"] = "login";
|
|
41
37
|
Command["Delay"] = "delay";
|
|
@@ -47,50 +43,49 @@ var Command;
|
|
|
47
43
|
Command["Period"] = "period";
|
|
48
44
|
Command["Score"] = "score";
|
|
49
45
|
Command["Push"] = "push";
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
[Command.
|
|
54
|
-
[Command.
|
|
55
|
-
[Command.
|
|
56
|
-
[Command.
|
|
57
|
-
[Command.
|
|
58
|
-
[Command.
|
|
59
|
-
[Command.
|
|
60
|
-
[Command.
|
|
61
|
-
[Command.
|
|
46
|
+
Command["PushFilterID"] = "pushFilterID";
|
|
47
|
+
})(Command || (Command = {}));
|
|
48
|
+
export const commands = new Map([
|
|
49
|
+
[Command.Login, loginCommand],
|
|
50
|
+
[Command.Delay, delayCommand],
|
|
51
|
+
[Command.SetPGN, setPGNCommand],
|
|
52
|
+
[Command.SetPGNMulti, setPGNMultiCommand],
|
|
53
|
+
[Command.SetLichessGames, setLichessGamesCommand],
|
|
54
|
+
[Command.FixSchedule, fixScheduleCommand],
|
|
55
|
+
[Command.StartsPrevious, startsPreviousCommand],
|
|
56
|
+
[Command.Period, periodCommand],
|
|
57
|
+
[Command.Score, scoreCommand],
|
|
58
|
+
[Command.Push, pushCommand],
|
|
59
|
+
[Command.PushFilterID, pushFilterIDCommand],
|
|
62
60
|
]);
|
|
63
|
-
|
|
61
|
+
export const client = createClient({
|
|
64
62
|
baseUrl: LICHESS_DOMAIN,
|
|
65
63
|
headers: {
|
|
66
|
-
Authorization: `Bearer ${
|
|
64
|
+
Authorization: `Bearer ${LICHESS_TOKEN}`,
|
|
67
65
|
Accept: "application/json",
|
|
68
|
-
"User-Agent":
|
|
66
|
+
"User-Agent": packageJson.name + "/" + packageJson.version,
|
|
69
67
|
},
|
|
70
68
|
});
|
|
71
|
-
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
console.
|
|
75
|
-
console.info(colors_1.default.blue("Use --help to see usage."));
|
|
69
|
+
export const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
70
|
+
export const msgCommonErrorHelp = (msg) => {
|
|
71
|
+
console.error(cl.red(msg));
|
|
72
|
+
console.info(cl.blue("Use --help to see usage."));
|
|
76
73
|
};
|
|
77
|
-
|
|
78
|
-
const handleApiResponse = async (promise, successMsg, errorContext) => {
|
|
74
|
+
export const handleApiResponse = async (promise, successMsg, errorContext) => {
|
|
79
75
|
try {
|
|
80
76
|
const response = await promise;
|
|
81
77
|
if (response.response.ok) {
|
|
82
|
-
console.log(
|
|
78
|
+
console.log(cl.green(successMsg));
|
|
83
79
|
}
|
|
84
80
|
else {
|
|
85
|
-
console.error(
|
|
81
|
+
console.error(cl.red(`${errorContext}: ${cl.whiteBold(response.response.statusText)}`));
|
|
86
82
|
}
|
|
87
83
|
}
|
|
88
84
|
catch (error) {
|
|
89
|
-
console.error(
|
|
85
|
+
console.error(cl.red(errorContext), error);
|
|
90
86
|
}
|
|
91
87
|
};
|
|
92
|
-
|
|
93
|
-
const translateRoundsToFix = (arg) => {
|
|
88
|
+
export const translateRoundsToFix = (arg) => {
|
|
94
89
|
const rounds = [];
|
|
95
90
|
const parts = arg.split(",");
|
|
96
91
|
for (const part of parts) {
|
|
@@ -121,32 +116,30 @@ const translateRoundsToFix = (arg) => {
|
|
|
121
116
|
}
|
|
122
117
|
return [...new Set(rounds)];
|
|
123
118
|
};
|
|
124
|
-
|
|
125
|
-
const checkTokenScopes = async (modRequired) => {
|
|
119
|
+
export const checkTokenScopes = async (modRequired) => {
|
|
126
120
|
const requiredScopes = ["study:read", "study:write"];
|
|
127
121
|
if (modRequired)
|
|
128
122
|
requiredScopes.push("web:mod");
|
|
129
|
-
const stored =
|
|
123
|
+
const stored = getStoredCredentials();
|
|
130
124
|
let scopes = [];
|
|
131
125
|
if (stored?.scopes) {
|
|
132
126
|
scopes = stored.scopes;
|
|
133
127
|
}
|
|
134
128
|
else {
|
|
135
|
-
const response = await
|
|
129
|
+
const response = await client.POST("/api/token/test", {
|
|
136
130
|
headers: {
|
|
137
131
|
"Content-Type": "text/plain",
|
|
138
132
|
},
|
|
139
|
-
body:
|
|
133
|
+
body: LICHESS_TOKEN,
|
|
140
134
|
bodySerializer: (body) => body,
|
|
141
135
|
});
|
|
142
136
|
const data = await response.data;
|
|
143
|
-
const scopesStr = data?.[
|
|
137
|
+
const scopesStr = data?.[LICHESS_TOKEN]?.scopes;
|
|
144
138
|
scopes = scopesStr ? scopesStr.split(",").map((s) => s.trim()) : [];
|
|
145
139
|
}
|
|
146
140
|
const missingScopes = requiredScopes.filter((scope) => !scopes.includes(scope));
|
|
147
141
|
if (missingScopes.length > 0) {
|
|
148
|
-
console.error(
|
|
142
|
+
console.error(cl.red(`Error: Missing required token scopes: ${missingScopes.join(", ")}`));
|
|
149
143
|
process.exit(1);
|
|
150
144
|
}
|
|
151
145
|
};
|
|
152
|
-
exports.checkTokenScopes = checkTokenScopes;
|
|
@@ -1,45 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const node_os_1 = require("node:os");
|
|
7
|
-
const CONFIG_DIR = (0, node_path_1.join)((0, node_os_1.homedir)(), ".libroadcast");
|
|
8
|
-
const CREDENTIALS_FILE = (0, node_path_1.join)(CONFIG_DIR, "credentials.json");
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync, } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
const CONFIG_DIR = join(homedir(), ".libroadcast");
|
|
5
|
+
const CREDENTIALS_FILE = join(CONFIG_DIR, "credentials.json");
|
|
9
6
|
const ensureConfigDir = () => {
|
|
10
|
-
if (!
|
|
11
|
-
|
|
7
|
+
if (!existsSync(CONFIG_DIR)) {
|
|
8
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
12
9
|
}
|
|
13
10
|
};
|
|
14
|
-
const getStoredCredentials = () => {
|
|
11
|
+
export const getStoredCredentials = () => {
|
|
15
12
|
try {
|
|
16
|
-
if (!
|
|
13
|
+
if (!existsSync(CREDENTIALS_FILE)) {
|
|
17
14
|
return null;
|
|
18
15
|
}
|
|
19
|
-
const content =
|
|
16
|
+
const content = readFileSync(CREDENTIALS_FILE, "utf-8");
|
|
20
17
|
return JSON.parse(content);
|
|
21
18
|
}
|
|
22
19
|
catch (error) {
|
|
23
20
|
return null;
|
|
24
21
|
}
|
|
25
22
|
};
|
|
26
|
-
|
|
27
|
-
const saveCredentials = (credentials) => {
|
|
23
|
+
export const saveCredentials = (credentials) => {
|
|
28
24
|
ensureConfigDir();
|
|
29
|
-
|
|
25
|
+
writeFileSync(CREDENTIALS_FILE, JSON.stringify(credentials, null, 2), "utf-8");
|
|
30
26
|
};
|
|
31
|
-
|
|
32
|
-
const clearCredentials = () => {
|
|
27
|
+
export const clearCredentials = () => {
|
|
33
28
|
try {
|
|
34
|
-
if (
|
|
35
|
-
|
|
29
|
+
if (existsSync(CREDENTIALS_FILE)) {
|
|
30
|
+
unlinkSync(CREDENTIALS_FILE);
|
|
36
31
|
}
|
|
37
32
|
}
|
|
38
33
|
catch (error) {
|
|
39
34
|
}
|
|
40
35
|
};
|
|
41
|
-
|
|
42
|
-
const fetchTokenScopes = async (token, domain) => {
|
|
36
|
+
export const fetchTokenScopes = async (token, domain) => {
|
|
43
37
|
try {
|
|
44
38
|
const normalizedDomain = domain.replace(/\/$/, "") + "/";
|
|
45
39
|
const url = `${normalizedDomain}api/token/test`;
|
|
@@ -61,4 +55,3 @@ const fetchTokenScopes = async (token, domain) => {
|
|
|
61
55
|
throw new Error(`Failed to fetch token scopes: ${error instanceof Error ? error.message : String(error)}`);
|
|
62
56
|
}
|
|
63
57
|
};
|
|
64
|
-
exports.fetchTokenScopes = fetchTokenScopes;
|
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getBroadcastRound = exports.getBroadcast = void 0;
|
|
7
|
-
const commandHandler_1 = require("./commandHandler");
|
|
8
|
-
const colors_1 = __importDefault(require("./colors"));
|
|
9
|
-
const getBroadcast = (broadcastId) => commandHandler_1.client
|
|
1
|
+
import { client } from "./commandHandler.js";
|
|
2
|
+
import cl from "./colors.js";
|
|
3
|
+
export const getBroadcast = (broadcastId) => client
|
|
10
4
|
.GET("/api/broadcast/{broadcastTournamentId}", {
|
|
11
5
|
params: {
|
|
12
6
|
path: { broadcastTournamentId: broadcastId },
|
|
@@ -14,11 +8,10 @@ const getBroadcast = (broadcastId) => commandHandler_1.client
|
|
|
14
8
|
})
|
|
15
9
|
.then((response) => response.data)
|
|
16
10
|
.catch((error) => {
|
|
17
|
-
console.error(
|
|
11
|
+
console.error(cl.red("Error fetching broadcast:"), error);
|
|
18
12
|
return null;
|
|
19
13
|
});
|
|
20
|
-
|
|
21
|
-
const getBroadcastRound = (roundId) => commandHandler_1.client
|
|
14
|
+
export const getBroadcastRound = (roundId) => client
|
|
22
15
|
.GET("/api/broadcast/{broadcastTournamentSlug}/{broadcastRoundSlug}/{broadcastRoundId}", {
|
|
23
16
|
params: {
|
|
24
17
|
path: {
|
|
@@ -30,7 +23,6 @@ const getBroadcastRound = (roundId) => commandHandler_1.client
|
|
|
30
23
|
})
|
|
31
24
|
.then((response) => response.data?.round)
|
|
32
25
|
.catch((error) => {
|
|
33
|
-
console.error(
|
|
26
|
+
console.error(cl.red("Error fetching broadcast round:"), error);
|
|
34
27
|
return null;
|
|
35
28
|
});
|
|
36
|
-
exports.getBroadcastRound = getBroadcastRound;
|
package/dist/utils/help.js
CHANGED
|
@@ -1,91 +1,92 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.includeHelp = exports.showHelp = void 0;
|
|
7
|
-
const commandHandler_1 = require("./commandHandler");
|
|
8
|
-
const colors_1 = __importDefault(require("./colors"));
|
|
1
|
+
import { Command } from "./commandHandler.js";
|
|
2
|
+
import cl from "./colors.js";
|
|
9
3
|
const helpLogin = [
|
|
10
|
-
` ${
|
|
11
|
-
` ${
|
|
12
|
-
` ${
|
|
13
|
-
` ${
|
|
14
|
-
` --logout (-lo) ${
|
|
4
|
+
` ${cl.underItalic("login [--logout]")}`,
|
|
5
|
+
` ${cl.gray("Save your Lichess token and domain for future use.")}`,
|
|
6
|
+
` ${cl.gray("This allows you to use the CLI without setting environment variables.")}`,
|
|
7
|
+
` ${cl.bold("Options:")}`,
|
|
8
|
+
` --logout (-lo) ${cl.gray("Clear saved credentials and log out.")}`,
|
|
15
9
|
].join("\n");
|
|
16
10
|
const helpDelay = [
|
|
17
|
-
` ${
|
|
18
|
-
` ${
|
|
19
|
-
` ${
|
|
20
|
-
` ${
|
|
21
|
-
` --onlyDelay ${
|
|
22
|
-
` --noDelay ${
|
|
23
|
-
` --rounds <roundsToFix> ${
|
|
11
|
+
` ${cl.underItalic("delay <broadcastId> <delayInSeconds> [--onlyDelay] [--noDelay] [--rounds <roundsToFix>]")} `,
|
|
12
|
+
` ${cl.gray("Sets the delay for all rounds in the specified broadcast.")}`,
|
|
13
|
+
` ${cl.bold("Note:")} ${cl.gray("The delay is specified in seconds. (max 3600 seconds = 1 hour)")}`,
|
|
14
|
+
` ${cl.bold("Options:")}`,
|
|
15
|
+
` --onlyDelay ${cl.gray("Set only the delay without changing the start time.")}`,
|
|
16
|
+
` --noDelay ${cl.gray("Do not modify the delay, only adjust the start time.")}`,
|
|
17
|
+
` --rounds <roundsToFix> ${cl.gray("Specify which rounds to fix using formats like '1-4', '8+', '3,5,7', etc.")}`,
|
|
24
18
|
].join("\n");
|
|
25
19
|
const helpSetPGN = [
|
|
26
|
-
` ${
|
|
27
|
-
` ${
|
|
28
|
-
` ${
|
|
29
|
-
` ${
|
|
30
|
-
` ${
|
|
31
|
-
` --withFilter ${
|
|
32
|
-
` --slice <sliceFilter> ${
|
|
33
|
-
` --rounds <roundsToFix> ${
|
|
20
|
+
` ${cl.underItalic("setPGN <broadcastId> <sourcePGNUrl> [--withFilter] [--slice <sliceFilter>] [--rounds <roundsToFix>]")}`,
|
|
21
|
+
` ${cl.gray("Sets the source PGN URL for all rounds in the specified broadcast.")}`,
|
|
22
|
+
` ${cl.italic("(optional)")} ${cl.gray('Use "{}" in the URL as a placeholder for the round number.')}`,
|
|
23
|
+
` ${cl.bold("Note:")} ${cl.gray('For livechesscloud URLs, please ensure it ends with "/{}".')}`,
|
|
24
|
+
` ${cl.bold("Options:")}`,
|
|
25
|
+
` --withFilter ${cl.gray("Apply round number filtering based on round number.")}`,
|
|
26
|
+
` --slice <sliceFilter> ${cl.gray("Apply slice filtering using the provided filter string.")}`,
|
|
27
|
+
` --rounds <roundsToFix> ${cl.gray("Specify which rounds to fix using formats like '1-4', '8+', '3,5,7', etc.")}`,
|
|
34
28
|
].join("\n");
|
|
35
29
|
const helpSetPGNMulti = [
|
|
36
|
-
` ${
|
|
37
|
-
` ${
|
|
38
|
-
` ${
|
|
39
|
-
` ${
|
|
40
|
-
` ${
|
|
41
|
-
` ${
|
|
42
|
-
` --withFilter ${
|
|
43
|
-
` --onlyGames <sliceFilter> ${
|
|
44
|
-
` --rounds <roundsToFix> ${
|
|
30
|
+
` ${cl.underItalic("setPGNMulti <broadcastId> <sourcePGNUrl> <gamesNum> [--withFilter] [--onlyGames <sliceFilter>] [--rounds <roundsToFix>]")}`,
|
|
31
|
+
` ${cl.gray("Sets the source PGN URLs for all rounds in the specified broadcast.")}`,
|
|
32
|
+
` ${cl.gray("Use {r} in the URL as a placeholder for the round number and {g} for the game number.")}`,
|
|
33
|
+
` ${cl.gray("Use the gamesNum parameter to specify how many games per round.")}`,
|
|
34
|
+
` ${cl.bold("Note:")} ${cl.gray('For broadcasts with multiple rounds, the source PGN URLs must include the "{g}" placeholder for round numbers.')}`,
|
|
35
|
+
` ${cl.bold("Options:")}`,
|
|
36
|
+
` --withFilter ${cl.gray("Apply round number filtering based on round number.")}`,
|
|
37
|
+
` --onlyGames <sliceFilter> ${cl.gray("Apply slice filtering using the provided filter string.")}`,
|
|
38
|
+
` --rounds <roundsToFix> ${cl.gray("Specify which rounds to fix using formats like '1-4', '8+', '3,5,7', etc.")}`,
|
|
45
39
|
].join("\n");
|
|
46
40
|
const helpSetLichessGames = [
|
|
47
|
-
` ${
|
|
48
|
-
` ${
|
|
49
|
-
` ${
|
|
41
|
+
` ${cl.underItalic("setLichessGames <broadcastRoundId> <gameIds...>")}`,
|
|
42
|
+
` ${cl.gray("Sets the games for the specified broadcast round using Lichess game IDs.")}`,
|
|
43
|
+
` ${cl.bold("Note:")} ${cl.gray("Maximum of 64 game IDs can be provided.")}`,
|
|
50
44
|
].join("\n");
|
|
51
45
|
const helpFixSchedule = [
|
|
52
|
-
` ${
|
|
53
|
-
` ${
|
|
54
|
-
` ${
|
|
55
|
-
` ${
|
|
56
|
-
` --rounds <roundsToFix> ${
|
|
46
|
+
` ${cl.underItalic("fixSchedule <broadcastId> <timeDiff> [--rounds <roundsToFix>]")}`,
|
|
47
|
+
` ${cl.gray("Fixes the schedule of rounds in the specified broadcast by applying a time difference.")}`,
|
|
48
|
+
` ${cl.bold("Note:")} ${cl.gray('The time difference should be in a format like "1h", "30m", "15s", etc.')}`,
|
|
49
|
+
` ${cl.bold("Options:")}`,
|
|
50
|
+
` --rounds <roundsToFix> ${cl.gray("Specify which rounds to fix using formats like '1-4', '8+', '3,5,7', etc.")}`,
|
|
57
51
|
].join("\n");
|
|
58
52
|
const helpStartsPrevious = [
|
|
59
|
-
` ${
|
|
60
|
-
` ${
|
|
53
|
+
` ${cl.underItalic("startsPrevious <broadcastId> <startsPrevious>")}`,
|
|
54
|
+
` ${cl.gray("Sets the startsAfterPrevious flag for all rounds in the specified broadcast.")}`,
|
|
61
55
|
].join("\n");
|
|
62
56
|
const helpSetPeriod = [
|
|
63
|
-
` ${
|
|
64
|
-
` ${
|
|
65
|
-
` ${
|
|
66
|
-
` ${
|
|
67
|
-
` ${
|
|
68
|
-
` --rounds <roundsToFix> ${
|
|
57
|
+
` ${cl.underItalic("period <broadcastId> <periodInSeconds>")}`,
|
|
58
|
+
` ${cl.gray("Sets the period between polling for all rounds in the specified broadcast.")}`,
|
|
59
|
+
` ${cl.redBold("Required:")} ${cl.gray(`Your Lichess token needs the ${cl.whiteBold("web:mod")} scope to use this command. (Broadcast/Study Admin perm required)`)}`,
|
|
60
|
+
` ${cl.bold("Note:")} ${cl.gray("The period is specified in seconds.")}`,
|
|
61
|
+
` ${cl.bold("Options:")}`,
|
|
62
|
+
` --rounds <roundsToFix> ${cl.gray("Specify which rounds to fix using formats like '1-4', '8+', '3,5,7', etc.")}`,
|
|
69
63
|
].join("\n");
|
|
70
64
|
const helpScore = [
|
|
71
|
-
` ${
|
|
72
|
-
` ${
|
|
73
|
-
` ${
|
|
74
|
-
` ${
|
|
75
|
-
` --rounds <roundsToFix> ${
|
|
65
|
+
` ${cl.underItalic("score <broadcastId> <whiteWin> <whiteDraw> <blackWin> <blackDraw> [--rounds <roundsToFix>]")}`,
|
|
66
|
+
` ${cl.gray("Sets the custom scoring for all rounds in the specified broadcast.")}`,
|
|
67
|
+
` ${cl.bold("Note:")} ${cl.gray("Scores must be numbers between 0 and 10.")}`,
|
|
68
|
+
` ${cl.bold("Options:")}`,
|
|
69
|
+
` --rounds <roundsToFix> ${cl.gray("Specify which rounds to fix using formats like '1-4', '8+', '3,5,7', etc.")}`,
|
|
76
70
|
].join("\n");
|
|
77
71
|
const helpPush = [
|
|
78
|
-
` ${
|
|
79
|
-
` ${
|
|
80
|
-
` ${
|
|
81
|
-
` ${
|
|
82
|
-
` --loop <intervalInSeconds> ${
|
|
72
|
+
` ${cl.underItalic("push <roundId> <PGNFromPathOrUrl> [--loop <intervalInSeconds>]")}`,
|
|
73
|
+
` ${cl.gray("Upload a PGN file from a local path or URL to the specified broadcast round.")}`,
|
|
74
|
+
` ${cl.bold("Note:")} ${cl.gray("The PGN file must be accessible from the provided path or URL.")}`,
|
|
75
|
+
` ${cl.bold("Options:")}`,
|
|
76
|
+
` --loop <intervalInSeconds> ${cl.gray("Continuously push the PGN file at the specified interval in seconds.")}`,
|
|
77
|
+
].join("\n");
|
|
78
|
+
const helpPushFilterID = [
|
|
79
|
+
` ${cl.underItalic("pushFilterID <roundId> <PGNFromPathOrUrl> <FideIds...> [--loop <intervalInSeconds>]")}`,
|
|
80
|
+
` ${cl.gray("Upload a PGN file from a local path or URL to the specified broadcast round, filtering games by FIDE ID.")}`,
|
|
81
|
+
` ${cl.bold("Note:")} ${cl.gray("The PGN file must be accessible from the provided path or URL.")}`,
|
|
82
|
+
` ${cl.bold("Options:")}`,
|
|
83
|
+
` --loop <intervalInSeconds> ${cl.gray("Continuously push the PGN file at the specified interval in seconds.")}`,
|
|
83
84
|
].join("\n");
|
|
84
85
|
const msg = [
|
|
85
|
-
`${
|
|
86
|
+
`${cl.boldYellow("Usage:")} ${cl.underItalic("<command> [options]")}`,
|
|
86
87
|
``,
|
|
87
88
|
``,
|
|
88
|
-
`${
|
|
89
|
+
`${cl.boldYellow("Commands:")}`,
|
|
89
90
|
helpLogin,
|
|
90
91
|
``,
|
|
91
92
|
helpDelay,
|
|
@@ -106,49 +107,52 @@ const msg = [
|
|
|
106
107
|
``,
|
|
107
108
|
helpPush,
|
|
108
109
|
``,
|
|
110
|
+
helpPushFilterID,
|
|
111
|
+
``,
|
|
109
112
|
``,
|
|
110
|
-
`${
|
|
111
|
-
` ${
|
|
112
|
-
` $ ${
|
|
113
|
-
` ${
|
|
114
|
-
` $ ${
|
|
115
|
-
` ${
|
|
116
|
-
` $ ${
|
|
117
|
-
` ${
|
|
118
|
-
` $ ${
|
|
119
|
-
` ${
|
|
120
|
-
` $ ${
|
|
121
|
-
` ${
|
|
122
|
-
` $ ${
|
|
123
|
-
` ${
|
|
124
|
-
` $ ${
|
|
125
|
-
` ${
|
|
126
|
-
` $ ${
|
|
127
|
-
` ${
|
|
128
|
-
` $ ${
|
|
129
|
-
` ${
|
|
130
|
-
` $ ${
|
|
131
|
-
` ${
|
|
132
|
-
` $ ${
|
|
133
|
-
` ${
|
|
134
|
-
` $ ${
|
|
113
|
+
`${cl.boldYellow("Examples:")}`,
|
|
114
|
+
` ${cl.gray("# Login with your Lichess token (interactive)")}`,
|
|
115
|
+
` $ ${cl.underItalic("login")}`,
|
|
116
|
+
` ${cl.gray("# Login with token as argument")}`,
|
|
117
|
+
` $ ${cl.underItalic("login")} ${cl.italic("lip_yourtoken https://lichess.org")}`,
|
|
118
|
+
` ${cl.gray("# Logout and clear saved credentials")}`,
|
|
119
|
+
` $ ${cl.underItalic("login")} ${cl.italic("--logout")}`,
|
|
120
|
+
` ${cl.gray("# Set a 5-minute delay without changing start time")}`,
|
|
121
|
+
` $ ${cl.underItalic("delay")} ${cl.italic("bcast123 300 --onlyDelay")}`,
|
|
122
|
+
` ${cl.gray("# Set source PGN URL with round and slice filters")}`,
|
|
123
|
+
` $ ${cl.underItalic("setPGN")} ${cl.italic('bcast123 https://example.com/pgns/round-{}/game.pgn --withFilter --slice "1-5,7,9-12"')}`,
|
|
124
|
+
` ${cl.gray("# Set source PGN URLs for multiple games per round")}`,
|
|
125
|
+
` $ ${cl.underItalic("setPGNMulti")} ${cl.italic('bcast123 https://example.com/pgns/round-{r}/game-{g}.pgn 12 --withFilter --onlyGames "1-5,7,9-12"')}`,
|
|
126
|
+
` ${cl.gray("# Set Lichess games for a broadcast round")}`,
|
|
127
|
+
` $ ${cl.underItalic("setLichessGames")} ${cl.italic("round456 gameId1 gameId2 gameId3")}`,
|
|
128
|
+
` ${cl.gray("# Fix schedule of rounds 1 to 4 and all rounds after 8 by adding 15 minutes")}`,
|
|
129
|
+
` $ ${cl.underItalic("fixSchedule")} ${cl.italic("bcast123 15m --rounds 1-4,8+")}`,
|
|
130
|
+
` ${cl.gray("# Set startsAfterPrevious to true for all rounds in a broadcast")}`,
|
|
131
|
+
` $ ${cl.underItalic("startsPrevious")} ${cl.italic("bcast123 true")}`,
|
|
132
|
+
` ${cl.gray("# Set polling period to 10 seconds for all rounds in a broadcast")}`,
|
|
133
|
+
` $ ${cl.underItalic("period")} ${cl.italic("bcast123 10")}`,
|
|
134
|
+
` ${cl.gray("# Set custom scoring for all rounds in a broadcast")}`,
|
|
135
|
+
` $ ${cl.underItalic("score")} ${cl.italic("bcast123 1.0 0.5 1.0 0.5")}`,
|
|
136
|
+
` ${cl.gray("# Push a PGN file in loop mode every 60 seconds")}`,
|
|
137
|
+
` $ ${cl.underItalic("push")} ${cl.italic("round456 /path/to/localfile.pgn --loop 60")}`,
|
|
138
|
+
` ${cl.gray("# Push a PGN file from URL filtering by FIDE IDs in loop mode every 120 seconds")}`,
|
|
139
|
+
` $ ${cl.underItalic("pushFilterID")} ${cl.italic("round456 https://example.com/games.pgn 12345 67890 --loop 120")}`,
|
|
135
140
|
];
|
|
136
|
-
const showHelp = (cmd) => {
|
|
141
|
+
export const showHelp = (cmd) => {
|
|
137
142
|
const ranges = {
|
|
138
|
-
[
|
|
139
|
-
[
|
|
140
|
-
[
|
|
141
|
-
[
|
|
142
|
-
[
|
|
143
|
-
[
|
|
144
|
-
[
|
|
145
|
-
[
|
|
146
|
-
[
|
|
147
|
-
[
|
|
143
|
+
[Command.Login]: helpLogin,
|
|
144
|
+
[Command.Delay]: helpDelay,
|
|
145
|
+
[Command.SetPGN]: helpSetPGN,
|
|
146
|
+
[Command.SetPGNMulti]: helpSetPGNMulti,
|
|
147
|
+
[Command.SetLichessGames]: helpSetLichessGames,
|
|
148
|
+
[Command.FixSchedule]: helpFixSchedule,
|
|
149
|
+
[Command.StartsPrevious]: helpStartsPrevious,
|
|
150
|
+
[Command.Period]: helpSetPeriod,
|
|
151
|
+
[Command.Score]: helpScore,
|
|
152
|
+
[Command.Push]: helpPush,
|
|
153
|
+
[Command.PushFilterID]: helpPushFilterID,
|
|
148
154
|
};
|
|
149
155
|
const range = cmd ? ranges[cmd] : undefined;
|
|
150
156
|
console.info(range ? range : msg.join("\n"));
|
|
151
157
|
};
|
|
152
|
-
|
|
153
|
-
const includeHelp = (str) => ["--help", "-h"].includes(str);
|
|
154
|
-
exports.includeHelp = includeHelp;
|
|
158
|
+
export const includeHelp = (str) => ["--help", "-h"].includes(str);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "libroadcast-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.1",
|
|
4
4
|
"description": "CLI to help with broadcast maintenance on Lichess",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"keywords": [
|
|
@@ -10,15 +10,16 @@
|
|
|
10
10
|
],
|
|
11
11
|
"author": "Sérgio Glórias",
|
|
12
12
|
"license": "MIT",
|
|
13
|
-
"type": "
|
|
13
|
+
"type": "module",
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@lichess-org/types": "^2.0.109",
|
|
16
16
|
"@types/node": "~24.10.4",
|
|
17
|
+
"chessops": "^0.15.0",
|
|
17
18
|
"ms": "3.0.0-canary.202508261828",
|
|
18
19
|
"openapi-fetch": "^0.15.0"
|
|
19
20
|
},
|
|
20
21
|
"devDependencies": {
|
|
21
|
-
"prettier": "3.
|
|
22
|
+
"prettier": "3.8.1",
|
|
22
23
|
"typescript": "^5.9.3"
|
|
23
24
|
},
|
|
24
25
|
"engines": {
|