nodejs-insta-private-api-mqt 1.3.83 → 1.3.84

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 (392) hide show
  1. package/dist-ts/dist/constants/constants.js +341 -0
  2. package/dist-ts/dist/constants/index.js +53 -0
  3. package/dist-ts/dist/core/client.js +437 -0
  4. package/dist-ts/dist/core/nav-chain.js +252 -0
  5. package/dist-ts/dist/core/repository.js +6 -0
  6. package/dist-ts/dist/core/request.js +358 -0
  7. package/dist-ts/dist/core/state.js +1428 -0
  8. package/dist-ts/dist/core/utils.js +723 -0
  9. package/dist-ts/dist/downloadMedia.js +336 -0
  10. package/dist-ts/dist/errors/index.js +37 -0
  11. package/dist-ts/dist/extend.js +157 -0
  12. package/dist-ts/dist/fbns/fbns.client.events.js +2 -0
  13. package/dist-ts/dist/fbns/fbns.client.js +237 -0
  14. package/dist-ts/dist/fbns/fbns.device-auth.js +59 -0
  15. package/dist-ts/dist/fbns/fbns.types.js +2 -0
  16. package/dist-ts/dist/fbns/fbns.utilities.js +78 -0
  17. package/dist-ts/dist/fbns/index.js +24 -0
  18. package/dist-ts/dist/index.js +137 -0
  19. package/dist-ts/dist/mqtt-shim.js +14 -0
  20. package/dist-ts/dist/mqttot/index.js +24 -0
  21. package/dist-ts/dist/mqttot/mqttot.client.js +322 -0
  22. package/dist-ts/dist/mqttot/mqttot.connect.request.packet.js +8 -0
  23. package/dist-ts/dist/mqttot/mqttot.connect.response.packet.js +23 -0
  24. package/dist-ts/dist/mqttot/mqttot.connection.js +68 -0
  25. package/dist-ts/dist/realtime/commands/commands.js +67 -0
  26. package/dist-ts/dist/realtime/commands/direct.commands.js +415 -0
  27. package/dist-ts/dist/realtime/commands/enhanced.direct.commands.js +1529 -0
  28. package/dist-ts/dist/realtime/commands/index.js +23 -0
  29. package/dist-ts/dist/realtime/delta-sync.manager.js +260 -0
  30. package/dist-ts/dist/realtime/features/dm-sender.js +94 -0
  31. package/dist-ts/dist/realtime/features/error-handler.js +167 -0
  32. package/dist-ts/dist/realtime/features/gap-handler.js +60 -0
  33. package/dist-ts/dist/realtime/features/persistent-logger.js +174 -0
  34. package/dist-ts/dist/realtime/features/presence.manager.js +68 -0
  35. package/dist-ts/dist/realtime/features/session-health-monitor.js +327 -0
  36. package/dist-ts/dist/realtime/index.js +21 -0
  37. package/dist-ts/dist/realtime/messages/app-presence.event.js +2 -0
  38. package/dist-ts/dist/realtime/messages/index.js +23 -0
  39. package/dist-ts/dist/realtime/messages/message-sync.message.js +42 -0
  40. package/dist-ts/dist/realtime/messages/realtime-sub.direct.data.js +2 -0
  41. package/dist-ts/dist/realtime/messages/thread-update.message.js +2 -0
  42. package/dist-ts/dist/realtime/mixins/index.js +23 -0
  43. package/dist-ts/dist/realtime/mixins/message-sync.mixin.js +585 -0
  44. package/dist-ts/dist/realtime/mixins/mixin.js +40 -0
  45. package/dist-ts/dist/realtime/mixins/presence-typing.mixin.js +29 -0
  46. package/dist-ts/dist/realtime/mixins/realtime-sub.mixin.js +171 -0
  47. package/dist-ts/dist/realtime/parsers/graphql-parser.js +43 -0
  48. package/dist-ts/dist/realtime/parsers/graphql.parser.js +22 -0
  49. package/dist-ts/dist/realtime/parsers/index.js +26 -0
  50. package/dist-ts/dist/realtime/parsers/iris-parser.js +43 -0
  51. package/dist-ts/dist/realtime/parsers/iris.parser.js +9 -0
  52. package/dist-ts/dist/realtime/parsers/json-parser.js +43 -0
  53. package/dist-ts/dist/realtime/parsers/json.parser.js +9 -0
  54. package/dist-ts/dist/realtime/parsers/parser.js +2 -0
  55. package/dist-ts/dist/realtime/parsers/region-hint-parser.js +43 -0
  56. package/dist-ts/dist/realtime/parsers/region-hint.parser.js +14 -0
  57. package/dist-ts/dist/realtime/parsers/skywalker-parser.js +43 -0
  58. package/dist-ts/dist/realtime/parsers/skywalker.parser.js +14 -0
  59. package/dist-ts/dist/realtime/parsers-advanced.js +138 -0
  60. package/dist-ts/dist/realtime/proto-parser.js +186 -0
  61. package/dist-ts/dist/realtime/protocols/iris.handshake.js +76 -0
  62. package/dist-ts/dist/realtime/protocols/skywalker.protocol.js +96 -0
  63. package/dist-ts/dist/realtime/realtime.client.events.js +2 -0
  64. package/dist-ts/dist/realtime/realtime.client.js +2117 -0
  65. package/dist-ts/dist/realtime/realtime.service.js +408 -0
  66. package/dist-ts/dist/realtime/reconnect.manager.js +72 -0
  67. package/dist-ts/dist/realtime/session.manager.js +106 -0
  68. package/dist-ts/dist/realtime/subscriptions/graphql.subscription.js +98 -0
  69. package/dist-ts/dist/realtime/subscriptions/index.js +22 -0
  70. package/dist-ts/dist/realtime/subscriptions/skywalker.subscription.js +12 -0
  71. package/dist-ts/dist/realtime/topic-map.js +57 -0
  72. package/dist-ts/dist/realtime/topic.js +76 -0
  73. package/dist-ts/dist/repositories/account.repository.js +1267 -0
  74. package/dist-ts/dist/repositories/bloks.repository.js +66 -0
  75. package/dist-ts/dist/repositories/captcha.repository.js +40 -0
  76. package/dist-ts/dist/repositories/challenge.repository.js +108 -0
  77. package/dist-ts/dist/repositories/clip.repository.js +134 -0
  78. package/dist-ts/dist/repositories/close-friends.repository.js +41 -0
  79. package/dist-ts/dist/repositories/collection.repository.js +64 -0
  80. package/dist-ts/dist/repositories/direct-thread.repository.js +423 -0
  81. package/dist-ts/dist/repositories/direct.repository.js +246 -0
  82. package/dist-ts/dist/repositories/explore.repository.js +60 -0
  83. package/dist-ts/dist/repositories/fbsearch.repository.js +124 -0
  84. package/dist-ts/dist/repositories/feed.repository.js +237 -0
  85. package/dist-ts/dist/repositories/friendship.repository.js +277 -0
  86. package/dist-ts/dist/repositories/fundraiser.repository.js +38 -0
  87. package/dist-ts/dist/repositories/hashtag.repository.js +80 -0
  88. package/dist-ts/dist/repositories/highlights.repository.js +100 -0
  89. package/dist-ts/dist/repositories/insights.repository.js +66 -0
  90. package/dist-ts/dist/repositories/location.repository.js +67 -0
  91. package/dist-ts/dist/repositories/media.repository.js +370 -0
  92. package/dist-ts/dist/repositories/multiple-accounts.repository.js +36 -0
  93. package/dist-ts/dist/repositories/news.repository.js +32 -0
  94. package/dist-ts/dist/repositories/note.repository.js +51 -0
  95. package/dist-ts/dist/repositories/notification.repository.js +77 -0
  96. package/dist-ts/dist/repositories/share.repository.js +34 -0
  97. package/dist-ts/dist/repositories/signup.repository.js +178 -0
  98. package/dist-ts/dist/repositories/story.repository.js +268 -0
  99. package/dist-ts/dist/repositories/timeline.repository.js +57 -0
  100. package/dist-ts/dist/repositories/totp.repository.js +124 -0
  101. package/dist-ts/dist/repositories/track.repository.js +50 -0
  102. package/dist-ts/dist/repositories/upload.repository.js +191 -0
  103. package/dist-ts/dist/repositories/user.repository.js +332 -0
  104. package/dist-ts/dist/sendmedia/index.js +24 -0
  105. package/dist-ts/dist/sendmedia/sendFile.js +56 -0
  106. package/dist-ts/dist/sendmedia/sendPhoto.js +132 -0
  107. package/dist-ts/dist/sendmedia/sendRavenPhoto.js +133 -0
  108. package/dist-ts/dist/sendmedia/sendRavenVideo.js +136 -0
  109. package/dist-ts/dist/sendmedia/uploadPhoto.js +89 -0
  110. package/dist-ts/dist/sendmedia/uploadfFile.js +108 -0
  111. package/dist-ts/dist/services/live.service.js +113 -0
  112. package/dist-ts/dist/services/search.service.js +91 -0
  113. package/dist-ts/dist/shared/index.js +98 -0
  114. package/dist-ts/dist/shared/shared.js +85 -0
  115. package/dist-ts/dist/thrift/index.js +23 -0
  116. package/dist-ts/dist/thrift/thrift.js +105 -0
  117. package/dist-ts/dist/thrift/thrift.reading.js +339 -0
  118. package/dist-ts/dist/thrift/thrift.writing.js +393 -0
  119. package/dist-ts/dist/types/index.js +276 -0
  120. package/dist-ts/dist/useMultiFileAuthState.js +1878 -0
  121. package/dist-ts/dist/utils/index.js +244 -0
  122. package/dist-ts/examples/listen-to-messages.js +73 -0
  123. package/package.json +1 -1
  124. package/src-ts/dist/realtime/protocols/proto-definitions.ts +80 -0
  125. package/src-ts/dist/utils/helper-1.ts +1 -0
  126. package/src-ts/dist/utils/helper-10.ts +1 -0
  127. package/src-ts/dist/utils/helper-11.ts +1 -0
  128. package/src-ts/dist/utils/helper-12.ts +1 -0
  129. package/src-ts/dist/utils/helper-13.ts +1 -0
  130. package/src-ts/dist/utils/helper-14.ts +1 -0
  131. package/src-ts/dist/utils/helper-15.ts +1 -0
  132. package/src-ts/dist/utils/helper-16.ts +1 -0
  133. package/src-ts/dist/utils/helper-17.ts +1 -0
  134. package/src-ts/dist/utils/helper-18.ts +1 -0
  135. package/src-ts/dist/utils/helper-19.ts +1 -0
  136. package/src-ts/dist/utils/helper-2.ts +1 -0
  137. package/src-ts/dist/utils/helper-20.ts +1 -0
  138. package/src-ts/dist/utils/helper-21.ts +1 -0
  139. package/src-ts/dist/utils/helper-22.ts +1 -0
  140. package/src-ts/dist/utils/helper-23.ts +1 -0
  141. package/src-ts/dist/utils/helper-24.ts +1 -0
  142. package/src-ts/dist/utils/helper-25.ts +1 -0
  143. package/src-ts/dist/utils/helper-26.ts +1 -0
  144. package/src-ts/dist/utils/helper-27.ts +1 -0
  145. package/src-ts/dist/utils/helper-28.ts +1 -0
  146. package/src-ts/dist/utils/helper-29.ts +1 -0
  147. package/src-ts/dist/utils/helper-3.ts +1 -0
  148. package/src-ts/dist/utils/helper-30.ts +1 -0
  149. package/src-ts/dist/utils/helper-4.ts +1 -0
  150. package/src-ts/dist/utils/helper-5.ts +1 -0
  151. package/src-ts/dist/utils/helper-6.ts +1 -0
  152. package/src-ts/dist/utils/helper-7.ts +1 -0
  153. package/src-ts/dist/utils/helper-8.ts +1 -0
  154. package/src-ts/dist/utils/helper-9.ts +1 -0
  155. package/src-ts/dist/utils/insta-mqtt-helper.ts +128 -0
  156. package/src-ts/examples/listen-to-messages.ts +86 -0
  157. package/dist/errors/index.d.ts +0 -16
  158. package/dist/errors/index.js.map +0 -1
  159. package/dist/fbns/fbns.client.d.ts +0 -32
  160. package/dist/fbns/fbns.client.events.d.ts +0 -41
  161. package/dist/fbns/fbns.client.events.js.map +0 -1
  162. package/dist/fbns/fbns.client.js.map +0 -1
  163. package/dist/fbns/fbns.device-auth.d.ts +0 -17
  164. package/dist/fbns/fbns.device-auth.js.map +0 -1
  165. package/dist/fbns/fbns.types.d.ts +0 -83
  166. package/dist/fbns/fbns.types.js.map +0 -1
  167. package/dist/fbns/fbns.utilities.d.ts +0 -2
  168. package/dist/fbns/fbns.utilities.js.map +0 -1
  169. package/dist/fbns/index.d.ts +0 -4
  170. package/dist/fbns/index.js.map +0 -1
  171. package/dist/mqtt-shim.d.ts +0 -96
  172. package/dist/mqttot/index.d.ts +0 -4
  173. package/dist/mqttot/index.js.map +0 -1
  174. package/dist/mqttot/mqttot.client.d.ts +0 -39
  175. package/dist/mqttot/mqttot.client.js.map +0 -1
  176. package/dist/mqttot/mqttot.connect.request.packet.d.ts +0 -7
  177. package/dist/mqttot/mqttot.connect.request.packet.js.map +0 -1
  178. package/dist/mqttot/mqttot.connect.response.packet.d.ts +0 -7
  179. package/dist/mqttot/mqttot.connect.response.packet.js.map +0 -1
  180. package/dist/mqttot/mqttot.connection.d.ts +0 -57
  181. package/dist/mqttot/mqttot.connection.js.map +0 -1
  182. package/dist/package.json +0 -59
  183. package/dist/realtime/commands/commands.d.ts +0 -15
  184. package/dist/realtime/commands/commands.js.map +0 -1
  185. package/dist/realtime/commands/direct.commands.d.ts +0 -75
  186. package/dist/realtime/commands/direct.commands.js.map +0 -1
  187. package/dist/realtime/commands/enhanced.direct.commands.js.bak +0 -967
  188. package/dist/realtime/commands/index.d.ts +0 -2
  189. package/dist/realtime/commands/index.js.map +0 -1
  190. package/dist/realtime/messages/app-presence.event.d.ts +0 -9
  191. package/dist/realtime/messages/app-presence.event.js.map +0 -1
  192. package/dist/realtime/messages/index.d.ts +0 -3
  193. package/dist/realtime/messages/index.js.map +0 -1
  194. package/dist/realtime/messages/message-sync.message.d.ts +0 -222
  195. package/dist/realtime/messages/message-sync.message.js.map +0 -1
  196. package/dist/realtime/messages/realtime-sub.direct.data.d.ts +0 -11
  197. package/dist/realtime/messages/realtime-sub.direct.data.js.map +0 -1
  198. package/dist/realtime/messages/thread-update.message.d.ts +0 -68
  199. package/dist/realtime/messages/thread-update.message.js.map +0 -1
  200. package/dist/realtime/mixins/index.d.ts +0 -3
  201. package/dist/realtime/mixins/index.js.map +0 -1
  202. package/dist/realtime/mixins/message-sync.mixin.d.ts +0 -8
  203. package/dist/realtime/mixins/message-sync.mixin.js.map +0 -1
  204. package/dist/realtime/mixins/mixin.d.ts +0 -19
  205. package/dist/realtime/mixins/mixin.js.map +0 -1
  206. package/dist/realtime/mixins/realtime-sub.mixin.d.ts +0 -8
  207. package/dist/realtime/mixins/realtime-sub.mixin.js.map +0 -1
  208. package/dist/realtime/parsers/graphql.parser.d.ts +0 -15
  209. package/dist/realtime/parsers/graphql.parser.js.map +0 -1
  210. package/dist/realtime/parsers/index.d.ts +0 -6
  211. package/dist/realtime/parsers/index.js.map +0 -1
  212. package/dist/realtime/parsers/iris.parser.d.ts +0 -17
  213. package/dist/realtime/parsers/iris.parser.js.map +0 -1
  214. package/dist/realtime/parsers/json.parser.d.ts +0 -6
  215. package/dist/realtime/parsers/json.parser.js.map +0 -1
  216. package/dist/realtime/parsers/parser.d.ts +0 -9
  217. package/dist/realtime/parsers/parser.js.map +0 -1
  218. package/dist/realtime/parsers/region-hint.parser.d.ts +0 -12
  219. package/dist/realtime/parsers/region-hint.parser.js.map +0 -1
  220. package/dist/realtime/parsers/skywalker.parser.d.ts +0 -12
  221. package/dist/realtime/parsers/skywalker.parser.js.map +0 -1
  222. package/dist/realtime/proto/common.proto +0 -38
  223. package/dist/realtime/proto/direct.proto +0 -65
  224. package/dist/realtime/proto/ig-messages.proto +0 -83
  225. package/dist/realtime/proto/iris.proto +0 -188
  226. package/dist/realtime/subscriptions/graphql.subscription.d.ts +0 -47
  227. package/dist/realtime/subscriptions/graphql.subscription.js.map +0 -1
  228. package/dist/realtime/subscriptions/index.d.ts +0 -2
  229. package/dist/realtime/subscriptions/index.js.map +0 -1
  230. package/dist/realtime/subscriptions/skywalker.subscription.d.ts +0 -4
  231. package/dist/realtime/subscriptions/skywalker.subscription.js.map +0 -1
  232. package/dist/thrift/index.d.ts +0 -3
  233. package/dist/thrift/index.js.map +0 -1
  234. package/dist/thrift/thrift.d.ts +0 -59
  235. package/dist/thrift/thrift.js.map +0 -1
  236. package/dist/thrift/thrift.reading.d.ts +0 -41
  237. package/dist/thrift/thrift.reading.js.map +0 -1
  238. package/dist/thrift/thrift.writing.d.ts +0 -44
  239. package/dist/thrift/thrift.writing.js.map +0 -1
  240. /package/{dist → dist-ts/dist}/realtime/protocols/proto-definitions.js +0 -0
  241. /package/{dist → dist-ts/dist}/utils/helper-1.js +0 -0
  242. /package/{dist → dist-ts/dist}/utils/helper-10.js +0 -0
  243. /package/{dist → dist-ts/dist}/utils/helper-11.js +0 -0
  244. /package/{dist → dist-ts/dist}/utils/helper-12.js +0 -0
  245. /package/{dist → dist-ts/dist}/utils/helper-13.js +0 -0
  246. /package/{dist → dist-ts/dist}/utils/helper-14.js +0 -0
  247. /package/{dist → dist-ts/dist}/utils/helper-15.js +0 -0
  248. /package/{dist → dist-ts/dist}/utils/helper-16.js +0 -0
  249. /package/{dist → dist-ts/dist}/utils/helper-17.js +0 -0
  250. /package/{dist → dist-ts/dist}/utils/helper-18.js +0 -0
  251. /package/{dist → dist-ts/dist}/utils/helper-19.js +0 -0
  252. /package/{dist → dist-ts/dist}/utils/helper-2.js +0 -0
  253. /package/{dist → dist-ts/dist}/utils/helper-20.js +0 -0
  254. /package/{dist → dist-ts/dist}/utils/helper-21.js +0 -0
  255. /package/{dist → dist-ts/dist}/utils/helper-22.js +0 -0
  256. /package/{dist → dist-ts/dist}/utils/helper-23.js +0 -0
  257. /package/{dist → dist-ts/dist}/utils/helper-24.js +0 -0
  258. /package/{dist → dist-ts/dist}/utils/helper-25.js +0 -0
  259. /package/{dist → dist-ts/dist}/utils/helper-26.js +0 -0
  260. /package/{dist → dist-ts/dist}/utils/helper-27.js +0 -0
  261. /package/{dist → dist-ts/dist}/utils/helper-28.js +0 -0
  262. /package/{dist → dist-ts/dist}/utils/helper-29.js +0 -0
  263. /package/{dist → dist-ts/dist}/utils/helper-3.js +0 -0
  264. /package/{dist → dist-ts/dist}/utils/helper-30.js +0 -0
  265. /package/{dist → dist-ts/dist}/utils/helper-4.js +0 -0
  266. /package/{dist → dist-ts/dist}/utils/helper-5.js +0 -0
  267. /package/{dist → dist-ts/dist}/utils/helper-6.js +0 -0
  268. /package/{dist → dist-ts/dist}/utils/helper-7.js +0 -0
  269. /package/{dist → dist-ts/dist}/utils/helper-8.js +0 -0
  270. /package/{dist → dist-ts/dist}/utils/helper-9.js +0 -0
  271. /package/{dist → dist-ts/dist}/utils/insta-mqtt-helper.js +0 -0
  272. /package/{dist/constants/constants.js → src-ts/dist/constants/constants.ts} +0 -0
  273. /package/{dist/constants/index.js → src-ts/dist/constants/index.ts} +0 -0
  274. /package/{dist/core/client.js → src-ts/dist/core/client.ts} +0 -0
  275. /package/{dist/core/nav-chain.js → src-ts/dist/core/nav-chain.ts} +0 -0
  276. /package/{dist/core/repository.js → src-ts/dist/core/repository.ts} +0 -0
  277. /package/{dist/core/request.js → src-ts/dist/core/request.ts} +0 -0
  278. /package/{dist/core/state.js → src-ts/dist/core/state.ts} +0 -0
  279. /package/{dist/core/utils.js → src-ts/dist/core/utils.ts} +0 -0
  280. /package/{dist/downloadMedia.js → src-ts/dist/downloadMedia.ts} +0 -0
  281. /package/{dist/errors/index.js → src-ts/dist/errors/index.ts} +0 -0
  282. /package/{dist/extend.js → src-ts/dist/extend.ts} +0 -0
  283. /package/{dist/fbns/fbns.client.events.js → src-ts/dist/fbns/fbns.client.events.ts} +0 -0
  284. /package/{dist/fbns/fbns.client.js → src-ts/dist/fbns/fbns.client.ts} +0 -0
  285. /package/{dist/fbns/fbns.device-auth.js → src-ts/dist/fbns/fbns.device-auth.ts} +0 -0
  286. /package/{dist/fbns/fbns.types.js → src-ts/dist/fbns/fbns.types.ts} +0 -0
  287. /package/{dist/fbns/fbns.utilities.js → src-ts/dist/fbns/fbns.utilities.ts} +0 -0
  288. /package/{dist/fbns/index.js → src-ts/dist/fbns/index.ts} +0 -0
  289. /package/{dist/index.js → src-ts/dist/index.ts} +0 -0
  290. /package/{dist/mqtt-shim.js → src-ts/dist/mqtt-shim.ts} +0 -0
  291. /package/{dist/mqttot/index.js → src-ts/dist/mqttot/index.ts} +0 -0
  292. /package/{dist/mqttot/mqttot.client.js → src-ts/dist/mqttot/mqttot.client.ts} +0 -0
  293. /package/{dist/mqttot/mqttot.connect.request.packet.js → src-ts/dist/mqttot/mqttot.connect.request.packet.ts} +0 -0
  294. /package/{dist/mqttot/mqttot.connect.response.packet.js → src-ts/dist/mqttot/mqttot.connect.response.packet.ts} +0 -0
  295. /package/{dist/mqttot/mqttot.connection.js → src-ts/dist/mqttot/mqttot.connection.ts} +0 -0
  296. /package/{dist/realtime/commands/commands.js → src-ts/dist/realtime/commands/commands.ts} +0 -0
  297. /package/{dist/realtime/commands/direct.commands.js → src-ts/dist/realtime/commands/direct.commands.ts} +0 -0
  298. /package/{dist/realtime/commands/enhanced.direct.commands.js → src-ts/dist/realtime/commands/enhanced.direct.commands.ts} +0 -0
  299. /package/{dist/realtime/commands/index.js → src-ts/dist/realtime/commands/index.ts} +0 -0
  300. /package/{dist/realtime/delta-sync.manager.js → src-ts/dist/realtime/delta-sync.manager.ts} +0 -0
  301. /package/{dist/realtime/features/dm-sender.js → src-ts/dist/realtime/features/dm-sender.ts} +0 -0
  302. /package/{dist/realtime/features/error-handler.js → src-ts/dist/realtime/features/error-handler.ts} +0 -0
  303. /package/{dist/realtime/features/gap-handler.js → src-ts/dist/realtime/features/gap-handler.ts} +0 -0
  304. /package/{dist/realtime/features/persistent-logger.js → src-ts/dist/realtime/features/persistent-logger.ts} +0 -0
  305. /package/{dist/realtime/features/presence.manager.js → src-ts/dist/realtime/features/presence.manager.ts} +0 -0
  306. /package/{dist/realtime/features/session-health-monitor.js → src-ts/dist/realtime/features/session-health-monitor.ts} +0 -0
  307. /package/{dist/realtime/index.js → src-ts/dist/realtime/index.ts} +0 -0
  308. /package/{dist/realtime/messages/app-presence.event.js → src-ts/dist/realtime/messages/app-presence.event.ts} +0 -0
  309. /package/{dist/realtime/messages/index.js → src-ts/dist/realtime/messages/index.ts} +0 -0
  310. /package/{dist/realtime/messages/message-sync.message.js → src-ts/dist/realtime/messages/message-sync.message.ts} +0 -0
  311. /package/{dist/realtime/messages/realtime-sub.direct.data.js → src-ts/dist/realtime/messages/realtime-sub.direct.data.ts} +0 -0
  312. /package/{dist/realtime/messages/thread-update.message.js → src-ts/dist/realtime/messages/thread-update.message.ts} +0 -0
  313. /package/{dist/realtime/mixins/index.js → src-ts/dist/realtime/mixins/index.ts} +0 -0
  314. /package/{dist/realtime/mixins/message-sync.mixin.js → src-ts/dist/realtime/mixins/message-sync.mixin.ts} +0 -0
  315. /package/{dist/realtime/mixins/mixin.js → src-ts/dist/realtime/mixins/mixin.ts} +0 -0
  316. /package/{dist/realtime/mixins/presence-typing.mixin.js → src-ts/dist/realtime/mixins/presence-typing.mixin.ts} +0 -0
  317. /package/{dist/realtime/mixins/realtime-sub.mixin.js → src-ts/dist/realtime/mixins/realtime-sub.mixin.ts} +0 -0
  318. /package/{dist/realtime/parsers/graphql-parser.js → src-ts/dist/realtime/parsers/graphql-parser.ts} +0 -0
  319. /package/{dist/realtime/parsers/graphql.parser.js → src-ts/dist/realtime/parsers/graphql.parser.ts} +0 -0
  320. /package/{dist/realtime/parsers/index.js → src-ts/dist/realtime/parsers/index.ts} +0 -0
  321. /package/{dist/realtime/parsers/iris-parser.js → src-ts/dist/realtime/parsers/iris-parser.ts} +0 -0
  322. /package/{dist/realtime/parsers/iris.parser.js → src-ts/dist/realtime/parsers/iris.parser.ts} +0 -0
  323. /package/{dist/realtime/parsers/json-parser.js → src-ts/dist/realtime/parsers/json-parser.ts} +0 -0
  324. /package/{dist/realtime/parsers/json.parser.js → src-ts/dist/realtime/parsers/json.parser.ts} +0 -0
  325. /package/{dist/realtime/parsers/parser.js → src-ts/dist/realtime/parsers/parser.ts} +0 -0
  326. /package/{dist/realtime/parsers/region-hint-parser.js → src-ts/dist/realtime/parsers/region-hint-parser.ts} +0 -0
  327. /package/{dist/realtime/parsers/region-hint.parser.js → src-ts/dist/realtime/parsers/region-hint.parser.ts} +0 -0
  328. /package/{dist/realtime/parsers/skywalker-parser.js → src-ts/dist/realtime/parsers/skywalker-parser.ts} +0 -0
  329. /package/{dist/realtime/parsers/skywalker.parser.js → src-ts/dist/realtime/parsers/skywalker.parser.ts} +0 -0
  330. /package/{dist/realtime/parsers-advanced.js → src-ts/dist/realtime/parsers-advanced.ts} +0 -0
  331. /package/{dist/realtime/proto-parser.js → src-ts/dist/realtime/proto-parser.ts} +0 -0
  332. /package/{dist/realtime/protocols/iris.handshake.js → src-ts/dist/realtime/protocols/iris.handshake.ts} +0 -0
  333. /package/{dist/realtime/protocols/skywalker.protocol.js → src-ts/dist/realtime/protocols/skywalker.protocol.ts} +0 -0
  334. /package/{dist/realtime/realtime.client.events.js → src-ts/dist/realtime/realtime.client.events.ts} +0 -0
  335. /package/{dist/realtime/realtime.client.js → src-ts/dist/realtime/realtime.client.ts} +0 -0
  336. /package/{dist/realtime/realtime.service.js → src-ts/dist/realtime/realtime.service.ts} +0 -0
  337. /package/{dist/realtime/reconnect.manager.js → src-ts/dist/realtime/reconnect.manager.ts} +0 -0
  338. /package/{dist/realtime/session.manager.js → src-ts/dist/realtime/session.manager.ts} +0 -0
  339. /package/{dist/realtime/subscriptions/graphql.subscription.js → src-ts/dist/realtime/subscriptions/graphql.subscription.ts} +0 -0
  340. /package/{dist/realtime/subscriptions/index.js → src-ts/dist/realtime/subscriptions/index.ts} +0 -0
  341. /package/{dist/realtime/subscriptions/skywalker.subscription.js → src-ts/dist/realtime/subscriptions/skywalker.subscription.ts} +0 -0
  342. /package/{dist/realtime/topic-map.js → src-ts/dist/realtime/topic-map.ts} +0 -0
  343. /package/{dist/realtime/topic.js → src-ts/dist/realtime/topic.ts} +0 -0
  344. /package/{dist/repositories/account.repository.js → src-ts/dist/repositories/account.repository.ts} +0 -0
  345. /package/{dist/repositories/bloks.repository.js → src-ts/dist/repositories/bloks.repository.ts} +0 -0
  346. /package/{dist/repositories/captcha.repository.js → src-ts/dist/repositories/captcha.repository.ts} +0 -0
  347. /package/{dist/repositories/challenge.repository.js → src-ts/dist/repositories/challenge.repository.ts} +0 -0
  348. /package/{dist/repositories/clip.repository.js → src-ts/dist/repositories/clip.repository.ts} +0 -0
  349. /package/{dist/repositories/close-friends.repository.js → src-ts/dist/repositories/close-friends.repository.ts} +0 -0
  350. /package/{dist/repositories/collection.repository.js → src-ts/dist/repositories/collection.repository.ts} +0 -0
  351. /package/{dist/repositories/direct-thread.repository.js → src-ts/dist/repositories/direct-thread.repository.ts} +0 -0
  352. /package/{dist/repositories/direct.repository.js → src-ts/dist/repositories/direct.repository.ts} +0 -0
  353. /package/{dist/repositories/explore.repository.js → src-ts/dist/repositories/explore.repository.ts} +0 -0
  354. /package/{dist/repositories/fbsearch.repository.js → src-ts/dist/repositories/fbsearch.repository.ts} +0 -0
  355. /package/{dist/repositories/feed.repository.js → src-ts/dist/repositories/feed.repository.ts} +0 -0
  356. /package/{dist/repositories/friendship.repository.js → src-ts/dist/repositories/friendship.repository.ts} +0 -0
  357. /package/{dist/repositories/fundraiser.repository.js → src-ts/dist/repositories/fundraiser.repository.ts} +0 -0
  358. /package/{dist/repositories/hashtag.repository.js → src-ts/dist/repositories/hashtag.repository.ts} +0 -0
  359. /package/{dist/repositories/highlights.repository.js → src-ts/dist/repositories/highlights.repository.ts} +0 -0
  360. /package/{dist/repositories/insights.repository.js → src-ts/dist/repositories/insights.repository.ts} +0 -0
  361. /package/{dist/repositories/location.repository.js → src-ts/dist/repositories/location.repository.ts} +0 -0
  362. /package/{dist/repositories/media.repository.js → src-ts/dist/repositories/media.repository.ts} +0 -0
  363. /package/{dist/repositories/multiple-accounts.repository.js → src-ts/dist/repositories/multiple-accounts.repository.ts} +0 -0
  364. /package/{dist/repositories/news.repository.js → src-ts/dist/repositories/news.repository.ts} +0 -0
  365. /package/{dist/repositories/note.repository.js → src-ts/dist/repositories/note.repository.ts} +0 -0
  366. /package/{dist/repositories/notification.repository.js → src-ts/dist/repositories/notification.repository.ts} +0 -0
  367. /package/{dist/repositories/share.repository.js → src-ts/dist/repositories/share.repository.ts} +0 -0
  368. /package/{dist/repositories/signup.repository.js → src-ts/dist/repositories/signup.repository.ts} +0 -0
  369. /package/{dist/repositories/story.repository.js → src-ts/dist/repositories/story.repository.ts} +0 -0
  370. /package/{dist/repositories/timeline.repository.js → src-ts/dist/repositories/timeline.repository.ts} +0 -0
  371. /package/{dist/repositories/totp.repository.js → src-ts/dist/repositories/totp.repository.ts} +0 -0
  372. /package/{dist/repositories/track.repository.js → src-ts/dist/repositories/track.repository.ts} +0 -0
  373. /package/{dist/repositories/upload.repository.js → src-ts/dist/repositories/upload.repository.ts} +0 -0
  374. /package/{dist/repositories/user.repository.js → src-ts/dist/repositories/user.repository.ts} +0 -0
  375. /package/{dist/sendmedia/index.js → src-ts/dist/sendmedia/index.ts} +0 -0
  376. /package/{dist/sendmedia/sendFile.js → src-ts/dist/sendmedia/sendFile.ts} +0 -0
  377. /package/{dist/sendmedia/sendPhoto.js → src-ts/dist/sendmedia/sendPhoto.ts} +0 -0
  378. /package/{dist/sendmedia/sendRavenPhoto.js → src-ts/dist/sendmedia/sendRavenPhoto.ts} +0 -0
  379. /package/{dist/sendmedia/sendRavenVideo.js → src-ts/dist/sendmedia/sendRavenVideo.ts} +0 -0
  380. /package/{dist/sendmedia/uploadPhoto.js → src-ts/dist/sendmedia/uploadPhoto.ts} +0 -0
  381. /package/{dist/sendmedia/uploadfFile.js → src-ts/dist/sendmedia/uploadfFile.ts} +0 -0
  382. /package/{dist/services/live.service.js → src-ts/dist/services/live.service.ts} +0 -0
  383. /package/{dist/services/search.service.js → src-ts/dist/services/search.service.ts} +0 -0
  384. /package/{dist/shared/index.js → src-ts/dist/shared/index.ts} +0 -0
  385. /package/{dist/shared/shared.js → src-ts/dist/shared/shared.ts} +0 -0
  386. /package/{dist/thrift/index.js → src-ts/dist/thrift/index.ts} +0 -0
  387. /package/{dist/thrift/thrift.reading.js → src-ts/dist/thrift/thrift.reading.ts} +0 -0
  388. /package/{dist/thrift/thrift.js → src-ts/dist/thrift/thrift.ts} +0 -0
  389. /package/{dist/thrift/thrift.writing.js → src-ts/dist/thrift/thrift.writing.ts} +0 -0
  390. /package/{dist/types/index.js → src-ts/dist/types/index.ts} +0 -0
  391. /package/{dist/useMultiFileAuthState.js → src-ts/dist/useMultiFileAuthState.ts} +0 -0
  392. /package/{dist/utils/index.js → src-ts/dist/utils/index.ts} +0 -0
@@ -0,0 +1,1878 @@
1
+ 'use strict';
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const { CookieJar } = require('tough-cookie');
5
+ const util = require('util');
6
+ const EventEmitter = require('events');
7
+ const crypto = require('crypto');
8
+ const FILE_NAMES = {
9
+ creds: 'creds.json',
10
+ device: 'device.json',
11
+ cookies: 'cookies.json',
12
+ mqttSession: 'mqtt-session.json',
13
+ subscriptions: 'subscriptions.json',
14
+ seqIds: 'seq-ids.json',
15
+ appState: 'app-state.json',
16
+ // Newly added MQTT / realtime persistence files
17
+ irisState: 'iris-state.json', // subscription / iris specific state
18
+ mqttTopics: 'mqtt-topics.json', // observed topics
19
+ mqttCapabilities: 'mqtt-capabilities.json', // realtime capabilities per device/version
20
+ mqttAuth: 'mqtt-auth.json', // mqtt auth token / jwt (if available)
21
+ lastPublishIds: 'last-publish-ids.json', // last published message ids / ack info
22
+ // Added utility files
23
+ loginHistory: 'login-history.json',
24
+ usageStats: 'usage-stats.json',
25
+ accountsIndex: 'accounts.json',
26
+ // MQTT helpers files
27
+ mqttHealth: 'mqtt-health.json',
28
+ mqttReconnect: 'mqtt-reconnect.json',
29
+ mqttMessageCache: 'mqtt-message-cache.json',
30
+ mqttOutbox: 'mqtt-outbox.json',
31
+ mqttSubscriptionHealth: 'mqtt-subscription-health.json',
32
+ mqttTraffic: 'mqtt-traffic.json',
33
+ mqttRisk: 'mqtt-risk.json'
34
+ };
35
+ class MultiFileAuthState extends EventEmitter {
36
+ constructor(folder) {
37
+ super();
38
+ this.folder = folder;
39
+ this._saveDebounceTimer = null;
40
+ this._saveDebounceMs = 500;
41
+ this._dirty = new Set();
42
+ // Auto-refresh fields
43
+ this._autoRefreshTimer = null;
44
+ this._autoRefreshIntervalMs = 5 * 60 * 1000; // default 5 minutes
45
+ this._autoRefreshClient = null;
46
+ // Reconnect/backoff runtime
47
+ this._reconnectBackoff = [2000, 5000, 15000, 60000];
48
+ this._reconnectAttempts = 0;
49
+ this._reconnectTimer = null;
50
+ this.data = {
51
+ creds: null,
52
+ device: null,
53
+ cookies: null,
54
+ mqttSession: null,
55
+ subscriptions: null,
56
+ seqIds: null,
57
+ appState: null,
58
+ // new
59
+ irisState: null,
60
+ mqttTopics: null,
61
+ mqttCapabilities: null,
62
+ mqttAuth: null,
63
+ lastPublishIds: null,
64
+ // utility
65
+ loginHistory: null,
66
+ usageStats: null,
67
+ accountsIndex: null,
68
+ // mqtt helpers
69
+ mqttHealth: null,
70
+ mqttReconnect: null,
71
+ mqttMessageCache: null,
72
+ mqttOutbox: null,
73
+ mqttSubscriptionHealth: null,
74
+ mqttTraffic: null,
75
+ mqttRisk: null
76
+ };
77
+ // ensure folder structure
78
+ this._ensureFolder();
79
+ this._ensureBackupFolder();
80
+ }
81
+ _getFilePath(key) {
82
+ return path.join(this.folder, FILE_NAMES[key]);
83
+ }
84
+ _getBackupFolder() {
85
+ return path.join(this.folder, 'backup');
86
+ }
87
+ _ensureFolder() {
88
+ if (!fs.existsSync(this.folder)) {
89
+ fs.mkdirSync(this.folder, { recursive: true, mode: 0o700 });
90
+ }
91
+ }
92
+ _ensureBackupFolder() {
93
+ // backups disabled — no-op
94
+ return;
95
+ }
96
+ // sanitize state to avoid nulls for key fields (useful to ensure instant non-null)
97
+ _sanitizeForSave(key, data) {
98
+ var _a, _b, _c, _d;
99
+ try {
100
+ if (!data)
101
+ return data;
102
+ if (key === 'creds') {
103
+ if (typeof data.userId === 'undefined' || data.userId === null)
104
+ data.userId = data.userId || 'pending';
105
+ if (typeof data.username === 'undefined' || data.username === null)
106
+ data.username = data.username || 'pending';
107
+ if (typeof data.sessionId === 'undefined' || data.sessionId === null)
108
+ data.sessionId = data.sessionId || `pending-${Date.now()}`;
109
+ if (typeof data.csrfToken === 'undefined' || data.csrfToken === null)
110
+ data.csrfToken = data.csrfToken || 'pending';
111
+ if (typeof data.isLoggedIn === 'undefined')
112
+ data.isLoggedIn = !!data.sessionId || !!data.authorization;
113
+ if (!data.loginAt)
114
+ data.loginAt = data.loginAt || new Date().toISOString();
115
+ }
116
+ if (key === 'mqttSession') {
117
+ if (!data.sessionId)
118
+ data.sessionId = data.sessionId || `local-mqtt-${Date.now()}`;
119
+ if (!data.mqttSessionId)
120
+ data.mqttSessionId = data.mqttSessionId || 'boot';
121
+ if (!data.lastConnected)
122
+ data.lastConnected = new Date().toISOString();
123
+ }
124
+ if (key === 'seqIds') {
125
+ if (typeof data.seq_id === 'undefined' || data.seq_id === null)
126
+ data.seq_id = data.seq_id || 0;
127
+ if (typeof data.snapshot_at_ms === 'undefined' || data.snapshot_at_ms === null)
128
+ data.snapshot_at_ms = data.snapshot_at_ms || Date.now();
129
+ }
130
+ if (key === 'mqttTopics') {
131
+ if (!data.topics)
132
+ data.topics = data.topics || ['ig_sub_direct', 'ig_sub_direct_v2_message_sync', 'presence_subscribe'];
133
+ if (!data.updatedAt)
134
+ data.updatedAt = new Date().toISOString();
135
+ }
136
+ if (key === 'mqttCapabilities') {
137
+ data.supportsTyping = Boolean((_a = data.supportsTyping) !== null && _a !== void 0 ? _a : true);
138
+ data.supportsReactions = Boolean((_b = data.supportsReactions) !== null && _b !== void 0 ? _b : true);
139
+ data.supportsVoice = Boolean((_c = data.supportsVoice) !== null && _c !== void 0 ? _c : false);
140
+ data.protocolVersion = data.protocolVersion || 3;
141
+ data.collectedAt = data.collectedAt || new Date().toISOString();
142
+ }
143
+ if (key === 'mqttHealth') {
144
+ data.lastPingAt = data.lastPingAt || null;
145
+ data.lastPongAt = data.lastPongAt || null;
146
+ data.latencyMs = data.latencyMs || 0;
147
+ data.missedPings = data.missedPings || 0;
148
+ data.status = data.status || 'unknown';
149
+ }
150
+ if (key === 'mqttMessageCache') {
151
+ if (!Array.isArray(data.lastIds))
152
+ data.lastIds = [];
153
+ if (!data.max)
154
+ data.max = data.max || 500;
155
+ }
156
+ if (key === 'mqttOutbox') {
157
+ if (!Array.isArray(data))
158
+ return [];
159
+ }
160
+ if (key === 'mqttSubscriptionHealth') {
161
+ data.expected = data.expected || (((_d = this.getMqttTopics()) === null || _d === void 0 ? void 0 : _d.topics) || ['ig_sub_direct']);
162
+ data.active = data.active || data.expected.slice();
163
+ data.lastCheck = data.lastCheck || new Date().toISOString();
164
+ data.needsResubscribe = data.needsResubscribe || false;
165
+ }
166
+ if (key === 'mqttTraffic') {
167
+ data.messagesInPerMin = data.messagesInPerMin || 0;
168
+ data.messagesOutPerMin = data.messagesOutPerMin || 0;
169
+ data.lastReset = data.lastReset || new Date().toISOString();
170
+ }
171
+ if (key === 'mqttReconnect') {
172
+ data.attempts = data.attempts || 0;
173
+ data.lastReason = data.lastReason || null;
174
+ data.lastAttemptAt = data.lastAttemptAt || null;
175
+ data.nextRetryInMs = data.nextRetryInMs || 0;
176
+ }
177
+ if (key === 'mqttRisk') {
178
+ data.riskScore = typeof data.riskScore === 'number' ? data.riskScore : 0;
179
+ data.level = data.level || 'low';
180
+ data.updatedAt = data.updatedAt || new Date().toISOString();
181
+ }
182
+ }
183
+ catch (e) {
184
+ // ignore sanitize errors
185
+ }
186
+ return data;
187
+ }
188
+ // create a timestamped backup of existing file (if present)
189
+ async _createBackup(key) {
190
+ // backups disabled — do nothing
191
+ return null;
192
+ }
193
+ async _writeFileAtomic(filePath, data) {
194
+ const tempPath = filePath + '.tmp';
195
+ const jsonData = JSON.stringify(data, null, 2);
196
+ await fs.promises.writeFile(tempPath, jsonData, { mode: 0o600 });
197
+ await fs.promises.rename(tempPath, filePath);
198
+ }
199
+ async _readFile(key) {
200
+ const filePath = this._getFilePath(key);
201
+ try {
202
+ if (fs.existsSync(filePath)) {
203
+ const raw = await fs.promises.readFile(filePath, 'utf8');
204
+ return JSON.parse(raw);
205
+ }
206
+ }
207
+ catch (e) {
208
+ console.warn(`[MultiFileAuthState] Error reading ${key}:`, e.message);
209
+ }
210
+ return null;
211
+ }
212
+ async _writeFile(key, data) {
213
+ this._ensureFolder();
214
+ const filePath = this._getFilePath(key);
215
+ try {
216
+ // sanitize to avoid nulls for key fields
217
+ const sanitized = this._sanitizeForSave(key, JSON.parse(JSON.stringify(data)));
218
+ // create backup before overwriting existing file
219
+ await this._createBackup(key);
220
+ await this._writeFileAtomic(filePath, sanitized);
221
+ return true;
222
+ }
223
+ catch (e) {
224
+ console.error(`[MultiFileAuthState] Error writing ${key}:`, e.message);
225
+ return false;
226
+ }
227
+ }
228
+ // restore the latest backup for a key (returns path of restored file or null)
229
+ async restoreLatestBackup(key) {
230
+ try {
231
+ const base = FILE_NAMES[key];
232
+ const bfolder = this._getBackupFolder();
233
+ if (!fs.existsSync(bfolder))
234
+ return null;
235
+ const files = await fs.promises.readdir(bfolder);
236
+ const matches = files.filter(f => f.startsWith(base + '.'));
237
+ if (!matches.length)
238
+ return null;
239
+ // sort descending by timestamp embedded in filename
240
+ matches.sort().reverse();
241
+ const latest = matches[0];
242
+ const src = path.join(bfolder, latest);
243
+ const dest = this._getFilePath(key);
244
+ await fs.promises.copyFile(src, dest);
245
+ this.emit('backup-restored', { key, file: src });
246
+ // reload into memory
247
+ this.data[key] = await this._readFile(key);
248
+ return src;
249
+ }
250
+ catch (e) {
251
+ console.warn('[MultiFileAuthState] restoreLatestBackup error:', e.message);
252
+ return null;
253
+ }
254
+ }
255
+ async loadAll() {
256
+ var _a, _b;
257
+ this._ensureFolder();
258
+ this._ensureBackupFolder();
259
+ const loadPromises = Object.keys(FILE_NAMES).map(async (key) => {
260
+ this.data[key] = await this._readFile(key);
261
+ });
262
+ await Promise.all(loadPromises);
263
+ // ensure usageStats and loginHistory objects exist
264
+ if (!this.data.loginHistory)
265
+ this.data.loginHistory = [];
266
+ if (!this.data.usageStats)
267
+ this.data.usageStats = {
268
+ apiRequests: 0,
269
+ mqttMessages: 0,
270
+ errors: 0,
271
+ reconnects: 0,
272
+ lastReset: new Date().toISOString()
273
+ };
274
+ if (!this.data.accountsIndex)
275
+ this.data.accountsIndex = {};
276
+ // ensure mqtt helper objects exist
277
+ if (!this.data.mqttHealth)
278
+ this.data.mqttHealth = { lastPingAt: null, lastPongAt: null, latencyMs: 0, missedPings: 0, status: 'unknown' };
279
+ if (!this.data.mqttReconnect)
280
+ this.data.mqttReconnect = { attempts: 0, lastReason: null, lastAttemptAt: null, nextRetryInMs: 0 };
281
+ if (!this.data.mqttMessageCache)
282
+ this.data.mqttMessageCache = { lastIds: [], max: 500 };
283
+ if (!this.data.mqttOutbox)
284
+ this.data.mqttOutbox = [];
285
+ if (!this.data.mqttSubscriptionHealth)
286
+ this.data.mqttSubscriptionHealth = { expected: (((_a = this.data.mqttTopics) === null || _a === void 0 ? void 0 : _a.topics) || ['ig_sub_direct']), active: (((_b = this.data.mqttTopics) === null || _b === void 0 ? void 0 : _b.topics) || ['ig_sub_direct']).slice(), lastCheck: new Date().toISOString(), needsResubscribe: false };
287
+ if (!this.data.mqttTraffic)
288
+ this.data.mqttTraffic = { messagesInPerMin: 0, messagesOutPerMin: 0, lastReset: new Date().toISOString() };
289
+ if (!this.data.mqttRisk)
290
+ this.data.mqttRisk = { riskScore: 0, level: 'low', updatedAt: new Date().toISOString() };
291
+ return {
292
+ creds: this.data.creds,
293
+ device: this.data.device,
294
+ cookies: this.data.cookies,
295
+ mqttSession: this.data.mqttSession,
296
+ subscriptions: this.data.subscriptions,
297
+ seqIds: this.data.seqIds,
298
+ appState: this.data.appState,
299
+ irisState: this.data.irisState,
300
+ mqttTopics: this.data.mqttTopics,
301
+ mqttCapabilities: this.data.mqttCapabilities,
302
+ mqttAuth: this.data.mqttAuth,
303
+ lastPublishIds: this.data.lastPublishIds,
304
+ loginHistory: this.data.loginHistory,
305
+ usageStats: this.data.usageStats,
306
+ accountsIndex: this.data.accountsIndex,
307
+ mqttHealth: this.data.mqttHealth,
308
+ mqttReconnect: this.data.mqttReconnect,
309
+ mqttMessageCache: this.data.mqttMessageCache,
310
+ mqttOutbox: this.data.mqttOutbox,
311
+ mqttSubscriptionHealth: this.data.mqttSubscriptionHealth,
312
+ mqttTraffic: this.data.mqttTraffic,
313
+ mqttRisk: this.data.mqttRisk,
314
+ hasSession: !!(this.data.creds && this.data.cookies)
315
+ };
316
+ }
317
+ async saveAll() {
318
+ const savePromises = Object.keys(FILE_NAMES).map(async (key) => {
319
+ if (this.data[key] !== null && this.data[key] !== undefined) {
320
+ await this._writeFile(key, this.data[key]);
321
+ }
322
+ });
323
+ // also save usageStats and loginHistory explicitly
324
+ if (this.data.loginHistory) {
325
+ try {
326
+ await this._writeFile('loginHistory', this.data.loginHistory);
327
+ }
328
+ catch (e) { }
329
+ }
330
+ if (this.data.usageStats) {
331
+ try {
332
+ await this._writeFile('usageStats', this.data.usageStats);
333
+ }
334
+ catch (e) { }
335
+ }
336
+ if (this.data.accountsIndex) {
337
+ try {
338
+ await this._writeFile('accountsIndex', this.data.accountsIndex);
339
+ }
340
+ catch (e) { }
341
+ }
342
+ // mqtt helpers
343
+ try {
344
+ await this._writeFile('mqttHealth', this.data.mqttHealth);
345
+ }
346
+ catch (e) { }
347
+ try {
348
+ await this._writeFile('mqttReconnect', this.data.mqttReconnect);
349
+ }
350
+ catch (e) { }
351
+ try {
352
+ await this._writeFile('mqttMessageCache', this.data.mqttMessageCache);
353
+ }
354
+ catch (e) { }
355
+ try {
356
+ await this._writeFile('mqttOutbox', this.data.mqttOutbox);
357
+ }
358
+ catch (e) { }
359
+ try {
360
+ await this._writeFile('mqttSubscriptionHealth', this.data.mqttSubscriptionHealth);
361
+ }
362
+ catch (e) { }
363
+ try {
364
+ await this._writeFile('mqttTraffic', this.data.mqttTraffic);
365
+ }
366
+ catch (e) { }
367
+ try {
368
+ await this._writeFile('mqttRisk', this.data.mqttRisk);
369
+ }
370
+ catch (e) { }
371
+ await Promise.all(savePromises);
372
+ }
373
+ async saveCreds() {
374
+ const promises = [];
375
+ if (this.data.creds)
376
+ promises.push(this._writeFile('creds', this.data.creds));
377
+ if (this.data.device)
378
+ promises.push(this._writeFile('device', this.data.device));
379
+ if (this.data.cookies)
380
+ promises.push(this._writeFile('cookies', this.data.cookies));
381
+ // also persist loginHistory and usageStats after creds save
382
+ if (this.data.loginHistory)
383
+ promises.push(this._writeFile('loginHistory', this.data.loginHistory));
384
+ if (this.data.usageStats)
385
+ promises.push(this._writeFile('usageStats', this.data.usageStats));
386
+ await Promise.all(promises);
387
+ this.emit('creds-saved');
388
+ }
389
+ async saveMqttState() {
390
+ // Save base mqtt data
391
+ const promises = [];
392
+ if (this.data.mqttSession)
393
+ promises.push(this._writeFile('mqttSession', this.data.mqttSession));
394
+ if (this.data.subscriptions)
395
+ promises.push(this._writeFile('subscriptions', this.data.subscriptions));
396
+ if (this.data.seqIds)
397
+ promises.push(this._writeFile('seqIds', this.data.seqIds));
398
+ // Save extended mqtt/realtime data (new files)
399
+ if (this.data.irisState)
400
+ promises.push(this._writeFile('irisState', this.data.irisState));
401
+ if (this.data.mqttTopics)
402
+ promises.push(this._writeFile('mqttTopics', this.data.mqttTopics));
403
+ if (this.data.mqttCapabilities)
404
+ promises.push(this._writeFile('mqttCapabilities', this.data.mqttCapabilities));
405
+ if (this.data.mqttAuth)
406
+ promises.push(this._writeFile('mqttAuth', this.data.mqttAuth));
407
+ if (this.data.lastPublishIds)
408
+ promises.push(this._writeFile('lastPublishIds', this.data.lastPublishIds));
409
+ // mqtt helpers
410
+ promises.push(this._writeFile('mqttHealth', this.data.mqttHealth));
411
+ promises.push(this._writeFile('mqttReconnect', this.data.mqttReconnect));
412
+ promises.push(this._writeFile('mqttMessageCache', this.data.mqttMessageCache));
413
+ promises.push(this._writeFile('mqttOutbox', this.data.mqttOutbox));
414
+ promises.push(this._writeFile('mqttSubscriptionHealth', this.data.mqttSubscriptionHealth));
415
+ promises.push(this._writeFile('mqttTraffic', this.data.mqttTraffic));
416
+ promises.push(this._writeFile('mqttRisk', this.data.mqttRisk));
417
+ await Promise.all(promises);
418
+ this.emit('mqtt-state-saved');
419
+ }
420
+ async saveAppState() {
421
+ if (this.data.appState) {
422
+ await this._writeFile('appState', this.data.appState);
423
+ }
424
+ }
425
+ _debouncedSave(keys) {
426
+ keys.forEach(k => this._dirty.add(k));
427
+ if (this._saveDebounceTimer) {
428
+ clearTimeout(this._saveDebounceTimer);
429
+ }
430
+ this._saveDebounceTimer = setTimeout(async () => {
431
+ const toSave = Array.from(this._dirty);
432
+ this._dirty.clear();
433
+ for (const key of toSave) {
434
+ if (this.data[key] !== null && this.data[key] !== undefined) {
435
+ try {
436
+ // ensure backup for critical files
437
+ if (['creds', 'cookies', 'device'].includes(key)) {
438
+ await this._createBackup(key);
439
+ }
440
+ await this._writeFile(key, this.data[key]);
441
+ }
442
+ catch (e) {
443
+ console.error(`[MultiFileAuthState] Debounced write error for ${key}:`, e.message);
444
+ // increment usageStats.errors
445
+ try {
446
+ this.incrementStat('errors');
447
+ }
448
+ catch (e2) { }
449
+ }
450
+ }
451
+ }
452
+ this.emit('debounced-save-complete', toSave);
453
+ }, this._saveDebounceMs);
454
+ }
455
+ // --- Setters that schedule debounced saves ---
456
+ setCreds(creds) {
457
+ this.data.creds = creds;
458
+ this._debouncedSave(['creds']);
459
+ }
460
+ setDevice(device) {
461
+ this.data.device = device;
462
+ this._debouncedSave(['device']);
463
+ }
464
+ setCookies(cookies) {
465
+ this.data.cookies = cookies;
466
+ this._debouncedSave(['cookies']);
467
+ }
468
+ setMqttSession(session) {
469
+ this.data.mqttSession = session;
470
+ this._debouncedSave(['mqttSession']);
471
+ }
472
+ setSubscriptions(subs) {
473
+ this.data.subscriptions = subs;
474
+ this._debouncedSave(['subscriptions']);
475
+ }
476
+ setSeqIds(seqIds) {
477
+ this.data.seqIds = seqIds;
478
+ this._debouncedSave(['seqIds']);
479
+ }
480
+ setAppState(state) {
481
+ this.data.appState = state;
482
+ this._debouncedSave(['appState']);
483
+ }
484
+ // --- New setters for additional MQTT files ---
485
+ setIrisState(irisState) {
486
+ this.data.irisState = irisState;
487
+ this._debouncedSave(['irisState']);
488
+ }
489
+ setMqttTopics(topics) {
490
+ this.data.mqttTopics = topics;
491
+ this._debouncedSave(['mqttTopics']);
492
+ }
493
+ setMqttCapabilities(capabilities) {
494
+ this.data.mqttCapabilities = capabilities;
495
+ this._debouncedSave(['mqttCapabilities']);
496
+ }
497
+ setMqttAuth(auth) {
498
+ this.data.mqttAuth = auth;
499
+ this._debouncedSave(['mqttAuth']);
500
+ }
501
+ setLastPublishIds(lastPublishIds) {
502
+ this.data.lastPublishIds = lastPublishIds;
503
+ this._debouncedSave(['lastPublishIds']);
504
+ }
505
+ // --- Utility setters ---
506
+ addLoginHistory(entry) {
507
+ if (!this.data.loginHistory)
508
+ this.data.loginHistory = [];
509
+ this.data.loginHistory.unshift(entry);
510
+ // keep bounded history length
511
+ if (this.data.loginHistory.length > 200)
512
+ this.data.loginHistory.length = 200;
513
+ this._debouncedSave(['loginHistory']);
514
+ this.emit('login-attempt', entry);
515
+ }
516
+ incrementStat(statName, by = 1) {
517
+ if (!this.data.usageStats)
518
+ this.data.usageStats = {
519
+ apiRequests: 0,
520
+ mqttMessages: 0,
521
+ errors: 0,
522
+ reconnects: 0,
523
+ lastReset: new Date().toISOString()
524
+ };
525
+ if (typeof this.data.usageStats[statName] === 'number') {
526
+ this.data.usageStats[statName] += by;
527
+ }
528
+ else {
529
+ this.data.usageStats[statName] = (this.data.usageStats[statName] || 0) + by;
530
+ }
531
+ this._debouncedSave(['usageStats']);
532
+ }
533
+ // --- MQTT helper methods ---
534
+ // update mqtt health and persist
535
+ _updateMqttHealth(partial) {
536
+ try {
537
+ if (!this.data.mqttHealth)
538
+ this.data.mqttHealth = {};
539
+ Object.assign(this.data.mqttHealth, partial);
540
+ // recompute status
541
+ if (this.data.mqttHealth.missedPings > 3) {
542
+ this.data.mqttHealth.status = 'degraded';
543
+ }
544
+ else if (this.data.mqttHealth.lastPongAt) {
545
+ this.data.mqttHealth.status = 'ok';
546
+ }
547
+ else {
548
+ this.data.mqttHealth.status = this.data.mqttHealth.status || 'unknown';
549
+ }
550
+ this._debouncedSave(['mqttHealth']);
551
+ }
552
+ catch (e) { }
553
+ }
554
+ // mark ping sent
555
+ markPing() {
556
+ this._updateMqttHealth({ lastPingAt: new Date().toISOString() });
557
+ }
558
+ // mark pong received and update latency
559
+ markPong() {
560
+ var _a, _b;
561
+ const now = Date.now();
562
+ const lastPing = ((_a = this.data.mqttHealth) === null || _a === void 0 ? void 0 : _a.lastPingAt) ? new Date(this.data.mqttHealth.lastPingAt).getTime() : null;
563
+ const latency = lastPing ? (now - lastPing) : 0;
564
+ const missed = Math.max(0, (((_b = this.data.mqttHealth) === null || _b === void 0 ? void 0 : _b.missedPings) || 0) - 1);
565
+ this._updateMqttHealth({ lastPongAt: new Date().toISOString(), latencyMs: latency, missedPings: missed });
566
+ }
567
+ // increment missed ping
568
+ markMissedPing() {
569
+ var _a;
570
+ const missed = (((_a = this.data.mqttHealth) === null || _a === void 0 ? void 0 : _a.missedPings) || 0) + 1;
571
+ this._updateMqttHealth({ missedPings: missed });
572
+ }
573
+ // message deduplication: return true if duplicate
574
+ isDuplicateMessage(messageId) {
575
+ if (!messageId)
576
+ return false;
577
+ if (!this.data.mqttMessageCache)
578
+ this.data.mqttMessageCache = { lastIds: [], max: 500 };
579
+ const idx = this.data.mqttMessageCache.lastIds.indexOf(messageId);
580
+ if (idx !== -1)
581
+ return true;
582
+ // push and cap
583
+ this.data.mqttMessageCache.lastIds.push(messageId);
584
+ if (this.data.mqttMessageCache.lastIds.length > (this.data.mqttMessageCache.max || 500)) {
585
+ this.data.mqttMessageCache.lastIds.shift();
586
+ }
587
+ this._debouncedSave(['mqttMessageCache']);
588
+ return false;
589
+ }
590
+ // enqueue outgoing message to outbox
591
+ enqueueOutbox(item) {
592
+ if (!this.data.mqttOutbox)
593
+ this.data.mqttOutbox = [];
594
+ // item: { topic, payload, qos, createdAt, tries }
595
+ const i = Object.assign({ qos: 1, createdAt: new Date().toISOString(), tries: 0 }, item);
596
+ this.data.mqttOutbox.push(i);
597
+ this._debouncedSave(['mqttOutbox']);
598
+ this.emit('outbox-enqueued', i);
599
+ return i;
600
+ }
601
+ // flush outbox (attempt send). Tries to use common publish/send methods on client
602
+ async flushOutbox(realtimeClient, maxPerRun = 50) {
603
+ if (!this.data.mqttOutbox || !this.data.mqttOutbox.length)
604
+ return 0;
605
+ const sent = [];
606
+ const keep = [];
607
+ let processed = 0;
608
+ for (const item of this.data.mqttOutbox) {
609
+ if (processed >= maxPerRun) {
610
+ keep.push(item);
611
+ continue;
612
+ }
613
+ processed++;
614
+ try {
615
+ item.tries = (item.tries || 0) + 1;
616
+ // try publish methods in order of likelihood
617
+ let ok = false;
618
+ if (realtimeClient && typeof realtimeClient.publish === 'function') {
619
+ // mqtt.js style
620
+ try {
621
+ realtimeClient.publish(item.topic, typeof item.payload === 'string' ? item.payload : JSON.stringify(item.payload), { qos: item.qos });
622
+ ok = true;
623
+ }
624
+ catch (e) {
625
+ ok = false;
626
+ }
627
+ }
628
+ else if (realtimeClient && typeof realtimeClient.send === 'function') {
629
+ try {
630
+ realtimeClient.send(item.topic, item.payload);
631
+ ok = true;
632
+ }
633
+ catch (e) {
634
+ ok = false;
635
+ }
636
+ }
637
+ else if (realtimeClient && typeof realtimeClient.sendMessage === 'function') {
638
+ try {
639
+ realtimeClient.sendMessage(item.payload);
640
+ ok = true;
641
+ }
642
+ catch (e) {
643
+ ok = false;
644
+ }
645
+ }
646
+ else {
647
+ // cannot send: keep in outbox
648
+ ok = false;
649
+ }
650
+ if (ok) {
651
+ sent.push(item);
652
+ this.incrementStat('mqttMessages', 1);
653
+ }
654
+ else {
655
+ // keep for retry, but if tries exceed threshold move to dead-letter (drop)
656
+ if (item.tries >= 10) {
657
+ this.emit('outbox-dropped', item);
658
+ }
659
+ else {
660
+ keep.push(item);
661
+ }
662
+ }
663
+ }
664
+ catch (e) {
665
+ keep.push(item);
666
+ }
667
+ }
668
+ // replace queue
669
+ this.data.mqttOutbox = keep.concat(this.data.mqttOutbox.slice(processed));
670
+ this._debouncedSave(['mqttOutbox']);
671
+ this.emit('outbox-flushed', { sentCount: sent.length, remaining: this.data.mqttOutbox.length });
672
+ return sent.length;
673
+ }
674
+ // subscription watchdog: check and attempt resubscribe
675
+ async checkSubscriptions(realtimeClient) {
676
+ var _a, _b, _c, _d;
677
+ try {
678
+ const expected = ((_a = this.data.mqttSubscriptionHealth) === null || _a === void 0 ? void 0 : _a.expected) || (((_b = this.data.mqttTopics) === null || _b === void 0 ? void 0 : _b.topics) || []);
679
+ let active = [];
680
+ // try to read from client
681
+ if ((_c = realtimeClient === null || realtimeClient === void 0 ? void 0 : realtimeClient.connection) === null || _c === void 0 ? void 0 : _c.subscribedTopics)
682
+ active = realtimeClient.connection.subscribedTopics;
683
+ else if (realtimeClient === null || realtimeClient === void 0 ? void 0 : realtimeClient._subscribedTopics)
684
+ active = realtimeClient._subscribedTopics;
685
+ else if (Array.isArray((_d = this.data.mqttTopics) === null || _d === void 0 ? void 0 : _d.topics))
686
+ active = this.data.mqttTopics.topics;
687
+ const needs = expected.filter(t => !active.includes(t));
688
+ this.data.mqttSubscriptionHealth = {
689
+ expected,
690
+ active,
691
+ lastCheck: new Date().toISOString(),
692
+ needsResubscribe: needs.length > 0
693
+ };
694
+ this._debouncedSave(['mqttSubscriptionHealth']);
695
+ if (needs.length && realtimeClient) {
696
+ for (const t of needs) {
697
+ try {
698
+ // call common subscribe methods
699
+ if (typeof realtimeClient.subscribe === 'function') {
700
+ realtimeClient.subscribe(t);
701
+ }
702
+ else if (realtimeClient.connection && typeof realtimeClient.connection.subscribe === 'function') {
703
+ realtimeClient.connection.subscribe(t);
704
+ }
705
+ else if (typeof realtimeClient.subscriptions === 'function') {
706
+ realtimeClient.subscriptions([t]);
707
+ }
708
+ // update active
709
+ if (!this.data.mqttSubscriptionHealth.active.includes(t))
710
+ this.data.mqttSubscriptionHealth.active.push(t);
711
+ this.emit('resubscribe-attempt', { topic: t });
712
+ }
713
+ catch (e) {
714
+ this.emit('resubscribe-failed', { topic: t, error: e.message });
715
+ }
716
+ }
717
+ this._debouncedSave(['mqttSubscriptionHealth']);
718
+ }
719
+ return this.data.mqttSubscriptionHealth;
720
+ }
721
+ catch (e) {
722
+ return null;
723
+ }
724
+ }
725
+ // traffic profiler: update incoming/outgoing counters
726
+ _updateTraffic(incoming = 0, outgoing = 0) {
727
+ try {
728
+ if (!this.data.mqttTraffic)
729
+ this.data.mqttTraffic = { messagesInPerMin: 0, messagesOutPerMin: 0, lastReset: new Date().toISOString() };
730
+ const lastReset = new Date(this.data.mqttTraffic.lastReset).getTime();
731
+ if (Date.now() - lastReset > 60 * 1000) {
732
+ // reset every minute
733
+ this.data.mqttTraffic.messagesInPerMin = 0;
734
+ this.data.mqttTraffic.messagesOutPerMin = 0;
735
+ this.data.mqttTraffic.lastReset = new Date().toISOString();
736
+ }
737
+ this.data.mqttTraffic.messagesInPerMin += incoming;
738
+ this.data.mqttTraffic.messagesOutPerMin += outgoing;
739
+ this._debouncedSave(['mqttTraffic']);
740
+ }
741
+ catch (e) { }
742
+ }
743
+ // compute simple risk score from reconnects, errors, traffic
744
+ _computeRiskScore() {
745
+ var _a, _b, _c;
746
+ try {
747
+ const reconnects = ((_a = this.data.usageStats) === null || _a === void 0 ? void 0 : _a.reconnects) || 0;
748
+ const errors = ((_b = this.data.usageStats) === null || _b === void 0 ? void 0 : _b.errors) || 0;
749
+ const outPerMin = ((_c = this.data.mqttTraffic) === null || _c === void 0 ? void 0 : _c.messagesOutPerMin) || 0;
750
+ // simple heuristic
751
+ let score = 0;
752
+ score += Math.min(1, reconnects / 10) * 0.4;
753
+ score += Math.min(1, errors / 20) * 0.3;
754
+ score += Math.min(1, outPerMin / 200) * 0.3;
755
+ const level = score > 0.7 ? 'high' : score > 0.35 ? 'medium' : 'low';
756
+ this.data.mqttRisk = { riskScore: Number(score.toFixed(3)), level, updatedAt: new Date().toISOString() };
757
+ this._debouncedSave(['mqttRisk']);
758
+ this.emit('risk-updated', this.data.mqttRisk);
759
+ return this.data.mqttRisk;
760
+ }
761
+ catch (e) {
762
+ return null;
763
+ }
764
+ }
765
+ // schedule auto reconnect using backoff; will attempt to call client.reconnect() if available or emit event
766
+ _scheduleReconnect(realtimeClient, reason = 'unknown') {
767
+ try {
768
+ this._reconnectAttempts = (this._reconnectAttempts || 0) + 1;
769
+ const idx = Math.min(this._reconnectAttempts - 1, this._reconnectBackoff.length - 1);
770
+ const delay = this._reconnectBackoff[idx] || this._reconnectBackoff[this._reconnectBackoff.length - 1];
771
+ this.data.mqttReconnect = {
772
+ attempts: this._reconnectAttempts,
773
+ lastReason: reason,
774
+ lastAttemptAt: new Date().toISOString(),
775
+ nextRetryInMs: delay
776
+ };
777
+ this.incrementStat('reconnects', 1);
778
+ this._debouncedSave(['mqttReconnect']);
779
+ if (this._reconnectTimer)
780
+ clearTimeout(this._reconnectTimer);
781
+ this._reconnectTimer = setTimeout(async () => {
782
+ try {
783
+ if (realtimeClient) {
784
+ if (typeof realtimeClient.reconnect === 'function') {
785
+ realtimeClient.reconnect();
786
+ }
787
+ else if (typeof realtimeClient.connect === 'function') {
788
+ // some libs have connect
789
+ realtimeClient.connect();
790
+ }
791
+ else {
792
+ // can't auto-call: emit event so app can handle
793
+ this.emit('should-reconnect', { reason });
794
+ }
795
+ }
796
+ else {
797
+ this.emit('should-reconnect', { reason });
798
+ }
799
+ }
800
+ catch (e) {
801
+ this.emit('reconnect-failed', { reason, error: e.message });
802
+ }
803
+ }, delay);
804
+ }
805
+ catch (e) { }
806
+ }
807
+ // reset reconnect attempts after successful connect
808
+ _resetReconnect() {
809
+ this._reconnectAttempts = 0;
810
+ if (this._reconnectTimer) {
811
+ clearTimeout(this._reconnectTimer);
812
+ this._reconnectTimer = null;
813
+ }
814
+ if (this.data.mqttReconnect) {
815
+ this.data.mqttReconnect.attempts = 0;
816
+ this.data.mqttReconnect.nextRetryInMs = 0;
817
+ this._debouncedSave(['mqttReconnect']);
818
+ }
819
+ }
820
+ // warm-restore: apply saved options into realtimeClient before connect to speed startup
821
+ warmRestoreClient(realtimeClient) {
822
+ var _a;
823
+ try {
824
+ const opts = this.getMqttConnectOptions();
825
+ if (!opts)
826
+ return false;
827
+ // Merge irisData, mqttAuthToken etc. into client init options if possible
828
+ if (realtimeClient.initOptions && typeof realtimeClient.initOptions === 'object') {
829
+ Object.assign(realtimeClient.initOptions, opts);
830
+ }
831
+ else {
832
+ realtimeClient.initOptions = opts;
833
+ }
834
+ // also set connection clientInfo if supported
835
+ if (realtimeClient.connection && realtimeClient.connection.clientInfo && ((_a = this.data.mqttSession) === null || _a === void 0 ? void 0 : _a.mqttSessionId)) {
836
+ realtimeClient.connection.clientInfo.clientMqttSessionId = this.data.mqttSession.mqttSessionId;
837
+ }
838
+ this.emit('warm-restore', { options: opts });
839
+ return true;
840
+ }
841
+ catch (e) {
842
+ return false;
843
+ }
844
+ }
845
+ // attach runtime helpers to realtimeClient to manage instant improvements
846
+ attachRealtimeClient(realtimeClient, opts = {}) {
847
+ try {
848
+ if (!realtimeClient)
849
+ return;
850
+ // warm restore immediately
851
+ try {
852
+ this.warmRestoreClient(realtimeClient);
853
+ }
854
+ catch (e) { }
855
+ // ping/pong monitoring
856
+ const pingIntervalMs = opts.pingIntervalMs || 30 * 1000; // 30s
857
+ let pingTimer = null;
858
+ const startPing = () => {
859
+ if (pingTimer)
860
+ clearInterval(pingTimer);
861
+ pingTimer = setInterval(() => {
862
+ try {
863
+ this.markPing();
864
+ if (typeof realtimeClient.ping === 'function') {
865
+ realtimeClient.ping();
866
+ }
867
+ else if (typeof realtimeClient.pingReq === 'function') {
868
+ realtimeClient.pingReq();
869
+ }
870
+ else if (typeof realtimeClient.pingServer === 'function') {
871
+ realtimeClient.pingServer();
872
+ }
873
+ else {
874
+ // some libraries use publish to $SYS topic or nothing; we still mark ping
875
+ }
876
+ // after ping, schedule missed ping detection
877
+ setTimeout(() => {
878
+ var _a, _b;
879
+ // if lastPongAt older than lastPingAt, consider missed
880
+ const lastPing = new Date(((_a = this.data.mqttHealth) === null || _a === void 0 ? void 0 : _a.lastPingAt) || 0).getTime();
881
+ const lastPong = new Date(((_b = this.data.mqttHealth) === null || _b === void 0 ? void 0 : _b.lastPongAt) || 0).getTime();
882
+ if (lastPing && (!lastPong || lastPong < lastPing)) {
883
+ this.markMissedPing();
884
+ }
885
+ }, Math.min(5000, Math.floor(pingIntervalMs / 2)));
886
+ }
887
+ catch (e) { }
888
+ }, pingIntervalMs);
889
+ };
890
+ const stopPing = () => { if (pingTimer)
891
+ clearInterval(pingTimer); pingTimer = null; };
892
+ // event handlers (subscribe to multiple common event names)
893
+ const onConnect = async (...args) => {
894
+ this._resetReconnect();
895
+ this.data.mqttSession = this.data.mqttSession || {};
896
+ this.data.mqttSession.lastConnected = new Date().toISOString();
897
+ this._debouncedSave(['mqttSession']);
898
+ this._updateMqttHealth({ status: 'ok', lastPongAt: new Date().toISOString(), missedPings: 0 });
899
+ this.emit('realtime-connected', { args });
900
+ // flush outbox on connect
901
+ try {
902
+ await this.flushOutbox(realtimeClient);
903
+ }
904
+ catch (e) { }
905
+ // check subscriptions
906
+ try {
907
+ await this.checkSubscriptions(realtimeClient);
908
+ }
909
+ catch (e) { }
910
+ startPing();
911
+ };
912
+ const onClose = (...args) => {
913
+ stopPing();
914
+ this._updateMqttHealth({ status: 'dead' });
915
+ this._scheduleReconnect(realtimeClient, 'close');
916
+ this.emit('realtime-closed', { args });
917
+ };
918
+ const onReconnect = (...args) => {
919
+ this.emit('realtime-reconnect', { args });
920
+ };
921
+ const onOffline = (...args) => {
922
+ this._updateMqttHealth({ status: 'degraded' });
923
+ this._scheduleReconnect(realtimeClient, 'offline');
924
+ this.emit('realtime-offline', { args });
925
+ };
926
+ const onError = (err) => {
927
+ this.incrementStat('errors', 1);
928
+ this._scheduleReconnect(realtimeClient, (err === null || err === void 0 ? void 0 : err.message) || 'error');
929
+ this.emit('realtime-error', { error: (err === null || err === void 0 ? void 0 : err.message) || String(err) });
930
+ };
931
+ const onMessage = async (topic, payload, packet) => {
932
+ // generic message handler: try to extract id for dedupe
933
+ // Many IG messages contain an id field in JSON payload; try to parse
934
+ let messageId = null;
935
+ try {
936
+ const s = (typeof payload === 'string') ? payload : (payload && payload.toString ? payload.toString() : null);
937
+ if (s) {
938
+ const j = JSON.parse(s);
939
+ if (j && (j.message_id || j.id || j.msg_id))
940
+ messageId = j.message_id || j.id || j.msg_id;
941
+ }
942
+ }
943
+ catch (e) {
944
+ // not json, ignore
945
+ }
946
+ if (messageId && this.isDuplicateMessage(messageId)) {
947
+ this.emit('message-duplicate', { topic, messageId });
948
+ return;
949
+ }
950
+ // update traffic counters
951
+ this._updateTraffic(1, 0);
952
+ this.incrementStat('mqttMessages', 1);
953
+ // mark pong if message looks like pong or heartbeat
954
+ if (topic && topic.includes('pong'))
955
+ this.markPong();
956
+ this.emit('realtime-message', { topic, payload, packet });
957
+ };
958
+ // wire up events safely for common handlers
959
+ try {
960
+ // mqtt.js style
961
+ if (typeof realtimeClient.on === 'function') {
962
+ realtimeClient.on('connect', onConnect);
963
+ realtimeClient.on('reconnect', onReconnect);
964
+ realtimeClient.on('close', onClose);
965
+ realtimeClient.on('offline', onOffline);
966
+ realtimeClient.on('error', onError);
967
+ realtimeClient.on('message', onMessage);
968
+ }
969
+ // websockets or other: attempt to attach possible event names
970
+ if (realtimeClient.addEventListener && typeof realtimeClient.addEventListener === 'function') {
971
+ try {
972
+ realtimeClient.addEventListener('open', onConnect);
973
+ }
974
+ catch (e) { }
975
+ try {
976
+ realtimeClient.addEventListener('close', onClose);
977
+ }
978
+ catch (e) { }
979
+ try {
980
+ realtimeClient.addEventListener('error', onError);
981
+ }
982
+ catch (e) { }
983
+ try {
984
+ realtimeClient.addEventListener('message', (ev) => onMessage(ev.topic || ev.type, ev.data || ev.payload, ev));
985
+ }
986
+ catch (e) { }
987
+ }
988
+ }
989
+ catch (e) { }
990
+ // also attach one-time status: if the client supports events differently, let app listen to 'should-reconnect'
991
+ // attach a cleanup handle
992
+ const cleanup = () => {
993
+ stopPing();
994
+ try {
995
+ if (typeof realtimeClient.off === 'function') {
996
+ realtimeClient.off('connect', onConnect);
997
+ realtimeClient.off('reconnect', onReconnect);
998
+ realtimeClient.off('close', onClose);
999
+ realtimeClient.off('offline', onOffline);
1000
+ realtimeClient.off('error', onError);
1001
+ realtimeClient.off('message', onMessage);
1002
+ }
1003
+ }
1004
+ catch (e) { }
1005
+ this.emit('realtime-detach');
1006
+ };
1007
+ // expose cleanup on client for convenience
1008
+ try {
1009
+ realtimeClient._authStateCleanup = cleanup;
1010
+ }
1011
+ catch (e) { }
1012
+ // return helper object to caller
1013
+ return {
1014
+ pingIntervalMs,
1015
+ stop: cleanup,
1016
+ flushOutbox: async (max) => { return await this.flushOutbox(realtimeClient, max); },
1017
+ checkSubscriptions: async () => { return await this.checkSubscriptions(realtimeClient); },
1018
+ warmRestore: () => { return this.warmRestoreClient(realtimeClient); }
1019
+ };
1020
+ }
1021
+ catch (e) {
1022
+ // emit attach failure
1023
+ this.emit('attach-failed', { error: e.message });
1024
+ return null;
1025
+ }
1026
+ }
1027
+ // --- Getters ---
1028
+ getCreds() { return this.data.creds; }
1029
+ getDevice() { return this.data.device; }
1030
+ getCookies() { return this.data.cookies; }
1031
+ getMqttSession() { return this.data.mqttSession; }
1032
+ getSubscriptions() { return this.data.subscriptions; }
1033
+ getSeqIds() { return this.data.seqIds; }
1034
+ getAppState() { return this.data.appState; }
1035
+ getIrisState() { return this.data.irisState; }
1036
+ getMqttTopics() { return this.data.mqttTopics; }
1037
+ getMqttCapabilities() { return this.data.mqttCapabilities; }
1038
+ getMqttAuth() { return this.data.mqttAuth; }
1039
+ getLastPublishIds() { return this.data.lastPublishIds; }
1040
+ getLoginHistory() { return this.data.loginHistory || []; }
1041
+ getUsageStats() { return this.data.usageStats || {}; }
1042
+ getAccountsIndex() { return this.data.accountsIndex || {}; }
1043
+ getMqttHealth() { return this.data.mqttHealth || {}; }
1044
+ getMqttReconnect() { return this.data.mqttReconnect || {}; }
1045
+ getMqttMessageCache() { return this.data.mqttMessageCache || {}; }
1046
+ getMqttOutbox() { return this.data.mqttOutbox || []; }
1047
+ getMqttSubscriptionHealth() { return this.data.mqttSubscriptionHealth || {}; }
1048
+ getMqttTraffic() { return this.data.mqttTraffic || {}; }
1049
+ getMqttRisk() { return this.data.mqttRisk || {}; }
1050
+ hasValidSession() {
1051
+ return !!(this.data.creds && this.data.cookies && this.data.creds.authorization);
1052
+ }
1053
+ hasMqttSession() {
1054
+ return !!((this.data.mqttSession && this.data.mqttSession.sessionId) ||
1055
+ (this.data.mqttAuth && this.data.mqttAuth.jwt));
1056
+ }
1057
+ async clearAll() {
1058
+ for (const key of Object.keys(FILE_NAMES)) {
1059
+ const filePath = this._getFilePath(key);
1060
+ try {
1061
+ if (fs.existsSync(filePath)) {
1062
+ await fs.promises.unlink(filePath);
1063
+ }
1064
+ }
1065
+ catch (e) { }
1066
+ this.data[key] = null;
1067
+ }
1068
+ // clear backups too? leave backups intact but emit event
1069
+ this.emit('cleared-all');
1070
+ }
1071
+ // --- Backup utilities exposed ---
1072
+ async listBackups() {
1073
+ try {
1074
+ const b = this._getBackupFolder();
1075
+ if (!fs.existsSync(b))
1076
+ return [];
1077
+ const files = await fs.promises.readdir(b);
1078
+ return files.map(f => path.join(b, f));
1079
+ }
1080
+ catch (e) {
1081
+ return [];
1082
+ }
1083
+ }
1084
+ // --- Device fingerprint helpers ---
1085
+ computeDeviceFingerprint(deviceObj) {
1086
+ try {
1087
+ const s = JSON.stringify(deviceObj || this.data.device || {});
1088
+ return crypto.createHash('sha256').update(s).digest('hex');
1089
+ }
1090
+ catch (e) {
1091
+ return null;
1092
+ }
1093
+ }
1094
+ // lock device fingerprint: saves hash into device.json (device.locked = true)
1095
+ async lockDeviceFingerprint() {
1096
+ try {
1097
+ if (!this.data.device)
1098
+ this.data.device = {};
1099
+ const hash = this.computeDeviceFingerprint(this.data.device);
1100
+ this.data.device.fingerprintHash = hash;
1101
+ this.data.device.locked = true;
1102
+ await this._writeFile('device', this.data.device);
1103
+ this.emit('device-locked', { fingerprintHash: hash });
1104
+ return hash;
1105
+ }
1106
+ catch (e) {
1107
+ console.warn('[MultiFileAuthState] lockDeviceFingerprint failed:', e.message);
1108
+ return null;
1109
+ }
1110
+ }
1111
+ verifyDeviceFingerprint(deviceObj) {
1112
+ var _a;
1113
+ try {
1114
+ const stored = ((_a = this.data.device) === null || _a === void 0 ? void 0 : _a.fingerprintHash) || null;
1115
+ if (!stored)
1116
+ return true; // no lock present
1117
+ const hash = this.computeDeviceFingerprint(deviceObj || this.data.device);
1118
+ return stored === hash;
1119
+ }
1120
+ catch (e) {
1121
+ return false;
1122
+ }
1123
+ }
1124
+ // --- Login history helpers ---
1125
+ recordLoginAttempt({ success, ip, userAgent, method = 'password', reason = null }) {
1126
+ const entry = {
1127
+ date: new Date().toISOString(),
1128
+ success: Boolean(success),
1129
+ ip: ip || null,
1130
+ userAgent: userAgent || null,
1131
+ method,
1132
+ reason
1133
+ };
1134
+ this.addLoginHistory(entry);
1135
+ return entry;
1136
+ }
1137
+ // mark account restricted / checkpoint
1138
+ markAccountRestricted({ status = 'checkpoint', reason = null }) {
1139
+ if (!this.data.creds)
1140
+ this.data.creds = {};
1141
+ this.data.creds.accountStatus = status;
1142
+ this.data.creds.restrictedAt = new Date().toISOString();
1143
+ this.data.creds.lastError = reason;
1144
+ this._debouncedSave(['creds']);
1145
+ this.emit('account-restricted', { status, reason });
1146
+ }
1147
+ // clear restriction
1148
+ clearAccountRestriction() {
1149
+ if (this.data.creds) {
1150
+ delete this.data.creds.accountStatus;
1151
+ delete this.data.creds.restrictedAt;
1152
+ delete this.data.creds.lastError;
1153
+ this._debouncedSave(['creds']);
1154
+ this.emit('account-unrestricted');
1155
+ }
1156
+ }
1157
+ // --- Health check ---
1158
+ getHealth() {
1159
+ var _a, _b, _c;
1160
+ return {
1161
+ validSession: this.hasValidSession(),
1162
+ hasCookies: !!this.data.cookies,
1163
+ hasMqtt: this.hasMqttSession(),
1164
+ lastLogin: (this.data.loginHistory && ((_a = this.data.loginHistory[0]) === null || _a === void 0 ? void 0 : _a.date)) || null,
1165
+ usageStats: this.getUsageStats(),
1166
+ accountStatus: ((_b = this.data.creds) === null || _b === void 0 ? void 0 : _b.accountStatus) || 'ok',
1167
+ deviceLocked: !!((_c = this.data.device) === null || _c === void 0 ? void 0 : _c.locked),
1168
+ mqttHealth: this.getMqttHealth(),
1169
+ mqttRisk: this.getMqttRisk()
1170
+ };
1171
+ }
1172
+ }
1173
+ // Helper: try to safely extract cookieJar serialization if exists
1174
+ async function trySerializeCookieJar(igState) {
1175
+ let cookies = null;
1176
+ try {
1177
+ if (igState.cookieJar && typeof igState.serializeCookieJar === 'function') {
1178
+ cookies = await igState.serializeCookieJar();
1179
+ }
1180
+ else if (igState.cookieJar && typeof igState.cookieJar.serialize === 'function') {
1181
+ // fallback: tough-cookie jar serialize
1182
+ const ser = await util.promisify(igState.cookieJar.serialize).bind(igState.cookieJar)();
1183
+ cookies = ser;
1184
+ }
1185
+ }
1186
+ catch (e) {
1187
+ console.warn('[MultiFileAuthState] Could not serialize cookies:', e.message);
1188
+ }
1189
+ return cookies;
1190
+ }
1191
+ // Helper: try to read a cookie value from a tough-cookie Jar or equivalent
1192
+ async function getCookieValueFromJar(cookieJar, name) {
1193
+ var _a, _b, _c, _d, _e;
1194
+ if (!cookieJar)
1195
+ return null;
1196
+ // try getCookieString (tough-cookie)
1197
+ try {
1198
+ if (typeof cookieJar.getCookieString === 'function') {
1199
+ const getCookieString = util.promisify(cookieJar.getCookieString).bind(cookieJar);
1200
+ const urls = ['https://www.instagram.com', 'https://instagram.com', 'https://i.instagram.com'];
1201
+ for (const url of urls) {
1202
+ try {
1203
+ const cookieString = await getCookieString(url);
1204
+ if (cookieString && typeof cookieString === 'string') {
1205
+ const pairs = cookieString.split(';').map(s => s.trim());
1206
+ for (const p of pairs) {
1207
+ const [k, ...rest] = p.split('=');
1208
+ if (k === name)
1209
+ return rest.join('=');
1210
+ }
1211
+ }
1212
+ }
1213
+ catch (e) {
1214
+ // ignore and try next url
1215
+ }
1216
+ }
1217
+ }
1218
+ }
1219
+ catch (e) {
1220
+ // ignore
1221
+ }
1222
+ // try getCookies which returns Cookie objects
1223
+ try {
1224
+ if (typeof cookieJar.getCookies === 'function') {
1225
+ const getCookies = util.promisify(cookieJar.getCookies).bind(cookieJar);
1226
+ const urls = ['https://www.instagram.com', 'https://instagram.com', 'https://i.instagram.com'];
1227
+ for (const url of urls) {
1228
+ try {
1229
+ const cookies = await getCookies(url);
1230
+ if (Array.isArray(cookies)) {
1231
+ for (const c of cookies) {
1232
+ // cookie object shapes vary: check common keys
1233
+ const key = (_b = (_a = c.key) !== null && _a !== void 0 ? _a : c.name) !== null && _b !== void 0 ? _b : c.name;
1234
+ const val = (_d = (_c = c.value) !== null && _c !== void 0 ? _c : c.value) !== null && _d !== void 0 ? _d : c.value;
1235
+ if (key === name)
1236
+ return val;
1237
+ }
1238
+ }
1239
+ }
1240
+ catch (e) {
1241
+ // ignore and try next url
1242
+ }
1243
+ }
1244
+ }
1245
+ }
1246
+ catch (e) {
1247
+ // ignore
1248
+ }
1249
+ // try serialized cookie jar structure if present
1250
+ try {
1251
+ if (cookieJar && typeof cookieJar === 'object' && cookieJar.cookies && Array.isArray(cookieJar.cookies)) {
1252
+ const found = cookieJar.cookies.find(c => (c.key === name || c.name === name || c.name === name));
1253
+ if (found)
1254
+ return (_e = found.value) !== null && _e !== void 0 ? _e : found.value;
1255
+ }
1256
+ }
1257
+ catch (e) {
1258
+ // ignore
1259
+ }
1260
+ return null;
1261
+ }
1262
+ // Extract cookie-derived fields (sessionid, csrftoken, ds_user_id, mid)
1263
+ async function extractCookieFields(igState) {
1264
+ const out = {
1265
+ sessionIdCookie: null,
1266
+ csrfTokenCookie: null,
1267
+ dsUserIdCookie: null,
1268
+ midCookie: null
1269
+ };
1270
+ try {
1271
+ const cookieJar = igState.cookieJar;
1272
+ out.sessionIdCookie = await getCookieValueFromJar(cookieJar, 'sessionid');
1273
+ out.csrfTokenCookie = await getCookieValueFromJar(cookieJar, 'csrftoken');
1274
+ out.dsUserIdCookie = await getCookieValueFromJar(cookieJar, 'ds_user_id') || await getCookieValueFromJar(cookieJar, 'ds_user');
1275
+ out.midCookie = await getCookieValueFromJar(cookieJar, 'mid');
1276
+ }
1277
+ catch (e) {
1278
+ // ignore
1279
+ }
1280
+ return out;
1281
+ }
1282
+ async function extractStateData(igState) {
1283
+ var _a;
1284
+ // Basic creds (existing)
1285
+ const creds = {
1286
+ authorization: igState.authorization || null,
1287
+ igWWWClaim: igState.igWWWClaim || null,
1288
+ passwordEncryptionKeyId: igState.passwordEncryptionKeyId || null,
1289
+ passwordEncryptionPubKey: igState.passwordEncryptionPubKey || null
1290
+ };
1291
+ // Device remains same
1292
+ const device = {
1293
+ deviceString: igState.deviceString || null,
1294
+ deviceId: igState.deviceId || null,
1295
+ uuid: igState.uuid || null,
1296
+ phoneId: igState.phoneId || null,
1297
+ adid: igState.adid || null,
1298
+ build: igState.build || null
1299
+ };
1300
+ // Try to serialize cookies (kept separate)
1301
+ const cookies = await trySerializeCookieJar(igState);
1302
+ // App state remains same
1303
+ const appState = {
1304
+ language: igState.language || 'en_US',
1305
+ timezoneOffset: igState.timezoneOffset || null,
1306
+ connectionTypeHeader: igState.connectionTypeHeader || 'WIFI',
1307
+ capabilitiesHeader: igState.capabilitiesHeader || null,
1308
+ checkpoint: igState.checkpoint || null,
1309
+ challenge: igState.challenge || null
1310
+ };
1311
+ // --- NEW: richer creds fields derived from igState + cookies ---
1312
+ // try to obtain cookie fields
1313
+ const cookieFields = await extractCookieFields(igState);
1314
+ // try to decode ds_user_id & sessionid from Bearer IGT:2 token (authorization), if present
1315
+ let bearerDsUserId = null;
1316
+ let bearerSessionId = null;
1317
+ try {
1318
+ if (creds.authorization && typeof creds.authorization === 'string') {
1319
+ const m = creds.authorization.match(/^Bearer IGT:2:(.+)$/);
1320
+ if (m && m[1]) {
1321
+ try {
1322
+ const json = Buffer.from(m[1], 'base64').toString('utf8');
1323
+ const parsed = JSON.parse(json);
1324
+ if (parsed && typeof parsed === 'object') {
1325
+ if (parsed.ds_user_id)
1326
+ bearerDsUserId = String(parsed.ds_user_id);
1327
+ if (parsed.sessionid)
1328
+ bearerSessionId = String(parsed.sessionid);
1329
+ }
1330
+ }
1331
+ catch (e2) {
1332
+ // ignore decode errors
1333
+ }
1334
+ }
1335
+ }
1336
+ }
1337
+ catch (e) {
1338
+ // ignore bearer parse error
1339
+ }
1340
+ // Primary identifiers
1341
+ let userIdFromState = null;
1342
+ try {
1343
+ userIdFromState = igState.cookieUserId || null;
1344
+ }
1345
+ catch (e) { }
1346
+ if (!userIdFromState) {
1347
+ userIdFromState = igState.userId || igState.user_id || null;
1348
+ }
1349
+ const dsUserIdFromCookies = cookieFields.dsUserIdCookie || igState.dsUserId || igState.ds_user_id || bearerDsUserId || null;
1350
+ const sessionIdFromCookies = cookieFields.sessionIdCookie || bearerSessionId || null;
1351
+ const csrfFromCookies = cookieFields.csrfTokenCookie || null;
1352
+ const midFromCookies = cookieFields.midCookie || igState.mid || null;
1353
+ // username if exposed on state
1354
+ const usernameFromState = igState.username || igState.userName || ((_a = igState.user) === null || _a === void 0 ? void 0 : _a.username) || null;
1355
+ // rankToken: if userId + uuid available, form `${userId}_${uuid}`
1356
+ let rankToken = null;
1357
+ try {
1358
+ if (userIdFromState && (igState.uuid || device.uuid)) {
1359
+ rankToken = `${userIdFromState}_${igState.uuid || device.uuid}`;
1360
+ }
1361
+ else if (igState.rankToken) {
1362
+ rankToken = igState.rankToken;
1363
+ }
1364
+ }
1365
+ catch (e) {
1366
+ rankToken = igState.rankToken || null;
1367
+ }
1368
+ // sessionId and csrfToken - prefer cookies, fallback to state fields if present
1369
+ const sessionId = sessionIdFromCookies || igState.sessionId || igState.sessionid || null;
1370
+ const csrfToken = csrfFromCookies || igState.csrfToken || igState.csrftoken || null;
1371
+ // mid fallback
1372
+ const mid = midFromCookies || igState.mid || null;
1373
+ // isLoggedIn heuristic: presence of sessionid cookie or an 'isLoggedIn' flag or authorization header
1374
+ const isLoggedIn = Boolean(sessionId ||
1375
+ igState.isLoggedIn ||
1376
+ (creds.authorization && creds.authorization.length));
1377
+ // loginAt / lastValidatedAt: try to take from igState if present, otherwise null
1378
+ const loginAt = igState.loginAt || igState.loggedInAt || null;
1379
+ const lastValidatedAt = igState.lastValidatedAt || igState.lastValidated || null;
1380
+ // Attach all new fields into creds object (non-destructive)
1381
+ creds.userId = userIdFromState || dsUserIdFromCookies || creds.userId || null;
1382
+ creds.dsUserId = dsUserIdFromCookies || null;
1383
+ creds.username = usernameFromState || null;
1384
+ creds.rankToken = rankToken;
1385
+ creds.sessionId = sessionId;
1386
+ creds.csrfToken = csrfToken;
1387
+ creds.mid = mid;
1388
+ creds.isLoggedIn = isLoggedIn;
1389
+ creds.loginAt = loginAt;
1390
+ creds.lastValidatedAt = lastValidatedAt;
1391
+ return { creds, device, cookies, appState };
1392
+ }
1393
+ async function applyStateData(igState, authState) {
1394
+ const { creds, device, cookies, appState } = authState.data;
1395
+ if (creds) {
1396
+ if (creds.authorization)
1397
+ igState.authorization = creds.authorization;
1398
+ if (creds.igWWWClaim)
1399
+ igState.igWWWClaim = creds.igWWWClaim;
1400
+ if (creds.passwordEncryptionKeyId)
1401
+ igState.passwordEncryptionKeyId = creds.passwordEncryptionKeyId;
1402
+ if (creds.passwordEncryptionPubKey)
1403
+ igState.passwordEncryptionPubKey = creds.passwordEncryptionPubKey;
1404
+ // if igState provides a helper to update authorization, call it
1405
+ if (typeof igState.updateAuthorization === 'function') {
1406
+ try {
1407
+ igState.updateAuthorization();
1408
+ }
1409
+ catch (e) { }
1410
+ }
1411
+ // apply new creds-derived fields if state supports them (non-intrusive)
1412
+ try {
1413
+ let _hasCookieUserId = false;
1414
+ try {
1415
+ _hasCookieUserId = !!igState.cookieUserId;
1416
+ }
1417
+ catch (e) { }
1418
+ if (creds.userId && !_hasCookieUserId)
1419
+ igState.cookieUserId = creds.userId;
1420
+ if (creds.username && !igState.username)
1421
+ igState.username = creds.username;
1422
+ if (creds.rankToken && !igState.rankToken)
1423
+ igState.rankToken = creds.rankToken;
1424
+ if (creds.sessionId && !igState.sessionId)
1425
+ igState.sessionId = creds.sessionId;
1426
+ if (creds.csrfToken && !igState.csrfToken)
1427
+ igState.csrfToken = creds.csrfToken;
1428
+ if (creds.mid && !igState.mid)
1429
+ igState.mid = creds.mid;
1430
+ if (typeof creds.isLoggedIn !== 'undefined' && !igState.isLoggedIn)
1431
+ igState.isLoggedIn = creds.isLoggedIn;
1432
+ if (creds.loginAt && !igState.loginAt)
1433
+ igState.loginAt = creds.loginAt;
1434
+ if (creds.lastValidatedAt && !igState.lastValidatedAt)
1435
+ igState.lastValidatedAt = creds.lastValidatedAt;
1436
+ }
1437
+ catch (e) {
1438
+ // ignore if igState shape different
1439
+ }
1440
+ }
1441
+ if (device) {
1442
+ if (device.deviceString)
1443
+ igState.deviceString = device.deviceString;
1444
+ if (device.deviceId)
1445
+ igState.deviceId = device.deviceId;
1446
+ if (device.uuid)
1447
+ igState.uuid = device.uuid;
1448
+ if (device.phoneId)
1449
+ igState.phoneId = device.phoneId;
1450
+ if (device.adid)
1451
+ igState.adid = device.adid;
1452
+ if (device.build)
1453
+ igState.build = device.build;
1454
+ }
1455
+ if (cookies) {
1456
+ try {
1457
+ if (typeof igState.deserializeCookieJar === 'function') {
1458
+ await igState.deserializeCookieJar(cookies);
1459
+ }
1460
+ else if (igState.cookieJar && typeof igState.cookieJar.restore === 'function') {
1461
+ // fallback restore
1462
+ await util.promisify(igState.cookieJar.restore).bind(igState.cookieJar)(cookies);
1463
+ }
1464
+ else if (igState.cookieJar && typeof igState.cookieJar._importCookies === 'function') {
1465
+ // last-resort, not likely
1466
+ try {
1467
+ igState.cookieJar._importCookies(cookies);
1468
+ }
1469
+ catch (e) { }
1470
+ }
1471
+ }
1472
+ catch (e) {
1473
+ console.warn('[MultiFileAuthState] Could not deserialize cookies:', e.message);
1474
+ }
1475
+ }
1476
+ if (appState) {
1477
+ if (appState.language)
1478
+ igState.language = appState.language;
1479
+ if (appState.timezoneOffset)
1480
+ igState.timezoneOffset = appState.timezoneOffset;
1481
+ if (appState.connectionTypeHeader)
1482
+ igState.connectionTypeHeader = appState.connectionTypeHeader;
1483
+ if (appState.capabilitiesHeader)
1484
+ igState.capabilitiesHeader = appState.capabilitiesHeader;
1485
+ if (appState.checkpoint)
1486
+ igState.checkpoint = appState.checkpoint;
1487
+ if (appState.challenge)
1488
+ igState.challenge = appState.challenge;
1489
+ }
1490
+ }
1491
+ // Main exported helper that wires MultiFileAuthState to your clients
1492
+ async function useMultiFileAuthState(folder) {
1493
+ const authState = new MultiFileAuthState(folder);
1494
+ await authState.loadAll();
1495
+ // Helper: persist additional derived creds fields when saving creds
1496
+ const enrichAndSaveCreds = async (igClientState) => {
1497
+ const { creds, device, cookies, appState } = await extractStateData(igClientState);
1498
+ // merge with existing creds non-destructive
1499
+ authState.data.creds = Object.assign({}, authState.data.creds || {}, creds);
1500
+ authState.data.device = Object.assign({}, authState.data.device || {}, device);
1501
+ authState.data.cookies = cookies || authState.data.cookies;
1502
+ authState.data.appState = Object.assign({}, authState.data.appState || {}, appState);
1503
+ await authState.saveCreds();
1504
+ await authState.saveAppState();
1505
+ };
1506
+ const saveCreds = async (igClient) => {
1507
+ if (!igClient || !igClient.state) {
1508
+ console.warn('[useMultiFileAuthState] No igClient provided to saveCreds');
1509
+ return;
1510
+ }
1511
+ // Use the enriched saver
1512
+ await enrichAndSaveCreds(igClient.state);
1513
+ // Also attempt to extract some cookie-derived fields for convenience
1514
+ try {
1515
+ const cookieFields = await extractCookieFields(igClient.state);
1516
+ if (cookieFields.sessionIdCookie) {
1517
+ if (!authState.data.creds)
1518
+ authState.data.creds = {};
1519
+ authState.data.creds.sessionId = cookieFields.sessionIdCookie;
1520
+ }
1521
+ if (cookieFields.dsUserIdCookie) {
1522
+ if (!authState.data.creds)
1523
+ authState.data.creds = {};
1524
+ authState.data.creds.dsUserId = cookieFields.dsUserIdCookie;
1525
+ }
1526
+ authState._debouncedSave(['creds']);
1527
+ }
1528
+ catch (e) { }
1529
+ console.log('[useMultiFileAuthState] Credentials saved to', folder);
1530
+ };
1531
+ const saveMqttSession = async (realtimeClient) => {
1532
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9;
1533
+ if (!realtimeClient) {
1534
+ console.warn('[useMultiFileAuthState] No realtimeClient provided');
1535
+ return;
1536
+ }
1537
+ // base mqtt session
1538
+ const mqttSession = {
1539
+ sessionId: null,
1540
+ mqttSessionId: null,
1541
+ lastConnected: new Date().toISOString(),
1542
+ userId: null
1543
+ };
1544
+ try {
1545
+ if (realtimeClient.ig && realtimeClient.ig.state) {
1546
+ mqttSession.userId = realtimeClient.ig.state.cookieUserId || realtimeClient.ig.state.userId || null;
1547
+ // attempt to extract sessionId from JWT helper if available
1548
+ mqttSession.sessionId = (typeof realtimeClient.extractSessionIdFromJWT === 'function') ? realtimeClient.extractSessionIdFromJWT() : null;
1549
+ }
1550
+ if (realtimeClient.connection) {
1551
+ mqttSession.mqttSessionId = ((_c = (_b = (_a = realtimeClient.connection) === null || _a === void 0 ? void 0 : _a.clientInfo) === null || _b === void 0 ? void 0 : _b.clientMqttSessionId) === null || _c === void 0 ? void 0 : _c.toString()) || null;
1552
+ }
1553
+ }
1554
+ catch (e) {
1555
+ // ignore
1556
+ }
1557
+ // subscriptions
1558
+ const subscriptions = {
1559
+ graphQlSubs: ((_d = realtimeClient.initOptions) === null || _d === void 0 ? void 0 : _d.graphQlSubs) || [],
1560
+ skywalkerSubs: ((_e = realtimeClient.initOptions) === null || _e === void 0 ? void 0 : _e.skywalkerSubs) || [],
1561
+ subscribedAt: new Date().toISOString()
1562
+ };
1563
+ // seq ids (iris)
1564
+ const seqIds = {};
1565
+ if ((_f = realtimeClient.initOptions) === null || _f === void 0 ? void 0 : _f.irisData) {
1566
+ seqIds.seq_id = realtimeClient.initOptions.irisData.seq_id || null;
1567
+ seqIds.snapshot_at_ms = realtimeClient.initOptions.irisData.snapshot_at_ms || null;
1568
+ }
1569
+ // --- Extended MQTT / realtime info (new) ---
1570
+ // irisState: things like subscription_id / device id / other iris metadata
1571
+ const irisState = {};
1572
+ try {
1573
+ // try to glean from various possible places on realtimeClient
1574
+ irisState.subscription_id = ((_h = (_g = realtimeClient.initOptions) === null || _g === void 0 ? void 0 : _g.irisData) === null || _h === void 0 ? void 0 : _h.subscription_id) || ((_j = realtimeClient.iris) === null || _j === void 0 ? void 0 : _j.subscriptionId) || ((_k = realtimeClient.irisState) === null || _k === void 0 ? void 0 : _k.subscription_id) || null;
1575
+ irisState.user_id = ((_m = (_l = realtimeClient.ig) === null || _l === void 0 ? void 0 : _l.state) === null || _m === void 0 ? void 0 : _m.cookieUserId) || ((_p = (_o = realtimeClient.ig) === null || _o === void 0 ? void 0 : _o.state) === null || _p === void 0 ? void 0 : _p.userId) || irisState.user_id || null;
1576
+ irisState.device_id = ((_r = (_q = realtimeClient.connection) === null || _q === void 0 ? void 0 : _q.clientInfo) === null || _r === void 0 ? void 0 : _r.deviceId) || ((_s = realtimeClient.initOptions) === null || _s === void 0 ? void 0 : _s.deviceId) || null;
1577
+ irisState.created_at = new Date().toISOString();
1578
+ }
1579
+ catch (e) { }
1580
+ // mqttTopics: topics observed/subscribed
1581
+ const mqttTopics = {};
1582
+ try {
1583
+ mqttTopics.topics = ((_t = realtimeClient.connection) === null || _t === void 0 ? void 0 : _t.subscribedTopics) || realtimeClient._subscribedTopics || realtimeClient.subscribedTopics || [];
1584
+ mqttTopics.updatedAt = new Date().toISOString();
1585
+ }
1586
+ catch (e) {
1587
+ mqttTopics.topics = [];
1588
+ mqttTopics.updatedAt = new Date().toISOString();
1589
+ }
1590
+ // mqttCapabilities: features supported / protocol version
1591
+ const mqttCapabilities = {};
1592
+ try {
1593
+ mqttCapabilities.supportsTyping = Boolean((_v = (_u = realtimeClient.initOptions) === null || _u === void 0 ? void 0 : _u.supportsTyping) !== null && _v !== void 0 ? _v : (_w = realtimeClient.capabilities) === null || _w === void 0 ? void 0 : _w.supportsTyping);
1594
+ mqttCapabilities.supportsReactions = Boolean((_y = (_x = realtimeClient.initOptions) === null || _x === void 0 ? void 0 : _x.supportsReactions) !== null && _y !== void 0 ? _y : (_z = realtimeClient.capabilities) === null || _z === void 0 ? void 0 : _z.supportsReactions);
1595
+ mqttCapabilities.supportsVoice = Boolean((_1 = (_0 = realtimeClient.initOptions) === null || _0 === void 0 ? void 0 : _0.supportsVoice) !== null && _1 !== void 0 ? _1 : (_2 = realtimeClient.capabilities) === null || _2 === void 0 ? void 0 : _2.supportsVoice);
1596
+ mqttCapabilities.protocolVersion = ((_3 = realtimeClient.connection) === null || _3 === void 0 ? void 0 : _3.protocolVersion) || ((_4 = realtimeClient.initOptions) === null || _4 === void 0 ? void 0 : _4.protocolVersion) || null;
1597
+ mqttCapabilities.collectedAt = new Date().toISOString();
1598
+ }
1599
+ catch (e) { }
1600
+ // mqttAuth: if realtimeClient keeps an auth token / jwt for mqtt, store (but be careful: short lived)
1601
+ const mqttAuth = {};
1602
+ try {
1603
+ mqttAuth.jwt = ((_5 = realtimeClient.connection) === null || _5 === void 0 ? void 0 : _5.authToken) || ((_6 = realtimeClient.mqttAuth) === null || _6 === void 0 ? void 0 : _6.jwt) || ((_7 = realtimeClient.initOptions) === null || _7 === void 0 ? void 0 : _7.mqttJwt) || null;
1604
+ mqttAuth.expiresAt = ((_8 = realtimeClient.connection) === null || _8 === void 0 ? void 0 : _8.authExpiresAt) || ((_9 = realtimeClient.mqttAuth) === null || _9 === void 0 ? void 0 : _9.expiresAt) || null;
1605
+ mqttAuth.collectedAt = new Date().toISOString();
1606
+ }
1607
+ catch (e) { }
1608
+ // lastPublishIds: tracking last message ids for reliable publish/acks
1609
+ const lastPublishIds = {};
1610
+ try {
1611
+ lastPublishIds.lastMessageId = realtimeClient._lastMessageId || realtimeClient.lastMessageId || null;
1612
+ lastPublishIds.lastAckedAt = realtimeClient._lastAckedAt || null;
1613
+ lastPublishIds.collectedAt = new Date().toISOString();
1614
+ }
1615
+ catch (e) { }
1616
+ // Assign all into authState and persist
1617
+ authState.data.mqttSession = mqttSession;
1618
+ authState.data.subscriptions = subscriptions;
1619
+ authState.data.seqIds = seqIds;
1620
+ authState.data.irisState = irisState;
1621
+ authState.data.mqttTopics = mqttTopics;
1622
+ authState.data.mqttCapabilities = mqttCapabilities;
1623
+ authState.data.mqttAuth = mqttAuth;
1624
+ authState.data.lastPublishIds = lastPublishIds;
1625
+ // Increment stats
1626
+ authState.incrementStat('mqttMessages');
1627
+ await authState.saveMqttState();
1628
+ console.log('[useMultiFileAuthState] MQTT session saved to', folder);
1629
+ };
1630
+ const loadCreds = async (igClient) => {
1631
+ if (!igClient || !igClient.state) {
1632
+ console.warn('[useMultiFileAuthState] No igClient provided to loadCreds');
1633
+ return false;
1634
+ }
1635
+ if (!authState.hasValidSession()) {
1636
+ console.log('[useMultiFileAuthState] No valid session found');
1637
+ return false;
1638
+ }
1639
+ await applyStateData(igClient.state, authState);
1640
+ console.log('[useMultiFileAuthState] Credentials loaded from', folder);
1641
+ return true;
1642
+ };
1643
+ const getMqttConnectOptions = () => {
1644
+ var _a, _b, _c, _d;
1645
+ if (!authState.hasMqttSession()) {
1646
+ // still return a warm default to help warm-restore
1647
+ const defaultTopics = ['ig_sub_direct', 'ig_sub_direct_v2_message_sync'];
1648
+ return {
1649
+ graphQlSubs: defaultTopics,
1650
+ skywalkerSubs: ['presence_subscribe', 'typing_subscribe'],
1651
+ irisData: { seq_id: ((_a = authState.getSeqIds()) === null || _a === void 0 ? void 0 : _a.seq_id) || 0, snapshot_at_ms: ((_b = authState.getSeqIds()) === null || _b === void 0 ? void 0 : _b.snapshot_at_ms) || Date.now() },
1652
+ mqttAuthToken: ((_c = authState.getMqttAuth()) === null || _c === void 0 ? void 0 : _c.jwt) || null,
1653
+ mqttAuthExpiresAt: ((_d = authState.getMqttAuth()) === null || _d === void 0 ? void 0 : _d.expiresAt) || null
1654
+ };
1655
+ }
1656
+ const subs = authState.getSubscriptions() || {};
1657
+ const seqIds = authState.getSeqIds() || {};
1658
+ const mqttAuth = authState.getMqttAuth() || null;
1659
+ return {
1660
+ graphQlSubs: subs.graphQlSubs || ['ig_sub_direct', 'ig_sub_direct_v2_message_sync'],
1661
+ skywalkerSubs: subs.skywalkerSubs || ['presence_subscribe', 'typing_subscribe'],
1662
+ irisData: seqIds.seq_id ? {
1663
+ seq_id: seqIds.seq_id,
1664
+ snapshot_at_ms: seqIds.snapshot_at_ms
1665
+ } : { seq_id: 0, snapshot_at_ms: Date.now() },
1666
+ mqttAuthToken: (mqttAuth === null || mqttAuth === void 0 ? void 0 : mqttAuth.jwt) || null,
1667
+ mqttAuthExpiresAt: (mqttAuth === null || mqttAuth === void 0 ? void 0 : mqttAuth.expiresAt) || null
1668
+ };
1669
+ };
1670
+ const clearSession = async () => {
1671
+ await authState.clearAll();
1672
+ console.log('[useMultiFileAuthState] Session cleared');
1673
+ };
1674
+ const isSessionValid = async (igClient) => {
1675
+ if (!authState.hasValidSession())
1676
+ return false;
1677
+ if (!igClient)
1678
+ return true;
1679
+ try {
1680
+ // quick check by calling account/currentUser or equivalent
1681
+ if (igClient.account && typeof igClient.account.currentUser === 'function') {
1682
+ await igClient.account.currentUser();
1683
+ return true;
1684
+ }
1685
+ // fallback assume valid if we have creds - up to caller to verify
1686
+ return true;
1687
+ }
1688
+ catch (e) {
1689
+ console.warn('[useMultiFileAuthState] Session validation failed:', e.message);
1690
+ // emit session-expired if credentials appear invalid
1691
+ authState.emit('session-expired', { reason: e.message });
1692
+ return false;
1693
+ }
1694
+ };
1695
+ // --- Auto-refresh / revalidation helpers ---
1696
+ const _autoRefreshCheck = async () => {
1697
+ try {
1698
+ if (!authState.data.creds)
1699
+ return;
1700
+ // If creds indicate expiry timestamp, check it
1701
+ const expiresAt = authState.data.creds.sessionExpiresAt ? new Date(authState.data.creds.sessionExpiresAt).getTime() : null;
1702
+ if (expiresAt && Date.now() > expiresAt) {
1703
+ authState.data.creds.isExpired = true;
1704
+ authState._debouncedSave(['creds']);
1705
+ authState.emit('session-expired', { reason: 'sessionExpiresAt' });
1706
+ }
1707
+ else {
1708
+ // if igClient provided, optionally validate remote
1709
+ if (authState._autoRefreshClient) {
1710
+ try {
1711
+ const valid = await isSessionValid(authState._autoRefreshClient);
1712
+ if (!valid) {
1713
+ authState.emit('session-expired', { reason: 'remote-check' });
1714
+ }
1715
+ else {
1716
+ // update lastValidatedAt
1717
+ if (!authState.data.creds)
1718
+ authState.data.creds = {};
1719
+ authState.data.creds.lastValidatedAt = new Date().toISOString();
1720
+ authState._debouncedSave(['creds']);
1721
+ }
1722
+ }
1723
+ catch (e) { }
1724
+ }
1725
+ }
1726
+ }
1727
+ catch (e) {
1728
+ // ignore
1729
+ }
1730
+ };
1731
+ const enableAutoRefresh = (igClient, intervalMs = 5 * 60 * 1000) => {
1732
+ // igClient optional: if provided, will be used to do remote validation
1733
+ try {
1734
+ disableAutoRefresh();
1735
+ authState._autoRefreshClient = igClient || null;
1736
+ authState._autoRefreshIntervalMs = intervalMs;
1737
+ authState._autoRefreshTimer = setInterval(_autoRefreshCheck, intervalMs);
1738
+ // run immediately once
1739
+ _autoRefreshCheck();
1740
+ authState.emit('auto-refresh-enabled', { intervalMs });
1741
+ }
1742
+ catch (e) {
1743
+ console.warn('[useMultiFileAuthState] enableAutoRefresh error:', e.message);
1744
+ }
1745
+ };
1746
+ const disableAutoRefresh = () => {
1747
+ try {
1748
+ if (authState._autoRefreshTimer) {
1749
+ clearInterval(authState._autoRefreshTimer);
1750
+ authState._autoRefreshTimer = null;
1751
+ authState._autoRefreshClient = null;
1752
+ authState.emit('auto-refresh-disabled');
1753
+ }
1754
+ }
1755
+ catch (e) { }
1756
+ };
1757
+ // --- Login history / audit helpers ---
1758
+ const recordLoginAttempt = async ({ success, ip = null, userAgent = null, method = 'password', reason = null }) => {
1759
+ const entry = authState.recordLoginAttempt({ success, ip, userAgent, method, reason });
1760
+ // return entry for caller
1761
+ return entry;
1762
+ };
1763
+ // --- Account restriction helpers ---
1764
+ const markAccountRestricted = ({ status = 'checkpoint', reason = null }) => {
1765
+ authState.markAccountRestricted({ status, reason });
1766
+ };
1767
+ const clearAccountRestriction = () => {
1768
+ authState.clearAccountRestriction();
1769
+ };
1770
+ // --- Usage stats helpers ---
1771
+ const incrementStat = (statName, by = 1) => {
1772
+ authState.incrementStat(statName, by);
1773
+ };
1774
+ // --- Backup / restore helpers exposed ---
1775
+ const restoreLatestBackup = async (key) => {
1776
+ return await authState.restoreLatestBackup(key);
1777
+ };
1778
+ // --- Device fingerprinting ---
1779
+ const lockDeviceFingerprint = async () => {
1780
+ return await authState.lockDeviceFingerprint();
1781
+ };
1782
+ const verifyDeviceFingerprint = (deviceObj) => {
1783
+ return authState.verifyDeviceFingerprint(deviceObj);
1784
+ };
1785
+ // --- Accounts manager ---
1786
+ const registerAccount = async (name, folderPath) => {
1787
+ if (!authState.data.accountsIndex)
1788
+ authState.data.accountsIndex = {};
1789
+ authState.data.accountsIndex[name] = folderPath;
1790
+ await authState._writeFile('accountsIndex', authState.data.accountsIndex);
1791
+ authState.emit('account-registered', { name, folderPath });
1792
+ return authState.data.accountsIndex;
1793
+ };
1794
+ const listAccounts = () => {
1795
+ return authState.getAccountsIndex();
1796
+ };
1797
+ // --- Health check ---
1798
+ const getHealth = () => {
1799
+ return authState.getHealth();
1800
+ };
1801
+ // --- MQTT helpers exposing internal features ---
1802
+ const attachRealtimeClient = (realtimeClient, opts = {}) => {
1803
+ return authState.attachRealtimeClient(realtimeClient, opts);
1804
+ };
1805
+ const enqueueOutbox = (item) => authState.enqueueOutbox(item);
1806
+ const flushOutbox = (client, max) => authState.flushOutbox(client, max);
1807
+ const checkSubscriptions = (client) => authState.checkSubscriptions(client);
1808
+ const computeRisk = () => authState._computeRiskScore();
1809
+ const warmRestore = (client) => authState.warmRestoreClient(client);
1810
+ const getMqttHealth = () => authState.getMqttHealth();
1811
+ const getMqttTraffic = () => authState.getMqttTraffic();
1812
+ const getMqttRisk = () => authState.getMqttRisk();
1813
+ const isDuplicateMessage = (id) => authState.isDuplicateMessage(id);
1814
+ const markPing = () => authState.markPing();
1815
+ const markPong = () => authState.markPong();
1816
+ // --- Misc helpers: loginHistory & usageStats getters ---
1817
+ const getLoginHistory = () => authState.getLoginHistory();
1818
+ const getUsageStats = () => authState.getUsageStats();
1819
+ return {
1820
+ state: authState,
1821
+ saveCreds,
1822
+ loadCreds,
1823
+ saveMqttSession,
1824
+ getMqttConnectOptions,
1825
+ clearSession,
1826
+ isSessionValid,
1827
+ hasSession: () => authState.hasValidSession(),
1828
+ hasMqttSession: () => authState.hasMqttSession(),
1829
+ folder,
1830
+ // pass-through for convenience
1831
+ getData: () => authState.data,
1832
+ // convenience setters/getters for the new data
1833
+ setIrisState: (s) => authState.setIrisState(s),
1834
+ setMqttTopics: (t) => authState.setMqttTopics(t),
1835
+ setMqttCapabilities: (c) => authState.setMqttCapabilities(c),
1836
+ setMqttAuth: (a) => authState.setMqttAuth(a),
1837
+ setLastPublishIds: (p) => authState.setLastPublishIds(p),
1838
+ getIrisState: () => authState.getIrisState(),
1839
+ getMqttTopics: () => authState.getMqttTopics(),
1840
+ getMqttCapabilities: () => authState.getMqttCapabilities(),
1841
+ getMqttAuth: () => authState.getMqttAuth(),
1842
+ getLastPublishIds: () => authState.getLastPublishIds(),
1843
+ // new utilities
1844
+ enableAutoRefresh,
1845
+ disableAutoRefresh,
1846
+ recordLoginAttempt,
1847
+ getLoginHistory,
1848
+ markAccountRestricted,
1849
+ clearAccountRestriction,
1850
+ incrementStat,
1851
+ getUsageStats,
1852
+ restoreLatestBackup,
1853
+ lockDeviceFingerprint,
1854
+ verifyDeviceFingerprint,
1855
+ registerAccount,
1856
+ listAccounts,
1857
+ getHealth,
1858
+ // mqtt helpers
1859
+ attachRealtimeClient,
1860
+ enqueueOutbox,
1861
+ flushOutbox,
1862
+ checkSubscriptions,
1863
+ computeRisk,
1864
+ warmRestore,
1865
+ getMqttHealth,
1866
+ getMqttTraffic,
1867
+ getMqttRisk,
1868
+ isDuplicateMessage,
1869
+ markPing,
1870
+ markPong
1871
+ };
1872
+ }
1873
+ module.exports = {
1874
+ useMultiFileAuthState,
1875
+ MultiFileAuthState,
1876
+ extractStateData,
1877
+ applyStateData
1878
+ };