ayman-fca 1.0.7 → 1.0.8

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.
Files changed (2) hide show
  1. package/index.js +742 -262
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1,271 +1,751 @@
1
- // ============================================================
2
- // AYMAN-FCA v2.0 ULTRA MASTER ENGINE
3
- // © 2026 Ayman. All Rights Reserved.
4
- //
5
- // يجمع كل الأنظمة:
6
- // SessionManager — جلسة + backup + validate
7
- // ReconnectEngine — Circuit Breaker + backoff
8
- // ③ KeepAliveEngine — نشاط حقيقي كل 4 دقائق
9
- // Watchdog — مراقبة MQTT + صمت
10
- // ⑤ HealthMonitor — Score 0-100
11
- // MemoryManager — تنظيف ذاكرة
12
- // BehaviorEngine — محاكاة إنسان
13
- // SmartCooldown — تحكم ذكي بالسرعة
14
- // ⑨ SilentRecovery — Soft Restart + Silent Mode
15
- // SmartMessageQueue— Queue ذكي
16
- // ⑪ GeoGuard — حماية الموقع الجغرافي
17
- // ============================================================
18
- "use strict";
19
-
20
- const EventEmitter = require("events");
21
- const path = require("path");
22
-
23
- // المسار الصحيح داخل حزمة المكتبة
24
- const logger = require("./func/logger");
25
-
26
- const SessionManager = require("./core/sessionManager");
27
- const ReconnectEngine = require("./core/reconnectEngine");
28
- const KeepAliveEngine = require("./core/keepAliveEngine");
29
- const Watchdog = require("./core/watchdog");
30
- const HealthMonitor = require("./core/healthMonitor");
31
- const MemoryManager = require("./core/memoryManager");
32
- const BehaviorEngine = require("./core/behaviorEngine");
33
- const SmartCooldown = require("./core/smartCooldown");
34
- const SilentRecovery = require("./core/silentRecovery");
35
- const SmartMessageQueue = require("./core/smartMessageQueue");
36
- const GeoGuard = require("./core/geoGuard");
37
- const { EVENTS } = require("./system/constants");
38
- const { isSessionError }= require("./system/errors");
39
-
40
- class AymanFCAUltra extends EventEmitter {
41
- constructor(options = {}) {
42
- super();
43
- this._appStatePath = options.appStatePath || path.join(process.cwd(), "appstate.json");
44
- this._onMessage = options.onMessage || null;
45
- this._api = null;
46
- this._ctx = null;
47
- this._restarting = false;
48
- this._startedAt = Date.now();
49
-
50
- // ── الأنظمة ──────────────────────────────────────────────
51
- this.session = new SessionManager({ primaryPath: this._appStatePath, onSave: options.onSave || null });
52
- this.reconnect = new ReconnectEngine();
53
- this.keepAlive = new KeepAliveEngine();
54
- this.watchdog = new Watchdog();
55
- this.health = new HealthMonitor();
56
- this.memory = new MemoryManager();
57
- this.behavior = new BehaviorEngine({ sessionStart: this._startedAt });
58
- this.cooldown = new SmartCooldown();
59
- this.silent = new SilentRecovery();
60
- this.queue = new SmartMessageQueue({ noise: true });
61
- this.geo = new GeoGuard({ lockRegion: true });
62
-
63
- this._wireSystems();
64
- // تأكد أن logger يحتوي على دالة banner لتجنب الأخطاء
65
- if (logger && typeof logger.banner === "function") logger.banner();
66
- }
67
-
68
- // ── ربط الأنظمة ببعضها ──────────────────────────────────
69
- _wireSystems() {
70
- this.watchdog.on(EVENTS.WATCHDOG_RESTART, ({ reasons }) => {
71
- this.health.penalize("mqtt_dead");
72
- this._restart("watchdog: " + reasons);
73
- });
74
-
75
- this.health.on(EVENTS.HEALTH_CRITICAL, ({ score }) => {
76
- logger.error(`Health منخفض (${score}) — restart`, "ULTRA");
77
- this._restart("health_critical");
78
- });
79
-
80
- this.session.on(EVENTS.SESSION_EXPIRED, () => {
81
- this.health.penalize("session_expired");
82
- this._restart("session_expired");
83
- });
84
-
85
- this.memory.on(EVENTS.MEMORY_HIGH, () => {
86
- this.health.penalize("memory_high");
87
- this.queue.setRiskLevel("high");
88
- });
89
-
90
- this.silent.on("silent:enter", () => {
91
- this.queue.pause("silent_mode");
92
- this.cooldown.recordError();
93
- });
94
- this.silent.on("silent:exit", () => {
95
- this.queue.resume();
96
- });
97
-
98
- this.reconnect.on(EVENTS.RECONNECT_DONE, () => {
99
- this.health.reward("reconnect_done");
100
- this.cooldown.reset();
101
- this.queue.setRiskLevel("normal");
102
- });
103
- this.reconnect.on(EVENTS.RECONNECT_FAIL, () => {
104
- this.health.penalize("reconnect_fail");
105
- });
106
-
107
- this.geo.on("region:unstable", () => {
108
- logger.warn("GeoGuard: عدم استقرار Silent Mode", "ULTRA");
109
- this.silent.enterSilentMode("geo_instability");
110
- });
111
-
112
- this.health.on(EVENTS.HEALTH_LOW, () => {
113
- this.queue.setRiskLevel("high");
114
- this.cooldown.recordError();
115
- });
116
- }
117
-
118
- _extractCtx(api) {
119
- for (const k of Object.getOwnPropertyNames(api)) {
120
- try {
121
- const v = api[k];
122
- if (v && typeof v === "object" && v.jar && v.userID && v.userID !== "0") return v;
123
- } catch(_) {}
124
- }
125
- return null;
126
- }
127
-
128
- _startSystems(api, ctx) {
129
- this.session.attach(api);
130
- this.keepAlive.attach(api, ctx);
131
- this.watchdog.attach(api, ctx);
132
- this.memory.registerCleanup(() => {
133
- if (ctx?.tasks instanceof Map && ctx.tasks.size > 100) ctx.tasks.clear();
134
- });
135
-
136
- if (ctx?.region) this.geo.recordRegion(ctx.region);
137
-
138
- this.session.start();
139
- this.keepAlive.start();
140
- this.watchdog.start();
141
- this.health.start();
142
- this.memory.start();
143
- this.queue.start();
144
- this.behavior.start(ctx?.mqttClient);
145
-
146
- logger.info("ULTRA: كل الأنظمة تعمل ✅", "ULTRA");
147
- this.emit("ready", { uid: ctx?.userID });
148
- }
149
-
150
- _stopSystems() {
151
- ["session","keepAlive","watchdog","health","memory","queue","behavior","silent"].forEach(s => {
152
- try { this[s].stop(); } catch(_) {}
153
- });
154
- }
155
-
156
- async _restart(reason) {
157
- if (this._restarting) return;
158
- this._restarting = true;
159
- logger.warn(`ULTRA: إعادة تشغيل — ${reason}`, "ULTRA");
160
-
161
- const ok = await this.silent.softRestart(async () => {
162
- this._stopSystems();
163
- try {
164
- if (this._ctx?.mqttClient) {
165
- this._ctx.mqttClient.removeAllListeners();
166
- this._ctx.mqttClient.end(true);
167
- }
168
- } catch(_) {}
169
- await this.reconnect.trigger(async () => {
170
- await this.attachToApi(this._api);
171
- }, new Error(reason));
172
- }, reason);
173
-
174
- if (!ok) logger.error("ULTRA: فشلت إعادة التشغيل", "ULTRA");
175
- this._restarting = false;
176
- }
177
-
178
- buildListenerCallback() {
179
- return (error, message) => {
180
- if (error) {
181
- if (error?.type === "stop_listen") return;
182
-
183
- if (this.silent.shouldGoSilent(error)) {
184
- this.silent.handleError(error, () => this._restart("silent_recovery"));
185
- return;
186
- }
187
-
188
- if (error?.type === "account_inactive" || isSessionError(error)) {
189
- this.health.penalize("session_expired");
190
- this._restart("account_inactive");
191
- return;
192
- }
193
-
194
- this.health.penalize("error");
195
- this.cooldown.recordError();
196
- this._restart("listen_error");
197
- return;
198
- }
199
-
200
- if (!message) return;
201
-
202
- this.watchdog.heartbeat();
203
- this.health.reward("message_ok");
204
- this.cooldown.recordSuccess();
205
-
206
- if (message.region) this.geo.recordRegion(message.region);
207
-
208
- if (["presence","typ","read_receipt"].includes(message.type)) return;
209
-
210
- if (this._onMessage) {
211
- try { this._onMessage(null, message); } catch(e) {}
212
- }
213
- this.emit("message", message);
1
+ declare module '@dongdev/fca-unofficial' {
2
+ import type EventEmitter from "events";
3
+ import type { Duplex, Readable, Transform } from "stream";
4
+
5
+ // ============================================================================
6
+ // Type Definitions
7
+ // ============================================================================
8
+
9
+ type ReadableStream = Readable | Duplex | Transform;
10
+
11
+ // ============================================================================
12
+ // Login Function
13
+ // ============================================================================
14
+
15
+ function login(
16
+ credentials: Partial<{
17
+ email: string;
18
+ password: string;
19
+ appState: AppstateData;
20
+ Cookie?: string | string[] | Record<string, string>;
21
+ }>,
22
+ options: Partial<IFCAU_Options>,
23
+ callback: (err: Error | null, api: IFCAU_API) => void
24
+ ): void;
25
+ function login(
26
+ credentials: Partial<{
27
+ email: string;
28
+ password: string;
29
+ appState: AppstateData;
30
+ Cookie?: string | string[] | Record<string, string>;
31
+ }>,
32
+ options: Partial<IFCAU_Options>
33
+ ): Promise<IFCAU_API>;
34
+ function login(
35
+ credentials: Partial<{
36
+ email: string;
37
+ password: string;
38
+ appState: AppstateData;
39
+ Cookie?: string | string[] | Record<string, string>;
40
+ }>,
41
+ callback: (err: Error | null, api: IFCAU_API) => void
42
+ ): void;
43
+ function login(
44
+ credentials: Partial<{
45
+ email: string;
46
+ password: string;
47
+ appState: AppstateData;
48
+ Cookie?: string | string[] | Record<string, string>;
49
+ }>
50
+ ): Promise<IFCAU_API>;
51
+
52
+ export default login;
53
+ export { login };
54
+
55
+ // ============================================================================
56
+ // Core Types
57
+ // ============================================================================
58
+
59
+ export type Cookie = {
60
+ key: string;
61
+ value: string;
62
+ domain: string;
63
+ path?: string;
64
+ hostOnly?: boolean;
65
+ creation?: string;
66
+ lastAccessed?: string;
67
+ };
68
+
69
+ export type AppstateData = {
70
+ appState: Cookie[];
71
+ };
72
+
73
+ export type MessageObject = {
74
+ body: string;
75
+ sticker?: string;
76
+ attachment?: ReadableStream | ReadableStream[];
77
+ url?: string;
78
+ emoji?: string;
79
+ emojiSize?: string;
80
+ mentions?: {
81
+ tag: string;
82
+ id: string;
83
+ fromIndex?: number;
84
+ }[];
85
+ location?: {
86
+ latitude: number;
87
+ longitude: number;
88
+ current?: boolean;
89
+ };
90
+ };
91
+
92
+ // ============================================================================
93
+ // Send Message Function
94
+ // ============================================================================
95
+
96
+ function sendMessage(
97
+ message: string | MessageObject,
98
+ threadID: string | string[],
99
+ callback?: (err?: Error, data?: { threadID: string; messageID: string; timestamp: number }) => void,
100
+ replyMessageID?: string,
101
+ isGroup?: boolean
102
+ ): Promise<{ threadID: string; messageID: string; timestamp: number }>;
103
+ function sendMessage(
104
+ message: string | MessageObject,
105
+ threadID: string | string[],
106
+ replyMessageID?: string,
107
+ isGroup?: boolean
108
+ ): Promise<{ threadID: string; messageID: string; timestamp: number }>;
109
+
110
+ // ============================================================================
111
+ // API Interface
112
+ // ============================================================================
113
+
114
+ export type IFCAU_API = {
115
+ // Group Management
116
+ addUserToGroup: (userID: string, threadID: string, callback?: (err?: Error) => void) => Promise<void>;
117
+ removeUserFromGroup: (userID: string, threadID: string, callback?: (err?: Error) => void) => Promise<void>;
118
+ createNewGroup: (participantIDs: string[], groupTitle?: string, callback?: (err: Error, threadID: string) => void) => Promise<string>;
119
+
120
+ // Admin & Permissions
121
+ changeAdminStatus: (threadID: string, adminIDs: string | string[], adminStatus: boolean, callback?: (err?: Error) => void) => Promise<void>;
122
+ changeApprovalMode: (approvalMode: 0 | 1, threadID: string, callback?: (err?: Error) => void) => Promise<void>;
123
+
124
+ // Thread Management
125
+ changeArchivedStatus: (threadOrThreads: string | string[], archive: boolean, callback?: (err?: Error) => void) => Promise<void>;
126
+ changeBlockedStatus: (userID: string, blocked: boolean, callback?: (err?: Error) => void) => Promise<void>;
127
+ changeGroupImage: (image: ReadableStream, threadID: string, callback?: (err?: Error) => void) => Promise<void>;
128
+ changeNickname: (nickname: string, threadID: string, participantID: string, callback?: (err?: Error) => void) => Promise<void>;
129
+ changeThreadColor: (color: string, threadID: string, callback?: (err?: Error) => void) => Promise<void>;
130
+ changeThreadEmoji: (emoji: string | null, threadID: string, callback?: (err?: Error) => void) => Promise<void>;
131
+ setTitle: (newTitle: string, threadID: string, callback?: (err?: Error) => void) => Promise<void>;
132
+ deleteThread: (threadOrThreads: string | string[], callback?: (err?: Error) => void) => Promise<void>;
133
+ muteThread: (threadID: string, muteSeconds: number, callback?: (err?: Error) => void) => Promise<void>;
134
+
135
+ // Messages
136
+ sendMessage: typeof sendMessage;
137
+ editMessage: (text: string, messageID: string, callback?: (err?: Error) => void) => Promise<void>;
138
+ deleteMessage: (messageOrMessages: string | string[], callback?: (err?: Error) => void) => Promise<void>;
139
+ unsendMessage: (messageID: string, callback?: (err?: Error) => void) => Promise<void>;
140
+ unsendMessageMqtt: (messageID: string, threadID: string, callback?: (err?: Error) => void) => Promise<void>;
141
+ forwardMessage: (messageID: string, threadID: string, callback?: (err?: Error) => void) => Promise<void>;
142
+ forwardAttachment: (attachmentID: string, userOrUsers: string | string[], callback?: (err?: Error) => void) => Promise<void>;
143
+ pinMessage: (pinMode: boolean, messageID: string, threadID: string, callback?: (err?: Error) => void) => Promise<void>;
144
+
145
+ // Reactions & Interactions
146
+ setMessageReaction: (reaction: string, messageID: string, threadID: string, callback?: (err?: Error) => void, forceCustomReaction?: boolean) => Promise<void>;
147
+ setMessageReactionMqtt: (reaction: string, messageID: string, threadID: string, callback?: (err?: Error) => void) => Promise<void>;
148
+ sendTypingIndicator: (threadID: string, callback?: (err?: Error) => void) => Promise<void>;
149
+ sendTypingIndicatorMqtt: (isTyping: boolean, threadID: string, callback?: (err?: Error) => void) => Promise<void>;
150
+
151
+ // Polls
152
+ createPoll: (title: string, threadID: string, options?: { [item: string]: boolean }, callback?: (err?: Error) => void) => Promise<void>;
153
+
154
+ // Read & Delivery Status
155
+ markAsRead: (threadID: string, read?: boolean, callback?: (err?: Error) => void) => Promise<void>;
156
+ markAsReadAll: (callback?: (err?: Error) => void) => Promise<void>;
157
+ markAsDelivered: (threadID: string, messageID: string, callback?: (err?: Error) => void) => Promise<void>;
158
+ markAsSeen: (seenTimestamp?: number, callback?: (err?: Error) => void) => Promise<void>;
159
+
160
+ // Thread Information
161
+ getThreadInfo: (threadID: string, callback?: (err: Error | null, thread: IFCAU_Thread) => void) => Promise<IFCAU_Thread>;
162
+ getThreadList: (limit: number, timestamp: number | null, tags: string[], callback?: (err: Error | null, threads: IFCAU_ThreadList) => void) => Promise<IFCAU_ThreadList>;
163
+ getThreadHistory: (threadID: string, amount: number, time?: number, callback?: (err: Error | null, messages: any[]) => void) => Promise<any[]>;
164
+ getThreadPictures: (threadID: string, offset: number, limit: number, callback?: (err: Error | null, pictures: string[]) => void) => Promise<string[]>;
165
+
166
+ // User Information
167
+ getUserInfo: (userOrUsers: string | string[], callback?: (err: Error | null, users: { [id: string]: IFCAU_User }) => void) => Promise<{ [id: string]: IFCAU_User }>;
168
+ getUserID: (name: string, callback?: (err: Error | null, obj: IFCAU_UserIDResponse) => void) => Promise<IFCAU_UserIDResponse>;
169
+ getFriendsList: (callback?: (err: Error | null, friends: IFCAU_Friend[]) => void) => Promise<IFCAU_Friend[]>;
170
+ getCurrentUserID: () => string;
171
+
172
+ // Utilities
173
+ getAppState: () => any;
174
+ getEmojiUrl: (c: string, size: number, pixelRatio: number) => string;
175
+ resolvePhotoUrl: (photoID: string, callback?: (err: Error | null, url: string) => void) => Promise<string>;
176
+ threadColors: {
177
+ [color: string]: string;
214
178
  };
215
- }
216
179
 
217
- async attachToApi(api) {
218
- this._api = api;
219
- this._ctx = this._extractCtx(api);
180
+ // Message Requests
181
+ handleMessageRequest: (threadOrThreads: string | string[], accept: boolean, callback?: (err?: Error) => void) => Promise<void>;
182
+
183
+ // Event Listeners
184
+ listen: (callback?: (err: Error | null, message: IFCAU_ListenMessage) => void) => EventEmitter;
185
+ listenMqtt: (callback?: (err: Error | null, message: IFCAU_ListenMessage) => void) => EventEmitter & { stopListening: (callback?: () => void) => void };
186
+
187
+ // Lifecycle & Remote Events
188
+ on: (event: string, listener: (...args: any[]) => void) => IFCAU_Api;
189
+ once: (event: string, listener: (...args: any[]) => void) => IFCAU_Api;
190
+ off: (event: string, listener: (...args: any[]) => void) => IFCAU_Api;
191
+ removeAllListeners: (event?: string) => IFCAU_Api;
192
+
193
+ // Middleware System
194
+ useMiddleware: (middleware: IFCAU_Middleware | string, fn?: IFCAU_Middleware) => () => void;
195
+ removeMiddleware: (identifier: string | IFCAU_Middleware) => boolean;
196
+ clearMiddleware: () => void;
197
+ listMiddleware: () => string[];
198
+ setMiddlewareEnabled: (name: string, enabled: boolean) => boolean;
199
+ readonly middlewareCount: number;
200
+
201
+ // Configuration & Session
202
+ setOptions: (options: Partial<IFCAU_Options>) => void;
203
+ logout: (callback?: (err?: Error) => void) => Promise<void>;
204
+
205
+ // Message Scheduler
206
+ scheduler: {
207
+ scheduleMessage: (message: string | MessageObject, threadID: string | string[], when: Date | number | string, options?: { replyMessageID?: string; isGroup?: boolean; callback?: (err?: Error) => void }) => string;
208
+ cancelScheduledMessage: (id: string) => boolean;
209
+ getScheduledMessage: (id: string) => IFCAU_ScheduledMessage | null;
210
+ listScheduledMessages: () => IFCAU_ScheduledMessage[];
211
+ cancelAllScheduledMessages: () => number;
212
+ getScheduledCount: () => number;
213
+ cleanup: () => void;
214
+ };
220
215
 
221
- if (this._ctx) {
222
- api.ctx = this._ctx;
223
- api.ctxMain = this._ctx;
224
- logger.info(`ULTRA مرتبط | UID: ${this._ctx.userID} | Region: ${this._ctx.region || "?"}`, "ULTRA");
216
+ // Auto-save AppState
217
+ enableAutoSaveAppState: (options?: { filePath?: string; interval?: number; saveOnLogin?: boolean }) => () => void;
218
+ };
219
+
220
+ // ============================================================================
221
+ // Listen Message Types
222
+ // ============================================================================
223
+
224
+ export type IFCAU_ListenMessage =
225
+ | {
226
+ type: "message";
227
+ attachments: IFCAU_Attachment[];
228
+ args: string[];
229
+ body: string;
230
+ isGroup: boolean;
231
+ mentions: { [id: string]: string };
232
+ messageID: string;
233
+ senderID: string;
234
+ threadID: string;
235
+ isUnread: boolean;
236
+ participantIDs: string[];
225
237
  }
238
+ | {
239
+ type: "event";
240
+ author: string;
241
+ logMessageBody: string;
242
+ logMessageData: {
243
+ image: {
244
+ attachmentID: string;
245
+ width: number;
246
+ height: number;
247
+ url: string;
248
+ };
249
+ };
250
+ logMessageType: "log:thread-image";
251
+ threadID: string;
252
+ }
253
+ | {
254
+ type: "event";
255
+ author: string;
256
+ logMessageBody: string;
257
+ logMessageData: {
258
+ addedParticipants: {
259
+ fanoutPolicy: string;
260
+ firstName: string;
261
+ fullName: string;
262
+ groupJoinStatus: string;
263
+ initialFolder: string;
264
+ initialFolderId: {
265
+ systemFolderId: string;
266
+ };
267
+ lastUnsubscribeTimestampMs: string;
268
+ userFbId: string;
269
+ isMessengerUser: boolean;
270
+ }[];
271
+ };
272
+ logMessageType: "log:subscribe";
273
+ threadID: string;
274
+ participantIDs: string[];
275
+ }
276
+ | {
277
+ type: "event";
278
+ author: string;
279
+ logMessageBody: string;
280
+ logMessageData: { leftParticipantFbId: string };
281
+ logMessageType: "log:unsubscribe";
282
+ threadID: string;
283
+ participantIDs: string[];
284
+ }
285
+ | {
286
+ type: "event";
287
+ author: string;
288
+ logMessageBody: string;
289
+ logMessageData: { name: string };
290
+ logMessageType: "log:thread-name";
291
+ threadID: string;
292
+ participantIDs: string[];
293
+ }
294
+ | {
295
+ type: "event";
296
+ author: string;
297
+ logMessageBody: string;
298
+ logMessageData: {
299
+ theme_color: string;
300
+ gradient?: string;
301
+ should_show_icon: string;
302
+ theme_id: string;
303
+ accessibility_label: string;
304
+ theme_name_with_subtitle: string;
305
+ theme_emoji?: string;
306
+ };
307
+ logMessageType: "log:thread-color";
308
+ threadID: string;
309
+ participantIDs: string[];
310
+ }
311
+ | {
312
+ type: "event";
313
+ author: string;
314
+ logMessageBody: string;
315
+ logMessageData: {
316
+ thread_quick_reaction_instruction_key_id: string;
317
+ thread_quick_reaction_emoji: string;
318
+ thread_quick_reaction_emoji_url: string;
319
+ };
320
+ logMessageType: "log:thread-icon";
321
+ threadID: string;
322
+ participantIDs: string[];
323
+ }
324
+ | {
325
+ type: "event";
326
+ author: string;
327
+ logMessageBody: string;
328
+ logMessageData: {
329
+ nickname: string;
330
+ participant_id: string;
331
+ };
332
+ logMessageType: "log:user-nickname";
333
+ threadID: string;
334
+ participantIDs: string[];
335
+ }
336
+ | {
337
+ type: "event";
338
+ author: string;
339
+ logMessageBody: string;
340
+ logMessageData: {
341
+ THREAD_CATEGORY: string;
342
+ TARGET_ID: string;
343
+ ADMIN_TYPE: string;
344
+ ADMIN_EVENT: 'add_admin' | 'remove_admin';
345
+ };
346
+ logMessageType: "log:thread-admins";
347
+ threadID: string;
348
+ participantIDs: string[];
349
+ }
350
+ | {
351
+ type: "event";
352
+ author: string;
353
+ logMessageBody: string;
354
+ logMessageData: {
355
+ removed_option_ids: string;
356
+ question_json: string;
357
+ event_type: 'question_creation' | 'update_vote' | 'add_unvoted_option' | 'multiple_updates';
358
+ added_option_ids: string;
359
+ new_option_texts: string;
360
+ new_option_ids: string;
361
+ question_id: string;
362
+ };
363
+ logMessageType: "log:thread-poll";
364
+ threadID: string;
365
+ participantIDs: string[];
366
+ }
367
+ | {
368
+ type: "event";
369
+ author: string;
370
+ logMessageBody: string;
371
+ logMessageData: { APPROVAL_MODE: '0' | '1'; THREAD_CATEGORY: string };
372
+ logMessageType: "log:thread-approval-mode";
373
+ threadID: string;
374
+ participantIDs: string[];
375
+ }
376
+ | {
377
+ type: "event";
378
+ author: string;
379
+ logMessageBody: string;
380
+ logMessageData: any;
381
+ logMessageType: "log:thread-call";
382
+ threadID: string;
383
+ participantIDs: string[];
384
+ }
385
+ | {
386
+ type: "typ";
387
+ from: string;
388
+ fromMobile: boolean;
389
+ isTyping: boolean;
390
+ threadID: string;
391
+ }
392
+ | {
393
+ type: "read";
394
+ threadID: string;
395
+ time: number;
396
+ }
397
+ | {
398
+ type: "read_receipt";
399
+ reader: string;
400
+ threadID: string;
401
+ time: number;
402
+ }
403
+ | {
404
+ type: "message_reaction";
405
+ threadID: string;
406
+ messageID: string;
407
+ reaction: string;
408
+ senderID: string;
409
+ userID: string;
410
+ reactionTimestamp: number;
411
+ }
412
+ | {
413
+ type: "presence";
414
+ statuses: number;
415
+ timestamp: number;
416
+ userID: string;
417
+ }
418
+ | {
419
+ type: "message_unsend";
420
+ threadID: string;
421
+ senderID: string;
422
+ messageID: string;
423
+ deletionTimestamp: number;
424
+ }
425
+ | {
426
+ type: "message_reply";
427
+ attachments: IFCAU_Attachment[];
428
+ args: string[];
429
+ body: string;
430
+ isGroup: boolean;
431
+ mentions: { [id: string]: string };
432
+ messageID: string;
433
+ senderID: string;
434
+ threadID: string;
435
+ isUnread: boolean;
436
+ participantIDs: string[];
437
+ messageReply: {
438
+ attachments: IFCAU_Attachment[];
439
+ body: string;
440
+ isGroup: boolean;
441
+ mentions: { [id: string]: string };
442
+ messageID: string;
443
+ senderID: string;
444
+ threadID: string;
445
+ isUnread: boolean;
446
+ };
447
+ };
226
448
 
227
- await this.behavior.warmUp();
228
-
229
- try { this.session.save(api.getAppState(), true); } catch(_) {}
230
-
231
- this._startSystems(api, this._ctx || {});
232
-
233
- return api;
234
- }
449
+ // ============================================================================
450
+ // Attachment Types
451
+ // ============================================================================
452
+
453
+ export type IFCAU_Attachment =
454
+ | {
455
+ type: "sticker";
456
+ ID: string;
457
+ url: string;
458
+ packID: string;
459
+ spriteUrl: string;
460
+ spriteUrl2x: string;
461
+ width: number;
462
+ height: number;
463
+ caption: string;
464
+ description: string;
465
+ frameCount: number;
466
+ frameRate: number;
467
+ framesPerRow: number;
468
+ framesPerCol: number;
469
+ }
470
+ | {
471
+ type: "file";
472
+ ID: string;
473
+ filename: string;
474
+ url: string;
475
+ isMalicious: boolean;
476
+ contentType: string;
477
+ }
478
+ | {
479
+ type: "photo";
480
+ ID: string;
481
+ filename: string;
482
+ thumbnailUrl: string;
483
+ previewUrl: string;
484
+ previewWidth: number;
485
+ previewHeight: number;
486
+ largePreviewUrl: string;
487
+ largePreviewWidth: number;
488
+ largePreviewHeight: number;
489
+ url: string;
490
+ width: number;
491
+ height: number;
492
+ }
493
+ | {
494
+ type: "animated_image";
495
+ ID: string;
496
+ filename: string;
497
+ previewUrl: string;
498
+ previewWidth: number;
499
+ previewHeight: number;
500
+ url: string;
501
+ width: number;
502
+ height: number;
503
+ }
504
+ | {
505
+ type: "video";
506
+ ID: string;
507
+ filename: string;
508
+ previewUrl: string;
509
+ previewWidth: number;
510
+ previewHeight: number;
511
+ url: string;
512
+ width: number;
513
+ height: number;
514
+ duration: number;
515
+ videoType: string;
516
+ }
517
+ | {
518
+ type: "audio";
519
+ ID: string;
520
+ filename: string;
521
+ audioType: string;
522
+ duration: number;
523
+ url: string;
524
+ isVoiceMail: boolean;
525
+ }
526
+ | {
527
+ type: "location";
528
+ ID: string;
529
+ latitude: number;
530
+ longitude: number;
531
+ image: string;
532
+ width: number;
533
+ height: number;
534
+ url: string;
535
+ address: string;
536
+ }
537
+ | {
538
+ type: "share";
539
+ ID: string;
540
+ url: string;
541
+ title: string;
542
+ description: string;
543
+ source: string;
544
+ image: string;
545
+ width: number;
546
+ height: number;
547
+ playable: boolean;
548
+ duration: number;
549
+ playableUrl: string;
550
+ subattachments: any;
551
+ properties: any;
552
+ };
235
553
 
236
- wrapSendMessage(api) {
237
- const original = api.sendMessage.bind(api);
238
- api.sendMessage = (msg, threadID, callback, messageID) => {
239
- this.behavior.antiRepeatDelay("send", typeof msg === "string" ? msg.slice(0, 30) : "obj");
554
+ // ============================================================================
555
+ // User Types
556
+ // ============================================================================
557
+
558
+ export type IFCAU_User = {
559
+ name: string;
560
+ firstName?: string;
561
+ vanity?: string;
562
+ thumbSrc: string;
563
+ profileUrl: string | null;
564
+ gender?: number;
565
+ type: string;
566
+ isFriend?: boolean;
567
+ isBirthday: boolean;
568
+ searchToken: any;
569
+ alternateName?: string;
570
+ };
571
+
572
+ export type IFCAU_UserIDResponse = {
573
+ userID: string;
574
+ photoUrl: string;
575
+ indexRank: number;
576
+ name: string;
577
+ isVerified: boolean;
578
+ profileUrl: string;
579
+ category: string;
580
+ score: number;
581
+ type: string;
582
+ }[];
583
+
584
+ export type IFCAU_Friend = {
585
+ alternativeName: string;
586
+ firstName: string;
587
+ gender: string;
588
+ userID: string;
589
+ isFriend: boolean;
590
+ fullName: string;
591
+ profilePicture: string;
592
+ type: string;
593
+ profileUrl: string;
594
+ vanity: string;
595
+ isBirthday: boolean;
596
+ };
597
+
598
+ // ============================================================================
599
+ // Thread Types
600
+ // ============================================================================
601
+
602
+ export type IFCAU_Thread = {
603
+ threadID: string;
604
+ participantIDs: string[];
605
+ threadName: string;
606
+ userInfo: (IFCAU_User & { id: string })[];
607
+ nicknames: { [id: string]: string } | null;
608
+ unreadCount: number;
609
+ messageCount: number;
610
+ imageSrc: string;
611
+ timestamp: number;
612
+ muteUntil: number | null;
613
+ isGroup: boolean;
614
+ isSubscribed: boolean;
615
+ folder: 'INBOX' | 'ARCHIVE' | string;
616
+ isArchived: boolean;
617
+ cannotReplyReason: string | null;
618
+ lastReadTimestamp: number;
619
+ emoji: string | null;
620
+ color: string | null;
621
+ adminIDs: string[];
622
+ approvalMode: boolean;
623
+ approvalQueue: { inviterID: string; requesterID: string; timestamp: string }[];
624
+ };
625
+
626
+ export type IFCAU_ThreadList = {
627
+ threadID: string;
628
+ name: string;
629
+ unreadCount: number;
630
+ messageCount: number;
631
+ imageSrc: string;
632
+ emoji: string | null;
633
+ color: string | null;
634
+ nicknames: { userid: string; nickname: string }[];
635
+ muteUntil: number | null;
636
+ participants: IFCAU_ThreadList_Participants[];
637
+ adminIDs: string[];
638
+ folder: "INBOX" | "ARCHIVED" | "PENNDING" | "OTHER" | string;
639
+ isGroup: boolean;
640
+ customizationEnabled: boolean;
641
+ participantAddMode: string;
642
+ reactionMuteMode: string;
643
+ isArchived: boolean;
644
+ isSubscribed: boolean;
645
+ timestamp: number;
646
+ snippet: string;
647
+ snippetAttachments: string;
648
+ snippetSender: string;
649
+ lastMessageTimestamp: number;
650
+ listReadTimestamp: number | null;
651
+ cannotReplyReason: string | null;
652
+ approvalMode: string;
653
+ }[];
654
+
655
+ export type IFCAU_ThreadList_Participants =
656
+ | {
657
+ accountType: "User";
658
+ userID: string;
659
+ name: string;
660
+ shortName: string;
661
+ gender: string;
662
+ url: string;
663
+ profilePicture: string;
664
+ username: string | null;
665
+ isViewerFriend: boolean;
666
+ isMessengerUser: boolean;
667
+ isVerified: boolean;
668
+ isMessageBlockedByViewer: boolean;
669
+ isViewerCoworker: boolean;
670
+ }
671
+ | {
672
+ accountType: "Page";
673
+ userID: string;
674
+ name: string;
675
+ url: string;
676
+ profilePicture: string;
677
+ username: string | null;
678
+ acceptMessengerUserFeedback: boolean;
679
+ isMessengerUser: boolean;
680
+ isVerified: boolean;
681
+ isMessengerPlatformBot: boolean;
682
+ isMessageBlockedByViewer: boolean;
683
+ }
684
+ | {
685
+ accountType: "ReducedMessagingActor";
686
+ userID: string;
687
+ name: string;
688
+ url: string;
689
+ profilePicture: string;
690
+ username: string | null;
691
+ acceptMessengerUserFeedback: boolean;
692
+ isMessageBlockedByViewer: boolean;
693
+ }
694
+ | {
695
+ accountType: "UnavailableMessagingActor";
696
+ userID: string;
697
+ name: string;
698
+ url: null;
699
+ profilePicture: string;
700
+ username: null;
701
+ acceptMessengerUserFeedback: boolean;
702
+ isMessageBlockedByViewer: boolean;
703
+ }
704
+ | {
705
+ accountType: string;
706
+ userID: string;
707
+ name: string;
708
+ };
240
709
 
241
- this.queue.enqueue(async () => {
242
- await this.cooldown.waitBeforeSend();
243
- const start = Date.now();
244
- return new Promise((res, rej) => {
245
- original(msg, threadID, (err, info) => {
246
- this.cooldown.recordLatency(Date.now() - start);
247
- if (err) { this.cooldown.recordError(); if (callback) callback(err); rej(err); }
248
- else { this.cooldown.recordSuccess(); if (callback) callback(null, info); res(info); }
249
- }, messageID);
250
- });
251
- }, { threadID });
710
+ // ============================================================================
711
+ // Middleware Types
712
+ // ============================================================================
713
+
714
+ export type IFCAU_Middleware = (event: IFCAU_ListenMessage, next: (err?: Error | false | null) => void) => void | Promise<void> | false | null;
715
+
716
+ // ============================================================================
717
+ // Scheduler Types
718
+ // ============================================================================
719
+
720
+ export type IFCAU_ScheduledMessage = {
721
+ id: string;
722
+ message: string | MessageObject;
723
+ threadID: string | string[];
724
+ timestamp: number;
725
+ createdAt: number;
726
+ options: {
727
+ replyMessageID?: string;
728
+ isGroup?: boolean;
729
+ callback?: (err?: Error) => void;
252
730
  };
253
- logger.info("ULTRA: sendMessage wrapped ✅", "ULTRA");
254
- }
255
-
256
- async stop() {
257
- this._stopSystems();
258
- try { if (this._api?.stopListening) this._api.stopListening(); } catch(_) {}
259
- logger.info("ULTRA: موقوف ✅", "ULTRA");
260
- }
261
-
262
- get api() { return this._api; }
263
- get ctx() { return this._ctx; }
264
- getHealth() { return this.health.getStats(); }
265
- getCooldown() { return this.cooldown.getStats(); }
266
- getQueue() { return this.queue.getStats(); }
267
- getGeo() { return this.geo.getStats(); }
268
- getSilent() { return this.silent.getStats(); }
731
+ timeUntilSend: number;
732
+ };
733
+
734
+ // ============================================================================
735
+ // Options Type
736
+ // ============================================================================
737
+
738
+ export type IFCAU_Options = {
739
+ pauseLog: boolean;
740
+ logLevel: "silly" | "verbose" | "info" | "http" | "warn" | "error" | "silent";
741
+ selfListen: boolean;
742
+ listenEvents: boolean;
743
+ pageID: string;
744
+ updatePresence: boolean;
745
+ forceLogin: boolean;
746
+ userAgent: string;
747
+ autoMarkRead: boolean;
748
+ proxy: string;
749
+ online: boolean;
750
+ };
269
751
  }
270
-
271
- module.exports = AymanFCAUltra;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ayman-fca",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "Facebook Chat API for Node.js — مكتبة KIRA بوت | © 2025 Ayman",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",