aboutsummaryrefslogtreecommitdiffstats
path: root/mod/notification-ntfy.rsc
blob: 7e4eaf0c3c03f99e5a0118309e86853665c16d01 (about) (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#!rsc by RouterOS
# RouterOS script: mod/notification-ntfy
# Copyright (c) 2013-2024 Christian Hesse <mail@eworm.de>
# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md
#
# requires RouterOS, version=7.14
#
# send notifications via Ntfy (ntfy.sh)
# https://git.eworm.de/cgit/routeros-scripts/about/doc/mod/notification-ntfy.md

:global FlushNtfyQueue;
:global NotificationFunctions;
:global PurgeNtfyQueue;
:global SendNtfy;
:global SendNtfy2;

# flush ntfy queue
:set FlushNtfyQueue do={ :do {
  :global NtfyQueue;
  :global NtfyMessageIDs;

  :global IsFullyConnected;
  :global LogPrint;

  :if ([ $IsFullyConnected ] = false) do={
    $LogPrint debug $0 ("System is not fully connected, not flushing.");
    :return false;
  }

  :local AllDone true;
  :local QueueLen [ :len $NtfyQueue ];

  :if ([ :len [ /system/scheduler/find where name="_FlushNtfyQueue" ] ] > 0 && $QueueLen = 0) do={
    $LogPrint warning $0 ("Flushing Ntfy messages from scheduler, but queue is empty.");
  }

  :foreach Id,Message in=$NtfyQueue do={
    :if ([ :typeof $Message ] = "array" ) do={
      :do {
        /tool/fetch check-certificate=yes-without-crl output=none http-method=post \
          http-header-field=($Message->"headers") http-data=($Message->"text") \
          ($Message->"url") user=($Message->"user") password=($Message->"pass") as-value;
        :set ($NtfyQueue->$Id);
      } on-error={
        $LogPrint debug $0 ("Sending queued Ntfy message failed.");
        :set AllDone false;
      }
    }
  }

  :if ($AllDone = true && $QueueLen = [ :len $NtfyQueue ]) do={
    /system/scheduler/remove [ find where name="_FlushNtfyQueue" ];
    :set NtfyQueue;
  }
} on-error={
  :global ExitError; $ExitError false $0;
} }

# send notification via ntfy - expects one array argument
:set ($NotificationFunctions->"ntfy") do={
  :local Notification $1;

  :global Identity;
  :global IdentityExtra;
  :global NtfyQueue;
  :global NtfyServer;
  :global NtfyServerOverride;
  :global NtfyServerPass;
  :global NtfyServerPassOverride;
  :global NtfyServerToken;
  :global NtfyServerTokenOverride;
  :global NtfyServerUser;
  :global NtfyServerUserOverride;
  :global NtfyTopic;
  :global NtfyTopicOverride;

  :global CertificateAvailable;
  :global EitherOr;
  :global FetchUserAgentStr;
  :global IfThenElse;
  :global LogPrint;
  :global SymbolForNotification;
  :global UrlEncode;

  :local Server [ $EitherOr ($NtfyServerOverride->($Notification->"origin")) $NtfyServer ];
  :local User [ $EitherOr ($NtfyServerUserOverride->($Notification->"origin")) $NtfyServerUser ];
  :local Pass [ $EitherOr ($NtfyServerPassOverride->($Notification->"origin")) $NtfyServerPass ];
  :local Token [ $EitherOr ($NtfyServerTokenOverride->($Notification->"origin")) $NtfyServerToken ];
  :local Topic [ $EitherOr ($NtfyTopicOverride->($Notification->"origin")) $NtfyTopic ];

  :if ([ :len $Topic ] = 0) do={
    :return false;
  }

  :local Url ("https://" . $Server . "/" . [ $UrlEncode $Topic ]);
  :local Headers ({ [ $FetchUserAgentStr ($Notification->"origin") ]; \
    ("Priority: " . [ $IfThenElse ($Notification->"silent") "low" "default" ]); \
    ("Title: " . "[" . $IdentityExtra . $Identity . "] " . ($Notification->"subject")) });
  :if ([ :len $Token ] > 0) do={
    :set Headers ($Headers, ("Authorization: Bearer " . $Token));
  }
  :local Text (($Notification->"message") . "\n");
  :if ([ :len ($Notification->"link") ] > 0) do={
    :set Text ($Text . "\n" . [ $SymbolForNotification "link" ] . ($Notification->"link"));
  }

  :do {
    :if ($Server = "ntfy.sh") do={
      :if ([ $CertificateAvailable "ISRG Root X1" ] = false) do={
        $LogPrint warning $0 ("Downloading required certificate failed.");
        :error false;
      }
    }
    /tool/fetch check-certificate=yes-without-crl output=none http-method=post \
      http-header-field=$Headers http-data=$Text $Url user=$User password=$Pass as-value;
  } on-error={
    $LogPrint info $0 ("Failed sending ntfy notification! Queuing...");

    :if ([ :typeof $NtfyQueue ] = "nothing") do={
      :set NtfyQueue ({});
    }
    :set Text ($Text . "\n" . [ $SymbolForNotification "alarm-clock" ] . \
      "This message was queued since " . [ /system/clock/get date ] . " " . \
      [ /system/clock/get time ] . " and may be obsolete.");
    :set ($NtfyQueue->[ :len $NtfyQueue ]) \
      { url=$Url; user=$User; pass=$Pass; headers=$Headers; text=$Text };
    :if ([ :len [ /system/scheduler/find where name="_FlushNtfyQueue" ] ] = 0) do={
      /system/scheduler/add name="_FlushNtfyQueue" interval=1m start-time=startup \
        on-event=(":global FlushNtfyQueue; \$FlushNtfyQueue;");
    }
  }
}

# purge the Ntfy queue
:set PurgeNtfyQueue do={
  :global NtfyQueue;

  /system/scheduler/remove [ find where name="_FlushNtfyQueue" ];
  :set NtfyQueue;
}

# send notification via ntfy - expects at least two string arguments
:set SendNtfy do={ :do {
  :global SendNtfy2;

  $SendNtfy2 ({ origin=$0; subject=$1; message=$2; link=$3; silent=$4 });
} on-error={
  :global ExitError; $ExitError false $0;
} }

# send notification via ntfy - expects one array argument
:set SendNtfy2 do={
  :local Notification $1;

  :global NotificationFunctions;

  ($NotificationFunctions->"ntfy") ("\$NotificationFunctions->\"ntfy\"") $Notification;
}