fix(notifications): multiple providers using the wrong params

This commit is contained in:
Nicolas Meienberger
2025-11-23 21:08:07 +01:00
parent 8d4e5d2d4e
commit e99487eed9
7 changed files with 90 additions and 16 deletions

View File

@@ -1859,13 +1859,15 @@ export type GetScheduleNotificationsResponses = {
priority: 'default' | 'high' | 'low' | 'max' | 'min'; priority: 'default' | 'high' | 'low' | 'max' | 'min';
topic: string; topic: string;
type: 'ntfy'; type: 'ntfy';
password?: string;
serverUrl?: string; serverUrl?: string;
token?: string; username?: string;
} | { } | {
priority: number; priority: number;
serverUrl: string; serverUrl: string;
token: string; token: string;
type: 'gotify'; type: 'gotify';
path?: string;
} | { } | {
shoutrrrUrl: string; shoutrrrUrl: string;
type: 'custom'; type: 'custom';
@@ -1873,6 +1875,7 @@ export type GetScheduleNotificationsResponses = {
type: 'discord'; type: 'discord';
webhookUrl: string; webhookUrl: string;
avatarUrl?: string; avatarUrl?: string;
threadId?: string;
username?: string; username?: string;
} | { } | {
type: 'slack'; type: 'slack';
@@ -1940,13 +1943,15 @@ export type UpdateScheduleNotificationsResponses = {
priority: 'default' | 'high' | 'low' | 'max' | 'min'; priority: 'default' | 'high' | 'low' | 'max' | 'min';
topic: string; topic: string;
type: 'ntfy'; type: 'ntfy';
password?: string;
serverUrl?: string; serverUrl?: string;
token?: string; username?: string;
} | { } | {
priority: number; priority: number;
serverUrl: string; serverUrl: string;
token: string; token: string;
type: 'gotify'; type: 'gotify';
path?: string;
} | { } | {
shoutrrrUrl: string; shoutrrrUrl: string;
type: 'custom'; type: 'custom';
@@ -1954,6 +1959,7 @@ export type UpdateScheduleNotificationsResponses = {
type: 'discord'; type: 'discord';
webhookUrl: string; webhookUrl: string;
avatarUrl?: string; avatarUrl?: string;
threadId?: string;
username?: string; username?: string;
} | { } | {
type: 'slack'; type: 'slack';
@@ -2010,13 +2016,15 @@ export type ListNotificationDestinationsResponses = {
priority: 'default' | 'high' | 'low' | 'max' | 'min'; priority: 'default' | 'high' | 'low' | 'max' | 'min';
topic: string; topic: string;
type: 'ntfy'; type: 'ntfy';
password?: string;
serverUrl?: string; serverUrl?: string;
token?: string; username?: string;
} | { } | {
priority: number; priority: number;
serverUrl: string; serverUrl: string;
token: string; token: string;
type: 'gotify'; type: 'gotify';
path?: string;
} | { } | {
shoutrrrUrl: string; shoutrrrUrl: string;
type: 'custom'; type: 'custom';
@@ -2024,6 +2032,7 @@ export type ListNotificationDestinationsResponses = {
type: 'discord'; type: 'discord';
webhookUrl: string; webhookUrl: string;
avatarUrl?: string; avatarUrl?: string;
threadId?: string;
username?: string; username?: string;
} | { } | {
type: 'slack'; type: 'slack';
@@ -2064,13 +2073,15 @@ export type CreateNotificationDestinationData = {
priority: 'default' | 'high' | 'low' | 'max' | 'min'; priority: 'default' | 'high' | 'low' | 'max' | 'min';
topic: string; topic: string;
type: 'ntfy'; type: 'ntfy';
password?: string;
serverUrl?: string; serverUrl?: string;
token?: string; username?: string;
} | { } | {
priority: number; priority: number;
serverUrl: string; serverUrl: string;
token: string; token: string;
type: 'gotify'; type: 'gotify';
path?: string;
} | { } | {
shoutrrrUrl: string; shoutrrrUrl: string;
type: 'custom'; type: 'custom';
@@ -2078,6 +2089,7 @@ export type CreateNotificationDestinationData = {
type: 'discord'; type: 'discord';
webhookUrl: string; webhookUrl: string;
avatarUrl?: string; avatarUrl?: string;
threadId?: string;
username?: string; username?: string;
} | { } | {
type: 'slack'; type: 'slack';
@@ -2117,13 +2129,15 @@ export type CreateNotificationDestinationResponses = {
priority: 'default' | 'high' | 'low' | 'max' | 'min'; priority: 'default' | 'high' | 'low' | 'max' | 'min';
topic: string; topic: string;
type: 'ntfy'; type: 'ntfy';
password?: string;
serverUrl?: string; serverUrl?: string;
token?: string; username?: string;
} | { } | {
priority: number; priority: number;
serverUrl: string; serverUrl: string;
token: string; token: string;
type: 'gotify'; type: 'gotify';
path?: string;
} | { } | {
shoutrrrUrl: string; shoutrrrUrl: string;
type: 'custom'; type: 'custom';
@@ -2131,6 +2145,7 @@ export type CreateNotificationDestinationResponses = {
type: 'discord'; type: 'discord';
webhookUrl: string; webhookUrl: string;
avatarUrl?: string; avatarUrl?: string;
threadId?: string;
username?: string; username?: string;
} | { } | {
type: 'slack'; type: 'slack';
@@ -2217,13 +2232,15 @@ export type GetNotificationDestinationResponses = {
priority: 'default' | 'high' | 'low' | 'max' | 'min'; priority: 'default' | 'high' | 'low' | 'max' | 'min';
topic: string; topic: string;
type: 'ntfy'; type: 'ntfy';
password?: string;
serverUrl?: string; serverUrl?: string;
token?: string; username?: string;
} | { } | {
priority: number; priority: number;
serverUrl: string; serverUrl: string;
token: string; token: string;
type: 'gotify'; type: 'gotify';
path?: string;
} | { } | {
shoutrrrUrl: string; shoutrrrUrl: string;
type: 'custom'; type: 'custom';
@@ -2231,6 +2248,7 @@ export type GetNotificationDestinationResponses = {
type: 'discord'; type: 'discord';
webhookUrl: string; webhookUrl: string;
avatarUrl?: string; avatarUrl?: string;
threadId?: string;
username?: string; username?: string;
} | { } | {
type: 'slack'; type: 'slack';
@@ -2271,13 +2289,15 @@ export type UpdateNotificationDestinationData = {
priority: 'default' | 'high' | 'low' | 'max' | 'min'; priority: 'default' | 'high' | 'low' | 'max' | 'min';
topic: string; topic: string;
type: 'ntfy'; type: 'ntfy';
password?: string;
serverUrl?: string; serverUrl?: string;
token?: string; username?: string;
} | { } | {
priority: number; priority: number;
serverUrl: string; serverUrl: string;
token: string; token: string;
type: 'gotify'; type: 'gotify';
path?: string;
} | { } | {
shoutrrrUrl: string; shoutrrrUrl: string;
type: 'custom'; type: 'custom';
@@ -2285,6 +2305,7 @@ export type UpdateNotificationDestinationData = {
type: 'discord'; type: 'discord';
webhookUrl: string; webhookUrl: string;
avatarUrl?: string; avatarUrl?: string;
threadId?: string;
username?: string; username?: string;
} | { } | {
type: 'slack'; type: 'slack';
@@ -2334,13 +2355,15 @@ export type UpdateNotificationDestinationResponses = {
priority: 'default' | 'high' | 'low' | 'max' | 'min'; priority: 'default' | 'high' | 'low' | 'max' | 'min';
topic: string; topic: string;
type: 'ntfy'; type: 'ntfy';
password?: string;
serverUrl?: string; serverUrl?: string;
token?: string; username?: string;
} | { } | {
priority: number; priority: number;
serverUrl: string; serverUrl: string;
token: string; token: string;
type: 'gotify'; type: 'gotify';
path?: string;
} | { } | {
shoutrrrUrl: string; shoutrrrUrl: string;
type: 'custom'; type: 'custom';
@@ -2348,6 +2371,7 @@ export type UpdateNotificationDestinationResponses = {
type: 'discord'; type: 'discord';
webhookUrl: string; webhookUrl: string;
avatarUrl?: string; avatarUrl?: string;
threadId?: string;
username?: string; username?: string;
} | { } | {
type: 'slack'; type: 'slack';

View File

@@ -370,6 +370,22 @@ export const CreateNotificationForm = ({ onSubmit, mode = "create", initialValue
</FormItem> </FormItem>
)} )}
/> />
<FormField
control={form.control}
name="threadId"
render={({ field }) => (
<FormItem>
<FormLabel>Thread ID (Optional)</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormDescription>
ID of the thread to post messages in. Leave empty to post in the main channel.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</> </>
)} )}
@@ -423,6 +439,20 @@ export const CreateNotificationForm = ({ onSubmit, mode = "create", initialValue
</FormItem> </FormItem>
)} )}
/> />
<FormField
control={form.control}
name="path"
render={({ field }) => (
<FormItem>
<FormLabel>Path (Optional)</FormLabel>
<FormControl>
<Input {...field} placeholder="/custom/path" />
</FormControl>
<FormDescription>Custom path on the Gotify server, if applicable.</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</> </>
)} )}
@@ -458,14 +488,28 @@ export const CreateNotificationForm = ({ onSubmit, mode = "create", initialValue
/> />
<FormField <FormField
control={form.control} control={form.control}
name="token" name="username"
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
<FormLabel>Access Token (Optional)</FormLabel> <FormLabel>Username (Optional)</FormLabel>
<FormControl>
<Input {...field} placeholder="username" />
</FormControl>
<FormDescription>Username for server authentication, if required.</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormItem>
<FormLabel>Password (Optional)</FormLabel>
<FormControl> <FormControl>
<Input {...field} type="password" placeholder="••••••••" /> <Input {...field} type="password" placeholder="••••••••" />
</FormControl> </FormControl>
<FormDescription>Required if the topic is protected.</FormDescription> <FormDescription>Password for server authentication, if required.</FormDescription>
<FormMessage /> <FormMessage />
</FormItem> </FormItem>
)} )}

View File

@@ -36,12 +36,14 @@ export const discordNotificationConfigSchema = type({
webhookUrl: "string", webhookUrl: "string",
username: "string?", username: "string?",
avatarUrl: "string?", avatarUrl: "string?",
threadId: "string?",
}); });
export const gotifyNotificationConfigSchema = type({ export const gotifyNotificationConfigSchema = type({
type: "'gotify'", type: "'gotify'",
serverUrl: "string", serverUrl: "string",
token: "string", token: "string",
path: "string?",
priority: "0 <= number <= 10", priority: "0 <= number <= 10",
}); });

View File

@@ -17,7 +17,10 @@ export function buildDiscordShoutrrrUrl(config: Extract<NotificationConfig, { ty
params.append("username", config.username); params.append("username", config.username);
} }
if (config.avatarUrl) { if (config.avatarUrl) {
params.append("avatar_url", config.avatarUrl); params.append("avatarurl", config.avatarUrl);
}
if (config.threadId) {
params.append("thread_id", config.threadId);
} }
if (params.toString()) { if (params.toString()) {

View File

@@ -4,8 +4,9 @@ export function buildGotifyShoutrrrUrl(config: Extract<NotificationConfig, { typ
const url = new URL(config.serverUrl); const url = new URL(config.serverUrl);
const hostname = url.hostname; const hostname = url.hostname;
const port = url.port ? `:${url.port}` : ""; const port = url.port ? `:${url.port}` : "";
const path = config.path ? `/${config.path.replace(/^\/+|\/+$/g, "")}` : "";
let shoutrrrUrl = `gotify://${hostname}${port}/${config.token}`; let shoutrrrUrl = `gotify://${hostname}${port}${path}/${config.token}`;
if (config.priority !== undefined) { if (config.priority !== undefined) {
shoutrrrUrl += `?priority=${config.priority}`; shoutrrrUrl += `?priority=${config.priority}`;

View File

@@ -20,7 +20,7 @@ export function buildSlackShoutrrrUrl(config: Extract<NotificationConfig, { type
params.append("username", config.username); params.append("username", config.username);
} }
if (config.iconEmoji) { if (config.iconEmoji) {
params.append("icon", config.iconEmoji); params.append("icon_emoji", config.iconEmoji);
} }
if (params.toString()) { if (params.toString()) {

View File

@@ -58,7 +58,7 @@ async function encryptSensitiveFields(config: NotificationConfig): Promise<Notif
case "ntfy": case "ntfy":
return { return {
...config, ...config,
token: config.token ? await cryptoUtils.encrypt(config.token) : undefined, password: config.password ? await cryptoUtils.encrypt(config.password) : undefined,
}; };
case "pushover": case "pushover":
return { return {
@@ -100,7 +100,7 @@ async function decryptSensitiveFields(config: NotificationConfig): Promise<Notif
case "ntfy": case "ntfy":
return { return {
...config, ...config,
token: config.token ? await cryptoUtils.decrypt(config.token) : undefined, password: config.password ? await cryptoUtils.decrypt(config.password) : undefined,
}; };
case "pushover": case "pushover":
return { return {