bb-fca 2.0.1 → 2.0.3
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/dist/deltas/apis/posting/friend.js +136 -3
- package/dist/deltas/apis/posting/friend.js.map +1 -1
- package/dist/deltas/apis/users/changeBio.js +61 -0
- package/dist/deltas/apis/users/changeBio.js.map +1 -0
- package/dist/deltas/apis/users/changeName.js +134 -0
- package/dist/deltas/apis/users/changeName.js.map +1 -0
- package/dist/deltas/apis/users/uploadAvatar.js +174 -0
- package/dist/deltas/apis/users/uploadAvatar.js.map +1 -0
- package/dist/deltas/apis/users/uploadCover.js +165 -0
- package/dist/deltas/apis/users/uploadCover.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/types/deltas/apis/posting/friend.d.ts +24 -0
- package/dist/types/deltas/apis/users/changeBio.d.ts +10 -0
- package/dist/types/deltas/apis/users/changeName.d.ts +15 -0
- package/dist/types/deltas/apis/users/uploadAvatar.d.ts +11 -0
- package/dist/types/deltas/apis/users/uploadCover.d.ts +15 -0
- package/package.json +1 -1
- package/src/deltas/apis/posting/friend.ts +156 -14
- package/src/deltas/apis/users/changeBio.ts +68 -0
- package/src/deltas/apis/users/changeName.ts +151 -0
- package/src/deltas/apis/users/uploadAvatar.ts +172 -0
- package/src/deltas/apis/users/uploadCover.ts +167 -0
- package/src/types/index.d.ts +22 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.default = default_1;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const utils = require("../../../utils");
|
|
39
|
+
/**
|
|
40
|
+
* @ChoruOfficial
|
|
41
|
+
* @description A module for uploading a new cover photo (ảnh bìa) to Facebook.
|
|
42
|
+
* Two-step process:
|
|
43
|
+
* 1. Upload: sends the image file via multipart/form-data to /profile/cover/comet_upload/
|
|
44
|
+
* 2. Confirm: calls ProfileCometCoverPhotoUpdateMutation to apply the photo as cover
|
|
45
|
+
* @param {Object} defaultFuncs The default functions provided by the API wrapper.
|
|
46
|
+
* @param {Object} api The full API object.
|
|
47
|
+
* @param {Object} ctx The context object containing the user's session state.
|
|
48
|
+
* @returns {Function} An async function that uploads a cover photo.
|
|
49
|
+
*/
|
|
50
|
+
function default_1(defaultFuncs, api, ctx) {
|
|
51
|
+
/**
|
|
52
|
+
* Step 2 — Confirm the uploaded photo as cover via ProfileCometCoverPhotoUpdateMutation.
|
|
53
|
+
* @private
|
|
54
|
+
* @param {string} photoID The ID of the uploaded photo.
|
|
55
|
+
* @param {string} profileID The profile ID.
|
|
56
|
+
* @param {{ x: number, y: number }} [focus] Optional focus point. Defaults to center {x:0.5, y:0.5}.
|
|
57
|
+
*/
|
|
58
|
+
async function setCoverPhoto(photoID, profileID, focus = { x: 0.5, y: 0.5 }) {
|
|
59
|
+
const variables = {
|
|
60
|
+
input: {
|
|
61
|
+
attribution_id_v2: `ProfileCometAboutTabRoot.react,comet.profile.collection.about,via_cold_start,${Date.now()},670164,,,`,
|
|
62
|
+
cover_photo_id: photoID,
|
|
63
|
+
focus: focus,
|
|
64
|
+
target_user_id: profileID,
|
|
65
|
+
actor_id: ctx.userID,
|
|
66
|
+
client_mutation_id: Math.floor(Math.random() * 10 + 1).toString(),
|
|
67
|
+
},
|
|
68
|
+
scale: 1,
|
|
69
|
+
contextualProfileContext: null,
|
|
70
|
+
};
|
|
71
|
+
const form = {
|
|
72
|
+
av: ctx.userID,
|
|
73
|
+
__user: ctx.userID,
|
|
74
|
+
__a: '1',
|
|
75
|
+
fb_dtsg: ctx.fb_dtsg,
|
|
76
|
+
jazoest: ctx.jazoest,
|
|
77
|
+
lsd: ctx.lsd,
|
|
78
|
+
fb_api_caller_class: 'RelayModern',
|
|
79
|
+
fb_api_req_friendly_name: 'ProfileCometCoverPhotoUpdateMutation',
|
|
80
|
+
variables: JSON.stringify(variables),
|
|
81
|
+
server_timestamps: 'true',
|
|
82
|
+
doc_id: '31388044007461211',
|
|
83
|
+
};
|
|
84
|
+
const res = await defaultFuncs.post('https://www.facebook.com/api/graphql/', ctx.jar, form, {});
|
|
85
|
+
if (res.data.errors)
|
|
86
|
+
throw new Error(JSON.stringify(res.data.errors));
|
|
87
|
+
return res.data;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Uploads a new cover photo (ảnh bìa) for the logged-in user, then confirms it as the cover.
|
|
91
|
+
* @async
|
|
92
|
+
* @param {string} imagePath The local file path to the image to upload.
|
|
93
|
+
* @param {string} [profileID=ctx.userID] The profile ID. Defaults to the logged-in user.
|
|
94
|
+
* @param {{ x: number, y: number }} [focus] Optional focus point for cropping. Defaults to {x:0.5, y:0.5}.
|
|
95
|
+
* @param {Function} [callback] Optional callback function.
|
|
96
|
+
* @returns {Promise<Object>} A promise that resolves with { upload, set } data on success.
|
|
97
|
+
* @throws {Error} If the imagePath is missing, the file does not exist, or any step fails.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* await api.uploadCover('/path/to/cover.jpg');
|
|
101
|
+
* await api.uploadCover('/path/to/cover.jpg', '61588408996667');
|
|
102
|
+
* await api.uploadCover('/path/to/cover.jpg', ctx.userID, { x: 0.5, y: 0.3 });
|
|
103
|
+
*/
|
|
104
|
+
return async function uploadCover(imagePath, profileID = ctx.userID, focus = { x: 0.5, y: 0.5 }, callback) {
|
|
105
|
+
let resolveFunc = function () { };
|
|
106
|
+
let rejectFunc = function () { };
|
|
107
|
+
const returnPromise = new Promise(function (resolve, reject) {
|
|
108
|
+
resolveFunc = resolve;
|
|
109
|
+
rejectFunc = reject;
|
|
110
|
+
});
|
|
111
|
+
callback =
|
|
112
|
+
callback ||
|
|
113
|
+
function (err, data) {
|
|
114
|
+
if (err)
|
|
115
|
+
return rejectFunc(err);
|
|
116
|
+
resolveFunc(data);
|
|
117
|
+
};
|
|
118
|
+
try {
|
|
119
|
+
if (!imagePath)
|
|
120
|
+
throw new Error('imagePath is required.');
|
|
121
|
+
if (typeof imagePath !== 'string')
|
|
122
|
+
throw new Error('imagePath must be a string.');
|
|
123
|
+
if (!fs.existsSync(imagePath))
|
|
124
|
+
throw new Error(`File not found: ${imagePath}`);
|
|
125
|
+
// Step 1: Upload the photo
|
|
126
|
+
const photoStream = fs.createReadStream(imagePath);
|
|
127
|
+
const url = new URL('https://www.facebook.com/profile/cover/comet_upload/');
|
|
128
|
+
url.searchParams.append('profile_id', profileID);
|
|
129
|
+
url.searchParams.append('av', ctx.userID);
|
|
130
|
+
url.searchParams.append('__aaid', '0');
|
|
131
|
+
url.searchParams.append('__user', ctx.userID);
|
|
132
|
+
url.searchParams.append('__a', '1');
|
|
133
|
+
url.searchParams.append('fb_dtsg', ctx.fb_dtsg);
|
|
134
|
+
url.searchParams.append('jazoest', ctx.jazoest);
|
|
135
|
+
url.searchParams.append('lsd', ctx.lsd);
|
|
136
|
+
const uploadResponse = await utils.postFormData(url.toString(), ctx.jar, { file: photoStream }, ctx.globalOptions, ctx);
|
|
137
|
+
const uploadResult = JSON.parse(uploadResponse.body.toString().replace(/^for \(;;\);/, ''));
|
|
138
|
+
if (uploadResult.error || uploadResult.errors) {
|
|
139
|
+
throw new Error(JSON.stringify(uploadResult.error || uploadResult.errors));
|
|
140
|
+
}
|
|
141
|
+
const photoID = uploadResult.payload?.fbid ||
|
|
142
|
+
uploadResult.payload?.photoID ||
|
|
143
|
+
uploadResult.payload?.photo_id ||
|
|
144
|
+
null;
|
|
145
|
+
if (!photoID) {
|
|
146
|
+
throw new Error('Upload succeeded but could not extract photo ID from response.');
|
|
147
|
+
}
|
|
148
|
+
// Step 2: Confirm as cover photo
|
|
149
|
+
const setResult = await setCoverPhoto(photoID, profileID, focus);
|
|
150
|
+
const result = {
|
|
151
|
+
success: true,
|
|
152
|
+
photoID: photoID,
|
|
153
|
+
upload: uploadResult,
|
|
154
|
+
set: setResult,
|
|
155
|
+
};
|
|
156
|
+
callback(null, result);
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
utils.error('uploadCover', err);
|
|
160
|
+
callback(err);
|
|
161
|
+
}
|
|
162
|
+
return returnPromise;
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=uploadCover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uploadCover.js","sourceRoot":"","sources":["../../../../src/deltas/apis/users/uploadCover.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -123,6 +123,13 @@ export interface UploadPhotoResult {
|
|
|
123
123
|
data: any;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
export interface ChangeNameResult {
|
|
127
|
+
/** Raw preview response data from AccountsCenter name validation query. */
|
|
128
|
+
preview: any;
|
|
129
|
+
/** Raw mutation result data confirming the name change. */
|
|
130
|
+
result: any;
|
|
131
|
+
}
|
|
132
|
+
|
|
126
133
|
export interface CurrentFriendInfo {
|
|
127
134
|
userID: string;
|
|
128
135
|
name: string;
|
|
@@ -637,6 +644,8 @@ export interface API {
|
|
|
637
644
|
getCurrentFriends(
|
|
638
645
|
callback?: Callback<CurrentFriendInfo[]>,
|
|
639
646
|
): Promise<CurrentFriendInfo[]>;
|
|
647
|
+
/** Send a friend request to a user by their ID via their profile page. */
|
|
648
|
+
add(userID: UserID, callback?: Callback): Promise<any>;
|
|
640
649
|
suggest: {
|
|
641
650
|
list(
|
|
642
651
|
limit?: number,
|
|
@@ -690,6 +699,19 @@ export interface API {
|
|
|
690
699
|
|
|
691
700
|
// ── Session ────────────────────────────────────────────────────
|
|
692
701
|
|
|
702
|
+
/**
|
|
703
|
+
* Changes the Facebook account display name (two-step: preview then confirm).
|
|
704
|
+
* Calls AccountsCenter GraphQL API.
|
|
705
|
+
* @param firstName New first name.
|
|
706
|
+
* @param lastName New last name.
|
|
707
|
+
* @param middleName Optional middle name (default: empty string).
|
|
708
|
+
*/
|
|
709
|
+
changeName(
|
|
710
|
+
firstName: string,
|
|
711
|
+
lastName: string,
|
|
712
|
+
middleName?: string,
|
|
713
|
+
): Promise<ChangeNameResult>;
|
|
714
|
+
|
|
693
715
|
/** Log out and invalidate the current session. */
|
|
694
716
|
logout(callback?: (err: any) => void): Promise<void>;
|
|
695
717
|
|
|
@@ -49,6 +49,30 @@ export default function (defaultFuncs: any, api: any, ctx: any): {
|
|
|
49
49
|
* @description Functions for managing friend suggestions.
|
|
50
50
|
*/
|
|
51
51
|
getCurrentFriends: (callback?: any) => Promise<any>;
|
|
52
|
+
/**
|
|
53
|
+
* Sends a friend request to a user by their ID (via Profile Button channel).
|
|
54
|
+
* @async
|
|
55
|
+
* @param {string} userID The ID of the user to add as a friend.
|
|
56
|
+
* @returns {Promise<Object>} A promise that resolves to the API response data on success.
|
|
57
|
+
* @throws {Error} If the userID is missing or the API request fails.
|
|
58
|
+
*/
|
|
59
|
+
add: (userID: any) => Promise<any>;
|
|
60
|
+
/**
|
|
61
|
+
* Cancels a sent friend request (hủy lời mời kết bạn đã gửi).
|
|
62
|
+
* @async
|
|
63
|
+
* @param {string} userID The ID of the user whose friend request is to be cancelled.
|
|
64
|
+
* @returns {Promise<Object>} A promise that resolves to the API response data upon successful cancellation.
|
|
65
|
+
* @throws {Error} If the userID is missing or the API request fails.
|
|
66
|
+
*/
|
|
67
|
+
cancelRequest: (userID: any) => Promise<any>;
|
|
68
|
+
/**
|
|
69
|
+
* Unfriends a user (hủy kết bạn).
|
|
70
|
+
* @async
|
|
71
|
+
* @param {string} userID The ID of the user to unfriend.
|
|
72
|
+
* @returns {Promise<Object>} A promise that resolves to the API response data upon successful unfriending.
|
|
73
|
+
* @throws {Error} If the userID is missing or the API request fails.
|
|
74
|
+
*/
|
|
75
|
+
unfriend: (userID: any) => Promise<any>;
|
|
52
76
|
suggest: {
|
|
53
77
|
/**
|
|
54
78
|
* Fetches a list of suggested friends (People You May Know).
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ChoruOfficial
|
|
3
|
+
* @description A module for updating the Facebook profile bio (tiểu sử).
|
|
4
|
+
* Calls ProfileCometBioFieldSaveMutation via /api/graphql/.
|
|
5
|
+
* @param {Object} defaultFuncs The default functions provided by the API wrapper.
|
|
6
|
+
* @param {Object} api The full API object.
|
|
7
|
+
* @param {Object} ctx The context object containing the user's session state.
|
|
8
|
+
* @returns {Function} An async function that updates the account's bio.
|
|
9
|
+
*/
|
|
10
|
+
export default function (defaultFuncs: any, api: any, ctx: any): (bio: string) => Promise<any>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ChoruOfficial
|
|
3
|
+
* @description A module for changing the Facebook account display name via AccountsCenter.
|
|
4
|
+
* The name change process is two-step:
|
|
5
|
+
* 1. Preview: validate and preview the new name
|
|
6
|
+
* 2. Confirm: apply the name change mutation
|
|
7
|
+
* @param {Object} defaultFuncs The default functions provided by the API wrapper.
|
|
8
|
+
* @param {Object} api The full API object.
|
|
9
|
+
* @param {Object} ctx The context object containing the user's session state.
|
|
10
|
+
* @returns {Function} An async function that changes the account's display name.
|
|
11
|
+
*/
|
|
12
|
+
export default function (defaultFuncs: any, api: any, ctx: any): (firstName: string, lastName: string, middleName?: string) => Promise<{
|
|
13
|
+
preview: any;
|
|
14
|
+
result: any;
|
|
15
|
+
}>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description A module for uploading a new profile picture (avatar) to Facebook.
|
|
3
|
+
* Two-step process:
|
|
4
|
+
* 1. Upload: sends the image file via multipart/form-data to /profile/picture/upload/
|
|
5
|
+
* 2. Set: calls ProfileCometProfilePictureSetMutation to apply the photo as avatar with optional caption
|
|
6
|
+
* @param {Object} defaultFuncs The default functions provided by the API wrapper.
|
|
7
|
+
* @param {Object} api The full API object.
|
|
8
|
+
* @param {Object} ctx The context object containing the user's session state.
|
|
9
|
+
* @returns {Function} An async function that uploads an avatar image.
|
|
10
|
+
*/
|
|
11
|
+
export default function (defaultFuncs: any, api: any, ctx: any): (imagePath: string, caption?: string, profileID?: string, callback?: any) => Promise<any>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ChoruOfficial
|
|
3
|
+
* @description A module for uploading a new cover photo (ảnh bìa) to Facebook.
|
|
4
|
+
* Two-step process:
|
|
5
|
+
* 1. Upload: sends the image file via multipart/form-data to /profile/cover/comet_upload/
|
|
6
|
+
* 2. Confirm: calls ProfileCometCoverPhotoUpdateMutation to apply the photo as cover
|
|
7
|
+
* @param {Object} defaultFuncs The default functions provided by the API wrapper.
|
|
8
|
+
* @param {Object} api The full API object.
|
|
9
|
+
* @param {Object} ctx The context object containing the user's session state.
|
|
10
|
+
* @returns {Function} An async function that uploads a cover photo.
|
|
11
|
+
*/
|
|
12
|
+
export default function (defaultFuncs: any, api: any, ctx: any): (imagePath: string, profileID?: string, focus?: {
|
|
13
|
+
x: number;
|
|
14
|
+
y: number;
|
|
15
|
+
}, callback?: any) => Promise<any>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bb-fca",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3",
|
|
4
4
|
"description": "BB-FCA is a powerful and user-friendly Facebook Chat API wrapper for Node.js, designed to simplify the process of creating chatbots and automating interactions on Facebook Messenger. With BB-FCA, developers can easily send messages, manage conversations, and interact with the Facebook Messenger platform using a simple and intuitive API.",
|
|
5
5
|
"main": "dist/core/client.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -8,7 +8,7 @@ import utils = require('../../../utils');
|
|
|
8
8
|
* @param {Object} ctx The context object containing the user's session state (e.g., userID, jar, fb_dtsg).
|
|
9
9
|
* @returns {Object} A `friendModule` object with methods for friend interactions.
|
|
10
10
|
*/
|
|
11
|
-
export default function(defaultFuncs: any, api: any, ctx: any) {
|
|
11
|
+
export default function (defaultFuncs: any, api: any, ctx: any) {
|
|
12
12
|
/**
|
|
13
13
|
* A private helper function to standardize friend data from various GraphQL endpoints.
|
|
14
14
|
* @private
|
|
@@ -60,7 +60,7 @@ export default function(defaultFuncs: any, api: any, ctx: any) {
|
|
|
60
60
|
* @returns {Promise<Array<Object>>} A promise that resolves to an array of friend request objects.
|
|
61
61
|
* @throws {Error} If the API request fails or HTML parsing fails.
|
|
62
62
|
*/
|
|
63
|
-
requests: async function() {
|
|
63
|
+
requests: async function () {
|
|
64
64
|
try {
|
|
65
65
|
const url = 'https://www.facebook.com/friends/requests';
|
|
66
66
|
const resData = await utils.get(
|
|
@@ -85,7 +85,7 @@ export default function(defaultFuncs: any, api: any, ctx: any) {
|
|
|
85
85
|
* @returns {Promise<Object>} A promise that resolves to the API response data upon successful acceptance.
|
|
86
86
|
* @throws {Error} If the identifier is missing, the user is not found in requests, or the API call fails.
|
|
87
87
|
*/
|
|
88
|
-
accept: async function(identifier) {
|
|
88
|
+
accept: async function (identifier) {
|
|
89
89
|
try {
|
|
90
90
|
if (!identifier) throw new Error('A name or user ID is required.');
|
|
91
91
|
let targetUserID = identifier;
|
|
@@ -102,12 +102,17 @@ export default function(defaultFuncs: any, api: any, ctx: any) {
|
|
|
102
102
|
}
|
|
103
103
|
const variables = {
|
|
104
104
|
input: {
|
|
105
|
+
click_correlation_id: Date.now().toString(),
|
|
106
|
+
click_proof_validation_result: '{"validated":true}',
|
|
105
107
|
friend_requester_id: targetUserID,
|
|
106
|
-
friending_channel: '
|
|
108
|
+
friending_channel: 'FRIENDS_HOME_REQUESTS',
|
|
109
|
+
warn_ack: false,
|
|
107
110
|
actor_id: ctx.userID,
|
|
108
111
|
client_mutation_id: Math.floor(Math.random() * 10 + 1).toString(),
|
|
109
112
|
},
|
|
110
|
-
scale:
|
|
113
|
+
scale: 1,
|
|
114
|
+
refresh_num: 0,
|
|
115
|
+
should_fix_banner: true,
|
|
111
116
|
};
|
|
112
117
|
const form = {
|
|
113
118
|
av: ctx.userID,
|
|
@@ -120,7 +125,7 @@ export default function(defaultFuncs: any, api: any, ctx: any) {
|
|
|
120
125
|
fb_api_req_friendly_name:
|
|
121
126
|
'FriendingCometFriendRequestConfirmMutation',
|
|
122
127
|
variables: JSON.stringify(variables),
|
|
123
|
-
doc_id: '
|
|
128
|
+
doc_id: '24769943302682670',
|
|
124
129
|
};
|
|
125
130
|
const res = await defaultFuncs.post(
|
|
126
131
|
'https://www.facebook.com/api/graphql/',
|
|
@@ -147,7 +152,7 @@ export default function(defaultFuncs: any, api: any, ctx: any) {
|
|
|
147
152
|
* @returns {Promise<Object>} A promise that resolves to the API response data upon successful deletion.
|
|
148
153
|
* @throws {Error} If the identifier is missing, the user is not found in requests, or the API call fails.
|
|
149
154
|
*/
|
|
150
|
-
delete: async function(identifier) {
|
|
155
|
+
delete: async function (identifier) {
|
|
151
156
|
try {
|
|
152
157
|
if (!identifier) throw new Error('A name or user ID is required.');
|
|
153
158
|
let targetUserID = identifier;
|
|
@@ -206,7 +211,7 @@ export default function(defaultFuncs: any, api: any, ctx: any) {
|
|
|
206
211
|
* @returns {Promise<Array<Object>>} A promise that resolves to an array of formatted friend objects.
|
|
207
212
|
* @throws {Error} If the API request fails.
|
|
208
213
|
*/
|
|
209
|
-
list: async function(userID = ctx.userID) {
|
|
214
|
+
list: async function (userID = ctx.userID) {
|
|
210
215
|
try {
|
|
211
216
|
const sectionToken = Buffer.from(
|
|
212
217
|
`app_section:${userID}:2356318349`,
|
|
@@ -249,6 +254,143 @@ export default function(defaultFuncs: any, api: any, ctx: any) {
|
|
|
249
254
|
*/
|
|
250
255
|
getCurrentFriends: getCurrentFriends,
|
|
251
256
|
|
|
257
|
+
/**
|
|
258
|
+
* Sends a friend request to a user by their ID (via Profile Button channel).
|
|
259
|
+
* @async
|
|
260
|
+
* @param {string} userID The ID of the user to add as a friend.
|
|
261
|
+
* @returns {Promise<Object>} A promise that resolves to the API response data on success.
|
|
262
|
+
* @throws {Error} If the userID is missing or the API request fails.
|
|
263
|
+
*/
|
|
264
|
+
add: async function (userID) {
|
|
265
|
+
try {
|
|
266
|
+
if (!userID) throw new Error('userID is required.');
|
|
267
|
+
const variables = {
|
|
268
|
+
input: {
|
|
269
|
+
click_correlation_id: Date.now().toString(),
|
|
270
|
+
click_proof_validation_result: '{"validated":true}',
|
|
271
|
+
friend_requestee_ids: [userID],
|
|
272
|
+
friending_channel: 'PROFILE_BUTTON',
|
|
273
|
+
warn_ack_for_ids: [],
|
|
274
|
+
actor_id: ctx.userID,
|
|
275
|
+
client_mutation_id: Math.floor(Math.random() * 10 + 1).toString(),
|
|
276
|
+
},
|
|
277
|
+
scale: 1,
|
|
278
|
+
};
|
|
279
|
+
const form = {
|
|
280
|
+
av: ctx.userID,
|
|
281
|
+
__user: ctx.userID,
|
|
282
|
+
__a: '1',
|
|
283
|
+
fb_dtsg: ctx.fb_dtsg,
|
|
284
|
+
jazoest: ctx.jazoest,
|
|
285
|
+
lsd: ctx.lsd,
|
|
286
|
+
fb_api_caller_class: 'RelayModern',
|
|
287
|
+
fb_api_req_friendly_name: 'FriendingCometFriendRequestSendMutation',
|
|
288
|
+
variables: JSON.stringify(variables),
|
|
289
|
+
doc_id: '34974854235435024',
|
|
290
|
+
};
|
|
291
|
+
const res = await defaultFuncs.post(
|
|
292
|
+
'https://www.facebook.com/api/graphql/',
|
|
293
|
+
ctx.jar,
|
|
294
|
+
form,
|
|
295
|
+
{},
|
|
296
|
+
);
|
|
297
|
+
if (res.data.errors) throw new Error(JSON.stringify(res.data.errors));
|
|
298
|
+
return res.data.data;
|
|
299
|
+
} catch (err) {
|
|
300
|
+
throw err;
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Cancels a sent friend request (hủy lời mời kết bạn đã gửi).
|
|
306
|
+
* @async
|
|
307
|
+
* @param {string} userID The ID of the user whose friend request is to be cancelled.
|
|
308
|
+
* @returns {Promise<Object>} A promise that resolves to the API response data upon successful cancellation.
|
|
309
|
+
* @throws {Error} If the userID is missing or the API request fails.
|
|
310
|
+
*/
|
|
311
|
+
cancelRequest: async function (userID) {
|
|
312
|
+
try {
|
|
313
|
+
if (!userID) throw new Error('userID is required.');
|
|
314
|
+
const variables = {
|
|
315
|
+
input: {
|
|
316
|
+
cancelled_friend_requestee_id: userID,
|
|
317
|
+
click_correlation_id: Date.now().toString(),
|
|
318
|
+
click_proof_validation_result: '{"validated":true}',
|
|
319
|
+
friending_channel: 'PROFILE_BUTTON',
|
|
320
|
+
actor_id: ctx.userID,
|
|
321
|
+
client_mutation_id: Math.floor(Math.random() * 10 + 1).toString(),
|
|
322
|
+
},
|
|
323
|
+
scale: 1,
|
|
324
|
+
};
|
|
325
|
+
const form = {
|
|
326
|
+
av: ctx.userID,
|
|
327
|
+
__user: ctx.userID,
|
|
328
|
+
__a: '1',
|
|
329
|
+
fb_dtsg: ctx.fb_dtsg,
|
|
330
|
+
jazoest: ctx.jazoest,
|
|
331
|
+
lsd: ctx.lsd,
|
|
332
|
+
fb_api_caller_class: 'RelayModern',
|
|
333
|
+
fb_api_req_friendly_name: 'FriendingCometFriendRequestCancelMutation',
|
|
334
|
+
variables: JSON.stringify(variables),
|
|
335
|
+
doc_id: '24453541284254355',
|
|
336
|
+
};
|
|
337
|
+
const res = await defaultFuncs.post(
|
|
338
|
+
'https://www.facebook.com/api/graphql/',
|
|
339
|
+
ctx.jar,
|
|
340
|
+
form,
|
|
341
|
+
{},
|
|
342
|
+
);
|
|
343
|
+
if (res.data.errors) throw new Error(JSON.stringify(res.data.errors));
|
|
344
|
+
return res.data.data;
|
|
345
|
+
} catch (err) {
|
|
346
|
+
throw err;
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Unfriends a user (hủy kết bạn).
|
|
352
|
+
* @async
|
|
353
|
+
* @param {string} userID The ID of the user to unfriend.
|
|
354
|
+
* @returns {Promise<Object>} A promise that resolves to the API response data upon successful unfriending.
|
|
355
|
+
* @throws {Error} If the userID is missing or the API request fails.
|
|
356
|
+
*/
|
|
357
|
+
unfriend: async function (userID) {
|
|
358
|
+
try {
|
|
359
|
+
if (!userID) throw new Error('userID is required.');
|
|
360
|
+
const variables = {
|
|
361
|
+
input: {
|
|
362
|
+
source: 'bd_profile_button',
|
|
363
|
+
unfriended_user_id: userID,
|
|
364
|
+
actor_id: ctx.userID,
|
|
365
|
+
client_mutation_id: Math.floor(Math.random() * 10 + 1).toString(),
|
|
366
|
+
},
|
|
367
|
+
scale: 1,
|
|
368
|
+
};
|
|
369
|
+
const form = {
|
|
370
|
+
av: ctx.userID,
|
|
371
|
+
__user: ctx.userID,
|
|
372
|
+
__a: '1',
|
|
373
|
+
fb_dtsg: ctx.fb_dtsg,
|
|
374
|
+
jazoest: ctx.jazoest,
|
|
375
|
+
lsd: ctx.lsd,
|
|
376
|
+
fb_api_caller_class: 'RelayModern',
|
|
377
|
+
fb_api_req_friendly_name: 'FriendingCometUnfriendMutation',
|
|
378
|
+
variables: JSON.stringify(variables),
|
|
379
|
+
doc_id: '24028849793460009',
|
|
380
|
+
};
|
|
381
|
+
const res = await defaultFuncs.post(
|
|
382
|
+
'https://www.facebook.com/api/graphql/',
|
|
383
|
+
ctx.jar,
|
|
384
|
+
form,
|
|
385
|
+
{},
|
|
386
|
+
);
|
|
387
|
+
if (res.data.errors) throw new Error(JSON.stringify(res.data.errors));
|
|
388
|
+
return res.data.data;
|
|
389
|
+
} catch (err) {
|
|
390
|
+
throw err;
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
|
|
252
394
|
suggest: {
|
|
253
395
|
/**
|
|
254
396
|
* Fetches a list of suggested friends (People You May Know).
|
|
@@ -257,7 +399,7 @@ export default function(defaultFuncs: any, api: any, ctx: any) {
|
|
|
257
399
|
* @returns {Promise<Array<Object>>} A promise that resolves to an array of suggested friend objects.
|
|
258
400
|
* @throws {Error} If the API request fails.
|
|
259
401
|
*/
|
|
260
|
-
list: async function(limit = 30) {
|
|
402
|
+
list: async function (limit = 30) {
|
|
261
403
|
try {
|
|
262
404
|
const form = {
|
|
263
405
|
av: ctx.userID,
|
|
@@ -290,7 +432,7 @@ export default function(defaultFuncs: any, api: any, ctx: any) {
|
|
|
290
432
|
* @returns {Promise<Object>} A promise that resolves to the API response data on success.
|
|
291
433
|
* @throws {Error} If the userID is missing or the API request fails.
|
|
292
434
|
*/
|
|
293
|
-
request: async function(userID) {
|
|
435
|
+
request: async function (userID) {
|
|
294
436
|
try {
|
|
295
437
|
if (!userID) throw new Error('userID is required.');
|
|
296
438
|
const variables = {
|
|
@@ -337,17 +479,17 @@ export default function(defaultFuncs: any, api: any, ctx: any) {
|
|
|
337
479
|
* @returns {Promise<Array<Object>>} A promise that resolves to an array of friend objects.
|
|
338
480
|
*/
|
|
339
481
|
async function getCurrentFriends(callback?) {
|
|
340
|
-
let resolveFunc: Function = function() {};
|
|
341
|
-
let rejectFunc: Function = function() {};
|
|
482
|
+
let resolveFunc: Function = function () { };
|
|
483
|
+
let rejectFunc: Function = function () { };
|
|
342
484
|
|
|
343
|
-
const returnPromise = new Promise<any>(function(resolve, reject) {
|
|
485
|
+
const returnPromise = new Promise<any>(function (resolve, reject) {
|
|
344
486
|
resolveFunc = resolve;
|
|
345
487
|
rejectFunc = reject;
|
|
346
488
|
});
|
|
347
489
|
|
|
348
490
|
callback =
|
|
349
491
|
callback ||
|
|
350
|
-
function(err, data) {
|
|
492
|
+
function (err, data) {
|
|
351
493
|
if (err) return rejectFunc(err);
|
|
352
494
|
resolveFunc(data);
|
|
353
495
|
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ChoruOfficial
|
|
3
|
+
* @description A module for updating the Facebook profile bio (tiểu sử).
|
|
4
|
+
* Calls ProfileCometBioFieldSaveMutation via /api/graphql/.
|
|
5
|
+
* @param {Object} defaultFuncs The default functions provided by the API wrapper.
|
|
6
|
+
* @param {Object} api The full API object.
|
|
7
|
+
* @param {Object} ctx The context object containing the user's session state.
|
|
8
|
+
* @returns {Function} An async function that updates the account's bio.
|
|
9
|
+
*/
|
|
10
|
+
export default function (defaultFuncs: any, api: any, ctx: any) {
|
|
11
|
+
/**
|
|
12
|
+
* Updates the profile bio (tiểu sử) of the logged-in user.
|
|
13
|
+
* @async
|
|
14
|
+
* @param {string} bio The new bio text to set. Pass an empty string to clear the bio.
|
|
15
|
+
* @returns {Promise<Object>} A promise that resolves to the API response data on success.
|
|
16
|
+
* @throws {Error} If the API request fails.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* await api.changeBio('day la tieu su doi toi');
|
|
20
|
+
* await api.changeBio(''); // clear bio
|
|
21
|
+
*/
|
|
22
|
+
return async function changeBio(bio: string): Promise<any> {
|
|
23
|
+
if (bio === undefined || bio === null) {
|
|
24
|
+
throw new Error('bio is required. Pass an empty string to clear it.');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// sectionToken = base64("app_section:<userID>:2327158227")
|
|
28
|
+
const sectionToken = Buffer.from(
|
|
29
|
+
`app_section:${ctx.userID}:2327158227`,
|
|
30
|
+
).toString('base64');
|
|
31
|
+
|
|
32
|
+
const variables = {
|
|
33
|
+
collectionToken: 'UNKNOWN',
|
|
34
|
+
input: {
|
|
35
|
+
bio: bio,
|
|
36
|
+
profile_field_section_type: 'DIRECTORY_BIO',
|
|
37
|
+
actor_id: ctx.userID,
|
|
38
|
+
client_mutation_id: Math.floor(Math.random() * 10 + 1).toString(),
|
|
39
|
+
},
|
|
40
|
+
scale: 1,
|
|
41
|
+
sectionToken: sectionToken,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const form = {
|
|
45
|
+
av: ctx.userID,
|
|
46
|
+
__user: ctx.userID,
|
|
47
|
+
__a: '1',
|
|
48
|
+
fb_dtsg: ctx.fb_dtsg,
|
|
49
|
+
jazoest: ctx.jazoest,
|
|
50
|
+
lsd: ctx.lsd,
|
|
51
|
+
fb_api_caller_class: 'RelayModern',
|
|
52
|
+
fb_api_req_friendly_name: 'ProfileCometBioFieldSaveMutation',
|
|
53
|
+
variables: JSON.stringify(variables),
|
|
54
|
+
server_timestamps: 'true',
|
|
55
|
+
doc_id: '26787878704133086',
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const res = await defaultFuncs.post(
|
|
59
|
+
'https://www.facebook.com/api/graphql/',
|
|
60
|
+
ctx.jar,
|
|
61
|
+
form,
|
|
62
|
+
{},
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
if (res.data.errors) throw new Error(JSON.stringify(res.data.errors));
|
|
66
|
+
return res.data.data;
|
|
67
|
+
};
|
|
68
|
+
}
|