main.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. # -*- coding: utf-8 -*-
  2. """
  3. DateTime-Info Plugin fuer Trixy.
  4. Beantwortet Fragen zu Datum und Uhrzeit:
  5. - Aktuelle Uhrzeit
  6. - Heutiges Datum
  7. - Wochentag-Abfragen fuer beliebige Daten
  8. """
  9. from datetime import date as date_type
  10. from datetime import datetime
  11. from pathlib import Path
  12. from typing import Any
  13. from trixy_core.nlp.decorators import intent, pattern, example
  14. from trixy_core.nlp.entities import _WEEKDAY_NAMES, _MONTH_NAMES, ResolvedEntity
  15. from trixy_core.nlp.handler import IntentReceivedData, IntentResult
  16. from trixy_core.nlp.intent_registry import IntentRegistry
  17. from trixy_core.plugins.trixy_plugin import TrixyPlugin
  18. from trixy_core.utils.debug import pdebug, pinfo
  19. class DatetimeInfoPlugin(TrixyPlugin):
  20. """Plugin fuer Datum- und Uhrzeit-Abfragen."""
  21. NAME = "datetime_info"
  22. VERSION = "1.0.0"
  23. DESCRIPTION = "Datum- und Uhrzeit-Abfragen per Sprache"
  24. AUTHOR = "Trixy"
  25. def __init__(
  26. self,
  27. application: Any,
  28. plugin_path: Path,
  29. config: dict[str, Any] | None = None,
  30. ) -> None:
  31. super().__init__(application, plugin_path, config)
  32. self._registry = IntentRegistry.get_instance()
  33. async def on_load(self) -> None:
  34. """Plugin laden."""
  35. pinfo(f"DatetimeInfoPlugin: Lade Plugin v{self.VERSION}")
  36. async def on_unload(self) -> None:
  37. """Plugin entladen."""
  38. self._registry.unregister_plugin(self.NAME)
  39. pdebug("DatetimeInfoPlugin: Entladen")
  40. # ===== Intent-Handler =====
  41. @intent("current_time", description="Aktuelle Uhrzeit abfragen")
  42. @pattern("(wieviel|wie viel) uhr ist [es]")
  43. @pattern("wie (spaet|spät) ist [es]")
  44. @pattern("uhrzeit")
  45. @pattern("(sag|nenn) [mir] [die] (uhrzeit|zeit)")
  46. @example("Wieviel Uhr ist es?", "Wie spät ist es?")
  47. async def handle_current_time(
  48. self, data: IntentReceivedData,
  49. ) -> IntentResult:
  50. """Handler fuer den Intent 'current_time'."""
  51. now = datetime.now()
  52. if now.minute == 0:
  53. response = f"Es ist {now.hour} Uhr."
  54. else:
  55. response = f"Es ist {now.hour} Uhr {now.minute:02d}."
  56. return IntentResult.success_with_response(response)
  57. @intent("current_date", description="Heutiges Datum abfragen")
  58. @pattern("(welcher|welches|was fuer ein) (tag|datum) ist heute")
  59. @pattern("was ist heute [fuer ein] (tag|datum)")
  60. @pattern("(sag|nenn) [mir] [das] datum")
  61. @pattern("datum [heute]")
  62. @example("Welcher Tag ist heute?", "Welches Datum haben wir?")
  63. async def handle_current_date(
  64. self, data: IntentReceivedData,
  65. ) -> IntentResult:
  66. """Handler fuer den Intent 'current_date'."""
  67. today = date_type.today()
  68. weekday = _WEEKDAY_NAMES[today.weekday()]
  69. month = _MONTH_NAMES[today.month]
  70. response = f"Heute ist {weekday}, der {today.day}. {month}."
  71. return IntentResult.success_with_response(response)
  72. @intent("date_query", description="Datum-Abfrage mit Slot")
  73. @pattern("(welcher|was fuer ein) (tag|wochentag) ist {date:datum}")
  74. @pattern("was ist {date:datum} [fuer ein] (tag|wochentag)")
  75. @pattern("was (fuer|für) [ein] (tag|wochentag) ist [der] {date:datum}")
  76. @pattern("(welcher|was fuer ein) (tag|wochentag) ist [der] {date:datum}")
  77. @example("Welcher Tag ist morgen?", "Was ist Dienstag fuer ein Tag?")
  78. @example("Was fuer ein Wochentag ist der 5. Mai?")
  79. async def handle_date_query(
  80. self, data: IntentReceivedData, date: str = "",
  81. ) -> IntentResult:
  82. """Handler fuer den Intent 'date_query'."""
  83. resolved = data.get_resolved_slot("date")
  84. if resolved is None or not isinstance(resolved.value, date_type):
  85. raw = data.get_slot("date", "")
  86. return IntentResult.failure(
  87. f"Datum '{raw}' konnte nicht aufgeloest werden",
  88. response_text="Das Datum konnte ich leider nicht verstehen.",
  89. )
  90. target: date_type = resolved.value
  91. weekday = _WEEKDAY_NAMES[target.weekday()]
  92. month = _MONTH_NAMES[target.month]
  93. # Antwort je nach Eingabe-Typ variieren
  94. raw_lower = resolved.raw.lower()
  95. if raw_lower in ("heute",):
  96. response = f"Heute ist {weekday}, der {target.day}. {month}."
  97. elif raw_lower in ("morgen",):
  98. response = f"Morgen ist {weekday}, der {target.day}. {month}."
  99. elif raw_lower in ("uebermorgen", "übermorgen"):
  100. response = f"Uebermorgen ist {weekday}, der {target.day}. {month}."
  101. elif raw_lower in (
  102. "montag", "dienstag", "mittwoch", "donnerstag",
  103. "freitag", "samstag", "sonntag",
  104. ):
  105. response = f"{weekday} ist der {target.day}. {month} {target.year}."
  106. else:
  107. # Absolutes Datum: "der 5. Mai 2026 ist ein Dienstag"
  108. response = (
  109. f"Der {target.day}. {month} {target.year} ist ein {weekday}."
  110. )
  111. return IntentResult.success_with_response(response)