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,1428 @@
1
+ // state.js
2
+ 'use strict';
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const util = require('util');
6
+ const { CookieJar } = require('tough-cookie');
7
+ const Chance = require('chance');
8
+ const Constants = require('../constants');
9
+ const EventEmitter = require('events');
10
+ const SESSION_FILE = path.resolve(process.cwd(), 'session.json');
11
+ const SESSION_BACKUP = path.resolve(process.cwd(), 'session_backup.json');
12
+ class State {
13
+ constructor() {
14
+ // public constants reference (kept as property for backwards compat)
15
+ this.constants = Constants;
16
+ // basic defaults
17
+ this.language = 'en_US';
18
+ this.locale = 'en_US';
19
+ this.timezoneOffset = new Date().getTimezoneOffset() * -60;
20
+ this.radioType = 'wifi-none';
21
+ this.capabilitiesHeader = '3brTvx0=';
22
+ this.connectionTypeHeader = 'WIFI';
23
+ this.isLayoutRTL = false;
24
+ this.adsOptOut = false;
25
+ this.thumbnailCacheBustingValue = 1000;
26
+ this.proxyUrl = null;
27
+ this.checkpoint = null;
28
+ this.challenge = null;
29
+ this.clientSessionIdLifetime = 1200000;
30
+ this.pigeonSessionIdLifetime = 1200000;
31
+ this.parsedAuthorization = undefined;
32
+ this.mid = '';
33
+ this.country = 'US';
34
+ this.countryCode = 1;
35
+ this.igURur = '';
36
+ this.igWWWClaim = '0';
37
+ this.requestId = '';
38
+ this.traySessionId = '';
39
+ // ===== PLATFORM SUPPORT (iOS + Android) =====
40
+ this.platform = 'android'; // 'android' or 'ios'
41
+ this.iosVersion = '18.3';
42
+ this.iosAppVersion = '366.0.0.38.99';
43
+ this.iosAppVersionCode = '632412089';
44
+ this.iosDeviceModel = 'iPhone16,2'; // iPhone 15 Pro Max
45
+ this.iosDeviceName = 'iPhone';
46
+ this.iosBundleId = 'com.burbn.instagram';
47
+ // cookie jar (tough-cookie)
48
+ this.cookieJar = new CookieJar();
49
+ // device defaults
50
+ this.generateDevice('instagram-private-api');
51
+ // internal event emitter (non-invasive - backward-compatible)
52
+ this._emitter = new EventEmitter();
53
+ // internal watcher handle for session file (if used)
54
+ this._sessionFileWatcher = null;
55
+ // Default values for added utilities
56
+ this._saveRetries = 3;
57
+ this._saveRetryDelayMs = 300;
58
+ this._maxBackupCopies = 5; // rotate backups up to this many
59
+ }
60
+ // ===== getters mapping to constants (read-only) =====
61
+ get appVersion() {
62
+ return this.constants.APP_VERSION;
63
+ }
64
+ get appVersionCode() {
65
+ return this.constants.APP_VERSION_CODE;
66
+ }
67
+ get signatureKey() {
68
+ return this.constants.SIGNATURE_KEY;
69
+ }
70
+ get signatureVersion() {
71
+ return this.constants.SIGNATURE_VERSION;
72
+ }
73
+ get fbAnalyticsApplicationId() {
74
+ return this.constants.FACEBOOK_ANALYTICS_APPLICATION_ID;
75
+ }
76
+ get bloksVersionId() {
77
+ return this.constants.BLOKS_VERSION_ID;
78
+ }
79
+ get clientSessionId() {
80
+ return this.generateTemporaryGuid('clientSessionId', this.clientSessionIdLifetime);
81
+ }
82
+ get pigeonSessionId() {
83
+ return this.generateTemporaryGuid('pigeonSessionId', this.pigeonSessionIdLifetime);
84
+ }
85
+ get appUserAgent() {
86
+ if (this.platform === 'ios') {
87
+ return this.iosUserAgent;
88
+ }
89
+ return `Instagram ${this.appVersion} Android (${this.deviceString}; ${this.language}; ${this.appVersionCode})`;
90
+ }
91
+ get iosUserAgent() {
92
+ return `Instagram ${this.iosAppVersion} (${this.iosDeviceModel}; iOS ${this.iosVersion}; ${this.language}; ${this.language}; scale=3.00; ${this.iosResolution}; ${this.iosAppVersionCode}) AppleWebKit/420+`;
93
+ }
94
+ get iosResolution() {
95
+ const resolutions = {
96
+ 'iPhone17,1': '1320x2868', // iPhone 16 Pro Max
97
+ 'iPhone17,2': '1206x2622', // iPhone 16 Pro
98
+ 'iPhone17,3': '1290x2796', // iPhone 16 Plus
99
+ 'iPhone17,4': '1179x2556', // iPhone 16
100
+ 'iPhone16,1': '1179x2556', // iPhone 15 Pro
101
+ 'iPhone16,2': '1290x2796', // iPhone 15 Pro Max
102
+ 'iPhone15,4': '1179x2556', // iPhone 15
103
+ 'iPhone15,5': '1290x2796', // iPhone 15 Plus
104
+ 'iPhone15,2': '1179x2556', // iPhone 14 Pro
105
+ 'iPhone15,3': '1290x2796', // iPhone 14 Pro Max
106
+ 'iPhone14,7': '1170x2532', // iPhone 14
107
+ 'iPhone14,8': '1284x2778', // iPhone 14 Plus
108
+ 'iPhone14,2': '1170x2532', // iPhone 13 Pro
109
+ 'iPhone14,3': '1284x2778', // iPhone 13 Pro Max
110
+ 'iPhone14,5': '1170x2532', // iPhone 13
111
+ 'iPhone13,2': '1170x2532', // iPhone 12
112
+ 'iPhone13,3': '1170x2532', // iPhone 12 Pro
113
+ 'iPhone13,4': '1284x2778', // iPhone 12 Pro Max
114
+ 'iPad14,3': '2048x2732', // iPad Pro 12.9" (6th gen)
115
+ 'iPad14,4': '2048x2732', // iPad Pro 12.9" (6th gen)
116
+ 'iPad14,5': '1668x2388', // iPad Pro 11" (4th gen)
117
+ 'iPad14,6': '1668x2388', // iPad Pro 11" (4th gen)
118
+ 'iPad13,18': '2360x1640', // iPad Air (5th gen)
119
+ 'iPad13,19': '2360x1640', // iPad Air (5th gen)
120
+ };
121
+ return resolutions[this.iosDeviceModel] || '1290x2796';
122
+ }
123
+ get packageName() {
124
+ return this.platform === 'ios' ? this.iosBundleId : 'com.instagram.android';
125
+ }
126
+ // ===== cookies/auth helpers =====
127
+ extractCookie(key) {
128
+ // tough-cookie CookieJar returns array via getCookiesSync in some versions; use synchronous API if present
129
+ try {
130
+ const cookies = this.cookieJar.getCookiesSync
131
+ ? this.cookieJar.getCookiesSync(this.constants.HOST)
132
+ : this.cookieJar.getCookies(this.constants.HOST);
133
+ // cookies might be an array or a Promise; if array, find
134
+ if (Array.isArray(cookies)) {
135
+ const found = cookies.find(c => c.key === key);
136
+ return found || null;
137
+ }
138
+ return null;
139
+ }
140
+ catch (e) {
141
+ // fallback: try jar serialized introspection (rare)
142
+ return null;
143
+ }
144
+ }
145
+ extractCookieValue(key) {
146
+ const cookie = this.extractCookie(key);
147
+ return cookie ? cookie.value : null;
148
+ }
149
+ get cookieCsrfToken() {
150
+ try {
151
+ return this.extractCookieValue('csrftoken');
152
+ }
153
+ catch {
154
+ return 'missing';
155
+ }
156
+ }
157
+ get cookieUserId() {
158
+ try {
159
+ return this.extractCookieValue('ds_user_id');
160
+ }
161
+ catch {
162
+ // fallback to parsed authorization if available
163
+ this.updateAuthorization();
164
+ if (this.parsedAuthorization && this.parsedAuthorization.ds_user_id) {
165
+ return this.parsedAuthorization.ds_user_id;
166
+ }
167
+ // fallback: check if userId was set directly on state
168
+ if (this._userId)
169
+ return this._userId;
170
+ return null;
171
+ }
172
+ }
173
+ set cookieUserId(val) {
174
+ this._userId = val;
175
+ }
176
+ get cookieUsername() {
177
+ try {
178
+ return this.extractCookieValue('ds_user');
179
+ }
180
+ catch {
181
+ return null;
182
+ }
183
+ }
184
+ hasValidAuthorization() {
185
+ return this.parsedAuthorization && this.parsedAuthorization.authorizationTag === this.authorization;
186
+ }
187
+ updateAuthorization() {
188
+ if (!this.authorization) {
189
+ this.parsedAuthorization = undefined;
190
+ return;
191
+ }
192
+ if (this.hasValidAuthorization())
193
+ return;
194
+ if (typeof this.authorization === 'string' && this.authorization.startsWith('Bearer IGT:2:')) {
195
+ try {
196
+ const json = Buffer.from(this.authorization.substring('Bearer IGT:2:'.length), 'base64').toString();
197
+ const parsed = JSON.parse(json);
198
+ // keep an extra tag to detect equality later
199
+ parsed.authorizationTag = this.authorization;
200
+ this.parsedAuthorization = parsed;
201
+ }
202
+ catch (e) {
203
+ this.parsedAuthorization = undefined;
204
+ }
205
+ }
206
+ else {
207
+ this.parsedAuthorization = undefined;
208
+ }
209
+ }
210
+ refreshAuthorization(newAuthToken) {
211
+ if (!newAuthToken || typeof newAuthToken !== 'string')
212
+ return false;
213
+ this.authorization = newAuthToken;
214
+ this.updateAuthorization();
215
+ return true;
216
+ }
217
+ // ===== serialization helpers for cookieJar =====
218
+ async serializeCookieJar() {
219
+ // CookieJar.serialize(cb) exists in tough-cookie; wrap it
220
+ const serializeFn = util.promisify((cb) => {
221
+ try {
222
+ this.cookieJar.serialize(cb);
223
+ }
224
+ catch (err) {
225
+ cb(err);
226
+ }
227
+ });
228
+ const data = await serializeFn();
229
+ // return an object safe to JSON.stringify
230
+ return data;
231
+ }
232
+ async deserializeCookieJar(serialized) {
233
+ // Accept serialized either as string (JSON) or object
234
+ let obj = serialized;
235
+ if (typeof serialized === 'string') {
236
+ try {
237
+ obj = JSON.parse(serialized);
238
+ }
239
+ catch (e) {
240
+ obj = serialized;
241
+ }
242
+ }
243
+ const deserializeFn = util.promisify((input, cb) => {
244
+ try {
245
+ CookieJar.deserialize(input, cb);
246
+ }
247
+ catch (err) {
248
+ cb(err);
249
+ }
250
+ });
251
+ // CookieJar.deserialize returns a CookieJar instance
252
+ const jar = await deserializeFn(obj);
253
+ if (jar && typeof jar === 'object') {
254
+ this.cookieJar = jar;
255
+ }
256
+ }
257
+ // ===== main serialize / deserialize for whole state =====
258
+ /**
259
+ * Return a plain-object ready to be JSON.stringify-ed and saved to disk.
260
+ */
261
+ async serialize() {
262
+ const cookieData = await this.serializeCookieJar();
263
+ const obj = {
264
+ constants: this.constants,
265
+ cookies: cookieData,
266
+ // include selective state fields (device + auth + extra fields commonly expected)
267
+ deviceString: this.deviceString,
268
+ deviceId: this.deviceId,
269
+ uuid: this.uuid,
270
+ phoneId: this.phoneId,
271
+ adid: this.adid,
272
+ build: this.build,
273
+ authorization: this.authorization,
274
+ igWWWClaim: this.igWWWClaim,
275
+ igURur: this.igURur,
276
+ mid: this.mid,
277
+ country: this.country,
278
+ countryCode: this.countryCode,
279
+ locale: this.locale,
280
+ passwordEncryptionKeyId: this.passwordEncryptionKeyId,
281
+ passwordEncryptionPubKey: this.passwordEncryptionPubKey,
282
+ language: this.language,
283
+ timezoneOffset: this.timezoneOffset,
284
+ connectionTypeHeader: this.connectionTypeHeader,
285
+ capabilitiesHeader: this.capabilitiesHeader,
286
+ requestId: this.requestId,
287
+ traySessionId: this.traySessionId,
288
+ userId: this._userId || null
289
+ };
290
+ return obj;
291
+ }
292
+ /**
293
+ * Merge data from a saved session into this State instance.
294
+ * Safe: does NOT overwrite prototype getters (like appVersion).
295
+ */
296
+ async deserialize(state) {
297
+ const obj = typeof state === 'string' ? JSON.parse(state) : state;
298
+ if (!obj || typeof obj !== 'object') {
299
+ throw new TypeError("State isn't an object or serialized JSON");
300
+ }
301
+ // If constants present and looks like an object, restore it
302
+ if (obj.constants) {
303
+ this.constants = obj.constants;
304
+ // don't delete - but won't assign later
305
+ }
306
+ // Restore cookieJar if present
307
+ if (obj.cookies) {
308
+ try {
309
+ await this.deserializeCookieJar(obj.cookies);
310
+ }
311
+ catch (e) {
312
+ // best-effort: ignore cookie restore failures
313
+ }
314
+ }
315
+ // Assign every other top-level property carefully, skipping prototype getters
316
+ for (const [key, value] of Object.entries(obj)) {
317
+ if (key === 'cookies' || key === 'constants')
318
+ continue;
319
+ // skip if prototype defines a getter for this key
320
+ const desc = Object.getOwnPropertyDescriptor(State.prototype, key);
321
+ if (desc && (typeof desc.get === 'function' || typeof desc.set === 'function')) {
322
+ // skip assigning to avoid "Cannot set property X of #<State> which has only a getter"
323
+ continue;
324
+ }
325
+ // otherwise set on this
326
+ try {
327
+ this[key] = value;
328
+ }
329
+ catch (e) {
330
+ // ignore property set failures (non-critical)
331
+ }
332
+ }
333
+ // If serialized state carried a raw userId, restore it into the internal field
334
+ if (obj.userId && !this._userId) {
335
+ this._userId = obj.userId;
336
+ }
337
+ // refresh parsed authorization (if any)
338
+ this.updateAuthorization();
339
+ }
340
+ // ===== file helpers: save/load to disk (session + backup) =====
341
+ async saveSessionToFile(filePath = SESSION_FILE, backupPath = SESSION_BACKUP) {
342
+ try {
343
+ const data = await this.serialize();
344
+ // Save cookies field as object (not string) — caller may JSON.stringify whole obj
345
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2), { mode: 0o600 });
346
+ // Also write a backup
347
+ try {
348
+ fs.writeFileSync(backupPath, JSON.stringify(data, null, 2), { mode: 0o600 });
349
+ }
350
+ catch (_) { }
351
+ return true;
352
+ }
353
+ catch (e) {
354
+ return false;
355
+ }
356
+ }
357
+ async loadSessionFromFile(filePath = SESSION_FILE, backupPath = SESSION_BACKUP) {
358
+ try {
359
+ if (!fs.existsSync(filePath))
360
+ return false;
361
+ const raw = fs.readFileSync(filePath, 'utf8');
362
+ const obj = JSON.parse(raw);
363
+ await this.deserialize(obj);
364
+ return true;
365
+ }
366
+ catch (e) {
367
+ // try backup
368
+ try {
369
+ if (fs.existsSync(backupPath)) {
370
+ const rawb = fs.readFileSync(backupPath, 'utf8');
371
+ const objb = JSON.parse(rawb);
372
+ await this.deserialize(objb);
373
+ return true;
374
+ }
375
+ }
376
+ catch (_) { }
377
+ return false;
378
+ }
379
+ }
380
+ // old convenience names so library code that calls state.saveSession()/loadSession() still works
381
+ async saveSession() {
382
+ return await this.saveSessionToFile();
383
+ }
384
+ async loadSession() {
385
+ return await this.loadSessionFromFile();
386
+ }
387
+ // ===== device / cookie utilities =====
388
+ generateDevice(seed) {
389
+ const chance = new Chance(seed);
390
+ // Default device: Samsung Galaxy S25 Ultra (2025 flagship)
391
+ // Users can override this with setCustomDevice() or usePresetDevice()
392
+ this.deviceString = `35/15; 505dpi; 1440x3120; samsung; SM-S928B; e3q; qcom`;
393
+ this.deviceId = `android-${chance.string({ pool: 'abcdef0123456789', length: 16 })}`;
394
+ this.uuid = chance.guid();
395
+ this.phoneId = chance.guid();
396
+ this.adid = chance.guid();
397
+ this.build = 'UP1A.231005.007';
398
+ this.requestId = chance.guid();
399
+ this.traySessionId = chance.guid();
400
+ }
401
+ regenerateDevice(seed = 'instagram-private-api') {
402
+ this.generateDevice(seed);
403
+ }
404
+ // ===== CUSTOM DEVICE EMULATION =====
405
+ // Allows users to set their own phone model for Instagram emulation
406
+ // Example devices included: Samsung S25 Ultra, Huawei P60 Pro, Google Pixel 8, etc.
407
+ /**
408
+ * Set a custom device to emulate when connecting to Instagram.
409
+ * This allows you to choose which phone model Instagram sees.
410
+ *
411
+ * @param {Object} deviceConfig - The device configuration
412
+ * @param {string} deviceConfig.manufacturer - Phone manufacturer (e.g., 'samsung', 'huawei', 'google')
413
+ * @param {string} deviceConfig.model - Phone model code (e.g., 'SM-S928B' for Samsung S25 Ultra)
414
+ * @param {string} deviceConfig.device - Device codename (e.g., 'e3q' for S25 Ultra)
415
+ * @param {string} deviceConfig.androidVersion - Android version (e.g., '15')
416
+ * @param {number} deviceConfig.androidApiLevel - Android API level (e.g., 35 for Android 15)
417
+ * @param {string} deviceConfig.resolution - Screen resolution (e.g., '1440x3120')
418
+ * @param {string} deviceConfig.dpi - Screen density (e.g., '505dpi')
419
+ * @param {string} deviceConfig.chipset - Chipset name (e.g., 'qcom')
420
+ * @param {string} deviceConfig.build - Build number (optional)
421
+ *
422
+ * @example
423
+ * // Samsung Galaxy S25 Ultra
424
+ * state.setCustomDevice({
425
+ * manufacturer: 'samsung',
426
+ * model: 'SM-S928B',
427
+ * device: 'e3q',
428
+ * androidVersion: '15',
429
+ * androidApiLevel: 35,
430
+ * resolution: '1440x3120',
431
+ * dpi: '505dpi',
432
+ * chipset: 'qcom'
433
+ * });
434
+ */
435
+ setCustomDevice(deviceConfig) {
436
+ const { manufacturer = 'samsung', model = 'SM-G930F', device = 'herolte', androidVersion = '8.0.0', androidApiLevel = 26, resolution = '1080x1920', dpi = '480dpi', chipset = 'samsungexynos8890', build = null } = deviceConfig || {};
437
+ // Build the device string in Instagram format
438
+ this.deviceString = `${androidApiLevel}/${androidVersion}; ${dpi}; ${resolution}; ${manufacturer}; ${model}; ${device}; ${chipset}`;
439
+ // Optionally update build if provided
440
+ if (build) {
441
+ this.build = build;
442
+ }
443
+ // Emit event for tracking
444
+ if (this._emitter) {
445
+ this._emitter.emit('device_changed', { deviceString: this.deviceString, model, manufacturer });
446
+ }
447
+ return this.deviceString;
448
+ }
449
+ /**
450
+ * Get a list of popular preset devices that can be used with setCustomDevice()
451
+ * @returns {Object} Object containing preset device configurations
452
+ */
453
+ getPresetDevices() {
454
+ return {
455
+ // Samsung devices
456
+ 'Samsung Galaxy S25 Ultra': {
457
+ manufacturer: 'samsung',
458
+ model: 'SM-S928B',
459
+ device: 'e3q',
460
+ androidVersion: '15',
461
+ androidApiLevel: 35,
462
+ resolution: '1440x3120',
463
+ dpi: '505dpi',
464
+ chipset: 'qcom',
465
+ build: 'UP1A.231005.007'
466
+ },
467
+ 'Samsung Galaxy S24 Ultra': {
468
+ manufacturer: 'samsung',
469
+ model: 'SM-S928B',
470
+ device: 'e2q',
471
+ androidVersion: '14',
472
+ androidApiLevel: 34,
473
+ resolution: '1440x3088',
474
+ dpi: '480dpi',
475
+ chipset: 'qcom',
476
+ build: 'UP1A.231005.007'
477
+ },
478
+ 'Samsung Galaxy S23 Ultra': {
479
+ manufacturer: 'samsung',
480
+ model: 'SM-S918B',
481
+ device: 'dm3q',
482
+ androidVersion: '14',
483
+ androidApiLevel: 34,
484
+ resolution: '1440x3088',
485
+ dpi: '480dpi',
486
+ chipset: 'qcom',
487
+ build: 'UP1A.231005.007'
488
+ },
489
+ 'Samsung Galaxy Z Fold 5': {
490
+ manufacturer: 'samsung',
491
+ model: 'SM-F946B',
492
+ device: 'q5q',
493
+ androidVersion: '14',
494
+ androidApiLevel: 34,
495
+ resolution: '1812x2176',
496
+ dpi: '420dpi',
497
+ chipset: 'qcom',
498
+ build: 'UP1A.231005.007'
499
+ },
500
+ // Huawei devices
501
+ 'Huawei P60 Pro': {
502
+ manufacturer: 'HUAWEI',
503
+ model: 'MNA-AL00',
504
+ device: 'mona',
505
+ androidVersion: '12',
506
+ androidApiLevel: 31,
507
+ resolution: '1260x2720',
508
+ dpi: '480dpi',
509
+ chipset: 'kirin',
510
+ build: 'HUAWEIMNA-AL00'
511
+ },
512
+ 'Huawei Mate 60 Pro': {
513
+ manufacturer: 'HUAWEI',
514
+ model: 'ALN-AL10',
515
+ device: 'aln',
516
+ androidVersion: '12',
517
+ androidApiLevel: 31,
518
+ resolution: '1260x2720',
519
+ dpi: '480dpi',
520
+ chipset: 'kirin',
521
+ build: 'HUAWEIALN-AL10'
522
+ },
523
+ // Google Pixel devices
524
+ 'Google Pixel 8 Pro': {
525
+ manufacturer: 'Google',
526
+ model: 'Pixel 8 Pro',
527
+ device: 'husky',
528
+ androidVersion: '14',
529
+ androidApiLevel: 34,
530
+ resolution: '1344x2992',
531
+ dpi: '480dpi',
532
+ chipset: 'google',
533
+ build: 'AP2A.240805.005'
534
+ },
535
+ 'Google Pixel 9 Pro': {
536
+ manufacturer: 'Google',
537
+ model: 'Pixel 9 Pro',
538
+ device: 'caiman',
539
+ androidVersion: '15',
540
+ androidApiLevel: 35,
541
+ resolution: '1280x2856',
542
+ dpi: '480dpi',
543
+ chipset: 'google',
544
+ build: 'AP3A.241005.015'
545
+ },
546
+ // OnePlus devices
547
+ 'OnePlus 12': {
548
+ manufacturer: 'OnePlus',
549
+ model: 'CPH2573',
550
+ device: 'aston',
551
+ androidVersion: '14',
552
+ androidApiLevel: 34,
553
+ resolution: '1440x3168',
554
+ dpi: '525dpi',
555
+ chipset: 'qcom',
556
+ build: 'UP1A.231005.007'
557
+ },
558
+ // Xiaomi devices
559
+ 'Xiaomi 14 Ultra': {
560
+ manufacturer: 'Xiaomi',
561
+ model: '24030PN60G',
562
+ device: 'aurora',
563
+ androidVersion: '14',
564
+ androidApiLevel: 34,
565
+ resolution: '1440x3200',
566
+ dpi: '522dpi',
567
+ chipset: 'qcom',
568
+ build: 'UP1A.231005.007'
569
+ },
570
+ 'Xiaomi Redmi Note 13 Pro': {
571
+ manufacturer: 'Xiaomi',
572
+ model: '2312DRA50G',
573
+ device: 'emerald',
574
+ androidVersion: '14',
575
+ androidApiLevel: 34,
576
+ resolution: '1220x2712',
577
+ dpi: '446dpi',
578
+ chipset: 'qcom',
579
+ build: 'UP1A.231005.007'
580
+ },
581
+ // OPPO devices
582
+ 'OPPO Find X7 Ultra': {
583
+ manufacturer: 'OPPO',
584
+ model: 'PHZ110',
585
+ device: 'OP5D4BL1',
586
+ androidVersion: '14',
587
+ androidApiLevel: 34,
588
+ resolution: '1440x3168',
589
+ dpi: '525dpi',
590
+ chipset: 'qcom',
591
+ build: 'UP1A.231005.007',
592
+ platform: 'android'
593
+ },
594
+ // ===== iOS DEVICES =====
595
+ // iPhone 16 Series (2024)
596
+ 'iPhone 16 Pro Max': {
597
+ platform: 'ios',
598
+ iosDeviceModel: 'iPhone17,1',
599
+ iosDeviceName: 'iPhone 16 Pro Max',
600
+ iosVersion: '18.1',
601
+ resolution: '1320x2868',
602
+ chipset: 'A18 Pro'
603
+ },
604
+ 'iPhone 16 Pro': {
605
+ platform: 'ios',
606
+ iosDeviceModel: 'iPhone17,2',
607
+ iosDeviceName: 'iPhone 16 Pro',
608
+ iosVersion: '18.1',
609
+ resolution: '1206x2622',
610
+ chipset: 'A18 Pro'
611
+ },
612
+ 'iPhone 16 Plus': {
613
+ platform: 'ios',
614
+ iosDeviceModel: 'iPhone17,3',
615
+ iosDeviceName: 'iPhone 16 Plus',
616
+ iosVersion: '18.1',
617
+ resolution: '1290x2796',
618
+ chipset: 'A18'
619
+ },
620
+ 'iPhone 16': {
621
+ platform: 'ios',
622
+ iosDeviceModel: 'iPhone17,4',
623
+ iosDeviceName: 'iPhone 16',
624
+ iosVersion: '18.1',
625
+ resolution: '1179x2556',
626
+ chipset: 'A18'
627
+ },
628
+ // iPhone 15 Series (2023)
629
+ 'iPhone 15 Pro Max': {
630
+ platform: 'ios',
631
+ iosDeviceModel: 'iPhone16,2',
632
+ iosDeviceName: 'iPhone 15 Pro Max',
633
+ iosVersion: '18.1',
634
+ resolution: '1290x2796',
635
+ chipset: 'A17 Pro'
636
+ },
637
+ 'iPhone 15 Pro': {
638
+ platform: 'ios',
639
+ iosDeviceModel: 'iPhone16,1',
640
+ iosDeviceName: 'iPhone 15 Pro',
641
+ iosVersion: '18.1',
642
+ resolution: '1179x2556',
643
+ chipset: 'A17 Pro'
644
+ },
645
+ 'iPhone 15 Plus': {
646
+ platform: 'ios',
647
+ iosDeviceModel: 'iPhone15,5',
648
+ iosDeviceName: 'iPhone 15 Plus',
649
+ iosVersion: '18.1',
650
+ resolution: '1290x2796',
651
+ chipset: 'A16'
652
+ },
653
+ 'iPhone 15': {
654
+ platform: 'ios',
655
+ iosDeviceModel: 'iPhone15,4',
656
+ iosDeviceName: 'iPhone 15',
657
+ iosVersion: '18.1',
658
+ resolution: '1179x2556',
659
+ chipset: 'A16'
660
+ },
661
+ // iPhone 14 Series (2022)
662
+ 'iPhone 14 Pro Max': {
663
+ platform: 'ios',
664
+ iosDeviceModel: 'iPhone15,3',
665
+ iosDeviceName: 'iPhone 14 Pro Max',
666
+ iosVersion: '18.1',
667
+ resolution: '1290x2796',
668
+ chipset: 'A16'
669
+ },
670
+ 'iPhone 14 Pro': {
671
+ platform: 'ios',
672
+ iosDeviceModel: 'iPhone15,2',
673
+ iosDeviceName: 'iPhone 14 Pro',
674
+ iosVersion: '18.1',
675
+ resolution: '1179x2556',
676
+ chipset: 'A16'
677
+ },
678
+ 'iPhone 14 Plus': {
679
+ platform: 'ios',
680
+ iosDeviceModel: 'iPhone14,8',
681
+ iosDeviceName: 'iPhone 14 Plus',
682
+ iosVersion: '18.1',
683
+ resolution: '1284x2778',
684
+ chipset: 'A15'
685
+ },
686
+ 'iPhone 14': {
687
+ platform: 'ios',
688
+ iosDeviceModel: 'iPhone14,7',
689
+ iosDeviceName: 'iPhone 14',
690
+ iosVersion: '18.1',
691
+ resolution: '1170x2532',
692
+ chipset: 'A15'
693
+ },
694
+ // iPhone 13 Series (2021)
695
+ 'iPhone 13 Pro Max': {
696
+ platform: 'ios',
697
+ iosDeviceModel: 'iPhone14,3',
698
+ iosDeviceName: 'iPhone 13 Pro Max',
699
+ iosVersion: '17.6',
700
+ resolution: '1284x2778',
701
+ chipset: 'A15'
702
+ },
703
+ 'iPhone 13 Pro': {
704
+ platform: 'ios',
705
+ iosDeviceModel: 'iPhone14,2',
706
+ iosDeviceName: 'iPhone 13 Pro',
707
+ iosVersion: '17.6',
708
+ resolution: '1170x2532',
709
+ chipset: 'A15'
710
+ },
711
+ 'iPhone 13': {
712
+ platform: 'ios',
713
+ iosDeviceModel: 'iPhone14,5',
714
+ iosDeviceName: 'iPhone 13',
715
+ iosVersion: '17.6',
716
+ resolution: '1170x2532',
717
+ chipset: 'A15'
718
+ },
719
+ // iPhone 12 Series (2020)
720
+ 'iPhone 12 Pro Max': {
721
+ platform: 'ios',
722
+ iosDeviceModel: 'iPhone13,4',
723
+ iosDeviceName: 'iPhone 12 Pro Max',
724
+ iosVersion: '17.6',
725
+ resolution: '1284x2778',
726
+ chipset: 'A14'
727
+ },
728
+ 'iPhone 12 Pro': {
729
+ platform: 'ios',
730
+ iosDeviceModel: 'iPhone13,3',
731
+ iosDeviceName: 'iPhone 12 Pro',
732
+ iosVersion: '17.6',
733
+ resolution: '1170x2532',
734
+ chipset: 'A14'
735
+ },
736
+ 'iPhone 12': {
737
+ platform: 'ios',
738
+ iosDeviceModel: 'iPhone13,2',
739
+ iosDeviceName: 'iPhone 12',
740
+ iosVersion: '17.6',
741
+ resolution: '1170x2532',
742
+ chipset: 'A14'
743
+ },
744
+ // iPad Pro Series
745
+ 'iPad Pro 12.9 (6th gen)': {
746
+ platform: 'ios',
747
+ iosDeviceModel: 'iPad14,3',
748
+ iosDeviceName: 'iPad Pro 12.9-inch (6th generation)',
749
+ iosVersion: '18.1',
750
+ resolution: '2048x2732',
751
+ chipset: 'M2'
752
+ },
753
+ 'iPad Pro 11 (4th gen)': {
754
+ platform: 'ios',
755
+ iosDeviceModel: 'iPad14,5',
756
+ iosDeviceName: 'iPad Pro 11-inch (4th generation)',
757
+ iosVersion: '18.1',
758
+ resolution: '1668x2388',
759
+ chipset: 'M2'
760
+ },
761
+ 'iPad Air (5th gen)': {
762
+ platform: 'ios',
763
+ iosDeviceModel: 'iPad13,18',
764
+ iosDeviceName: 'iPad Air (5th generation)',
765
+ iosVersion: '18.1',
766
+ resolution: '2360x1640',
767
+ chipset: 'M1'
768
+ }
769
+ };
770
+ }
771
+ /**
772
+ * Get only iOS device presets
773
+ * @returns {Object} Object containing iOS device configurations
774
+ */
775
+ getIOSDevices() {
776
+ const all = this.getPresetDevices();
777
+ const iosDevices = {};
778
+ for (const [name, config] of Object.entries(all)) {
779
+ if (config.platform === 'ios') {
780
+ iosDevices[name] = config;
781
+ }
782
+ }
783
+ return iosDevices;
784
+ }
785
+ /**
786
+ * Get only Android device presets
787
+ * @returns {Object} Object containing Android device configurations
788
+ */
789
+ getAndroidDevices() {
790
+ const all = this.getPresetDevices();
791
+ const androidDevices = {};
792
+ for (const [name, config] of Object.entries(all)) {
793
+ if (config.platform !== 'ios') {
794
+ androidDevices[name] = config;
795
+ }
796
+ }
797
+ return androidDevices;
798
+ }
799
+ /**
800
+ * Set an iOS device to emulate
801
+ * @param {Object} iosConfig - iOS device configuration
802
+ * @returns {string} The iOS User-Agent
803
+ */
804
+ setIOSDevice(iosConfig) {
805
+ const { iosDeviceModel = 'iPhone16,2', iosDeviceName = 'iPhone 15 Pro Max', iosVersion = '18.3', iosAppVersion = '366.0.0.38.99', iosAppVersionCode = '632412089' } = iosConfig || {};
806
+ this.platform = 'ios';
807
+ this.iosDeviceModel = iosDeviceModel;
808
+ this.iosDeviceName = iosDeviceName;
809
+ this.iosVersion = iosVersion;
810
+ this.iosAppVersion = iosAppVersion;
811
+ this.iosAppVersionCode = iosAppVersionCode;
812
+ // Generate iOS-specific device identifiers
813
+ const chance = new Chance(`ios-${iosDeviceModel}-${Date.now()}`);
814
+ this.deviceId = `ios-${chance.string({ pool: 'ABCDEF0123456789', length: 40 })}`;
815
+ this.uuid = chance.guid().toUpperCase();
816
+ this.phoneId = chance.guid().toUpperCase();
817
+ this.adid = chance.guid().toUpperCase();
818
+ if (this._emitter) {
819
+ this._emitter.emit('device_changed', {
820
+ platform: 'ios',
821
+ deviceModel: iosDeviceModel,
822
+ deviceName: iosDeviceName,
823
+ userAgent: this.iosUserAgent
824
+ });
825
+ }
826
+ return this.iosUserAgent;
827
+ }
828
+ /**
829
+ * Switch to iOS platform with a preset device
830
+ * @param {string} presetName - Name of the iOS preset (e.g., 'iPhone 16 Pro Max')
831
+ * @returns {string|null} iOS User-Agent if successful, null if preset not found
832
+ */
833
+ useIOSDevice(presetName) {
834
+ const presets = this.getPresetDevices();
835
+ if (presets[presetName] && presets[presetName].platform === 'ios') {
836
+ return this.setIOSDevice(presets[presetName]);
837
+ }
838
+ const iosDevices = Object.keys(this.getIOSDevices());
839
+ console.warn(`iOS device "${presetName}" not found. Available iOS devices:`, iosDevices);
840
+ return null;
841
+ }
842
+ /**
843
+ * Switch to Android platform with a preset device
844
+ * @param {string} presetName - Name of the Android preset (e.g., 'Samsung Galaxy S25 Ultra')
845
+ * @returns {string|null} Device string if successful, null if preset not found
846
+ */
847
+ useAndroidDevice(presetName) {
848
+ const presets = this.getPresetDevices();
849
+ if (presets[presetName] && presets[presetName].platform !== 'ios') {
850
+ this.platform = 'android';
851
+ return this.setCustomDevice(presets[presetName]);
852
+ }
853
+ const androidDevices = Object.keys(this.getAndroidDevices());
854
+ console.warn(`Android device "${presetName}" not found. Available Android devices:`, androidDevices);
855
+ return null;
856
+ }
857
+ /**
858
+ * Switch platform between iOS and Android
859
+ * @param {string} targetPlatform - 'ios' or 'android'
860
+ * @param {string} devicePreset - Optional device preset name
861
+ */
862
+ switchPlatform(targetPlatform, devicePreset = null) {
863
+ if (targetPlatform === 'ios') {
864
+ if (devicePreset) {
865
+ return this.useIOSDevice(devicePreset);
866
+ }
867
+ return this.useIOSDevice('iPhone 16 Pro Max');
868
+ }
869
+ else if (targetPlatform === 'android') {
870
+ if (devicePreset) {
871
+ return this.useAndroidDevice(devicePreset);
872
+ }
873
+ this.platform = 'android';
874
+ return this.useAndroidDevice('Samsung Galaxy S25 Ultra');
875
+ }
876
+ console.warn('Invalid platform. Use "ios" or "android".');
877
+ return null;
878
+ }
879
+ /**
880
+ * Get current platform info
881
+ * @returns {Object} Current platform and device information
882
+ */
883
+ getPlatformInfo() {
884
+ return {
885
+ platform: this.platform,
886
+ userAgent: this.appUserAgent,
887
+ packageName: this.packageName,
888
+ deviceId: this.deviceId,
889
+ ...(this.platform === 'ios' ? {
890
+ iosDeviceModel: this.iosDeviceModel,
891
+ iosDeviceName: this.iosDeviceName,
892
+ iosVersion: this.iosVersion,
893
+ iosAppVersion: this.iosAppVersion
894
+ } : {
895
+ deviceString: this.deviceString,
896
+ build: this.build
897
+ })
898
+ };
899
+ }
900
+ /**
901
+ * List all available device presets grouped by platform
902
+ * @returns {Object} Devices grouped by platform
903
+ */
904
+ listAllDevices() {
905
+ return {
906
+ android: Object.keys(this.getAndroidDevices()),
907
+ ios: Object.keys(this.getIOSDevices())
908
+ };
909
+ }
910
+ /**
911
+ * Quick method to set a device from presets by name
912
+ * @param {string} presetName - Name of the preset (e.g., 'Samsung Galaxy S25 Ultra')
913
+ * @returns {string|null} Device string if successful, null if preset not found
914
+ *
915
+ * @example
916
+ * state.usePresetDevice('Samsung Galaxy S25 Ultra');
917
+ * state.usePresetDevice('Huawei P60 Pro');
918
+ * state.usePresetDevice('Google Pixel 8 Pro');
919
+ */
920
+ usePresetDevice(presetName) {
921
+ const presets = this.getPresetDevices();
922
+ if (presets[presetName]) {
923
+ return this.setCustomDevice(presets[presetName]);
924
+ }
925
+ console.warn(`Preset device "${presetName}" not found. Available presets:`, Object.keys(presets));
926
+ return null;
927
+ }
928
+ /**
929
+ * Get the current device info being emulated
930
+ * @returns {Object} Current device configuration
931
+ */
932
+ getCurrentDeviceInfo() {
933
+ return {
934
+ deviceString: this.deviceString,
935
+ deviceId: this.deviceId,
936
+ uuid: this.uuid,
937
+ phoneId: this.phoneId,
938
+ adid: this.adid,
939
+ build: this.build,
940
+ userAgent: this.appUserAgent
941
+ };
942
+ }
943
+ generateTemporaryGuid(seed, lifetime) {
944
+ return new Chance(`${seed}${this.deviceId}${Math.round(Date.now() / lifetime)}`).guid();
945
+ }
946
+ clearCookies() {
947
+ this.cookieJar = new CookieJar();
948
+ }
949
+ listCookies() {
950
+ try {
951
+ const cookies = this.cookieJar.getCookiesSync
952
+ ? this.cookieJar.getCookiesSync(this.constants.HOST)
953
+ : this.cookieJar.getCookies(this.constants.HOST);
954
+ if (Array.isArray(cookies)) {
955
+ for (const c of cookies) {
956
+ console.log(`- ${c.key}=${c.value}`);
957
+ }
958
+ return cookies;
959
+ }
960
+ return [];
961
+ }
962
+ catch (e) {
963
+ return [];
964
+ }
965
+ }
966
+ logStateSummary() {
967
+ console.log('--- State Summary ---');
968
+ console.log(`Device ID: ${this.deviceId}`);
969
+ console.log(`UUID: ${this.uuid}`);
970
+ console.log(`User Agent: ${this.appUserAgent}`);
971
+ console.log(`Language: ${this.language}`);
972
+ console.log(`Timezone Offset: ${this.timezoneOffset}`);
973
+ console.log(`Authorization: ${this.authorization ? 'Present' : 'Missing'}`);
974
+ console.log('----------------------');
975
+ }
976
+ //
977
+ // === NEW UTILITIES ADDED BELOW (non-destructive; keep backwards compat)
978
+ //
979
+ /**
980
+ * Subscribe to internal state events (non-invasive).
981
+ * Events emitted:
982
+ * - 'session_saved' => (filePath)
983
+ * - 'session_save_failed' => (err)
984
+ * - 'session_loaded' => (filePath)
985
+ * - 'session_load_failed' => (err)
986
+ * - 'cookies_cleared'
987
+ * - 'device_regenerated'
988
+ * - 'session_file_changed' => (eventType, filename)
989
+ */
990
+ on(event, listener) {
991
+ this._emitter.on(event, listener);
992
+ }
993
+ off(event, listener) {
994
+ this._emitter.removeListener(event, listener);
995
+ }
996
+ once(event, listener) {
997
+ this._emitter.once(event, listener);
998
+ }
999
+ /**
1000
+ * Atomic save with retries and backup rotation.
1001
+ * Attempts to write to a temp file, rename into place (atomic on most OSes),
1002
+ * and maintain up to `_maxBackupCopies` rotated backups.
1003
+ */
1004
+ async safeSaveSessionToFile(filePath = SESSION_FILE, backupPath = SESSION_BACKUP, opts = {}) {
1005
+ const retries = typeof opts.retries === 'number' ? opts.retries : this._saveRetries;
1006
+ const delayMs = typeof opts.delayMs === 'number' ? opts.delayMs : this._saveRetryDelayMs;
1007
+ const maxBackups = typeof opts.maxBackups === 'number' ? opts.maxBackups : this._maxBackupCopies;
1008
+ const tempPath = `${filePath}.tmp`;
1009
+ let lastErr;
1010
+ for (let attempt = 0; attempt <= retries; attempt++) {
1011
+ try {
1012
+ const data = await this.serialize();
1013
+ // ensure parent dir exists
1014
+ await fs.promises.mkdir(path.dirname(filePath), { recursive: true });
1015
+ // write temp and rename (atomic on many systems)
1016
+ await fs.promises.writeFile(tempPath, JSON.stringify(data, null, 2), { mode: 0o600 });
1017
+ await fs.promises.rename(tempPath, filePath);
1018
+ // maintain backup copy
1019
+ try {
1020
+ await this._rotateAndWriteBackup(filePath, backupPath, maxBackups);
1021
+ }
1022
+ catch (_) {
1023
+ // non-fatal for backup rotation
1024
+ }
1025
+ this._emitter.emit('session_saved', filePath);
1026
+ return true;
1027
+ }
1028
+ catch (err) {
1029
+ lastErr = err;
1030
+ // small backoff
1031
+ await new Promise(r => setTimeout(r, delayMs * (attempt + 1)));
1032
+ }
1033
+ }
1034
+ this._emitter.emit('session_save_failed', lastErr);
1035
+ throw lastErr || new Error('safeSaveSessionToFile failed');
1036
+ }
1037
+ // helper: rotate existing backups and write new backup copy
1038
+ async _rotateAndWriteBackup(filePath, backupPath, maxBackups) {
1039
+ try {
1040
+ // if no original file, just copy
1041
+ if (!fs.existsSync(filePath)) {
1042
+ const data = await this.serialize();
1043
+ await fs.promises.writeFile(backupPath, JSON.stringify(data, null, 2), { mode: 0o600 });
1044
+ return;
1045
+ }
1046
+ // rotate existing numeric backups (backupPath.1, backupPath.2, ...)
1047
+ for (let i = maxBackups - 1; i >= 1; i--) {
1048
+ const src = `${backupPath}.${i}`;
1049
+ const dst = `${backupPath}.${i + 1}`;
1050
+ if (fs.existsSync(src)) {
1051
+ try {
1052
+ await fs.promises.rename(src, dst);
1053
+ }
1054
+ catch (_) { }
1055
+ }
1056
+ }
1057
+ // move current backup to .1
1058
+ if (fs.existsSync(backupPath)) {
1059
+ try {
1060
+ await fs.promises.rename(backupPath, `${backupPath}.1`);
1061
+ }
1062
+ catch (_) { }
1063
+ }
1064
+ // write a new backup from current file
1065
+ const content = await fs.promises.readFile(filePath, 'utf8');
1066
+ await fs.promises.writeFile(backupPath, content, { mode: 0o600 });
1067
+ }
1068
+ catch (e) {
1069
+ // ignore backup rotation issues
1070
+ }
1071
+ }
1072
+ /**
1073
+ * Safe load with retries. Emits session_loaded/session_load_failed events.
1074
+ */
1075
+ async safeLoadSessionFromFile(filePath = SESSION_FILE, backupPath = SESSION_BACKUP, opts = {}) {
1076
+ const retries = typeof opts.retries === 'number' ? opts.retries : 2;
1077
+ const delayMs = typeof opts.delayMs === 'number' ? opts.delayMs : 200;
1078
+ let lastErr;
1079
+ for (let attempt = 0; attempt <= retries; attempt++) {
1080
+ try {
1081
+ const ok = await this.loadSessionFromFile(filePath, backupPath);
1082
+ if (ok) {
1083
+ this._emitter.emit('session_loaded', filePath);
1084
+ return true;
1085
+ }
1086
+ // if not ok, wait and retry
1087
+ await new Promise(r => setTimeout(r, delayMs * (attempt + 1)));
1088
+ }
1089
+ catch (err) {
1090
+ lastErr = err;
1091
+ await new Promise(r => setTimeout(r, delayMs * (attempt + 1)));
1092
+ }
1093
+ }
1094
+ this._emitter.emit('session_load_failed', lastErr);
1095
+ throw lastErr || new Error('safeLoadSessionFromFile failed');
1096
+ }
1097
+ /**
1098
+ * Validate minimal session integrity: ensure cookie jar has expected cookies or parsed authorization
1099
+ */
1100
+ validateSession() {
1101
+ try {
1102
+ // try to read ds_user_id or parsed authorization
1103
+ let ok = false;
1104
+ try {
1105
+ const uid = this.extractCookieValue('ds_user_id');
1106
+ ok = !!uid;
1107
+ }
1108
+ catch (_) {
1109
+ // fallback to parsed authorization
1110
+ this.updateAuthorization();
1111
+ ok = !!(this.parsedAuthorization && this.parsedAuthorization.ds_user_id);
1112
+ }
1113
+ return ok;
1114
+ }
1115
+ catch (_) {
1116
+ return false;
1117
+ }
1118
+ }
1119
+ /**
1120
+ * Merge cookies from another serialized jar or CookieJar instance into current cookieJar.
1121
+ * Accepts: serialized object/string (as used by serializeCookieJar) or CookieJar instance.
1122
+ */
1123
+ async mergeCookieJarFrom(other) {
1124
+ try {
1125
+ if (!other)
1126
+ return false;
1127
+ // if serialized string/object
1128
+ if (typeof other === 'string' || (typeof other === 'object' && !other.getCookieSync)) {
1129
+ // deserialize into a temporary jar
1130
+ const deserializeFn = util.promisify((input, cb) => {
1131
+ try {
1132
+ CookieJar.deserialize(input, cb);
1133
+ }
1134
+ catch (err) {
1135
+ cb(err);
1136
+ }
1137
+ });
1138
+ const tmpJar = await deserializeFn(typeof other === 'string' ? JSON.parse(other) : other);
1139
+ if (!tmpJar)
1140
+ return false;
1141
+ // merge: extract cookies for host and set into current jar
1142
+ const host = this.constants.HOST;
1143
+ const cookies = tmpJar.getCookiesSync ? tmpJar.getCookiesSync(host) : await tmpJar.getCookies(host);
1144
+ if (Array.isArray(cookies)) {
1145
+ for (const c of cookies) {
1146
+ try {
1147
+ // setCookieSync may not exist in some versions; fallback to async
1148
+ if (typeof this.cookieJar.setCookieSync === 'function') {
1149
+ this.cookieJar.setCookieSync(c, host);
1150
+ }
1151
+ else if (typeof this.cookieJar.setCookie === 'function') {
1152
+ // promisify setCookie
1153
+ await util.promisify(this.cookieJar.setCookie).call(this.cookieJar, c, host);
1154
+ }
1155
+ }
1156
+ catch (_) { }
1157
+ }
1158
+ }
1159
+ return true;
1160
+ }
1161
+ else if (typeof other.getCookiesSync === 'function' || typeof other.getCookies === 'function') {
1162
+ // assume CookieJar instance
1163
+ const host = this.constants.HOST;
1164
+ const cookies = other.getCookiesSync ? other.getCookiesSync(host) : await other.getCookies(host);
1165
+ if (Array.isArray(cookies)) {
1166
+ for (const c of cookies) {
1167
+ try {
1168
+ if (typeof this.cookieJar.setCookieSync === 'function') {
1169
+ this.cookieJar.setCookieSync(c, host);
1170
+ }
1171
+ else if (typeof this.cookieJar.setCookie === 'function') {
1172
+ await util.promisify(this.cookieJar.setCookie).call(this.cookieJar, c, host);
1173
+ }
1174
+ }
1175
+ catch (_) { }
1176
+ }
1177
+ }
1178
+ return true;
1179
+ }
1180
+ }
1181
+ catch (e) {
1182
+ return false;
1183
+ }
1184
+ return false;
1185
+ }
1186
+ /**
1187
+ * Export a minimal session object (useful for sending to remote storage or IPC).
1188
+ */
1189
+ async exportMinimalSession() {
1190
+ const cookieData = await this.serializeCookieJar();
1191
+ return {
1192
+ deviceId: this.deviceId,
1193
+ deviceString: this.deviceString,
1194
+ uuid: this.uuid,
1195
+ phoneId: this.phoneId,
1196
+ adid: this.adid,
1197
+ build: this.build,
1198
+ authorization: this.authorization,
1199
+ cookies: cookieData
1200
+ };
1201
+ }
1202
+ /**
1203
+ * Import minimal session object (merges cookies if present and sets fields).
1204
+ */
1205
+ async importMinimalSession(minObj = {}) {
1206
+ if (!minObj || typeof minObj !== 'object')
1207
+ return false;
1208
+ try {
1209
+ if (minObj.cookies) {
1210
+ try {
1211
+ await this.mergeCookieJarFrom(minObj.cookies);
1212
+ }
1213
+ catch (_) { }
1214
+ }
1215
+ // set other fields cautiously
1216
+ const fields = ['deviceId', 'deviceString', 'uuid', 'phoneId', 'adid', 'build', 'authorization'];
1217
+ for (const k of fields) {
1218
+ if (typeof minObj[k] !== 'undefined')
1219
+ this[k] = minObj[k];
1220
+ }
1221
+ this.updateAuthorization();
1222
+ return true;
1223
+ }
1224
+ catch (e) {
1225
+ return false;
1226
+ }
1227
+ }
1228
+ /**
1229
+ * Set proxy URL (persists only in-memory; use saveSessionToFile to persist).
1230
+ */
1231
+ setProxyUrl(url) {
1232
+ this.proxyUrl = url || null;
1233
+ return this.proxyUrl;
1234
+ }
1235
+ clearProxyUrl() {
1236
+ this.proxyUrl = null;
1237
+ return true;
1238
+ }
1239
+ /**
1240
+ * Mark checkpoint metadata object (stores arbitrary checkpoint info).
1241
+ */
1242
+ markCheckpoint(obj) {
1243
+ try {
1244
+ this.checkpoint = obj;
1245
+ return true;
1246
+ }
1247
+ catch (_) {
1248
+ return false;
1249
+ }
1250
+ }
1251
+ clearCheckpoint() {
1252
+ this.checkpoint = null;
1253
+ return true;
1254
+ }
1255
+ /**
1256
+ * Ensure session file has safe permissions (owner read/write only)
1257
+ */
1258
+ ensureFilePermissions(filePath = SESSION_FILE) {
1259
+ try {
1260
+ if (fs.existsSync(filePath)) {
1261
+ fs.chmodSync(filePath, 0o600);
1262
+ }
1263
+ return true;
1264
+ }
1265
+ catch (e) {
1266
+ return false;
1267
+ }
1268
+ }
1269
+ /**
1270
+ * Watch the session file for external changes and emit 'session_file_changed'.
1271
+ * Note: uses fs.watchFile which is more portable; call stopWatchingSessionFile() to stop.
1272
+ */
1273
+ watchSessionFile(filePath = SESSION_FILE, intervalMs = 1000) {
1274
+ try {
1275
+ if (this._sessionFileWatcher) {
1276
+ // already watching
1277
+ return true;
1278
+ }
1279
+ // use watchFile (polling) for reliability across platforms
1280
+ fs.watchFile(filePath, { interval: intervalMs }, (curr, prev) => {
1281
+ // ignore if size/time identical
1282
+ if (curr.mtimeMs !== prev.mtimeMs || curr.size !== prev.size) {
1283
+ this._emitter.emit('session_file_changed', { filePath, curr, prev });
1284
+ }
1285
+ });
1286
+ this._sessionFileWatcher = true;
1287
+ return true;
1288
+ }
1289
+ catch (e) {
1290
+ return false;
1291
+ }
1292
+ }
1293
+ stopWatchingSessionFile(filePath = SESSION_FILE) {
1294
+ try {
1295
+ if (!this._sessionFileWatcher)
1296
+ return true;
1297
+ fs.unwatchFile(filePath);
1298
+ this._sessionFileWatcher = null;
1299
+ return true;
1300
+ }
1301
+ catch (e) {
1302
+ return false;
1303
+ }
1304
+ }
1305
+ /**
1306
+ * If device looks missing or invalid, regenerate device fields.
1307
+ * Condition: deviceId missing or doesn't start with expected prefix.
1308
+ */
1309
+ refreshDeviceIfMissingOrOld(seed = 'instagram-private-api') {
1310
+ try {
1311
+ if (!this.deviceId || typeof this.deviceId !== 'string' || !this.deviceId.startsWith('android-')) {
1312
+ this.generateDevice(seed);
1313
+ this._emitter.emit('device_regenerated');
1314
+ return true;
1315
+ }
1316
+ return false;
1317
+ }
1318
+ catch (e) {
1319
+ return false;
1320
+ }
1321
+ }
1322
+ /**
1323
+ * Refresh authorization state from cookies (useful after merging cookies).
1324
+ */
1325
+ refreshAuthFromCookies() {
1326
+ try {
1327
+ this.updateAuthorization();
1328
+ return true;
1329
+ }
1330
+ catch (e) {
1331
+ return false;
1332
+ }
1333
+ }
1334
+ /**
1335
+ * Safe load helper that tries to load, validate, and optionally attempt fallback to backup copies.
1336
+ * If `validate` is true, will call validateSession() and throw if invalid.
1337
+ */
1338
+ async loadAndValidateSession(filePath = SESSION_FILE, backupPath = SESSION_BACKUP, opts = {}) {
1339
+ const validate = opts.validate !== false; // default true
1340
+ try {
1341
+ const ok = await this.safeLoadSessionFromFile(filePath, backupPath, opts);
1342
+ if (!ok)
1343
+ throw new Error('load failed');
1344
+ if (validate && !this.validateSession()) {
1345
+ // try backup load
1346
+ const triedBackups = await this._tryLoadRotatedBackups(backupPath, opts);
1347
+ if (!triedBackups)
1348
+ throw new Error('session invalid and backups failed');
1349
+ }
1350
+ this._emitter.emit('session_loaded', filePath);
1351
+ return true;
1352
+ }
1353
+ catch (e) {
1354
+ this._emitter.emit('session_load_failed', e);
1355
+ throw e;
1356
+ }
1357
+ }
1358
+ // helper: try load rotated backups .1 .. .N
1359
+ async _tryLoadRotatedBackups(backupPath, opts = {}) {
1360
+ try {
1361
+ const max = typeof opts.maxBackups === 'number' ? opts.maxBackups : this._maxBackupCopies;
1362
+ for (let i = 1; i <= max; i++) {
1363
+ const p = `${backupPath}.${i}`;
1364
+ if (!fs.existsSync(p))
1365
+ continue;
1366
+ try {
1367
+ const raw = await fs.promises.readFile(p, 'utf8');
1368
+ const obj = JSON.parse(raw);
1369
+ await this.deserialize(obj);
1370
+ if (this.validateSession())
1371
+ return true;
1372
+ }
1373
+ catch (_) {
1374
+ // continue trying next
1375
+ }
1376
+ }
1377
+ }
1378
+ catch (_) { }
1379
+ return false;
1380
+ }
1381
+ /**
1382
+ * Clear all session data (cookies + auth + device optional).
1383
+ * If `preserveDevice` is true, device fields are kept.
1384
+ */
1385
+ clearAllSession(preserveDevice = true) {
1386
+ try {
1387
+ this.clearCookies();
1388
+ this.authorization = undefined;
1389
+ this.parsedAuthorization = undefined;
1390
+ this.igWWWClaim = undefined;
1391
+ this.passwordEncryptionKeyId = undefined;
1392
+ this.passwordEncryptionPubKey = undefined;
1393
+ if (!preserveDevice) {
1394
+ this.generateDevice('instagram-private-api');
1395
+ }
1396
+ this._emitter.emit('cookies_cleared');
1397
+ return true;
1398
+ }
1399
+ catch (e) {
1400
+ return false;
1401
+ }
1402
+ }
1403
+ /**
1404
+ * Quick helper: get value of cookie if exists, or null (non-throwing).
1405
+ */
1406
+ getCookieValueSafe(key) {
1407
+ try {
1408
+ const c = this.extractCookie(key);
1409
+ return c ? c.value : null;
1410
+ }
1411
+ catch (_) {
1412
+ return null;
1413
+ }
1414
+ }
1415
+ /**
1416
+ * Convenience: set default save/retry options
1417
+ */
1418
+ setSaveRetryOptions({ retries, delayMs, maxBackups } = {}) {
1419
+ if (typeof retries === 'number')
1420
+ this._saveRetries = retries;
1421
+ if (typeof delayMs === 'number')
1422
+ this._saveRetryDelayMs = delayMs;
1423
+ if (typeof maxBackups === 'number')
1424
+ this._maxBackupCopies = maxBackups;
1425
+ return { retries: this._saveRetries, delayMs: this._saveRetryDelayMs, maxBackups: this._maxBackupCopies };
1426
+ }
1427
+ }
1428
+ module.exports = State;