66import sys
77from collections .abc import MutableMapping
88from dataclasses import dataclass
9- from typing import NoReturn
9+ from typing import Callable , NoReturn , Self
1010
1111import requests
1212
@@ -54,10 +54,9 @@ class RequestParameter:
5454
5555@dataclass
5656class Context :
57- url : str
5857 request_parameter : RequestParameter
5958 message : Message
60- data : dict [ str , str ]
59+ send_function : Callable [[ Self ], int ]
6160
6261
6362# .
@@ -110,15 +109,9 @@ def _get_context_parameter(raw_context: PluginNotificationContext) -> Errors | C
110109 endpoint = raw_context ["PARAMETER_MODEM_TYPE" ]
111110 if endpoint == "trb140" :
112111 return Context (
113- url = request_parameter .url + "/cgi-bin/sms_send" ,
114112 request_parameter = request_parameter ,
113+ send_function = _send_func_trb140 ,
115114 message = message ,
116- data = {
117- "username" : request_parameter .user ,
118- "password" : request_parameter .pwd ,
119- "number" : request_parameter .recipient ,
120- "text" : message ,
121- },
122115 )
123116
124117 return Errors (["Unknown unsupported modem: %s" % endpoint ])
@@ -157,25 +150,95 @@ def _get_request_params_from_context(
157150# '----------------------------------------------------------------------'
158151
159152
160- def process_notifications (context : Context ) -> int :
161- """Main processing of notifications for this API endpoint."""
162- response = requests .post (
163- context .url ,
164- proxies = context .request_parameter .proxies ,
165- timeout = context .request_parameter .timeout ,
166- data = context .data ,
167- verify = context .request_parameter .verify ,
168- )
153+ def _send_func_trb140 (context : Context ) -> int :
154+ """Main processing of notifications for trb140"""
155+ try :
156+ response = _trb140_mobile_post (context )
157+ if "<!doctype html" in response .text .lower ():
158+ return _trb140_api (context )
159+
160+ response .raise_for_status ()
169161
170- if response .status_code != 200 or response .content != b"OK\n " :
171- sys .stderr .write (f"Error Status: { response .status_code } Details: { response .content !r} \n " )
162+ if response .status_code != 200 or not response .content .startswith (b"OK\n " ):
163+ sys .stderr .write (
164+ f"Error Status: { response .status_code } Details: { response .content !r} \n "
165+ )
166+ return 2
167+
168+ except requests .exceptions .HTTPError as e :
169+ sys .stderr .write (f"HTTPError sending SMS: { e } , { response .content !r} \n " )
172170 return 2
173171
174- sys .stdout .write ("Notification successfully send via sms.\n " )
172+ except Exception as e :
173+ sys .stderr .write (f"Error sending SMS: { e } \n " )
174+ return 2
175175
176+ sys .stdout .write ("Notification successfully sent via sms.\n " )
176177 return 0
177178
178179
180+ def _trb140_api (context : Context ) -> int :
181+ """Since firmware 7.14 the API has to be used"""
182+ try :
183+ token_response = requests .post (
184+ context .request_parameter .url + "/api/login" ,
185+ json = {
186+ "username" : context .request_parameter .user ,
187+ "password" : context .request_parameter .pwd ,
188+ },
189+ headers = {"Content-Type" : "application/json" },
190+ proxies = context .request_parameter .proxies ,
191+ timeout = context .request_parameter .timeout ,
192+ verify = context .request_parameter .verify ,
193+ )
194+ token_response .raise_for_status ()
195+ token = token_response .json ().get ("data" , {}).get ("token" )
196+ if not token :
197+ raise ValueError ("Got no session token.\n " )
198+
199+ sms_data = {
200+ "number" : context .request_parameter .recipient ,
201+ "message" : context .message ,
202+ "modem" : "3-1" ,
203+ }
204+
205+ sms_response = requests .post (
206+ context .request_parameter .url + "/api/messages/actions/send" ,
207+ json = {"data" : sms_data },
208+ headers = {"Content-Type" : "application/json" , "Authorization" : f"Bearer { token } " },
209+ proxies = context .request_parameter .proxies ,
210+ timeout = context .request_parameter .timeout ,
211+ verify = context .request_parameter .verify ,
212+ )
213+ sms_response .raise_for_status ()
214+
215+ if sms_response .json ().get ("success" ) is True and sms_response .status_code == 200 :
216+ sys .stdout .write ("Notification successfully sent via sms.\n " )
217+ return 0
218+
219+ return 2
220+
221+ except ValueError as e :
222+ sys .stderr .write (f"Error calling API: { e } " )
223+ return 2
224+
225+
226+ def _trb140_mobile_post (context : Context ) -> requests .Response :
227+ """This endpoint has to be used until firmware version 7.13"""
228+ return requests .post (
229+ context .request_parameter .url + "/cgi-bin/sms_send" ,
230+ proxies = context .request_parameter .proxies ,
231+ timeout = context .request_parameter .timeout ,
232+ data = {
233+ "username" : context .request_parameter .user ,
234+ "password" : context .request_parameter .pwd ,
235+ "number" : context .request_parameter .recipient ,
236+ "text" : context .message ,
237+ },
238+ verify = context .request_parameter .verify ,
239+ )
240+
241+
179242def main () -> NoReturn :
180243 """Construct needed context and call the related class."""
181244 raw_context : PluginNotificationContext = collect_context ()
@@ -186,7 +249,7 @@ def main() -> NoReturn:
186249 sys .stdout .write (" " .join (context ))
187250 sys .exit (2 )
188251
189- sys .exit (process_notifications (context ))
252+ sys .exit (context . send_function (context ))
190253
191254
192255# .
0 commit comments