bb-fca 2.0.18 → 2.0.19

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.
@@ -720,6 +720,48 @@ export interface API {
720
720
  callback?: Callback<CommentResult>,
721
721
  ): Promise<CommentResult>;
722
722
 
723
+ /**
724
+ * Upload and publish a video as a Facebook Reel.
725
+ * Full flow: upload video → copyright check → publish.
726
+ *
727
+ * @param options - The reel options.
728
+ * @param options.videoPath - File path to the video file.
729
+ * @param options.message - Caption text for the reel.
730
+ * @param options.privacy - Privacy: "EVERYONE", "FRIENDS", or "SELF". Default: "EVERYONE".
731
+ * @param options.skipCopyrightCheck - Skip copyright check polling. Default: false.
732
+ * @param options.copyrightCheckTimeout - Max time for copyright check (ms). Default: 60000.
733
+ * @param options.copyrightCheckInterval - Polling interval for copyright check (ms). Default: 2000.
734
+ * @param callback - Optional callback function.
735
+ * @returns A promise that resolves with the reel's information.
736
+ */
737
+ createReel(
738
+ options: {
739
+ videoPath: string;
740
+ message?: string;
741
+ privacy?: 'EVERYONE' | 'FRIENDS' | 'SELF';
742
+ skipCopyrightCheck?: boolean;
743
+ copyrightCheckTimeout?: number;
744
+ copyrightCheckInterval?: number;
745
+ },
746
+ callback?: Callback<{
747
+ success: boolean;
748
+ postID: string | null;
749
+ storyID: string | null;
750
+ videoID: string;
751
+ publishingFlow: string | null;
752
+ composerSessionId: string;
753
+ data: any;
754
+ }>,
755
+ ): Promise<{
756
+ success: boolean;
757
+ postID: string | null;
758
+ storyID: string | null;
759
+ videoID: string;
760
+ publishingFlow: string | null;
761
+ composerSessionId: string;
762
+ data: any;
763
+ }>;
764
+
723
765
  /** Share a Facebook post. */
724
766
  share(
725
767
  text: string,
@@ -19,8 +19,19 @@ let proxyAgent: any = null;
19
19
  // Request interceptor: attach cookies from jar + proxy agent
20
20
  (client.interceptors as any).request.use((config: any) => {
21
21
  const url = config.url || '';
22
+ const currentJar = config.jar || jar;
22
23
  try {
23
- const cookieString = jar.getCookieStringSync(url);
24
+ let cookieString = currentJar.getCookieStringSync(url);
25
+
26
+ // Cross-domain fallback: if URL is a facebook.com subdomain, ensure we send facebook.com cookies
27
+ if (url.includes('facebook.com') || url.includes('messenger.com')) {
28
+ const baseCookies = currentJar.getCookieStringSync('https://www.facebook.com');
29
+ if (baseCookies) {
30
+ // Merge cookies if necessary, but usually baseCookies is sufficient for subdomains
31
+ cookieString = cookieString ? `${cookieString}; ${baseCookies}` : baseCookies;
32
+ }
33
+ }
34
+
24
35
  if (cookieString) {
25
36
  config.headers = config.headers || {};
26
37
  config.headers['Cookie'] = cookieString;
@@ -41,11 +52,15 @@ let proxyAgent: any = null;
41
52
  // Response interceptor: save set-cookie headers back to jar
42
53
  (client.interceptors as any).response.use((response: any) => {
43
54
  const url = response.config.url || '';
55
+ const currentJar = response.config.jar || jar;
44
56
  const setCookieHeaders = response.headers['set-cookie'];
45
57
  if (setCookieHeaders && Array.isArray(setCookieHeaders)) {
46
58
  for (const cookie of setCookieHeaders) {
47
59
  try {
48
- jar.setCookieSync(cookie, url);
60
+ currentJar.setCookieSync(cookie, url);
61
+ if (url.includes('facebook.com')) {
62
+ currentJar.setCookieSync(cookie, 'https://www.facebook.com');
63
+ }
49
64
  } catch (e) {
50
65
  // Ignore invalid cookies
51
66
  }
@@ -56,11 +71,15 @@ let proxyAgent: any = null;
56
71
  // Also save cookies from error responses
57
72
  if (error.response) {
58
73
  const url = error.response.config?.url || '';
74
+ const currentJar = error.response.config?.jar || jar;
59
75
  const setCookieHeaders = error.response.headers?.['set-cookie'];
60
76
  if (setCookieHeaders && Array.isArray(setCookieHeaders)) {
61
77
  for (const cookie of setCookieHeaders) {
62
78
  try {
63
- jar.setCookieSync(cookie, url);
79
+ currentJar.setCookieSync(cookie, url);
80
+ if (url.includes('facebook.com')) {
81
+ currentJar.setCookieSync(cookie, 'https://www.facebook.com');
82
+ }
64
83
  } catch (e) {
65
84
  // Ignore
66
85
  }
@@ -148,6 +167,7 @@ export async function get(
148
167
  timeout: 60000,
149
168
  params: qs,
150
169
  validateStatus: (status: number) => status >= 200 && status < 600,
170
+ jar: reqJar,
151
171
  };
152
172
  return requestWithRetry(async () => await client.get(url, config));
153
173
  }
@@ -186,6 +206,7 @@ export async function post(
186
206
  headers,
187
207
  timeout: 60000,
188
208
  validateStatus: (status: number) => status >= 200 && status < 600,
209
+ jar: reqJar,
189
210
  };
190
211
  return requestWithRetry(async () => await client.post(url, data, config));
191
212
  }
@@ -214,6 +235,7 @@ export async function postFormData(
214
235
  timeout: 60000,
215
236
  params: qs,
216
237
  validateStatus: (status: number) => status >= 200 && status < 600,
238
+ jar: reqJar,
217
239
  };
218
240
  return requestWithRetry(async () => await client.post(url, formData, config));
219
241
  }
@@ -232,6 +254,7 @@ export async function postRaw(
232
254
  maxContentLength: Infinity,
233
255
  maxBodyLength: Infinity,
234
256
  validateStatus: (status: number) => status >= 200 && status < 600,
257
+ jar: reqJar,
235
258
  };
236
259
  return requestWithRetry(async () => await client.post(url, body, config));
237
260
  }