mitsupi 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +95 -0
  3. package/TODO.md +11 -0
  4. package/commands/handoff.md +100 -0
  5. package/commands/make-release.md +75 -0
  6. package/commands/pickup.md +30 -0
  7. package/commands/update-changelog.md +78 -0
  8. package/package.json +22 -0
  9. package/pi-extensions/answer.ts +527 -0
  10. package/pi-extensions/codex-tuning.ts +632 -0
  11. package/pi-extensions/commit.ts +248 -0
  12. package/pi-extensions/cwd-history.ts +237 -0
  13. package/pi-extensions/issues.ts +548 -0
  14. package/pi-extensions/loop.ts +446 -0
  15. package/pi-extensions/qna.ts +167 -0
  16. package/pi-extensions/reveal.ts +689 -0
  17. package/pi-extensions/review.ts +807 -0
  18. package/pi-themes/armin.json +81 -0
  19. package/pi-themes/nightowl.json +82 -0
  20. package/skills/anachb/SKILL.md +183 -0
  21. package/skills/anachb/departures.sh +79 -0
  22. package/skills/anachb/disruptions.sh +53 -0
  23. package/skills/anachb/route.sh +87 -0
  24. package/skills/anachb/search.sh +43 -0
  25. package/skills/ghidra/SKILL.md +254 -0
  26. package/skills/ghidra/scripts/find-ghidra.sh +54 -0
  27. package/skills/ghidra/scripts/ghidra-analyze.sh +239 -0
  28. package/skills/ghidra/scripts/ghidra_scripts/ExportAll.java +278 -0
  29. package/skills/ghidra/scripts/ghidra_scripts/ExportCalls.java +148 -0
  30. package/skills/ghidra/scripts/ghidra_scripts/ExportDecompiled.java +84 -0
  31. package/skills/ghidra/scripts/ghidra_scripts/ExportFunctions.java +114 -0
  32. package/skills/ghidra/scripts/ghidra_scripts/ExportStrings.java +123 -0
  33. package/skills/ghidra/scripts/ghidra_scripts/ExportSymbols.java +135 -0
  34. package/skills/github/SKILL.md +47 -0
  35. package/skills/improve-skill/SKILL.md +155 -0
  36. package/skills/improve-skill/scripts/extract-session.js +349 -0
  37. package/skills/oebb-scotty/SKILL.md +429 -0
  38. package/skills/oebb-scotty/arrivals.sh +83 -0
  39. package/skills/oebb-scotty/departures.sh +83 -0
  40. package/skills/oebb-scotty/disruptions.sh +33 -0
  41. package/skills/oebb-scotty/search-station.sh +36 -0
  42. package/skills/oebb-scotty/trip.sh +119 -0
  43. package/skills/openscad/SKILL.md +232 -0
  44. package/skills/openscad/examples/parametric_box.scad +92 -0
  45. package/skills/openscad/examples/phone_stand.scad +95 -0
  46. package/skills/openscad/tools/common.sh +50 -0
  47. package/skills/openscad/tools/export-stl.sh +56 -0
  48. package/skills/openscad/tools/extract-params.sh +147 -0
  49. package/skills/openscad/tools/multi-preview.sh +68 -0
  50. package/skills/openscad/tools/preview.sh +74 -0
  51. package/skills/openscad/tools/render-with-params.sh +91 -0
  52. package/skills/openscad/tools/validate.sh +46 -0
  53. package/skills/pi-share/SKILL.md +105 -0
  54. package/skills/pi-share/fetch-session.mjs +322 -0
  55. package/skills/sentry/SKILL.md +239 -0
  56. package/skills/sentry/lib/auth.js +99 -0
  57. package/skills/sentry/scripts/fetch-event.js +329 -0
  58. package/skills/sentry/scripts/fetch-issue.js +356 -0
  59. package/skills/sentry/scripts/list-issues.js +239 -0
  60. package/skills/sentry/scripts/search-events.js +291 -0
  61. package/skills/sentry/scripts/search-logs.js +240 -0
  62. package/skills/tmux/SKILL.md +105 -0
  63. package/skills/tmux/scripts/find-sessions.sh +112 -0
  64. package/skills/tmux/scripts/wait-for-text.sh +83 -0
  65. package/skills/web-browser/SKILL.md +91 -0
  66. package/skills/web-browser/scripts/cdp.js +210 -0
  67. package/skills/web-browser/scripts/dismiss-cookies.js +373 -0
  68. package/skills/web-browser/scripts/eval.js +68 -0
  69. package/skills/web-browser/scripts/logs-tail.js +69 -0
  70. package/skills/web-browser/scripts/nav.js +65 -0
  71. package/skills/web-browser/scripts/net-summary.js +94 -0
  72. package/skills/web-browser/scripts/package-lock.json +33 -0
  73. package/skills/web-browser/scripts/package.json +6 -0
  74. package/skills/web-browser/scripts/pick.js +165 -0
  75. package/skills/web-browser/scripts/screenshot.js +52 -0
  76. package/skills/web-browser/scripts/start.js +80 -0
  77. package/skills/web-browser/scripts/watch.js +266 -0
@@ -0,0 +1,81 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/badlogic/pi-mono/main/packages/coding-agent/theme-schema.json",
3
+ "name": "armin",
4
+ "vars": {
5
+ "cyan": "#52b8c9",
6
+ "blue": "#5a8ad0",
7
+ "green": "#68c4b0",
8
+ "red": "#c95a4a",
9
+ "yellow": "#d9c878",
10
+ "magenta": "#d84a88",
11
+ "gray": "#7a8899",
12
+ "dimGray": "#5a6a7a",
13
+ "darkGray": "#3a4a5a",
14
+ "accent": "#64b8c9",
15
+ "foreground": "#a8b0c8",
16
+ "background": "#111e2a",
17
+ "userMsgBg": "#1a2836",
18
+ "toolPendingBg": "#162230",
19
+ "toolSuccessBg": "#16282a",
20
+ "toolErrorBg": "#2a1e22"
21
+ },
22
+ "colors": {
23
+ "accent": "accent",
24
+ "border": "blue",
25
+ "borderAccent": "cyan",
26
+ "borderMuted": "darkGray",
27
+ "success": "green",
28
+ "error": "red",
29
+ "warning": "yellow",
30
+ "muted": "gray",
31
+ "dim": "dimGray",
32
+ "text": "",
33
+ "thinkingText": "gray",
34
+
35
+ "selectedBg": "darkGray",
36
+ "userMessageBg": "userMsgBg",
37
+ "userMessageText": "",
38
+ "toolPendingBg": "toolPendingBg",
39
+ "toolSuccessBg": "toolSuccessBg",
40
+ "toolErrorBg": "toolErrorBg",
41
+ "toolTitle": "",
42
+ "toolOutput": "gray",
43
+ "customMessageBg": "userMsgBg",
44
+ "customMessageText": "",
45
+ "customMessageLabel": "accent",
46
+
47
+ "mdHeading": "yellow",
48
+ "mdLink": "blue",
49
+ "mdLinkUrl": "dimGray",
50
+ "mdCode": "accent",
51
+ "mdCodeBlock": "green",
52
+ "mdCodeBlockBorder": "gray",
53
+ "mdQuote": "gray",
54
+ "mdQuoteBorder": "gray",
55
+ "mdHr": "gray",
56
+ "mdListBullet": "accent",
57
+
58
+ "toolDiffAdded": "green",
59
+ "toolDiffRemoved": "red",
60
+ "toolDiffContext": "gray",
61
+
62
+ "syntaxComment": "#5a7a6a",
63
+ "syntaxKeyword": "blue",
64
+ "syntaxFunction": "yellow",
65
+ "syntaxVariable": "cyan",
66
+ "syntaxString": "green",
67
+ "syntaxNumber": "magenta",
68
+ "syntaxType": "cyan",
69
+ "syntaxOperator": "foreground",
70
+ "syntaxPunctuation": "foreground",
71
+
72
+ "thinkingOff": "darkGray",
73
+ "thinkingMinimal": "#4a5a6a",
74
+ "thinkingLow": "#4a6a8a",
75
+ "thinkingMedium": "#5a8aaa",
76
+ "thinkingHigh": "#8a6a9a",
77
+ "thinkingXhigh": "#aa6aaa",
78
+
79
+ "bashMode": "green"
80
+ }
81
+ }
@@ -0,0 +1,82 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/badlogic/pi-mono/main/packages/coding-agent/theme-schema.json",
3
+ "name": "nightowl",
4
+ "vars": {
5
+ "cyan": "#7fdbca",
6
+ "blue": "#82AAFF",
7
+ "green": "#c5e478",
8
+ "red": "#EF5350",
9
+ "yellow": "#ffcb8b",
10
+ "magenta": "#c792ea",
11
+ "gray": "#5f7e97",
12
+ "dimGray": "#4b6479",
13
+ "darkGray": "#122d42",
14
+ "accent": "#80CBC4",
15
+ "foreground": "#d6deeb",
16
+ "background": "#011627",
17
+ "userMsgBg": "#0b2942",
18
+ "toolPendingBg": "#01111d",
19
+ "toolSuccessBg": "#0b253a",
20
+ "toolErrorBg": "#1a1015"
21
+ },
22
+ "colors": {
23
+ "accent": "accent",
24
+ "border": "blue",
25
+ "borderAccent": "cyan",
26
+ "borderMuted": "darkGray",
27
+ "success": "green",
28
+ "error": "red",
29
+ "warning": "yellow",
30
+ "muted": "gray",
31
+ "dim": "dimGray",
32
+ "text": "",
33
+ "thinkingText": "gray",
34
+
35
+ "userMessageBg": "userMsgBg",
36
+ "userMessageText": "",
37
+ "toolPendingBg": "toolPendingBg",
38
+ "toolSuccessBg": "toolSuccessBg",
39
+ "toolErrorBg": "toolErrorBg",
40
+ "toolTitle": "",
41
+ "toolOutput": "gray",
42
+
43
+ "selectedBg": "darkGray",
44
+ "customMessageBg": "userMsgBg",
45
+ "customMessageText": "",
46
+ "customMessageLabel": "accent",
47
+
48
+ "mdHeading": "blue",
49
+ "mdLink": "cyan",
50
+ "mdLinkUrl": "dimGray",
51
+ "mdCode": "accent",
52
+ "mdCodeBlock": "green",
53
+ "mdCodeBlockBorder": "gray",
54
+ "mdQuote": "gray",
55
+ "mdQuoteBorder": "gray",
56
+ "mdHr": "gray",
57
+ "mdListBullet": "accent",
58
+
59
+ "toolDiffAdded": "green",
60
+ "toolDiffRemoved": "red",
61
+ "toolDiffContext": "gray",
62
+
63
+ "syntaxComment": "#637777",
64
+ "syntaxKeyword": "magenta",
65
+ "syntaxFunction": "blue",
66
+ "syntaxVariable": "cyan",
67
+ "syntaxString": "#c789d6",
68
+ "syntaxNumber": "#F78C6C",
69
+ "syntaxType": "yellow",
70
+ "syntaxOperator": "cyan",
71
+ "syntaxPunctuation": "foreground",
72
+
73
+ "thinkingOff": "darkGray",
74
+ "thinkingMinimal": "#234d70",
75
+ "thinkingLow": "#1d3b53",
76
+ "thinkingMedium": "#5f7e97",
77
+ "thinkingHigh": "#7e57c2",
78
+ "thinkingXhigh": "#c792ea",
79
+
80
+ "bashMode": "green"
81
+ }
82
+ }
@@ -0,0 +1,183 @@
1
+ ---
2
+ name: anachb
3
+ description: Austrian public transport (VOR AnachB) for all of Austria. Query real-time departures, search stations/stops, plan routes between locations, and check service disruptions. Use when asking about Austrian trains, buses, trams, metro (U-Bahn), or directions involving public transport in Austria.
4
+ ---
5
+
6
+ # VOR AnachB - Austrian Public Transport API
7
+
8
+ Query Austrian public transport for real-time departures, route planning, and service disruptions using the HAFAS API.
9
+
10
+ ## Quick Reference
11
+
12
+ | Script | Purpose |
13
+ |--------|---------|
14
+ | `search.sh` | Find stations/stops by name |
15
+ | `departures.sh` | Real-time departures at a station |
16
+ | `route.sh` | Plan a trip between two locations |
17
+ | `disruptions.sh` | Current service disruptions |
18
+
19
+ **API:** HAFAS (Hacon Fahrplan-Auskunfts-System)
20
+ **Endpoint:** `https://vao.demo.hafas.de/gate`
21
+
22
+ ---
23
+
24
+ ## 1. Search Stations/Stops
25
+
26
+ Find station IDs by name:
27
+
28
+ ```bash
29
+ ./search.sh "Stephansplatz"
30
+ ./search.sh "Wien Hauptbahnhof"
31
+ ./search.sh "Linz"
32
+ ./search.sh "Salzburg Hbf"
33
+ ```
34
+
35
+ Returns station names, IDs (extId), and coordinates.
36
+
37
+ **Response fields:**
38
+ - `name`: Station name
39
+ - `extId`: Station ID for use in other queries
40
+ - `type`: S (Station), A (Address), P (POI)
41
+ - `coordinates`: WGS84 coordinates (lon/lat in 1e-6 format)
42
+
43
+ ---
44
+
45
+ ## 2. Real-Time Departures
46
+
47
+ Get next departures from a station:
48
+
49
+ ```bash
50
+ ./departures.sh <station-id> [count]
51
+
52
+ # Examples:
53
+ ./departures.sh 490132000 # Wien Stephansplatz, 10 departures
54
+ ./departures.sh 490132000 20 # Wien Stephansplatz, 20 departures
55
+ ./departures.sh 490060200 # Wien Hauptbahnhof
56
+ ./departures.sh 444130000 # Linz Hbf
57
+ ./departures.sh 455000100 # Salzburg Hbf
58
+ ```
59
+
60
+ **Response fields:**
61
+ - `line`: Line name (U1, S1, RJ, etc.)
62
+ - `direction`: Final destination
63
+ - `departure`: Scheduled departure time
64
+ - `delay`: Delay in minutes (if any)
65
+ - `platform`: Platform/track number
66
+
67
+ ---
68
+
69
+ ## 3. Route Planning
70
+
71
+ Plan a trip between two stations:
72
+
73
+ ```bash
74
+ ./route.sh <from-id> <to-id> [results]
75
+
76
+ # Examples:
77
+ ./route.sh 490132000 490060200 # Stephansplatz → Hauptbahnhof
78
+ ./route.sh 490132000 444130000 5 # Wien → Linz, 5 results
79
+ ./route.sh "Graz Hbf" "Wien Hbf" # Search by name (slower)
80
+ ```
81
+
82
+ **Response fields:**
83
+ - `departure`: Departure time
84
+ - `arrival`: Arrival time
85
+ - `duration`: Trip duration
86
+ - `changes`: Number of transfers
87
+ - `legs`: Array of trip segments with line info
88
+
89
+ ---
90
+
91
+ ## 4. Disruptions
92
+
93
+ Check current service disruptions:
94
+
95
+ ```bash
96
+ ./disruptions.sh [category]
97
+
98
+ # Examples:
99
+ ./disruptions.sh # All disruptions
100
+ ./disruptions.sh TRAIN # Train disruptions only
101
+ ./disruptions.sh BUS # Bus disruptions only
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Common Station IDs
107
+
108
+ | Station | ID |
109
+ |---------|-----|
110
+ | Wien Stephansplatz | 490132000 |
111
+ | Wien Hauptbahnhof | 490134900 |
112
+ | Wien Westbahnhof | 490024300 |
113
+ | Wien Praterstern | 490056100 |
114
+ | Wien Karlsplatz | 490024600 |
115
+ | Wien Schwedenplatz | 490119500 |
116
+ | Linz Hbf | 444116400 |
117
+ | Salzburg Hbf | 455000200 |
118
+ | Graz Hbf | 460086000 |
119
+ | Innsbruck Hbf | 481070100 |
120
+ | Klagenfurt Hbf | 492019500 |
121
+ | St. Pölten Hbf | 431543300 |
122
+ | Wiener Neustadt Hbf | 430521000 |
123
+ | Krems a.d. Donau | 431046400 |
124
+
125
+ **Tip:** Always use `./search.sh` to find the correct station ID.
126
+
127
+ ---
128
+
129
+ ## Transport Types
130
+
131
+ | Code | Type |
132
+ |------|------|
133
+ | ICE/RJ/RJX | High-speed trains |
134
+ | IC/EC | InterCity/EuroCity |
135
+ | REX/R | Regional Express/Regional |
136
+ | S | S-Bahn (suburban rail) |
137
+ | U | U-Bahn (Vienna metro) |
138
+ | STR | Tram/Straßenbahn |
139
+ | BUS | Bus |
140
+ | AST | Demand-responsive transport |
141
+
142
+ ---
143
+
144
+ ## API Details (for advanced usage)
145
+
146
+ The scripts use the HAFAS JSON API. For custom queries:
147
+
148
+ ```bash
149
+ curl -s -X POST "https://vao.demo.hafas.de/gate" \
150
+ -H "Content-Type: application/json" \
151
+ -d '{
152
+ "svcReqL": [{
153
+ "req": { ... },
154
+ "meth": "METHOD_NAME",
155
+ "id": "1|1|"
156
+ }],
157
+ "client": {"id": "VAO", "v": "1", "type": "AND", "name": "nextgen"},
158
+ "ver": "1.73",
159
+ "lang": "de",
160
+ "auth": {"aid": "nextgen", "type": "AID"}
161
+ }'
162
+ ```
163
+
164
+ **Available methods:**
165
+ - `LocMatch` - Location/station search
166
+ - `StationBoard` - Departures/arrivals
167
+ - `TripSearch` - Route planning
168
+ - `HimSearch` - Disruptions/service messages
169
+ - `JourneyDetails` - Details of a specific journey
170
+
171
+ ---
172
+
173
+ ## Tips
174
+
175
+ 1. **Find station IDs first**: Always use `search.sh` to find the correct station ID before querying departures or routes.
176
+
177
+ 2. **Station vs Stop**: Major stations have multiple platforms - the main station ID covers all platforms.
178
+
179
+ 3. **Real-time data**: Departures include real-time delays when available.
180
+
181
+ 4. **Austria-wide**: This API covers all Austrian public transport, not just Vienna.
182
+
183
+ 5. **Cross-border**: Some routes extend to neighboring countries (Germany, Czech Republic, etc.).
@@ -0,0 +1,79 @@
1
+ #!/bin/bash
2
+ # Get real-time departures from an Austrian public transport station
3
+ # Usage: ./departures.sh <station-id> [count]
4
+ #
5
+ # Find station IDs with: ./search.sh <name>
6
+ # Example: ./departures.sh 490132000 # Wien Stephansplatz
7
+ # Example: ./departures.sh 490060200 20 # Wien Hauptbahnhof, 20 results
8
+
9
+ STATION_ID="${1:-}"
10
+ COUNT="${2:-10}"
11
+
12
+ if [ -z "$STATION_ID" ]; then
13
+ echo "Usage: $0 <station-id> [count]"
14
+ echo ""
15
+ echo "Find station IDs with: ./search.sh <name>"
16
+ echo ""
17
+ echo "Common station IDs:"
18
+ echo " 490132000 - Wien Stephansplatz"
19
+ echo " 490134900 - Wien Hauptbahnhof"
20
+ echo " 490024300 - Wien Westbahnhof"
21
+ echo " 444116400 - Linz Hbf"
22
+ echo " 455000200 - Salzburg Hbf"
23
+ echo " 460086000 - Graz Hbf"
24
+ exit 1
25
+ fi
26
+
27
+ curl -s -X POST "https://vao.demo.hafas.de/gate" \
28
+ -H "Content-Type: application/json" \
29
+ -d '{
30
+ "svcReqL": [{
31
+ "req": {
32
+ "stbLoc": {"extId": "'"$STATION_ID"'", "type": "S"},
33
+ "type": "DEP",
34
+ "maxJny": '"$COUNT"'
35
+ },
36
+ "meth": "StationBoard",
37
+ "id": "1|2|"
38
+ }],
39
+ "client": {"id": "VAO", "v": "1", "type": "AND", "name": "nextgen"},
40
+ "ver": "1.73",
41
+ "lang": "de",
42
+ "auth": {"aid": "nextgen", "type": "AID"}
43
+ }' | jq '
44
+ .svcResL[0].res as $res |
45
+ ($res.common.prodL // []) as $products |
46
+ ($res.common.locL // []) as $locations |
47
+ ($res.common.dirL // []) as $directions |
48
+
49
+ # Get station name
50
+ ($locations[0].name // "Unknown") as $stationName |
51
+
52
+ # Helper to format time
53
+ def formatTime: if . and (. | length) >= 4 then "\(.[0:2]):\(.[2:4])" else null end;
54
+
55
+ # Helper to calculate delay
56
+ def calcDelay(real; sched):
57
+ if real and sched and (real | length) >= 4 and (sched | length) >= 4 then
58
+ ((real[0:2] | tonumber) * 60 + (real[2:4] | tonumber)) -
59
+ ((sched[0:2] | tonumber) * 60 + (sched[2:4] | tonumber))
60
+ else null end;
61
+
62
+ {
63
+ station: $stationName,
64
+ departures: [
65
+ ($res.jnyL // [])[:'"$COUNT"'] | .[] |
66
+ (if .dirX != null and $directions[.dirX] != null then $directions[.dirX].txt else .dirTxt end) as $dir |
67
+ calcDelay(.stbStop.dTimeR; .stbStop.dTimeS) as $delayMin |
68
+ {
69
+ line: ($products[.prodX // 0].name // "?"),
70
+ direction: ($dir // null),
71
+ departure: ((.stbStop.dTimeR // .stbStop.dTimeS) | formatTime),
72
+ scheduled: (.stbStop.dTimeS | formatTime),
73
+ delay: (if $delayMin != null and $delayMin > 0 then "+\($delayMin)min" elif $delayMin != null and $delayMin < 0 then "\($delayMin)min" else null end),
74
+ platform: (.stbStop.dPlatfS // .stbStop.dPlatfR // null),
75
+ cancelled: (if .stbStop.dCncl == true then true else null end)
76
+ }
77
+ ]
78
+ }
79
+ '
@@ -0,0 +1,53 @@
1
+ #!/bin/bash
2
+ # Get current service disruptions in Austrian public transport
3
+ # Usage: ./disruptions.sh [max-results]
4
+ #
5
+ # Example: ./disruptions.sh # Get up to 20 disruptions
6
+ # Example: ./disruptions.sh 50 # Get up to 50 disruptions
7
+
8
+ MAX_RESULTS="${1:-20}"
9
+
10
+ curl -s -X POST "https://vao.demo.hafas.de/gate" \
11
+ -H "Content-Type: application/json" \
12
+ -d '{
13
+ "svcReqL": [{
14
+ "req": {
15
+ "maxNum": '"$MAX_RESULTS"',
16
+ "himFltrL": [{"mode": "INC", "type": "HIMCAT", "value": "*"}]
17
+ },
18
+ "meth": "HimSearch",
19
+ "id": "1|4|"
20
+ }],
21
+ "client": {"id": "VAO", "v": "1", "type": "AND", "name": "nextgen"},
22
+ "ver": "1.73",
23
+ "lang": "de",
24
+ "auth": {"aid": "nextgen", "type": "AID"}
25
+ }' | jq '
26
+ .svcResL[0].res as $res |
27
+ ($res.common.himL // []) as $messages |
28
+
29
+ if ($messages | length) == 0 then
30
+ {
31
+ status: "ok",
32
+ message: "No disruptions currently reported",
33
+ count: 0,
34
+ disruptions: []
35
+ }
36
+ else
37
+ {
38
+ count: ($messages | length),
39
+ disruptions: [
40
+ $messages[] | {
41
+ id: .hid,
42
+ category: .cat,
43
+ priority: .prio,
44
+ head: .head,
45
+ text: .text,
46
+ validFrom: .sDate,
47
+ validTo: .eDate,
48
+ affectedLines: ((.affProdRefL // []) | map(.name) | if . == [] then null else . end)
49
+ }
50
+ ]
51
+ }
52
+ end
53
+ '
@@ -0,0 +1,87 @@
1
+ #!/bin/bash
2
+ # Plan a trip between two stations in Austrian public transport
3
+ # Usage: ./route.sh <from-id> <to-id> [results]
4
+ #
5
+ # Find station IDs with: ./search.sh <name>
6
+ # Example: ./route.sh 490132000 490060200 # Stephansplatz → Hauptbahnhof
7
+ # Example: ./route.sh 490132000 444130000 5 # Wien → Linz, 5 results
8
+
9
+ FROM_ID="${1:-}"
10
+ TO_ID="${2:-}"
11
+ COUNT="${3:-3}"
12
+
13
+ if [ -z "$FROM_ID" ] || [ -z "$TO_ID" ]; then
14
+ echo "Usage: $0 <from-station-id> <to-station-id> [results]"
15
+ echo ""
16
+ echo "Find station IDs with: ./search.sh <name>"
17
+ echo ""
18
+ echo "Example: $0 490132000 490060200 # Stephansplatz → Hauptbahnhof"
19
+ echo "Example: $0 490132000 444130000 5 # Wien → Linz, 5 results"
20
+ exit 1
21
+ fi
22
+
23
+ curl -s -X POST "https://vao.demo.hafas.de/gate" \
24
+ -H "Content-Type: application/json" \
25
+ -d '{
26
+ "svcReqL": [{
27
+ "req": {
28
+ "depLocL": [{"extId": "'"$FROM_ID"'", "type": "S"}],
29
+ "arrLocL": [{"extId": "'"$TO_ID"'", "type": "S"}],
30
+ "getPasslist": false,
31
+ "maxChg": 5,
32
+ "numF": '"$COUNT"'
33
+ },
34
+ "meth": "TripSearch",
35
+ "id": "1|3|"
36
+ }],
37
+ "client": {"id": "VAO", "v": "1", "type": "AND", "name": "nextgen"},
38
+ "ver": "1.73",
39
+ "lang": "de",
40
+ "auth": {"aid": "nextgen", "type": "AID"}
41
+ }' | jq '
42
+ .svcResL[0].res as $res |
43
+ ($res.common.prodL // []) as $products |
44
+ ($res.common.locL // []) as $locations |
45
+ ($res.common.dirL // []) as $directions |
46
+
47
+ # Get from/to names
48
+ (($res.outConL // [])[0].dep.locX // 0) as $fromIdx |
49
+ (($res.outConL // [])[0].arr.locX // 0) as $toIdx |
50
+ ($locations[$fromIdx].name // "Unknown") as $fromName |
51
+ ($locations[$toIdx].name // "Unknown") as $toName |
52
+
53
+ # Helper function to format time
54
+ def formatTime: if . and (. | length) >= 4 then "\(.[0:2]):\(.[2:4])" else . end;
55
+
56
+ # Helper function to format duration string HHMMSS
57
+ def formatDuration:
58
+ if . and (. | length) >= 6 then
59
+ (.[0:2] | tonumber) as $h | (.[2:4] | tonumber) as $m |
60
+ if $h > 0 then "\($h)h \($m)min" else "\($m)min" end
61
+ else . end;
62
+
63
+ {
64
+ from: $fromName,
65
+ to: $toName,
66
+ trips: [
67
+ ($res.outConL // [])[:'"$COUNT"'] | .[] | {
68
+ departure: (.dep.dTimeS // "?") | formatTime,
69
+ arrival: (.arr.aTimeS // "?") | formatTime,
70
+ duration: (.dur // null) | formatDuration,
71
+ changes: (.chg // 0),
72
+ legs: [
73
+ (.secL // []) | .[] |
74
+ select(.type == "JNY") |
75
+ {
76
+ line: ($products[.jny.prodX // 0].name // "?"),
77
+ direction: (if .jny.dirX != null and $directions[.jny.dirX] != null then $directions[.jny.dirX].txt else null end),
78
+ from: ($locations[.dep.locX // 0].name // "?"),
79
+ departure: (.dep.dTimeS // "?") | formatTime,
80
+ to: ($locations[.arr.locX // 0].name // "?"),
81
+ arrival: (.arr.aTimeS // "?") | formatTime
82
+ }
83
+ ]
84
+ }
85
+ ]
86
+ }
87
+ '
@@ -0,0 +1,43 @@
1
+ #!/bin/bash
2
+ # Search for stations/stops in Austrian public transport
3
+ # Usage: ./search.sh <name>
4
+ #
5
+ # Returns: Station name, ID, type, and coordinates
6
+
7
+ QUERY="${1:-}"
8
+
9
+ if [ -z "$QUERY" ]; then
10
+ echo "Usage: $0 <station-name>"
11
+ echo "Example: $0 Stephansplatz"
12
+ echo "Example: $0 \"Wien Hauptbahnhof\""
13
+ exit 1
14
+ fi
15
+
16
+ curl -s -X POST "https://vao.demo.hafas.de/gate" \
17
+ -H "Content-Type: application/json" \
18
+ -d '{
19
+ "svcReqL": [{
20
+ "req": {
21
+ "input": {
22
+ "loc": {"name": "'"$QUERY"'"},
23
+ "field": "S"
24
+ }
25
+ },
26
+ "meth": "LocMatch",
27
+ "id": "1|1|"
28
+ }],
29
+ "client": {"id": "VAO", "v": "1", "type": "AND", "name": "nextgen"},
30
+ "ver": "1.73",
31
+ "lang": "de",
32
+ "auth": {"aid": "nextgen", "type": "AID"}
33
+ }' | jq -r '
34
+ .svcResL[0].res.match.locL // [] |
35
+ map(select(.type == "S" or .type == "A")) |
36
+ .[:15] |
37
+ map({
38
+ name: .name,
39
+ id: .extId,
40
+ type: (if .type == "S" then "Station" elif .type == "A" then "Address" else .type end),
41
+ coordinates: (if .crd then "\(.crd.y / 1000000), \(.crd.x / 1000000)" else null end)
42
+ })
43
+ '