Meteorschauer neu

This commit is contained in:
2026-04-05 12:11:47 +02:00
parent 31c9612cc5
commit 2821e1e301
6 changed files with 1013 additions and 3921 deletions
+5
View File
@@ -0,0 +1,5 @@
# Rechtesystem
Die Anleitung liegt jetzt unter:
- [docs/README_RECHTESYSTEM.md](/c:/Users/ich/source/repos/skyview.astronomiemuseum.de/docs/README_RECHTESYSTEM.md)
+240
View File
@@ -799,3 +799,243 @@ Stack trace:
[Sun Apr 5 11:12:44 2026] 127.0.0.1:54192 Closing
[Sun Apr 5 11:12:45 2026] 127.0.0.1:55784 [200]: GET /favicon.ico
[Sun Apr 5 11:12:45 2026] 127.0.0.1:55784 Closing
[Sun Apr 5 11:25:50 2026] 127.0.0.1:63666 Accepted
[Sun Apr 5 11:25:50 2026] 127.0.0.1:63666 [200]: GET /admin_users.php
[Sun Apr 5 11:25:50 2026] 127.0.0.1:63666 Closing
[Sun Apr 5 11:25:50 2026] 127.0.0.1:57197 Accepted
[Sun Apr 5 11:25:50 2026] 127.0.0.1:57197 [200]: GET /css/style.css
[Sun Apr 5 11:25:50 2026] 127.0.0.1:57197 Closing
[Sun Apr 5 11:25:50 2026] 127.0.0.1:52830 Accepted
[Sun Apr 5 11:25:50 2026] 127.0.0.1:52830 [200]: GET /images/star16x16.png
[Sun Apr 5 11:25:50 2026] 127.0.0.1:52830 Closing
[Sun Apr 5 11:25:50 2026] 127.0.0.1:61588 Accepted
[Sun Apr 5 11:25:50 2026] 127.0.0.1:57469 Accepted
[Sun Apr 5 11:25:50 2026] 127.0.0.1:61588 [200]: GET /images/star16x16_rays.png
[Sun Apr 5 11:25:50 2026] 127.0.0.1:61588 Closing
[Sun Apr 5 11:25:51 2026] 127.0.0.1:57469 [200]: GET /favicon.ico
[Sun Apr 5 11:25:51 2026] 127.0.0.1:57469 Closing
[Sun Apr 5 11:25:57 2026] 127.0.0.1:53473 Accepted
[Sun Apr 5 11:25:57 2026] 127.0.0.1:53473 [302]: POST /admin_users.php
[Sun Apr 5 11:25:57 2026] 127.0.0.1:53473 Closing
[Sun Apr 5 11:25:57 2026] 127.0.0.1:63758 Accepted
[Sun Apr 5 11:25:57 2026] 127.0.0.1:63758 [200]: GET /admin_users.php
[Sun Apr 5 11:25:57 2026] 127.0.0.1:63758 Closing
[Sun Apr 5 11:25:58 2026] 127.0.0.1:55984 Accepted
[Sun Apr 5 11:25:58 2026] 127.0.0.1:55984 [200]: GET /css/style.css
[Sun Apr 5 11:25:58 2026] 127.0.0.1:55984 Closing
[Sun Apr 5 11:25:58 2026] 127.0.0.1:62490 Accepted
[Sun Apr 5 11:25:58 2026] 127.0.0.1:62490 [200]: GET /images/star16x16.png
[Sun Apr 5 11:25:58 2026] 127.0.0.1:62490 Closing
[Sun Apr 5 11:25:58 2026] 127.0.0.1:63631 Accepted
[Sun Apr 5 11:25:58 2026] 127.0.0.1:54175 Accepted
[Sun Apr 5 11:25:58 2026] 127.0.0.1:63631 [200]: GET /images/star16x16_rays.png
[Sun Apr 5 11:25:58 2026] 127.0.0.1:63631 Closing
[Sun Apr 5 11:25:59 2026] 127.0.0.1:54175 [200]: GET /favicon.ico
[Sun Apr 5 11:25:59 2026] 127.0.0.1:54175 Closing
[Sun Apr 5 11:48:43 2026] 127.0.0.1:52829 Accepted
[Sun Apr 5 11:48:44 2026] 127.0.0.1:52829 [200]: GET /index.php
[Sun Apr 5 11:48:44 2026] 127.0.0.1:52829 Closing
[Sun Apr 5 11:48:44 2026] 127.0.0.1:56008 Accepted
[Sun Apr 5 11:48:44 2026] 127.0.0.1:56008 [200]: GET /css/style.css
[Sun Apr 5 11:48:44 2026] 127.0.0.1:56008 Closing
[Sun Apr 5 11:48:45 2026] 127.0.0.1:60849 Accepted
[Sun Apr 5 11:48:45 2026] 127.0.0.1:58446 Accepted
[Sun Apr 5 11:48:45 2026] 127.0.0.1:60849 [200]: GET /images/star16x16.png
[Sun Apr 5 11:48:45 2026] 127.0.0.1:58446 [200]: GET /images/star16x16_rays.png
[Sun Apr 5 11:48:45 2026] 127.0.0.1:60849 Closing
[Sun Apr 5 11:48:45 2026] 127.0.0.1:58446 Closing
[Sun Apr 5 11:48:45 2026] 127.0.0.1:51829 Accepted
[Sun Apr 5 11:48:46 2026] 127.0.0.1:51829 [200]: GET /favicon.ico
[Sun Apr 5 11:48:46 2026] 127.0.0.1:51829 Closing
[Sun Apr 5 11:48:46 2026] 127.0.0.1:49634 Accepted
[Sun Apr 5 11:48:59 2026] 127.0.0.1:49634 [200]: GET /meteorshowers.php
[Sun Apr 5 11:48:59 2026] 127.0.0.1:49634 Closing
[Sun Apr 5 11:48:59 2026] 127.0.0.1:59855 Accepted
[Sun Apr 5 11:48:59 2026] 127.0.0.1:59855 [200]: GET /css/style.css
[Sun Apr 5 11:48:59 2026] 127.0.0.1:59855 Closing
[Sun Apr 5 11:48:59 2026] 127.0.0.1:52333 Accepted
[Sun Apr 5 11:48:59 2026] 127.0.0.1:52570 Accepted
[Sun Apr 5 11:48:59 2026] 127.0.0.1:50708 Accepted
[Sun Apr 5 11:48:59 2026] 127.0.0.1:52333 [200]: GET /js/astronomy.browser.min.js
[Sun Apr 5 11:48:59 2026] 127.0.0.1:52570 [200]: GET /images/star16x16.png
[Sun Apr 5 11:48:59 2026] 127.0.0.1:50708 [200]: GET /images/star16x16_rays.png
[Sun Apr 5 11:48:59 2026] 127.0.0.1:52333 Closing
[Sun Apr 5 11:48:59 2026] 127.0.0.1:52570 Closing
[Sun Apr 5 11:48:59 2026] 127.0.0.1:50708 Closing
[Sun Apr 5 11:49:00 2026] 127.0.0.1:64311 Accepted
[Sun Apr 5 11:49:00 2026] 127.0.0.1:64311 [200]: GET /images/moons/moon4geocron.png
[Sun Apr 5 11:49:00 2026] 127.0.0.1:64311 Closing
[Sun Apr 5 11:49:00 2026] 127.0.0.1:59676 Accepted
[Sun Apr 5 11:49:01 2026] 127.0.0.1:59676 [200]: GET /favicon.ico
[Sun Apr 5 11:49:01 2026] 127.0.0.1:59676 Closing
[Sun Apr 5 11:49:01 2026] 127.0.0.1:64240 Accepted
[Sun Apr 5 11:49:57 2026] 127.0.0.1:61674 Accepted
[Sun Apr 5 11:49:57 2026] 127.0.0.1:61674 [302]: GET /meteorshowers.php
[Sun Apr 5 11:49:57 2026] 127.0.0.1:61674 Closing
[Sun Apr 5 11:49:57 2026] 127.0.0.1:61676 Accepted
[Sun Apr 5 11:49:57 2026] 127.0.0.1:61676 [200]: GET /login.php
[Sun Apr 5 11:49:57 2026] 127.0.0.1:61676 Closing
[Sun Apr 5 11:50:14 2026] 127.0.0.1:64240 Closed without sending a request; it was probably just an unused speculative preconnection
[Sun Apr 5 11:50:14 2026] 127.0.0.1:64240 Closing
[Sun Apr 5 11:50:14 2026] 127.0.0.1:52919 Accepted
[Sun Apr 5 11:50:14 2026] 127.0.0.1:52919 [200]: GET /meteorshowers.php
[Sun Apr 5 11:50:14 2026] 127.0.0.1:52919 Closing
[Sun Apr 5 11:50:14 2026] 127.0.0.1:62156 Accepted
[Sun Apr 5 11:50:14 2026] 127.0.0.1:62156 [200]: GET /css/style.css
[Sun Apr 5 11:50:14 2026] 127.0.0.1:62156 Closing
[Sun Apr 5 11:50:14 2026] 127.0.0.1:52596 Accepted
[Sun Apr 5 11:50:14 2026] 127.0.0.1:52596 [200]: GET /images/star16x16.png
[Sun Apr 5 11:50:14 2026] 127.0.0.1:52596 Closing
[Sun Apr 5 11:50:14 2026] 127.0.0.1:65473 Accepted
[Sun Apr 5 11:50:14 2026] 127.0.0.1:59808 Accepted
[Sun Apr 5 11:50:14 2026] 127.0.0.1:65473 [200]: GET /images/star16x16_rays.png
[Sun Apr 5 11:50:14 2026] 127.0.0.1:65473 Closing
[Sun Apr 5 11:50:15 2026] 127.0.0.1:59808 [200]: GET /favicon.ico
[Sun Apr 5 11:50:15 2026] 127.0.0.1:59808 Closing
[Sun Apr 5 11:50:32 2026] 127.0.0.1:56279 Accepted
[Sun Apr 5 11:50:32 2026] 127.0.0.1:56279 [200]: GET /meteorshowers.php?q=&mode=active
[Sun Apr 5 11:50:32 2026] 127.0.0.1:56279 Closing
[Sun Apr 5 11:50:32 2026] 127.0.0.1:58009 Accepted
[Sun Apr 5 11:50:32 2026] 127.0.0.1:58009 [200]: GET /css/style.css
[Sun Apr 5 11:50:32 2026] 127.0.0.1:58009 Closing
[Sun Apr 5 11:50:32 2026] 127.0.0.1:50221 Accepted
[Sun Apr 5 11:50:32 2026] 127.0.0.1:50221 [200]: GET /images/star16x16.png
[Sun Apr 5 11:50:32 2026] 127.0.0.1:50221 Closing
[Sun Apr 5 11:50:32 2026] 127.0.0.1:64906 Accepted
[Sun Apr 5 11:50:32 2026] 127.0.0.1:51891 Accepted
[Sun Apr 5 11:50:32 2026] 127.0.0.1:64906 [200]: GET /images/star16x16_rays.png
[Sun Apr 5 11:50:32 2026] 127.0.0.1:64906 Closing
[Sun Apr 5 11:50:33 2026] 127.0.0.1:51891 [200]: GET /favicon.ico
[Sun Apr 5 11:50:33 2026] 127.0.0.1:51891 Closing
[Sun Apr 5 11:50:35 2026] 127.0.0.1:55431 Accepted
[Sun Apr 5 11:50:35 2026] 127.0.0.1:55431 [200]: GET /meteorshowers.php?q=&mode=all
[Sun Apr 5 11:50:35 2026] 127.0.0.1:55431 Closing
[Sun Apr 5 11:50:35 2026] 127.0.0.1:56566 Accepted
[Sun Apr 5 11:50:35 2026] 127.0.0.1:56566 [200]: GET /css/style.css
[Sun Apr 5 11:50:35 2026] 127.0.0.1:56566 Closing
[Sun Apr 5 11:50:35 2026] 127.0.0.1:61013 Accepted
[Sun Apr 5 11:50:35 2026] 127.0.0.1:61013 [200]: GET /images/star16x16.png
[Sun Apr 5 11:50:35 2026] 127.0.0.1:61013 Closing
[Sun Apr 5 11:50:35 2026] 127.0.0.1:58944 Accepted
[Sun Apr 5 11:50:35 2026] 127.0.0.1:56599 Accepted
[Sun Apr 5 11:50:35 2026] 127.0.0.1:58944 [200]: GET /images/star16x16_rays.png
[Sun Apr 5 11:50:35 2026] 127.0.0.1:58944 Closing
[Sun Apr 5 11:50:36 2026] 127.0.0.1:56599 [200]: GET /favicon.ico
[Sun Apr 5 11:50:36 2026] 127.0.0.1:56599 Closing
[Sun Apr 5 11:54:38 2026] 127.0.0.1:57364 Accepted
[Sun Apr 5 11:54:38 2026] 127.0.0.1:57364 [200]: GET /meteorshowers.php?q=&mode=all
[Sun Apr 5 11:54:38 2026] 127.0.0.1:57364 Closing
[Sun Apr 5 11:54:38 2026] 127.0.0.1:50807 Accepted
[Sun Apr 5 11:54:38 2026] 127.0.0.1:50807 [200]: GET /css/style.css
[Sun Apr 5 11:54:38 2026] 127.0.0.1:50807 Closing
[Sun Apr 5 11:54:38 2026] 127.0.0.1:59570 Accepted
[Sun Apr 5 11:54:38 2026] 127.0.0.1:59570 [200]: GET /images/star16x16.png
[Sun Apr 5 11:54:38 2026] 127.0.0.1:59570 Closing
[Sun Apr 5 11:54:39 2026] 127.0.0.1:57873 Accepted
[Sun Apr 5 11:54:39 2026] 127.0.0.1:54508 Accepted
[Sun Apr 5 11:54:39 2026] 127.0.0.1:57873 [200]: GET /images/star16x16_rays.png
[Sun Apr 5 11:54:39 2026] 127.0.0.1:57873 Closing
[Sun Apr 5 11:54:39 2026] 127.0.0.1:54508 [200]: GET /favicon.ico
[Sun Apr 5 11:54:39 2026] 127.0.0.1:54508 Closing
[Sun Apr 5 11:55:26 2026] 127.0.0.1:63857 Accepted
[Sun Apr 5 11:55:26 2026] 127.0.0.1:63857 [302]: GET /meteorshowers.php
[Sun Apr 5 11:55:26 2026] 127.0.0.1:63857 Closing
[Sun Apr 5 11:55:26 2026] 127.0.0.1:63859 Accepted
[Sun Apr 5 11:55:26 2026] 127.0.0.1:63859 [200]: GET /login.php
[Sun Apr 5 11:55:26 2026] 127.0.0.1:63859 Closing
[Sun Apr 5 11:56:30 2026] 127.0.0.1:51672 Accepted
[Sun Apr 5 11:56:30 2026] 127.0.0.1:51672 [200]: GET /meteorshowers.php?q=&mode=all
[Sun Apr 5 11:56:30 2026] 127.0.0.1:51672 Closing
[Sun Apr 5 11:56:30 2026] 127.0.0.1:57680 Accepted
[Sun Apr 5 11:56:30 2026] 127.0.0.1:57680 [200]: GET /css/style.css
[Sun Apr 5 11:56:30 2026] 127.0.0.1:57680 Closing
[Sun Apr 5 11:56:31 2026] 127.0.0.1:57516 Accepted
[Sun Apr 5 11:56:31 2026] 127.0.0.1:57516 [200]: GET /images/star16x16.png
[Sun Apr 5 11:56:31 2026] 127.0.0.1:57516 Closing
[Sun Apr 5 11:56:31 2026] 127.0.0.1:64583 Accepted
[Sun Apr 5 11:56:31 2026] 127.0.0.1:55172 Accepted
[Sun Apr 5 11:56:31 2026] 127.0.0.1:64583 [200]: GET /images/star16x16_rays.png
[Sun Apr 5 11:56:31 2026] 127.0.0.1:64583 Closing
[Sun Apr 5 11:56:32 2026] 127.0.0.1:55172 [200]: GET /favicon.ico
[Sun Apr 5 11:56:32 2026] 127.0.0.1:55172 Closing
[Sun Apr 5 11:56:36 2026] 127.0.0.1:51181 Accepted
[Sun Apr 5 11:56:36 2026] 127.0.0.1:51181 [200]: GET /meteorshowers.php?q=&mode=all
[Sun Apr 5 11:56:36 2026] 127.0.0.1:51181 Closing
[Sun Apr 5 11:56:36 2026] 127.0.0.1:63170 Accepted
[Sun Apr 5 11:56:36 2026] 127.0.0.1:63170 [200]: GET /css/style.css
[Sun Apr 5 11:56:36 2026] 127.0.0.1:63170 Closing
[Sun Apr 5 11:56:36 2026] 127.0.0.1:58615 Accepted
[Sun Apr 5 11:56:36 2026] 127.0.0.1:58615 [200]: GET /images/star16x16.png
[Sun Apr 5 11:56:36 2026] 127.0.0.1:58615 Closing
[Sun Apr 5 11:56:36 2026] 127.0.0.1:59905 Accepted
[Sun Apr 5 11:56:36 2026] 127.0.0.1:49289 Accepted
[Sun Apr 5 11:56:36 2026] 127.0.0.1:59905 [200]: GET /images/star16x16_rays.png
[Sun Apr 5 11:56:36 2026] 127.0.0.1:59905 Closing
[Sun Apr 5 11:56:37 2026] 127.0.0.1:49289 [200]: GET /favicon.ico
[Sun Apr 5 11:56:37 2026] 127.0.0.1:49289 Closing
[Sun Apr 5 11:57:43 2026] 127.0.0.1:51973 Accepted
[Sun Apr 5 11:57:43 2026] 127.0.0.1:51973 [302]: GET /meteorshowers.php
[Sun Apr 5 11:57:43 2026] 127.0.0.1:51973 Closing
[Sun Apr 5 11:57:43 2026] 127.0.0.1:51975 Accepted
[Sun Apr 5 11:57:43 2026] 127.0.0.1:51975 [200]: GET /login.php
[Sun Apr 5 11:57:43 2026] 127.0.0.1:51975 Closing
[Sun Apr 5 11:58:09 2026] 127.0.0.1:62492 Accepted
[Sun Apr 5 11:58:09 2026] 127.0.0.1:62492 [200]: GET /meteorshowers.php?q=&mode=all
[Sun Apr 5 11:58:09 2026] 127.0.0.1:62492 Closing
[Sun Apr 5 11:58:09 2026] 127.0.0.1:52376 Accepted
[Sun Apr 5 11:58:09 2026] 127.0.0.1:52376 [200]: GET /css/style.css
[Sun Apr 5 11:58:09 2026] 127.0.0.1:52376 Closing
[Sun Apr 5 11:58:09 2026] 127.0.0.1:50060 Accepted
[Sun Apr 5 11:58:09 2026] 127.0.0.1:50060 [200]: GET /images/star16x16.png
[Sun Apr 5 11:58:09 2026] 127.0.0.1:50060 Closing
[Sun Apr 5 11:58:09 2026] 127.0.0.1:63671 Accepted
[Sun Apr 5 11:58:09 2026] 127.0.0.1:63196 Accepted
[Sun Apr 5 11:58:09 2026] 127.0.0.1:63671 [200]: GET /images/star16x16_rays.png
[Sun Apr 5 11:58:09 2026] 127.0.0.1:63671 Closing
[Sun Apr 5 11:58:10 2026] 127.0.0.1:63196 [200]: GET /favicon.ico
[Sun Apr 5 11:58:10 2026] 127.0.0.1:63196 Closing
[Sun Apr 5 11:59:27 2026] 127.0.0.1:52816 Accepted
[Sun Apr 5 11:59:27 2026] 127.0.0.1:52816 [200]: GET /meteorshowers.php?q=&mode=all
[Sun Apr 5 11:59:27 2026] 127.0.0.1:52816 Closing
[Sun Apr 5 11:59:27 2026] 127.0.0.1:54341 Accepted
[Sun Apr 5 11:59:27 2026] 127.0.0.1:54341 [200]: GET /css/style.css
[Sun Apr 5 11:59:27 2026] 127.0.0.1:54341 Closing
[Sun Apr 5 11:59:27 2026] 127.0.0.1:49273 Accepted
[Sun Apr 5 11:59:27 2026] 127.0.0.1:49273 [200]: GET /images/star16x16.png
[Sun Apr 5 11:59:27 2026] 127.0.0.1:49273 Closing
[Sun Apr 5 11:59:27 2026] 127.0.0.1:55327 Accepted
[Sun Apr 5 11:59:27 2026] 127.0.0.1:56745 Accepted
[Sun Apr 5 11:59:27 2026] 127.0.0.1:55327 [200]: GET /images/star16x16_rays.png
[Sun Apr 5 11:59:27 2026] 127.0.0.1:55327 Closing
[Sun Apr 5 11:59:28 2026] 127.0.0.1:56745 [200]: GET /favicon.ico
[Sun Apr 5 11:59:28 2026] 127.0.0.1:56745 Closing
[Sun Apr 5 12:02:37 2026] 127.0.0.1:63271 Accepted
[Sun Apr 5 12:02:37 2026] 127.0.0.1:63271 [200]: GET /meteorshowers.php?q=&mode=all
[Sun Apr 5 12:02:37 2026] 127.0.0.1:63271 Closing
[Sun Apr 5 12:02:37 2026] 127.0.0.1:60905 Accepted
[Sun Apr 5 12:02:37 2026] 127.0.0.1:60905 [200]: GET /css/style.css
[Sun Apr 5 12:02:37 2026] 127.0.0.1:60905 Closing
[Sun Apr 5 12:02:38 2026] 127.0.0.1:61012 Accepted
[Sun Apr 5 12:02:38 2026] 127.0.0.1:61012 [200]: GET /images/star16x16.png
[Sun Apr 5 12:02:38 2026] 127.0.0.1:61012 Closing
[Sun Apr 5 12:02:38 2026] 127.0.0.1:60220 Accepted
[Sun Apr 5 12:02:38 2026] 127.0.0.1:49322 Accepted
[Sun Apr 5 12:02:38 2026] 127.0.0.1:60220 [200]: GET /images/star16x16_rays.png
[Sun Apr 5 12:02:38 2026] 127.0.0.1:60220 Closing
[Sun Apr 5 12:02:39 2026] 127.0.0.1:49322 [200]: GET /favicon.ico
[Sun Apr 5 12:02:39 2026] 127.0.0.1:49322 Closing
[Sun Apr 5 12:02:49 2026] 127.0.0.1:55826 Accepted
[Sun Apr 5 12:02:49 2026] 127.0.0.1:55826 [200]: GET /meteorshowers.php?q=&mode=all
[Sun Apr 5 12:02:49 2026] 127.0.0.1:55826 Closing
[Sun Apr 5 12:02:49 2026] 127.0.0.1:58635 Accepted
[Sun Apr 5 12:02:49 2026] 127.0.0.1:58635 [200]: GET /css/style.css
[Sun Apr 5 12:02:49 2026] 127.0.0.1:58635 Closing
[Sun Apr 5 12:02:50 2026] 127.0.0.1:55997 Accepted
[Sun Apr 5 12:02:50 2026] 127.0.0.1:55997 [200]: GET /images/star16x16.png
[Sun Apr 5 12:02:50 2026] 127.0.0.1:55997 Closing
[Sun Apr 5 12:02:50 2026] 127.0.0.1:55677 Accepted
[Sun Apr 5 12:02:50 2026] 127.0.0.1:62995 Accepted
[Sun Apr 5 12:02:50 2026] 127.0.0.1:55677 [200]: GET /images/star16x16_rays.png
[Sun Apr 5 12:02:50 2026] 127.0.0.1:55677 Closing
[Sun Apr 5 12:02:51 2026] 127.0.0.1:62995 [200]: GET /favicon.ico
[Sun Apr 5 12:02:51 2026] 127.0.0.1:62995 Closing
+424 -3894
View File
File diff suppressed because it is too large Load Diff
+221 -25
View File
@@ -109,6 +109,20 @@ function setExclusiveFavorite(PDO $pdo, string $tableName, string $idColumn, int
}
}
function countUserRows(PDO $pdo, string $tableName, int $userId): int
{
$stmtCount = $pdo->prepare("
SELECT COUNT(*)
FROM `{$tableName}`
WHERE `user_id` = :user_id
");
$stmtCount->execute([
':user_id' => $userId,
]);
return (int) $stmtCount->fetchColumn();
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = $_POST['action'] ?? '';
@@ -168,17 +182,89 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
if (empty($errors)) {
$stmtDelete = $pdo->prepare("
DELETE FROM `app_user_satellites`
$stmtSatellite = $pdo->prepare("
SELECT `satellite_id`, `is_favorite`
FROM `app_user_satellites`
WHERE `user_id` = :user_id
AND `satellite_id` = :satellite_id
LIMIT 1
");
$stmtDelete->execute([
$stmtSatellite->execute([
':user_id' => $userId,
':satellite_id' => $satelliteId,
]);
$satelliteRow = $stmtSatellite->fetch();
$successMessage = 'Der Satellit wurde entfernt.';
if (!$satelliteRow) {
$errors[] = 'Der Satellit ist nicht in deiner Liste vorhanden.';
}
}
if (empty($errors)) {
$satelliteCount = countUserRows($pdo, 'app_user_satellites', $userId);
if ($satelliteCount <= 1) {
$errors[] = 'Der letzte Satellit kann nicht geloescht werden.';
}
}
if (empty($errors)) {
$pdo->beginTransaction();
try {
$stmtDelete = $pdo->prepare("
DELETE FROM `app_user_satellites`
WHERE `user_id` = :user_id
AND `satellite_id` = :satellite_id
");
$stmtDelete->execute([
':user_id' => $userId,
':satellite_id' => $satelliteId,
]);
if ((int) ($satelliteRow['is_favorite'] ?? 0) === 1) {
$stmtNextFavorite = $pdo->prepare("
SELECT `satellite_id`
FROM `app_user_satellites`
WHERE `user_id` = :user_id
ORDER BY `created_at` ASC, `satellite_id` ASC
LIMIT 1
");
$stmtNextFavorite->execute([
':user_id' => $userId,
]);
$nextSatelliteId = $stmtNextFavorite->fetchColumn();
if ($nextSatelliteId !== false) {
$stmtResetFavorites = $pdo->prepare("
UPDATE `app_user_satellites`
SET `is_favorite` = 0
WHERE `user_id` = :user_id
");
$stmtResetFavorites->execute([
':user_id' => $userId,
]);
$stmtSetFavorite = $pdo->prepare("
UPDATE `app_user_satellites`
SET `is_favorite` = 1
WHERE `user_id` = :user_id
AND `satellite_id` = :satellite_id
");
$stmtSetFavorite->execute([
':user_id' => $userId,
':satellite_id' => (int) $nextSatelliteId,
]);
}
}
$pdo->commit();
$successMessage = 'Der Satellit wurde entfernt.';
} catch (Throwable $e) {
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
$errors[] = 'Der Satellit konnte nicht entfernt werden.';
}
}
}
@@ -189,6 +275,32 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$errors[] = 'Ungueltiger Satellit.';
}
if (empty($errors)) {
$stmtCurrentSatellite = $pdo->prepare("
SELECT `is_favorite`
FROM `app_user_satellites`
WHERE `user_id` = :user_id
AND `satellite_id` = :satellite_id
LIMIT 1
");
$stmtCurrentSatellite->execute([
':user_id' => $userId,
':satellite_id' => $satelliteId,
]);
$currentSatelliteFavorite = $stmtCurrentSatellite->fetchColumn();
if ($currentSatelliteFavorite === false) {
$errors[] = 'Der Satellit ist nicht in deiner Liste vorhanden.';
}
}
if (empty($errors)) {
$satelliteCount = countUserRows($pdo, 'app_user_satellites', $userId);
if ($satelliteCount <= 1 && (int) $currentSatelliteFavorite === 1) {
$errors[] = 'Beim letzten Satelliten kann der Favorit nicht entfernt werden.';
}
}
if (empty($errors)) {
if (!setExclusiveFavorite($pdo, 'app_user_satellites', 'satellite_id', $userId, $satelliteId)) {
$errors[] = 'Der Satellit ist nicht in deiner Liste vorhanden.';
@@ -450,17 +562,89 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
if (empty($errors)) {
$stmtDelete = $pdo->prepare("
DELETE FROM `app_user_locations`
$stmtLocation = $pdo->prepare("
SELECT `id`, `is_default`
FROM `app_user_locations`
WHERE `id` = :id
AND `user_id` = :user_id
LIMIT 1
");
$stmtDelete->execute([
$stmtLocation->execute([
':id' => $locationId,
':user_id' => $userId,
]);
$locationRow = $stmtLocation->fetch();
$successMessage = 'Der Standort wurde geloescht.';
if (!$locationRow) {
$errors[] = 'Der Standort wurde nicht gefunden.';
}
}
if (empty($errors)) {
$locationCount = countUserRows($pdo, 'app_user_locations', $userId);
if ($locationCount <= 1) {
$errors[] = 'Der letzte Standort kann nicht geloescht werden.';
}
}
if (empty($errors)) {
$pdo->beginTransaction();
try {
$stmtDelete = $pdo->prepare("
DELETE FROM `app_user_locations`
WHERE `id` = :id
AND `user_id` = :user_id
");
$stmtDelete->execute([
':id' => $locationId,
':user_id' => $userId,
]);
if ((int) ($locationRow['is_default'] ?? 0) === 1) {
$stmtNextDefault = $pdo->prepare("
SELECT `id`
FROM `app_user_locations`
WHERE `user_id` = :user_id
ORDER BY `name` ASC, `id` ASC
LIMIT 1
");
$stmtNextDefault->execute([
':user_id' => $userId,
]);
$nextLocationId = $stmtNextDefault->fetchColumn();
if ($nextLocationId !== false) {
$stmtResetDefaults = $pdo->prepare("
UPDATE `app_user_locations`
SET `is_default` = 0
WHERE `user_id` = :user_id
");
$stmtResetDefaults->execute([
':user_id' => $userId,
]);
$stmtSetDefault = $pdo->prepare("
UPDATE `app_user_locations`
SET `is_default` = 1
WHERE `user_id` = :user_id
AND `id` = :id
");
$stmtSetDefault->execute([
':user_id' => $userId,
':id' => (int) $nextLocationId,
]);
}
}
$pdo->commit();
$successMessage = 'Der Standort wurde geloescht.';
} catch (Throwable $e) {
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
$errors[] = 'Der Standort konnte nicht geloescht werden.';
}
}
}
}
@@ -697,11 +881,15 @@ $loggedIn = true;
<button type="submit" class="btn btn-sm btn-secondary">Als Standard</button>
</form>
<?php endif; ?>
<form method="post" action="" class="favorites-loading-form" data-loading-message="Standort wird entfernt..." onsubmit="return confirm('Standort wirklich loeschen?');">
<input type="hidden" name="action" value="delete_location">
<input type="hidden" name="location_id" value="<?= (int) $location['id'] ?>">
<button type="submit" class="btn btn-sm btn-danger">Loeschen</button>
</form>
<?php if (count($locations) > 1): ?>
<form method="post" action="" class="favorites-loading-form" data-loading-message="Standort wird entfernt..." onsubmit="return confirm('Standort wirklich loeschen?');">
<input type="hidden" name="action" value="delete_location">
<input type="hidden" name="location_id" value="<?= (int) $location['id'] ?>">
<button type="submit" class="btn btn-sm btn-danger">Loeschen</button>
</form>
<?php else: ?>
<span class="hint">Letzter Standort</span>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
@@ -893,18 +1081,26 @@ $loggedIn = true;
<td><?= (int) $satellite['is_favorite'] === 1 ? '*' : '-' ?></td>
<td><?= h($satellite['created_at']) ?></td>
<td class="action-cell">
<form method="post" action="" class="favorites-loading-form" data-loading-message="Satelliten-Favorit wird aktualisiert...">
<input type="hidden" name="action" value="toggle_satellite_favorite">
<input type="hidden" name="satellite_id" value="<?= (int) $satellite['id'] ?>">
<button type="submit" class="btn btn-sm btn-secondary">
<?= (int) $satellite['is_favorite'] === 1 ? 'Favorit entfernen' : 'Als Favorit' ?>
</button>
</form>
<form method="post" action="" class="favorites-loading-form" data-loading-message="Satellit wird entfernt..." onsubmit="return confirm('Satellit wirklich entfernen?');">
<input type="hidden" name="action" value="remove_satellite">
<input type="hidden" name="satellite_id" value="<?= (int) $satellite['id'] ?>">
<button type="submit" class="btn btn-sm btn-danger">Entfernen</button>
</form>
<?php if (count($trackedSatellites) <= 1 && (int) $satellite['is_favorite'] === 1): ?>
<span class="hint">Favorit bleibt gesetzt</span>
<?php else: ?>
<form method="post" action="" class="favorites-loading-form" data-loading-message="Satelliten-Favorit wird aktualisiert...">
<input type="hidden" name="action" value="toggle_satellite_favorite">
<input type="hidden" name="satellite_id" value="<?= (int) $satellite['id'] ?>">
<button type="submit" class="btn btn-sm btn-secondary">
<?= (int) $satellite['is_favorite'] === 1 ? 'Favorit entfernen' : 'Als Favorit' ?>
</button>
</form>
<?php endif; ?>
<?php if (count($trackedSatellites) > 1): ?>
<form method="post" action="" class="favorites-loading-form" data-loading-message="Satellit wird entfernt..." onsubmit="return confirm('Satellit wirklich entfernen?');">
<input type="hidden" name="action" value="remove_satellite">
<input type="hidden" name="satellite_id" value="<?= (int) $satellite['id'] ?>">
<button type="submit" class="btn btn-sm btn-danger">Entfernen</button>
</form>
<?php else: ?>
<span class="hint">Letzter Satellit</span>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
Binary file not shown.
+123 -2
View File
@@ -93,6 +93,117 @@ def serialize_event(label: str, event_time: astronomy.Time | None, tz: ZoneInfo)
}
def normalize_longitude_deg(value: float) -> float:
value = math.fmod(value, 360.0)
if value < 0.0:
value += 360.0
return value
def action_solar_longitude_to_datetime(args: list[str]) -> dict:
if len(args) != 3:
fail(
"Aktion solar_longitude_to_datetime erwartet 3 Argumente: lambda_target_deg year timezone",
extra={"argv": args},
)
lambda_target_deg = parse_float(args[0], "Solare Laenge")
lambda_target_deg = normalize_longitude_deg(lambda_target_deg)
try:
year = int(args[1])
except ValueError as exc:
fail("Jahr ist ungueltig.", extra={"details": str(exc), "argv": args})
timezone_name = args[2]
try:
tz = ZoneInfo(timezone_name)
except Exception as exc: # pragma: no cover
fail("Zeitzone ist ungueltig oder auf dem Server nicht verfuegbar.", extra={"details": str(exc)})
start_dt_utc = datetime(year, 1, 1, 0, 0, 0, tzinfo=timezone.utc)
start_time = dt_to_time(start_dt_utc)
lambda0_deg = float(astronomy.SunPosition(start_time).elon)
delta_lambda_deg = normalize_longitude_deg(lambda_target_deg - lambda0_deg)
delta_t_days = delta_lambda_deg / 0.98564736
estimated_dt_utc = start_dt_utc + timedelta(days=delta_t_days)
search_start_dt_utc = estimated_dt_utc - timedelta(days=5)
search_start_time = dt_to_time(search_start_dt_utc)
result_time = astronomy.SearchSunLongitude(lambda_target_deg, search_start_time, 10.0)
if result_time is None:
fail(
"Kein Zeitpunkt fuer die angegebene solare Laenge gefunden.",
extra={
"lambda_target_deg": lambda_target_deg,
"year": year,
"timezone": timezone_name,
},
)
utc_dt = time_to_datetime(result_time)
local_dt = utc_dt.astimezone(tz)
return {
"ok": True,
"action": "solar_longitude_to_datetime",
"input": {
"lambda_target_deg": lambda_target_deg,
"year": year,
"timezone": timezone_name,
},
"reference": {
"utc_iso": start_dt_utc.isoformat().replace("+00:00", "Z"),
"lambda0_deg": lambda0_deg,
},
"estimate": {
"delta_lambda_deg": delta_lambda_deg,
"delta_t_days": delta_t_days,
"estimated_utc_iso": estimated_dt_utc.isoformat().replace("+00:00", "Z"),
},
"result": {
"utc_iso": utc_dt.isoformat().replace("+00:00", "Z"),
"local_iso": local_dt.isoformat(),
"local_date": local_dt.strftime("%Y-%m-%d"),
"local_time": local_dt.strftime("%H:%M:%S"),
"jd_tt": float(result_time.tt) + 2451545.0,
"jd_ut": float(result_time.ut) + 2451545.0,
},
}
def action_current_solar_longitude(args: list[str]) -> dict:
if len(args) != 1:
fail(
"Aktion current_solar_longitude erwartet 1 Argument: timezone",
extra={"argv": args},
)
timezone_name = args[0]
try:
tz = ZoneInfo(timezone_name)
except Exception as exc: # pragma: no cover
fail("Zeitzone ist ungueltig oder auf dem Server nicht verfuegbar.", extra={"details": str(exc)})
utc_dt = datetime.now(timezone.utc)
time_value = dt_to_time(utc_dt)
solar_longitude_deg = float(astronomy.SunPosition(time_value).elon)
local_dt = utc_dt.astimezone(tz)
return {
"ok": True,
"action": "current_solar_longitude",
"result": {
"solar_longitude_deg": solar_longitude_deg,
"utc_iso": utc_dt.isoformat().replace("+00:00", "Z"),
"local_iso": local_dt.isoformat(),
"local_date": local_dt.strftime("%Y-%m-%d"),
"local_time": local_dt.strftime("%H:%M:%S"),
},
}
def search_event(
body: astronomy.Body,
direction: astronomy.Direction,
@@ -4014,7 +4125,7 @@ def action_satellite_passes(args: list[str]) -> dict:
def main() -> None:
if len(sys.argv) < 2:
fail("Es wurde keine Aktion uebergeben.", extra={"available_actions": ["sun_moon_rise_set", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "month_sky_context", "moon_phases_for_month", "golden_handle_for_month", "season_changes_for_month", "time_changes_for_month", "moon_planet_approaches", "moon_deep_sky_approaches_for_month", "planet_bright_star_approaches_for_month", "planet_conjunctions_for_month", "eclipses_for_month", "moon_apsides_for_month", "sun_apsides_for_month", "inner_planet_elongations_for_month", "venus_peak_magnitude_for_month", "outer_planet_events_for_month", "outer_planet_stations_for_month", "jupiter_moons_one_side_for_month", "mercury_good_visibility_for_month", "planet_parades_for_month", "planet_constellation_changes_for_month", "moon_star_occultations_for_month"]})
fail("Es wurde keine Aktion uebergeben.", extra={"available_actions": ["sun_moon_rise_set", "solar_longitude_to_datetime", "current_solar_longitude", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "month_sky_context", "moon_phases_for_month", "golden_handle_for_month", "season_changes_for_month", "time_changes_for_month", "moon_planet_approaches", "moon_deep_sky_approaches_for_month", "planet_bright_star_approaches_for_month", "planet_conjunctions_for_month", "eclipses_for_month", "moon_apsides_for_month", "sun_apsides_for_month", "inner_planet_elongations_for_month", "venus_peak_magnitude_for_month", "outer_planet_events_for_month", "outer_planet_stations_for_month", "jupiter_moons_one_side_for_month", "mercury_good_visibility_for_month", "planet_parades_for_month", "planet_constellation_changes_for_month", "moon_star_occultations_for_month"]})
action = sys.argv[1]
args = sys.argv[2:]
@@ -4024,6 +4135,16 @@ def main() -> None:
print(json.dumps(result, ensure_ascii=True))
return
if action == "solar_longitude_to_datetime":
result = action_solar_longitude_to_datetime(args)
print(json.dumps(result, ensure_ascii=True))
return
if action == "current_solar_longitude":
result = action_current_solar_longitude(args)
print(json.dumps(result, ensure_ascii=True))
return
if action == "moon_star_occultations":
result = action_moon_star_occultations(args)
print(json.dumps(result, ensure_ascii=True))
@@ -4149,7 +4270,7 @@ def main() -> None:
print(json.dumps(result, ensure_ascii=True))
return
fail("Unbekannte Aktion.", extra={"action": action, "available_actions": ["sun_moon_rise_set", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "month_sky_context", "moon_phases_for_month", "golden_handle_for_month", "season_changes_for_month", "time_changes_for_month", "moon_planet_approaches", "moon_deep_sky_approaches_for_month", "planet_bright_star_approaches_for_month", "planet_conjunctions_for_month", "eclipses_for_month", "moon_apsides_for_month", "sun_apsides_for_month", "inner_planet_elongations_for_month", "venus_peak_magnitude_for_month", "outer_planet_events_for_month", "outer_planet_stations_for_month", "jupiter_moons_one_side_for_month", "mercury_good_visibility_for_month", "planet_parades_for_month", "planet_constellation_changes_for_month", "moon_star_occultations_for_month"]})
fail("Unbekannte Aktion.", extra={"action": action, "available_actions": ["sun_moon_rise_set", "solar_longitude_to_datetime", "current_solar_longitude", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "month_sky_context", "moon_phases_for_month", "golden_handle_for_month", "season_changes_for_month", "time_changes_for_month", "moon_planet_approaches", "moon_deep_sky_approaches_for_month", "planet_bright_star_approaches_for_month", "planet_conjunctions_for_month", "eclipses_for_month", "moon_apsides_for_month", "sun_apsides_for_month", "inner_planet_elongations_for_month", "venus_peak_magnitude_for_month", "outer_planet_events_for_month", "outer_planet_stations_for_month", "jupiter_moons_one_side_for_month", "mercury_good_visibility_for_month", "planet_parades_for_month", "planet_constellation_changes_for_month", "moon_star_occultations_for_month"]})
if __name__ == "__main__":