libroadcast-cli 2.7.0 → 2.8.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 CHANGED
@@ -76,12 +76,15 @@ Commands:
76
76
  Options:
77
77
  --loop <intervalInSeconds> Continuously push the PGN file at the specified interval in seconds.
78
78
 
79
- pushFilterID <roundId> <PGNFromPathOrUrl> <FideIds...> [--loop <intervalInSeconds>] [--firstOngoing]
79
+ pushFilterID <roundId> <PGNFromPathOrUrl> <FideIds...> [--loop <intervalInSeconds>]
80
80
  Upload a PGN file from a local path or URL to the specified broadcast round, filtering games by FIDE ID.
81
81
  Note: The PGN file must be accessible from the provided path or URL.
82
82
  Options:
83
83
  --loop <intervalInSeconds> Continuously push the PGN file at the specified interval in seconds.
84
- --firstOngoing Push the first ongoing games in each round.
84
+
85
+ convertNamesToID <roundId>
86
+ Convert Lichess Usernames source to Lichess Game IDs source for the specified broadcast round.
87
+ Note: This command will fetch the source PGN, extract Lichess Game IDs from the PGN headers, and update the broadcast round to use these game IDs as the source.
85
88
 
86
89
 
87
90
  Examples:
@@ -111,6 +114,8 @@ Examples:
111
114
  $ push round456 /path/to/localfile.pgn --loop 60
112
115
  # Push a PGN file from URL filtering by FIDE IDs in loop mode every 120 seconds
113
116
  $ pushFilterID round456 https://example.com/games.pgn 12345 67890 --loop 120
117
+ # Convert Lichess Usernames source to Lichess Game IDs source for a broadcast round
118
+ $ convertNamesToID round456
114
119
  ```
115
120
 
116
121
  ### Test Docker Build Locally
@@ -0,0 +1,50 @@
1
+ import { exit } from "node:process";
2
+ import { msgCommonErrorHelp, checkTokenScopes, client, handleApiResponse, } from "../utils/commandHandler.js";
3
+ import { parsePgn } from "chessops/pgn";
4
+ import { getBroadcastRound } from "../utils/getInfoBroadcast.js";
5
+ import cl from "../utils/colors.js";
6
+ const setGameIds = (roundInfo, gameIds) => handleApiResponse(client.POST("/broadcast/round/{broadcastRoundId}/edit", {
7
+ params: {
8
+ path: { broadcastRoundId: roundInfo.id },
9
+ query: { patch: 1 },
10
+ },
11
+ body: {
12
+ syncSource: "ids",
13
+ syncIds: gameIds,
14
+ },
15
+ }), `Successfully set game IDs for round ${cl.whiteBold(roundInfo.id)}.`, `Error setting game IDs for round ${cl.whiteBold(roundInfo.id)}`);
16
+ const getGameIdFromPgn = async (roundId) => {
17
+ const response = await client.GET("/api/broadcast/round/{broadcastRoundId}.pgn", {
18
+ params: { path: { broadcastRoundId: roundId } },
19
+ parseAs: "text",
20
+ });
21
+ if (!response.response.ok) {
22
+ console.error(cl.red("Failed to fetch PGN for the round."));
23
+ exit(1);
24
+ }
25
+ const pgn = parsePgn(response.data);
26
+ const gamesWithIds = pgn
27
+ .map((game) => game.headers.get("GameId") || null)
28
+ .filter((id) => typeof id === "string");
29
+ return gamesWithIds;
30
+ };
31
+ export const convertNamesToIDCommand = async (args) => {
32
+ await checkTokenScopes();
33
+ const [roundId] = args.slice(0, 1);
34
+ if (!roundId) {
35
+ msgCommonErrorHelp("Round ID is required.");
36
+ exit(1);
37
+ }
38
+ const roundInfo = await getBroadcastRound(roundId);
39
+ if (!roundInfo) {
40
+ console.error(cl.red("Round not found."));
41
+ exit(1);
42
+ }
43
+ const gameIds = await getGameIdFromPgn(roundId);
44
+ if (gameIds.length === 0) {
45
+ console.error(cl.red("No games with GameId found in the PGN."));
46
+ exit(1);
47
+ }
48
+ const IdsString = gameIds.join(" ");
49
+ await setGameIds(roundInfo, IdsString);
50
+ };
@@ -16,6 +16,7 @@ import { pushCommand } from "../cmd/push.js";
16
16
  import { pushFilterIDCommand } from "../cmd/pushFilterID.js";
17
17
  import { loginCommand } from "../cmd/login.js";
18
18
  import { getStoredCredentials } from "./credentials.js";
19
+ import { convertNamesToIDCommand } from "../cmd/convertNamesToID.js";
19
20
  const getToken = () => {
20
21
  const stored = getStoredCredentials();
21
22
  const envToken = process.env.LICHESS_TOKEN;
@@ -45,6 +46,7 @@ export var Command;
45
46
  Command["Score"] = "score";
46
47
  Command["Push"] = "push";
47
48
  Command["PushFilterID"] = "pushFilterID";
49
+ Command["ConvertNamesToID"] = "convertNamesToID";
48
50
  })(Command || (Command = {}));
49
51
  export const commands = new Map([
50
52
  [Command.Login, loginCommand],
@@ -58,6 +60,7 @@ export const commands = new Map([
58
60
  [Command.Score, scoreCommand],
59
61
  [Command.Push, pushCommand],
60
62
  [Command.PushFilterID, pushFilterIDCommand],
63
+ [Command.ConvertNamesToID, convertNamesToIDCommand],
61
64
  ]);
62
65
  export const client = createClient({
63
66
  baseUrl: LICHESS_DOMAIN,
@@ -82,6 +82,11 @@ const helpPushFilterID = [
82
82
  ` ${cl.bold("Options:")}`,
83
83
  ` --loop <intervalInSeconds> ${cl.gray("Continuously push the PGN file at the specified interval in seconds.")}`,
84
84
  ].join("\n");
85
+ const helpConvertNamesToID = [
86
+ ` ${cl.underItalic("convertNamesToID <roundId>")}`,
87
+ ` ${cl.gray("Convert Lichess Usernames source to Lichess Game IDs source for the specified broadcast round.")}`,
88
+ ` ${cl.bold("Note:")} ${cl.gray("This command will fetch the source PGN, extract Lichess Game IDs from the PGN headers, and update the broadcast round to use these game IDs as the source.")}`,
89
+ ].join("\n");
85
90
  const msg = [
86
91
  `${cl.boldYellow("Usage:")} ${cl.underItalic("<command> [options]")}`,
87
92
  ``,
@@ -109,6 +114,8 @@ const msg = [
109
114
  ``,
110
115
  helpPushFilterID,
111
116
  ``,
117
+ helpConvertNamesToID,
118
+ ``,
112
119
  ``,
113
120
  `${cl.boldYellow("Examples:")}`,
114
121
  ` ${cl.gray("# Login with your Lichess token (interactive)")}`,
@@ -137,6 +144,8 @@ const msg = [
137
144
  ` $ ${cl.underItalic("push")} ${cl.italic("round456 /path/to/localfile.pgn --loop 60")}`,
138
145
  ` ${cl.gray("# Push a PGN file from URL filtering by FIDE IDs in loop mode every 120 seconds")}`,
139
146
  ` $ ${cl.underItalic("pushFilterID")} ${cl.italic("round456 https://example.com/games.pgn 12345 67890 --loop 120")}`,
147
+ ` ${cl.gray("# Convert Lichess Usernames source to Lichess Game IDs source for a broadcast round")}`,
148
+ ` $ ${cl.underItalic("convertNamesToID")} ${cl.italic("round456")}`,
140
149
  ];
141
150
  export const showHelp = (cmd) => {
142
151
  const ranges = {
@@ -151,6 +160,7 @@ export const showHelp = (cmd) => {
151
160
  [Command.Score]: helpScore,
152
161
  [Command.Push]: helpPush,
153
162
  [Command.PushFilterID]: helpPushFilterID,
163
+ [Command.ConvertNamesToID]: helpConvertNamesToID,
154
164
  };
155
165
  const range = cmd ? ranges[cmd] : undefined;
156
166
  console.info(range ? range : msg.join("\n"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "libroadcast-cli",
3
- "version": "2.7.0",
3
+ "version": "2.8.0",
4
4
  "description": "CLI to help with broadcast maintenance on Lichess",
5
5
  "main": "dist/index.js",
6
6
  "keywords": [
@@ -16,7 +16,7 @@
16
16
  "@types/node": "~24.10.4",
17
17
  "chessops": "^0.15.0",
18
18
  "ms": "3.0.0-canary.202508261828",
19
- "openapi-fetch": "^0.15.0"
19
+ "openapi-fetch": "^0.17.0"
20
20
  },
21
21
  "devDependencies": {
22
22
  "prettier": "3.8.1",