Add Ping Bot Config to Settings

This commit is contained in:
pdxlocations
2026-03-28 22:35:34 -07:00
parent 6721874937
commit 0ad39fd6a0
8 changed files with 69 additions and 15 deletions
+6 -2
View File
@@ -96,8 +96,6 @@ bot.status.disabled, "Disabled", ""
bot.dialog.title, "Bot Responder", ""
bot.dialog.body, "Bot responder is now {status}.", ""
bot.status.message, "Bot responder is now {status}.", ""
bot.catch_words, "ping; test", "Semicolon-separated bot trigger words."
bot.response.word, "Pong!", "Bot response word."
[User Settings]
user, "User"
@@ -124,10 +122,16 @@ nak_str, "NAK", ""
ack_unknown_str, "ACK (unknown)", ""
node_sort, "Node sort", ""
theme, "Theme", ""
ping_bot, "Ping Bot", ""
COLOR_CONFIG_DARK, "Theme colors (dark)", ""
COLOR_CONFIG_LIGHT, "Theme colors (light)", ""
COLOR_CONFIG_GREEN, "Theme colors (green)", ""
[app_settings.ping_bot]
title, "Ping Bot", ""
catch_words, "Catch words", "Semicolon-separated bot trigger words."
response_word, "Response word", "Bot response word."
[app_settings.color_config]
default, "Default", ""
background, "Background", ""
+6 -2
View File
@@ -88,8 +88,6 @@ bot.status.disabled, "Désactivé", ""
bot.dialog.title, "Bot répondeur", ""
bot.dialog.body, "Le bot répondeur est maintenant {status}.", ""
bot.status.message, "Le bot répondeur est maintenant {status}.", ""
bot.catch_words, "ping", "Mots déclencheurs du bot séparés par des virgules."
bot.response.word, "Pong!", "Mot de reponse du bot (orthographe preferee)."
[User Settings]
user, "Utilisateur", ""
@@ -116,6 +114,12 @@ nak_str, "NAK", ""
ack_unknown_str, "ACK (inconnu)", ""
node_sort, "Tri des nœuds", ""
theme, "Thème", ""
ping_bot, "Bot Ping", ""
[app_settings.ping_bot]
title, "Bot Ping", ""
catch_words, "Mots déclencheurs", "Mots déclencheurs du bot séparés par des points-virgules."
response_word, "Mot de réponse", "Mot de réponse du bot."
[config.device]
title, "Appareil", ""
+6 -2
View File
@@ -96,8 +96,6 @@ bot.status.disabled, "Выключен", ""
bot.dialog.title, "Автоответчик", ""
bot.dialog.body, "Автоответчик теперь {status}.", ""
bot.status.message, "Автоответчик теперь {status}.", ""
bot.catch_words, "ping; пинг", "Слова для активации бота, разделенные точкой с запятой."
bot.response.word, "Понг!", "Ответное слово бота (предпочтительное написание)."
[User Settings]
user, "Пользователь"
@@ -124,10 +122,16 @@ nak_str, "NAK", ""
ack_unknown_str, "ACK (неизвестный)", ""
node_sort, "Сортировка нод", ""
theme, "Тема", ""
ping_bot, "Пинг-бот", ""
COLOR_CONFIG_DARK, "Цвета темы (темная)", ""
COLOR_CONFIG_LIGHT, "Цвета темы (светлая)", ""
COLOR_CONFIG_GREEN, "Цвета темы (зеленая)", ""
[app_settings.ping_bot]
title, "Пинг-бот", ""
catch_words, "Слова-триггеры", "Слова для активации бота, разделенные точкой с запятой."
response_word, "Ответное слово", "Ответное слово бота."
[app_settings.color_config]
default, "По умолчанию", ""
background, "Фон", ""
+5 -5
View File
@@ -4,15 +4,15 @@ import threading
import time
from typing import Any, Dict
import contact.ui.default_config as config
from contact.utilities.singleton import app_state, interface_state, ui_state
from contact.message_handlers.tx_handler import send_message
from contact.utilities.i18n import t
BOT_RESPONSE_DELAY_SECONDS = 2.3
def _get_bot_catch_words() -> set[str]:
"""Return normalized bot trigger words from localisation settings."""
raw_words = t("ui.bot.catch_words", default="ping")
"""Return normalized bot trigger words from app settings."""
raw_words = getattr(config, "ping_bot_catch_words", "ping; test")
words = {
word.strip().casefold()
for word in raw_words.replace(";", ",").split(",")
@@ -60,7 +60,7 @@ def bot_respond(packet: Dict[str, Any], message: str, send_channel: int) -> bool
if transport_name in transport_text:
details.append(f"Via: {transport_name}")
response_data_string = t("ui.bot.response.word", default="Pong!")
response_data_string = getattr(config, "ping_bot_response_word", "Pong!")
if details:
response_data_string += f" {', '.join(details)}"
@@ -84,4 +84,4 @@ def bot_respond(packet: Dict[str, Any], message: str, send_channel: int) -> bool
threading.Thread(target=send_response_delayed, name="bot-response", daemon=True).start()
return True
return True
+8 -1
View File
@@ -238,6 +238,10 @@ def initialize_config() -> Dict[str, object]:
"ack_unknown_str": "[…]",
"node_sort": "lastHeard",
"theme": "dark",
"ping_bot": {
"catch_words": "ping; test",
"response_word": "Pong!",
},
"COLOR_CONFIG_DARK": COLOR_CONFIG_DARK,
"COLOR_CONFIG_LIGHT": COLOR_CONFIG_LIGHT,
"COLOR_CONFIG_GREEN": COLOR_CONFIG_GREEN,
@@ -272,7 +276,7 @@ def assign_config_variables(loaded_config: Dict[str, object]) -> None:
global notification_symbol, ack_implicit_str, ack_str, nak_str, ack_unknown_str
global node_list_16ths, channel_list_16ths, single_pane_mode
global theme, COLOR_CONFIG, language
global node_sort, notification_sound
global node_sort, notification_sound, ping_bot_catch_words, ping_bot_response_word
channel_list_16ths = loaded_config["channel_list_16ths"]
node_list_16ths = loaded_config["node_list_16ths"]
@@ -291,6 +295,9 @@ def assign_config_variables(loaded_config: Dict[str, object]) -> None:
ack_unknown_str = loaded_config["ack_unknown_str"]
node_sort = loaded_config["node_sort"]
theme = loaded_config["theme"]
ping_bot = loaded_config.get("ping_bot", {})
ping_bot_catch_words = ping_bot.get("catch_words", "ping; test")
ping_bot_response_word = ping_bot.get("response_word", "Pong!")
if theme == "dark":
COLOR_CONFIG = loaded_config["COLOR_CONFIG_DARK"]
elif theme == "light":
+4 -1
View File
@@ -309,7 +309,10 @@ def display_menu() -> tuple[Any, Any, List[str]]:
else:
display_key = key
display_key = f"{display_key}"[: w // 2 - 2]
display_value = f"{value}"[: w // 2 - 8]
if isinstance(value, dict) or (isinstance(value, list) and len(value) != 2):
display_value = ">"
else:
display_value = f"{value}"[: w // 2 - 8]
color = get_color("settings_default", reverse=(idx == menu_state.selected_index))
menu_pad.addstr(idx, 0, f"{display_key:<{w // 2 - 2}} {display_value}".ljust(w - 8), color)
+31
View File
@@ -0,0 +1,31 @@
import unittest
import importlib
import sys
import types
from unittest import mock
import contact.ui.default_config as config
class BotHandlerTests(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
sys.modules.setdefault(
"contact.message_handlers.tx_handler",
types.SimpleNamespace(send_message=mock.Mock()),
)
cls.bot_handler = importlib.import_module("contact.message_handlers.bot_handler")
def test_is_bot_message_uses_configured_catch_words(self) -> None:
with mock.patch.object(config, "ping_bot_catch_words", "ping; test; pong"):
self.assertTrue(self.bot_handler.is_bot_message("PING"))
self.assertTrue(self.bot_handler.is_bot_message("test"))
self.assertFalse(self.bot_handler.is_bot_message("hello"))
def test_is_bot_message_ignores_empty_config_values(self) -> None:
with mock.patch.object(config, "ping_bot_catch_words", " ; ; "):
self.assertTrue(self.bot_handler.is_bot_message("ping"))
if __name__ == "__main__":
unittest.main()
+3 -2
View File
@@ -65,8 +65,9 @@ class I18nTests(unittest.TestCase):
"ui.bot.dialog.title",
"ui.bot.dialog.body",
"ui.bot.status.message",
"ui.bot.catch_words",
"ui.bot.response.word",
"app_settings.ping_bot",
"app_settings.ping_bot.catch_words",
"app_settings.ping_bot.response_word",
}
for language in config.get_localisation_options():