n8n-nodes-ntfy-next 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.
- package/LICENSE.md +19 -0
- package/README.md +14 -0
- package/dist/Ntfy.node.js +170 -0
- package/dist/NtfyApi.credentials.js +132 -0
- package/dist/ntfy.dark.svg +7 -0
- package/dist/ntfy.light.svg +7 -0
- package/package.json +44 -0
package/LICENSE.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
© 2025 Iván Ovejero
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
4
|
+
this software and associated documentation files (the "Software"), to deal in
|
5
|
+
the Software without restriction, including without limitation the rights to
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
7
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
8
|
+
so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
SOFTWARE.
|
package/README.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# n8n-nodes-ntfy
|
2
|
+
|
3
|
+
[n8n community package](https://docs.n8n.io/integrations/community-nodes/installation/gui-install/) to push messages via [ntfy.sh](https://ntfy.sh/)
|
4
|
+
|
5
|
+
- Set headers via fields or JSON
|
6
|
+
- Support for self-hosted ntfy instances
|
7
|
+
- Credentials for basic + bearer + query auth
|
8
|
+
|
9
|
+
<img src="docs/ndv.png" width="400">
|
10
|
+
|
11
|
+
## Docs
|
12
|
+
|
13
|
+
- [`development.md`](docs/development.md)
|
14
|
+
- [`self-hosting.md`](docs/self-hosting.md)
|
@@ -0,0 +1,170 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.Ntfy = void 0;
|
4
|
+
class Ntfy {
|
5
|
+
constructor() {
|
6
|
+
this.description = {
|
7
|
+
displayName: "ntfy",
|
8
|
+
name: "ntfy",
|
9
|
+
icon: { light: "file:ntfy.light.svg", dark: "file:ntfy.dark.svg" },
|
10
|
+
group: ["transform"],
|
11
|
+
version: 1,
|
12
|
+
subtitle: '={{ $parameter["topic"] }}',
|
13
|
+
description: "Push messages via ntfy.sh",
|
14
|
+
defaults: {
|
15
|
+
name: "ntfy",
|
16
|
+
},
|
17
|
+
inputs: ["main" /* NodeConnectionType.Main */],
|
18
|
+
outputs: ["main" /* NodeConnectionType.Main */],
|
19
|
+
requestDefaults: {
|
20
|
+
baseURL: '={{ $credentials.baseUrl.replace(new RegExp("/$"), "") }}',
|
21
|
+
},
|
22
|
+
credentials: [
|
23
|
+
{
|
24
|
+
name: "ntfyApi",
|
25
|
+
required: true,
|
26
|
+
},
|
27
|
+
],
|
28
|
+
properties: [
|
29
|
+
{
|
30
|
+
displayName: "Topic",
|
31
|
+
name: "topic",
|
32
|
+
type: "string",
|
33
|
+
description: 'Topic to <a href="https://docs.ntfy.sh/publish/#publishing">push</a> a message to',
|
34
|
+
required: true,
|
35
|
+
default: "",
|
36
|
+
placeholder: "e.g. mytopic",
|
37
|
+
routing: {
|
38
|
+
request: {
|
39
|
+
method: "POST",
|
40
|
+
url: "=/{{ $parameter.topic }}",
|
41
|
+
},
|
42
|
+
},
|
43
|
+
},
|
44
|
+
{
|
45
|
+
displayName: "Message",
|
46
|
+
name: "message",
|
47
|
+
type: "string",
|
48
|
+
description: "Message to publish to a topic",
|
49
|
+
required: true,
|
50
|
+
default: "",
|
51
|
+
placeholder: "e.g. Hello world!",
|
52
|
+
routing: {
|
53
|
+
send: { preSend: [populateMessage] },
|
54
|
+
},
|
55
|
+
},
|
56
|
+
{
|
57
|
+
displayName: "Send Additional Headers",
|
58
|
+
name: "sendAdditionalHeaders",
|
59
|
+
type: "boolean",
|
60
|
+
default: false,
|
61
|
+
noDataExpression: true,
|
62
|
+
description: 'Whether to send <a href="https://docs.ntfy.sh/publish/#list-of-all-parameters">additional headers</a> with the request',
|
63
|
+
},
|
64
|
+
{
|
65
|
+
displayName: "Specify Headers Using...",
|
66
|
+
name: "specifyHeadersUsing",
|
67
|
+
type: "options",
|
68
|
+
noDataExpression: true,
|
69
|
+
displayOptions: {
|
70
|
+
show: {
|
71
|
+
sendAdditionalHeaders: [true],
|
72
|
+
},
|
73
|
+
},
|
74
|
+
options: [
|
75
|
+
{
|
76
|
+
name: "Fields",
|
77
|
+
value: "keypair",
|
78
|
+
},
|
79
|
+
{
|
80
|
+
name: "JSON",
|
81
|
+
value: "json",
|
82
|
+
},
|
83
|
+
],
|
84
|
+
default: "keypair",
|
85
|
+
},
|
86
|
+
{
|
87
|
+
displayName: "Header Fields",
|
88
|
+
name: "headerFields",
|
89
|
+
type: "fixedCollection",
|
90
|
+
displayOptions: {
|
91
|
+
show: {
|
92
|
+
sendAdditionalHeaders: [true],
|
93
|
+
specifyHeadersUsing: ["keypair"],
|
94
|
+
},
|
95
|
+
},
|
96
|
+
typeOptions: {
|
97
|
+
multipleValues: true,
|
98
|
+
},
|
99
|
+
placeholder: "Add Header Field",
|
100
|
+
routing: {
|
101
|
+
send: { preSend: [populateHeaderFields] },
|
102
|
+
},
|
103
|
+
default: {
|
104
|
+
parameters: [
|
105
|
+
{
|
106
|
+
name: "",
|
107
|
+
value: "",
|
108
|
+
},
|
109
|
+
],
|
110
|
+
},
|
111
|
+
options: [
|
112
|
+
{
|
113
|
+
name: "parameters",
|
114
|
+
displayName: "Parameter",
|
115
|
+
values: [
|
116
|
+
{
|
117
|
+
displayName: "Name",
|
118
|
+
name: "name",
|
119
|
+
type: "string",
|
120
|
+
default: "",
|
121
|
+
placeholder: "e.g. X-Title",
|
122
|
+
},
|
123
|
+
{
|
124
|
+
displayName: "Value",
|
125
|
+
name: "value",
|
126
|
+
type: "string",
|
127
|
+
default: "",
|
128
|
+
placeholder: "e.g. This is a title",
|
129
|
+
},
|
130
|
+
],
|
131
|
+
},
|
132
|
+
],
|
133
|
+
},
|
134
|
+
{
|
135
|
+
displayName: "JSON Headers",
|
136
|
+
name: "jsonHeaders",
|
137
|
+
type: "json",
|
138
|
+
displayOptions: {
|
139
|
+
show: {
|
140
|
+
sendAdditionalHeaders: [true],
|
141
|
+
specifyHeadersUsing: ["json"],
|
142
|
+
},
|
143
|
+
},
|
144
|
+
routing: {
|
145
|
+
send: { preSend: [populateJsonHeaders] },
|
146
|
+
},
|
147
|
+
default: '{ "X-Title": "This is a title" }',
|
148
|
+
},
|
149
|
+
],
|
150
|
+
};
|
151
|
+
}
|
152
|
+
}
|
153
|
+
exports.Ntfy = Ntfy;
|
154
|
+
async function populateMessage(opts) {
|
155
|
+
opts.body = this.getNodeParameter("message");
|
156
|
+
return opts;
|
157
|
+
}
|
158
|
+
async function populateHeaderFields(opts) {
|
159
|
+
var _a;
|
160
|
+
(_a = opts.headers) !== null && _a !== void 0 ? _a : (opts.headers = {});
|
161
|
+
const { parameters } = this.getNodeParameter("headerFields");
|
162
|
+
for (const p of parameters) {
|
163
|
+
opts.headers[p.name] = p.value;
|
164
|
+
}
|
165
|
+
return opts;
|
166
|
+
}
|
167
|
+
async function populateJsonHeaders(opts) {
|
168
|
+
opts.headers = JSON.parse(this.getNodeParameter("jsonHeaders"));
|
169
|
+
return opts;
|
170
|
+
}
|
@@ -0,0 +1,132 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.NtfyApi = void 0;
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
5
|
+
class NtfyApi {
|
6
|
+
constructor() {
|
7
|
+
this.name = "ntfyApi";
|
8
|
+
this.displayName = "ntfy API";
|
9
|
+
this.icon = { light: "file:ntfy.light.svg", dark: "file:ntfy.dark.svg" };
|
10
|
+
this.properties = [
|
11
|
+
{
|
12
|
+
displayName: "Base URL",
|
13
|
+
name: "baseUrl",
|
14
|
+
type: "string",
|
15
|
+
default: "https://ntfy.sh",
|
16
|
+
description: "Base URL of the ntfy instance",
|
17
|
+
required: true,
|
18
|
+
},
|
19
|
+
{
|
20
|
+
displayName: "Auth Type",
|
21
|
+
name: "authType",
|
22
|
+
type: "options",
|
23
|
+
description: '<a href="https://docs.ntfy.sh/publish/#authentication">Auth type</a> to use',
|
24
|
+
required: true,
|
25
|
+
options: [
|
26
|
+
{
|
27
|
+
name: "No Auth",
|
28
|
+
value: "noAuth",
|
29
|
+
},
|
30
|
+
{
|
31
|
+
name: "Basic Auth",
|
32
|
+
value: "basicAuth",
|
33
|
+
},
|
34
|
+
{
|
35
|
+
name: "Bearer Auth",
|
36
|
+
value: "bearerAuth",
|
37
|
+
},
|
38
|
+
{
|
39
|
+
name: "Query Auth",
|
40
|
+
value: "queryAuth",
|
41
|
+
},
|
42
|
+
],
|
43
|
+
default: "noAuth",
|
44
|
+
},
|
45
|
+
{
|
46
|
+
displayName: "Username",
|
47
|
+
name: "username",
|
48
|
+
type: "string",
|
49
|
+
description: '<a href="https://docs.ntfy.sh/publish/#username-password">Username</a> for basic auth',
|
50
|
+
default: "",
|
51
|
+
required: true,
|
52
|
+
displayOptions: {
|
53
|
+
show: {
|
54
|
+
authType: ["basicAuth"],
|
55
|
+
},
|
56
|
+
},
|
57
|
+
},
|
58
|
+
{
|
59
|
+
displayName: "Password",
|
60
|
+
name: "password",
|
61
|
+
type: "string",
|
62
|
+
description: '<a href="https://docs.ntfy.sh/publish/#username-password">Password</a> for basic auth',
|
63
|
+
typeOptions: {
|
64
|
+
password: true,
|
65
|
+
},
|
66
|
+
default: "",
|
67
|
+
placeholder: "e.g. mypassword123",
|
68
|
+
required: true,
|
69
|
+
displayOptions: {
|
70
|
+
show: {
|
71
|
+
authType: ["basicAuth"],
|
72
|
+
},
|
73
|
+
},
|
74
|
+
},
|
75
|
+
{
|
76
|
+
displayName: "Bearer Token",
|
77
|
+
name: "bearerToken",
|
78
|
+
required: true,
|
79
|
+
description: '<a href="https://docs.ntfy.sh/publish/#access-tokens">Bearer token</a> for bearer auth',
|
80
|
+
type: "string",
|
81
|
+
typeOptions: { password: true },
|
82
|
+
default: "",
|
83
|
+
placeholder: "e.g. tk_AgQdq7mVBoFD37zQVN29RhuMzNIz2",
|
84
|
+
displayOptions: {
|
85
|
+
show: {
|
86
|
+
authType: ["bearerAuth"],
|
87
|
+
},
|
88
|
+
},
|
89
|
+
},
|
90
|
+
{
|
91
|
+
displayName: "Query Parameter",
|
92
|
+
name: "queryParameter",
|
93
|
+
type: "string",
|
94
|
+
required: true,
|
95
|
+
description: '<a href="https://docs.ntfy.sh/publish/#query-param">Query parameter</a> for auth',
|
96
|
+
default: "",
|
97
|
+
displayOptions: {
|
98
|
+
show: {
|
99
|
+
authType: ["queryAuth"],
|
100
|
+
},
|
101
|
+
},
|
102
|
+
},
|
103
|
+
];
|
104
|
+
this.test = {
|
105
|
+
request: {
|
106
|
+
baseURL: '={{ $credentials.baseUrl }}',
|
107
|
+
url: '/v1/health',
|
108
|
+
},
|
109
|
+
};
|
110
|
+
}
|
111
|
+
async authenticate(credentials, opts) {
|
112
|
+
const c = credentials;
|
113
|
+
if (c.authType === "noAuth")
|
114
|
+
return opts;
|
115
|
+
if (c.authType === "basicAuth") {
|
116
|
+
opts.auth = { username: c.username, password: c.password };
|
117
|
+
return opts;
|
118
|
+
}
|
119
|
+
if (c.authType === "bearerAuth") {
|
120
|
+
opts.headers = {
|
121
|
+
Authorization: `Bearer ${c.bearerToken}`,
|
122
|
+
};
|
123
|
+
return opts;
|
124
|
+
}
|
125
|
+
if (c.authType === "queryAuth") {
|
126
|
+
opts.url = `${opts.url}?auth=${c.queryParameter}`;
|
127
|
+
return opts;
|
128
|
+
}
|
129
|
+
throw new n8n_workflow_1.ApplicationError("Invalid credentials type");
|
130
|
+
}
|
131
|
+
}
|
132
|
+
exports.NtfyApi = NtfyApi;
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<svg width="800" height="800" viewBox="0 0 50.8 50.8" xmlns="http://www.w3.org/2000/svg">
|
2
|
+
<g style="stroke:#fff;stroke-opacity:1">
|
3
|
+
<path d="M44.98 39.952V10.848H7.407v27.814l-1.587 4.2 8.393-2.91Z" style="fill:none;fill-opacity:1;stroke:#fff;stroke-width:3.175;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1;paint-order:markers fill stroke"/>
|
4
|
+
<path d="M27.781 31.485h8.202" style="fill:none;fill-opacity:1;stroke:#fff;stroke-width:3.175;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"/>
|
5
|
+
<path d="m65.979 100.011 9.511 5.492-9.511 5.491" style="display:inline;fill:none;fill-opacity:1;stroke:#fff;stroke-width:3.175;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" transform="translate(-51.81 -80.758)"/>
|
6
|
+
</g>
|
7
|
+
</svg>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<svg width="800" height="800" viewBox="0 0 50.8 50.8" xmlns="http://www.w3.org/2000/svg">
|
2
|
+
<g style="stroke:#000;stroke-opacity:1">
|
3
|
+
<path d="M44.98 39.952V10.848H7.407v27.814l-1.587 4.2 8.393-2.91Z" style="fill:none;fill-opacity:1;stroke:#000;stroke-width:3.175;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1;paint-order:markers fill stroke"/>
|
4
|
+
<path d="M27.781 31.485h8.202" style="fill:none;fill-opacity:1;stroke:#000;stroke-width:3.175;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"/>
|
5
|
+
<path d="m65.979 100.011 9.511 5.492-9.511 5.491" style="display:inline;fill:none;fill-opacity:1;stroke:#000;stroke-width:3.175;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" transform="translate(-51.81 -80.758)"/>
|
6
|
+
</g>
|
7
|
+
</svg>
|
package/package.json
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
{
|
2
|
+
"name": "n8n-nodes-ntfy-next",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"description": "n8n community package to push messages via ntfy.sh",
|
5
|
+
"keywords": [
|
6
|
+
"n8n-community-node-package",
|
7
|
+
"ntfy"
|
8
|
+
],
|
9
|
+
"license": "MIT",
|
10
|
+
"author": {
|
11
|
+
"name": "Iván Ovejero"
|
12
|
+
},
|
13
|
+
"repository": {
|
14
|
+
"type": "git",
|
15
|
+
"url": "https://github.com/ivov/n8n-nodes-ntfy.git"
|
16
|
+
},
|
17
|
+
"engines": {
|
18
|
+
"node": ">=20.15",
|
19
|
+
"pnpm": ">=9.15"
|
20
|
+
},
|
21
|
+
"packageManager": "pnpm@9.15.1",
|
22
|
+
"main": "index.js",
|
23
|
+
"files": [
|
24
|
+
"dist"
|
25
|
+
],
|
26
|
+
"scripts": {
|
27
|
+
"build": "tsc && cp src/*.svg dist/"
|
28
|
+
},
|
29
|
+
"n8n": {
|
30
|
+
"n8nNodesApiVersion": 1,
|
31
|
+
"credentials": [
|
32
|
+
"dist/NtfyApi.credentials.js"
|
33
|
+
],
|
34
|
+
"nodes": [
|
35
|
+
"dist/Ntfy.node.js"
|
36
|
+
]
|
37
|
+
},
|
38
|
+
"peerDependencies": {
|
39
|
+
"n8n-workflow": "*"
|
40
|
+
},
|
41
|
+
"devDependencies": {
|
42
|
+
"typescript": "^5.7.3"
|
43
|
+
}
|
44
|
+
}
|