node-csfd-api 5.6.1 → 5.6.2

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
@@ -565,16 +565,27 @@ Download `csfd-windows-x64.zip` from the [latest release](https://github.com/bar
565
565
 
566
566
  > 💡 The examples below use `csfd` (Options B, C & D). If you use npx, replace it with `npx node-csfd-api` — e.g. `npx node-csfd-api export ratings 912`.
567
567
 
568
- #### 1. Movie Details
568
+ #### 1. Search
569
569
 
570
570
  ```bash
571
- csfd movie 535121
571
+ csfd search tarantino
572
+ # npx node-csfd-api search tarantino
573
+ csfd search "blade runner" --json # raw JSON output
574
+ # npx node-csfd-api search "blade runner" --json
575
+ ```
576
+
577
+ #### 2. Movie Details
578
+
579
+ ```bash
580
+ csfd movie 535121 # by ID
572
581
  # npx node-csfd-api movie 535121
573
- csfd movie 535121 --json # raw JSON output, pipe-friendly
582
+ csfd movie "blade runner" # by title searches and shows the top result
583
+ # npx node-csfd-api movie "blade runner"
584
+ csfd movie 535121 --json # raw JSON output, pipe-friendly
574
585
  # npx node-csfd-api movie 535121 --json
575
586
  ```
576
587
 
577
- #### 2. Export Ratings (CSV, JSON & Letterboxd)
588
+ #### 3. Export Ratings (CSV, JSON & Letterboxd)
578
589
 
579
590
  > Backup your personal user ratings. _Use this tool just to keep a local copy of your data._
580
591
 
package/bin/search.js ADDED
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env node
2
+ import { csfd } from "../index.js";
3
+ import { c } from "./utils.js";
4
+
5
+ //#region src/bin/search.ts
6
+ async function runSearch(query, json) {
7
+ const results = await csfd.search(query);
8
+ if (json) {
9
+ console.log(JSON.stringify(results, null, 2));
10
+ return;
11
+ }
12
+ printSearch(query, results);
13
+ }
14
+ function printSearch(query, results) {
15
+ const ratingDot = (colorRating) => colorRating === "good" ? c.green("●") : colorRating === "average" ? c.yellow("●") : colorRating === "bad" ? c.red("●") : c.dim("●");
16
+ const section = (label, count) => count > 0 ? `\n${c.bold(label)} ${c.dim(`(${count})`)}` : null;
17
+ const total = results.movies.length + results.tvSeries.length + results.creators.length + results.users.length;
18
+ console.log("");
19
+ console.log(`${c.bold("Search results for")} ${c.cyan(`"${query}"`)} ${c.dim(`— ${total} found`)}`);
20
+ console.log(c.dim("─".repeat(52)));
21
+ const movieLine = (r) => ` ${c.dim(String(r.id).padEnd(8))} ${ratingDot(r.colorRating)} ${r.title}` + (r.year ? c.dim(` ${r.year}`) : "") + (r.origins?.length ? c.dim(` ${r.origins[0]}`) : "");
22
+ if (results.movies.length > 0) {
23
+ console.log(section("Movies", results.movies.length));
24
+ results.movies.forEach((r) => console.log(movieLine(r)));
25
+ }
26
+ if (results.tvSeries.length > 0) {
27
+ console.log(section("TV Series", results.tvSeries.length));
28
+ results.tvSeries.forEach((r) => console.log(movieLine(r)));
29
+ }
30
+ if (results.creators.length > 0) {
31
+ console.log(section("Creators", results.creators.length));
32
+ results.creators.forEach((r) => console.log(` ${c.dim(String(r.id).padEnd(8))} ${r.name}`));
33
+ }
34
+ if (results.users.length > 0) {
35
+ console.log(section("Users", results.users.length));
36
+ results.users.forEach((r) => console.log(` ${c.dim(String(r.id).padEnd(8))} ${r.user}` + (r.userRealName ? c.dim(` (${r.userRealName})`) : "")));
37
+ }
38
+ if (total === 0) console.log(c.dim(" No results found."));
39
+ console.log("");
40
+ }
41
+
42
+ //#endregion
43
+ export { runSearch };
package/cli.js CHANGED
@@ -94,11 +94,45 @@ async function main() {
94
94
  process.exit(1);
95
95
  }
96
96
  break;
97
+ case "search": {
98
+ const query = args.slice(1).filter((a) => !a.startsWith("--")).join(" ");
99
+ if (!query) {
100
+ console.error(err("Please provide a search query."));
101
+ console.log(c.dim(` Usage: ${getCommandName()} search <query> [--json]`));
102
+ process.exit(1);
103
+ }
104
+ try {
105
+ const { runSearch } = await import("./bin/search.js");
106
+ await runSearch(query, args.includes("--json"));
107
+ } catch (error) {
108
+ console.error(err("Search failed:"), error);
109
+ process.exit(1);
110
+ }
111
+ break;
112
+ }
97
113
  case "movie": {
98
- const movieId = parseNumericArg(args[1], `${getCommandName()} movie <id> [--json]`);
114
+ const input = args.slice(1).filter((a) => !a.startsWith("--")).join(" ");
115
+ if (!input) {
116
+ console.error(err("Please provide a movie ID or title."));
117
+ console.log(c.dim(` Usage: ${getCommandName()} movie <id|title> [--json]`));
118
+ process.exit(1);
119
+ }
120
+ const json = args.includes("--json");
99
121
  try {
100
122
  const { runMovieLookup } = await import("./bin/lookup-movie.js");
101
- await runMovieLookup(movieId, args.includes("--json"));
123
+ const numericId = /^\d+$/.test(input) ? Number(input) : null;
124
+ if (numericId !== null) await runMovieLookup(numericId, json);
125
+ else {
126
+ const { csfd } = await import("./index.js");
127
+ const results = await csfd.search(input);
128
+ const first = results.movies[0] ?? results.tvSeries[0];
129
+ if (!first) {
130
+ console.error(err(`No movies found for "${input}".`));
131
+ process.exit(1);
132
+ }
133
+ console.log(c.dim(` → ${first.title}${first.year ? ` (${first.year})` : ""}`));
134
+ await runMovieLookup(first.id, json);
135
+ }
102
136
  } catch (error) {
103
137
  console.error(err("Failed to fetch movie:"), error);
104
138
  process.exit(1);
@@ -107,7 +141,7 @@ async function main() {
107
141
  }
108
142
  case "--version":
109
143
  case "-v":
110
- console.log(c.bold("5.6.1"));
144
+ console.log(c.bold("5.6.2"));
111
145
  break;
112
146
  case "update":
113
147
  await runUpdate();
@@ -200,15 +234,15 @@ async function checkForUpdateInBackground() {
200
234
  } catch {}
201
235
  }
202
236
  } catch {}
203
- if (!latestVersion || compareSemver("5.6.1", latestVersion) >= 0) return;
237
+ if (!latestVersion || compareSemver("5.6.2", latestVersion) >= 0) return;
204
238
  console.log("");
205
239
  console.log(c.dim(" " + "─".repeat(44)));
206
- console.log(` ${c.yellow(c.bold("↑ Update available:"))} ${c.dim("5.6.1")} → ${c.bold(c.green(latestVersion))}`);
240
+ console.log(` ${c.yellow(c.bold("↑ Update available:"))} ${c.dim("5.6.2")} → ${c.bold(c.green(latestVersion))}`);
207
241
  console.log(` ${c.dim("Run")} ${c.cyan(getCommandName() + " update")} ${c.dim("for upgrade instructions.")}`);
208
242
  } catch {}
209
243
  }
210
244
  async function runUpdate() {
211
- console.log(c.dim("Current version: ") + c.bold("5.6.1"));
245
+ console.log(c.dim("Current version: ") + c.bold("5.6.2"));
212
246
  console.log(c.dim("Checking for updates..."));
213
247
  let latest;
214
248
  try {
@@ -221,7 +255,7 @@ async function runUpdate() {
221
255
  console.error(err("Could not determine latest version."));
222
256
  process.exit(1);
223
257
  }
224
- const cmp = compareSemver("5.6.1", latest);
258
+ const cmp = compareSemver("5.6.2", latest);
225
259
  if (cmp === 0) {
226
260
  console.log(c.green("✔ Already up to date."));
227
261
  return;
@@ -234,7 +268,7 @@ async function runUpdate() {
234
268
  }
235
269
  function printUsage() {
236
270
  const cmd = getCommandName();
237
- const header = c.bold(c.cyan("csfd")) + " " + c.dim(`v5.6.1`);
271
+ const header = c.bold(c.cyan("csfd")) + " " + c.dim(`v5.6.2`);
238
272
  const usage = c.bold("Usage:") + ` ${c.cyan(cmd)} ${c.dim("<command> [options]")}`;
239
273
  const section = (title) => c.bold(title);
240
274
  const cmd_ = (name) => " " + c.cyan(name);
@@ -256,7 +290,8 @@ ${sub_("--letterboxd")} ${desc("Letterboxd-compatible CSV")}
256
290
  ${cmd_("export reviews <userId>")} ${desc("Export user reviews")}
257
291
  ${sub_("--csv")} ${desc("CSV format (default)")}
258
292
  ${sub_("--json")} ${desc("JSON format")}
259
- ${cmd_("movie <id>")} ${desc("Show movie details")}
293
+ ${cmd_("search <query>")} ${desc("Search movies, series, creators and users")}
294
+ ${cmd_("movie <id|title>")} ${desc("Show movie details (ID or film name)")}
260
295
  ${sub_("--json")} ${desc("Output raw JSON")}
261
296
  ${cmd_("update")} ${desc("Check for updates")}
262
297
  ${cmd_("help")} ${desc("Show this help")}
package/package.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  //#region package.json
3
3
  var name = "node-csfd-api";
4
- var version = "5.6.1";
4
+ var version = "5.6.2";
5
5
  var homepage = "https://github.com/bartholomej/node-csfd-api#readme";
6
6
 
7
7
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-csfd-api",
3
- "version": "5.6.1",
3
+ "version": "5.6.2",
4
4
  "description": "ČSFD API in JavaScript. Amazing NPM library for scrapping csfd.cz :)",
5
5
  "author": "BART! <bart@bartweb.cz>",
6
6
  "publishConfig": {