From 09cb65ae05e6ead475964269a88f609278e899dd Mon Sep 17 00:00:00 2001 From: Markus Opolka Date: Mon, 29 Jun 2026 10:31:47 +0200 Subject: [PATCH 1/5] Remove symlinks and add .py suffix to scripts Users can still rename the scripts however they like. --- check_smseagle | 200 -------------------------------------------- check_smseagle.py | 201 ++++++++++++++++++++++++++++++++++++++++++++- notify_smseagle | 123 --------------------------- notify_smseagle.py | 124 +++++++++++++++++++++++++++- 4 files changed, 323 insertions(+), 325 deletions(-) delete mode 100755 check_smseagle mode change 120000 => 100755 check_smseagle.py delete mode 100755 notify_smseagle mode change 120000 => 100755 notify_smseagle.py diff --git a/check_smseagle b/check_smseagle deleted file mode 100755 index 8eaae26..0000000 --- a/check_smseagle +++ /dev/null @@ -1,200 +0,0 @@ -#!/usr/bin/python3 -# Copyright (C) 2016 NETWAYS GmbH, https://netways.de -# -# Author: Alexander A. Klimov -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - - -from argparse import ArgumentParser -from urllib.parse import urljoin -import os -import sys -import urllib3 -import requests - -__version__ = "2.0.0" - -# Return code level -# 0 - OK - The plugin was able to check the service and it appeared to be functioning properly -# 1 - WARNING - The plugin was able to check the service, but it appeared to be above some "warning" -# threshold or did not appear to be working properly -# 2 - CRITICAL - The plugin detected that either the service was not running or it was above some "critical" threshold -# 3 - UNKNOWN - Invalid command line arguments were supplied to the plugin or low-level failures -OK = 0 -WARNING = 1 -CRITICAL = 2 -UNKNOWN = 3 - - -def generate_output(status='[UNKNOWN]', description=None, perfdata=None): - """ - Generate plugin data output with status and perfdata - """ - - pluginoutput = str(status) - - if description: - pluginoutput += ' - ' + str(description) - - # Perfdata we explicitly extracted from the data - if perfdata: - pluginoutput += '|' + ' '.join( - [key.lower().replace(" ", "_").replace(",", "") + '=' + str(value) for key, value in perfdata.items()]) - - print(pluginoutput) - - -def commandline(args): - """ - Parse commandline arguments. - """ - def environ_or_required(key): - return ({'default': os.environ.get(key)} if os.environ.get(key) else {'required': True}) - - parser = ArgumentParser(description="check_smseagle (Version: %s)" % (__version__)) - - parser.add_argument("-u", "--url", - **environ_or_required('CHECK_SMSEAGLE_API_URL'), - help="Hostname of the device (CHECK_SMSEAGLE_API_URL)") - parser.add_argument('-t', '--token', - **environ_or_required('CHECK_SMSEAGLE_API_TOKEN'), - help="API token for authentication (CHECK_SMSEAGLE_API_TOKEN)") - parser.add_argument("-M", "--modem", - help="Modem ID") - parser.add_argument("-w", "--warning", default=10, type=int, - help="Warning if the GSM signal strength is less than PERCENT. Must be greater than --critical") - parser.add_argument("-c", "--critical", default=5, type=int, - help="Critical if the GSM signal strength is less than PERCENT") - parser.add_argument("-T", "--timeout", help="Seconds before connection times out (default 10)", - default=10, - type=int) - parser.add_argument("--insecure", - action="store_true", - default=False, - help="Allow insecure SSL connections (default False)") - - args = parser.parse_args(args) - - if args.warning == args.critical: - print("[UNKNOWN] - The critical and warning thresholds must not be identical") - sys.exit(3) - - if args.critical > args.warning: - print("[UNKNOWN] - The critical threshold must not be greater than the warning") - sys.exit(3) - - return args - - -def make_request(args, url): - """ - Prepare and submits request with given arguments. - Returns Response. - - Request should be similar to: - { - "modem_no": 2, - "signal_strength": 57 - } - """ - - # Compress warnings if insecure and change request verification - verify = True - if args.insecure: - urllib3.disable_warnings() - verify = False - - response = requests.request( - method="GET", - headers={ - "accept": "application/json", - "access-token": args.token - }, - verify=verify, - url=url, - timeout=args.timeout - ) - - if response.status_code != 200: - raise RuntimeError("Could not get response") - - return response - - -def prepare_url(args): - """ - Prepare url for the request - """ - base_url = urljoin(args.url, "/api/v2/modem/signal") - if args.modem is not None: - url = base_url + "/" + args.modem - return url - - return base_url - - -def get_strength(response): - """ - Parse response and returns signal_strength of given modem - """ - data = response.json() - return data["signal_strength"] - - -def main(args): - url = prepare_url(args) - - try: - response = make_request(args, url) - - except Exception as data_exc: # pylint: disable=broad-except - print("[UNKNOWN] - Couldn't fetch the GSM signal strength because of an error", data_exc) - return UNKNOWN - - try: - strength = get_strength(response) - except Exception as parse_exc: # pylint: disable=broad-except - print("[UNKNOWN] - Couldn't evaluate the GSM signal strength", parse_exc) - return UNKNOWN - - if strength == -1: - generate_output("[CRITICAL]", 'GSM modem is disconnected from GSM network') - return CRITICAL - - if strength < args.critical: - exit_code = CRITICAL - status = "[CRITICAL]" - elif strength < args.warning: - exit_code = WARNING - status = "[WARNING]" - else: - exit_code = OK - status = "[OK]" - - generate_output(status, f"GSM signal strength: {strength}%", - {'gsm_signal_strenght': f"{strength}%;{args.warning}:;{args.critical}:;;"}) - return exit_code - - -if __name__ == '__main__': # pragma: no cover - try: - ARGS = commandline(sys.argv[1:]) - sys.exit(main(ARGS)) - except SystemExit: - # Re-throw the exception - raise sys.exc_info()[1].with_traceback(sys.exc_info()[2]) # pylint: disable=raise-missing-from - except: - print("[UNKNOWN] - Error: %s" % (str(sys.exc_info()[1]))) - sys.exit(3) diff --git a/check_smseagle.py b/check_smseagle.py deleted file mode 120000 index e55c5bb..0000000 --- a/check_smseagle.py +++ /dev/null @@ -1 +0,0 @@ -check_smseagle \ No newline at end of file diff --git a/check_smseagle.py b/check_smseagle.py new file mode 100755 index 0000000..8eaae26 --- /dev/null +++ b/check_smseagle.py @@ -0,0 +1,200 @@ +#!/usr/bin/python3 +# Copyright (C) 2016 NETWAYS GmbH, https://netways.de +# +# Author: Alexander A. Klimov +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +from argparse import ArgumentParser +from urllib.parse import urljoin +import os +import sys +import urllib3 +import requests + +__version__ = "2.0.0" + +# Return code level +# 0 - OK - The plugin was able to check the service and it appeared to be functioning properly +# 1 - WARNING - The plugin was able to check the service, but it appeared to be above some "warning" +# threshold or did not appear to be working properly +# 2 - CRITICAL - The plugin detected that either the service was not running or it was above some "critical" threshold +# 3 - UNKNOWN - Invalid command line arguments were supplied to the plugin or low-level failures +OK = 0 +WARNING = 1 +CRITICAL = 2 +UNKNOWN = 3 + + +def generate_output(status='[UNKNOWN]', description=None, perfdata=None): + """ + Generate plugin data output with status and perfdata + """ + + pluginoutput = str(status) + + if description: + pluginoutput += ' - ' + str(description) + + # Perfdata we explicitly extracted from the data + if perfdata: + pluginoutput += '|' + ' '.join( + [key.lower().replace(" ", "_").replace(",", "") + '=' + str(value) for key, value in perfdata.items()]) + + print(pluginoutput) + + +def commandline(args): + """ + Parse commandline arguments. + """ + def environ_or_required(key): + return ({'default': os.environ.get(key)} if os.environ.get(key) else {'required': True}) + + parser = ArgumentParser(description="check_smseagle (Version: %s)" % (__version__)) + + parser.add_argument("-u", "--url", + **environ_or_required('CHECK_SMSEAGLE_API_URL'), + help="Hostname of the device (CHECK_SMSEAGLE_API_URL)") + parser.add_argument('-t', '--token', + **environ_or_required('CHECK_SMSEAGLE_API_TOKEN'), + help="API token for authentication (CHECK_SMSEAGLE_API_TOKEN)") + parser.add_argument("-M", "--modem", + help="Modem ID") + parser.add_argument("-w", "--warning", default=10, type=int, + help="Warning if the GSM signal strength is less than PERCENT. Must be greater than --critical") + parser.add_argument("-c", "--critical", default=5, type=int, + help="Critical if the GSM signal strength is less than PERCENT") + parser.add_argument("-T", "--timeout", help="Seconds before connection times out (default 10)", + default=10, + type=int) + parser.add_argument("--insecure", + action="store_true", + default=False, + help="Allow insecure SSL connections (default False)") + + args = parser.parse_args(args) + + if args.warning == args.critical: + print("[UNKNOWN] - The critical and warning thresholds must not be identical") + sys.exit(3) + + if args.critical > args.warning: + print("[UNKNOWN] - The critical threshold must not be greater than the warning") + sys.exit(3) + + return args + + +def make_request(args, url): + """ + Prepare and submits request with given arguments. + Returns Response. + + Request should be similar to: + { + "modem_no": 2, + "signal_strength": 57 + } + """ + + # Compress warnings if insecure and change request verification + verify = True + if args.insecure: + urllib3.disable_warnings() + verify = False + + response = requests.request( + method="GET", + headers={ + "accept": "application/json", + "access-token": args.token + }, + verify=verify, + url=url, + timeout=args.timeout + ) + + if response.status_code != 200: + raise RuntimeError("Could not get response") + + return response + + +def prepare_url(args): + """ + Prepare url for the request + """ + base_url = urljoin(args.url, "/api/v2/modem/signal") + if args.modem is not None: + url = base_url + "/" + args.modem + return url + + return base_url + + +def get_strength(response): + """ + Parse response and returns signal_strength of given modem + """ + data = response.json() + return data["signal_strength"] + + +def main(args): + url = prepare_url(args) + + try: + response = make_request(args, url) + + except Exception as data_exc: # pylint: disable=broad-except + print("[UNKNOWN] - Couldn't fetch the GSM signal strength because of an error", data_exc) + return UNKNOWN + + try: + strength = get_strength(response) + except Exception as parse_exc: # pylint: disable=broad-except + print("[UNKNOWN] - Couldn't evaluate the GSM signal strength", parse_exc) + return UNKNOWN + + if strength == -1: + generate_output("[CRITICAL]", 'GSM modem is disconnected from GSM network') + return CRITICAL + + if strength < args.critical: + exit_code = CRITICAL + status = "[CRITICAL]" + elif strength < args.warning: + exit_code = WARNING + status = "[WARNING]" + else: + exit_code = OK + status = "[OK]" + + generate_output(status, f"GSM signal strength: {strength}%", + {'gsm_signal_strenght': f"{strength}%;{args.warning}:;{args.critical}:;;"}) + return exit_code + + +if __name__ == '__main__': # pragma: no cover + try: + ARGS = commandline(sys.argv[1:]) + sys.exit(main(ARGS)) + except SystemExit: + # Re-throw the exception + raise sys.exc_info()[1].with_traceback(sys.exc_info()[2]) # pylint: disable=raise-missing-from + except: + print("[UNKNOWN] - Error: %s" % (str(sys.exc_info()[1]))) + sys.exit(3) diff --git a/notify_smseagle b/notify_smseagle deleted file mode 100755 index 32a7937..0000000 --- a/notify_smseagle +++ /dev/null @@ -1,123 +0,0 @@ -#!/usr/bin/python3 - -# Copyright (C) 2016 NETWAYS GmbH, https://netways.de -# -# Author: Alexander A. Klimov -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - - -from argparse import ArgumentParser -from urllib.parse import urljoin -import json -import os -import sys -import requests -import urllib3 - -__version__ = '2.0.0' - - -def commandline(args): - """ - Defines the CLI Parser and parses the arguments - """ - def environ_or_required(key): - return ({'default': os.environ.get(key)} if os.environ.get(key) else {'required': True}) - - parser = ArgumentParser(description="notify_smseagle (Version: %s)" % (__version__)) - - parser.add_argument("-u", "--url", - **environ_or_required('CHECK_SMSEAGLE_API_URL'), - help="Hostname of the device (CHECK_SMSEAGLE_API_URL)") - parser.add_argument('-t', '--token', - **environ_or_required('CHECK_SMSEAGLE_API_TOKEN'), - help="API token for authentication (CHECK_SMSEAGLE_API_TOKEN)") - parser.add_argument('-r', '--recipient', required=True, - help="Recipient for the message (required)") - parser.add_argument('-m', '--message', required=True, - help="The message to send (required)") - parser.add_argument('-T', '--timeout', help='Seconds before connection times out (default 10)', - default=10, - type=int) - parser.add_argument('--insecure', - action='store_true', - default=False, - help='Allow insecure SSL connections (default False)') - - return parser.parse_args(args) - - -def prepare_data(args): - return json.dumps({ - "to": [ - args.recipient - ], - "text": args.message - }) - - -def make_request(args, data): - """ - Prepare and submits request with given arguments. - """ - - # Compress warnings if insecure and change request verification - verify = True - if args.insecure: - urllib3.disable_warnings() - verify = False - - resp = requests.request( - method="POST", - headers={ - 'Content-Type': 'application/json', - 'access-token': args.token - }, - verify=verify, - url=urljoin(args.url, "/api/v2/messages/sms"), - data=data, - timeout=args.timeout - ) - - return resp - - -def main(args): - try: - data = prepare_data(args) - except Exception as exc: # pylint: disable=broad-except - print("Error: Could not prepare json data.", exc) - return 3 - - try: - response = make_request(args, data) - except Exception as exc: # pylint: disable=broad-except - print("Error: Could not connect to SMS Eagle and send message.", exc) - return 3 - - if not response.status_code == 200: - print("Error: Could not send message.", response) - return 2 - - return 0 - - -if __name__ == '__main__': # pragma: no cover - try: - ARGS = commandline(sys.argv[1:]) - sys.exit(main(ARGS)) - except Exception as e: # pylint: disable=broad-except - print("Error: ", e) - sys.exit(3) diff --git a/notify_smseagle.py b/notify_smseagle.py deleted file mode 120000 index c6999ee..0000000 --- a/notify_smseagle.py +++ /dev/null @@ -1 +0,0 @@ -notify_smseagle \ No newline at end of file diff --git a/notify_smseagle.py b/notify_smseagle.py new file mode 100755 index 0000000..32a7937 --- /dev/null +++ b/notify_smseagle.py @@ -0,0 +1,123 @@ +#!/usr/bin/python3 + +# Copyright (C) 2016 NETWAYS GmbH, https://netways.de +# +# Author: Alexander A. Klimov +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +from argparse import ArgumentParser +from urllib.parse import urljoin +import json +import os +import sys +import requests +import urllib3 + +__version__ = '2.0.0' + + +def commandline(args): + """ + Defines the CLI Parser and parses the arguments + """ + def environ_or_required(key): + return ({'default': os.environ.get(key)} if os.environ.get(key) else {'required': True}) + + parser = ArgumentParser(description="notify_smseagle (Version: %s)" % (__version__)) + + parser.add_argument("-u", "--url", + **environ_or_required('CHECK_SMSEAGLE_API_URL'), + help="Hostname of the device (CHECK_SMSEAGLE_API_URL)") + parser.add_argument('-t', '--token', + **environ_or_required('CHECK_SMSEAGLE_API_TOKEN'), + help="API token for authentication (CHECK_SMSEAGLE_API_TOKEN)") + parser.add_argument('-r', '--recipient', required=True, + help="Recipient for the message (required)") + parser.add_argument('-m', '--message', required=True, + help="The message to send (required)") + parser.add_argument('-T', '--timeout', help='Seconds before connection times out (default 10)', + default=10, + type=int) + parser.add_argument('--insecure', + action='store_true', + default=False, + help='Allow insecure SSL connections (default False)') + + return parser.parse_args(args) + + +def prepare_data(args): + return json.dumps({ + "to": [ + args.recipient + ], + "text": args.message + }) + + +def make_request(args, data): + """ + Prepare and submits request with given arguments. + """ + + # Compress warnings if insecure and change request verification + verify = True + if args.insecure: + urllib3.disable_warnings() + verify = False + + resp = requests.request( + method="POST", + headers={ + 'Content-Type': 'application/json', + 'access-token': args.token + }, + verify=verify, + url=urljoin(args.url, "/api/v2/messages/sms"), + data=data, + timeout=args.timeout + ) + + return resp + + +def main(args): + try: + data = prepare_data(args) + except Exception as exc: # pylint: disable=broad-except + print("Error: Could not prepare json data.", exc) + return 3 + + try: + response = make_request(args, data) + except Exception as exc: # pylint: disable=broad-except + print("Error: Could not connect to SMS Eagle and send message.", exc) + return 3 + + if not response.status_code == 200: + print("Error: Could not send message.", response) + return 2 + + return 0 + + +if __name__ == '__main__': # pragma: no cover + try: + ARGS = commandline(sys.argv[1:]) + sys.exit(main(ARGS)) + except Exception as e: # pylint: disable=broad-except + print("Error: ", e) + sys.exit(3) From 66dc49145ad8b531ab1d32723ba73ea15843d631 Mon Sep 17 00:00:00 2001 From: Markus Opolka Date: Mon, 29 Jun 2026 10:35:48 +0200 Subject: [PATCH 2/5] Bump development requirements --- requirements-dev.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index fb210c4..1e599a0 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,2 +1,2 @@ -pylint==3.0.2 -coverage==7.3.2 +pylint==4.0.6 +coverage==7.14.3 From 8682238454db4c0d812e91686574d2ec33e4a888 Mon Sep 17 00:00:00 2001 From: Markus Opolka Date: Mon, 29 Jun 2026 10:36:03 +0200 Subject: [PATCH 3/5] Fix GH actions not using python version matrix --- .github/workflows/test-check.yml | 15 ++++++++++++++- .github/workflows/test-notify.yml | 14 +++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-check.yml b/.github/workflows/test-check.yml index f05ae76..6a378eb 100644 --- a/.github/workflows/test-check.yml +++ b/.github/workflows/test-check.yml @@ -7,17 +7,30 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.9] + python-version: ["3.10", "3.14"] + name: GitHub Action steps: - name: Checkout uses: actions/checkout@v6 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.python-version }} + + - name: Display Python version + run: python -c "import sys; print(sys.version)" + - name: Install dependencies run: | + python -m pip install -r requirements.txt python -m pip install -r requirements-dev.txt + - name: Lint run: | make lint-check + - name: Unittest run: | make coverage-check diff --git a/.github/workflows/test-notify.yml b/.github/workflows/test-notify.yml index e13e008..f14e1f8 100644 --- a/.github/workflows/test-notify.yml +++ b/.github/workflows/test-notify.yml @@ -7,18 +7,30 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.9] + python-version: ["3.10", "3.14"] + name: GitHub Action steps: - name: Checkout uses: actions/checkout@v6 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.python-version }} + + - name: Display Python version + run: python -c "import sys; print(sys.version)" + - name: Install dependencies run: | python -m pip install -r requirements.txt python -m pip install -r requirements-dev.txt + - name: Lint run: | make lint-notify + - name: Unittest run: | make coverage-notify From a9cb65b9721e774ae94288fdce9d940b301d3208 Mon Sep 17 00:00:00 2001 From: Markus Opolka Date: Mon, 29 Jun 2026 10:46:03 +0200 Subject: [PATCH 4/5] Run 2to3 on smseagle_ack.cgi --- README.md | 2 +- check_smseagle.py | 2 -- notify_smseagle.py | 3 --- smseagle_ack.cgi | 17 ++++++----------- 4 files changed, 7 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 84e2454..42cbf8a 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ It parses incoming SMSs and acknowledges host/service problems if an SMS request ## Requirements -Python 2.6 or 2.7 +Python 3 ## Configuration diff --git a/check_smseagle.py b/check_smseagle.py index 8eaae26..4883c11 100755 --- a/check_smseagle.py +++ b/check_smseagle.py @@ -1,8 +1,6 @@ #!/usr/bin/python3 # Copyright (C) 2016 NETWAYS GmbH, https://netways.de # -# Author: Alexander A. Klimov -# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or diff --git a/notify_smseagle.py b/notify_smseagle.py index 32a7937..26e7b4c 100755 --- a/notify_smseagle.py +++ b/notify_smseagle.py @@ -1,9 +1,6 @@ #!/usr/bin/python3 - # Copyright (C) 2016 NETWAYS GmbH, https://netways.de # -# Author: Alexander A. Klimov -# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or diff --git a/smseagle_ack.cgi b/smseagle_ack.cgi index ec5cf51..d879c47 100755 --- a/smseagle_ack.cgi +++ b/smseagle_ack.cgi @@ -1,9 +1,6 @@ -#!/usr/bin/python2 - +#!/usr/bin/python3 # Copyright (C) 2016 NETWAYS GmbH, https://netways.de # -# Author: Alexander A. Klimov -# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or @@ -17,16 +14,14 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -from __future__ import print_function - import os import re import sys + from cgi import FieldStorage -from ConfigParser import NoSectionError, NoOptionError, RawConfigParser +from configparser import NoSectionError, NoOptionError, RawConfigParser from datetime import datetime -from itertools import cycle, izip +from itertools import cycle from syslog import LOG_PID, openlog, syslog from time import time @@ -73,7 +68,7 @@ def safe_eq(known, unknown): """ result = int(len(known) != len(unknown)) - for (x, y) in izip(unknown, cycle(known)): + for (x, y) in zip(unknown, cycle(known)): result |= ord(x) ^ ord(y) return not result @@ -86,7 +81,7 @@ try: cfg.readfp(f) raw_data = FieldStorage() - data = dict(((k, raw_data.getfirst(k)) for k in raw_data.keys())) + data = dict(((k, raw_data.getfirst(k)) for k in list(raw_data.keys()))) apikey = cfg.get('security', 'apikey') if apikey is not None: From ae93fd833169626b2c6e1028e124c776249d55bf Mon Sep 17 00:00:00 2001 From: Markus Opolka Date: Mon, 29 Jun 2026 10:52:01 +0200 Subject: [PATCH 5/5] Fix version string to v2.0.1 --- check_smseagle.py | 2 +- notify_smseagle.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/check_smseagle.py b/check_smseagle.py index 4883c11..4e898b7 100755 --- a/check_smseagle.py +++ b/check_smseagle.py @@ -22,7 +22,7 @@ import urllib3 import requests -__version__ = "2.0.0" +__version__ = "2.0.1" # Return code level # 0 - OK - The plugin was able to check the service and it appeared to be functioning properly diff --git a/notify_smseagle.py b/notify_smseagle.py index 26e7b4c..7cd7da1 100755 --- a/notify_smseagle.py +++ b/notify_smseagle.py @@ -23,7 +23,7 @@ import requests import urllib3 -__version__ = '2.0.0' +__version__ = '2.0.1' def commandline(args):