refactor: improve code formatting and readability in configuration and run files
All checks were successful
CI / lint-and-test (push) Successful in 38s

- Simplified the assignment of `bot_username` in `config.py` for better clarity.
- Removed redundant import statement in `run.py` to streamline the code.
- Enhanced formatting in `group_duty_pin.py` and test files for improved readability and consistency.
- No functional changes were made; the focus was on code style and organization.
This commit is contained in:
2026-03-02 17:22:55 +03:00
parent 2fb553567f
commit bdead6eef7
4 changed files with 75 additions and 28 deletions

View File

@@ -94,9 +94,7 @@ class Settings:
) )
raw_host = (os.getenv("HTTP_HOST") or "127.0.0.1").strip() raw_host = (os.getenv("HTTP_HOST") or "127.0.0.1").strip()
http_host = raw_host if raw_host else "127.0.0.1" http_host = raw_host if raw_host else "127.0.0.1"
bot_username = ( bot_username = (os.getenv("BOT_USERNAME", "") or "").strip().lstrip("@").lower()
(os.getenv("BOT_USERNAME", "") or "").strip().lstrip("@").lower()
)
return cls( return cls(
bot_token=bot_token, bot_token=bot_token,
database_url=os.getenv("DATABASE_URL", "sqlite:///data/duty_teller.db"), database_url=os.getenv("DATABASE_URL", "sqlite:///data/duty_teller.db"),

View File

@@ -439,7 +439,9 @@ async def trust_group_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE) ->
loop = asyncio.get_running_loop() loop = asyncio.get_running_loop()
already_trusted = await loop.run_in_executor( already_trusted = await loop.run_in_executor(
None, None,
lambda: _sync_trust_group(chat_id, update.effective_user.id if update.effective_user else None), lambda: _sync_trust_group(
chat_id, update.effective_user.id if update.effective_user else None
),
) )
if already_trusted: if already_trusted:
await update.message.reply_text(t(lang, "trust_group.already_trusted")) await update.message.reply_text(t(lang, "trust_group.already_trusted"))

View File

@@ -11,6 +11,7 @@ from telegram.ext import ApplicationBuilder
from duty_teller import config from duty_teller import config
from duty_teller.config import require_bot_token from duty_teller.config import require_bot_token
from duty_teller.handlers import group_duty_pin, register_handlers from duty_teller.handlers import group_duty_pin, register_handlers
from duty_teller.utils.http_client import safe_urlopen
async def _resolve_bot_username(application) -> None: async def _resolve_bot_username(application) -> None:
@@ -19,7 +20,7 @@ async def _resolve_bot_username(application) -> None:
me = await application.bot.get_me() me = await application.bot.get_me()
config.BOT_USERNAME = (me.username or "").lower() config.BOT_USERNAME = (me.username or "").lower()
logger.info("Resolved BOT_USERNAME from API: %s", config.BOT_USERNAME) logger.info("Resolved BOT_USERNAME from API: %s", config.BOT_USERNAME)
from duty_teller.utils.http_client import safe_urlopen
logging.basicConfig( logging.basicConfig(
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",

View File

@@ -177,7 +177,9 @@ async def test_update_group_pin_sends_new_unpins_pins_saves_schedules_next():
with patch.object(config, "DUTY_PIN_NOTIFY", True): with patch.object(config, "DUTY_PIN_NOTIFY", True):
with patch.object(mod, "_sync_is_trusted", return_value=True): with patch.object(mod, "_sync_is_trusted", return_value=True):
with patch.object( with patch.object(
mod, "_sync_get_pin_refresh_data", return_value=(1, "Current duty", None) mod,
"_sync_get_pin_refresh_data",
return_value=(1, "Current duty", None),
): ):
with patch.object(mod, "_schedule_next_update", AsyncMock()): with patch.object(mod, "_schedule_next_update", AsyncMock()):
with patch.object(mod, "_sync_save_pin") as mock_save: with patch.object(mod, "_sync_save_pin") as mock_save:
@@ -205,7 +207,9 @@ async def test_update_group_pin_delete_message_raises_bad_request_still_schedule
context.bot.send_message = AsyncMock(return_value=new_msg) context.bot.send_message = AsyncMock(return_value=new_msg)
context.bot.unpin_chat_message = AsyncMock() context.bot.unpin_chat_message = AsyncMock()
context.bot.pin_chat_message = AsyncMock() context.bot.pin_chat_message = AsyncMock()
context.bot.delete_message = AsyncMock(side_effect=BadRequest("Message to delete not found")) context.bot.delete_message = AsyncMock(
side_effect=BadRequest("Message to delete not found")
)
context.application = MagicMock() context.application = MagicMock()
context.application.job_queue = MagicMock() context.application.job_queue = MagicMock()
context.application.job_queue.get_jobs_by_name = MagicMock(return_value=[]) context.application.job_queue.get_jobs_by_name = MagicMock(return_value=[])
@@ -214,9 +218,13 @@ async def test_update_group_pin_delete_message_raises_bad_request_still_schedule
with patch.object(config, "DUTY_PIN_NOTIFY", True): with patch.object(config, "DUTY_PIN_NOTIFY", True):
with patch.object(mod, "_sync_is_trusted", return_value=True): with patch.object(mod, "_sync_is_trusted", return_value=True):
with patch.object( with patch.object(
mod, "_sync_get_pin_refresh_data", return_value=(1, "Current duty", None) mod,
"_sync_get_pin_refresh_data",
return_value=(1, "Current duty", None),
): ):
with patch.object(mod, "_schedule_next_update", AsyncMock()) as mock_schedule: with patch.object(
mod, "_schedule_next_update", AsyncMock()
) as mock_schedule:
with patch.object(mod, "_sync_save_pin") as mock_save: with patch.object(mod, "_sync_save_pin") as mock_save:
with patch.object(mod, "logger") as mock_logger: with patch.object(mod, "logger") as mock_logger:
await mod.update_group_pin(context) await mod.update_group_pin(context)
@@ -259,7 +267,9 @@ async def test_update_group_pin_send_raises_no_unpin_pin_schedule_still_called()
with patch.object( with patch.object(
mod, "_sync_get_pin_refresh_data", return_value=(2, "Text", None) mod, "_sync_get_pin_refresh_data", return_value=(2, "Text", None)
): ):
with patch.object(mod, "_schedule_next_update", AsyncMock()) as mock_schedule: with patch.object(
mod, "_schedule_next_update", AsyncMock()
) as mock_schedule:
await mod.update_group_pin(context) await mod.update_group_pin(context)
context.bot.unpin_chat_message.assert_not_called() context.bot.unpin_chat_message.assert_not_called()
context.bot.pin_chat_message.assert_not_called() context.bot.pin_chat_message.assert_not_called()
@@ -440,7 +450,9 @@ async def test_pin_duty_cmd_no_message_id_creates_sends_pins_saves_schedules_rep
with patch.object( with patch.object(
mod, "_get_next_shift_end_sync", return_value=None mod, "_get_next_shift_end_sync", return_value=None
): ):
with patch.object(mod, "_schedule_next_update", AsyncMock()): with patch.object(
mod, "_schedule_next_update", AsyncMock()
):
with patch( with patch(
"duty_teller.handlers.group_duty_pin.t" "duty_teller.handlers.group_duty_pin.t"
) as mock_t: ) as mock_t:
@@ -475,12 +487,16 @@ async def test_pin_duty_cmd_no_message_id_send_message_raises_replies_failed():
with patch("duty_teller.handlers.group_duty_pin.get_lang", return_value="en"): with patch("duty_teller.handlers.group_duty_pin.get_lang", return_value="en"):
with patch.object(mod, "_sync_is_trusted", return_value=True): with patch.object(mod, "_sync_is_trusted", return_value=True):
with patch.object(mod, "_sync_get_message_id", return_value=None): with patch.object(mod, "_sync_get_message_id", return_value=None):
with patch.object(mod, "_get_duty_message_text_sync", return_value="Duty"): with patch.object(
mod, "_get_duty_message_text_sync", return_value="Duty"
):
with patch.object(mod, "_sync_save_pin") as mock_save: with patch.object(mod, "_sync_save_pin") as mock_save:
with patch.object( with patch.object(
mod, "_schedule_next_update", AsyncMock() mod, "_schedule_next_update", AsyncMock()
) as mock_schedule: ) as mock_schedule:
with patch("duty_teller.handlers.group_duty_pin.t") as mock_t: with patch(
"duty_teller.handlers.group_duty_pin.t"
) as mock_t:
mock_t.return_value = "Failed" mock_t.return_value = "Failed"
await mod.pin_duty_cmd(update, context) await mod.pin_duty_cmd(update, context)
update.message.reply_text.assert_called_once_with("Failed") update.message.reply_text.assert_called_once_with("Failed")
@@ -513,12 +529,16 @@ async def test_pin_duty_cmd_no_message_id_pin_raises_saves_and_replies_could_not
with patch("duty_teller.handlers.group_duty_pin.get_lang", return_value="en"): with patch("duty_teller.handlers.group_duty_pin.get_lang", return_value="en"):
with patch.object(mod, "_sync_is_trusted", return_value=True): with patch.object(mod, "_sync_is_trusted", return_value=True):
with patch.object(mod, "_sync_get_message_id", return_value=None): with patch.object(mod, "_sync_get_message_id", return_value=None):
with patch.object(mod, "_get_duty_message_text_sync", return_value="Duty"): with patch.object(
mod, "_get_duty_message_text_sync", return_value="Duty"
):
with patch.object(mod, "_sync_save_pin") as mock_save: with patch.object(mod, "_sync_save_pin") as mock_save:
with patch.object( with patch.object(
mod, "_get_next_shift_end_sync", return_value=None mod, "_get_next_shift_end_sync", return_value=None
): ):
with patch.object(mod, "_schedule_next_update", AsyncMock()): with patch.object(
mod, "_schedule_next_update", AsyncMock()
):
with patch( with patch(
"duty_teller.handlers.group_duty_pin.t" "duty_teller.handlers.group_duty_pin.t"
) as mock_t: ) as mock_t:
@@ -667,7 +687,9 @@ async def test_refresh_pin_cmd_untrusted_group_rejects():
with patch("duty_teller.handlers.group_duty_pin.get_lang", return_value="en"): with patch("duty_teller.handlers.group_duty_pin.get_lang", return_value="en"):
with patch.object(mod, "_sync_is_trusted", return_value=False): with patch.object(mod, "_sync_is_trusted", return_value=False):
with patch.object(mod, "_refresh_pin_for_chat", AsyncMock()) as mock_refresh: with patch.object(
mod, "_refresh_pin_for_chat", AsyncMock()
) as mock_refresh:
with patch("duty_teller.handlers.group_duty_pin.t") as mock_t: with patch("duty_teller.handlers.group_duty_pin.t") as mock_t:
mock_t.return_value = "Not authorized" mock_t.return_value = "Not authorized"
await mod.refresh_pin_cmd(update, context) await mod.refresh_pin_cmd(update, context)
@@ -725,9 +747,13 @@ async def test_my_chat_member_handler_bot_added_sends_pins_and_schedules():
with patch("duty_teller.handlers.group_duty_pin.get_lang", return_value="en"): with patch("duty_teller.handlers.group_duty_pin.get_lang", return_value="en"):
with patch.object(mod, "_sync_is_trusted", return_value=True): with patch.object(mod, "_sync_is_trusted", return_value=True):
with patch.object(mod, "_get_duty_message_text_sync", return_value="Duty text"): with patch.object(
mod, "_get_duty_message_text_sync", return_value="Duty text"
):
with patch.object(mod, "_sync_save_pin"): with patch.object(mod, "_sync_save_pin"):
with patch.object(mod, "_get_next_shift_end_sync", return_value=None): with patch.object(
mod, "_get_next_shift_end_sync", return_value=None
):
with patch.object(mod, "_schedule_next_update", AsyncMock()): with patch.object(mod, "_schedule_next_update", AsyncMock()):
await mod.my_chat_member_handler(update, context) await mod.my_chat_member_handler(update, context)
context.bot.send_message.assert_called_once_with( context.bot.send_message.assert_called_once_with(
@@ -782,9 +808,13 @@ async def test_my_chat_member_handler_trusted_group_sends_duty():
with patch("duty_teller.handlers.group_duty_pin.get_lang", return_value="en"): with patch("duty_teller.handlers.group_duty_pin.get_lang", return_value="en"):
with patch.object(mod, "_sync_is_trusted", return_value=True): with patch.object(mod, "_sync_is_trusted", return_value=True):
with patch.object(mod, "_get_duty_message_text_sync", return_value="Duty text"): with patch.object(
mod, "_get_duty_message_text_sync", return_value="Duty text"
):
with patch.object(mod, "_sync_save_pin"): with patch.object(mod, "_sync_save_pin"):
with patch.object(mod, "_get_next_shift_end_sync", return_value=None): with patch.object(
mod, "_get_next_shift_end_sync", return_value=None
):
with patch.object(mod, "_schedule_next_update", AsyncMock()): with patch.object(mod, "_schedule_next_update", AsyncMock()):
await mod.my_chat_member_handler(update, context) await mod.my_chat_member_handler(update, context)
context.bot.send_message.assert_called_once_with( context.bot.send_message.assert_called_once_with(
@@ -818,9 +848,13 @@ async def test_my_chat_member_handler_pin_raises_sends_could_not_pin():
with patch.object(mod, "_sync_is_trusted", return_value=True): with patch.object(mod, "_sync_is_trusted", return_value=True):
with patch.object(mod, "_get_duty_message_text_sync", return_value="Duty"): with patch.object(mod, "_get_duty_message_text_sync", return_value="Duty"):
with patch.object(mod, "_sync_save_pin"): with patch.object(mod, "_sync_save_pin"):
with patch.object(mod, "_get_next_shift_end_sync", return_value=None): with patch.object(
mod, "_get_next_shift_end_sync", return_value=None
):
with patch.object(mod, "_schedule_next_update", AsyncMock()): with patch.object(mod, "_schedule_next_update", AsyncMock()):
with patch("duty_teller.handlers.group_duty_pin.t") as mock_t: with patch(
"duty_teller.handlers.group_duty_pin.t"
) as mock_t:
mock_t.return_value = "Make me admin to pin" mock_t.return_value = "Make me admin to pin"
await mod.my_chat_member_handler(update, context) await mod.my_chat_member_handler(update, context)
assert context.bot.send_message.call_count >= 2 assert context.bot.send_message.call_count >= 2
@@ -896,7 +930,9 @@ async def test_refresh_pin_for_chat_untrusted_removes_pin():
result = await mod._refresh_pin_for_chat(context, 100) result = await mod._refresh_pin_for_chat(context, 100)
assert result == "untrusted" assert result == "untrusted"
mock_delete_pin.assert_called_once_with(100) mock_delete_pin.assert_called_once_with(100)
context.application.job_queue.get_jobs_by_name.assert_called_once_with("duty_pin_100") context.application.job_queue.get_jobs_by_name.assert_called_once_with(
"duty_pin_100"
)
mock_job.schedule_removal.assert_called_once() mock_job.schedule_removal.assert_called_once()
context.bot.unpin_chat_message.assert_called_once_with(chat_id=100) context.bot.unpin_chat_message.assert_called_once_with(chat_id=100)
context.bot.delete_message.assert_called_once_with(chat_id=100, message_id=11) context.bot.delete_message.assert_called_once_with(chat_id=100, message_id=11)
@@ -953,11 +989,19 @@ async def test_trust_group_cmd_admin_adds_group():
with patch.object(mod, "is_admin_async", AsyncMock(return_value=True)): with patch.object(mod, "is_admin_async", AsyncMock(return_value=True)):
with patch.object(mod, "_sync_trust_group", return_value=False): with patch.object(mod, "_sync_trust_group", return_value=False):
with patch.object(mod, "_sync_get_message_id", return_value=None): with patch.object(mod, "_sync_get_message_id", return_value=None):
with patch.object(mod, "_get_duty_message_text_sync", return_value="Duty text"): with patch.object(
mod, "_get_duty_message_text_sync", return_value="Duty text"
):
with patch.object(mod, "_sync_save_pin") as mock_save: with patch.object(mod, "_sync_save_pin") as mock_save:
with patch.object(mod, "_get_next_shift_end_sync", return_value=None): with patch.object(
with patch.object(mod, "_schedule_next_update", AsyncMock()): mod, "_get_next_shift_end_sync", return_value=None
with patch("duty_teller.handlers.group_duty_pin.t") as mock_t: ):
with patch.object(
mod, "_schedule_next_update", AsyncMock()
):
with patch(
"duty_teller.handlers.group_duty_pin.t"
) as mock_t:
mock_t.return_value = "Added" mock_t.return_value = "Added"
with patch.object( with patch.object(
config, "DUTY_PIN_NOTIFY", False config, "DUTY_PIN_NOTIFY", False
@@ -1028,7 +1072,9 @@ async def test_untrust_group_cmd_removes_group():
await mod.untrust_group_cmd(update, context) await mod.untrust_group_cmd(update, context)
update.message.reply_text.assert_called_once_with("Removed") update.message.reply_text.assert_called_once_with("Removed")
mock_t.assert_called_with("en", "untrust_group.removed") mock_t.assert_called_with("en", "untrust_group.removed")
context.application.job_queue.get_jobs_by_name.assert_called_once_with("duty_pin_100") context.application.job_queue.get_jobs_by_name.assert_called_once_with(
"duty_pin_100"
)
mock_job.schedule_removal.assert_called_once() mock_job.schedule_removal.assert_called_once()
context.bot.unpin_chat_message.assert_called_once_with(chat_id=100) context.bot.unpin_chat_message.assert_called_once_with(chat_id=100)
context.bot.delete_message.assert_called_once_with(chat_id=100, message_id=99) context.bot.delete_message.assert_called_once_with(chat_id=100, message_id=99)