facebook-comments-client 0.1.4

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 kenesuino
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,225 @@
1
+ # facebook-comments-client
2
+
3
+ Fetch comments from Facebook posts — including posts inside Facebook Groups where your account already has legitimate access — using an authorized Playwright session. Returns clean, normalized JSON that is independent of Facebook's internal response structure.
4
+
5
+ This is a **focused library**. It contains no database, no Supabase, no queues, no cron jobs, and no backend server. Its sole responsibility:
6
+
7
+ ```
8
+ Facebook Post URL → Authenticate/Reuse Authorized Session → Fetch Available Comments → Return Clean Structured JSON
9
+ ```
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install facebook-comments-client
15
+ # The library drives a real browser via Playwright:
16
+ npx playwright install chromium
17
+ ```
18
+
19
+ Requirements: Node.js 20+.
20
+
21
+ ## Quick start
22
+
23
+ ```ts
24
+ import { FacebookCommentsClient } from "facebook-comments-client";
25
+
26
+ const client = new FacebookCommentsClient({
27
+ session: {
28
+ type: "file",
29
+ path: "./facebook-session.json"
30
+ }
31
+ });
32
+
33
+ const result = await client.getComments({
34
+ url: "https://www.facebook.com/groups/GROUP_ID/posts/POST_ID/",
35
+ maxComments: 100,
36
+ includeReplies: true
37
+ });
38
+
39
+ console.log(result.comments);
40
+ await client.close();
41
+ ```
42
+
43
+ ## Interactive login
44
+
45
+ The library never enters credentials for you. It opens a visible browser, you log in manually, and the authorized session is exported:
46
+
47
+ ```ts
48
+ import { FacebookCommentsClient } from "facebook-comments-client";
49
+
50
+ await FacebookCommentsClient.login({
51
+ outputPath: "./facebook-session.json"
52
+ });
53
+ ```
54
+
55
+ Or from the CLI:
56
+
57
+ ```bash
58
+ npx fb-comments login --output ./facebook-session.json
59
+ ```
60
+
61
+ The helper waits for the Facebook `c_user` cookie to appear (up to 5 minutes by default), saves the Playwright storage state, and closes the browser.
62
+
63
+ ## Session file usage
64
+
65
+ ```ts
66
+ const client = new FacebookCommentsClient({
67
+ session: { type: "file", path: "./facebook-session.json" }
68
+ });
69
+ ```
70
+
71
+ `type: "storage"` is accepted as an alias. The file is a standard Playwright storage state (as produced by `context.storageState()` and by the login helper above).
72
+
73
+ ## Environment variable usage
74
+
75
+ Handy for deployments. Encode a storage state once:
76
+
77
+ ```ts
78
+ const encoded = Buffer.from(JSON.stringify(storageState)).toString("base64");
79
+ ```
80
+
81
+ Then configure the client:
82
+
83
+ ```ts
84
+ const client = new FacebookCommentsClient({
85
+ session: { type: "env", envKey: "FACEBOOK_STORAGE_STATE" }
86
+ });
87
+ ```
88
+
89
+ The variable is base64(-url) decoded, JSON parsed, and validated with Zod before a browser context is created. You can also pass a plain cookie array via `{ type: "cookies", cookies }` or an inline object via `{ type: "state", state }`.
90
+
91
+ ## Fetching comments
92
+
93
+ ```ts
94
+ const result = await client.getComments({
95
+ url: "https://www.facebook.com/groups/123/posts/456/",
96
+ maxComments: 100, // default 50
97
+ includeReplies: true, // default false
98
+ maxReplies: 20, // default 20, per comment
99
+ timeout: 30000, // navigation timeout ms
100
+ headless: true // override client default
101
+ });
102
+ ```
103
+
104
+ Returns a normalized shape:
105
+
106
+ ```ts
107
+ {
108
+ post: { id: "456", url: "https://www.facebook.com/groups/123/posts/456/" },
109
+ comments: [
110
+ {
111
+ id: "comment_123" | null,
112
+ author: { id: "user_123" | null, name: "John Doe" | null, profileUrl: "..." | null },
113
+ message: "Hello!",
114
+ createdAt: "2026-08-28T10:30:00.000Z" | null,
115
+ reactions: { total: 5 | null },
116
+ parentId: null,
117
+ replies: [ /* same shape */ ]
118
+ }
119
+ ],
120
+ pagination: { hasMore: false, nextCursor: null }
121
+ }
122
+ ```
123
+
124
+ Every field degrades to `null` instead of crashing when Facebook's markup differs — missing profile URLs, unparseable timestamps, unavailable reaction counts, etc.
125
+
126
+ ## Fetching replies
127
+
128
+ Set `includeReplies: true` (and optionally `maxReplies`). The fetcher expands "View more replies" controls (bounded) and nests replies under their parent comment with `parentId` set.
129
+
130
+ ## Pagination
131
+
132
+ ```ts
133
+ const page1 = await client.getComments({ url, maxComments: 25 });
134
+
135
+ if (page1.pagination.hasMore) {
136
+ const page2 = await client.getComments({
137
+ url,
138
+ maxComments: 25,
139
+ cursor: page1.pagination.nextCursor
140
+ });
141
+ }
142
+ ```
143
+
144
+ The cursor is an opaque base64url token — an offset into the comment stream. No Facebook internals leak into your code.
145
+
146
+ ## Error handling
147
+
148
+ ```ts
149
+ import {
150
+ FacebookClientError,
151
+ FacebookAuthenticationError,
152
+ FacebookSessionExpiredError,
153
+ FacebookPostNotFoundError,
154
+ FacebookAccessDeniedError,
155
+ FacebookExtractionError
156
+ } from "facebook-comments-client";
157
+
158
+ try {
159
+ const { comments } = await client.getComments({ url: postUrl });
160
+ } catch (error) {
161
+ if (error instanceof FacebookSessionExpiredError) {
162
+ console.log("Facebook session needs to be refreshed.");
163
+ }
164
+ }
165
+ ```
166
+
167
+ Every error carries a stable `code` (`FB_AUTH`, `FB_SESSION_EXPIRED`, `FB_POST_NOT_FOUND`, `FB_ACCESS_DENIED`, `FB_EXTRACTION`, `FB_CLIENT`), a safe human-readable message, and a `retryable` boolean. Error messages never contain cookies or storage-state content. See [docs/errors.md](docs/errors.md).
168
+
169
+ ## Security notes
170
+
171
+ - **Treat session files as passwords.** A storage state grants full access to the logged-in account.
172
+ - The library never logs cookie values, tokens, or storage states; its logger redacts sensitive keys, and error messages are scrubbed.
173
+ - `facebook-session.json`, `*.storage-state.json`, and `.env` are in `.gitignore` — never commit them.
174
+ - Environment variables are convenient for deployment, but session expiration and secret handling are your responsibility. Prefer your platform's secret manager over plaintext `.env` files.
175
+ - Use sessions belonging to accounts that legitimately have access to the requested content. This library does not bypass logins, CAPTCHAs, or access controls, and contains no stealth, fingerprint-spoofing, proxy-rotation, or restriction-evasion features.
176
+
177
+ ## Session refresh instructions
178
+
179
+ Facebook sessions expire (typically days to weeks):
180
+
181
+ 1. `client.validateSession()` returns `{ valid: true, authenticated: false }`, or `getComments` throws `FacebookSessionExpiredError`.
182
+ 2. Re-run the login helper: `await FacebookCommentsClient.login({ outputPath })` (or `fb-comments login`).
183
+ 3. If you use the env-var provider, re-encode the fresh state and update the variable.
184
+
185
+ ## Known limitations
186
+
187
+ - **Facebook markup is unstable by nature.** All selectors and text patterns live in [`src/config/selectors.ts`](src/config/selectors.ts); when extraction quality degrades, that one file is the place to look. Extraction issues throw `FacebookExtractionError` rather than returning garbage silently.
188
+ - The structured-data extractor is opportunistic; on most modern pages the accessibility-based DOM extractor does the real work.
189
+ - Timestamps shown as relative times ("2h") are approximations computed from fetch time.
190
+ - Comment ids are frequently absent in the DOM and are returned as `null`.
191
+ - Localization: text patterns currently target English UI text. Non-English Facebook UIs may need additional patterns in `selectors.ts`.
192
+ - Very long threads (hundreds of comments) require pagination; the load-more loop is intentionally bounded.
193
+ - Integration tests against live Facebook are opt-in (`tests/integration/live.test.ts`) and need `FB_TEST_URL` + `FACEBOOK_STORAGE_STATE`.
194
+
195
+ ## CLI
196
+
197
+ ```bash
198
+ # Login (manual, headed browser)
199
+ fb-comments login --output ./facebook-session.json
200
+
201
+ # Fetch comments
202
+ fb-comments comments "https://www.facebook.com/groups/123/posts/456/" --replies --limit 100
203
+
204
+ # Machine-readable output
205
+ fb-comments comments POST_URL --json
206
+
207
+ # Session from env var
208
+ FACEBOOK_STORAGE_STATE="..." fb-comments comments POST_URL
209
+ ```
210
+
211
+ ## Development
212
+
213
+ ```bash
214
+ npm install
215
+ npx playwright install chromium
216
+ npm test # unit + fixture tests (offline, no Facebook login needed)
217
+ npm run build # dist/ ESM + CJS + types + CLI
218
+ npm run lint
219
+ ```
220
+
221
+ See [docs/api.md](docs/api.md) for the full API surface, [docs/authentication.md](docs/authentication.md) and [docs/session-management.md](docs/session-management.md) for session details.
222
+
223
+ ## License
224
+
225
+ MIT