node-csfd-api 4.2.0-next.1 → 4.3.0-next.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 +76 -4
- package/bin/export-ratings.mjs +61 -0
- package/{mcp-server.mjs → bin/mcp-server.mjs} +2 -2
- package/{server.mjs → bin/server.mjs} +2 -2
- package/cli.mjs +101 -0
- package/package.json +4 -5
package/README.md
CHANGED
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
<div align="center">
|
|
8
8
|
|
|
9
|
-
# CSFD API 🎬
|
|
9
|
+
# CSFD API 🎬 + CSFD Export + MCP Server 🤖
|
|
10
10
|
|
|
11
|
-
#### Modern TypeScript NPM library for scraping **
|
|
11
|
+
#### Modern TypeScript NPM library for scraping **CSFD.CZ**. Scraper, API, Export and MCP Server in one package. _(unofficial)_
|
|
12
12
|
|
|
13
|
-
[Features](#-features) • [Installation](#-installation) • [Quick Start](#-quick-start) • [API Reference](#-api-reference) • [Examples](#-usage-examples) • [Docker](#-docker-support)
|
|
13
|
+
[Features](#-features) • [Installation](#-installation) • [Quick Start](#-quick-start) • [API Reference](#-api-reference) • [Examples](#-usage-examples) • [MCP Server](#-mcp-server-model-context-protocol) • [Docker](#-docker-support)
|
|
14
14
|
|
|
15
15
|
</div>
|
|
16
16
|
|
|
@@ -22,14 +22,16 @@
|
|
|
22
22
|
- 🧪 **Well-tested** - ~100% code coverage
|
|
23
23
|
- 🚀 **Universal** - Works in Node.js, browsers, and serverless environments
|
|
24
24
|
- 🐳 **Docker ready** - Pre-built Docker images available
|
|
25
|
+
- 🤖 **MCP Server** - Use CSFD data directly within LLMs like Claude Desktop
|
|
25
26
|
- 🔄 **Modern API** - Promise-based with async/await support
|
|
26
|
-
- 📦 **
|
|
27
|
+
- 📦 **Few dependencies** - Lightweight and efficient
|
|
27
28
|
|
|
28
29
|
### Supported Platforms
|
|
29
30
|
|
|
30
31
|
- Node.js (ESM & CommonJS)
|
|
31
32
|
- Browsers (with CORS considerations)
|
|
32
33
|
- Docker containers
|
|
34
|
+
- MCP Server (Claude Desktop, etc.)
|
|
33
35
|
- Serverless (Firebase Functions, AWS Lambda, CloudFlare Workers, etc.)
|
|
34
36
|
- Chrome Extensions
|
|
35
37
|
- React Native (Yes, with Expo too!)
|
|
@@ -75,6 +77,7 @@ console.log(reviews);
|
|
|
75
77
|
- [Creators](#creators)
|
|
76
78
|
- [User Ratings](#user-ratings)
|
|
77
79
|
- [User Reviews](#user-reviews)
|
|
80
|
+
- [MCP Server](#-mcp-server-model-context-protocol)
|
|
78
81
|
- [Docker Support](#-docker-support)
|
|
79
82
|
- [Development](#-development)
|
|
80
83
|
|
|
@@ -517,6 +520,75 @@ const filtered = await csfd.userReviews(195357, {
|
|
|
517
520
|
|
|
518
521
|
Same options as [UserRatingsOptions](#userrationsoptions).
|
|
519
522
|
|
|
523
|
+
## 💻 CLI Tools
|
|
524
|
+
|
|
525
|
+
This library comes with a powerful CLI that exposes several tools.
|
|
526
|
+
|
|
527
|
+
### 1. Export Ratings (CSV, JSON & Letterboxd)
|
|
528
|
+
|
|
529
|
+
> Backup your personal user ratings to CSV (default), JSON, or Letterboxd format. Use this tool just to keep a local copy of your data.
|
|
530
|
+
|
|
531
|
+
```bash
|
|
532
|
+
# Export to CSV (default) -> saves as <userId>-ratings.csv
|
|
533
|
+
npx node-csfd-api export ratings 912
|
|
534
|
+
|
|
535
|
+
# Export to JSON -> saves as <userId>-ratings.json
|
|
536
|
+
npx node-csfd-api export ratings 912 --json
|
|
537
|
+
|
|
538
|
+
# Export to Letterboxd CSV -> saves as <userId>-for-letterboxd.csv
|
|
539
|
+
npx node-csfd-api export ratings 912 --letterboxd
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
### 2. REST API Server
|
|
543
|
+
|
|
544
|
+
Run a standalone REST API server.
|
|
545
|
+
|
|
546
|
+
```bash
|
|
547
|
+
npx node-csfd-api server
|
|
548
|
+
# Server listening on port 3000
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
### 3. MCP Server
|
|
552
|
+
|
|
553
|
+
Run the Model Context Protocol server for AI agents.
|
|
554
|
+
|
|
555
|
+
```bash
|
|
556
|
+
npx node-csfd-api mcp
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
## 🤖 MCP Server (Model Context Protocol)
|
|
560
|
+
|
|
561
|
+
This library includes a built-in [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server. This allows you to use ČSFD data directly within LLMs like **Claude Desktop**.
|
|
562
|
+
|
|
563
|
+
### Features
|
|
564
|
+
|
|
565
|
+
- **Search**: Search for movies, TV series, and users.
|
|
566
|
+
- **Details**: Get comprehensive details about movies, creators, and users.
|
|
567
|
+
- **Reviews**: Read user reviews and ratings.
|
|
568
|
+
|
|
569
|
+
### Usage with Claude Desktop
|
|
570
|
+
|
|
571
|
+
Add the following configuration to your `claude_desktop_config.json`:
|
|
572
|
+
|
|
573
|
+
```json
|
|
574
|
+
{
|
|
575
|
+
"mcpServers": {
|
|
576
|
+
"csfd": {
|
|
577
|
+
"command": "npx",
|
|
578
|
+
"args": ["-y", "node-csfd-api", "mcp"]
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
### Supported Tools
|
|
585
|
+
|
|
586
|
+
- `search`: Search query (returns movies, series, users)
|
|
587
|
+
- `movie_details`: Get movie details by ID
|
|
588
|
+
- `creator_details`: Get creator details by ID
|
|
589
|
+
- `user_ratings`: Get user ratings
|
|
590
|
+
- `user_reviews`: Get user reviews
|
|
591
|
+
|
|
520
592
|
## 🐳 Docker Support
|
|
521
593
|
|
|
522
594
|
Run the CSFD API as a standalone REST service using Docker.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { writeFile } from "node:fs/promises";
|
|
2
|
+
import { csfd } from "./../index.mjs";
|
|
3
|
+
async function runRatingsExport(userId, options) {
|
|
4
|
+
try {
|
|
5
|
+
if (options.format === "letterboxd") {
|
|
6
|
+
csfd.setOptions({ language: "en" });
|
|
7
|
+
}
|
|
8
|
+
console.log(`Fetching ratings for user ${userId} (${options.format.toUpperCase()})...`);
|
|
9
|
+
const ratings = await csfd.userRatings(userId, options.userRatingsOptions);
|
|
10
|
+
console.log(`Fetched ${ratings.length} ratings.`);
|
|
11
|
+
let content = "";
|
|
12
|
+
let fileName = "";
|
|
13
|
+
const escapeCsvField = (value) => {
|
|
14
|
+
const needsQuotes = /[",\n\r]/.test(value);
|
|
15
|
+
const escaped = value.replaceAll('"', '""');
|
|
16
|
+
return needsQuotes ? `"${escaped}"` : escaped;
|
|
17
|
+
};
|
|
18
|
+
if (options.format === "letterboxd") {
|
|
19
|
+
content = [
|
|
20
|
+
"Title,Year,Rating,WatchedDate",
|
|
21
|
+
...ratings.map((r) => {
|
|
22
|
+
const title = escapeCsvField(r.title ?? "");
|
|
23
|
+
const year = r.year ?? "";
|
|
24
|
+
const rating = r.userRating ?? "";
|
|
25
|
+
const watchedDate = escapeCsvField(r.userDate ?? "");
|
|
26
|
+
return `${title},${year},${rating},${watchedDate}`;
|
|
27
|
+
})
|
|
28
|
+
].join("\n");
|
|
29
|
+
fileName = `${userId}-for-letterboxd.csv`;
|
|
30
|
+
} else if (options.format === "json") {
|
|
31
|
+
content = JSON.stringify(ratings, null, 2);
|
|
32
|
+
fileName = `${userId}-ratings.json`;
|
|
33
|
+
} else {
|
|
34
|
+
const headers = ["id", "title", "year", "rating", "date", "type", "url", "colorRating"];
|
|
35
|
+
content = [
|
|
36
|
+
headers.join(","),
|
|
37
|
+
...ratings.map((r) => {
|
|
38
|
+
return [
|
|
39
|
+
r.id,
|
|
40
|
+
escapeCsvField(r.title ?? ""),
|
|
41
|
+
r.year ?? "",
|
|
42
|
+
r.userRating ?? "",
|
|
43
|
+
escapeCsvField(r.userDate ?? ""),
|
|
44
|
+
escapeCsvField(r.type ?? ""),
|
|
45
|
+
escapeCsvField(r.url ?? ""),
|
|
46
|
+
escapeCsvField(r.colorRating ?? "")
|
|
47
|
+
].join(",");
|
|
48
|
+
})
|
|
49
|
+
].join("\n");
|
|
50
|
+
fileName = `${userId}-ratings.csv`;
|
|
51
|
+
}
|
|
52
|
+
await writeFile(fileName, content);
|
|
53
|
+
console.log("Saved in file:", `./${fileName}`);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.error("Error exporting ratings:", error);
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export {
|
|
60
|
+
runRatingsExport
|
|
61
|
+
};
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
4
|
import { z } from "zod";
|
|
5
|
-
import packageJson from "
|
|
6
|
-
import { csfd } from "
|
|
5
|
+
import packageJson from "./../package.json" with { type: "json" };
|
|
6
|
+
import { csfd } from "./../index.mjs";
|
|
7
7
|
const server = new McpServer({
|
|
8
8
|
name: packageJson.name,
|
|
9
9
|
version: packageJson.version
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import "dotenv/config";
|
|
3
3
|
import express from "express";
|
|
4
|
-
import packageJson from "
|
|
5
|
-
import { csfd } from "
|
|
4
|
+
import packageJson from "./../package.json" with { type: "json" };
|
|
5
|
+
import { csfd } from "./../index.mjs";
|
|
6
6
|
const LOG_COLORS = {
|
|
7
7
|
info: "\x1B[36m",
|
|
8
8
|
// cyan
|
package/cli.mjs
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
5
|
+
const __dirname = path.dirname(__filename);
|
|
6
|
+
async function main() {
|
|
7
|
+
const args = process.argv.slice(2);
|
|
8
|
+
const command = args[0];
|
|
9
|
+
switch (command) {
|
|
10
|
+
case "server":
|
|
11
|
+
case "api":
|
|
12
|
+
try {
|
|
13
|
+
await import(path.join(__dirname, "bin/server.mjs"));
|
|
14
|
+
} catch (error) {
|
|
15
|
+
console.error("Failed to start server:", error);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
break;
|
|
19
|
+
case "mcp":
|
|
20
|
+
try {
|
|
21
|
+
await import(path.join(__dirname, "bin/mcp-server.mjs"));
|
|
22
|
+
} catch (error) {
|
|
23
|
+
console.error("Failed to start MCP server:", error);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
break;
|
|
27
|
+
case "export":
|
|
28
|
+
if (args[1] === "ratings") {
|
|
29
|
+
const userIdRaw = args[2];
|
|
30
|
+
const userId = Number(userIdRaw);
|
|
31
|
+
if (!userIdRaw || isNaN(userId)) {
|
|
32
|
+
console.error("Error: Please provide a valid numeric User ID.");
|
|
33
|
+
console.log("Usage: npx node-csfd-api export ratings <userId> [options]");
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
const isLetterboxd = args.includes("--letterboxd");
|
|
37
|
+
const isJson = args.includes("--json");
|
|
38
|
+
const isCsv = args.includes("--csv");
|
|
39
|
+
let format = "csv";
|
|
40
|
+
if (isLetterboxd) {
|
|
41
|
+
format = "letterboxd";
|
|
42
|
+
} else if (isJson) {
|
|
43
|
+
format = "json";
|
|
44
|
+
} else if (isCsv) {
|
|
45
|
+
format = "csv";
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const modulePath = path.join(__dirname, "bin/export-ratings.mjs");
|
|
49
|
+
const { runRatingsExport } = await import(modulePath);
|
|
50
|
+
await runRatingsExport(userId, {
|
|
51
|
+
format,
|
|
52
|
+
userRatingsOptions: {
|
|
53
|
+
// Default behavior for Letterboxd (films only) if not overridden
|
|
54
|
+
includesOnly: isLetterboxd ? ["film"] : void 0,
|
|
55
|
+
allPages: true,
|
|
56
|
+
allPagesDelay: 1e3
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
} catch (error) {
|
|
60
|
+
console.error("Failed to run export:", error);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
} else if (args[1] === "letterboxd") {
|
|
64
|
+
console.warn(
|
|
65
|
+
'Deprecation Warning: "export letterboxd" is deprecated. Please use "export ratings <id> --letterboxd" instead.'
|
|
66
|
+
);
|
|
67
|
+
console.log("Usage: npx node-csfd-api export ratings <userId> --letterboxd");
|
|
68
|
+
process.exit(1);
|
|
69
|
+
} else {
|
|
70
|
+
console.error(`Unknown export target: ${args[1]}`);
|
|
71
|
+
printUsage();
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
break;
|
|
75
|
+
case "help":
|
|
76
|
+
case "--help":
|
|
77
|
+
case "-h":
|
|
78
|
+
default:
|
|
79
|
+
printUsage();
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function printUsage() {
|
|
84
|
+
console.log(`
|
|
85
|
+
Usage: npx node-csfd-api <command> [options]
|
|
86
|
+
|
|
87
|
+
Commands:
|
|
88
|
+
server, api Start the REST API server
|
|
89
|
+
mcp Start the MCP (Model Context Protocol) server for AI agents
|
|
90
|
+
export ratings <userId> Export user ratings to CSV (default), JSON, or Letterboxd format
|
|
91
|
+
Options:
|
|
92
|
+
--csv Export to CSV format (default)
|
|
93
|
+
--json Export to JSON format
|
|
94
|
+
--letterboxd Export to Letterboxd-compatible CSV format
|
|
95
|
+
help Show this help message
|
|
96
|
+
`);
|
|
97
|
+
}
|
|
98
|
+
main().catch((error) => {
|
|
99
|
+
console.error("Fatal error:", error);
|
|
100
|
+
process.exit(1);
|
|
101
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-csfd-api",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.0-next.0",
|
|
4
4
|
"description": "ČSFD API in JavaScript. Amazing NPM library for scrapping csfd.cz :)",
|
|
5
5
|
"author": "BART! <bart@bartweb.cz>",
|
|
6
6
|
"publishConfig": {
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
12
12
|
"cross-fetch": "^4.1.0",
|
|
13
|
-
"
|
|
13
|
+
"dotenv": "^17.3.1",
|
|
14
14
|
"express": "^5.2.1",
|
|
15
|
-
"
|
|
15
|
+
"node-html-parser": "^7.0.2",
|
|
16
16
|
"zod": "^4.3.6"
|
|
17
17
|
},
|
|
18
18
|
"repository": {
|
|
@@ -51,8 +51,7 @@
|
|
|
51
51
|
"./package.json": "./package.json"
|
|
52
52
|
},
|
|
53
53
|
"bin": {
|
|
54
|
-
"csfd-
|
|
55
|
-
"csfd-server": "server.mjs"
|
|
54
|
+
"node-csfd-api": "cli.mjs"
|
|
56
55
|
},
|
|
57
56
|
"sideEffects": false
|
|
58
57
|
}
|