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
|
|
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
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
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 [
|
|
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
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
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
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
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 = (
|
|
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 = (
|
|
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 = (
|
|
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 = (
|
|
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 = (
|
|
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 = (
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
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
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
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
|
|
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: (
|
|
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 = (
|
|
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 = (
|
|
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' : (
|
|
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 = (
|
|
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
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
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
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
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
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
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
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
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
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
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 = (
|
|
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 = ((
|
|
1417
|
+
const options = ((_v = pollOptionsData.optionValues) !== null && _v !== void 0 ? _v : [])
|
|
1192
1418
|
.map((o) => o.option.trim())
|
|
1193
1419
|
.filter(Boolean);
|
|
1194
|
-
const
|
|
1195
|
-
chatGuid,
|
|
1420
|
+
const pollBody = {
|
|
1196
1421
|
options,
|
|
1197
1422
|
};
|
|
1198
1423
|
if (pollTitle)
|
|
1199
|
-
|
|
1200
|
-
const
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
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
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
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
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
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
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
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
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
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];
|