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,186 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024;
7
+ const DEFAULT_MAX_FILES = 5;
8
+ const DEFAULT_FLUSH_INTERVAL = 30000;
9
+
10
+ class PersistentLogger {
11
+ constructor(options = {}) {
12
+ this.logDir = options.logDir || './logs';
13
+ this.prefix = options.prefix || 'instagram-mqtt';
14
+ this.maxFileSize = options.maxFileSize || DEFAULT_MAX_FILE_SIZE;
15
+ this.maxFiles = options.maxFiles || DEFAULT_MAX_FILES;
16
+ this.flushIntervalMs = options.flushIntervalMs || DEFAULT_FLUSH_INTERVAL;
17
+ this.logToConsole = options.logToConsole !== false;
18
+ this.logLevel = options.logLevel || 'info';
19
+
20
+ this._buffer = [];
21
+ this._currentFile = null;
22
+ this._currentFileSize = 0;
23
+ this._flushTimer = null;
24
+ this._started = false;
25
+ this._totalLines = 0;
26
+
27
+ this._levels = { debug: 0, info: 1, warn: 2, error: 3 };
28
+ }
29
+
30
+ start() {
31
+ if (this._started) return;
32
+ this._started = true;
33
+
34
+ try {
35
+ if (!fs.existsSync(this.logDir)) {
36
+ fs.mkdirSync(this.logDir, { recursive: true });
37
+ }
38
+ } catch (e) {
39
+ console.error('[LOGGER] Failed to create log directory:', e?.message || e);
40
+ }
41
+
42
+ this._rotateIfNeeded();
43
+
44
+ this._flushTimer = setInterval(() => {
45
+ this._flush();
46
+ }, this.flushIntervalMs);
47
+
48
+ this.info('PersistentLogger started', { logDir: this.logDir, maxFileSize: this.maxFileSize, maxFiles: this.maxFiles });
49
+ }
50
+
51
+ stop() {
52
+ this._started = false;
53
+ if (this._flushTimer) {
54
+ clearInterval(this._flushTimer);
55
+ this._flushTimer = null;
56
+ }
57
+ this._flush();
58
+ }
59
+
60
+ debug(...args) { this._write('debug', args); }
61
+ info(...args) { this._write('info', args); }
62
+ warn(...args) { this._write('warn', args); }
63
+ error(...args) { this._write('error', args); }
64
+
65
+ _write(level, args) {
66
+ if (this._levels[level] < this._levels[this.logLevel]) return;
67
+
68
+ const timestamp = new Date().toISOString();
69
+ const message = args.map(a => {
70
+ if (typeof a === 'object') {
71
+ try { return JSON.stringify(a); } catch (e) { return String(a); }
72
+ }
73
+ return String(a);
74
+ }).join(' ');
75
+
76
+ const line = `[${timestamp}] [${level.toUpperCase()}] ${message}`;
77
+
78
+ if (this.logToConsole) {
79
+ const consoleFn = level === 'error' ? console.error : (level === 'warn' ? console.warn : console.log);
80
+ consoleFn(line);
81
+ }
82
+
83
+ this._buffer.push(line);
84
+ this._totalLines++;
85
+
86
+ if (this._buffer.length >= 50) {
87
+ this._flush();
88
+ }
89
+ }
90
+
91
+ _flush() {
92
+ if (this._buffer.length === 0) return;
93
+ if (!this._currentFile) this._rotateIfNeeded();
94
+
95
+ try {
96
+ const content = this._buffer.join('\n') + '\n';
97
+ fs.appendFileSync(this._currentFile, content);
98
+ this._currentFileSize += Buffer.byteLength(content);
99
+ this._buffer = [];
100
+
101
+ if (this._currentFileSize >= this.maxFileSize) {
102
+ this._rotateIfNeeded();
103
+ }
104
+ } catch (e) {
105
+ if (this.logToConsole) {
106
+ console.error('[LOGGER] Failed to flush:', e?.message || e);
107
+ }
108
+ }
109
+ }
110
+
111
+ _rotateIfNeeded() {
112
+ try {
113
+ if (this._currentFile && fs.existsSync(this._currentFile)) {
114
+ try {
115
+ const stat = fs.statSync(this._currentFile);
116
+ this._currentFileSize = stat.size;
117
+ if (this._currentFileSize < this.maxFileSize) return;
118
+ } catch (e) {}
119
+ }
120
+
121
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').replace('T', '_').slice(0, 19);
122
+ this._currentFile = path.join(this.logDir, `${this.prefix}_${timestamp}.log`);
123
+ this._currentFileSize = 0;
124
+
125
+ this._cleanOldFiles();
126
+ } catch (e) {
127
+ if (this.logToConsole) {
128
+ console.error('[LOGGER] Rotation error:', e?.message || e);
129
+ }
130
+ }
131
+ }
132
+
133
+ _cleanOldFiles() {
134
+ try {
135
+ const files = fs.readdirSync(this.logDir)
136
+ .filter(f => f.startsWith(this.prefix) && f.endsWith('.log'))
137
+ .sort();
138
+
139
+ while (files.length > this.maxFiles) {
140
+ const oldest = files.shift();
141
+ try {
142
+ fs.unlinkSync(path.join(this.logDir, oldest));
143
+ } catch (e) {}
144
+ }
145
+ } catch (e) {}
146
+ }
147
+
148
+ getLogFiles() {
149
+ try {
150
+ return fs.readdirSync(this.logDir)
151
+ .filter(f => f.startsWith(this.prefix) && f.endsWith('.log'))
152
+ .sort()
153
+ .map(f => path.join(this.logDir, f));
154
+ } catch (e) {
155
+ return [];
156
+ }
157
+ }
158
+
159
+ getRecentLines(count = 100) {
160
+ this._flush();
161
+ try {
162
+ const files = this.getLogFiles();
163
+ if (files.length === 0) return [];
164
+
165
+ const lastFile = files[files.length - 1];
166
+ const content = fs.readFileSync(lastFile, 'utf8');
167
+ const lines = content.trim().split('\n');
168
+ return lines.slice(-count);
169
+ } catch (e) {
170
+ return [];
171
+ }
172
+ }
173
+
174
+ getStats() {
175
+ return {
176
+ started: this._started,
177
+ totalLines: this._totalLines,
178
+ bufferSize: this._buffer.length,
179
+ currentFile: this._currentFile,
180
+ currentFileSize: this._currentFileSize,
181
+ logFiles: this.getLogFiles(),
182
+ };
183
+ }
184
+ }
185
+
186
+ module.exports = { PersistentLogger };
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PresenceManager = void 0;
4
+ const shared_1 = require("../../shared");
5
+ const uuid_1 = require("uuid");
6
+ /**
7
+ * Presence Manager - Handle online/offline status
8
+ */
9
+ class PresenceManager {
10
+ constructor(client) {
11
+ this.presenceDebug = (0, shared_1.debugChannel)('realtime', 'presence');
12
+ this.userPresence = new Map();
13
+ this.client = client;
14
+ }
15
+ /**
16
+ * Update user presence
17
+ */
18
+ updatePresence(userId, status, lastActivity = Date.now()) {
19
+ this.presenceDebug(`User ${userId} is ${status}`);
20
+ this.userPresence.set(userId, { status, lastActivity });
21
+ this.client.emit('presence', {
22
+ user_id: userId,
23
+ status,
24
+ last_activity: lastActivity,
25
+ });
26
+ }
27
+ /**
28
+ * Get user presence
29
+ */
30
+ getPresence(userId) {
31
+ return this.userPresence.get(userId) || { status: 'offline', lastActivity: null };
32
+ }
33
+ /**
34
+ * Broadcast user's own presence
35
+ */
36
+ async broadcastPresence(status = 'online') {
37
+ this.presenceDebug(`Broadcasting presence: ${status}`);
38
+ const payload = {
39
+ action: 'presence_status',
40
+ status,
41
+ timestamp: Date.now(),
42
+ client_context: (0, uuid_1.v4)(),
43
+ };
44
+ return this.client.directCommands?.sendCommand({
45
+ action: 'send_presence',
46
+ data: payload,
47
+ threadId: '',
48
+ });
49
+ }
50
+ /**
51
+ * Handle presence update
52
+ */
53
+ handlePresenceUpdate(data) {
54
+ try {
55
+ const update = typeof data === 'string' ? JSON.parse(data) : data;
56
+ if (update.user_id && update.status) {
57
+ this.updatePresence(update.user_id, update.status, update.last_activity);
58
+ }
59
+ return update;
60
+ } catch (err) {
61
+ this.presenceDebug(`Failed to parse presence update: ${err.message}`);
62
+ return null;
63
+ }
64
+ }
65
+ }
66
+ exports.PresenceManager = PresenceManager;
@@ -0,0 +1,345 @@
1
+ 'use strict';
2
+
3
+ const EventEmitter = require('eventemitter3');
4
+
5
+ const SESSION_CHECK_INTERVAL = 30 * 60 * 1000;
6
+ const SESSION_CHECK_JITTER = 5 * 60 * 1000;
7
+ const MIN_CHECK_INTERVAL = 5 * 60 * 1000;
8
+
9
+ class SessionHealthMonitor extends EventEmitter {
10
+ constructor(realtimeClient, options = {}) {
11
+ super();
12
+ this.rt = realtimeClient;
13
+ this.ig = realtimeClient.ig;
14
+ this.options = {
15
+ checkIntervalMs: options.checkIntervalMs || SESSION_CHECK_INTERVAL,
16
+ jitterMs: options.jitterMs || SESSION_CHECK_JITTER,
17
+ autoRelogin: options.autoRelogin !== false,
18
+ credentials: options.credentials || null,
19
+ onSessionExpired: options.onSessionExpired || null,
20
+ maxConsecutiveFailures: options.maxConsecutiveFailures || 5,
21
+ ...options,
22
+ };
23
+
24
+ this._checkTimer = null;
25
+ this._running = false;
26
+ this._consecutiveFailures = 0;
27
+ this._lastCheckAt = null;
28
+ this._lastCheckResult = null;
29
+ this._sessionValid = true;
30
+ this._reloginInProgress = false;
31
+ this._reloginCount = 0;
32
+
33
+ this._stats = {
34
+ startedAt: null,
35
+ totalChecks: 0,
36
+ successfulChecks: 0,
37
+ failedChecks: 0,
38
+ sessionExpiries: 0,
39
+ relogins: 0,
40
+ successfulRelogins: 0,
41
+ failedRelogins: 0,
42
+ totalUptimeMs: 0,
43
+ longestUptimeMs: 0,
44
+ reconnects: 0,
45
+ lastUptimeStart: null,
46
+ uptimeSegments: [],
47
+ };
48
+ }
49
+
50
+ start() {
51
+ if (this._running) return;
52
+ this._running = true;
53
+ this._stats.startedAt = Date.now();
54
+ this._stats.lastUptimeStart = Date.now();
55
+ this._log('[HEALTH] Session health monitor started');
56
+ this._log(`[HEALTH] Check interval: ${Math.round(this.options.checkIntervalMs / 60000)}min + up to ${Math.round(this.options.jitterMs / 60000)}min jitter`);
57
+ this._log(`[HEALTH] Auto-relogin: ${this.options.autoRelogin ? 'enabled' : 'disabled'}`);
58
+
59
+ this._scheduleNextCheck();
60
+
61
+ if (this.rt) {
62
+ this.rt.on('reconnected', () => {
63
+ this._stats.reconnects++;
64
+ this._recordUptimeSegment();
65
+ this._stats.lastUptimeStart = Date.now();
66
+ this._log('[HEALTH] Reconnected - uptime segment recorded');
67
+ });
68
+
69
+ this.rt.on('disconnect', () => {
70
+ this._recordUptimeSegment();
71
+ });
72
+
73
+ this.rt.on('reconnect_failed', () => {
74
+ this._log('[HEALTH] All reconnect attempts exhausted - checking session validity');
75
+ this._performCheck().catch(() => {});
76
+ });
77
+ }
78
+ }
79
+
80
+ stop() {
81
+ this._running = false;
82
+ if (this._checkTimer) {
83
+ clearTimeout(this._checkTimer);
84
+ this._checkTimer = null;
85
+ }
86
+ this._recordUptimeSegment();
87
+ this._log('[HEALTH] Session health monitor stopped');
88
+ }
89
+
90
+ _scheduleNextCheck() {
91
+ if (!this._running) return;
92
+ if (this._checkTimer) clearTimeout(this._checkTimer);
93
+
94
+ const jitter = Math.floor(Math.random() * this.options.jitterMs);
95
+ const delay = Math.max(MIN_CHECK_INTERVAL, this.options.checkIntervalMs + jitter);
96
+
97
+ this._checkTimer = setTimeout(async () => {
98
+ try {
99
+ await this._performCheck();
100
+ } catch (e) {
101
+ this._log('[HEALTH] Check error:', e?.message || e);
102
+ }
103
+ this._scheduleNextCheck();
104
+ }, delay);
105
+ }
106
+
107
+ async _performCheck() {
108
+ this._stats.totalChecks++;
109
+ this._lastCheckAt = Date.now();
110
+
111
+ try {
112
+ const result = await this._checkSessionValidity();
113
+ this._lastCheckResult = result;
114
+
115
+ if (result.valid) {
116
+ this._consecutiveFailures = 0;
117
+ this._sessionValid = true;
118
+ this._stats.successfulChecks++;
119
+ this._log(`[HEALTH] Session valid (userId: ${result.userId || 'unknown'}, check #${this._stats.totalChecks})`);
120
+ this.emit('health_check', { status: 'ok', result, stats: this.getStats() });
121
+ return true;
122
+ } else {
123
+ this._consecutiveFailures++;
124
+ this._stats.failedChecks++;
125
+ this._log(`[HEALTH] Session check failed (${this._consecutiveFailures}/${this.options.maxConsecutiveFailures}): ${result.reason}`);
126
+ this.emit('health_check', { status: 'failed', result, consecutiveFailures: this._consecutiveFailures });
127
+
128
+ if (this._consecutiveFailures >= 2) {
129
+ this._sessionValid = false;
130
+ this._stats.sessionExpiries++;
131
+ this._log('[HEALTH] Session appears expired');
132
+ this.emit('session_expired', { result, consecutiveFailures: this._consecutiveFailures });
133
+
134
+ if (this.options.autoRelogin) {
135
+ return await this._attemptRelogin();
136
+ } else if (typeof this.options.onSessionExpired === 'function') {
137
+ try { await this.options.onSessionExpired(result); } catch (e) {}
138
+ }
139
+ }
140
+ return false;
141
+ }
142
+ } catch (e) {
143
+ this._consecutiveFailures++;
144
+ this._stats.failedChecks++;
145
+ this._log('[HEALTH] Session check threw:', e?.message || e);
146
+ this.emit('health_check', { status: 'error', error: e?.message, consecutiveFailures: this._consecutiveFailures });
147
+
148
+ if (this._consecutiveFailures >= this.options.maxConsecutiveFailures) {
149
+ this._log(`[HEALTH] Max consecutive failures (${this.options.maxConsecutiveFailures}) reached`);
150
+ if (this.options.autoRelogin) {
151
+ return await this._attemptRelogin();
152
+ }
153
+ }
154
+ return false;
155
+ }
156
+ }
157
+
158
+ async _checkSessionValidity() {
159
+ try {
160
+ const response = await this.ig.request.send({
161
+ url: '/api/v1/accounts/current_user/',
162
+ method: 'GET',
163
+ qs: { edit: true },
164
+ });
165
+
166
+ if (response?.body?.user) {
167
+ return {
168
+ valid: true,
169
+ userId: response.body.user.pk || response.body.user.pk_id,
170
+ username: response.body.user.username,
171
+ fullName: response.body.user.full_name,
172
+ };
173
+ }
174
+
175
+ return { valid: false, reason: 'No user data in response', statusCode: response?.statusCode };
176
+ } catch (e) {
177
+ const status = e?.response?.statusCode || e?.statusCode;
178
+ const body = e?.response?.body;
179
+
180
+ if (status === 401 || status === 403) {
181
+ return { valid: false, reason: `Auth error (${status})`, statusCode: status, requiresRelogin: true };
182
+ }
183
+ if (status === 429) {
184
+ return { valid: false, reason: 'Rate limited (429) - session might still be valid', statusCode: status, rateLimited: true };
185
+ }
186
+ if (body?.message === 'login_required' || body?.error_type === 'inactive user') {
187
+ return { valid: false, reason: body.message || body.error_type, statusCode: status, requiresRelogin: true };
188
+ }
189
+ if (e.code === 'ENOTFOUND' || e.code === 'ECONNREFUSED' || e.code === 'ETIMEDOUT') {
190
+ return { valid: false, reason: `Network error: ${e.code}`, networkError: true };
191
+ }
192
+
193
+ return { valid: false, reason: e?.message || 'Unknown error', statusCode: status };
194
+ }
195
+ }
196
+
197
+ async _attemptRelogin() {
198
+ if (this._reloginInProgress) {
199
+ this._log('[HEALTH] Relogin already in progress, skipping');
200
+ return false;
201
+ }
202
+ this._reloginInProgress = true;
203
+ this._stats.relogins++;
204
+
205
+ try {
206
+ const creds = this.options.credentials;
207
+ if (!creds || !creds.username || !creds.password) {
208
+ this._log('[HEALTH] No credentials available for auto-relogin');
209
+ this.emit('relogin_needed', { reason: 'No credentials configured' });
210
+ return false;
211
+ }
212
+
213
+ this._log(`[HEALTH] Attempting auto-relogin as ${creds.username}...`);
214
+ this.emit('relogin_start', { username: creds.username });
215
+
216
+ try {
217
+ await this.ig.login({ username: creds.username, password: creds.password });
218
+ this._log('[HEALTH] Relogin successful!');
219
+ this._stats.successfulRelogins++;
220
+ this._reloginCount++;
221
+ this._consecutiveFailures = 0;
222
+ this._sessionValid = true;
223
+
224
+ if (this.rt._attachedAuthState && typeof this.rt._attachedAuthState.saveCreds === 'function') {
225
+ try {
226
+ await this.rt._attachedAuthState.saveCreds(this.ig);
227
+ this._log('[HEALTH] Credentials saved after relogin');
228
+ } catch (e) {
229
+ this._log('[HEALTH] Failed to save credentials:', e?.message || e);
230
+ }
231
+ }
232
+
233
+ this.emit('relogin_success', { username: creds.username, reloginCount: this._reloginCount });
234
+
235
+ try {
236
+ this._log('[HEALTH] Triggering MQTT reconnect with fresh session...');
237
+ await this.rt._attemptReconnectSafely();
238
+ } catch (e) {
239
+ this._log('[HEALTH] MQTT reconnect after relogin failed:', e?.message || e);
240
+ }
241
+
242
+ return true;
243
+ } catch (e) {
244
+ this._stats.failedRelogins++;
245
+ const isChallenge = e?.message?.includes('challenge') || e?.message?.includes('checkpoint');
246
+ this._log(`[HEALTH] Relogin failed: ${e?.message || e}`);
247
+
248
+ if (isChallenge) {
249
+ this._log('[HEALTH] Account requires verification - cannot auto-relogin');
250
+ this.emit('relogin_challenge', { error: e?.message });
251
+ }
252
+
253
+ this.emit('relogin_failed', { error: e?.message, isChallenge });
254
+ return false;
255
+ }
256
+ } finally {
257
+ this._reloginInProgress = false;
258
+ }
259
+ }
260
+
261
+ async forceCheck() {
262
+ return this._performCheck();
263
+ }
264
+
265
+ isSessionValid() {
266
+ return this._sessionValid;
267
+ }
268
+
269
+ getStats() {
270
+ const now = Date.now();
271
+ const currentSegmentMs = this._stats.lastUptimeStart ? (now - this._stats.lastUptimeStart) : 0;
272
+ const totalUptime = this._stats.totalUptimeMs + currentSegmentMs;
273
+ const totalRuntime = this._stats.startedAt ? (now - this._stats.startedAt) : 0;
274
+
275
+ return {
276
+ running: this._running,
277
+ sessionValid: this._sessionValid,
278
+ startedAt: this._stats.startedAt ? new Date(this._stats.startedAt).toISOString() : null,
279
+ totalRuntimeMs: totalRuntime,
280
+ totalRuntimeHuman: this._humanDuration(totalRuntime),
281
+ totalUptimeMs: totalUptime,
282
+ totalUptimeHuman: this._humanDuration(totalUptime),
283
+ uptimePercent: totalRuntime > 0 ? Math.round((totalUptime / totalRuntime) * 10000) / 100 : 100,
284
+ currentSessionMs: currentSegmentMs,
285
+ currentSessionHuman: this._humanDuration(currentSegmentMs),
286
+ longestSessionMs: Math.max(this._stats.longestUptimeMs, currentSegmentMs),
287
+ longestSessionHuman: this._humanDuration(Math.max(this._stats.longestUptimeMs, currentSegmentMs)),
288
+ totalChecks: this._stats.totalChecks,
289
+ successfulChecks: this._stats.successfulChecks,
290
+ failedChecks: this._stats.failedChecks,
291
+ sessionExpiries: this._stats.sessionExpiries,
292
+ reconnects: this._stats.reconnects,
293
+ relogins: this._stats.relogins,
294
+ successfulRelogins: this._stats.successfulRelogins,
295
+ failedRelogins: this._stats.failedRelogins,
296
+ consecutiveFailures: this._consecutiveFailures,
297
+ lastCheckAt: this._lastCheckAt ? new Date(this._lastCheckAt).toISOString() : null,
298
+ lastCheckResult: this._lastCheckResult,
299
+ };
300
+ }
301
+
302
+ _recordUptimeSegment() {
303
+ if (this._stats.lastUptimeStart) {
304
+ const segmentMs = Date.now() - this._stats.lastUptimeStart;
305
+ this._stats.totalUptimeMs += segmentMs;
306
+ if (segmentMs > this._stats.longestUptimeMs) this._stats.longestUptimeMs = segmentMs;
307
+ this._stats.uptimeSegments.push({
308
+ start: new Date(this._stats.lastUptimeStart).toISOString(),
309
+ end: new Date().toISOString(),
310
+ durationMs: segmentMs,
311
+ });
312
+ if (this._stats.uptimeSegments.length > 100) {
313
+ this._stats.uptimeSegments = this._stats.uptimeSegments.slice(-50);
314
+ }
315
+ this._stats.lastUptimeStart = null;
316
+ }
317
+ }
318
+
319
+ _humanDuration(ms) {
320
+ if (!ms || ms <= 0) return '0s';
321
+ const d = Math.floor(ms / 86400000);
322
+ const h = Math.floor((ms % 86400000) / 3600000);
323
+ const m = Math.floor((ms % 3600000) / 60000);
324
+ const s = Math.floor((ms % 60000) / 1000);
325
+ const parts = [];
326
+ if (d > 0) parts.push(`${d}d`);
327
+ if (h > 0) parts.push(`${h}h`);
328
+ if (m > 0) parts.push(`${m}m`);
329
+ if (s > 0 || parts.length === 0) parts.push(`${s}s`);
330
+ return parts.join(' ');
331
+ }
332
+
333
+ _log(...args) {
334
+ if (this.rt && typeof this.rt.realtimeDebug === 'function') {
335
+ this.rt.realtimeDebug(...args);
336
+ } else {
337
+ console.log(...args);
338
+ }
339
+ try {
340
+ this.emit('log', args.join(' '));
341
+ } catch (e) {}
342
+ }
343
+ }
344
+
345
+ module.exports = { SessionHealthMonitor };
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PresenceTypingMixin = exports.EnhancedDirectCommands = exports.GapHandler = exports.ErrorHandler = exports.DMSender = exports.PresenceManager = exports.SkywalkerProtocol = exports.IrisHandshake = exports.RealtimeClient = void 0;
4
+
5
+ const realtime_client_1 = require("./realtime.client");
6
+ Object.defineProperty(exports, "RealtimeClient", { enumerable: true, get: function () { return realtime_client_1.RealtimeClient; } });
7
+
8
+ const iris_handshake_1 = require("./protocols/iris.handshake");
9
+ Object.defineProperty(exports, "IrisHandshake", { enumerable: true, get: function () { return iris_handshake_1.IrisHandshake; } });
10
+
11
+ const skywalker_protocol_1 = require("./protocols/skywalker.protocol");
12
+ Object.defineProperty(exports, "SkywalkerProtocol", { enumerable: true, get: function () { return skywalker_protocol_1.SkywalkerProtocol; } });
13
+
14
+ const presence_manager_1 = require("./features/presence.manager");
15
+ Object.defineProperty(exports, "PresenceManager", { enumerable: true, get: function () { return presence_manager_1.PresenceManager; } });
16
+
17
+ const dm_sender_1 = require("./features/dm-sender");
18
+ Object.defineProperty(exports, "DMSender", { enumerable: true, get: function () { return dm_sender_1.DMSender; } });
19
+
20
+ const error_handler_1 = require("./features/error-handler");
21
+ Object.defineProperty(exports, "ErrorHandler", { enumerable: true, get: function () { return error_handler_1.ErrorHandler; } });
22
+
23
+ const gap_handler_1 = require("./features/gap-handler");
24
+ Object.defineProperty(exports, "GapHandler", { enumerable: true, get: function () { return gap_handler_1.GapHandler; } });
25
+
26
+ const presence_typing_mixin_1 = require("./mixins/presence-typing.mixin");
27
+ Object.defineProperty(exports, "PresenceTypingMixin", { enumerable: true, get: function () { return presence_typing_mixin_1.PresenceTypingMixin; } });
28
+
29
+ const enhanced_direct_commands_1 = require("./commands/enhanced.direct.commands");
30
+ Object.defineProperty(exports, "EnhancedDirectCommands", { enumerable: true, get: function () { return enhanced_direct_commands_1.EnhancedDirectCommands; } });
@@ -0,0 +1,9 @@
1
+ export interface AppPresenceEvent {
2
+ user_id: string;
3
+ is_active: boolean;
4
+ last_activity_at_ms: string;
5
+ in_threads: any[];
6
+ }
7
+ export interface AppPresenceEventWrapper {
8
+ presence_event: AppPresenceEvent;
9
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=app-presence.event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-presence.event.js","sourceRoot":"","sources":["../../../src/realtime/messages/app-presence.event.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ export * from './message-sync.message';
2
+ export * from './realtime-sub.direct.data';
3
+ export * from './app-presence.event';
@@ -0,0 +1,20 @@
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./message-sync.message"), exports);
18
+ __exportStar(require("./realtime-sub.direct.data"), exports);
19
+ __exportStar(require("./app-presence.event"), exports);
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/realtime/messages/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAuC;AACvC,6DAA2C;AAC3C,uDAAqC"}