bb-fca 2.0.7 → 2.0.9

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.
@@ -771,14 +771,16 @@ export interface API {
771
771
  searchCity(
772
772
  query: string,
773
773
  searchCategory?: string,
774
- ): Promise<Array<{
775
- fbid: string;
776
- title: string;
777
- value: string;
778
- photoUri: string;
779
- subtitle: string;
780
- secondSubtitle: string;
781
- }>>;
774
+ ): Promise<
775
+ Array<{
776
+ fbid: string;
777
+ title: string;
778
+ value: string;
779
+ photoUri: string;
780
+ subtitle: string;
781
+ secondSubtitle: string;
782
+ }>
783
+ >;
782
784
 
783
785
  /**
784
786
  * Searches for companies/workplaces matching the given query string.
@@ -787,14 +789,16 @@ export interface API {
787
789
  */
788
790
  searchCompany(
789
791
  query: string,
790
- ): Promise<Array<{
791
- fbid: string;
792
- title: string;
793
- value: string;
794
- photoUri: string;
795
- subtitle: string;
796
- secondSubtitle: string;
797
- }>>;
792
+ ): Promise<
793
+ Array<{
794
+ fbid: string;
795
+ title: string;
796
+ value: string;
797
+ photoUri: string;
798
+ subtitle: string;
799
+ secondSubtitle: string;
800
+ }>
801
+ >;
798
802
 
799
803
  /**
800
804
  * Searches for job titles/positions matching the given query string.
@@ -803,14 +807,16 @@ export interface API {
803
807
  */
804
808
  searchJobTitle(
805
809
  query: string,
806
- ): Promise<Array<{
807
- fbid: string;
808
- title: string;
809
- value: string;
810
- photoUri: string;
811
- subtitle: string;
812
- secondSubtitle: string;
813
- }>>;
810
+ ): Promise<
811
+ Array<{
812
+ fbid: string;
813
+ title: string;
814
+ value: string;
815
+ photoUri: string;
816
+ subtitle: string;
817
+ secondSubtitle: string;
818
+ }>
819
+ >;
814
820
 
815
821
  /**
816
822
  * Fetches the friend list of a given user with pagination support.
@@ -861,10 +867,7 @@ export interface API {
861
867
  * @param cityId The Facebook ID of the city (from searchCity's fbid field).
862
868
  * @param privacy Privacy setting: 'EVERYONE', 'FRIENDS', or 'SELF' (default: 'EVERYONE').
863
869
  */
864
- updateCity(
865
- cityId: string,
866
- privacy?: string,
867
- ): Promise<any>;
870
+ updateCity(cityId: string, privacy?: string): Promise<any>;
868
871
 
869
872
  /**
870
873
  * Updates the hometown on the profile.
@@ -872,10 +875,7 @@ export interface API {
872
875
  * @param cityId The Facebook ID of the city (from searchCity's fbid field).
873
876
  * @param privacy Privacy setting: 'EVERYONE', 'FRIENDS', or 'SELF' (default: 'EVERYONE').
874
877
  */
875
- updateHometown(
876
- cityId: string,
877
- privacy?: string,
878
- ): Promise<any>;
878
+ updateHometown(cityId: string, privacy?: string): Promise<any>;
879
879
 
880
880
  /**
881
881
  * Changes the Facebook account display name (two-step: preview then confirm).
@@ -3,9 +3,14 @@ const gradient = require('gradient-string');
3
3
  const echaceb = gradient(['#0061ff', '#681297']);
4
4
  const ws = echaceb('bb-fca');
5
5
 
6
- let h;
7
- const i = {};
8
- const j = {
6
+ /**
7
+ * Presence compression token map.
8
+ * Keys are single uppercase letters used as compact tokens;
9
+ * values are the URL-encoded JSON substrings they replace.
10
+ * This map is used by presenceEncode/presenceDecode to compress
11
+ * presence payloads before sending to Facebook's EdgeChat API.
12
+ */
13
+ const PRESENCE_TOKEN_MAP: Record<string, string> = {
9
14
  _: '%',
10
15
  A: '%2',
11
16
  B: '000',
@@ -36,17 +41,27 @@ const j = {
36
41
  Z:
37
42
  '%2c%22sb%22%3a1%2c%22t%22%3a%5b%5d%2c%22f%22%3anull%2c%22uct%22%3a0%2c%22s%22%3a0%2c%22blo%22%3a0%7d%2c%22bl%22%3a%7b%22ac%22%3a',
38
43
  };
39
- (function() {
40
- const l = [];
41
- for (const m in j) {
42
- i[j[m]] = m;
43
- l.push(j[m]);
44
+
45
+ /** Reverse map: encoded substring → token letter. Built from PRESENCE_TOKEN_MAP. */
46
+ const presenceDecodeMap: Record<string, string> = {};
47
+
48
+ /** RegExp that matches any encodedsubstring in PRESENCE_TOKEN_MAP (longest first). */
49
+ let presenceEncodeRegex: RegExp;
50
+
51
+ (function buildPresenceMaps(): void {
52
+ const encodedValues: string[] = [];
53
+ for (const token in PRESENCE_TOKEN_MAP) {
54
+ presenceDecodeMap[PRESENCE_TOKEN_MAP[token]] = token;
55
+ encodedValues.push(PRESENCE_TOKEN_MAP[token]);
44
56
  }
45
- l.reverse();
46
- h = new RegExp(l.join('|'), 'g');
57
+ // Sort longest first so greedy matching works correctly
58
+ encodedValues.reverse();
59
+ presenceEncodeRegex = new RegExp(encodedValues.join('|'), 'g');
47
60
  })();
48
61
 
49
- const NUM_TO_MONTH = [
62
+ // ─── Calendar helpers ───────────────────────────────────────────────────────
63
+
64
+ const NUM_TO_MONTH: string[] = [
50
65
  'Jan',
51
66
  'Feb',
52
67
  'Mar',
@@ -60,26 +75,27 @@ const NUM_TO_MONTH = [
60
75
  'Nov',
61
76
  'Dec',
62
77
  ];
63
- const NUM_TO_DAY = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
78
+ const NUM_TO_DAY: string[] = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
79
+
80
+ // ─── Utility functions ───────────────────────────────────────────────────────
64
81
 
65
- function getRandom(arr) {
82
+ function getRandom<T>(arr: T[]): T {
66
83
  return arr[Math.floor(Math.random() * arr.length)];
67
84
  }
68
85
 
69
- function padZeros(val, len = 2) {
70
- val = String(val);
71
- while (val.length < len) val = '0' + val;
72
- return val;
86
+ function padZeros(val: string | number, len: number = 2): string {
87
+ let s = String(val);
88
+ while (s.length < len) s = '0' + s;
89
+ return s;
73
90
  }
74
91
 
75
- function generateThreadingID(clientID) {
76
- const k = Date.now();
77
- const l = Math.floor(Math.random() * 4294967295);
78
- const m = clientID;
79
- return '<' + k + ':' + l + '-' + m + '@mail.projektitan.com>';
92
+ function generateThreadingID(clientID: string): string {
93
+ const timestamp = Date.now();
94
+ const rand = Math.floor(Math.random() * 4294967295);
95
+ return '<' + timestamp + ':' + rand + '-' + clientID + '@mail.projektitan.com>';
80
96
  }
81
97
 
82
- function binaryToDecimal(data) {
98
+ function binaryToDecimal(data: string): string {
83
99
  let ret = '';
84
100
  while (data !== '0') {
85
101
  let end = 0;
@@ -100,7 +116,7 @@ function binaryToDecimal(data) {
100
116
  return ret;
101
117
  }
102
118
 
103
- function generateOfflineThreadingID() {
119
+ function generateOfflineThreadingID(): string {
104
120
  const ret = Date.now();
105
121
  const value = Math.floor(Math.random() * 4294967295);
106
122
  const str = ('0000000000000000000000' + value.toString(2)).slice(-22);
@@ -108,26 +124,33 @@ function generateOfflineThreadingID() {
108
124
  return binaryToDecimal(msgs);
109
125
  }
110
126
 
111
- function presenceEncode(str) {
127
+ /**
128
+ * Compresses a presence JSON string using PRESENCE_TOKEN_MAP shortcuts.
129
+ * Reduces payload size when communicating with Facebook's EdgeChat API.
130
+ */
131
+ function presenceEncode(str: string): string {
112
132
  return encodeURIComponent(str)
113
- .replace(/([_A-Z])|%../g, function(m, n) {
133
+ .replace(/([_A-Z])|%../g, function(m: string, n: string): string {
114
134
  return n ? '%' + n.charCodeAt(0).toString(16) : m;
115
135
  })
116
136
  .toLowerCase()
117
- .replace(h, function(m) {
118
- return i[m];
137
+ .replace(presenceEncodeRegex, function(m: string): string {
138
+ return presenceDecodeMap[m];
119
139
  });
120
140
  }
121
141
 
122
- function presenceDecode(str) {
142
+ /**
143
+ * Decompresses a presence-encoded string back to its original form.
144
+ */
145
+ function presenceDecode(str: string): string {
123
146
  return decodeURIComponent(
124
- str.replace(/[_A-Z]/g, function(m) {
125
- return j[m];
147
+ str.replace(/[_A-Z]/g, function(m: string): string {
148
+ return PRESENCE_TOKEN_MAP[m];
126
149
  }),
127
150
  );
128
151
  }
129
152
 
130
- function generatePresence(userID) {
153
+ function generatePresence(userID: string): string {
131
154
  const time = Date.now();
132
155
  return (
133
156
  'E' +
@@ -153,7 +176,7 @@ function generatePresence(userID) {
153
176
  );
154
177
  }
155
178
 
156
- function generateAccessiblityCookie() {
179
+ function generateAccessiblityCookie(): string {
157
180
  const time = Date.now();
158
181
  return encodeURIComponent(
159
182
  JSON.stringify({
@@ -169,20 +192,19 @@ function generateAccessiblityCookie() {
169
192
  );
170
193
  }
171
194
 
172
- function getGUID() {
195
+ function getGUID(): string {
173
196
  let sectionLength = Date.now();
174
197
  const id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(
175
- c,
176
- ) {
198
+ c: string,
199
+ ): string {
177
200
  const r = Math.floor((sectionLength + Math.random() * 16) % 16);
178
201
  sectionLength = Math.floor(sectionLength / 16);
179
- const _guid = (c == 'x' ? r : (r & 7) | 8).toString(16);
180
- return _guid;
202
+ return (c == 'x' ? r : (r & 7) | 8).toString(16);
181
203
  });
182
204
  return id;
183
205
  }
184
206
 
185
- function getFrom(str, startToken, endToken) {
207
+ function getFrom(str: string, startToken: string, endToken: string): string {
186
208
  const start = str.indexOf(startToken) + startToken.length;
187
209
  if (start < startToken.length) return '';
188
210
 
@@ -196,7 +218,7 @@ function getFrom(str, startToken, endToken) {
196
218
  return lastHalf.substring(0, end);
197
219
  }
198
220
 
199
- function makeParsable(html) {
221
+ function makeParsable(html: string): string | string[] {
200
222
  const withoutForLoop = html.replace(/for\s*\(\s*;\s*;\s*\)\s*;\s*/, '');
201
223
  const maybeMultipleObjects = withoutForLoop.split(/\}\r\n *\{/);
202
224
  if (maybeMultipleObjects.length === 1) return maybeMultipleObjects;
@@ -204,52 +226,57 @@ function makeParsable(html) {
204
226
  return '[' + maybeMultipleObjects.join('},{') + ']';
205
227
  }
206
228
 
207
- function arrToForm(form) {
229
+ function arrToForm(form: Array<{ name: string; val: any }>): Record<string, any> {
208
230
  return arrayToObject(
209
231
  form,
210
- function(v) {
211
- return v.name;
212
- },
213
- function(v) {
214
- return v.val;
215
- },
232
+ function(v) { return v.name; },
233
+ function(v) { return v.val; },
216
234
  );
217
235
  }
218
236
 
219
- function arrayToObject(arr, getKey, getValue) {
220
- return arr.reduce(function(acc, val) {
237
+ function arrayToObject<T>(
238
+ arr: T[],
239
+ getKey: (v: T) => string,
240
+ getValue: (v: T) => any,
241
+ ): Record<string, any> {
242
+ return arr.reduce(function(acc: Record<string, any>, val: T) {
221
243
  acc[getKey(val)] = getValue(val);
222
244
  return acc;
223
245
  }, {});
224
246
  }
225
247
 
226
- function getSignatureID() {
248
+ function getSignatureID(): string {
227
249
  return Math.floor(Math.random() * 2147483648).toString(16);
228
250
  }
229
251
 
230
- function generateTimestampRelative() {
252
+ function generateTimestampRelative(): string {
231
253
  const d = new Date();
232
254
  return d.getHours() + ':' + padZeros(d.getMinutes());
233
255
  }
234
256
 
235
- function getType(obj) {
257
+ function getType(obj: unknown): string {
236
258
  return Object.prototype.toString.call(obj).slice(8, -1);
237
259
  }
238
260
 
239
- // Logs
261
+ // ─── Logging ─────────────────────────────────────────────────────────────────
262
+
240
263
  let logging = true;
241
- function logOptions(bool) {
264
+
265
+ function logOptions(bool: boolean): void {
242
266
  logging = bool;
243
267
  }
244
- function log(...args) {
268
+
269
+ function log(...args: unknown[]): void {
245
270
  if (logging === false) return;
246
271
  console.log(ws, chalk.green.bold('[LOG]'), ...args);
247
272
  }
248
- function error(...args) {
273
+
274
+ function error(...args: unknown[]): void {
249
275
  if (logging === false) return;
250
276
  console.error(ws, chalk.red.bold('[ERROR]'), ...args);
251
277
  }
252
- function warn(...args) {
278
+
279
+ function warn(...args: unknown[]): void {
253
280
  if (logging === false) return;
254
281
  console.warn(ws, chalk.yellow.bold('[WARNING]'), ...args);
255
282
  }