diff --git a/pyhafas/client.py b/pyhafas/client.py index f91c4be..af467aa 100644 --- a/pyhafas/client.py +++ b/pyhafas/client.py @@ -158,6 +158,46 @@ def journeys( return self.profile.parse_journeys_request(res) + def journeys_from_leg( + self, + origin: Leg, + destination: Union[Station, str], + via: List[Union[Station, str]] = [], + min_change_time: int = 0, + max_changes: int = -1, + products: Dict[str, bool] = {}, + ) -> List[Journey]: + """ + Returns possible journeys from a leg to a destination + + Possible journeys between two destinations are calculated by HaFAS and returned. It's also possible to add multiple via stations. + + :param origin: FPTF `Leg` object from where to search + :param destination: FPTF `Station` object or ID of destination/ending station + :param via: (optional) List of via stations. The route is calculated via all of these stations in the order of the list. The stations have to be a FPTF `Station` object or the ID of the station. The default is no via stations. + :param min_change_time: (optional) Minimum transfer/change time at each station. Default is the default that HaFAS specifies internal. + :param max_changes: (optional) Maximum number of changes. Default is unlimited. + :param products: (optional) Dict of product name(s) and whether it should be enabled or not. Modifies the default products specified in the profile. + :return: List of FPTF `Journey` objects + """ + if not isinstance(destination, Station): + destination = Station(destination) + for via_station in via: + if not isinstance(via_station, Station): + via[via.index(via_station)] = Station(via_station) + + body = self.profile.format_search_from_leg_request( + origin, + destination, + via, + min_change_time, + max_changes, + products + ) + res = self.profile.request(body) + + return self.profile.parse_journeys_request(res) + def journey(self, journey: Union[Journey, str]) -> Journey: """ Returns information about a specific journey by its ID diff --git a/pyhafas/profile/base/requests/journeys.py b/pyhafas/profile/base/requests/journeys.py index af98176..5607828 100644 --- a/pyhafas/profile/base/requests/journeys.py +++ b/pyhafas/profile/base/requests/journeys.py @@ -4,7 +4,7 @@ from pyhafas.profile import ProfileInterface from pyhafas.profile.interfaces.requests.journeys import \ JourneysRequestInterface -from pyhafas.types.fptf import Journey, Station +from pyhafas.types.fptf import Journey, Station, Leg from pyhafas.types.hafas_response import HafasResponse @@ -82,6 +82,55 @@ def format_journeys_request( 'meth': 'TripSearch' } + def format_search_from_leg_request( + self: ProfileInterface, + origin: Leg, + destination: Station, + via: List[Station], + min_change_time: int, + max_changes: int, + products: Dict[str, bool], + ) -> dict: + """ + Creates the HaFAS request body for a journeys request + + :param origin: Origin leg + :param destination: Destionation station + :param via: Via stations, maybe empty list) + :param min_change_time: Minimum transfer/change time at each station + :param max_changes: Maximum number of changes + :param products: Allowed products (a product is a mean of transport like ICE,IC) + :return: Request body for HaFAS + """ + return { + 'req': { + 'arrLocL': [{ + 'lid': 'A=1@L={}@'.format(destination.id) + }], + 'viaLocL': [{ + 'loc': { + 'lid': 'A=1@L={}@'.format(via_station.id) + } + } for via_station in via], + 'locData': { + 'loc': { + 'lid': 'A=1@L={}@'.format(origin.origin.id) + }, + 'type': 'DEP', + 'date': origin.departure.strftime("%Y%m%d"), + 'time': origin.departure.strftime("%H%M%S") + }, + 'jnyFltrL': [ + self.format_products_filter(products) + ], + 'minChgTime': min_change_time, + 'maxChg': max_changes, + 'jid': origin.id, + 'sotMode': 'JI' + }, + 'meth': 'SearchOnTrip' + } + def parse_journeys_request( self: ProfileInterface, data: HafasResponse) -> List[Journey]: diff --git a/pyhafas/profile/db/__init__.py b/pyhafas/profile/db/__init__.py index a26047a..4bbb94f 100644 --- a/pyhafas/profile/db/__init__.py +++ b/pyhafas/profile/db/__init__.py @@ -19,12 +19,12 @@ class DBProfile(BaseProfile): requestBody = { 'client': { 'id': 'DB', - 'v': '16040000', + 'v': '20100000', 'type': 'IPH', 'name': 'DB Navigator' }, - 'ext': 'DB.R19.04.a', - 'ver': '1.16', + 'ext': 'DB.R21.12.a', + 'ver': '1.15', 'auth': { 'type': 'AID', 'aid': 'n91dB8Z77MLdoR0K' diff --git a/pyhafas/profile/interfaces/requests/journeys.py b/pyhafas/profile/interfaces/requests/journeys.py index a20196f..0663ccb 100644 --- a/pyhafas/profile/interfaces/requests/journeys.py +++ b/pyhafas/profile/interfaces/requests/journeys.py @@ -2,7 +2,7 @@ import datetime from typing import Dict, List -from pyhafas.types.fptf import Journey, Station +from pyhafas.types.fptf import Journey, Station, Leg from pyhafas.types.hafas_response import HafasResponse @@ -34,6 +34,29 @@ def format_journeys_request( """ pass + @abc.abstractmethod + def format_search_from_leg_request( + self, + origin: Leg, + destination: Station, + via: List[Station], + min_change_time: int, + max_changes: int, + products: Dict[str, bool], + ) -> dict: + """ + Creates the HaFAS request body for a search from leg request + + :param origin: Origin leg + :param destination: Destionation station + :param via: Via stations, maybe empty list) + :param min_change_time: Minimum transfer/change time at each station + :param max_changes: Maximum number of changes + :param products: Allowed products (a product is a mean of transport like ICE,IC) + :return: Request body for HaFAS + """ + pass + @abc.abstractmethod def parse_journeys_request(self, data: HafasResponse) -> List[Journey]: """