@lazyneoaz/metachat 1.0.10 → 1.1.0

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 (53) hide show
  1. package/package.json +1 -1
  2. package/src/apis/addUserToGroup.js +1 -1
  3. package/src/apis/changeAdminStatus.js +46 -55
  4. package/src/apis/changeArchivedStatus.js +16 -8
  5. package/src/apis/changeAvatar.js +2 -2
  6. package/src/apis/changeBio.js +1 -1
  7. package/src/apis/changeBlockedStatus.js +1 -1
  8. package/src/apis/changeGroupImage.js +23 -15
  9. package/src/apis/changeThreadColor.js +1 -1
  10. package/src/apis/changeThreadEmoji.js +14 -8
  11. package/src/apis/createNewGroup.js +13 -5
  12. package/src/apis/createPoll.js +14 -5
  13. package/src/apis/deleteMessage.js +11 -8
  14. package/src/apis/deleteThread.js +1 -1
  15. package/src/apis/editMessage.js +59 -48
  16. package/src/apis/emoji.js +2 -2
  17. package/src/apis/follow.js +26 -30
  18. package/src/apis/forwardAttachment.js +3 -2
  19. package/src/apis/forwardMessage.js +1 -1
  20. package/src/apis/gcmember.js +4 -3
  21. package/src/apis/gcname.js +3 -3
  22. package/src/apis/gcrule.js +4 -3
  23. package/src/apis/getFriendsList.js +2 -2
  24. package/src/apis/getThreadInfo.js +1 -1
  25. package/src/apis/getThreadPictures.js +1 -1
  26. package/src/apis/handleMessageRequest.js +1 -1
  27. package/src/apis/listenMqtt.js +160 -6
  28. package/src/apis/markAsRead.js +15 -9
  29. package/src/apis/muteThread.js +1 -1
  30. package/src/apis/nickname.js +62 -48
  31. package/src/apis/pinMessage.js +110 -130
  32. package/src/apis/removeUserFromGroup.js +9 -2
  33. package/src/apis/resolvePhotoUrl.js +1 -1
  34. package/src/apis/searchForThread.js +1 -1
  35. package/src/apis/sendEffect.js +3 -2
  36. package/src/apis/sendMessage.js +13 -2
  37. package/src/apis/setMessageReaction.js +58 -19
  38. package/src/apis/setMessageReactionMqtt.js +96 -56
  39. package/src/apis/setThreadThemeMqtt.js +70 -75
  40. package/src/apis/shareContact.js +37 -31
  41. package/src/apis/theme.js +1 -1
  42. package/src/apis/unfriend.js +1 -1
  43. package/src/apis/unsendMessage.js +71 -9
  44. package/src/app/state.js +1 -1
  45. package/src/engine/models/loginHelper.js +5 -0
  46. package/src/types/index.d.ts +40 -1
  47. package/src/utils/antiSuspension.js +5 -5
  48. package/src/utils/auth-helpers.js +1 -1
  49. package/src/utils/clients.js +21 -0
  50. package/src/utils/headers.js +1 -1
  51. package/src/utils/lsRequest.js +175 -0
  52. package/src/utils/rateLimiter.js +6 -2
  53. package/src/utils/tokenRefresh.js +24 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lazyneoaz/metachat",
3
- "version": "1.0.10",
3
+ "version": "1.1.0",
4
4
  "type": "commonjs",
5
5
  "types": "src/types/index.d.ts",
6
6
  "description": "Advanced Facebook Chat API client for building Messenger bots — real-time messaging, thread management, MQTT, and session stability.",
@@ -19,7 +19,7 @@ module.exports = (defaultFuncs, api, ctx) => {
19
19
  }
20
20
 
21
21
  try {
22
- if (!ctx.mqttClient) {
22
+ if (!ctx.mqttClient || !ctx.mqttClient.connected) {
23
23
  throw new Error("Not connected to MQTT. Please use listenMqtt first.");
24
24
  }
25
25
 
@@ -20,112 +20,103 @@ module.exports = function (defaultFuncs, api, ctx) {
20
20
  if (err) return rejectFunc(err);
21
21
  resolveFunc(data);
22
22
  };
23
+ } else {
24
+ const _userCb = callback;
25
+ callback = function(err, data) {
26
+ if (err) { _userCb(err); return rejectFunc(err); }
27
+ _userCb(null, data);
28
+ resolveFunc(data);
29
+ };
23
30
  }
24
31
 
25
32
  if (getType(threadID) !== "String") {
26
- return callback({ error: "changeAdminStatus: threadID must be a string" });
33
+ callback(new Error("changeAdminStatus: threadID must be a string"));
34
+ return returnPromise;
27
35
  }
28
36
  if (getType(adminID) !== "String" && getType(adminID) !== "Array") {
29
- return callback({ error: "changeAdminStatus: adminID must be a string or an array" });
37
+ callback(new Error("changeAdminStatus: adminID must be a string or an array"));
38
+ return returnPromise;
30
39
  }
31
40
  if (getType(adminStatus) !== "Boolean") {
32
- return callback({ error: "changeAdminStatus: adminStatus must be true or false" });
41
+ callback(new Error("changeAdminStatus: adminStatus must be true or false"));
42
+ return returnPromise;
33
43
  }
34
44
 
35
- if (ctx.mqttClient) {
45
+ const isAdmin = adminStatus ? 1 : 0;
46
+
47
+ if (ctx.mqttClient && ctx.mqttClient.connected) {
36
48
  const tasks = [];
37
- const isAdmin = adminStatus ? 1 : 0;
38
49
  const epochID = utils.generateOfflineThreadingID();
39
50
 
40
- if (getType(adminID) === "Array") {
41
- adminID.forEach((id, index) => {
42
- tasks.push({
43
- failure_count: null,
44
- label: "25",
45
- payload: JSON.stringify({
46
- thread_key: threadID,
47
- contact_id: id,
48
- is_admin: isAdmin
49
- }),
50
- queue_name: "admin_status",
51
- task_id: index + 1
52
- });
53
- });
54
- } else {
51
+ if (typeof ctx.wsReqNumber !== "number") ctx.wsReqNumber = 0;
52
+ if (typeof ctx.wsTaskNumber !== "number") ctx.wsTaskNumber = 0;
53
+
54
+ const adminIDs = getType(adminID) === "Array" ? adminID : [adminID];
55
+ adminIDs.forEach((id) => {
55
56
  tasks.push({
56
57
  failure_count: null,
57
58
  label: "25",
58
59
  payload: JSON.stringify({
59
60
  thread_key: threadID,
60
- contact_id: adminID,
61
+ contact_id: id,
61
62
  is_admin: isAdmin
62
63
  }),
63
64
  queue_name: "admin_status",
64
- task_id: 1
65
+ task_id: ++ctx.wsTaskNumber
65
66
  });
66
- }
67
+ });
67
68
 
68
- let count_req = 0;
69
69
  const form = JSON.stringify({
70
- app_id: "2220391788200892",
70
+ app_id: String(ctx.appID || ctx.mqttAppID || "2220391788200892"),
71
71
  payload: JSON.stringify({
72
72
  epoch_id: epochID,
73
73
  tasks: tasks,
74
74
  version_id: "8798795233522156"
75
75
  }),
76
- request_id: ++count_req,
76
+ request_id: ++ctx.wsReqNumber,
77
77
  type: 3
78
78
  });
79
79
 
80
- ctx.mqttClient.publish("/ls_req", form, {}, (err, _packet) => {
80
+ ctx.mqttClient.publish("/ls_req", form, { qos: 1, retain: false }, (err) => {
81
81
  if (err) {
82
82
  utils.error("changeAdminStatus (MQTT)", err);
83
- return callback(err);
84
- } else {
85
- utils.log("Admin status changed successfully via MQTT");
86
- return callback(null, { success: true });
83
+ return callback(err instanceof Error ? err : new Error(String(err)));
87
84
  }
85
+ utils.log("Admin status changed successfully via MQTT");
86
+ return callback(null, { success: true });
88
87
  });
89
88
  } else {
90
89
  utils.warn("MQTT client not available, using HTTP fallback for changeAdminStatus");
91
90
  const tasks = [];
92
91
  const epochID = utils.generateOfflineThreadingID();
93
92
 
94
- if (getType(adminID) === "Array") {
95
- adminID.forEach((id, index) => {
96
- tasks.push({
97
- label: '25',
98
- payload: JSON.stringify({ thread_key: threadID, contact_id: id, is_admin: adminStatus }),
99
- queue_name: 'admin_status',
100
- task_id: index + 1,
101
- failure_count: null
102
- });
103
- });
104
- } else {
93
+ if (typeof ctx.wsReqNumber !== "number") ctx.wsReqNumber = 0;
94
+ if (typeof ctx.wsTaskNumber !== "number") ctx.wsTaskNumber = 0;
95
+
96
+ const adminIDs = getType(adminID) === "Array" ? adminID : [adminID];
97
+ adminIDs.forEach((id) => {
105
98
  tasks.push({
106
- label: '25',
107
- payload: JSON.stringify({ thread_key: threadID, contact_id: adminID, is_admin: adminStatus }),
108
- queue_name: 'admin_status',
109
- task_id: 1,
99
+ label: "25",
100
+ payload: JSON.stringify({ thread_key: threadID, contact_id: id, is_admin: isAdmin }),
101
+ queue_name: "admin_status",
102
+ task_id: ++ctx.wsTaskNumber,
110
103
  failure_count: null
111
104
  });
112
- }
105
+ });
113
106
 
114
107
  const form = {
115
108
  fb_dtsg: ctx.fb_dtsg,
116
- request_id: 1,
109
+ request_id: ++ctx.wsReqNumber,
117
110
  type: 3,
118
- payload: {
119
- version_id: '3816854585040595',
111
+ payload: JSON.stringify({
112
+ version_id: "8798795233522156",
120
113
  tasks: tasks,
121
114
  epoch_id: epochID,
122
115
  data_trace_id: null
123
- },
124
- app_id: '772021112871879'
116
+ }),
117
+ app_id: String(ctx.appID || ctx.mqttAppID || "772021112871879")
125
118
  };
126
119
 
127
- form.payload = JSON.stringify(form.payload);
128
-
129
120
  defaultFuncs
130
121
  .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
131
122
  .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
@@ -135,7 +126,7 @@ module.exports = function (defaultFuncs, api, ctx) {
135
126
  })
136
127
  .catch(err => {
137
128
  utils.error("changeAdminStatus (HTTP)", err);
138
- callback(err);
129
+ callback(err instanceof Error ? err : new Error(String(err && err.message ? err.message : err)));
139
130
  });
140
131
  }
141
132
 
@@ -11,19 +11,27 @@ module.exports = (defaultFuncs, api, ctx) => {
11
11
  rejectFunc = reject;
12
12
  });
13
13
 
14
+ // Detect (threadIDs, callback) — archive omitted
15
+ if (utils.getType(archive) === "Function") {
16
+ callback = archive;
17
+ archive = true;
18
+ }
19
+
14
20
  if (!callback) {
15
21
  callback = (err, result) => {
16
22
  if (err) return rejectFunc(err);
17
23
  resolveFunc(result);
18
24
  };
25
+ } else {
26
+ const _userCb = callback;
27
+ callback = (err, result) => {
28
+ if (err) { _userCb(err); return rejectFunc(err); }
29
+ _userCb(null, result);
30
+ resolveFunc(result);
31
+ };
19
32
  }
20
33
 
21
34
  try {
22
- if (utils.getType(archive) === "Function") {
23
- callback = archive;
24
- archive = true;
25
- }
26
-
27
35
  if (utils.getType(archive) !== "Boolean") {
28
36
  throw new Error("archive parameter must be a boolean");
29
37
  }
@@ -35,7 +43,7 @@ module.exports = (defaultFuncs, api, ctx) => {
35
43
  const form = {
36
44
  should_archive: archive
37
45
  };
38
-
46
+
39
47
  threadIDs.forEach(id => {
40
48
  form[`thread_fbids[${id}]`] = true;
41
49
  });
@@ -47,13 +55,13 @@ module.exports = (defaultFuncs, api, ctx) => {
47
55
  ).then(utils.parseAndCheckLogin(ctx, defaultFuncs));
48
56
 
49
57
  if (res && res.error) {
50
- throw res;
58
+ throw new Error(String(res.error_msg || res.error || "changeArchivedStatus failed"));
51
59
  }
52
60
 
53
61
  callback(null, { success: true });
54
62
  } catch (err) {
55
63
  utils.error("changeArchivedStatus", err);
56
- callback(err);
64
+ callback(err instanceof Error ? err : new Error(String(err && err.message ? err.message : err)));
57
65
  }
58
66
 
59
67
  return returnPromise;
@@ -18,7 +18,7 @@ module.exports = (defaultFuncs, api, ctx) => {
18
18
  {}
19
19
  ).then(utils.parseAndCheckLogin(ctx, defaultFuncs))
20
20
  .then(resData => {
21
- if (resData.error) throw resData;
21
+ if (resData.error) throw new Error(resData.error_msg || resData.errorSummary || String(resData.error));
22
22
  return resData;
23
23
  });
24
24
  }
@@ -89,7 +89,7 @@ module.exports = (defaultFuncs, api, ctx) => {
89
89
  .then(utils.parseAndCheckLogin(ctx, defaultFuncs));
90
90
 
91
91
  if (res.errors) {
92
- throw res;
92
+ throw new Error(JSON.stringify(res.errors));
93
93
  }
94
94
 
95
95
  callback(null, res[0].data.profile_picture_set);
@@ -55,7 +55,7 @@ module.exports = (defaultFuncs, api, ctx) => {
55
55
  .then(utils.parseAndCheckLogin(ctx, defaultFuncs));
56
56
 
57
57
  if (res.errors) {
58
- throw res;
58
+ throw new Error(JSON.stringify(res.errors));
59
59
  }
60
60
 
61
61
  callback(null, { success: true });
@@ -40,7 +40,7 @@ module.exports = (defaultFuncs, api, ctx) => {
40
40
  ).then(utils.parseAndCheckLogin(ctx, defaultFuncs));
41
41
 
42
42
  if (res && res.error) {
43
- throw res;
43
+ throw new Error(res.error_msg || res.errorSummary || String(res.error));
44
44
  }
45
45
 
46
46
  return callback(null, { success: true, blocked: block });
@@ -30,10 +30,22 @@ module.exports = (defaultFuncs, api, ctx) => {
30
30
  if (err) return rejectFunc(err);
31
31
  resolveFunc(result);
32
32
  };
33
+ } else {
34
+ const _userCb = callback;
35
+ callback = (err, result) => {
36
+ if (err) { _userCb(err); return rejectFunc(err); }
37
+ _userCb(null, result);
38
+ resolveFunc(result);
39
+ };
33
40
  }
34
41
 
42
+ // Hoist these before the try so they are accessible in the catch block
43
+ let responseHandled = false;
44
+ let timeout = null;
45
+ let onResponse = null;
46
+
35
47
  try {
36
- if (!ctx.mqttClient) {
48
+ if (!ctx.mqttClient || !ctx.mqttClient.connected) {
37
49
  throw new Error("Not connected to MQTT. Please use listenMqtt first.");
38
50
  }
39
51
 
@@ -48,8 +60,7 @@ module.exports = (defaultFuncs, api, ctx) => {
48
60
  const reqID = ++ctx.wsReqNumber;
49
61
  const taskID = ++ctx.wsTaskNumber;
50
62
 
51
- let responseHandled = false;
52
- const onResponse = (topic, message) => {
63
+ onResponse = (topic, message) => {
53
64
  if (topic !== "/ls_resp" || responseHandled) return;
54
65
  let jsonMsg;
55
66
  try {
@@ -63,16 +74,13 @@ module.exports = (defaultFuncs, api, ctx) => {
63
74
  clearTimeout(timeout);
64
75
  ctx.mqttClient.removeListener("message", onResponse);
65
76
  callback(null, { success: true, response: jsonMsg.payload });
66
- resolveFunc({ success: true, response: jsonMsg.payload });
67
77
  };
68
78
 
69
- const timeout = setTimeout(() => {
79
+ timeout = setTimeout(() => {
70
80
  if (!responseHandled) {
71
81
  responseHandled = true;
72
82
  ctx.mqttClient.removeListener("message", onResponse);
73
- const err = new Error("MQTT request timeout");
74
- callback(err);
75
- rejectFunc(err);
83
+ callback(new Error("MQTT request timeout"));
76
84
  }
77
85
  }, 30000);
78
86
 
@@ -102,7 +110,7 @@ module.exports = (defaultFuncs, api, ctx) => {
102
110
  };
103
111
 
104
112
  const request = {
105
- app_id: "2220391788200892",
113
+ app_id: String(ctx.appID || ctx.mqttAppID || "2220391788200892"),
106
114
  payload: JSON.stringify(mqttPayload),
107
115
  request_id: reqID,
108
116
  type: 3
@@ -116,18 +124,18 @@ module.exports = (defaultFuncs, api, ctx) => {
116
124
  responseHandled = true;
117
125
  clearTimeout(timeout);
118
126
  ctx.mqttClient.removeListener("message", onResponse);
119
- callback(err);
120
- rejectFunc(err);
127
+ callback(err instanceof Error ? err : new Error(String(err)));
121
128
  }
122
129
  });
123
130
  } catch (err) {
124
131
  if (!responseHandled) {
125
132
  responseHandled = true;
126
- clearTimeout(timeout);
127
- ctx.mqttClient.removeListener("message", onResponse);
133
+ if (timeout) clearTimeout(timeout);
134
+ if (onResponse && ctx.mqttClient) {
135
+ try { ctx.mqttClient.removeListener("message", onResponse); } catch (_) {}
136
+ }
128
137
  utils.error("changeGroupImage", err);
129
- callback(err);
130
- rejectFunc(err);
138
+ callback(err instanceof Error ? err : new Error(String(err && err.message ? err.message : err)));
131
139
  }
132
140
  }
133
141
 
@@ -20,7 +20,7 @@ module.exports = (defaultFuncs, api, ctx) => {
20
20
  }
21
21
 
22
22
  try {
23
- if (!ctx.mqttClient) {
23
+ if (!ctx.mqttClient || !ctx.mqttClient.connected) {
24
24
  throw new Error("Not connected to MQTT. Please use listenMqtt first.");
25
25
  }
26
26
 
@@ -17,7 +17,15 @@ module.exports = function (defaultFuncs, api, ctx) {
17
17
  }
18
18
  resolveFunc();
19
19
  };
20
+ } else {
21
+ const _userCb = callback;
22
+ callback = function(err) {
23
+ if (err) { _userCb(err); return rejectFunc(err); }
24
+ _userCb(null);
25
+ resolveFunc();
26
+ };
20
27
  }
28
+
21
29
  const form = {
22
30
  emoji_choice: emoji,
23
31
  thread_or_other_fbid: threadID,
@@ -32,20 +40,18 @@ module.exports = function (defaultFuncs, api, ctx) {
32
40
  .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
33
41
  .then(function (resData) {
34
42
  if (resData.error === 1357031) {
35
- throw {
36
- error:
37
- "Trying to change emoji of a chat that doesn't exist. Have at least one message in the thread before trying to change the emoji.",
38
- };
43
+ throw new Error(
44
+ "Trying to change emoji of a chat that doesn't exist. Have at least one message in the thread before trying to change the emoji."
45
+ );
39
46
  }
40
47
  if (resData.error) {
41
- throw resData;
48
+ throw new Error(String(resData.error_msg || resData.error || "changeThreadEmoji failed"));
42
49
  }
43
-
44
- return callback();
50
+ return callback(null);
45
51
  })
46
52
  .catch(function (err) {
47
53
  utils.error("changeThreadEmoji", err);
48
- return callback(err);
54
+ return callback(err instanceof Error ? err : new Error(String(err && err.message ? err.message : err)));
49
55
  });
50
56
 
51
57
  return returnPromise;
@@ -11,18 +11,26 @@ module.exports = (defaultFuncs, api, ctx) => {
11
11
  rejectFunc = reject;
12
12
  });
13
13
 
14
+ if (utils.getType(groupTitle) === "Function") {
15
+ callback = groupTitle;
16
+ groupTitle = null;
17
+ }
18
+
14
19
  if (!callback) {
15
20
  callback = (err, result) => {
16
21
  if (err) return rejectFunc(err);
17
22
  resolveFunc(result);
18
23
  };
24
+ } else {
25
+ const _userCb = callback;
26
+ callback = (err, result) => {
27
+ if (err) { _userCb(err); return rejectFunc(err); }
28
+ _userCb(null, result);
29
+ resolveFunc(result);
30
+ };
19
31
  }
20
32
 
21
33
  try {
22
- if (utils.getType(groupTitle) === "Function") {
23
- callback = groupTitle;
24
- groupTitle = null;
25
- }
26
34
 
27
35
  if (utils.getType(participantIDs) !== "Array") {
28
36
  throw new Error("createNewGroup: participantIDs should be an array.");
@@ -64,7 +72,7 @@ module.exports = (defaultFuncs, api, ctx) => {
64
72
  .then(utils.parseAndCheckLogin(ctx, defaultFuncs));
65
73
 
66
74
  if (res.errors) {
67
- throw res;
75
+ throw new Error(JSON.stringify(res.errors));
68
76
  }
69
77
 
70
78
  const threadID = res.data.messenger_group_thread_create.thread.thread_key.thread_fbid;
@@ -19,7 +19,7 @@ module.exports = (defaultFuncs, api, ctx) => {
19
19
  }
20
20
 
21
21
  try {
22
- if (!ctx.mqttClient) {
22
+ if (!ctx.mqttClient || !ctx.mqttClient.connected) {
23
23
  throw new Error("Not connected to MQTT. Please use listenMqtt first.");
24
24
  }
25
25
 
@@ -35,6 +35,9 @@ module.exports = (defaultFuncs, api, ctx) => {
35
35
  throw new Error("options must be an array with at least 2 options");
36
36
  }
37
37
 
38
+ if (typeof ctx.wsReqNumber !== 'number') ctx.wsReqNumber = 0;
39
+ if (typeof ctx.wsTaskNumber !== 'number') ctx.wsTaskNumber = 0;
40
+
38
41
  const payload = {
39
42
  epoch_id: utils.generateOfflineThreadingID(),
40
43
  tasks: [
@@ -48,10 +51,10 @@ module.exports = (defaultFuncs, api, ctx) => {
48
51
  sync_group: 1
49
52
  }),
50
53
  queue_name: "poll_creation",
51
- task_id: Math.floor(Math.random() * 1001)
54
+ task_id: ++ctx.wsTaskNumber
52
55
  }
53
56
  ],
54
- version_id: "8768858626531631"
57
+ version_id: "34195258046739157"
55
58
  };
56
59
 
57
60
  const form = JSON.stringify({
@@ -61,8 +64,14 @@ module.exports = (defaultFuncs, api, ctx) => {
61
64
  type: 3
62
65
  });
63
66
 
64
- ctx.mqttClient.publish("/ls_req", form, { qos: 1, retain: false });
65
- callback(null, { success: true });
67
+ ctx.mqttClient.publish("/ls_req", form, { qos: 1, retain: false }, (pubErr) => {
68
+ if (pubErr) {
69
+ utils.error("createPoll", pubErr);
70
+ callback(pubErr instanceof Error ? pubErr : new Error(String(pubErr)));
71
+ } else {
72
+ callback(null, { success: true });
73
+ }
74
+ });
66
75
  } catch (err) {
67
76
  utils.error("createPoll", err);
68
77
  callback(err);
@@ -16,27 +16,30 @@ module.exports = (defaultFuncs, api, ctx) => {
16
16
  if (err) return rejectFunc(err);
17
17
  resolveFunc(result);
18
18
  };
19
+ } else {
20
+ const _userCb = callback;
21
+ callback = (err, result) => {
22
+ if (err) { _userCb(err); return rejectFunc(err); }
23
+ _userCb(null, result);
24
+ resolveFunc(result);
25
+ };
19
26
  }
20
27
 
21
28
  try {
22
- const form = {
23
- message_id: messageID
24
- };
25
-
26
29
  const res = await defaultFuncs.post(
27
30
  "https://www.facebook.com/ajax/mercury/delete_messages.php",
28
31
  ctx.jar,
29
- form
32
+ { message_id: messageID }
30
33
  ).then(utils.parseAndCheckLogin(ctx, defaultFuncs));
31
34
 
32
35
  if (res && res.error) {
33
- throw res;
36
+ throw new Error(String(res.error_msg || res.error || "deleteMessage failed"));
34
37
  }
35
38
 
36
- return callback(null, { success: true });
39
+ callback(null, { success: true });
37
40
  } catch (err) {
38
41
  utils.error("deleteMessage", err);
39
- callback(err);
42
+ callback(err instanceof Error ? err : new Error(String(err && err.message ? err.message : err)));
40
43
  }
41
44
 
42
45
  return returnPromise;
@@ -38,7 +38,7 @@ module.exports = (defaultFuncs, api, ctx) => {
38
38
  ).then(utils.parseAndCheckLogin(ctx, defaultFuncs));
39
39
 
40
40
  if (res && res.error) {
41
- throw res;
41
+ throw new Error(res.error_msg || res.errorSummary || String(res.error));
42
42
  }
43
43
 
44
44
  callback(null, { success: true });