Skip to content

Commit

Permalink
✨ add link to marudor.de details interface (#6)
Browse files Browse the repository at this point in the history
* ✨ 🚧 add link to marudor.de details interface
* 👽 integrate new marudor.de API introduced by marudor/bahn.expert#529 / docs at: https://docs.marudor.de/#operation/DetailsRedirect
  • Loading branch information
jeyemwey committed Oct 25, 2021
1 parent f20c641 commit 95be029
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 15 deletions.
13 changes: 12 additions & 1 deletion client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ function App() {
const [departureInvalid, setDepartureInvalid] = useState(false);
const [pending, setPending] = useState(false);
const [error, setError] = useState<string | undefined>("");
const [includeMarudorLink, setIncludeMarudorLink] = useState(false);
const [includeTrwlLink, setIncludeTrwlLink] = useState(false);

useEffect(() => {
Expand Down Expand Up @@ -86,7 +87,8 @@ function App() {
<Button href={BACKEND_URL + "cal?" + new URLSearchParams({
refreshToken,
departureTZOffset: departure.getTimezoneOffset().toString(),
includeTrwlLink: includeTrwlLink ? "true" : "false"
includeTrwlLink: includeTrwlLink ? "true" : "false",
includeMarudorLink: includeMarudorLink ? "true" : "false"
})}>Kalender</Button>;

return (
Expand Down Expand Up @@ -143,6 +145,15 @@ function App() {
isInvalid={departureInvalid} />
</Form.Group>

<Form.Group className="mb-3" controlId="formDestination">
<Form.Check
type={"checkbox"}
id={"includeMarudorLink"}
label={"Marudor-Link einfügen"}
checked={includeMarudorLink}
onChange={e => setIncludeMarudorLink(e.target.checked)}
/>
</Form.Group>
<Form.Group className="mb-3" controlId="formDestination">
<Form.Check
type={"checkbox"}
Expand Down
3 changes: 2 additions & 1 deletion src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,10 @@ app.get("/cal", async (req, res) => {
const departureTZOffset = reqDepartureTZOffset - new Date().getTimezoneOffset(); // also remove the server tz offset

const includeTrwlLink = (req.query.includeTrwlLink as string) === "true"
const includeMarudorLink = (req.query.includeMarudorLink as string) === "true"

const journey = await client.refreshJourney(token, {stopovers: true});
const calendar = toCalendar({journey, departureTZOffset, includeTrwlLink});
const calendar = toCalendar({journey, departureTZOffset, includeTrwlLink, includeMarudorLink});

return calendar.serve(res);
});
Expand Down
2 changes: 1 addition & 1 deletion src/hafas-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const dbProfile = require('hafas-client/p/db')

type Id = never
export type Mode = 'train' | 'bus' | 'watercraft' | 'taxi' | 'gondola' | 'aircraft' | 'car' | 'bicycle' | 'walking';
type Product = 'nationalExpress'| 'national'| 'regionalExp'| 'regional'| 'suburban'| 'bus'| 'ferry'| 'subway'| 'tram'| 'taxi';
export type Product = 'nationalExpress'| 'national'| 'regionalExp'| 'regional'| 'suburban'| 'bus'| 'ferry'| 'subway'| 'tram'| 'taxi';

type Price = { amount: number, currency: 'EUR' | 'GBP' | 'CHF' /* ISO 4217 code, required */ } | { amount: null, hint?: string }
export type Stopover = ArrivingDepartingWithPossibleDelay & {
Expand Down
14 changes: 7 additions & 7 deletions src/ical.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe("leg to calendar event", () => {
it("works for simple leg", () => {
const leg = { ...baseLeg } as Leg;

const event = legToEvent({leg, departureTZOffset: TIMEZONE_OFFSET, includeTrwlLink: false});
const event = legToEvent({leg, departureTZOffset: TIMEZONE_OFFSET, includeTrwlLink: false, includeMarudorLink: false});
assert.deepStrictEqual(event, baseEvent);
});

Expand All @@ -52,7 +52,7 @@ describe("leg to calendar event", () => {
summary: "🚆 RE 1: Beginn (Gl. 104 D-G) -> Ende (Gl. 9 3/4)"
}

const event = legToEvent({leg, departureTZOffset: TIMEZONE_OFFSET, includeTrwlLink: false});
const event = legToEvent({leg, departureTZOffset: TIMEZONE_OFFSET, includeTrwlLink: false, includeMarudorLink: false});
assert.deepStrictEqual(event, expected);
});

Expand All @@ -69,7 +69,7 @@ describe("leg to calendar event", () => {
end: new Date("2021-10-16T22:40:00Z")
}

const event = legToEvent({leg, departureTZOffset: TIMEZONE_OFFSET, includeTrwlLink: false});
const event = legToEvent({leg, departureTZOffset: TIMEZONE_OFFSET, includeTrwlLink: false, includeMarudorLink: false});
assert.deepStrictEqual(event, expected);
});

Expand Down Expand Up @@ -97,7 +97,7 @@ describe("leg to calendar event", () => {
description: baseEvent.description + "\nZwischenstop: Stopover1 (an: 22:10, ab: 22:11)"
} as Event;

const event = legToEvent({leg, departureTZOffset: TIMEZONE_OFFSET, includeTrwlLink: false});
const event = legToEvent({leg, departureTZOffset: TIMEZONE_OFFSET, includeTrwlLink: false, includeMarudorLink: false});
assert.deepStrictEqual(event, expected);
});

Expand Down Expand Up @@ -134,7 +134,7 @@ describe("leg to calendar event", () => {
description: baseEvent.description + "\nZwischenstops: Stopover1 (an: 22:10, ab: 22:11), Stopover2 (an: 22:20, ab: 22:21)"
} as Event;

const event = legToEvent({leg, departureTZOffset: TIMEZONE_OFFSET, includeTrwlLink: false});
const event = legToEvent({leg, departureTZOffset: TIMEZONE_OFFSET, includeTrwlLink: false, includeMarudorLink: false});
assert.deepStrictEqual(event, expected);
});

Expand All @@ -161,7 +161,7 @@ describe("leg to calendar event", () => {
description: baseEvent.description + "\nZwischenstop: Stopover1 (an: 22:10)"
} as Event;

const event = legToEvent({leg, departureTZOffset: TIMEZONE_OFFSET, includeTrwlLink: false});
const event = legToEvent({leg, departureTZOffset: TIMEZONE_OFFSET, includeTrwlLink: false, includeMarudorLink: false});
assert.deepStrictEqual(event, expected);
});

Expand All @@ -188,7 +188,7 @@ describe("leg to calendar event", () => {
description: baseEvent.description + "\nZwischenstop: Stopover1 (ab: 22:10)"
} as Event;

const event = legToEvent({leg, departureTZOffset: TIMEZONE_OFFSET, includeTrwlLink: false});
const event = legToEvent({leg, departureTZOffset: TIMEZONE_OFFSET, includeTrwlLink: false, includeMarudorLink: false});
assert.deepStrictEqual(event, expected);
});
});
Expand Down
21 changes: 16 additions & 5 deletions src/ical.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Journey, Leg } from "./hafas-client"
import { Journey, Leg, Product } from "./hafas-client"
import { dateWithDelay, toShortDate } from "./date-utils"
import ical, { ICalCalendar } from 'ical-generator';
import { getVtimezoneComponent } from "@touch4it/ical-timezones";
Expand Down Expand Up @@ -76,7 +76,18 @@ const getTrwlLink = (leg: Leg): string => {
return `\n\nTräwelling-Check In: ` + base_url + new URLSearchParams(args).toString()
}

export const legToEvent = ({ leg, departureTZOffset, includeTrwlLink }: { leg: Leg, departureTZOffset: number, includeTrwlLink: boolean }): Event | null => {
const getMarudorLink = (leg: Leg): string => {
// marudor.de only offers details for a subset of transport services
if ((["national", "nationalExpress", "regional", "regionalExp", "suburban"] as Product[]).includes(leg.line.product) === false) {
return "";
}

const base_url = "https://marudor.de/api/hafas/v1/detailsRedirect/";

return `\n\nMarudor-Link: ` + base_url + encodeURIComponent(leg.tripId);
}

export const legToEvent = ({ leg, departureTZOffset, includeTrwlLink, includeMarudorLink }: { leg: Leg, departureTZOffset: number, includeTrwlLink: boolean, includeMarudorLink: boolean }): Event | null => {
if (leg.mode === "walking" || leg.mode === "bicycle" || leg.walking) {
return null
}
Expand All @@ -95,17 +106,17 @@ export const legToEvent = ({ leg, departureTZOffset, includeTrwlLink }: { leg: L

return {
summary: `${getEmoji(leg)} ${leg.line?.name}: ${leg.origin.name}${departurePlatform} -> ${leg.destination.name}${arrivalPlatform}`,
description: `${leg.line.operator?.name ? `Betreiber: ${leg.line.operator.name}` : ""}${stopoverList}${includeTrwlLink ? `${getTrwlLink(leg)}` : ""}`,
description: `${leg.line.operator?.name ? `Betreiber: ${leg.line.operator.name}` : ""}${stopoverList}${includeTrwlLink ? `${getTrwlLink(leg)}` : ""}${includeMarudorLink ? `${getMarudorLink(leg)}` : ""}`,
start: departure,
end: arrival,
location: leg.origin.name
}
}

export const toCalendar = ({ journey, departureTZOffset, includeTrwlLink }: { journey: Journey, departureTZOffset: number, includeTrwlLink: boolean }): ICalCalendar => {
export const toCalendar = ({ journey, departureTZOffset, includeTrwlLink, includeMarudorLink }: { journey: Journey, departureTZOffset: number, includeTrwlLink: boolean, includeMarudorLink: boolean }): ICalCalendar => {
const origin = journey.legs[0].origin.name
const destination = journey.legs[journey.legs.length - 1].destination.name
const events = journey.legs.map(leg => legToEvent({ leg, departureTZOffset, includeTrwlLink })).filter(e => e !== null)
const events = journey.legs.map(leg => legToEvent({ leg, departureTZOffset, includeTrwlLink, includeMarudorLink })).filter(e => e !== null)

const calendar = ical({
name: `Reise von ${origin} nach ${destination}`,
Expand Down

0 comments on commit 95be029

Please sign in to comment.