Skip to content

Commit f7546cc

Browse files
authored
feat: allow to pass SlotSearchType to find-appointment command (#14)
* feat: allow to pass slotSearchType to find-appointment command fix cs fix cs fix cs * update README.md
1 parent f875591 commit f7546cc

File tree

3 files changed

+52
-4
lines changed

3 files changed

+52
-4
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,14 @@ All commands are run from the web terminal.
130130
python medichaser.py find-appointment -r 204 -s 112 -l 60
131131
```
132132

133+
- **Search diagnostic procedures** (set slot search type):
134+
135+
```bash
136+
python medichaser.py find-appointment -r 204 -s 132 -S DiagnosticProcedure
137+
```
138+
139+
Use `-S`/`--slot-search-type` to override the default slot search type.
140+
133141
- **Continuous monitoring and notifications**:
134142

135143
```bash

medichaser.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@
7777
MEDICOVER_MAIN_URL = "https://online24.medicover.pl"
7878
MEDICOVER_API_URL = "https://api-gateway-online24.medicover.pl"
7979

80+
DEFAULT_SLOT_SEARCH_TYPE: int = 0
81+
8082
token_lock = FileLock(TOKEN_LOCK_PATH, timeout=60)
8183
login_lock = FileLock(LOGIN_LOCK_PATH, timeout=60)
8284

@@ -801,6 +803,7 @@ def find_appointments(
801803
end_date: datetime.date | None,
802804
language: int | None,
803805
doctor: int | None = None,
806+
slot_search_type: int | str = DEFAULT_SLOT_SEARCH_TYPE,
804807
) -> list[dict[str, Any]]:
805808
appointment_url = (
806809
f"{MEDICOVER_API_URL}/appointments/api/search-appointments/slots"
@@ -812,7 +815,7 @@ def find_appointments(
812815
"Page": 1,
813816
"PageSize": 5000,
814817
"StartTime": start_date.isoformat(),
815-
"SlotSearchType": 0,
818+
"SlotSearchType": slot_search_type,
816819
"VisitType": "Center",
817820
}
818821

@@ -837,13 +840,16 @@ def find_appointments(
837840
return items
838841

839842
def find_filters(
840-
self, region: int | None = None, specialty: list[int] | None = None
843+
self,
844+
region: int | None = None,
845+
specialty: list[int] | None = None,
846+
slot_search_type: int | str = DEFAULT_SLOT_SEARCH_TYPE,
841847
) -> dict[str, Any]:
842848
filters_url = (
843849
f"{MEDICOVER_API_URL}/appointments/api/search-appointments/filters"
844850
)
845851

846-
params: dict[str, Any] = {"SlotSearchType": 0}
852+
params: dict[str, Any] = {"SlotSearchType": slot_search_type}
847853
if region:
848854
params["RegionIds"] = region
849855
if specialty:
@@ -950,6 +956,13 @@ def json_date_serializer(obj: Any) -> str:
950956
raise TypeError(f"Object of type {type(obj).__name__} is not JSON serializable")
951957

952958

959+
def parse_slot_search_type(value: str) -> int | str:
960+
try:
961+
return int(value)
962+
except ValueError:
963+
return value
964+
965+
953966
class NextRun:
954967
def __init__(self, interval_minutes: int | None = 60) -> None:
955968
self.next_run = datetime.datetime.now(tz=datetime.UTC)
@@ -1033,6 +1046,13 @@ def main() -> None:
10331046
default=None,
10341047
help="Repeat interval in minutes",
10351048
)
1049+
find_appointment.add_argument(
1050+
"-S",
1051+
"--slot-search-type",
1052+
default=DEFAULT_SLOT_SEARCH_TYPE,
1053+
type=parse_slot_search_type,
1054+
help='Slot search type (e.g. "0", "DiagnosticProcedure"). Default: 0',
1055+
)
10361056

10371057
list_filters = subparsers.add_parser("list-filters", help="List filters")
10381058
list_filters_subparsers = list_filters.add_subparsers(
@@ -1120,6 +1140,7 @@ def main() -> None:
11201140
args.enddate,
11211141
args.language,
11221142
args.doctor,
1143+
args.slot_search_type,
11231144
)
11241145
except ExpiredToken as e:
11251146
log.warning("Expired token error: %s", e)

tests.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from notifiers.exceptions import BadArguments
2727

2828
from medichaser import (
29+
DEFAULT_SLOT_SEARCH_TYPE,
2930
AppointmentFinder,
3031
Authenticator,
3132
InvalidGrantError,
@@ -460,6 +461,10 @@ def test_find_appointments_basic(self, monkeypatch: pytest.MonkeyPatch) -> None:
460461

461462
assert result == [{"id": 1}, {"id": 2}]
462463
mock_http_get.assert_called_once()
464+
call_args = mock_http_get.call_args
465+
assert call_args is not None
466+
params: dict[str, Any] = call_args.args[1]
467+
assert params["SlotSearchType"] == DEFAULT_SLOT_SEARCH_TYPE
463468

464469
def test_find_appointments_with_filters(
465470
self, monkeypatch: pytest.MonkeyPatch
@@ -486,6 +491,7 @@ def test_find_appointments_with_filters(
486491
call_args = mock_http_get.call_args
487492
assert call_args is not None
488493
params: dict[str, Any] = call_args.args[1]
494+
assert params["SlotSearchType"] == DEFAULT_SLOT_SEARCH_TYPE
489495
assert "DoctorLanguageIds" in params
490496
assert "DoctorIds" in params
491497

@@ -534,6 +540,10 @@ def test_find_filters(self, monkeypatch: pytest.MonkeyPatch) -> None:
534540

535541
assert result == {"regions": [{"id": 1}]}
536542
mock_http_get.assert_called_once()
543+
call_args = mock_http_get.call_args
544+
assert call_args is not None
545+
params: dict[str, Any] = call_args.args[1]
546+
assert params["SlotSearchType"] == DEFAULT_SLOT_SEARCH_TYPE
537547

538548

539549
class TestNotifier:
@@ -1099,6 +1109,7 @@ def test_main_find_appointment_single_run(monkeypatch: pytest.MonkeyPatch) -> No
10991109
interval=None,
11001110
notification="pushbullet",
11011111
title="Test",
1112+
slot_search_type="DiagnosticProcedure",
11021113
)
11031114

11041115
mock_parser = MagicMock()
@@ -1133,7 +1144,14 @@ def test_main_find_appointment_single_run(monkeypatch: pytest.MonkeyPatch) -> No
11331144
mock_auth_instance.login.assert_called_once()
11341145
mock_auth_instance.refresh_token.assert_called_once()
11351146
mock_finder_instance.find_appointments.assert_called_once_with(
1136-
1, [2], 3, datetime.date(2025, 1, 1), datetime.date(2025, 1, 31), 6, 4
1147+
1,
1148+
[2],
1149+
3,
1150+
datetime.date(2025, 1, 1),
1151+
datetime.date(2025, 1, 31),
1152+
6,
1153+
4,
1154+
"DiagnosticProcedure",
11371155
)
11381156
mock_display.assert_called_once_with([{"id": 1, "name": "Appointment"}])
11391157
mock_notifier.assert_called_once_with(
@@ -1248,6 +1266,7 @@ def test_main_find_appointment_interval_run(monkeypatch: pytest.MonkeyPatch) ->
12481266
interval=10,
12491267
notification="pushover",
12501268
title="Interval Test",
1269+
slot_search_type=DEFAULT_SLOT_SEARCH_TYPE,
12511270
)
12521271

12531272
mock_parser = MagicMock()

0 commit comments

Comments
 (0)