Refactor: Rename user_stats to user_profile and restructure schema

- Rename user_stats table to user_profile
- Split full_name into first_name and last_name columns
- Remove message_count (focus on profile data only)
- Add is_bot flag to track bot accounts
- Create migration.sql with automatic data migration and schema conversion
- Update MIGRATION.md with rename and migration instructions
- Update all DatabaseManager methods to use new table structure
- Update profile change detection to use separated name fields
This commit is contained in:
2026-06-09 20:42:49 +02:00
parent 2af4603ba3
commit 9006efcb8f
3 changed files with 75 additions and 146 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
config.yaml config.yaml
activity_log.txt
venv venv
.venv .venv
*.db *.db
-86
View File
@@ -1,86 +0,0 @@
[2026-06-09 15:52:24] | CHAT_ID=-1001465084814 | TOPIC=MAIN | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: '....'
[2026-06-09 15:52:24] | CHAT_ID=-1001465084814 | TOPIC=MAIN | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: '....'
[2026-06-09 16:19:40] | CHAT_ID=-1001465084814 | TOPIC=MAIN | TYPE=MESSAGE | USER=884807537 (None) | DETAILS=Nachricht gesendet: 'Liege zu verschenken, abzuholen in Palmbach....'
[2026-06-09 16:19:40] | CHAT_ID=-1001465084814 | TOPIC=MAIN | TYPE=MESSAGE | USER=884807537 (None) | DETAILS=Nachricht gesendet: 'Liege zu verschenken, abzuholen in Palmbach....'
[2026-06-09 16:25:07] | CHAT_ID=-1001465084814 | TOPIC=MAIN | TYPE=MESSAGE | USER=1392350107 (None) | DETAILS=Nachricht gesendet: 'Hab geschrieben...'
[2026-06-09 16:25:07] | CHAT_ID=-1001465084814 | TOPIC=MAIN | TYPE=MESSAGE | USER=1392350107 (None) | DETAILS=Nachricht gesendet: 'Hab geschrieben...'
[2026-06-09 16:27:17] | CHAT_ID=-1001465084814 | TOPIC=MAIN | TYPE=MESSAGE | USER=884807537 (None) | DETAILS=Nachricht gesendet: 'Reserviert für Mariiam...'
[2026-06-09 16:27:17] | CHAT_ID=-1001465084814 | TOPIC=MAIN | TYPE=MESSAGE | USER=884807537 (None) | DETAILS=Nachricht gesendet: 'Reserviert für Mariiam...'
[2026-06-09 18:12:25] | CHAT_ID=-1001465084814 | TOPIC=MAIN | TYPE=MESSAGE | USER=8062402525 (nwskhhh) | DETAILS=Nachricht gesendet: 'Доброго времени суток дорогие друзья😁
Хотелось бы ...'
[2026-06-09 18:12:25] | CHAT_ID=-1001465084814 | TOPIC=MAIN | TYPE=MESSAGE | USER=8062402525 (nwskhhh) | DETAILS=Nachricht gesendet: 'Доброго времени суток дорогие друзья😁
Хотелось бы ...'
[2026-06-09 18:28:43] | CHAT_ID=-1001465084814 | TOPIC=MAIN | TYPE=MESSAGE | USER=93813065 (chrisarnu) | DETAILS=Nachricht gesendet: '@admin...'
[2026-06-09 18:28:43] | CHAT_ID=-1001465084814 | TOPIC=MAIN | TYPE=MESSAGE | USER=93813065 (chrisarnu) | DETAILS=Nachricht gesendet: '@admin...'
[2026-06-09 19:36:03] | CHAT_ID=-1001465084814 | TOPIC=MAIN | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: '....'
[2026-06-09 19:36:03] | CHAT_ID=-1001465084814 | TOPIC=MAIN | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: '....'
[2026-06-09 19:38:04] | CHAT_ID=-1001465084814 | TOPIC=MAIN | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: '....'
[2026-06-09 19:38:04] | CHAT_ID=-1001465084814 | TOPIC=MAIN | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: '....'
[2026-06-09 19:47:37] | CHAT_ID=-1001465084814 | TOPIC=84696 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: '....'
[2026-06-09 19:47:37] | CHAT_ID=-1001465084814 | TOPIC=84696 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: '....'
[2026-06-09 19:49:05] | CHAT_ID=-1001465084814 | TOPIC=84696 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: '....'
[2026-06-09 19:49:05] | CHAT_ID=-1001465084814 | TOPIC=84696 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: '....'
[2026-06-09 19:54:35] | CHAT_ID=-1001202289941 | TOPIC=MAIN | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'hi...'
[2026-06-09 19:54:35] | CHAT_ID=-1001202289941 | TOPIC=MAIN | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'hi...'
[2026-06-09 19:54:55] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'test...'
[2026-06-09 19:54:55] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'test...'
[2026-06-09 19:55:53] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'a...'
[2026-06-09 19:55:53] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'a...'
[2026-06-09 19:56:20] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'b...'
[2026-06-09 19:56:20] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'b...'
[2026-06-09 19:56:50] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 's...'
[2026-06-09 19:56:50] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 's...'
[2026-06-09 19:57:21] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'a...'
[2026-06-09 19:57:21] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'a...'
[2026-06-09 19:58:47] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'b...'
[2026-06-09 19:58:47] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'b...'
[2026-06-09 20:14:31] | CHAT_ID=-1001202289941 | TOPIC=976 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'a...'
[2026-06-09 20:14:31] | CHAT_ID=-1001202289941 | TOPIC=976 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'a...'
[2026-06-09 20:14:38] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'a...'
[2026-06-09 20:14:38] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'a...'
[2026-06-09 20:14:52] | CHAT_ID=-1001202289941 | TOPIC=757 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'a...'
[2026-06-09 20:14:52] | CHAT_ID=-1001202289941 | TOPIC=757 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'a...'
[2026-06-09 20:14:59] | CHAT_ID=-1001202289941 | TOPIC=976 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'a...'
[2026-06-09 20:14:59] | CHAT_ID=-1001202289941 | TOPIC=976 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'a...'
[2026-06-09 20:15:36] | CHAT_ID=-1001202289941 | TOPIC=976 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'ah ok...'
[2026-06-09 20:15:36] | CHAT_ID=-1001202289941 | TOPIC=976 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'ah ok...'
[2026-06-09 20:16:36] | CHAT_ID=-1001202289941 | TOPIC=976 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'hmm...'
[2026-06-09 20:16:36] | CHAT_ID=-1001202289941 | TOPIC=976 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'hmm...'
[2026-06-09 20:17:53] | CHAT_ID=-1001202289941 | TOPIC=757 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'a...'
[2026-06-09 20:17:53] | CHAT_ID=-1001202289941 | TOPIC=757 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'a...'
[2026-06-09 20:18:13] | CHAT_ID=-1001202289941 | TOPIC=757 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'OK?...'
[2026-06-09 20:18:13] | CHAT_ID=-1001202289941 | TOPIC=757 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'OK?...'
[2026-06-09 20:21:32] | CHAT_ID=-1001202289941 | TOPIC=757 | TYPE=PROFILE_CHANGE | USER=151261436 (tokelemma) | DETAILS=Profiländerung erkannt | Name: 'Toke 🌻' → 'Toke. 🌻'
[2026-06-09 20:21:32] | CHAT_ID=-1001202289941 | TOPIC=757 | TYPE=PROFILE_CHANGE | USER=151261436 (tokelemma) | DETAILS=Profiländerung erkannt | Name: 'Toke 🌻' → 'Toke. 🌻'
[2026-06-09 20:21:32] | CHAT_ID=-1001202289941 | TOPIC=757 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'a...'
[2026-06-09 20:21:32] | CHAT_ID=-1001202289941 | TOPIC=757 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'a...'
[2026-06-09 20:22:38] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=PROFILE_CHANGE | USER=151261436 (tokelemma) | DETAILS=Profiländerung erkannt | Name: 'Toke 🌻' → 'Toke. 🌻'
[2026-06-09 20:22:38] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=PROFILE_CHANGE | USER=151261436 (tokelemma) | DETAILS=Profiländerung erkannt | Name: 'Toke 🌻' → 'Toke. 🌻'
[2026-06-09 20:22:38] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'geht das?...'
[2026-06-09 20:22:38] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'geht das?...'
[2026-06-09 20:23:31] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=PROFILE_CHANGE | USER=151261436 (tokelemma) | DETAILS=Profiländerung erkannt | Name: 'Toke 🌻' → 'Toke. 🌻'
[2026-06-09 20:23:31] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=PROFILE_CHANGE | USER=151261436 (tokelemma) | DETAILS=Profiländerung erkannt | Name: 'Toke 🌻' → 'Toke. 🌻'
[2026-06-09 20:23:31] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'aha...'
[2026-06-09 20:23:31] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'aha...'
[2026-06-09 20:24:05] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=PROFILE_CHANGE | USER=151261436 (tokelemma) | DETAILS=Profiländerung erkannt | Name: 'Toke 🌻' → 'Toke. 🌻'
[2026-06-09 20:24:05] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=PROFILE_CHANGE | USER=151261436 (tokelemma) | DETAILS=Profiländerung erkannt | Name: 'Toke 🌻' → 'Toke. 🌻'
[2026-06-09 20:24:05] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'aber...'
[2026-06-09 20:24:05] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'aber...'
[2026-06-09 20:24:57] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=PROFILE_CHANGE | USER=151261436 (tokelemma) | DETAILS=Profiländerung erkannt | Name: 'Toke 🌻' → 'Toke. 🌻'
[2026-06-09 20:24:57] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=PROFILE_CHANGE | USER=151261436 (tokelemma) | DETAILS=Profiländerung erkannt | Name: 'Toke 🌻' → 'Toke. 🌻'
[2026-06-09 20:24:57] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'nun?...'
[2026-06-09 20:24:57] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'nun?...'
[2026-06-09 20:25:14] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=PROFILE_CHANGE | USER=151261436 (tokelemma) | DETAILS=Profiländerung erkannt | Name: 'Toke 🌻' → 'Toke. 🌻'
[2026-06-09 20:25:14] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=PROFILE_CHANGE | USER=151261436 (tokelemma) | DETAILS=Profiländerung erkannt | Name: 'Toke 🌻' → 'Toke. 🌻'
[2026-06-09 20:25:14] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'grummel...'
[2026-06-09 20:25:14] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'grummel...'
[2026-06-09 20:27:30] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=PROFILE_CHANGE | USER=151261436 (tokelemma) | DETAILS=Profiländerung erkannt | Name: 'Toke 🌻' → 'Toke. 🌻'
[2026-06-09 20:27:30] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=PROFILE_CHANGE | USER=151261436 (tokelemma) | DETAILS=Profiländerung erkannt | Name: 'Toke 🌻' → 'Toke. 🌻'
[2026-06-09 20:27:30] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'asd...'
[2026-06-09 20:27:30] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'asd...'
[2026-06-09 20:27:34] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'sad...'
[2026-06-09 20:27:34] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'sad...'
[2026-06-09 20:28:04] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=PROFILE_CHANGE | USER=151261436 (tokelemma) | DETAILS=Profiländerung erkannt | Name: 'Toke. 🌻' → 'Toke 🌻'
[2026-06-09 20:28:04] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=PROFILE_CHANGE | USER=151261436 (tokelemma) | DETAILS=Profiländerung erkannt | Name: 'Toke. 🌻' → 'Toke 🌻'
[2026-06-09 20:28:04] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'Und back...'
[2026-06-09 20:28:04] | CHAT_ID=-1001202289941 | TOPIC=761 | TYPE=MESSAGE | USER=151261436 (tokelemma) | DETAILS=Nachricht gesendet: 'Und back...'
+74 -59
View File
@@ -68,14 +68,15 @@ class DatabaseManager:
) )
""") """)
# 2. user_stats (Angepasst mit Name/Username) # 2. user_profile (Refaktoriert: first_name, last_name, is_bot, kein message_count)
self.cursor.execute(""" self.cursor.execute("""
CREATE TABLE IF NOT EXISTS user_stats ( CREATE TABLE IF NOT EXISTS user_profile (
user_id INTEGER PRIMARY KEY, user_id INTEGER PRIMARY KEY,
message_count INTEGER DEFAULT 0, first_name TEXT,
last_message_timestamp TEXT NULL, last_name TEXT,
full_name TEXT, -- NEU: Benutzername speichern username TEXT,
username TEXT -- NEU: Benutzernamen speichern is_bot INTEGER DEFAULT 0,
last_message_timestamp TEXT NULL
) )
""") """)
@@ -123,52 +124,61 @@ class DatabaseManager:
except Exception as e: except Exception as e:
logging.error(f"Fehler beim Protokollieren der Profiländerung: {e}") logging.error(f"Fehler beim Protokollieren der Profiländerung: {e}")
def update_user_stats(self, user_id: int, message_count: int, last_message_timestamp: str, full_name: str = None, username: str = None):
"""Aktualisiert die Statistiken und das letzte bekannte Profil des Benutzers."""
try:
# Die Spaltenliste muss genau den Reihenfolge der Argumente entsprechen.
self.cursor.execute("""
INSERT INTO user_stats (user_id, message_count, last_message_timestamp, full_name, username)
VALUES (?, ?, ?, ?, ?)
ON CONFLICT(user_id) DO UPDATE SET
message_count = excluded.message_count,
last_message_timestamp = excluded.last_message_timestamp,
full_name = (CASE WHEN user_stats.full_name IS NULL THEN excluded.full_name ELSE user_stats.full_name END),
username = (CASE WHEN user_stats.username IS NULL THEN excluded.username ELSE user_stats.username END)
""", (user_id, message_count, last_message_timestamp, full_name, username))
self.conn.commit()
except Exception as e:
logging.error(f"Fehler beim Aktualisieren der User Stats für {user_id}: {e}")
def get_user_profile(self, user_id: int) -> dict: def get_user_profile(self, user_id: int) -> dict:
"""Lädt das gespeicherte Profil eines Benutzers aus der Datenbank.""" """Lädt das gespeicherte Profil eines Benutzers aus der Datenbank."""
try: try:
self.cursor.execute(""" self.cursor.execute("""
SELECT full_name, username FROM user_stats WHERE user_id = ? SELECT first_name, last_name, username, is_bot FROM user_profile WHERE user_id = ?
""", (user_id,)) """, (user_id,))
result = self.cursor.fetchone() result = self.cursor.fetchone()
if result: if result:
return {'full_name': result[0], 'username': result[1]} return {
'first_name': result[0],
'last_name': result[1],
'username': result[2],
'is_bot': result[3]
}
return None return None
except Exception as e: except Exception as e:
logging.error(f"Fehler beim Laden des Benutzerprofils {user_id}: {e}") logging.error(f"Fehler beim Laden des Benutzerprofils {user_id}: {e}")
return None return None
def update_user_profile(self, user_id: int, full_name: str, username: str): def update_user_profile(self, user_id: int, first_name: str, last_name: str, username: str, is_bot: bool = False):
"""Aktualisiert nur die Profilinformationen (Name/Username) eines Benutzers. """Aktualisiert nur die Profilinformationen eines Benutzers (ohne Nachrichtenstatistiken).
Erstellt den Benutzer automatisch, falls er noch nicht existiert. Erstellt den Benutzer automatisch, falls er noch nicht existiert.
""" """
try: try:
self.cursor.execute(""" self.cursor.execute("""
INSERT INTO user_stats (user_id, full_name, username, message_count, last_message_timestamp) INSERT INTO user_profile (user_id, first_name, last_name, username, is_bot, last_message_timestamp)
VALUES (?, ?, ?, 0, NULL) VALUES (?, ?, ?, ?, ?, NULL)
ON CONFLICT(user_id) DO UPDATE SET full_name = excluded.full_name, username = excluded.username ON CONFLICT(user_id) DO UPDATE SET
""", (user_id, full_name, username)) first_name = excluded.first_name,
last_name = excluded.last_name,
username = excluded.username,
is_bot = excluded.is_bot
""", (user_id, first_name, last_name, username, int(is_bot)))
self.conn.commit() self.conn.commit()
except Exception as e: except Exception as e:
logging.error(f"Fehler beim Aktualisieren des Benutzerprofils {user_id}: {e}") logging.error(f"Fehler beim Aktualisieren des Benutzerprofils {user_id}: {e}")
def update_user_stats(self, user_id: int, last_message_timestamp: str, first_name: str = None, last_name: str = None, username: str = None, is_bot: bool = False):
"""Aktualisiert die Statistiken und das letzte bekannte Profil des Benutzers."""
try:
self.cursor.execute("""
INSERT INTO user_profile (user_id, first_name, last_name, username, is_bot, last_message_timestamp)
VALUES (?, ?, ?, ?, ?, ?)
ON CONFLICT(user_id) DO UPDATE SET
last_message_timestamp = excluded.last_message_timestamp,
first_name = COALESCE(excluded.first_name, user_profile.first_name),
last_name = COALESCE(excluded.last_name, user_profile.last_name),
username = COALESCE(excluded.username, user_profile.username),
is_bot = COALESCE(NULLIF(excluded.is_bot, 0), user_profile.is_bot)
""", (user_id, first_name, last_name, username, int(is_bot), last_message_timestamp))
self.conn.commit()
except Exception as e:
logging.error(f"Fehler beim Aktualisieren der User Stats für {user_id}: {e}")
def close(self): def close(self):
"""Schließt die Datenbankverbindung.""" """Schließt die Datenbankverbindung."""
self.conn.close() self.conn.close()
@@ -222,34 +232,44 @@ class MonitoringBot:
# --- EVENT HANDLER 2: PROFILDÄNDERUNG (Profilvergleich mit DB) --- # --- EVENT HANDLER 2: PROFILDÄNDERUNG (Profilvergleich mit DB) ---
async def handle_profile_update(self, update: Update, context: ContextTypes.DEFAULT_TYPE): async def handle_profile_update(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Erkennt Profiländerungen durch Vergleich des gespeicherten Profils mit dem aktuellen.""" """Erkennt Profiländerungen durch Vergleich des gespeicherten Profils mit dem aktuellen."""
if not update or not update.effective_user or not update.effective_chat:
#if not update or not update.effective_user or not update.effective_chat: return
# return
user = update.effective_user user = update.effective_user
chat_id = update.effective_chat.id chat_id = update.effective_chat.id
topic_id = self._get_topic_id(update) topic_id = self._get_topic_id(update)
current_full_name = user.full_name
# Extrahiere current profile
current_first_name = user.first_name or ""
current_last_name = user.last_name or ""
current_username = getattr(user, 'username', None) current_username = getattr(user, 'username', None)
current_is_bot = user.is_bot
# Lade das alte Profil aus der Datenbank # Lade das alte Profil aus der Datenbank
old_profile = self.db.get_user_profile(user.id) old_profile = self.db.get_user_profile(user.id)
# Vergleiche mit dem aktuellen Profil # Vergleiche mit dem aktuellen Profil
if old_profile: if old_profile:
old_full_name = old_profile['full_name'] old_first_name = old_profile['first_name'] or ""
old_last_name = old_profile['last_name'] or ""
old_username = old_profile['username'] old_username = old_profile['username']
old_is_bot = old_profile['is_bot']
# Prüfe auf Änderungen # Prüfe auf Änderungen
has_name_changed = old_full_name != current_full_name has_name_changed = (old_first_name != current_first_name) or (old_last_name != current_last_name)
has_username_changed = old_username != current_username has_username_changed = old_username != current_username
has_is_bot_changed = old_is_bot != current_is_bot
if has_name_changed or has_username_changed: if has_name_changed or has_username_changed or has_is_bot_changed:
details = f"Profiländerung erkannt" details = f"Profiländerung erkannt"
if has_name_changed: if has_name_changed:
details += f" | Name: '{old_full_name}''{current_full_name}'" old_full = f"{old_first_name} {old_last_name}".strip()
new_full = f"{current_first_name} {current_last_name}".strip()
details += f" | Name: '{old_full}''{new_full}'"
if has_username_changed: if has_username_changed:
details += f" | Username: '{old_username}''{current_username}'" details += f" | Username: '{old_username}''{current_username}'"
if has_is_bot_changed:
details += f" | is_bot: {old_is_bot}{current_is_bot}"
self._log_event( self._log_event(
client=update, context=context, chat_id=chat_id, topic_id=topic_id, client=update, context=context, chat_id=chat_id, topic_id=topic_id,
@@ -262,8 +282,8 @@ class MonitoringBot:
group_chat_id=chat_id, group_chat_id=chat_id,
user_id=user.id, user_id=user.id,
topic_id=topic_id, topic_id=topic_id,
old_name=old_full_name or "N/A", old_name=f"{old_first_name} {old_last_name}".strip() or "N/A",
new_name=current_full_name, new_name=f"{current_first_name} {current_last_name}".strip(),
old_user=old_username or "N/A", old_user=old_username or "N/A",
new_user=current_username or "N/A", new_user=current_username or "N/A",
details=details details=details
@@ -272,8 +292,10 @@ class MonitoringBot:
# Persistiere die neuen Profilinformationen in user_stats # Persistiere die neuen Profilinformationen in user_stats
self.db.update_user_profile( self.db.update_user_profile(
user_id=user.id, user_id=user.id,
full_name=current_full_name, first_name=current_first_name,
username=current_username last_name=current_last_name,
username=current_username,
is_bot=current_is_bot
) )
@@ -297,13 +319,14 @@ class MonitoringBot:
user = update.effective_user user = update.effective_user
timestamp_str = datetime.now().isoformat() timestamp_str = datetime.now().isoformat()
# 2. Statistik-Update: User ID, Count erhöhen und aktuelle Profildaten speichern # 2. Statistik-Update: Profildaten speichern und Timestamp aktualisieren
self._update_user_stats( self._update_user_stats(
user_id=user.id, user_id=user.id,
message_count=+1,
last_message_timestamp=timestamp_str, last_message_timestamp=timestamp_str,
full_name=user.full_name, # Aktueller Name vom Telegram Update first_name=user.first_name,
username=getattr(user, 'username', None) # Optional: Username last_name=user.last_name or None,
username=getattr(user, 'username', None),
is_bot=user.is_bot
) )
# General Logging (Protokollierung des Ereignisses) # General Logging (Protokollierung des Ereignisses)
@@ -318,29 +341,21 @@ class MonitoringBot:
"""Interne Funktion zur Durchführung des Datenbank- und File-Logging.""" """Interne Funktion zur Durchführung des Datenbank- und File-Logging."""
self.db.log_activity(group_chat_id=chat_id, topic_id=topic_id, activity_type=activity_type, user_id=user_id, username=username, details=details) self.db.log_activity(group_chat_id=chat_id, topic_id=topic_id, activity_type=activity_type, user_id=user_id, username=username, details=details)
# Debug Output (Bleibt stabil) # Debug Output
if ENABLE_DEBUG_MODE: if ENABLE_DEBUG_MODE:
logging.info(f"[LOG] Aktivität erfasst ({activity_type}): User {user_id} | Topic '{topic_id}'") logging.info(f"[LOG] Aktivität erfasst ({activity_type}): User {user_id} | Topic '{topic_id}'")
if WRITE_ACTIVITY_TO_FILE: if WRITE_ACTIVITY_TO_FILE:
print(f"--- DEBUG LOG ENTRY --- Type: {activity_type}, Topic: {topic_id}, User: {username or user_id}") print(f"--- DEBUG LOG ENTRY --- Type: {activity_type}, Topic: {topic_id}, User: {username or user_id}")
# Optional File Logging (Bleibt stabil)
if WRITE_ACTIVITY_TO_FILE:
log_message = f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] | CHAT_ID={chat_id} | TOPIC={topic_id} | TYPE={activity_type} | USER={user_id} ({username}) | DETAILS={details}\n"
with open(LOGGING_FILE, 'a', encoding='utf-8') as f:
f.write(log_message)
# Optional File Logging # Optional File Logging
if WRITE_ACTIVITY_TO_FILE: if WRITE_ACTIVITY_TO_FILE:
log_message = f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] | CHAT_ID={chat_id} | TOPIC={topic_id} | TYPE={activity_type} | USER={user_id} ({username}) | DETAILS={details}\n" log_message = f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] | CHAT_ID={chat_id} | TOPIC={topic_id} | TYPE={activity_type} | USER={user_id} ({username}) | DETAILS={details}\n"
with open(LOGGING_FILE, 'a', encoding='utf-8') as f: with open(LOGGING_FILE, 'a', encoding='utf-8') as f:
f.write(log_message) f.write(log_message)
def _update_user_stats(self, user_id: int, message_count: int, last_message_timestamp: str, full_name: str = None, username: str = None): def _update_user_stats(self, user_id: int, last_message_timestamp: str, first_name: str = None, last_name: str = None, username: str = None, is_bot: bool = False):
"""Aktualisiert die Statistiken und das Profil des Benutzers via DatabaseManager.""" """Wrapper für DatabaseManager.update_user_stats()."""
# Ruft die korrigierte Methode aus dem Manager auf. self.db.update_user_stats(user_id, last_message_timestamp, first_name, last_name, username, is_bot)
self.db.update_user_stats(user_id, message_count, last_message_timestamp, full_name=full_name, username=username)
# --- HAUPT-RUN FUNKTION (Bleibt gleich) --- # --- HAUPT-RUN FUNKTION (Bleibt gleich) ---