n8n-nodes-nextcloud-talk 1.0.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 (35) hide show
  1. package/README.md +156 -0
  2. package/dist/credentials/NextcloudApi.credentials.d.ts +10 -0
  3. package/dist/credentials/NextcloudApi.credentials.js +60 -0
  4. package/dist/credentials/NextcloudApi.credentials.js.map +1 -0
  5. package/dist/icons/nextcloud-talk.dark.png +0 -0
  6. package/dist/icons/nextcloud-talk.png +0 -0
  7. package/dist/icons/nextcloud.dark.svg +15 -0
  8. package/dist/icons/nextcloud.svg +15 -0
  9. package/dist/nodes/NextcloudTalk/NextcloudTalk.node.d.ts +5 -0
  10. package/dist/nodes/NextcloudTalk/NextcloudTalk.node.js +380 -0
  11. package/dist/nodes/NextcloudTalk/NextcloudTalk.node.js.map +1 -0
  12. package/dist/nodes/NextcloudTalk/NextcloudTalkTrigger.node.d.ts +5 -0
  13. package/dist/nodes/NextcloudTalk/NextcloudTalkTrigger.node.js +102 -0
  14. package/dist/nodes/NextcloudTalk/NextcloudTalkTrigger.node.js.map +1 -0
  15. package/dist/nodes/NextcloudTalk/descriptions/conversation.description.d.ts +3 -0
  16. package/dist/nodes/NextcloudTalk/descriptions/conversation.description.js +248 -0
  17. package/dist/nodes/NextcloudTalk/descriptions/conversation.description.js.map +1 -0
  18. package/dist/nodes/NextcloudTalk/descriptions/message.description.d.ts +3 -0
  19. package/dist/nodes/NextcloudTalk/descriptions/message.description.js +212 -0
  20. package/dist/nodes/NextcloudTalk/descriptions/message.description.js.map +1 -0
  21. package/dist/nodes/NextcloudTalk/descriptions/participant.description.d.ts +3 -0
  22. package/dist/nodes/NextcloudTalk/descriptions/participant.description.js +100 -0
  23. package/dist/nodes/NextcloudTalk/descriptions/participant.description.js.map +1 -0
  24. package/dist/nodes/NextcloudTalk/descriptions/poll.description.d.ts +3 -0
  25. package/dist/nodes/NextcloudTalk/descriptions/poll.description.js +165 -0
  26. package/dist/nodes/NextcloudTalk/descriptions/poll.description.js.map +1 -0
  27. package/dist/nodes/NextcloudTalk/descriptions/reaction.description.d.ts +3 -0
  28. package/dist/nodes/NextcloudTalk/descriptions/reaction.description.js +82 -0
  29. package/dist/nodes/NextcloudTalk/descriptions/reaction.description.js.map +1 -0
  30. package/dist/nodes/NextcloudTalk/helpers.d.ts +5 -0
  31. package/dist/nodes/NextcloudTalk/helpers.js +28 -0
  32. package/dist/nodes/NextcloudTalk/helpers.js.map +1 -0
  33. package/dist/package.json +61 -0
  34. package/dist/tsconfig.tsbuildinfo +1 -0
  35. package/package.json +60 -0
package/README.md ADDED
@@ -0,0 +1,156 @@
1
+ # n8n-nodes-nextcloud-talk
2
+
3
+ An [n8n](https://n8n.io/) community node for [Nextcloud Talk](https://nextcloud.com/talk/).
4
+
5
+ **Table of contents**
6
+
7
+ - [Installation](#installation)
8
+ - [Setting up a bot account](#setting-up-a-bot-account)
9
+ - [Features](#features)
10
+ - [Development](#development)
11
+
12
+ ## Installation
13
+
14
+ Follow the [community node installation guide](https://docs.n8n.io/integrations/community-nodes/installation/) in the n8n documentation.
15
+
16
+ The package name is `n8n-nodes-nextcloud-talk`.
17
+
18
+ ## Setting up a bot account
19
+
20
+ This node authenticates as a Nextcloud user, so the recommended approach is to create a **dedicated user account** that acts as the bot. This keeps bot activity separate from personal accounts and makes it easy to revoke access later.
21
+
22
+ **1. Create a dedicated user**
23
+
24
+ In the Nextcloud admin panel, create a new user (e.g. `n8n-bot`) with a display name that will appear in Talk alongside its messages. See the [Nextcloud user management documentation](https://docs.nextcloud.com/server/latest/admin_manual/configuration_user/user_configuration.html) for details.
25
+
26
+ **2. Add the bot to the relevant conversations**
27
+
28
+ Log in as an admin or as a moderator of each conversation the bot needs access to, then add the bot user as a participant. The bot can only read or post in conversations it is a member of.
29
+
30
+ **3. Generate an app password**
31
+
32
+ Log in as the bot user and go to **Settings → Security → Devices & sessions**. Scroll to the *App passwords* section, enter a name (e.g. `n8n`), and click **Create new app password**. Copy the generated password — it is only shown once.
33
+
34
+ See the [Nextcloud app passwords documentation](https://docs.nextcloud.com/server/latest/user_manual/en/session_management.html#managing-devices) for more detail.
35
+
36
+ **4. Configure the credential in n8n**
37
+
38
+ In n8n, create a new **Nextcloud API** credential and fill in:
39
+
40
+ | Field | Value |
41
+ | --- | --- |
42
+ | Server URL | Your Nextcloud instance URL, e.g. `https://cloud.example.com` |
43
+ | Username | The bot account username, e.g. `n8n-bot` |
44
+ | App Password | The app password generated in step 3 |
45
+
46
+ ## Features
47
+
48
+ ### Conversation
49
+
50
+ | Operation | Description |
51
+ | ---------------------- | ---------------------------------------------------------- |
52
+ | List | Return all conversations the authenticated user is part of |
53
+ | Get | Get details of a single conversation by token |
54
+ | Create | Create a new group conversation |
55
+ | Delete | Delete a conversation |
56
+ | Rename | Change the display name of a conversation |
57
+ | Set Description | Update the conversation description |
58
+ | Toggle Guest Access | Allow or disallow guests to join via a public link |
59
+ | Toggle Favorite | Mark or unmark a conversation as a favorite |
60
+ | Set Notification Level | Control when you receive notifications for a conversation |
61
+ | Set Read-Only | Lock or unlock a conversation for new messages |
62
+
63
+ ### Message
64
+
65
+ | Operation | Description |
66
+ | ------------ | --------------------------------------------------------------------- |
67
+ | Get Many | Retrieve messages from a conversation, with optional limit and offset |
68
+ | Send | Post a new message to a conversation |
69
+ | Reply | Reply to an existing message |
70
+ | Edit | Update the text of a previously sent message |
71
+ | Delete | Delete a message |
72
+ | Mark as Read | Set the read marker to the latest message |
73
+
74
+ ### Participant
75
+
76
+ | Operation | Description |
77
+ | --------------------- | ---------------------------------------------- |
78
+ | List | List all participants in a conversation |
79
+ | Add | Add a user or group to a conversation |
80
+ | Remove | Remove a participant from a conversation |
81
+ | Promote to Moderator | Grant moderator privileges to a participant |
82
+ | Demote from Moderator | Remove moderator privileges from a participant |
83
+
84
+ ### Poll
85
+
86
+ | Operation | Description |
87
+ | --------- | -------------------------------------------- |
88
+ | Create | Create a poll in a conversation |
89
+ | Get | Retrieve a poll and its current results |
90
+ | Vote | Submit a vote on a poll |
91
+ | Close | Close a poll so no further votes can be cast |
92
+
93
+ ### Reaction
94
+
95
+ | Operation | Description |
96
+ | --------- | -------------------------------------------------------------- |
97
+ | Add | React to a message with an emoji |
98
+ | Remove | Remove your reaction from a message |
99
+ | Get | List all reactions on a message, with optional filter by emoji |
100
+
101
+ ### Trigger
102
+
103
+ | Trigger | Description |
104
+ | ---------- | -------------------------------------------------------------------- |
105
+ | On Message | Poll a conversation for new messages and emit them as workflow items |
106
+
107
+ ## Development
108
+
109
+ ### Prerequisites
110
+
111
+ - Node.js 20+
112
+ - Docker (for the integration test environment)
113
+
114
+ ### Setup
115
+
116
+ ```bash
117
+ npm ci
118
+ ```
119
+
120
+ ### Local development
121
+
122
+ ```bash
123
+ npm run dev
124
+ ```
125
+
126
+ This starts a local n8n instance at **http://localhost:5678** with the node loaded and hot-reload enabled — changes to source files are picked up automatically without restarting.
127
+
128
+ ### Running the integration tests
129
+
130
+ The test suite spins up a real Nextcloud instance in Docker, installs the Talk app, and runs every operation against it. No manual setup is required.
131
+
132
+ ```bash
133
+ npm run test:integration
134
+ ```
135
+
136
+ The test runner handles the full lifecycle automatically:
137
+
138
+ 1. Starts a Nextcloud container (`nextcloud:30-apache`) via Docker Compose
139
+ 2. Waits for Nextcloud to be ready
140
+ 3. Installs the Talk (spreed) app via `occ`
141
+ 4. Creates a `testuser` account used by several tests
142
+ 5. Runs all tests sequentially (tests share Nextcloud state, so parallel execution is disabled)
143
+ 6. Tears down the container when done
144
+
145
+ To run against a different port (e.g. if 8080 is already in use):
146
+
147
+ ```bash
148
+ NEXTCLOUD_PORT=9090 npm run test:integration
149
+ ```
150
+
151
+ ### Linting
152
+
153
+ ```bash
154
+ npm run lint # check
155
+ npm run lint:fix # auto-fix
156
+ ```
@@ -0,0 +1,10 @@
1
+ import type { IAuthenticateGeneric, Icon, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
2
+ export declare class NextcloudApi implements ICredentialType {
3
+ name: string;
4
+ displayName: string;
5
+ icon: Icon;
6
+ documentationUrl: string;
7
+ properties: INodeProperties[];
8
+ authenticate: IAuthenticateGeneric;
9
+ test: ICredentialTestRequest;
10
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NextcloudApi = void 0;
4
+ class NextcloudApi {
5
+ constructor() {
6
+ this.name = 'nextcloudApi';
7
+ this.displayName = 'Nextcloud API';
8
+ this.icon = { light: 'file:../icons/nextcloud.svg', dark: 'file:../icons/nextcloud.dark.svg' };
9
+ this.documentationUrl = 'https://docs.nextcloud.com/server/latest/developer_manual/client_apis/';
10
+ this.properties = [
11
+ {
12
+ displayName: 'Server URL',
13
+ name: 'serverUrl',
14
+ type: 'string',
15
+ default: '',
16
+ placeholder: 'https://cloud.example.com',
17
+ description: 'The URL of your Nextcloud instance',
18
+ required: true,
19
+ },
20
+ {
21
+ displayName: 'Username',
22
+ name: 'username',
23
+ type: 'string',
24
+ default: '',
25
+ required: true,
26
+ },
27
+ {
28
+ displayName: 'App Password',
29
+ name: 'appPassword',
30
+ type: 'string',
31
+ typeOptions: { password: true },
32
+ default: '',
33
+ description: 'App password generated in Nextcloud under User Settings → Security → App passwords',
34
+ required: true,
35
+ },
36
+ ];
37
+ this.authenticate = {
38
+ type: 'generic',
39
+ properties: {
40
+ auth: {
41
+ username: '={{$credentials.username}}',
42
+ password: '={{$credentials.appPassword}}',
43
+ },
44
+ headers: {
45
+ 'OCS-APIRequest': 'true',
46
+ 'Content-Type': 'application/json',
47
+ },
48
+ },
49
+ };
50
+ this.test = {
51
+ request: {
52
+ baseURL: '={{$credentials.serverUrl}}',
53
+ url: '/ocs/v2.php/apps/spreed/api/v4/room',
54
+ method: 'GET',
55
+ },
56
+ };
57
+ }
58
+ }
59
+ exports.NextcloudApi = NextcloudApi;
60
+ //# sourceMappingURL=NextcloudApi.credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NextcloudApi.credentials.js","sourceRoot":"","sources":["../../credentials/NextcloudApi.credentials.ts"],"names":[],"mappings":";;;AAQA,MAAa,YAAY;IAAzB;QACC,SAAI,GAAG,cAAc,CAAC;QAEtB,gBAAW,GAAG,eAAe,CAAC;QAE9B,SAAI,GAAS,EAAE,KAAK,EAAE,6BAA6B,EAAE,IAAI,EAAE,kCAAkC,EAAE,CAAC;QAEhG,qBAAgB,GAAG,wEAAwE,CAAC;QAE5F,eAAU,GAAsB;YAC/B;gBACC,WAAW,EAAE,YAAY;gBACzB,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,EAAE;gBACX,WAAW,EAAE,2BAA2B;gBACxC,WAAW,EAAE,oCAAoC;gBACjD,QAAQ,EAAE,IAAI;aACd;YACD;gBACC,WAAW,EAAE,UAAU;gBACvB,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;aACd;YACD;gBACC,WAAW,EAAE,cAAc;gBAC3B,IAAI,EAAE,aAAa;gBACnB,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC/B,OAAO,EAAE,EAAE;gBACX,WAAW,EACV,oFAAoF;gBACrF,QAAQ,EAAE,IAAI;aACd;SACD,CAAC;QAEF,iBAAY,GAAyB;YACpC,IAAI,EAAE,SAAS;YACf,UAAU,EAAE;gBACX,IAAI,EAAE;oBACL,QAAQ,EAAE,4BAA4B;oBACtC,QAAQ,EAAE,+BAA+B;iBACzC;gBACD,OAAO,EAAE;oBACR,gBAAgB,EAAE,MAAM;oBACxB,cAAc,EAAE,kBAAkB;iBAClC;aACD;SACD,CAAC;QAEF,SAAI,GAA2B;YAC9B,OAAO,EAAE;gBACR,OAAO,EAAE,6BAA6B;gBACtC,GAAG,EAAE,qCAAqC;gBAC1C,MAAM,EAAE,KAAK;aACb;SACD,CAAC;IACH,CAAC;CAAA;AA3DD,oCA2DC"}
Binary file
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+
3
+ <svg xmlns="http://www.w3.org/2000/svg"
4
+ aria-label="NextCloud" role="img"
5
+ viewBox="0 0 512 512">
6
+
7
+ width="512" height="512"
8
+ rx="15%"
9
+ fill="#0082c9"/>
10
+
11
+
12
+
13
+
14
+
15
+
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+
3
+ <svg xmlns="http://www.w3.org/2000/svg"
4
+ aria-label="NextCloud" role="img"
5
+ viewBox="0 0 512 512">
6
+
7
+ width="512" height="512"
8
+ rx="15%"
9
+ fill="#0082c9"/>
10
+
11
+
12
+
13
+
14
+
15
+
@@ -0,0 +1,5 @@
1
+ import { type IExecuteFunctions, type INodeExecutionData, type INodeType, type INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class NextcloudTalk implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
@@ -0,0 +1,380 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NextcloudTalk = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ const helpers_1 = require("./helpers");
6
+ const message_description_1 = require("./descriptions/message.description");
7
+ const conversation_description_1 = require("./descriptions/conversation.description");
8
+ const participant_description_1 = require("./descriptions/participant.description");
9
+ const poll_description_1 = require("./descriptions/poll.description");
10
+ const reaction_description_1 = require("./descriptions/reaction.description");
11
+ class NextcloudTalk {
12
+ constructor() {
13
+ this.description = {
14
+ displayName: 'Nextcloud Talk',
15
+ name: 'nextcloudTalk',
16
+ icon: {
17
+ light: 'file:../../icons/nextcloud.svg',
18
+ dark: 'file:../../icons/nextcloud.dark.svg',
19
+ },
20
+ group: ['output'],
21
+ version: 1,
22
+ subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
23
+ description: 'Send and manage messages in Nextcloud Talk conversations',
24
+ defaults: {
25
+ name: 'Nextcloud Talk',
26
+ },
27
+ usableAsTool: true,
28
+ inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
29
+ outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
30
+ credentials: [
31
+ {
32
+ name: 'nextcloudApi',
33
+ required: true,
34
+ },
35
+ ],
36
+ properties: [
37
+ {
38
+ displayName: 'Resource',
39
+ name: 'resource',
40
+ type: 'options',
41
+ noDataExpression: true,
42
+ options: [
43
+ { name: 'Conversation', value: 'conversation' },
44
+ { name: 'Message', value: 'message' },
45
+ { name: 'Participant', value: 'participant' },
46
+ { name: 'Poll', value: 'poll' },
47
+ { name: 'Reaction', value: 'reaction' },
48
+ ],
49
+ default: 'message',
50
+ },
51
+ ...conversation_description_1.conversationOperations,
52
+ ...conversation_description_1.conversationFields,
53
+ ...message_description_1.messageOperations,
54
+ ...message_description_1.messageFields,
55
+ ...participant_description_1.participantOperations,
56
+ ...participant_description_1.participantFields,
57
+ ...poll_description_1.pollOperations,
58
+ ...poll_description_1.pollFields,
59
+ ...reaction_description_1.reactionOperations,
60
+ ...reaction_description_1.reactionFields,
61
+ ],
62
+ };
63
+ }
64
+ async execute() {
65
+ var _a, _b;
66
+ const items = this.getInputData();
67
+ const returnData = [];
68
+ for (let i = 0; i < items.length; i++) {
69
+ try {
70
+ const resource = this.getNodeParameter('resource', i);
71
+ const operation = this.getNodeParameter('operation', i);
72
+ if (resource === 'conversation') {
73
+ if (operation === 'getMany') {
74
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'GET', helpers_1.ROOM_API_PATH, '/room');
75
+ const conversations = (0, helpers_1.extractOcsData)(response);
76
+ for (const conversation of conversations) {
77
+ returnData.push({ json: conversation, pairedItem: { item: i } });
78
+ }
79
+ }
80
+ else if (operation === 'get') {
81
+ const token = this.getNodeParameter('token', i);
82
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'GET', helpers_1.ROOM_API_PATH, `/room/${token}`);
83
+ returnData.push({
84
+ json: (0, helpers_1.extractOcsData)(response),
85
+ pairedItem: { item: i },
86
+ });
87
+ }
88
+ else if (operation === 'create') {
89
+ const roomType = this.getNodeParameter('roomType', i);
90
+ const body = { roomType };
91
+ if (roomType === 1 || roomType === 2) {
92
+ const invite = this.getNodeParameter('invite', i);
93
+ if (invite)
94
+ body.invite = invite;
95
+ }
96
+ if (roomType === 2) {
97
+ body.source = this.getNodeParameter('source', i);
98
+ }
99
+ if (roomType === 2 || roomType === 3) {
100
+ const roomName = this.getNodeParameter('roomName', i);
101
+ if (roomName)
102
+ body.roomName = roomName;
103
+ }
104
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'POST', helpers_1.ROOM_API_PATH, '/room', body);
105
+ returnData.push({
106
+ json: (0, helpers_1.extractOcsData)(response),
107
+ pairedItem: { item: i },
108
+ });
109
+ }
110
+ else if (operation === 'delete') {
111
+ const token = this.getNodeParameter('token', i);
112
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'DELETE', helpers_1.ROOM_API_PATH, `/room/${token}`);
113
+ returnData.push({
114
+ json: (0, helpers_1.extractOcsData)(response),
115
+ pairedItem: { item: i },
116
+ });
117
+ }
118
+ else if (operation === 'rename') {
119
+ const token = this.getNodeParameter('token', i);
120
+ const roomName = this.getNodeParameter('roomName', i);
121
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'PUT', helpers_1.ROOM_API_PATH, `/room/${token}`, { roomName });
122
+ returnData.push({
123
+ json: (0, helpers_1.extractOcsData)(response),
124
+ pairedItem: { item: i },
125
+ });
126
+ }
127
+ else if (operation === 'setDescription') {
128
+ const token = this.getNodeParameter('token', i);
129
+ const description = this.getNodeParameter('description', i);
130
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'PUT', helpers_1.ROOM_API_PATH, `/room/${token}/description`, { description });
131
+ returnData.push({
132
+ json: (0, helpers_1.extractOcsData)(response),
133
+ pairedItem: { item: i },
134
+ });
135
+ }
136
+ else if (operation === 'setGuestAccess') {
137
+ const token = this.getNodeParameter('token', i);
138
+ const allowGuests = this.getNodeParameter('allowGuests', i);
139
+ const response = await helpers_1.nextcloudApiRequest.call(this, allowGuests ? 'POST' : 'DELETE', helpers_1.ROOM_API_PATH, `/room/${token}/public`);
140
+ returnData.push({
141
+ json: (0, helpers_1.extractOcsData)(response),
142
+ pairedItem: { item: i },
143
+ });
144
+ }
145
+ else if (operation === 'setFavorite') {
146
+ const token = this.getNodeParameter('token', i);
147
+ const favorite = this.getNodeParameter('favorite', i);
148
+ const response = await helpers_1.nextcloudApiRequest.call(this, favorite ? 'POST' : 'DELETE', helpers_1.ROOM_API_PATH, `/room/${token}/favorite`);
149
+ returnData.push({
150
+ json: (0, helpers_1.extractOcsData)(response),
151
+ pairedItem: { item: i },
152
+ });
153
+ }
154
+ else if (operation === 'setNotificationLevel') {
155
+ const token = this.getNodeParameter('token', i);
156
+ const level = this.getNodeParameter('notificationLevel', i);
157
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'POST', helpers_1.ROOM_API_PATH, `/room/${token}/notify`, { level });
158
+ returnData.push({
159
+ json: (0, helpers_1.extractOcsData)(response),
160
+ pairedItem: { item: i },
161
+ });
162
+ }
163
+ else if (operation === 'setReadOnly') {
164
+ const token = this.getNodeParameter('token', i);
165
+ const readOnly = this.getNodeParameter('readOnly', i);
166
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'PUT', helpers_1.ROOM_API_PATH, `/room/${token}/read-only`, { state: readOnly ? 1 : 0 });
167
+ returnData.push({
168
+ json: (0, helpers_1.extractOcsData)(response),
169
+ pairedItem: { item: i },
170
+ });
171
+ }
172
+ }
173
+ else if (resource === 'message') {
174
+ const token = this.getNodeParameter('token', i);
175
+ if (operation === 'getMany') {
176
+ const returnAll = this.getNodeParameter('returnAll', i);
177
+ const additionalOptions = this.getNodeParameter('additionalOptions', i);
178
+ const qs = { lookIntoFuture: 0 };
179
+ qs.limit = returnAll ? 200 : this.getNodeParameter('limit', i);
180
+ if (additionalOptions.lastKnownMessageId) {
181
+ qs.lastKnownMessageId = additionalOptions.lastKnownMessageId;
182
+ }
183
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'GET', helpers_1.CHAT_API_PATH, `/chat/${token}`, {}, qs);
184
+ const messages = (0, helpers_1.extractOcsData)(response);
185
+ for (const message of messages) {
186
+ returnData.push({ json: message, pairedItem: { item: i } });
187
+ }
188
+ }
189
+ else if (operation === 'send') {
190
+ const message = this.getNodeParameter('message', i);
191
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'POST', helpers_1.CHAT_API_PATH, `/chat/${token}`, { message });
192
+ returnData.push({
193
+ json: (0, helpers_1.extractOcsData)(response),
194
+ pairedItem: { item: i },
195
+ });
196
+ }
197
+ else if (operation === 'reply') {
198
+ const replyTo = this.getNodeParameter('replyTo', i);
199
+ const message = this.getNodeParameter('message', i);
200
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'POST', helpers_1.CHAT_API_PATH, `/chat/${token}`, { message, replyTo });
201
+ returnData.push({
202
+ json: (0, helpers_1.extractOcsData)(response),
203
+ pairedItem: { item: i },
204
+ });
205
+ }
206
+ else if (operation === 'react') {
207
+ const messageId = this.getNodeParameter('messageId', i);
208
+ const reaction = this.getNodeParameter('reaction', i);
209
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'POST', helpers_1.CHAT_API_PATH, `/reaction/${token}/${messageId}`, { reaction });
210
+ returnData.push({
211
+ json: (0, helpers_1.extractOcsData)(response),
212
+ pairedItem: { item: i },
213
+ });
214
+ }
215
+ else if (operation === 'edit') {
216
+ const messageId = this.getNodeParameter('messageId', i);
217
+ const message = this.getNodeParameter('message', i);
218
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'PUT', helpers_1.CHAT_API_PATH, `/chat/${token}/${messageId}`, { message });
219
+ returnData.push({
220
+ json: (0, helpers_1.extractOcsData)(response),
221
+ pairedItem: { item: i },
222
+ });
223
+ }
224
+ else if (operation === 'delete') {
225
+ const messageId = this.getNodeParameter('messageId', i);
226
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'DELETE', helpers_1.CHAT_API_PATH, `/chat/${token}/${messageId}`);
227
+ returnData.push({
228
+ json: (0, helpers_1.extractOcsData)(response),
229
+ pairedItem: { item: i },
230
+ });
231
+ }
232
+ else if (operation === 'markRead') {
233
+ const lastReadMessage = this.getNodeParameter('lastReadMessage', i);
234
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'POST', helpers_1.CHAT_API_PATH, `/chat/${token}/read`, { lastReadMessage: lastReadMessage || null });
235
+ returnData.push({
236
+ json: (0, helpers_1.extractOcsData)(response),
237
+ pairedItem: { item: i },
238
+ });
239
+ }
240
+ }
241
+ else if (resource === 'participant') {
242
+ const token = this.getNodeParameter('token', i);
243
+ if (operation === 'getMany') {
244
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'GET', helpers_1.ROOM_API_PATH, `/room/${token}/participants`);
245
+ const participants = (0, helpers_1.extractOcsData)(response);
246
+ for (const participant of participants) {
247
+ returnData.push({ json: participant, pairedItem: { item: i } });
248
+ }
249
+ }
250
+ else if (operation === 'add') {
251
+ const newParticipant = this.getNodeParameter('newParticipant', i);
252
+ const source = this.getNodeParameter('source', i);
253
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'POST', helpers_1.ROOM_API_PATH, `/room/${token}/participants`, { newParticipant, source });
254
+ returnData.push({
255
+ json: (0, helpers_1.extractOcsData)(response),
256
+ pairedItem: { item: i },
257
+ });
258
+ }
259
+ else if (operation === 'remove') {
260
+ const attendeeId = this.getNodeParameter('attendeeId', i);
261
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'DELETE', helpers_1.ROOM_API_PATH, `/room/${token}/attendees`, { attendeeId });
262
+ returnData.push({
263
+ json: (0, helpers_1.extractOcsData)(response),
264
+ pairedItem: { item: i },
265
+ });
266
+ }
267
+ else if (operation === 'promote') {
268
+ const attendeeId = this.getNodeParameter('attendeeId', i);
269
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'POST', helpers_1.ROOM_API_PATH, `/room/${token}/moderators`, { attendeeId });
270
+ returnData.push({
271
+ json: (0, helpers_1.extractOcsData)(response),
272
+ pairedItem: { item: i },
273
+ });
274
+ }
275
+ else if (operation === 'demote') {
276
+ const attendeeId = this.getNodeParameter('attendeeId', i);
277
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'DELETE', helpers_1.ROOM_API_PATH, `/room/${token}/moderators`, { attendeeId });
278
+ returnData.push({
279
+ json: (0, helpers_1.extractOcsData)(response),
280
+ pairedItem: { item: i },
281
+ });
282
+ }
283
+ }
284
+ else if (resource === 'poll') {
285
+ const token = this.getNodeParameter('token', i);
286
+ if (operation === 'create') {
287
+ const question = this.getNodeParameter('question', i);
288
+ const resultMode = this.getNodeParameter('resultMode', i);
289
+ const maxVotes = this.getNodeParameter('maxVotes', i);
290
+ const pollOptionsCollection = this.getNodeParameter('pollOptions', i);
291
+ const options = ((_a = pollOptionsCollection.option) !== null && _a !== void 0 ? _a : []).map((o) => o.text);
292
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'POST', helpers_1.CHAT_API_PATH, `/poll/${token}`, { question, options, resultMode, maxVotes });
293
+ returnData.push({
294
+ json: (0, helpers_1.extractOcsData)(response),
295
+ pairedItem: { item: i },
296
+ });
297
+ }
298
+ else if (operation === 'get') {
299
+ const pollId = this.getNodeParameter('pollId', i);
300
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'GET', helpers_1.CHAT_API_PATH, `/poll/${token}/${pollId}`);
301
+ returnData.push({
302
+ json: (0, helpers_1.extractOcsData)(response),
303
+ pairedItem: { item: i },
304
+ });
305
+ }
306
+ else if (operation === 'vote') {
307
+ const pollId = this.getNodeParameter('pollId', i);
308
+ const optionIdsCollection = this.getNodeParameter('optionIds', i);
309
+ const optionIds = ((_b = optionIdsCollection.id) !== null && _b !== void 0 ? _b : []).map((o) => o.value);
310
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'POST', helpers_1.CHAT_API_PATH, `/poll/${token}/${pollId}`, { optionIds });
311
+ returnData.push({
312
+ json: (0, helpers_1.extractOcsData)(response),
313
+ pairedItem: { item: i },
314
+ });
315
+ }
316
+ else if (operation === 'close') {
317
+ const pollId = this.getNodeParameter('pollId', i);
318
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'DELETE', helpers_1.CHAT_API_PATH, `/poll/${token}/${pollId}`);
319
+ returnData.push({
320
+ json: (0, helpers_1.extractOcsData)(response),
321
+ pairedItem: { item: i },
322
+ });
323
+ }
324
+ }
325
+ else if (resource === 'reaction') {
326
+ const token = this.getNodeParameter('token', i);
327
+ const messageId = this.getNodeParameter('messageId', i);
328
+ if (operation === 'add') {
329
+ const reaction = this.getNodeParameter('reaction', i);
330
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'POST', helpers_1.CHAT_API_PATH, `/reaction/${token}/${messageId}`, { reaction });
331
+ const reactionData = (0, helpers_1.extractOcsData)(response);
332
+ for (const [emoji, reactions] of Object.entries(reactionData)) {
333
+ if (Array.isArray(reactions)) {
334
+ for (const r of reactions) {
335
+ returnData.push({ json: { ...r, reaction: emoji }, pairedItem: { item: i } });
336
+ }
337
+ }
338
+ }
339
+ }
340
+ else if (operation === 'remove') {
341
+ const reaction = this.getNodeParameter('reaction', i);
342
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'DELETE', helpers_1.CHAT_API_PATH, `/reaction/${token}/${messageId}`, { reaction });
343
+ returnData.push({
344
+ json: (0, helpers_1.extractOcsData)(response),
345
+ pairedItem: { item: i },
346
+ });
347
+ }
348
+ else if (operation === 'get') {
349
+ const reactionFilter = this.getNodeParameter('reaction', i);
350
+ const qs = {};
351
+ if (reactionFilter)
352
+ qs.reaction = reactionFilter;
353
+ const response = await helpers_1.nextcloudApiRequest.call(this, 'GET', helpers_1.CHAT_API_PATH, `/reaction/${token}/${messageId}`, {}, qs);
354
+ const reactionData = (0, helpers_1.extractOcsData)(response);
355
+ for (const [emoji, reactions] of Object.entries(reactionData)) {
356
+ if (Array.isArray(reactions)) {
357
+ for (const r of reactions) {
358
+ returnData.push({ json: { ...r, reaction: emoji }, pairedItem: { item: i } });
359
+ }
360
+ }
361
+ }
362
+ }
363
+ }
364
+ }
365
+ catch (error) {
366
+ if (this.continueOnFail()) {
367
+ returnData.push({
368
+ json: { error: error.message },
369
+ pairedItem: { item: i },
370
+ });
371
+ continue;
372
+ }
373
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), error, { itemIndex: i });
374
+ }
375
+ }
376
+ return [returnData];
377
+ }
378
+ }
379
+ exports.NextcloudTalk = NextcloudTalk;
380
+ //# sourceMappingURL=NextcloudTalk.node.js.map