n8n-nodes-imessage 0.3.4 → 0.3.6

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.
@@ -10,6 +10,110 @@ function generateTempGuid() {
10
10
  }
11
11
  return result;
12
12
  }
13
+ function normalizeChatGuid(guid) {
14
+ const trimmed = guid.trim();
15
+ const parts = trimmed.split(';');
16
+ if (parts.length === 3) {
17
+ const addr = parts[2];
18
+ const sep = parts[1];
19
+ return [`iMessage;${sep};${addr}`, `any;${sep};${addr}`];
20
+ }
21
+ if (!trimmed.includes(';')) {
22
+ return [`iMessage;-;${trimmed}`, `any;-;${trimmed}`, trimmed];
23
+ }
24
+ return [trimmed];
25
+ }
26
+ function extractAddressFromChatGuid(chatGuid) {
27
+ const parts = chatGuid.split(';-;');
28
+ if (parts.length === 2 && parts[1])
29
+ return parts[1];
30
+ return undefined;
31
+ }
32
+ function resolveAddress(chatGuid) {
33
+ const direct = extractAddressFromChatGuid(chatGuid);
34
+ if (direct)
35
+ return direct;
36
+ for (const variant of normalizeChatGuid(chatGuid)) {
37
+ const address = extractAddressFromChatGuid(variant);
38
+ if (address)
39
+ return address;
40
+ }
41
+ return undefined;
42
+ }
43
+ function chatGuidFromResponse(data) {
44
+ if (!data || typeof data !== 'object')
45
+ return undefined;
46
+ const record = data;
47
+ if (typeof record.guid === 'string')
48
+ return record.guid;
49
+ if (record.chat && typeof record.chat === 'object') {
50
+ const guid = record.chat.guid;
51
+ if (typeof guid === 'string')
52
+ return guid;
53
+ }
54
+ return undefined;
55
+ }
56
+ function isNotFoundError(error) {
57
+ if (isChatNotExistError(error))
58
+ return true;
59
+ if (!error || typeof error !== 'object')
60
+ return false;
61
+ const err = error;
62
+ if (err.statusCode === 404 || err.httpCode === '404')
63
+ return true;
64
+ const text = [err.message, err.description]
65
+ .filter((part) => typeof part === 'string')
66
+ .join(' ')
67
+ .toLowerCase();
68
+ return (text.includes('404') ||
69
+ text.includes('not found') ||
70
+ text.includes('could not be found'));
71
+ }
72
+ function parseTimestamp(value) {
73
+ if (!value)
74
+ return undefined;
75
+ const time = new Date(value).getTime();
76
+ return Number.isNaN(time) ? undefined : time;
77
+ }
78
+ function buildMessageQueryBody(params) {
79
+ var _a;
80
+ const body = {};
81
+ if (params.chatGuid)
82
+ body.chatGuid = params.chatGuid;
83
+ if (params.limit !== undefined)
84
+ body.limit = params.limit;
85
+ if (params.sort)
86
+ body.sort = params.sort;
87
+ if (params.with)
88
+ body.with = params.with;
89
+ if ((_a = params.where) === null || _a === void 0 ? void 0 : _a.length)
90
+ body.where = params.where;
91
+ const after = parseTimestamp(params.after);
92
+ const before = parseTimestamp(params.before);
93
+ if (after !== undefined)
94
+ body.after = after;
95
+ if (before !== undefined)
96
+ body.before = before;
97
+ return body;
98
+ }
99
+ function isChatNotExistError(error) {
100
+ var _a;
101
+ if (!error || typeof error !== 'object')
102
+ return false;
103
+ const err = error;
104
+ const text = [err.message, err.description, (_a = err.cause) === null || _a === void 0 ? void 0 : _a.message]
105
+ .filter((part) => typeof part === 'string')
106
+ .join(' ')
107
+ .toLowerCase();
108
+ return text.includes('chat does not exist') || text.includes('chat not found');
109
+ }
110
+ function isInboundMessage(message) {
111
+ if (message.isFromMe === false)
112
+ return true;
113
+ if (message.is_from_me === 0 || message.is_from_me === false)
114
+ return true;
115
+ return false;
116
+ }
13
117
  class PhotonIMessage {
14
118
  constructor() {
15
119
  this.description = {
@@ -817,21 +921,110 @@ class PhotonIMessage {
817
921
  };
818
922
  }
819
923
  async execute() {
820
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1;
924
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
821
925
  const items = this.getInputData();
822
926
  const returnData = [];
823
927
  const resource = this.getNodeParameter('resource', 0);
824
928
  const operation = this.getNodeParameter('operation', 0);
825
929
  const credentials = await this.getCredentials('photonIMessageApi');
826
930
  const baseUrl = credentials.serverUrl.replace(/\/+$/, '');
827
- const normalizeChatGuid = (guid) => {
828
- const parts = guid.split(';');
829
- if (parts.length === 3) {
830
- const addr = parts[2];
831
- const sep = parts[1];
832
- return [`iMessage;${sep};${addr}`, `any;${sep};${addr}`];
931
+ const enforceInboundFirstPolicy = async (chatGuid, itemIndex) => {
932
+ var _a;
933
+ const guids = normalizeChatGuid(chatGuid);
934
+ const queryErrors = [];
935
+ for (const variant of guids) {
936
+ try {
937
+ const checkResponse = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
938
+ method: 'POST',
939
+ url: `${baseUrl}/api/v1/message/query`,
940
+ body: {
941
+ chatGuid: variant,
942
+ limit: 25,
943
+ sort: 'DESC',
944
+ },
945
+ json: true,
946
+ });
947
+ const messages = checkResponse.data;
948
+ if (Array.isArray(messages) &&
949
+ messages.some((message) => isInboundMessage(message))) {
950
+ return;
951
+ }
952
+ }
953
+ catch (error) {
954
+ queryErrors.push((_a = error.message) !== null && _a !== void 0 ? _a : String(error));
955
+ }
956
+ }
957
+ if (queryErrors.length === guids.length) {
958
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Could not verify inbound-first policy: the message query API failed for every chat GUID variant.', {
959
+ itemIndex,
960
+ description: `Check that Server URL is your advanced-imessage-kit runtime (for example https://xxx.imsgd.photon.codes) ` +
961
+ `and that chatGuid uses service;-;address format (for example iMessage;-;+15551234567). ` +
962
+ `Last error: ${queryErrors[queryErrors.length - 1]}`,
963
+ });
964
+ }
965
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Inbound-first policy: this contact has not messaged your number yet. To prevent spam, messages can only be sent to contacts who have initiated a conversation first.', { itemIndex });
966
+ };
967
+ const createChatForGuid = async (chatGuid, message) => {
968
+ var _a, _b;
969
+ const address = resolveAddress(chatGuid);
970
+ if (!address) {
971
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Could not extract a recipient address from chatGuid "${chatGuid}". Use iMessage;-;+15551234567 or a bare phone/email.`);
972
+ }
973
+ const createResponse = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
974
+ method: 'POST',
975
+ url: `${baseUrl}/api/v1/chat/new`,
976
+ body: {
977
+ addresses: [address],
978
+ method: 'private-api',
979
+ ...(message ? { message } : {}),
980
+ },
981
+ json: true,
982
+ });
983
+ const data = (_a = createResponse.data) !== null && _a !== void 0 ? _a : createResponse;
984
+ return (_b = chatGuidFromResponse(data)) !== null && _b !== void 0 ? _b : normalizeChatGuid(chatGuid)[0];
985
+ };
986
+ const withChatGuidVariants = async (chatGuid, request) => {
987
+ const variants = normalizeChatGuid(chatGuid);
988
+ let lastError;
989
+ for (const variant of variants) {
990
+ try {
991
+ return await request(variant);
992
+ }
993
+ catch (error) {
994
+ lastError = error;
995
+ if (!isNotFoundError(error)) {
996
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
997
+ }
998
+ }
999
+ }
1000
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), lastError);
1001
+ };
1002
+ const queryMessagesForChatGuids = async (guids, queryParams) => {
1003
+ let lastError;
1004
+ for (const variant of guids) {
1005
+ try {
1006
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1007
+ method: 'POST',
1008
+ url: `${baseUrl}/api/v1/message/query`,
1009
+ body: buildMessageQueryBody({ ...queryParams, chatGuid: variant }),
1010
+ json: true,
1011
+ });
1012
+ const batch = response.data;
1013
+ if (Array.isArray(batch) && batch.length > 0) {
1014
+ return batch;
1015
+ }
1016
+ }
1017
+ catch (error) {
1018
+ lastError = error;
1019
+ if (!isNotFoundError(error)) {
1020
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
1021
+ }
1022
+ }
1023
+ }
1024
+ if (lastError) {
1025
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), lastError);
833
1026
  }
834
- return [guid];
1027
+ return [];
835
1028
  };
836
1029
  for (let i = 0; i < items.length; i++) {
837
1030
  try {
@@ -839,6 +1032,7 @@ class PhotonIMessage {
839
1032
  if (resource === 'message') {
840
1033
  if (operation === 'sendMessage') {
841
1034
  const chatGuid = this.getNodeParameter('chatGuid', i);
1035
+ await enforceInboundFirstPolicy(chatGuid, i);
842
1036
  const message = this.getNodeParameter('message', i);
843
1037
  const additionalFields = this.getNodeParameter('additionalFields', i);
844
1038
  const body = {
@@ -853,16 +1047,32 @@ class PhotonIMessage {
853
1047
  body.effectId = additionalFields.effectId;
854
1048
  if (additionalFields.selectedMessageGuid)
855
1049
  body.selectedMessageGuid = additionalFields.selectedMessageGuid;
856
- const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
857
- method: 'POST',
858
- url: `${baseUrl}/api/v1/message/text`,
859
- body,
860
- json: true,
861
- });
862
- responseData = (_a = response.data) !== null && _a !== void 0 ? _a : response;
1050
+ try {
1051
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1052
+ method: 'POST',
1053
+ url: `${baseUrl}/api/v1/message/text`,
1054
+ body,
1055
+ json: true,
1056
+ });
1057
+ responseData = (_a = response.data) !== null && _a !== void 0 ? _a : response;
1058
+ }
1059
+ catch (error) {
1060
+ if (!isChatNotExistError(error)) {
1061
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), error, { itemIndex: i });
1062
+ }
1063
+ const resolvedGuid = await createChatForGuid(chatGuid, message);
1064
+ const retryResponse = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1065
+ method: 'POST',
1066
+ url: `${baseUrl}/api/v1/message/text`,
1067
+ body: { ...body, chatGuid: resolvedGuid },
1068
+ json: true,
1069
+ });
1070
+ responseData = (_b = retryResponse.data) !== null && _b !== void 0 ? _b : retryResponse;
1071
+ }
863
1072
  }
864
1073
  else if (operation === 'sendAttachment') {
865
1074
  const chatGuid = this.getNodeParameter('chatGuid', i);
1075
+ await enforceInboundFirstPolicy(chatGuid, i);
866
1076
  const filePath = this.getNodeParameter('filePath', i);
867
1077
  const additionalFields = this.getNodeParameter('attachmentAdditionalFields', i);
868
1078
  const body = {
@@ -873,31 +1083,46 @@ class PhotonIMessage {
873
1083
  body.name = additionalFields.fileName;
874
1084
  if (additionalFields.isAudioMessage)
875
1085
  body.isAudioMessage = additionalFields.isAudioMessage;
876
- const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
877
- method: 'POST',
878
- url: `${baseUrl}/api/v1/message/attachment`,
879
- body,
880
- json: true,
881
- });
882
- responseData = (_b = response.data) !== null && _b !== void 0 ? _b : response;
1086
+ try {
1087
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1088
+ method: 'POST',
1089
+ url: `${baseUrl}/api/v1/message/attachment`,
1090
+ body,
1091
+ json: true,
1092
+ });
1093
+ responseData = (_c = response.data) !== null && _c !== void 0 ? _c : response;
1094
+ }
1095
+ catch (error) {
1096
+ if (!isChatNotExistError(error)) {
1097
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), error, { itemIndex: i });
1098
+ }
1099
+ const resolvedGuid = await createChatForGuid(chatGuid);
1100
+ const retryResponse = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1101
+ method: 'POST',
1102
+ url: `${baseUrl}/api/v1/message/attachment`,
1103
+ body: { ...body, chatGuid: resolvedGuid },
1104
+ json: true,
1105
+ });
1106
+ responseData = (_d = retryResponse.data) !== null && _d !== void 0 ? _d : retryResponse;
1107
+ }
883
1108
  }
884
1109
  else if (operation === 'unsendMessage') {
885
1110
  const messageGuid = this.getNodeParameter('messageGuid', i);
886
1111
  const unsendFields = this.getNodeParameter('unsendAdditionalFields', i, {});
887
- const partIndex = (_c = unsendFields.unsendPartIndex) !== null && _c !== void 0 ? _c : 0;
1112
+ const partIndex = (_e = unsendFields.unsendPartIndex) !== null && _e !== void 0 ? _e : 0;
888
1113
  const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
889
1114
  method: 'POST',
890
1115
  url: `${baseUrl}/api/v1/message/${encodeURIComponent(messageGuid)}/unsend`,
891
1116
  body: { partIndex },
892
1117
  json: true,
893
1118
  });
894
- responseData = (_d = response.data) !== null && _d !== void 0 ? _d : response;
1119
+ responseData = (_f = response.data) !== null && _f !== void 0 ? _f : response;
895
1120
  }
896
1121
  else if (operation === 'editMessage') {
897
1122
  const messageGuid = this.getNodeParameter('messageGuid', i);
898
1123
  const editedMessage = this.getNodeParameter('editedMessage', i);
899
1124
  const editFields = this.getNodeParameter('editAdditionalFields', i, {});
900
- const partIndex = (_e = editFields.editPartIndex) !== null && _e !== void 0 ? _e : 0;
1125
+ const partIndex = (_g = editFields.editPartIndex) !== null && _g !== void 0 ? _g : 0;
901
1126
  const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
902
1127
  method: 'POST',
903
1128
  url: `${baseUrl}/api/v1/message/${encodeURIComponent(messageGuid)}/edit`,
@@ -908,7 +1133,7 @@ class PhotonIMessage {
908
1133
  },
909
1134
  json: true,
910
1135
  });
911
- responseData = (_f = response.data) !== null && _f !== void 0 ? _f : response;
1136
+ responseData = (_h = response.data) !== null && _h !== void 0 ? _h : response;
912
1137
  }
913
1138
  else if (operation === 'downloadAttachment') {
914
1139
  const attachmentGuid = this.getNodeParameter('attachmentGuid', i);
@@ -927,26 +1152,29 @@ class PhotonIMessage {
927
1152
  json: true,
928
1153
  encoding: 'arraybuffer',
929
1154
  });
930
- responseData = (_g = response.data) !== null && _g !== void 0 ? _g : response;
1155
+ responseData = (_j = response.data) !== null && _j !== void 0 ? _j : response;
931
1156
  }
932
1157
  else if (operation === 'reactToMessage') {
933
1158
  const chatGuid = this.getNodeParameter('chatGuid', i);
934
1159
  const messageGuid = this.getNodeParameter('messageGuid', i);
935
1160
  const reaction = this.getNodeParameter('reaction', i);
936
1161
  const reactFields = this.getNodeParameter('reactAdditionalFields', i, {});
937
- const partIndex = (_h = reactFields.partIndex) !== null && _h !== void 0 ? _h : 0;
938
- const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
939
- method: 'POST',
940
- url: `${baseUrl}/api/v1/message/react`,
941
- body: {
942
- chatGuid,
943
- selectedMessageGuid: messageGuid,
944
- reaction,
945
- partIndex,
946
- },
947
- json: true,
1162
+ const partIndex = (_k = reactFields.partIndex) !== null && _k !== void 0 ? _k : 0;
1163
+ responseData = await withChatGuidVariants(chatGuid, async (variant) => {
1164
+ var _a;
1165
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1166
+ method: 'POST',
1167
+ url: `${baseUrl}/api/v1/message/react`,
1168
+ body: {
1169
+ chatGuid: variant,
1170
+ selectedMessageGuid: messageGuid,
1171
+ reaction,
1172
+ partIndex,
1173
+ },
1174
+ json: true,
1175
+ });
1176
+ return (_a = response.data) !== null && _a !== void 0 ? _a : response;
948
1177
  });
949
- responseData = (_j = response.data) !== null && _j !== void 0 ? _j : response;
950
1178
  }
951
1179
  else if (operation === 'searchMessages') {
952
1180
  const query = this.getNodeParameter('query', i);
@@ -959,25 +1187,28 @@ class PhotonIMessage {
959
1187
  args: { text: `%${query}%` },
960
1188
  },
961
1189
  ];
1190
+ let messages = [];
962
1191
  if (additionalFields.chatGuid) {
963
- const guids = normalizeChatGuid(additionalFields.chatGuid);
964
- const guidPlaceholders = guids.map((_, idx) => `:guid${idx}`).join(', ');
965
- const guidArgs = {};
966
- guids.forEach((g, idx) => { guidArgs[`guid${idx}`] = g; });
967
- where.push({ statement: `chat.guid IN (${guidPlaceholders})`, args: guidArgs });
1192
+ messages = await queryMessagesForChatGuids(normalizeChatGuid(additionalFields.chatGuid), {
1193
+ where,
1194
+ limit,
1195
+ sort: (_l = additionalFields.sort) !== null && _l !== void 0 ? _l : 'DESC',
1196
+ });
1197
+ }
1198
+ else {
1199
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1200
+ method: 'POST',
1201
+ url: `${baseUrl}/api/v1/message/query`,
1202
+ body: buildMessageQueryBody({
1203
+ where,
1204
+ limit,
1205
+ sort: (_m = additionalFields.sort) !== null && _m !== void 0 ? _m : 'DESC',
1206
+ }),
1207
+ json: true,
1208
+ });
1209
+ const batch = (_o = response.data) !== null && _o !== void 0 ? _o : response;
1210
+ messages = Array.isArray(batch) ? batch : [];
968
1211
  }
969
- const body = {
970
- where,
971
- limit,
972
- sort: (_k = additionalFields.sort) !== null && _k !== void 0 ? _k : 'DESC',
973
- };
974
- const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
975
- method: 'POST',
976
- url: `${baseUrl}/api/v1/message/query`,
977
- body,
978
- json: true,
979
- });
980
- const messages = (_l = response.data) !== null && _l !== void 0 ? _l : response;
981
1212
  if (Array.isArray(messages)) {
982
1213
  for (const msg of messages) {
983
1214
  returnData.push({
@@ -995,40 +1226,13 @@ class PhotonIMessage {
995
1226
  const limit = returnAll ? 1000 : this.getNodeParameter('limit', i, 50);
996
1227
  const additionalFields = this.getNodeParameter('getMessagesAdditionalFields', i);
997
1228
  const guids = normalizeChatGuid(chatGuid);
998
- const guidPlaceholders = guids.map((_, idx) => `:guid${idx}`).join(', ');
999
- const guidArgs = {};
1000
- guids.forEach((g, idx) => { guidArgs[`guid${idx}`] = g; });
1001
- const where = [
1002
- {
1003
- statement: `chat.guid IN (${guidPlaceholders})`,
1004
- args: guidArgs,
1005
- },
1006
- ];
1007
- if (additionalFields.after) {
1008
- const afterTime = new Date(additionalFields.after).getTime();
1009
- if (!Number.isNaN(afterTime)) {
1010
- where.push({ statement: 'message.date > :after', args: { after: afterTime } });
1011
- }
1012
- }
1013
- if (additionalFields.before) {
1014
- const beforeTime = new Date(additionalFields.before).getTime();
1015
- if (!Number.isNaN(beforeTime)) {
1016
- where.push({ statement: 'message.date < :before', args: { before: beforeTime } });
1017
- }
1018
- }
1019
- const body = {
1020
- where,
1229
+ const messages = await queryMessagesForChatGuids(guids, {
1021
1230
  limit,
1022
- sort: (_m = additionalFields.sort) !== null && _m !== void 0 ? _m : 'DESC',
1231
+ sort: (_p = additionalFields.sort) !== null && _p !== void 0 ? _p : 'DESC',
1232
+ after: additionalFields.after,
1233
+ before: additionalFields.before,
1023
1234
  with: ['chat', 'handle', 'attachment'],
1024
- };
1025
- const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1026
- method: 'POST',
1027
- url: `${baseUrl}/api/v1/message/query`,
1028
- body,
1029
- json: true,
1030
1235
  });
1031
- const messages = (_o = response.data) !== null && _o !== void 0 ? _o : response;
1032
1236
  if (Array.isArray(messages)) {
1033
1237
  for (const msg of messages) {
1034
1238
  returnData.push({
@@ -1059,16 +1263,16 @@ class PhotonIMessage {
1059
1263
  },
1060
1264
  json: true,
1061
1265
  });
1062
- const chats = (_p = response.data) !== null && _p !== void 0 ? _p : response;
1266
+ const chats = (_q = response.data) !== null && _q !== void 0 ? _q : response;
1063
1267
  if (Array.isArray(chats)) {
1064
1268
  for (const chat of chats) {
1065
1269
  const participants = chat.participants;
1066
1270
  const isGroup = chat.style === 43;
1067
- const participantAddresses = (_q = participants === null || participants === void 0 ? void 0 : participants.map((p) => p.address)) !== null && _q !== void 0 ? _q : [];
1271
+ const participantAddresses = (_r = participants === null || participants === void 0 ? void 0 : participants.map((p) => p.address)) !== null && _r !== void 0 ? _r : [];
1068
1272
  returnData.push({
1069
1273
  json: {
1070
1274
  ...chat,
1071
- displayName: chat.displayName || (isGroup ? 'Group Chat' : (_r = participantAddresses[0]) !== null && _r !== void 0 ? _r : ''),
1275
+ displayName: chat.displayName || (isGroup ? 'Group Chat' : (_s = participantAddresses[0]) !== null && _s !== void 0 ? _s : ''),
1072
1276
  isGroup,
1073
1277
  participantAddresses,
1074
1278
  participantCount: participantAddresses.length,
@@ -1096,32 +1300,41 @@ class PhotonIMessage {
1096
1300
  body,
1097
1301
  json: true,
1098
1302
  });
1099
- responseData = (_s = response.data) !== null && _s !== void 0 ? _s : response;
1303
+ responseData = (_t = response.data) !== null && _t !== void 0 ? _t : response;
1100
1304
  }
1101
1305
  else if (operation === 'markChatRead') {
1102
1306
  const chatGuid = this.getNodeParameter('chatGuid', i);
1103
- const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1104
- method: 'POST',
1105
- url: `${baseUrl}/api/v1/chat/${encodeURIComponent(chatGuid)}/read`,
1106
- json: true,
1307
+ responseData = await withChatGuidVariants(chatGuid, async (variant) => {
1308
+ var _a;
1309
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1310
+ method: 'POST',
1311
+ url: `${baseUrl}/api/v1/chat/${encodeURIComponent(variant)}/read`,
1312
+ json: true,
1313
+ });
1314
+ return (_a = response.data) !== null && _a !== void 0 ? _a : response;
1107
1315
  });
1108
- responseData = (_t = response.data) !== null && _t !== void 0 ? _t : response;
1109
1316
  }
1110
1317
  else if (operation === 'startTyping') {
1111
1318
  const chatGuid = this.getNodeParameter('chatGuid', i);
1112
- await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1113
- method: 'POST',
1114
- url: `${baseUrl}/api/v1/chat/${encodeURIComponent(chatGuid)}/typing`,
1115
- json: true,
1319
+ await withChatGuidVariants(chatGuid, async (variant) => {
1320
+ await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1321
+ method: 'POST',
1322
+ url: `${baseUrl}/api/v1/chat/${encodeURIComponent(variant)}/typing`,
1323
+ json: true,
1324
+ });
1325
+ return variant;
1116
1326
  });
1117
1327
  responseData = { typing: true, chatGuid };
1118
1328
  }
1119
1329
  else if (operation === 'stopTyping') {
1120
1330
  const chatGuid = this.getNodeParameter('chatGuid', i);
1121
- await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1122
- method: 'DELETE',
1123
- url: `${baseUrl}/api/v1/chat/${encodeURIComponent(chatGuid)}/typing`,
1124
- json: true,
1331
+ await withChatGuidVariants(chatGuid, async (variant) => {
1332
+ await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1333
+ method: 'DELETE',
1334
+ url: `${baseUrl}/api/v1/chat/${encodeURIComponent(variant)}/typing`,
1335
+ json: true,
1336
+ });
1337
+ return variant;
1125
1338
  });
1126
1339
  responseData = { typing: false, chatGuid };
1127
1340
  }
@@ -1129,6 +1342,7 @@ class PhotonIMessage {
1129
1342
  else if (resource === 'scheduledMessage') {
1130
1343
  if (operation === 'createScheduledMessage') {
1131
1344
  const chatGuid = this.getNodeParameter('chatGuid', i);
1345
+ await enforceInboundFirstPolicy(chatGuid, i);
1132
1346
  const message = this.getNodeParameter('message', i);
1133
1347
  const sendAt = this.getNodeParameter('sendAt', i);
1134
1348
  const scheduleType = this.getNodeParameter('scheduleType', i);
@@ -1138,22 +1352,34 @@ class PhotonIMessage {
1138
1352
  schedule.intervalType = scheduleType;
1139
1353
  schedule.interval = 1;
1140
1354
  }
1141
- const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1142
- method: 'POST',
1143
- url: `${baseUrl}/api/v1/message/schedule`,
1144
- body: {
1145
- type: 'send-message',
1146
- payload: {
1147
- chatGuid,
1148
- message,
1149
- method: 'private-api',
1355
+ const scheduleRequest = async (resolvedGuid) => {
1356
+ var _a;
1357
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1358
+ method: 'POST',
1359
+ url: `${baseUrl}/api/v1/message/schedule`,
1360
+ body: {
1361
+ type: 'send-message',
1362
+ payload: {
1363
+ chatGuid: resolvedGuid,
1364
+ message,
1365
+ method: 'private-api',
1366
+ },
1367
+ scheduledFor: new Date(sendAt).getTime(),
1368
+ schedule,
1150
1369
  },
1151
- scheduledFor: new Date(sendAt).getTime(),
1152
- schedule,
1153
- },
1154
- json: true,
1155
- });
1156
- responseData = (_u = response.data) !== null && _u !== void 0 ? _u : response;
1370
+ json: true,
1371
+ });
1372
+ return (_a = response.data) !== null && _a !== void 0 ? _a : response;
1373
+ };
1374
+ try {
1375
+ responseData = await withChatGuidVariants(chatGuid, scheduleRequest);
1376
+ }
1377
+ catch (error) {
1378
+ if (!isChatNotExistError(error) && !isNotFoundError(error)) {
1379
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), error, { itemIndex: i });
1380
+ }
1381
+ responseData = await scheduleRequest(await createChatForGuid(chatGuid));
1382
+ }
1157
1383
  }
1158
1384
  else if (operation === 'listScheduledMessages') {
1159
1385
  const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
@@ -1161,7 +1387,7 @@ class PhotonIMessage {
1161
1387
  url: `${baseUrl}/api/v1/message/schedule`,
1162
1388
  json: true,
1163
1389
  });
1164
- const schedules = (_v = response.data) !== null && _v !== void 0 ? _v : response;
1390
+ const schedules = (_u = response.data) !== null && _u !== void 0 ? _u : response;
1165
1391
  if (Array.isArray(schedules)) {
1166
1392
  for (const sched of schedules) {
1167
1393
  returnData.push({
@@ -1188,70 +1414,93 @@ class PhotonIMessage {
1188
1414
  const chatGuid = this.getNodeParameter('chatGuid', i);
1189
1415
  const pollTitle = this.getNodeParameter('pollTitle', i, '');
1190
1416
  const pollOptionsData = this.getNodeParameter('pollOptions', i);
1191
- const options = ((_w = pollOptionsData.optionValues) !== null && _w !== void 0 ? _w : [])
1417
+ const options = ((_v = pollOptionsData.optionValues) !== null && _v !== void 0 ? _v : [])
1192
1418
  .map((o) => o.option.trim())
1193
1419
  .filter(Boolean);
1194
- const body = {
1195
- chatGuid,
1420
+ const pollBody = {
1196
1421
  options,
1197
1422
  };
1198
1423
  if (pollTitle)
1199
- body.title = pollTitle;
1200
- const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1201
- method: 'POST',
1202
- url: `${baseUrl}/api/v1/message/poll/create`,
1203
- body,
1204
- json: true,
1205
- });
1206
- responseData = (_x = response.data) !== null && _x !== void 0 ? _x : response;
1424
+ pollBody.title = pollTitle;
1425
+ const createPollRequest = async (resolvedGuid) => {
1426
+ var _a;
1427
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1428
+ method: 'POST',
1429
+ url: `${baseUrl}/api/v1/message/poll/create`,
1430
+ body: { ...pollBody, chatGuid: resolvedGuid },
1431
+ json: true,
1432
+ });
1433
+ return (_a = response.data) !== null && _a !== void 0 ? _a : response;
1434
+ };
1435
+ try {
1436
+ responseData = await withChatGuidVariants(chatGuid, createPollRequest);
1437
+ }
1438
+ catch (error) {
1439
+ if (!isChatNotExistError(error) && !isNotFoundError(error)) {
1440
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), error, { itemIndex: i });
1441
+ }
1442
+ responseData = await createPollRequest(await createChatForGuid(chatGuid));
1443
+ }
1207
1444
  }
1208
1445
  else if (operation === 'vote') {
1209
1446
  const chatGuid = this.getNodeParameter('chatGuid', i);
1210
1447
  const pollMessageGuid = this.getNodeParameter('pollMessageGuid', i);
1211
1448
  const optionIdentifier = this.getNodeParameter('optionIdentifier', i);
1212
- const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1213
- method: 'POST',
1214
- url: `${baseUrl}/api/v1/message/poll/vote`,
1215
- body: { chatGuid, pollMessageGuid, optionIdentifier },
1216
- json: true,
1449
+ responseData = await withChatGuidVariants(chatGuid, async (variant) => {
1450
+ var _a;
1451
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1452
+ method: 'POST',
1453
+ url: `${baseUrl}/api/v1/message/poll/vote`,
1454
+ body: { chatGuid: variant, pollMessageGuid, optionIdentifier },
1455
+ json: true,
1456
+ });
1457
+ return (_a = response.data) !== null && _a !== void 0 ? _a : response;
1217
1458
  });
1218
- responseData = (_y = response.data) !== null && _y !== void 0 ? _y : response;
1219
1459
  }
1220
1460
  else if (operation === 'unvote') {
1221
1461
  const chatGuid = this.getNodeParameter('chatGuid', i);
1222
1462
  const pollMessageGuid = this.getNodeParameter('pollMessageGuid', i);
1223
1463
  const optionIdentifier = this.getNodeParameter('optionIdentifier', i);
1224
- const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1225
- method: 'POST',
1226
- url: `${baseUrl}/api/v1/message/poll/unvote`,
1227
- body: { chatGuid, pollMessageGuid, optionIdentifier },
1228
- json: true,
1464
+ responseData = await withChatGuidVariants(chatGuid, async (variant) => {
1465
+ var _a;
1466
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1467
+ method: 'POST',
1468
+ url: `${baseUrl}/api/v1/message/poll/unvote`,
1469
+ body: { chatGuid: variant, pollMessageGuid, optionIdentifier },
1470
+ json: true,
1471
+ });
1472
+ return (_a = response.data) !== null && _a !== void 0 ? _a : response;
1229
1473
  });
1230
- responseData = (_z = response.data) !== null && _z !== void 0 ? _z : response;
1231
1474
  }
1232
1475
  else if (operation === 'addOption') {
1233
1476
  const chatGuid = this.getNodeParameter('chatGuid', i);
1234
1477
  const pollMessageGuid = this.getNodeParameter('pollMessageGuid', i);
1235
1478
  const optionText = this.getNodeParameter('optionText', i);
1236
- const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1237
- method: 'POST',
1238
- url: `${baseUrl}/api/v1/message/poll/add-option`,
1239
- body: { chatGuid, pollMessageGuid, optionText },
1240
- json: true,
1479
+ responseData = await withChatGuidVariants(chatGuid, async (variant) => {
1480
+ var _a;
1481
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1482
+ method: 'POST',
1483
+ url: `${baseUrl}/api/v1/message/poll/add-option`,
1484
+ body: { chatGuid: variant, pollMessageGuid, optionText },
1485
+ json: true,
1486
+ });
1487
+ return (_a = response.data) !== null && _a !== void 0 ? _a : response;
1241
1488
  });
1242
- responseData = (_0 = response.data) !== null && _0 !== void 0 ? _0 : response;
1243
1489
  }
1244
1490
  }
1245
1491
  else if (resource === 'contact') {
1246
1492
  if (operation === 'shareContactCard') {
1247
1493
  const chatGuid = this.getNodeParameter('chatGuid', i);
1248
- const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1249
- method: 'POST',
1250
- url: `${baseUrl}/api/v1/contact/share`,
1251
- body: { chatGuid },
1252
- json: true,
1494
+ responseData = await withChatGuidVariants(chatGuid, async (variant) => {
1495
+ var _a;
1496
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'photonIMessageApi', {
1497
+ method: 'POST',
1498
+ url: `${baseUrl}/api/v1/contact/share`,
1499
+ body: { chatGuid: variant },
1500
+ json: true,
1501
+ });
1502
+ return (_a = response.data) !== null && _a !== void 0 ? _a : response;
1253
1503
  });
1254
- responseData = (_1 = response.data) !== null && _1 !== void 0 ? _1 : response;
1255
1504
  }
1256
1505
  }
1257
1506
  else if (resource === 'handle') {
@@ -1285,7 +1534,7 @@ class PhotonIMessage {
1285
1534
  });
1286
1535
  continue;
1287
1536
  }
1288
- throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
1537
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), error, { itemIndex: i });
1289
1538
  }
1290
1539
  }
1291
1540
  return [returnData];