@eryxenx/insta-chat 2.0.6 → 2.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/DOCS.md +1 -1
- package/package.json +2 -2
- package/src/api/messaging/unsendMessage.js +7 -3
- package/src/api.js +1 -1
- package/src/app/InstaContext.js +1 -1
- package/src/events/normalizeEvent.js +6 -0
- package/src/methods/message.js +9 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,31 @@ All notable changes to `@eryxenx/insta-chat` are documented here.
|
|
|
4
4
|
The format follows [Keep a Changelog](https://keepachangelog.com/) and uses
|
|
5
5
|
[Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [2.0.8] - 2026-10-11
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **`unsendMessage` never deleted the message.** The REST delete request was
|
|
12
|
+
sent with an empty body, which Instagram rejects with `status: "fail"` (or a
|
|
13
|
+
404/redirect). The web client sends `_csrftoken` and `_uuid`, so `/unsend`
|
|
14
|
+
now includes both. Previously the call resolved to `false`, which the bot
|
|
15
|
+
surfaced as "Could not unsend this message (Instagram refused it, or the
|
|
16
|
+
message is too old)."
|
|
17
|
+
|
|
18
|
+
## [2.0.7] - 2026-10-11
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- **`unsendMessage` silently failed for a message the bot did not send in this
|
|
23
|
+
process.** The thread of the id being unsent was resolved only from the
|
|
24
|
+
in-memory `messageID -> threadID` map, so unsending a message sent before a
|
|
25
|
+
restart (or a reply to someone else's message) threw `Unknown thread for
|
|
26
|
+
message` internally and returned `false` — `/unsend` appeared to do nothing.
|
|
27
|
+
`unsendMessage(messageID, callback?, threadID?)` now accepts the thread
|
|
28
|
+
explicitly, and the normalizer remembers the replied-to message id (whose
|
|
29
|
+
thread is known) so the map lookup succeeds. The thread the message was seen
|
|
30
|
+
in is always a safe explicit value for `/unsend`.
|
|
31
|
+
|
|
7
32
|
## [2.0.6] - 2026-10-10
|
|
8
33
|
|
|
9
34
|
### Added
|
package/DOCS.md
CHANGED
|
@@ -58,7 +58,7 @@ Facebook-Chat-API shape. Its methods live one-per-file under
|
|
|
58
58
|
|
|
59
59
|
| Group | Methods |
|
|
60
60
|
|-------|---------|
|
|
61
|
-
| messaging | `sendMessage(form, threadID, cb?, replyToMessage?)`, `sendMessageSync`, `editMessage(text, messageID)`, `unsendMessage(messageID)`, `setMessageReaction(emoji, messageID, cb?, threadID?)`, `sendTypingIndicator`, `markAsRead`, `shareContact`, `resolvePhotoUrl` |
|
|
61
|
+
| messaging | `sendMessage(form, threadID, cb?, replyToMessage?)`, `sendMessageSync`, `editMessage(text, messageID)`, `unsendMessage(messageID, cb?, threadID?)`, `setMessageReaction(emoji, messageID, cb?, threadID?)`, `sendTypingIndicator`, `markAsRead`, `shareContact`, `resolvePhotoUrl` |
|
|
62
62
|
| threads | `getThreadInfo`, `getThreadList`, `getThreadHistory` |
|
|
63
63
|
| users | `getUserInfo`, `getUID`, `getProfilePictureUrl` |
|
|
64
64
|
| account | `getCurrentUserID`, `getAppState`, `getCookies`, `setOptions` |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eryxenx/insta-chat",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.8",
|
|
4
4
|
"description": " Unofficial Instagram Chat API for Node.js | Build Instagram DM bots on personal accounts \u2014 send messages, media, voice notes, reactions, edit & unsend, listen for incoming chats. No browser at runtime",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"CHANGELOG.md"
|
|
24
24
|
],
|
|
25
25
|
"scripts": {
|
|
26
|
-
"test": "node test/smoke.js && node test/antiSuspension.test.js && node test/replyContent.test.js && node test/edit.test.js && node test/sendReply.test.js && node test/client.test.js && node test/relayError.test.js && node test/safetyWiring.test.js && node test/mediaOrder.test.js && node test/sessionSafety.test.js && node test/emptySend.test.js && node test/pollFloor.test.js",
|
|
26
|
+
"test": "node test/smoke.js && node test/antiSuspension.test.js && node test/replyContent.test.js && node test/edit.test.js && node test/sendReply.test.js && node test/client.test.js && node test/relayError.test.js && node test/safetyWiring.test.js && node test/mediaOrder.test.js && node test/sessionSafety.test.js && node test/emptySend.test.js && node test/pollFloor.test.js && node test/unsend.test.js",
|
|
27
27
|
"build": "node scripts/build.js"
|
|
28
28
|
},
|
|
29
29
|
"keywords": [
|
|
@@ -5,12 +5,16 @@
|
|
|
5
5
|
* Original author credit must be retained in all copies and derivatives.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
// fca.unsendMessage(messageID) — the thread
|
|
8
|
+
// fca.unsendMessage(messageID, callback, threadID) — the thread may be passed
|
|
9
|
+
// explicitly; otherwise it is resolved from the id. A bot that only knows the
|
|
10
|
+
// replied-to message id (it did not send that message in this process, e.g.
|
|
11
|
+
// after a restart) cannot resolve the thread, so the explicit thread is what
|
|
12
|
+
// makes /unsend work reliably.
|
|
9
13
|
module.exports = function (client) {
|
|
10
|
-
return async function unsendMessage(messageID, callback) {
|
|
14
|
+
return async function unsendMessage(messageID, callback, threadID) {
|
|
11
15
|
const cb = typeof callback === "function" ? callback : null;
|
|
12
16
|
try {
|
|
13
|
-
const tid = client._resolveThread(messageID);
|
|
17
|
+
const tid = client._resolveThread(messageID, threadID);
|
|
14
18
|
const ok = await client.api.unsendMessage(tid, String(messageID));
|
|
15
19
|
if (cb) cb(null, ok);
|
|
16
20
|
return ok;
|
package/src/api.js
CHANGED
|
@@ -43,7 +43,7 @@ class InstaAPI {
|
|
|
43
43
|
const sessionParams = options.sessionParams || this._loadSessionParams(options.sessionParamsFile);
|
|
44
44
|
if (sessionParams) this.http.setSessionParams(sessionParams);
|
|
45
45
|
|
|
46
|
-
this.message = new MessageMethods(this.http);
|
|
46
|
+
this.message = new MessageMethods(this.http, this.identity);
|
|
47
47
|
this.reaction = new ReactionMethods(this.http);
|
|
48
48
|
this.typing = new TypingMethods(this.http);
|
|
49
49
|
this.thread = new ThreadMethods(this.http);
|
package/src/app/InstaContext.js
CHANGED
|
@@ -139,6 +139,12 @@ class EventNormalizer {
|
|
|
139
139
|
// client must know which thread it belongs to.
|
|
140
140
|
if (typeof this.client.rememberThread === "function") {
|
|
141
141
|
this.client.rememberThread(event.messageID, threadID);
|
|
142
|
+
// Remember the replied-to message too: /unsend resolves its thread from
|
|
143
|
+
// that id, and the bot may be unssending a message it sent in an earlier
|
|
144
|
+
// process (so it is not in _msgThread otherwise).
|
|
145
|
+
if (event.messageReply && event.messageReply.messageID) {
|
|
146
|
+
this.client.rememberThread(event.messageReply.messageID, threadID);
|
|
147
|
+
}
|
|
142
148
|
}
|
|
143
149
|
|
|
144
150
|
return event;
|
package/src/methods/message.js
CHANGED
|
@@ -12,8 +12,9 @@ const { classify } = require("../utils/errors");
|
|
|
12
12
|
const NO_FALLBACK_KINDS = new Set(["rate_limited", "challenge", "blocked", "suspended", "auth"]);
|
|
13
13
|
|
|
14
14
|
class MessageMethods {
|
|
15
|
-
constructor(http) {
|
|
15
|
+
constructor(http, identity) {
|
|
16
16
|
this.http = http;
|
|
17
|
+
this.identity = identity;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
// Confirmed send path from a live web session: the IGDirectTextSendMutation
|
|
@@ -98,8 +99,14 @@ class MessageMethods {
|
|
|
98
99
|
});
|
|
99
100
|
}
|
|
100
101
|
|
|
102
|
+
// Instagram's REST delete requires the request to look like the web client's:
|
|
103
|
+
// a `_csrftoken` (the csrftoken cookie) and a `_uuid` (the browser/device id).
|
|
104
|
+
// An empty body is rejected — Instagram answers with `status: "fail"` (or a
|
|
105
|
+
// 404/redirect), which made `unsend` a silent no-op.
|
|
101
106
|
async unsend(threadID, itemID) {
|
|
102
|
-
const
|
|
107
|
+
const csrf = this.http.getCookie("csrftoken");
|
|
108
|
+
const body = { _csrftoken: csrf, _uuid: this.identity?.uuid || this.http.uuid() };
|
|
109
|
+
const res = await this.http.postForm(EP.ITEM_DELETE(threadID, itemID), body);
|
|
103
110
|
return res?.status === "ok";
|
|
104
111
|
}
|
|
105
112
|
|