From 0e919dffbd886064b0c87c928cf170b282ce9ff32390c4b9d660d347dc832e36 Mon Sep 17 00:00:00 2001
From: localhorst <localhorst@mosad.xyz>
Date: Sun, 29 Dec 2024 23:01:59 +0100
Subject: [PATCH] webhook dummy

---
 .gitignore           | 179 +++++++++++++++++++++++++++++++++++++++++++
 README.md            |   8 +-
 ttn-webhook-dummy.py |  92 ++++++++++++++++++++++
 3 files changed, 278 insertions(+), 1 deletion(-)
 create mode 100644 ttn-webhook-dummy.py

diff --git a/.gitignore b/.gitignore
index bcdd288..b20625b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -130,3 +130,182 @@ dist
 .yarn/install-state.gz
 .pnp.*
 
+testdata/
+
+ ---> Python
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+cover/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+.pybuilder/
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+#   For a library or package, you might want to ignore these files since the code is
+#   intended to run in multiple environments; otherwise, check them in:
+# .python-version
+
+# pipenv
+#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+#   However, in case of collaboration, if having platform-specific dependencies or dependencies
+#   having no cross-platform support, pipenv may install dependencies that don't work, or not
+#   install all needed dependencies.
+#Pipfile.lock
+
+# poetry
+#   Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
+#   This is especially recommended for binary packages to ensure reproducibility, and is more
+#   commonly ignored for libraries.
+#   https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
+#poetry.lock
+
+# pdm
+#   Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
+#pdm.lock
+#   pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
+#   in version control.
+#   https://pdm.fming.dev/#use-with-ide
+.pdm.toml
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# Cython debug symbols
+cython_debug/
+
+# PyCharm
+#  JetBrains specific template is maintained in a separate JetBrains.gitignore that can
+#  be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
+#  and can be added to the global gitignore or merged into this file.  For a more nuclear
+#  option (not recommended) you can uncomment the following to ignore the entire idea folder.
+#.idea/
+
+# ---> VisualStudioCode
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+!.vscode/*.code-snippets
+
+# Local History for Visual Studio Code
+.history/
+
+# Built Visual Studio Code Extensions
+*.vsix
+
+config.py
\ No newline at end of file
diff --git a/README.md b/README.md
index 2052c09..070119d 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,9 @@
 # LocationHub
 
-TODO
\ No newline at end of file
+TODO
+
+
+### Testing Webhook
+To test the webhook use the python script `ttn-webhook-dummy.py` to send prerecorded TTN Uplinks.
+
+To test the script you can use `while true; do echo -e "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nSuccess"; nc -l -p 8080 -q 1; done`
\ No newline at end of file
diff --git a/ttn-webhook-dummy.py b/ttn-webhook-dummy.py
new file mode 100644
index 0000000..77c02f2
--- /dev/null
+++ b/ttn-webhook-dummy.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+""" Author:                     Hendrik Schutter, mail@hendrikschutter.com
+"""
+
+import requests
+import os
+import json
+import argparse
+import random
+
+def send_post_request(uri, data):
+    try:
+        requests.post(uri, json=data, timeout=1)
+    except requests.exceptions.RequestException as e:
+        pass
+
+
+def main():
+    parser = argparse.ArgumentParser(
+        description="Read JSON files and send them as POST requests to simulate a webhook request."
+    )
+    parser.add_argument(
+        "uri",
+        type=str,
+        help="The URI to send POST requests to (e.g., http://127.0.0.1:8080/api)",
+    )
+    parser.add_argument(
+        "directory",
+        type=str,
+        nargs="?",
+        default="./testdata/",
+        help="Directory containing JSON files (default: './testdata/')",
+    )
+    parser.add_argument(
+        "mode",
+        type=str,
+        choices=["send_all", "send_one", "send_random"],
+        default="send_one",
+        help="Mode for sending files: 'send_all', 'send_one', or 'send_random' (default: 'send_one')",
+    )
+
+    args = parser.parse_args()
+
+    if not os.path.exists(args.directory):
+        print(f"Directory {args.directory} does not exist.")
+        return
+
+    json_files = [f for f in os.listdir(args.directory) if f.endswith(".json")]
+    if not json_files:
+        print(f"No JSON files found in {args.directory}.")
+        return
+
+    if args.mode == "send_all":
+        for filename in json_files:
+            filepath = os.path.join(args.directory, filename)
+            with open(filepath, "r", encoding="utf-8") as file:
+                try:
+                    data = json.load(file)
+                    print(f"Sending {filename} to {args.uri}")
+                    send_post_request(args.uri, data)
+                except json.JSONDecodeError as e:
+                    print(f"Error reading {filename}: {e}")
+
+    elif args.mode == "send_one":
+        for filename in json_files:
+            filepath = os.path.join(args.directory, filename)
+            with open(filepath, "r", encoding="utf-8") as file:
+                try:
+                    data = json.load(file)
+                    print(f"Sending {filename} to {args.uri}")
+                    send_post_request(args.uri, data)
+                    input("Press Enter to send the next file...")
+                except json.JSONDecodeError as e:
+                    print(f"Error reading {filename}: {e}")
+
+    elif args.mode == "send_random":
+        while json_files:
+            filename = random.choice(json_files)
+            filepath = os.path.join(args.directory, filename)
+            with open(filepath, "r", encoding="utf-8") as file:
+                try:
+                    data = json.load(file)
+                    print(f"Sending {filename} to {args.uri}")
+                    send_post_request(args.uri, data)
+                    input("Press Enter to send another random file...")
+                except json.JSONDecodeError as e:
+                    print(f"Error reading {filename}: {e}")
+
+
+if __name__ == "__main__":
+    main()