From 1e07ffdca6363d6a527b6cff7388ed84638649fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20A=2E?= <44995463+Th3Tul1p3@users.noreply.github.com> Date: Tue, 16 Dec 2025 05:39:33 +0100 Subject: [PATCH 1/7] Add files via upload --- scripts/artifacts/swissmeteo.py | 136 ++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 scripts/artifacts/swissmeteo.py diff --git a/scripts/artifacts/swissmeteo.py b/scripts/artifacts/swissmeteo.py new file mode 100644 index 00000000..665e5449 --- /dev/null +++ b/scripts/artifacts/swissmeteo.py @@ -0,0 +1,136 @@ +__artifacts_v2__ = { + "plz_interaction": { + "name": "Swissmeteo - Interaction with places", + "description": "Parse the interaction with meteo prevision of particular places", + "author": "jerome.arn@vd.ch", + "creation_date": "2025-09-25", + "last_update_date": "2025-10-03", + "requirements": "none", + "category": "Meteo", + "notes": "", + "paths": ('*/data/ch.admin.meteoswiss/databases/favorites_prediction_db.sqlite', '*/data/ch.admin.meteoswiss/files/db/localdata.sqlite'), + "output_types": "standard", + "html_columns": ['Meteo of the city (link)', 'Consultation Location'], + "artifact_icon": "flag" + }, + "swissmeteo_plz": { + "name": "Swissmeteo - App opening with geolocation", + "description": "Parse the app opening time and location", + "author": "jerome.arn@vd.ch", + "creation_date": "2025-09-25", + "last_update_date": "2025-11-03", + "requirements": "none", + "category": "Meteo", + "notes": "", + "paths": ('*/data/ch.admin.meteoswiss/databases/favorites_prediction_db.sqlite', '*/data/ch.admin.meteoswiss/files/db/localdata.sqlite'), + "output_types": "standard", + "html_columns": ['Map link'], + "artifact_icon": "flag" + } +} + +from scripts.ilapfuncs import artifact_processor, get_file_path, \ + get_sqlite_db_records, logfunc, open_sqlite_db_readonly + +@artifact_processor +def plz_interaction(files_found, report_folder, seeker, wrap_text): + source_path = get_file_path(files_found, "favorites_prediction_db.sqlite") + data_list = [] + + for file_found in files_found: + file_found = str(file_found) + + if files_found[0].endswith('favorites_prediction_db.sqlite'): + query = ''' + SELECT + datetime(timestamp/1000, 'unixepoch', 'localtime') AS created_date, + plz, + lat, + lon + FROM plz_interaction + ''' + + data_headers = ('Consulted timestamp', "Meteo of the city", "Meteo of the city (link)", "Consultation Location") + db_records = get_sqlite_db_records(files_found[0], query) + + local_data = [] + if files_found[1].endswith('localdata.sqlite'): + db = open_sqlite_db_readonly(files_found[1]) + cursor = db.cursor() + + for record in db_records: + local_data = get_location_infos(cursor, record[1]) + # test for 1111 postal code case + if len(local_data) > 0: + meteo_link = lv03_to_osm(local_data[0][1], local_data[0][2]) + if not (record[2] and record[3]): + cons_link = '' + else: + cons_link = coordinate_to_osm(record[2], record[3]) + data_list.append((record[0], local_data[0][4], meteo_link, cons_link)) + else: + data_list.append(record) + + return data_headers, data_list, source_path + else: + logfunc('No Swissmeteo') + +@artifact_processor +def swissmeteo_plz(files_found, report_folder, seeker, wrap_text): + source_path = get_file_path(files_found, "favorites_prediction_db.sqlite") + data_list = [] + + for file_found in files_found: + file_found = str(file_found) + + if files_found[0].endswith('favorites_prediction_db.sqlite'): + query = ''' + SELECT + datetime(timestamp/1000, 'unixepoch', 'localtime') AS created_date, + lat, + lon + FROM app_open + ''' + + data_headers = ('Opened timestamp', 'Latitude', 'Longitude', "Map link") + db_records = get_sqlite_db_records(files_found[0], query) + for record in db_records: + data_list.append((record[0], record[1], record[2], coordinate_to_osm(record[1], record[2]))) + + return data_headers, data_list, source_path + else: + logfunc('No plz_interaction') + +def coordinate_to_osm(lat, lon): + return f"https://www.openstreetmap.org/?mlat={lat}&mlon={lon}&zoom=15" + +def lv03_to_osm(E, N): + # based on https://github.com/ValentinMinder/Swisstopo-WGS84-LV03/blob/master/scripts/py/wgs84_ch1903.py + y, x = (E-600000)/1e6, (N-200000)/1e6; + lat = (16.9023892 + (3.238272 * x)) + \ + - (0.270978 * pow(y, 2)) + \ + - (0.002528 * pow(x, 2)) + \ + - (0.0447 * pow(y, 2) * x) + \ + - (0.0140 * pow(x, 3)) + lon = (2.6779094 + (4.728982 * y) + \ + + (0.791484 * y * x) + \ + + (0.1306 * y * pow(x, 2))) + \ + - (0.0436 * pow(y, 3)) + lat, lon = lat*100/36, lon*100/36; + return f"https://www.openstreetmap.org/?mlat={lat}&mlon={lon}&zoom=15" + +def get_location_infos(cursor, NPA): + query = ''' + SELECT + plz_pk, + x, + y, + altitude, + primary_name + FROM plz + WHERE plz_pk = ? + ''' + + cursor.execute(query, (NPA,)) + local_data = cursor.fetchall() + return local_data \ No newline at end of file From b23b074771a2387772282c0216073304e1c7111d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20A=2E?= <44995463+Th3Tul1p3@users.noreply.github.com> Date: Tue, 16 Dec 2025 21:57:36 +0100 Subject: [PATCH 2/7] Fix linting errors --- scripts/artifacts/swissmeteo.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/artifacts/swissmeteo.py b/scripts/artifacts/swissmeteo.py index 665e5449..97682263 100644 --- a/scripts/artifacts/swissmeteo.py +++ b/scripts/artifacts/swissmeteo.py @@ -33,9 +33,10 @@ get_sqlite_db_records, logfunc, open_sqlite_db_readonly @artifact_processor -def plz_interaction(files_found, report_folder, seeker, wrap_text): +def plz_interaction(files_found): source_path = get_file_path(files_found, "favorites_prediction_db.sqlite") data_list = [] + cursor = None for file_found in files_found: file_found = str(file_found) @@ -76,7 +77,7 @@ def plz_interaction(files_found, report_folder, seeker, wrap_text): logfunc('No Swissmeteo') @artifact_processor -def swissmeteo_plz(files_found, report_folder, seeker, wrap_text): +def swissmeteo_plz(files_found): source_path = get_file_path(files_found, "favorites_prediction_db.sqlite") data_list = [] @@ -106,7 +107,7 @@ def coordinate_to_osm(lat, lon): def lv03_to_osm(E, N): # based on https://github.com/ValentinMinder/Swisstopo-WGS84-LV03/blob/master/scripts/py/wgs84_ch1903.py - y, x = (E-600000)/1e6, (N-200000)/1e6; + y, x = (E-600000)/1e6, (N-200000)/1e6 lat = (16.9023892 + (3.238272 * x)) + \ - (0.270978 * pow(y, 2)) + \ - (0.002528 * pow(x, 2)) + \ @@ -133,4 +134,4 @@ def get_location_infos(cursor, NPA): cursor.execute(query, (NPA,)) local_data = cursor.fetchall() - return local_data \ No newline at end of file + return local_data From 32d351c18fab5db0806d3eaa07e015cb59752fba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20A=2E?= <44995463+Th3Tul1p3@users.noreply.github.com> Date: Tue, 16 Dec 2025 22:02:12 +0100 Subject: [PATCH 3/7] Fix linting errors --- scripts/artifacts/swissmeteo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/artifacts/swissmeteo.py b/scripts/artifacts/swissmeteo.py index 97682263..888dc54c 100644 --- a/scripts/artifacts/swissmeteo.py +++ b/scripts/artifacts/swissmeteo.py @@ -117,7 +117,7 @@ def lv03_to_osm(E, N): + (0.791484 * y * x) + \ + (0.1306 * y * pow(x, 2))) + \ - (0.0436 * pow(y, 3)) - lat, lon = lat*100/36, lon*100/36; + lat, lon = lat*100/36, lon*100/36 return f"https://www.openstreetmap.org/?mlat={lat}&mlon={lon}&zoom=15" def get_location_infos(cursor, NPA): From 49d380bf7887579da40cccc9b32497043f350de9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20A=2E?= <44995463+Th3Tul1p3@users.noreply.github.com> Date: Wed, 17 Dec 2025 10:20:49 +0100 Subject: [PATCH 4/7] fix python errors --- scripts/artifacts/swissmeteo.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/artifacts/swissmeteo.py b/scripts/artifacts/swissmeteo.py index 888dc54c..929d4910 100644 --- a/scripts/artifacts/swissmeteo.py +++ b/scripts/artifacts/swissmeteo.py @@ -33,7 +33,7 @@ get_sqlite_db_records, logfunc, open_sqlite_db_readonly @artifact_processor -def plz_interaction(files_found): +def plz_interaction(files_found, report_folder, seeker, wrap_text): source_path = get_file_path(files_found, "favorites_prediction_db.sqlite") data_list = [] cursor = None @@ -77,7 +77,7 @@ def plz_interaction(files_found): logfunc('No Swissmeteo') @artifact_processor -def swissmeteo_plz(files_found): +def swissmeteo_plz(files_found, report_folder, seeker, wrap_text): source_path = get_file_path(files_found, "favorites_prediction_db.sqlite") data_list = [] From 4b7530f4e0ef123a6d7f38822ecead73ded5847f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20A=2E?= <44995463+Th3Tul1p3@users.noreply.github.com> Date: Wed, 17 Dec 2025 18:52:53 +0100 Subject: [PATCH 5/7] unused parameters --- scripts/artifacts/swissmeteo.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/artifacts/swissmeteo.py b/scripts/artifacts/swissmeteo.py index 929d4910..cce09c5a 100644 --- a/scripts/artifacts/swissmeteo.py +++ b/scripts/artifacts/swissmeteo.py @@ -33,7 +33,7 @@ get_sqlite_db_records, logfunc, open_sqlite_db_readonly @artifact_processor -def plz_interaction(files_found, report_folder, seeker, wrap_text): +def plz_interaction(files_found, _report_folder, _seeker, _wrap_text): source_path = get_file_path(files_found, "favorites_prediction_db.sqlite") data_list = [] cursor = None @@ -77,7 +77,7 @@ def plz_interaction(files_found, report_folder, seeker, wrap_text): logfunc('No Swissmeteo') @artifact_processor -def swissmeteo_plz(files_found, report_folder, seeker, wrap_text): +def swissmeteo_plz(files_found, _report_folder, _seeker, _wrap_text): source_path = get_file_path(files_found, "favorites_prediction_db.sqlite") data_list = [] From a966f105c38459d5b583bb32789c24b5764ab2e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20A=2E?= <44995463+Th3Tul1p3@users.noreply.github.com> Date: Wed, 17 Dec 2025 18:58:44 +0100 Subject: [PATCH 6/7] Added to Contributors --- scripts/version_info.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/version_info.py b/scripts/version_info.py index 5979d62d..ebdc924c 100755 --- a/scripts/version_info.py +++ b/scripts/version_info.py @@ -30,4 +30,5 @@ ['Damien Attoe', 'https://digital4n6withdamien.blogspot.com/','@AttoeDamien','https://github.com/SpyderForensics'], ['Anna Kirpichnikova', 'https://www.linkedin.com/in/anna-kirpichnikova-a4819a10b/','','https://github.com/As-arsenicum-33'], ['Christian Peter', 'https://www.linkedin.com/in/christian-peter-49b4ab182/', '@DasZamomin', 'https://github.com/prosch88'] + ['Jérôme Arn', 'https://www.linkedin.com/in/j%C3%A9r%C3%B4me-a-dfir/', '@theTul1p3', 'https://github.com/Th3Tul1p3'] ] From 2e2ed08e60ecbb4bfdecacc9cb7d9d5d5efe8fce Mon Sep 17 00:00:00 2001 From: Kevin - Stark 4N6 <48143894+stark4n6@users.noreply.github.com> Date: Wed, 17 Dec 2025 13:16:00 -0500 Subject: [PATCH 7/7] Update version_info.py --- scripts/version_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/version_info.py b/scripts/version_info.py index ebdc924c..d56e68e7 100755 --- a/scripts/version_info.py +++ b/scripts/version_info.py @@ -29,6 +29,6 @@ ['Anthony Reince', 'https://www.linkedin.com/in/anthony-reince-a60115239/','',''], ['Damien Attoe', 'https://digital4n6withdamien.blogspot.com/','@AttoeDamien','https://github.com/SpyderForensics'], ['Anna Kirpichnikova', 'https://www.linkedin.com/in/anna-kirpichnikova-a4819a10b/','','https://github.com/As-arsenicum-33'], - ['Christian Peter', 'https://www.linkedin.com/in/christian-peter-49b4ab182/', '@DasZamomin', 'https://github.com/prosch88'] + ['Christian Peter', 'https://www.linkedin.com/in/christian-peter-49b4ab182/', '@DasZamomin', 'https://github.com/prosch88'], ['Jérôme Arn', 'https://www.linkedin.com/in/j%C3%A9r%C3%B4me-a-dfir/', '@theTul1p3', 'https://github.com/Th3Tul1p3'] ]