nodejs-insta-private-api-mqt 1.3.70

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 (240) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3677 -0
  3. package/dist/constants/constants.js +342 -0
  4. package/dist/constants/index.js +58 -0
  5. package/dist/core/client.js +419 -0
  6. package/dist/core/nav-chain.js +282 -0
  7. package/dist/core/repository.js +7 -0
  8. package/dist/core/request.js +390 -0
  9. package/dist/core/state.js +1473 -0
  10. package/dist/core/utils.js +786 -0
  11. package/dist/downloadMedia.js +381 -0
  12. package/dist/errors/index.d.ts +16 -0
  13. package/dist/errors/index.js +38 -0
  14. package/dist/errors/index.js.map +1 -0
  15. package/dist/extend.js +167 -0
  16. package/dist/fbns/fbns.client.d.ts +32 -0
  17. package/dist/fbns/fbns.client.events.d.ts +41 -0
  18. package/dist/fbns/fbns.client.events.js +3 -0
  19. package/dist/fbns/fbns.client.events.js.map +1 -0
  20. package/dist/fbns/fbns.client.js +252 -0
  21. package/dist/fbns/fbns.client.js.map +1 -0
  22. package/dist/fbns/fbns.device-auth.d.ts +17 -0
  23. package/dist/fbns/fbns.device-auth.js +54 -0
  24. package/dist/fbns/fbns.device-auth.js.map +1 -0
  25. package/dist/fbns/fbns.types.d.ts +83 -0
  26. package/dist/fbns/fbns.types.js +3 -0
  27. package/dist/fbns/fbns.types.js.map +1 -0
  28. package/dist/fbns/fbns.utilities.d.ts +2 -0
  29. package/dist/fbns/fbns.utilities.js +79 -0
  30. package/dist/fbns/fbns.utilities.js.map +1 -0
  31. package/dist/fbns/index.d.ts +4 -0
  32. package/dist/fbns/index.js +21 -0
  33. package/dist/fbns/index.js.map +1 -0
  34. package/dist/index.js +139 -0
  35. package/dist/mqtt-shim.d.ts +96 -0
  36. package/dist/mqtt-shim.js +15 -0
  37. package/dist/mqttot/index.d.ts +4 -0
  38. package/dist/mqttot/index.js +21 -0
  39. package/dist/mqttot/index.js.map +1 -0
  40. package/dist/mqttot/mqttot.client.d.ts +39 -0
  41. package/dist/mqttot/mqttot.client.js +318 -0
  42. package/dist/mqttot/mqttot.client.js.map +1 -0
  43. package/dist/mqttot/mqttot.connect.request.packet.d.ts +7 -0
  44. package/dist/mqttot/mqttot.connect.request.packet.js +9 -0
  45. package/dist/mqttot/mqttot.connect.request.packet.js.map +1 -0
  46. package/dist/mqttot/mqttot.connect.response.packet.d.ts +7 -0
  47. package/dist/mqttot/mqttot.connect.response.packet.js +24 -0
  48. package/dist/mqttot/mqttot.connect.response.packet.js.map +1 -0
  49. package/dist/mqttot/mqttot.connection.d.ts +57 -0
  50. package/dist/mqttot/mqttot.connection.js +79 -0
  51. package/dist/mqttot/mqttot.connection.js.map +1 -0
  52. package/dist/package.json +59 -0
  53. package/dist/realtime/commands/commands.d.ts +15 -0
  54. package/dist/realtime/commands/commands.js +71 -0
  55. package/dist/realtime/commands/commands.js.map +1 -0
  56. package/dist/realtime/commands/direct.commands.d.ts +75 -0
  57. package/dist/realtime/commands/direct.commands.js +417 -0
  58. package/dist/realtime/commands/direct.commands.js.map +1 -0
  59. package/dist/realtime/commands/enhanced.direct.commands.js +1731 -0
  60. package/dist/realtime/commands/enhanced.direct.commands.js.bak +967 -0
  61. package/dist/realtime/commands/index.d.ts +2 -0
  62. package/dist/realtime/commands/index.js +20 -0
  63. package/dist/realtime/commands/index.js.map +1 -0
  64. package/dist/realtime/delta-sync.manager.js +293 -0
  65. package/dist/realtime/features/dm-sender.js +88 -0
  66. package/dist/realtime/features/error-handler.js +185 -0
  67. package/dist/realtime/features/gap-handler.js +61 -0
  68. package/dist/realtime/features/persistent-logger.js +186 -0
  69. package/dist/realtime/features/presence.manager.js +66 -0
  70. package/dist/realtime/features/session-health-monitor.js +345 -0
  71. package/dist/realtime/index.js +30 -0
  72. package/dist/realtime/messages/app-presence.event.d.ts +9 -0
  73. package/dist/realtime/messages/app-presence.event.js +3 -0
  74. package/dist/realtime/messages/app-presence.event.js.map +1 -0
  75. package/dist/realtime/messages/index.d.ts +3 -0
  76. package/dist/realtime/messages/index.js +20 -0
  77. package/dist/realtime/messages/index.js.map +1 -0
  78. package/dist/realtime/messages/message-sync.message.d.ts +222 -0
  79. package/dist/realtime/messages/message-sync.message.js +43 -0
  80. package/dist/realtime/messages/message-sync.message.js.map +1 -0
  81. package/dist/realtime/messages/realtime-sub.direct.data.d.ts +11 -0
  82. package/dist/realtime/messages/realtime-sub.direct.data.js +3 -0
  83. package/dist/realtime/messages/realtime-sub.direct.data.js.map +1 -0
  84. package/dist/realtime/messages/thread-update.message.d.ts +68 -0
  85. package/dist/realtime/messages/thread-update.message.js +3 -0
  86. package/dist/realtime/messages/thread-update.message.js.map +1 -0
  87. package/dist/realtime/mixins/index.d.ts +3 -0
  88. package/dist/realtime/mixins/index.js +20 -0
  89. package/dist/realtime/mixins/index.js.map +1 -0
  90. package/dist/realtime/mixins/message-sync.mixin.d.ts +8 -0
  91. package/dist/realtime/mixins/message-sync.mixin.js +596 -0
  92. package/dist/realtime/mixins/message-sync.mixin.js.map +1 -0
  93. package/dist/realtime/mixins/mixin.d.ts +19 -0
  94. package/dist/realtime/mixins/mixin.js +41 -0
  95. package/dist/realtime/mixins/mixin.js.map +1 -0
  96. package/dist/realtime/mixins/presence-typing.mixin.js +33 -0
  97. package/dist/realtime/mixins/realtime-sub.mixin.d.ts +8 -0
  98. package/dist/realtime/mixins/realtime-sub.mixin.js +181 -0
  99. package/dist/realtime/mixins/realtime-sub.mixin.js.map +1 -0
  100. package/dist/realtime/parsers/graphql-parser.js +43 -0
  101. package/dist/realtime/parsers/graphql.parser.d.ts +15 -0
  102. package/dist/realtime/parsers/graphql.parser.js +22 -0
  103. package/dist/realtime/parsers/graphql.parser.js.map +1 -0
  104. package/dist/realtime/parsers/index.d.ts +6 -0
  105. package/dist/realtime/parsers/index.js +23 -0
  106. package/dist/realtime/parsers/index.js.map +1 -0
  107. package/dist/realtime/parsers/iris-parser.js +43 -0
  108. package/dist/realtime/parsers/iris.parser.d.ts +17 -0
  109. package/dist/realtime/parsers/iris.parser.js +10 -0
  110. package/dist/realtime/parsers/iris.parser.js.map +1 -0
  111. package/dist/realtime/parsers/json-parser.js +43 -0
  112. package/dist/realtime/parsers/json.parser.d.ts +6 -0
  113. package/dist/realtime/parsers/json.parser.js +10 -0
  114. package/dist/realtime/parsers/json.parser.js.map +1 -0
  115. package/dist/realtime/parsers/parser.d.ts +9 -0
  116. package/dist/realtime/parsers/parser.js +3 -0
  117. package/dist/realtime/parsers/parser.js.map +1 -0
  118. package/dist/realtime/parsers/region-hint-parser.js +43 -0
  119. package/dist/realtime/parsers/region-hint.parser.d.ts +12 -0
  120. package/dist/realtime/parsers/region-hint.parser.js +15 -0
  121. package/dist/realtime/parsers/region-hint.parser.js.map +1 -0
  122. package/dist/realtime/parsers/skywalker-parser.js +43 -0
  123. package/dist/realtime/parsers/skywalker.parser.d.ts +12 -0
  124. package/dist/realtime/parsers/skywalker.parser.js +15 -0
  125. package/dist/realtime/parsers/skywalker.parser.js.map +1 -0
  126. package/dist/realtime/parsers-advanced.js +158 -0
  127. package/dist/realtime/proto/common.proto +38 -0
  128. package/dist/realtime/proto/direct.proto +65 -0
  129. package/dist/realtime/proto/ig-messages.proto +83 -0
  130. package/dist/realtime/proto/iris.proto +188 -0
  131. package/dist/realtime/proto-parser.js +195 -0
  132. package/dist/realtime/protocols/iris.handshake.js +74 -0
  133. package/dist/realtime/protocols/proto-definitions.js +80 -0
  134. package/dist/realtime/protocols/skywalker.protocol.js +91 -0
  135. package/dist/realtime/realtime.client.events.js +3 -0
  136. package/dist/realtime/realtime.client.js +1915 -0
  137. package/dist/realtime/realtime.service.js +462 -0
  138. package/dist/realtime/reconnect.manager.js +88 -0
  139. package/dist/realtime/session.manager.js +121 -0
  140. package/dist/realtime/subscriptions/graphql.subscription.d.ts +47 -0
  141. package/dist/realtime/subscriptions/graphql.subscription.js +99 -0
  142. package/dist/realtime/subscriptions/graphql.subscription.js.map +1 -0
  143. package/dist/realtime/subscriptions/index.d.ts +2 -0
  144. package/dist/realtime/subscriptions/index.js +19 -0
  145. package/dist/realtime/subscriptions/index.js.map +1 -0
  146. package/dist/realtime/subscriptions/skywalker.subscription.d.ts +4 -0
  147. package/dist/realtime/subscriptions/skywalker.subscription.js +13 -0
  148. package/dist/realtime/subscriptions/skywalker.subscription.js.map +1 -0
  149. package/dist/realtime/topic-map.js +71 -0
  150. package/dist/realtime/topic.js +80 -0
  151. package/dist/repositories/account.repository.js +575 -0
  152. package/dist/repositories/bloks.repository.js +70 -0
  153. package/dist/repositories/captcha.repository.js +44 -0
  154. package/dist/repositories/challenge.repository.js +120 -0
  155. package/dist/repositories/clip.repository.js +165 -0
  156. package/dist/repositories/close-friends.repository.js +46 -0
  157. package/dist/repositories/collection.repository.js +68 -0
  158. package/dist/repositories/direct-thread.repository.js +446 -0
  159. package/dist/repositories/direct.repository.js +232 -0
  160. package/dist/repositories/explore.repository.js +70 -0
  161. package/dist/repositories/fbsearch.repository.js +140 -0
  162. package/dist/repositories/feed.repository.js +245 -0
  163. package/dist/repositories/friendship.repository.js +296 -0
  164. package/dist/repositories/fundraiser.repository.js +49 -0
  165. package/dist/repositories/hashtag.repository.js +99 -0
  166. package/dist/repositories/highlights.repository.js +121 -0
  167. package/dist/repositories/insights.repository.js +82 -0
  168. package/dist/repositories/location.repository.js +84 -0
  169. package/dist/repositories/media.repository.js +395 -0
  170. package/dist/repositories/multiple-accounts.repository.js +41 -0
  171. package/dist/repositories/news.repository.js +35 -0
  172. package/dist/repositories/note.repository.js +57 -0
  173. package/dist/repositories/notification.repository.js +79 -0
  174. package/dist/repositories/share.repository.js +35 -0
  175. package/dist/repositories/signup.repository.js +218 -0
  176. package/dist/repositories/story.repository.js +290 -0
  177. package/dist/repositories/timeline.repository.js +60 -0
  178. package/dist/repositories/totp.repository.js +139 -0
  179. package/dist/repositories/track.repository.js +53 -0
  180. package/dist/repositories/upload.repository.js +204 -0
  181. package/dist/repositories/user.repository.js +360 -0
  182. package/dist/sendmedia/index.js +27 -0
  183. package/dist/sendmedia/sendFile.js +72 -0
  184. package/dist/sendmedia/sendPhoto.js +142 -0
  185. package/dist/sendmedia/sendRavenPhoto.js +153 -0
  186. package/dist/sendmedia/sendRavenVideo.js +158 -0
  187. package/dist/sendmedia/uploadPhoto.js +107 -0
  188. package/dist/sendmedia/uploadfFile.js +130 -0
  189. package/dist/services/live.service.js +139 -0
  190. package/dist/services/search.service.js +115 -0
  191. package/dist/shared/index.js +96 -0
  192. package/dist/shared/shared.js +86 -0
  193. package/dist/thrift/index.d.ts +3 -0
  194. package/dist/thrift/index.js +20 -0
  195. package/dist/thrift/index.js.map +1 -0
  196. package/dist/thrift/thrift.d.ts +59 -0
  197. package/dist/thrift/thrift.js +101 -0
  198. package/dist/thrift/thrift.js.map +1 -0
  199. package/dist/thrift/thrift.reading.d.ts +41 -0
  200. package/dist/thrift/thrift.reading.js +327 -0
  201. package/dist/thrift/thrift.reading.js.map +1 -0
  202. package/dist/thrift/thrift.writing.d.ts +44 -0
  203. package/dist/thrift/thrift.writing.js +342 -0
  204. package/dist/thrift/thrift.writing.js.map +1 -0
  205. package/dist/types/index.js +285 -0
  206. package/dist/useMultiFileAuthState.js +1768 -0
  207. package/dist/utils/helper-1.js +1 -0
  208. package/dist/utils/helper-10.js +1 -0
  209. package/dist/utils/helper-11.js +1 -0
  210. package/dist/utils/helper-12.js +1 -0
  211. package/dist/utils/helper-13.js +1 -0
  212. package/dist/utils/helper-14.js +1 -0
  213. package/dist/utils/helper-15.js +1 -0
  214. package/dist/utils/helper-16.js +1 -0
  215. package/dist/utils/helper-17.js +1 -0
  216. package/dist/utils/helper-18.js +1 -0
  217. package/dist/utils/helper-19.js +1 -0
  218. package/dist/utils/helper-2.js +1 -0
  219. package/dist/utils/helper-20.js +1 -0
  220. package/dist/utils/helper-21.js +1 -0
  221. package/dist/utils/helper-22.js +1 -0
  222. package/dist/utils/helper-23.js +1 -0
  223. package/dist/utils/helper-24.js +1 -0
  224. package/dist/utils/helper-25.js +1 -0
  225. package/dist/utils/helper-26.js +1 -0
  226. package/dist/utils/helper-27.js +1 -0
  227. package/dist/utils/helper-28.js +1 -0
  228. package/dist/utils/helper-29.js +1 -0
  229. package/dist/utils/helper-3.js +1 -0
  230. package/dist/utils/helper-30.js +1 -0
  231. package/dist/utils/helper-4.js +1 -0
  232. package/dist/utils/helper-5.js +1 -0
  233. package/dist/utils/helper-6.js +1 -0
  234. package/dist/utils/helper-7.js +1 -0
  235. package/dist/utils/helper-8.js +1 -0
  236. package/dist/utils/helper-9.js +1 -0
  237. package/dist/utils/index.js +280 -0
  238. package/dist/utils/insta-mqtt-helper.js +128 -0
  239. package/examples/listen-to-messages.js +86 -0
  240. package/package.json +82 -0
@@ -0,0 +1,596 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MessageSyncMixin = void 0;
4
+ const mixin_1 = require("./mixin");
5
+ const constants_1 = require("../../constants");
6
+ const shared_1 = require("../../shared")
7
+ const mqtts_1 = require("mqtts");
8
+
9
+ /**
10
+ * MessageSyncMixin - patched for 2026 (robust parsing + safe username fetch + tolerant timestamp handling)
11
+ *
12
+ * Changes applied:
13
+ * - tolerant parsing for e.value (string / object / already-parsed)
14
+ * - support for several path shapes when extracting thread id
15
+ * - safer timestamp parsing (accepts seconds, milliseconds, microseconds, nanoseconds)
16
+ * - username fetch uses a pending map + small backoff to reduce rush/rate-limit risk
17
+ * - defensive try/catch around JSON.parse and all external calls
18
+ * - keeps original API: apply(client) registers post-connect hook and emits same events
19
+ *
20
+ * Additional change requested:
21
+ * - set message status to 'received' for incoming messages and 'sent' for messages authored by the logged-in account,
22
+ * instead of the previous 'good'.
23
+ *
24
+ * Note: No rate-limiting code is included.
25
+ */
26
+
27
+ class MessageSyncMixin extends mixin_1.Mixin {
28
+ constructor() {
29
+ super();
30
+ this.userCache = new Map();
31
+ this.pendingUserFetches = new Map();
32
+ }
33
+
34
+ apply(client) {
35
+ console.log(`\n[MESSAGE_SYNC MIXIN] Applying mixin...`);
36
+
37
+ (0, mixin_1.hook)(client, 'connect', {
38
+ post: async () => {
39
+ console.log(`[MESSAGE_SYNC] Post-connect hook called`);
40
+
41
+ let retries = 0;
42
+ while (!client.mqtt && retries < 50) {
43
+ await new Promise(r => setTimeout(r, 100));
44
+ retries++;
45
+ }
46
+ if (!client.mqtt) {
47
+ throw new mqtts_1.IllegalStateError('No mqtt client created after retries');
48
+ }
49
+
50
+ console.log(`[MESSAGE_SYNC] MQTT ready, registering listen() on topic 146 (MESSAGE_SYNC)`);
51
+
52
+ if (client.mqtt.listen) {
53
+ console.log(`[MESSAGE_SYNC] mqtt.listen() method found, registering callback...`);
54
+ client.mqtt.listen({
55
+ topic: constants_1.Topics.MESSAGE_SYNC.id,
56
+ transformer: async ({ payload }) => {
57
+ try {
58
+ const unzipped = await (0, shared_1.tryUnzipAsync)(payload);
59
+ const parsed = constants_1.Topics.MESSAGE_SYNC.parser
60
+ .parseMessage(constants_1.Topics.MESSAGE_SYNC, unzipped)
61
+ .map(msg => msg.data);
62
+ return parsed;
63
+ } catch (err) {
64
+ // If transformer fails, return empty array so handler is tolerant
65
+ console.warn('[MESSAGE_SYNC] transformer parse failed:', err?.message || err);
66
+ return [];
67
+ }
68
+ },
69
+ }, data => {
70
+ this.handleMessageSync(client, data);
71
+ });
72
+ } else {
73
+ console.log(`[MESSAGE_SYNC] mqtt.listen() NOT FOUND - using fallback 'receive' event`);
74
+ client.on('receive', (topic, messages) => {
75
+ try {
76
+ if (topic.id === constants_1.Topics.MESSAGE_SYNC.id) {
77
+ const data = messages.map(m => m.data);
78
+ this.handleMessageSync(client, data);
79
+ }
80
+ } catch (err) {
81
+ console.warn('[MESSAGE_SYNC] receive fallback handler error:', err?.message || err);
82
+ }
83
+ });
84
+ }
85
+ },
86
+ });
87
+ }
88
+
89
+ async getUsernameFromId(client, userId) {
90
+ if (!userId) return null;
91
+
92
+ const userIdStr = String(userId);
93
+
94
+ if (this.userCache.has(userIdStr)) {
95
+ return this.userCache.get(userIdStr);
96
+ }
97
+
98
+ if (this.pendingUserFetches.has(userIdStr)) {
99
+ try {
100
+ return await this.pendingUserFetches.get(userIdStr);
101
+ } catch (e) {
102
+ // if pending fetch failed, continue to fresh attempt
103
+ }
104
+ }
105
+
106
+ const fetchPromise = (async () => {
107
+ try {
108
+ // small backoff to avoid immediate burst of parallel requests
109
+ await new Promise(r => setTimeout(r, 120));
110
+ if (client.ig && client.ig.user && client.ig.user.info) {
111
+ try {
112
+ const userInfo = await client.ig.user.info(userIdStr);
113
+ if (userInfo && userInfo.username) {
114
+ this.userCache.set(userIdStr, userInfo.username);
115
+ return userInfo.username;
116
+ }
117
+ } catch (innerErr) {
118
+ // rate-limited or not found - swallow
119
+ }
120
+ }
121
+ } catch (err) {
122
+ // Silently fail - will use ID instead
123
+ }
124
+ return null;
125
+ })();
126
+
127
+ this.pendingUserFetches.set(userIdStr, fetchPromise);
128
+ const result = await fetchPromise;
129
+ this.pendingUserFetches.delete(userIdStr);
130
+
131
+ return result;
132
+ }
133
+
134
+ extractMessageContent(msgValue, itemType) {
135
+ let content = '';
136
+ let mediaInfo = '';
137
+
138
+ try {
139
+ switch (itemType) {
140
+ case 'text':
141
+ content = msgValue.text || msgValue.body || '';
142
+ break;
143
+
144
+ case 'media':
145
+ case 'raven_media':
146
+ content = '[PHOTO/VIDEO]';
147
+ if (msgValue.media) {
148
+ const media = msgValue.media;
149
+ if (media.image_versions2) {
150
+ content = '[PHOTO]';
151
+ mediaInfo = ` URL: ${media.image_versions2?.candidates?.[0]?.url || 'N/A'}`;
152
+ } else if (media.video_versions) {
153
+ content = '[VIDEO]';
154
+ mediaInfo = ` Duration: ${media.video_duration || 'N/A'}s`;
155
+ }
156
+ }
157
+ if (msgValue.visual_media) {
158
+ content = '[DISAPPEARING MEDIA]';
159
+ }
160
+ break;
161
+
162
+ case 'voice_media':
163
+ content = '[VOICE MESSAGE]';
164
+ if (msgValue.voice_media?.media?.audio) {
165
+ const duration = msgValue.voice_media.media.audio.duration || 0;
166
+ content = `[VOICE MESSAGE] Duration: ${duration}ms`;
167
+ }
168
+ break;
169
+
170
+ case 'animated_media':
171
+ content = '[GIF]';
172
+ if (msgValue.animated_media?.images?.fixed_height?.url) {
173
+ mediaInfo = ` URL: ${msgValue.animated_media.images.fixed_height.url}`;
174
+ }
175
+ break;
176
+
177
+ case 'media_share':
178
+ content = '[SHARED POST]';
179
+ if (msgValue.media_share) {
180
+ const share = msgValue.media_share;
181
+ content = `[SHARED POST] From: @${share.user?.username || 'unknown'}`;
182
+ if (share.caption?.text) {
183
+ content += ` Caption: "${String(share.caption.text).substring(0, 50)}..."`;
184
+ }
185
+ }
186
+ break;
187
+
188
+ case 'reel_share':
189
+ content = '[SHARED REEL]';
190
+ if (msgValue.reel_share) {
191
+ const reel = msgValue.reel_share;
192
+ content = `[SHARED REEL] From: @${reel.media?.user?.username || 'unknown'}`;
193
+ if (reel.text) {
194
+ content += ` Text: "${reel.text}"`;
195
+ }
196
+ }
197
+ break;
198
+
199
+ case 'story_share':
200
+ content = '[SHARED STORY]';
201
+ if (msgValue.story_share) {
202
+ const story = msgValue.story_share;
203
+ content = `[SHARED STORY] From: @${story.media?.user?.username || 'unknown'}`;
204
+ if (story.message) {
205
+ content += ` Message: "${story.message}"`;
206
+ }
207
+ }
208
+ break;
209
+
210
+ case 'felix_share':
211
+ content = '[SHARED IGTV/VIDEO]';
212
+ if (msgValue.felix_share?.video) {
213
+ content = `[SHARED IGTV] Title: "${msgValue.felix_share.video.title || 'N/A'}"`;
214
+ }
215
+ break;
216
+
217
+ case 'clip':
218
+ content = '[SHARED CLIP]';
219
+ if (msgValue.clip?.clip) {
220
+ content = `[SHARED CLIP] From: @${msgValue.clip.clip.user?.username || 'unknown'}`;
221
+ }
222
+ break;
223
+
224
+ case 'profile':
225
+ content = '[SHARED PROFILE]';
226
+ if (msgValue.profile) {
227
+ content = `[SHARED PROFILE] @${msgValue.profile.username || 'unknown'}`;
228
+ }
229
+ break;
230
+
231
+ case 'location':
232
+ content = '[LOCATION]';
233
+ if (msgValue.location) {
234
+ content = `[LOCATION] ${msgValue.location.name || msgValue.location.address || 'Unknown location'}`;
235
+ }
236
+ break;
237
+
238
+ case 'hashtag':
239
+ content = '[HASHTAG]';
240
+ if (msgValue.hashtag) {
241
+ content = `[HASHTAG] #${msgValue.hashtag.name || 'unknown'}`;
242
+ }
243
+ break;
244
+
245
+ case 'like':
246
+ content = '[LIKE]';
247
+ break;
248
+
249
+ case 'link':
250
+ content = '[LINK]';
251
+ if (msgValue.link) {
252
+ content = `[LINK] ${msgValue.link.text || msgValue.link.link_url || 'N/A'}`;
253
+ }
254
+ break;
255
+
256
+ case 'action_log':
257
+ content = '[ACTION]';
258
+ if (msgValue.action_log) {
259
+ content = `[ACTION] ${msgValue.action_log.description || 'N/A'}`;
260
+ }
261
+ break;
262
+
263
+ case 'placeholder':
264
+ content = '[PLACEHOLDER]';
265
+ if (msgValue.placeholder?.message) {
266
+ content = `[PLACEHOLDER] ${msgValue.placeholder.message}`;
267
+ }
268
+ break;
269
+
270
+ case 'xma':
271
+ case 'xma_media_share':
272
+ content = '[XMA SHARE]';
273
+ if (msgValue.xma_link_url) {
274
+ content = `[XMA SHARE] ${msgValue.xma_link_url}`;
275
+ }
276
+ break;
277
+
278
+ case 'video_call_event':
279
+ content = '[VIDEO CALL EVENT]';
280
+ if (msgValue.video_call_event) {
281
+ content = `[VIDEO CALL] ${msgValue.video_call_event.action || 'event'}`;
282
+ }
283
+ break;
284
+
285
+ default:
286
+ if (msgValue && (msgValue.text || msgValue.body)) {
287
+ content = msgValue.text || msgValue.body;
288
+ } else {
289
+ content = `[${(itemType || 'UNKNOWN').toUpperCase()}]`;
290
+ }
291
+ }
292
+ } catch (e) {
293
+ // defensive fallback
294
+ try {
295
+ if (msgValue && (msgValue.text || msgValue.body)) {
296
+ content = msgValue.text || msgValue.body;
297
+ } else {
298
+ content = `[${(itemType || 'UNKNOWN').toUpperCase()}]`;
299
+ }
300
+ } catch (e2) {
301
+ content = `[${(itemType || 'UNKNOWN').toUpperCase()}]`;
302
+ }
303
+ }
304
+
305
+ return content + mediaInfo;
306
+ }
307
+
308
+ formatMessageForConsole(msgData) {
309
+ const separator = '----------------------------------------';
310
+ // robust timestamp formatting into readable date+time in Europe/Bucharest
311
+ let ts = 'N/A';
312
+ try {
313
+ const parsed = this.parseTimestamp(msgData.timestamp);
314
+ if (parsed) {
315
+ const d = new Date(parsed);
316
+ ts = d.toLocaleString('ro-RO', {
317
+ year: 'numeric',
318
+ month: '2-digit',
319
+ day: '2-digit',
320
+ hour: '2-digit',
321
+ minute: '2-digit',
322
+ second: '2-digit',
323
+ hour12: false,
324
+ timeZone: 'Europe/Bucharest'
325
+ });
326
+ }
327
+ } catch (e) {
328
+ ts = 'N/A';
329
+ }
330
+ const lines = [
331
+ '',
332
+ separator,
333
+ '[NEW MESSAGE]',
334
+ separator,
335
+ `Username: ${msgData.username || 'unknown'}`,
336
+ `ID: ${msgData.userId || 'unknown'}`,
337
+ `Text: ${msgData.text || 'N/A'}`,
338
+ `Type: ${msgData.itemType || 'text'}`,
339
+ `Thread: ${msgData.threadId || 'unknown'}`,
340
+ `Message ID: ${msgData.messageId || 'unknown'}`,
341
+ `Timestamp: ${ts}`,
342
+ `Status: ${msgData.status || 'unknown'}`,
343
+ separator,
344
+ ''
345
+ ];
346
+ return lines.join('\n');
347
+ }
348
+
349
+ /**
350
+ * parseTimestamp
351
+ * - accepts numeric strings or numbers in seconds, milliseconds, microseconds, nanoseconds
352
+ * - normalizes to milliseconds
353
+ * - sanity-checks to avoid absurd future dates; returns Date.now() fallback if out of range
354
+ */
355
+ parseTimestamp(ts) {
356
+ try {
357
+ if (ts === undefined || ts === null) return null;
358
+ // if object with .ms or similar, try common fields
359
+ if (typeof ts === 'object') {
360
+ if (ts.ms) return Number(ts.ms);
361
+ if (ts.seconds) return Number(ts.seconds) * 1000;
362
+ if (ts.nano) return Math.floor(Number(ts.nano) / 1e6);
363
+ // fallback to toString
364
+ ts = String(ts);
365
+ }
366
+ let n = Number(ts);
367
+ if (!Number.isFinite(n)) return null;
368
+
369
+ // Heuristics:
370
+ // nanoseconds ~ 1e18+, microseconds ~ 1e15+, milliseconds ~ 1e12, seconds ~ 1e9
371
+ if (n > 1e17) {
372
+ // nanoseconds -> ms
373
+ n = Math.floor(n / 1e6);
374
+ } else if (n > 1e14) {
375
+ // microseconds -> ms
376
+ n = Math.floor(n / 1e3);
377
+ } else if (n > 1e12) {
378
+ // likely already ms (leave)
379
+ n = Math.floor(n);
380
+ } else if (n > 1e9) {
381
+ // seconds -> ms
382
+ n = Math.floor(n * 1000);
383
+ } else if (n > 1e6) {
384
+ // ambiguous (older formats) -> treat as seconds -> ms
385
+ n = Math.floor(n * 1000);
386
+ } else {
387
+ // too small -> invalid
388
+ return null;
389
+ }
390
+
391
+ // sanity range: allow roughly 2010-2036 (ms)
392
+ const min = 1262304000000; // 2010-01-01
393
+ const max = 2114380800000; // 2037-01-01 (safe future upper bound)
394
+ if (!Number.isFinite(n) || n < min || n > max) {
395
+ // fallback to now to avoid huge future years displayed
396
+ return Date.now();
397
+ }
398
+ return n;
399
+ } catch (e) {
400
+ return null;
401
+ }
402
+ }
403
+
404
+ async handleMessageSync(client, syncData) {
405
+ if (!syncData || !Array.isArray(syncData)) {
406
+ console.log(`[MESSAGE_SYNC] No sync data received`);
407
+ return;
408
+ }
409
+
410
+ for (const element of syncData) {
411
+ try {
412
+ const data = element.data;
413
+
414
+ if (!data) {
415
+ // fallback: emit iris with original element
416
+ client.emit('iris', element);
417
+ continue;
418
+ }
419
+
420
+ // ensure element.data removed in downstream parsed message (keeps original behavior)
421
+ delete element.data;
422
+
423
+ for (const e of data) {
424
+ try {
425
+ // tolerant handling: e.value may be string, object, null, or already parsed
426
+ let parsedValue = {};
427
+ if (e.value === undefined || e.value === null) {
428
+ parsedValue = {};
429
+ } else if (typeof e.value === 'string') {
430
+ const str = e.value.trim();
431
+ if (str.length === 0) {
432
+ parsedValue = {};
433
+ } else {
434
+ try {
435
+ parsedValue = JSON.parse(str);
436
+ } catch (errJson) {
437
+ // If not JSON, attempt basic fallback (sometimes server sends plain key=value or quoted)
438
+ try {
439
+ // try to safe-evaluate limited forms like a bare object without quotes (rare)
440
+ parsedValue = {};
441
+ } catch (err2) {
442
+ parsedValue = {};
443
+ }
444
+ }
445
+ }
446
+ } else if (typeof e.value === 'object') {
447
+ parsedValue = e.value;
448
+ } else {
449
+ parsedValue = {};
450
+ }
451
+
452
+ // Sometimes the message payload is nested under 'message' or similar
453
+ const msgValue = parsedValue.message || parsedValue.data || parsedValue || {};
454
+
455
+ if (!e.path) {
456
+ // no path means iris-like delta; merge element + e
457
+ client.emit('iris', { ...element, ...e, value: msgValue });
458
+ continue;
459
+ }
460
+
461
+ // normalize path check for thread messages
462
+ if ((e.path && e.path.startsWith('/direct_v2/threads')) ||
463
+ (e.path && e.path.startsWith('/direct_v2/inbox/threads')) ||
464
+ (e.path && e.path.indexOf('/direct_v2/threads/') !== -1) ) {
465
+
466
+ if (msgValue && (msgValue.item_type || msgValue.itemType || msgValue.type || msgValue.msg_type)) {
467
+ // determine item type as robustly as possible
468
+ const itemType = msgValue.item_type || msgValue.itemType || msgValue.type || msgValue.msg_type || 'text';
469
+
470
+ // thread id extraction
471
+ const threadId = MessageSyncMixin.getThreadIdFromPath(e.path);
472
+
473
+ // user id resolution: try many possible fields
474
+ const userId = msgValue.user_id || msgValue.from_user_id || msgValue.sender_id || msgValue.userId || msgValue.senderId || null;
475
+
476
+ // username resolution: prefer embedded username, otherwise fetch
477
+ let username = msgValue.username || msgValue.from_username || null;
478
+ if (!username && userId) {
479
+ try {
480
+ username = await this.getUsernameFromId(client, userId);
481
+ } catch (ux) {
482
+ username = null;
483
+ }
484
+ }
485
+ if (!username) {
486
+ username = `user_${userId || 'unknown'}`;
487
+ }
488
+
489
+ const textContent = this.extractMessageContent(msgValue, itemType);
490
+
491
+ const messageId = msgValue.item_id || msgValue.id || msgValue.client_context || msgValue.client_context_id || msgValue.message_id || msgValue.messageId || null;
492
+ const timestamp = msgValue.timestamp || msgValue.ts || msgValue.client_time || null;
493
+
494
+ // determine status based on whether message author is the logged-in account
495
+ let status = 'received';
496
+ try {
497
+ const ownId = client?.ig?.state?.cookieUserId || client?.ig?.state?.userId || null;
498
+ if (ownId && userId && String(userId) === String(ownId)) {
499
+ status = 'sent';
500
+ } else {
501
+ status = 'received';
502
+ }
503
+ } catch (stErr) {
504
+ status = 'received';
505
+ }
506
+
507
+ const msgData = {
508
+ username: username,
509
+ userId: userId,
510
+ text: textContent,
511
+ itemType: itemType,
512
+ threadId: threadId,
513
+ messageId: messageId,
514
+ timestamp: timestamp,
515
+ status: status,
516
+ rawData: msgValue
517
+ };
518
+
519
+ // console output (keeps original formatted block)
520
+ try {
521
+ console.log(this.formatMessageForConsole(msgData));
522
+ } catch (eLog) {
523
+ // don't let logging break processing
524
+ }
525
+
526
+ const parsedMessage = {
527
+ ...element,
528
+ message: {
529
+ path: e.path,
530
+ op: e.op,
531
+ thread_id: threadId,
532
+ ...msgValue,
533
+ },
534
+ parsed: msgData
535
+ };
536
+
537
+ client.emit('message', parsedMessage);
538
+ continue;
539
+ } // end if msgValue has item_type
540
+ } // end if path matches threads
541
+
542
+ // If not a thread message, emit as threadUpdate or iris depending on payload
543
+ try {
544
+ const updateValue = e.value ? (typeof e.value === 'string' ? (() => {
545
+ try { return JSON.parse(e.value); } catch { return e.value; }
546
+ })() : e.value) : {};
547
+ client.emit('threadUpdate', {
548
+ ...element,
549
+ meta: {
550
+ path: e.path,
551
+ op: e.op,
552
+ thread_id: MessageSyncMixin.getThreadIdFromPath(e.path),
553
+ },
554
+ update: updateValue,
555
+ });
556
+ } catch (errUpdate) {
557
+ client.emit('iris', { ...element, ...e, value: parsedValue });
558
+ }
559
+ } catch (inner) {
560
+ console.log(`[MESSAGE_SYNC] element handling error: ${inner?.message || inner}`);
561
+ }
562
+ }
563
+ } catch (outer) {
564
+ console.log(`[MESSAGE_SYNC] item error: ${outer?.message || outer}`);
565
+ }
566
+ }
567
+ }
568
+
569
+ static getThreadIdFromPath(path) {
570
+ if (!path) return undefined;
571
+ // Common patterns:
572
+ // /direct_v2/threads/<thread_id>/...
573
+ // /direct_v2/inbox/threads/<thread_id>/...
574
+ // /direct_v2/threads/<thread_id>
575
+ // possibly with trailing segments
576
+ try {
577
+ let m = path.match(/\/direct_v2\/threads\/(\d+)/);
578
+ if (m && m[1]) return m[1];
579
+ m = path.match(/\/direct_v2\/inbox\/threads\/(\d+)/);
580
+ if (m && m[1]) return m[1];
581
+ m = path.match(/\/direct_v2\/inbox\/(\d+)/);
582
+ if (m && m[1]) return m[1];
583
+ // last resort: look for any long numeric id in path
584
+ const anyId = path.match(/(\d{6,})/);
585
+ if (anyId && anyId[1]) return anyId[1];
586
+ } catch (e) {
587
+ // ignore
588
+ }
589
+ return undefined;
590
+ }
591
+
592
+ get name() {
593
+ return 'Message Sync';
594
+ }
595
+ }
596
+ exports.MessageSyncMixin = MessageSyncMixin;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-sync.mixin.js","sourceRoot":"","sources":["../../../src/realtime/mixins/message-sync.mixin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { RealtimeClient } from '../realtime.client';
2
+ import { IgApiClient } from 'instagram-private-api';
3
+ export declare abstract class Mixin {
4
+ abstract apply(client: RealtimeClient, ig: IgApiClient): void;
5
+ abstract get name(): string;
6
+ }
7
+ export declare function applyMixins(mixins: Mixin[], client: RealtimeClient, ig: IgApiClient): void;
8
+ export declare function hook<K extends string, Fn extends (...args: any[]) => any>(target: {
9
+ [x in K]: Fn;
10
+ }, key: K, hooks: {
11
+ pre?: (...args: Parameters<Fn>) => void | {
12
+ returnValue: ReturnType<Fn>;
13
+ overrideReturn: boolean;
14
+ };
15
+ post?: (returnValue: ReturnType<Fn>, ...args: Parameters<Fn>) => void | {
16
+ returnValue: ReturnType<Fn>;
17
+ overrideReturn: boolean;
18
+ };
19
+ }): void;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hook = exports.applyMixins = exports.Mixin = void 0;
4
+ class Mixin {
5
+ }
6
+ exports.Mixin = Mixin;
7
+ function applyMixins(mixins, client, ig) {
8
+ for (const mixin of mixins)
9
+ mixin.apply(client, ig);
10
+ }
11
+ exports.applyMixins = applyMixins;
12
+ function hook(target, key, hooks) {
13
+ const base = target[key];
14
+ const wrapper = (...args) => {
15
+ let returnValue;
16
+ let overrideReturn = false;
17
+ if (hooks.pre) {
18
+ const res = hooks.pre.apply(target, args);
19
+ if (typeof res === 'object' && res.overrideReturn) {
20
+ overrideReturn = true;
21
+ returnValue = res.returnValue;
22
+ }
23
+ }
24
+ const actualReturn = base.apply(target, args);
25
+ if (!overrideReturn)
26
+ returnValue = actualReturn;
27
+ if (hooks.post) {
28
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- it's always defined
29
+ const res = hooks.post.apply(target, [returnValue, ...args]);
30
+ if (typeof res === 'object' && res.overrideReturn) {
31
+ returnValue = res.returnValue;
32
+ }
33
+ }
34
+ // @ts-expect-error -- return value will be set [if pre sets it, else overrideReturn is false and it will be set by the actual function
35
+ return returnValue;
36
+ };
37
+ // @ts-expect-error -- any[] vs Parameters<Fn>
38
+ target[key] = wrapper.bind(target);
39
+ }
40
+ exports.hook = hook;
41
+ //# sourceMappingURL=mixin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mixin.js","sourceRoot":"","sources":["../../../src/realtime/mixins/mixin.ts"],"names":[],"mappings":";;;AAGA,MAAsB,KAAK;CAG1B;AAHD,sBAGC;AAED,SAAgB,WAAW,CAAC,MAAe,EAAE,MAAsB,EAAE,EAAe;IACjF,KAAK,MAAM,KAAK,IAAI,MAAM;QAAE,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACvD,CAAC;AAFD,kCAEC;AAED,SAAgB,IAAI,CACjB,MAAwB,EACxB,GAAM,EACN,KAMC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,MAAM,OAAO,GAAG,CAAC,GAAG,IAAoB,EAAkB,EAAE;QACzD,IAAI,WAA2B,CAAC;QAChC,IAAI,cAAc,GAAG,KAAK,CAAC;QAC3B,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC1C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,cAAc,EAAE,CAAC;gBACjD,cAAc,GAAG,IAAI,CAAC;gBACtB,WAAW,GAAG,GAAG,CAAC,WAAW,CAAC;YACjC,CAAC;QACJ,CAAC;QACD,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,cAAc;YAAE,WAAW,GAAG,YAAY,CAAC;QAEhD,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YACd,2FAA2F;YAC3F,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,WAAY,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;YAC9D,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,cAAc,EAAE,CAAC;gBACjD,WAAW,GAAG,GAAG,CAAC,WAAW,CAAC;YACjC,CAAC;QACJ,CAAC;QACD,uIAAuI;QACvI,OAAO,WAAW,CAAC;IACtB,CAAC,CAAC;IACF,8CAA8C;IAC9C,MAAM,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACtC,CAAC;AArCD,oBAqCC"}