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,429 @@
1
+ ---
2
+ name: oebb-scotty
3
+ description: Austrian rail travel planner (ÖBB Scotty). Use when planning train journeys in Austria, checking departures/arrivals at stations, or looking for service disruptions. Covers ÖBB trains, S-Bahn, regional trains, and connections to neighboring countries.
4
+ ---
5
+
6
+ # ÖBB Scotty API
7
+
8
+ Query Austria's public transport for trip planning, station departures, and service alerts via the HAFAS mgate API.
9
+
10
+ ## Quick Reference
11
+
12
+ | Method | Purpose |
13
+ |--------|---------|
14
+ | `LocMatch` | Search for stations/stops by name |
15
+ | `TripSearch` | Plan a journey between two locations |
16
+ | `StationBoard` | Get departures/arrivals at a station |
17
+ | `HimSearch` | Get service alerts and disruptions |
18
+
19
+ **Base URL:** `https://fahrplan.oebb.at/bin/mgate.exe`
20
+
21
+ ---
22
+
23
+ ## Authentication
24
+
25
+ All requests require these headers in the JSON body:
26
+
27
+ ```json
28
+ {
29
+ "id": "1",
30
+ "ver": "1.67",
31
+ "lang": "deu",
32
+ "auth": {"type": "AID", "aid": "OWDL4fE4ixNiPBBm"},
33
+ "client": {"id": "OEBB", "type": "WEB", "name": "webapp", "l": "vs_webapp"},
34
+ "formatted": false,
35
+ "svcReqL": [...]
36
+ }
37
+ ```
38
+
39
+ ---
40
+
41
+ ## 1. Location Search (`LocMatch`)
42
+
43
+ Search for stations, stops, addresses, or POIs by name.
44
+
45
+ ### Request
46
+
47
+ ```bash
48
+ curl -s -X POST "https://fahrplan.oebb.at/bin/mgate.exe" \
49
+ -H "Content-Type: application/json" \
50
+ -d '{
51
+ "id":"1","ver":"1.67","lang":"deu",
52
+ "auth":{"type":"AID","aid":"OWDL4fE4ixNiPBBm"},
53
+ "client":{"id":"OEBB","type":"WEB","name":"webapp","l":"vs_webapp"},
54
+ "formatted":false,
55
+ "svcReqL":[{
56
+ "req":{"input":{"field":"S","loc":{"name":"Wien Hbf","type":"ALL"},"maxLoc":10}},
57
+ "meth":"LocMatch"
58
+ }]
59
+ }'
60
+ ```
61
+
62
+ ### Response Structure
63
+
64
+ ```json
65
+ {
66
+ "svcResL": [{
67
+ "res": {
68
+ "match": {
69
+ "locL": [{
70
+ "lid": "A=1@O=Wien Hbf (U)@X=16377950@Y=48184986@U=181@L=1290401@",
71
+ "type": "S",
72
+ "name": "Wien Hbf (U)",
73
+ "extId": "1290401",
74
+ "crd": { "x": 16377950, "y": 48184986 },
75
+ "pCls": 6015
76
+ }]
77
+ }
78
+ }
79
+ }]
80
+ }
81
+ ```
82
+
83
+ ### Location Types
84
+
85
+ | Type | Description |
86
+ |------|-------------|
87
+ | `S` | Station/Stop |
88
+ | `A` | Address |
89
+ | `P` | POI (Point of Interest) |
90
+
91
+ ### Key Fields
92
+
93
+ | Field | Description |
94
+ |-------|-------------|
95
+ | `lid` | Location ID string (use in TripSearch) |
96
+ | `extId` | External station ID |
97
+ | `name` | Station name |
98
+ | `crd.x/y` | Coordinates (x=lon, y=lat, scaled by 10^6) |
99
+ | `pCls` | Product class bitmask |
100
+
101
+ ---
102
+
103
+ ## 2. Trip Search (`TripSearch`)
104
+
105
+ Plan a journey between two locations.
106
+
107
+ ### Request
108
+
109
+ ```bash
110
+ curl -s -X POST "https://fahrplan.oebb.at/bin/mgate.exe" \
111
+ -H "Content-Type: application/json" \
112
+ -d '{
113
+ "id":"1","ver":"1.67","lang":"deu",
114
+ "auth":{"type":"AID","aid":"OWDL4fE4ixNiPBBm"},
115
+ "client":{"id":"OEBB","type":"WEB","name":"webapp","l":"vs_webapp"},
116
+ "formatted":false,
117
+ "svcReqL":[{
118
+ "req":{
119
+ "depLocL":[{"lid":"A=1@O=Wien Hbf@L=8103000@","type":"S"}],
120
+ "arrLocL":[{"lid":"A=1@O=Salzburg Hbf@L=8100002@","type":"S"}],
121
+ "jnyFltrL":[{"type":"PROD","mode":"INC","value":"1023"}],
122
+ "getPolyline":false,
123
+ "getPasslist":true,
124
+ "outDate":"20260109",
125
+ "outTime":"080000",
126
+ "outFrwd":true,
127
+ "numF":5
128
+ },
129
+ "meth":"TripSearch"
130
+ }]
131
+ }'
132
+ ```
133
+
134
+ ### Parameters
135
+
136
+ | Param | Description |
137
+ |-------|-------------|
138
+ | `depLocL` | Departure location(s) - use `lid` from LocMatch |
139
+ | `arrLocL` | Arrival location(s) |
140
+ | `outDate` | Departure date (YYYYMMDD) |
141
+ | `outTime` | Departure time (HHMMSS) |
142
+ | `outFrwd` | `true` = search forward, `false` = search backward |
143
+ | `numF` | Number of connections to return |
144
+ | `jnyFltrL` | Product filter (see below) |
145
+ | `getPasslist` | Include intermediate stops |
146
+
147
+ ### Product Filter Values
148
+
149
+ | Bit | Value | Product |
150
+ |-----|-------|---------|
151
+ | 0 | 1 | ICE/RJX (High-speed) |
152
+ | 1 | 2 | IC/EC (InterCity) |
153
+ | 2 | 4 | NJ (Night trains) |
154
+ | 3 | 8 | D/EN (Express) |
155
+ | 4 | 16 | REX/R (Regional Express) |
156
+ | 5 | 32 | S-Bahn |
157
+ | 6 | 64 | Bus |
158
+ | 7 | 128 | Ferry |
159
+ | 8 | 256 | U-Bahn |
160
+ | 9 | 512 | Tram |
161
+
162
+ Use `1023` for all products, or sum specific bits.
163
+
164
+ ### Response Structure
165
+
166
+ ```json
167
+ {
168
+ "svcResL": [{
169
+ "res": {
170
+ "outConL": [{
171
+ "date": "20260109",
172
+ "dur": "025200",
173
+ "chg": 0,
174
+ "dep": {
175
+ "dTimeS": "075700",
176
+ "dPltfS": {"txt": "8A-B"}
177
+ },
178
+ "arr": {
179
+ "aTimeS": "104900",
180
+ "aPltfS": {"txt": "7"}
181
+ },
182
+ "secL": [{
183
+ "type": "JNY",
184
+ "jny": {
185
+ "prodX": 0,
186
+ "dirTxt": "Salzburg Hbf",
187
+ "stopL": [...]
188
+ }
189
+ }]
190
+ }],
191
+ "common": {
192
+ "locL": [...],
193
+ "prodL": [...]
194
+ }
195
+ }
196
+ }]
197
+ }
198
+ ```
199
+
200
+ ### Key Connection Fields
201
+
202
+ | Field | Description |
203
+ |-------|-------------|
204
+ | `dur` | Duration (HHMMSS) |
205
+ | `chg` | Number of changes |
206
+ | `dTimeS` | Scheduled departure |
207
+ | `dTimeR` | Real-time departure (if available) |
208
+ | `aTimeS` | Scheduled arrival |
209
+ | `aTimeR` | Real-time arrival (if available) |
210
+ | `dPltfS.txt` | Departure platform |
211
+ | `aPltfS.txt` | Arrival platform |
212
+ | `secL` | Journey sections (legs) |
213
+ | `secL[].jny.prodX` | Index into `common.prodL[]` for train name |
214
+
215
+ ### Understanding prodX (Product Index)
216
+
217
+ **Important:** The `prodX` field in journey sections is an index into the `common.prodL[]` array, NOT the train name itself. To get the actual train name (e.g., "S7", "RJX 662"), you must look up `common.prodL[prodX].name`.
218
+
219
+ ### Extracting Trip Summaries with jq
220
+
221
+ The raw TripSearch response is very verbose. Use this jq filter to extract a concise summary with resolved train names:
222
+
223
+ ```bash
224
+ curl -s -X POST "https://fahrplan.oebb.at/bin/mgate.exe" \
225
+ -H "Content-Type: application/json" \
226
+ -d '{ ... }' | jq '
227
+ .svcResL[0].res as $r |
228
+ $r.common.prodL as $prods |
229
+ [$r.outConL[] | {
230
+ dep: .dep.dTimeS,
231
+ arr: .arr.aTimeS,
232
+ depPlatform: .dep.dPltfS.txt,
233
+ arrPlatform: .arr.aPltfS.txt,
234
+ dur: .dur,
235
+ chg: .chg,
236
+ legs: [.secL[] | select(.type == "JNY") | {
237
+ train: $prods[.jny.prodX].name,
238
+ dir: .jny.dirTxt,
239
+ dep: .dep.dTimeS,
240
+ arr: .arr.aTimeS,
241
+ depPlatform: .dep.dPltfS.txt,
242
+ arrPlatform: .arr.aPltfS.txt
243
+ }]
244
+ }]'
245
+ ```
246
+
247
+ Example output:
248
+ ```json
249
+ [
250
+ {
251
+ "dep": "213900",
252
+ "arr": "221100",
253
+ "depPlatform": "1",
254
+ "arrPlatform": "3A-B",
255
+ "dur": "003200",
256
+ "chg": 0,
257
+ "legs": [{"train": "S 7", "dir": "Flughafen Wien Bahnhof", "dep": "213900", "arr": "221100", ...}]
258
+ }
259
+ ]
260
+ ```
261
+
262
+ ---
263
+
264
+ ## 3. Station Board (`StationBoard`)
265
+
266
+ Get departures or arrivals at a station.
267
+
268
+ ### Request
269
+
270
+ ```bash
271
+ curl -s -X POST "https://fahrplan.oebb.at/bin/mgate.exe" \
272
+ -H "Content-Type: application/json" \
273
+ -d '{
274
+ "id":"1","ver":"1.67","lang":"deu",
275
+ "auth":{"type":"AID","aid":"OWDL4fE4ixNiPBBm"},
276
+ "client":{"id":"OEBB","type":"WEB","name":"webapp","l":"vs_webapp"},
277
+ "formatted":false,
278
+ "svcReqL":[{
279
+ "req":{
280
+ "stbLoc":{"lid":"A=1@O=Wien Hbf@L=8103000@","type":"S"},
281
+ "date":"20260109",
282
+ "time":"080000",
283
+ "type":"DEP",
284
+ "maxJny":20
285
+ },
286
+ "meth":"StationBoard"
287
+ }]
288
+ }'
289
+ ```
290
+
291
+ ### Parameters
292
+
293
+ | Param | Description |
294
+ |-------|-------------|
295
+ | `stbLoc` | Station location |
296
+ | `date` | Date (YYYYMMDD) |
297
+ | `time` | Time (HHMMSS) |
298
+ | `type` | `DEP` (departures) or `ARR` (arrivals) |
299
+ | `maxJny` | Maximum number of journeys |
300
+
301
+ ### Response Structure
302
+
303
+ ```json
304
+ {
305
+ "svcResL": [{
306
+ "res": {
307
+ "jnyL": [{
308
+ "prodX": 0,
309
+ "dirTxt": "Salzburg Hbf",
310
+ "stbStop": {
311
+ "dTimeS": "080000",
312
+ "dPltfS": {"txt": "8A-B"}
313
+ }
314
+ }],
315
+ "common": {
316
+ "prodL": [{
317
+ "name": "RJX 662",
318
+ "cls": 1,
319
+ "prodCtx": {"catOutL": "Railjet Xpress"}
320
+ }]
321
+ }
322
+ }
323
+ }]
324
+ }
325
+ ```
326
+
327
+ ---
328
+
329
+ ## 4. Service Alerts (`HimSearch`)
330
+
331
+ Get current disruptions and service information.
332
+
333
+ ### Request
334
+
335
+ ```bash
336
+ curl -s -X POST "https://fahrplan.oebb.at/bin/mgate.exe" \
337
+ -H "Content-Type: application/json" \
338
+ -d '{
339
+ "id":"1","ver":"1.67","lang":"deu",
340
+ "auth":{"type":"AID","aid":"OWDL4fE4ixNiPBBm"},
341
+ "client":{"id":"OEBB","type":"WEB","name":"webapp","l":"vs_webapp"},
342
+ "formatted":false,
343
+ "svcReqL":[{
344
+ "req":{
345
+ "himFltrL":[{"type":"PROD","mode":"INC","value":"255"}],
346
+ "maxNum":20
347
+ },
348
+ "meth":"HimSearch"
349
+ }]
350
+ }'
351
+ ```
352
+
353
+ ### Response Structure
354
+
355
+ ```json
356
+ {
357
+ "svcResL": [{
358
+ "res": {
359
+ "msgL": [{
360
+ "hid": "HIM_FREETEXT_843858",
361
+ "head": "Verringertes Sitzplatzangebot",
362
+ "text": "Wegen einer technischen Störung...",
363
+ "prio": 0,
364
+ "sDate": "20260108",
365
+ "eDate": "20260108"
366
+ }]
367
+ }
368
+ }]
369
+ }
370
+ ```
371
+
372
+ ---
373
+
374
+ ## Common Station IDs
375
+
376
+ | Station | extId |
377
+ |---------|-------|
378
+ | Wien Hbf | 8103000 |
379
+ | Wien Meidling | 8100514 |
380
+ | Wien Westbahnhof | 8101003 |
381
+ | Salzburg Hbf | 8100002 |
382
+ | Linz Hbf | 8100013 |
383
+ | Graz Hbf | 8100173 |
384
+ | Innsbruck Hbf | 8100108 |
385
+ | Klagenfurt Hbf | 8100085 |
386
+ | St. Pölten Hbf | 8100008 |
387
+ | Wr. Neustadt Hbf | 8100516 |
388
+
389
+ ---
390
+
391
+ ## Time Format
392
+
393
+ - Dates: `YYYYMMDD` (e.g., `20260109`)
394
+ - Times: `HHMMSS` (e.g., `080000` = 08:00:00)
395
+ - Duration: `HHMMSS` (e.g., `025200` = 2h 52m)
396
+
397
+ ---
398
+
399
+ ## Error Handling
400
+
401
+ Check `err` field in response:
402
+
403
+ ```json
404
+ {
405
+ "err": "OK", // Success
406
+ "err": "PARSE", // Invalid request format
407
+ "err": "NO_MATCH", // No results found
408
+ "errTxt": "..." // Error details
409
+ }
410
+ ```
411
+
412
+ ---
413
+
414
+ ## Product Classes (cls values)
415
+
416
+ | cls | Product |
417
+ |-----|---------|
418
+ | 1 | ICE/RJX |
419
+ | 2 | IC/EC |
420
+ | 4 | Night trains |
421
+ | 8 | NJ/EN |
422
+ | 16 | REX/Regional |
423
+ | 32 | S-Bahn |
424
+ | 64 | Bus |
425
+ | 128 | Ferry |
426
+ | 256 | U-Bahn |
427
+ | 512 | Tram |
428
+ | 1024 | On-demand |
429
+ | 2048 | Other |
@@ -0,0 +1,83 @@
1
+ #!/bin/bash
2
+ # Get arrivals at an ÖBB station
3
+ # Usage: ./arrivals.sh <station-name> [date] [time] [max-results]
4
+ #
5
+ # Date format: YYYYMMDD (default: today)
6
+ # Time format: HHMM (default: now)
7
+ # Example: ./arrivals.sh "Salzburg Hbf" 20260109 0800 20
8
+
9
+ STATION="${1:-}"
10
+ DATE="${2:-$(date +%Y%m%d)}"
11
+ TIME="${3:-$(date +%H%M)}00"
12
+ MAX="${4:-20}"
13
+
14
+ if [ -z "$STATION" ]; then
15
+ echo "Usage: $0 <station-name> [date] [time] [max-results]"
16
+ echo "Example: $0 'Salzburg Hbf' 20260109 0800 20"
17
+ exit 1
18
+ fi
19
+
20
+ # Ensure time has seconds
21
+ if [ ${#TIME} -eq 4 ]; then
22
+ TIME="${TIME}00"
23
+ fi
24
+
25
+ # First, resolve station name to LID
26
+ STATION_LID=$(curl -s -X POST "https://fahrplan.oebb.at/bin/mgate.exe" \
27
+ -H "Content-Type: application/json" \
28
+ -d '{
29
+ "id":"1","ver":"1.67","lang":"deu",
30
+ "auth":{"type":"AID","aid":"OWDL4fE4ixNiPBBm"},
31
+ "client":{"id":"OEBB","type":"WEB","name":"webapp","l":"vs_webapp"},
32
+ "formatted":false,
33
+ "svcReqL":[{
34
+ "req":{"input":{"field":"S","loc":{"name":"'"$STATION"'","type":"S"},"maxLoc":1}},
35
+ "meth":"LocMatch"
36
+ }]
37
+ }' | jq -r '.svcResL[0].res.match.locL[0].lid // empty')
38
+
39
+ if [ -z "$STATION_LID" ]; then
40
+ echo "Error: Could not find station: $STATION"
41
+ exit 1
42
+ fi
43
+
44
+ # Get arrivals
45
+ curl -s -X POST "https://fahrplan.oebb.at/bin/mgate.exe" \
46
+ -H "Content-Type: application/json" \
47
+ -d '{
48
+ "id":"1","ver":"1.67","lang":"deu",
49
+ "auth":{"type":"AID","aid":"OWDL4fE4ixNiPBBm"},
50
+ "client":{"id":"OEBB","type":"WEB","name":"webapp","l":"vs_webapp"},
51
+ "formatted":false,
52
+ "svcReqL":[{
53
+ "req":{
54
+ "stbLoc":{"lid":"'"$STATION_LID"'","type":"S"},
55
+ "date":"'"$DATE"'",
56
+ "time":"'"$TIME"'",
57
+ "type":"ARR",
58
+ "maxJny":'"$MAX"'
59
+ },
60
+ "meth":"StationBoard"
61
+ }]
62
+ }' | jq '
63
+ .svcResL[0].res as $res |
64
+ {
65
+ station: ($res.common.locL[0].name),
66
+ date: "'"$DATE"'",
67
+ arrivals: [
68
+ $res.jnyL[] | {
69
+ time: (.stbStop.aTimeS | "\(.[0:2]):\(.[2:4])"),
70
+ timeReal: (if .stbStop.aTimeR then (.stbStop.aTimeR | "\(.[0:2]):\(.[2:4])") else null end),
71
+ delay: (if .stbStop.aTimeR and .stbStop.aTimeS then
72
+ (((.stbStop.aTimeR[0:2] | tonumber) * 60 + (.stbStop.aTimeR[2:4] | tonumber)) -
73
+ ((.stbStop.aTimeS[0:2] | tonumber) * 60 + (.stbStop.aTimeS[2:4] | tonumber)))
74
+ else null end),
75
+ platform: .stbStop.aPltfS.txt,
76
+ train: ($res.common.prodL[.prodX].name // ""),
77
+ category: ($res.common.prodL[.prodX].prodCtx.catOutL // ""),
78
+ from: .dirTxt,
79
+ cancelled: (.stbStop.aCncl // false)
80
+ }
81
+ ]
82
+ }
83
+ '
@@ -0,0 +1,83 @@
1
+ #!/bin/bash
2
+ # Get departures from an ÖBB station
3
+ # Usage: ./departures.sh <station-name> [date] [time] [max-results]
4
+ #
5
+ # Date format: YYYYMMDD (default: today)
6
+ # Time format: HHMM (default: now)
7
+ # Example: ./departures.sh "Wien Hbf" 20260109 0800 20
8
+
9
+ STATION="${1:-}"
10
+ DATE="${2:-$(date +%Y%m%d)}"
11
+ TIME="${3:-$(date +%H%M)}00"
12
+ MAX="${4:-20}"
13
+
14
+ if [ -z "$STATION" ]; then
15
+ echo "Usage: $0 <station-name> [date] [time] [max-results]"
16
+ echo "Example: $0 'Wien Hbf' 20260109 0800 20"
17
+ exit 1
18
+ fi
19
+
20
+ # Ensure time has seconds
21
+ if [ ${#TIME} -eq 4 ]; then
22
+ TIME="${TIME}00"
23
+ fi
24
+
25
+ # First, resolve station name to LID
26
+ STATION_LID=$(curl -s -X POST "https://fahrplan.oebb.at/bin/mgate.exe" \
27
+ -H "Content-Type: application/json" \
28
+ -d '{
29
+ "id":"1","ver":"1.67","lang":"deu",
30
+ "auth":{"type":"AID","aid":"OWDL4fE4ixNiPBBm"},
31
+ "client":{"id":"OEBB","type":"WEB","name":"webapp","l":"vs_webapp"},
32
+ "formatted":false,
33
+ "svcReqL":[{
34
+ "req":{"input":{"field":"S","loc":{"name":"'"$STATION"'","type":"S"},"maxLoc":1}},
35
+ "meth":"LocMatch"
36
+ }]
37
+ }' | jq -r '.svcResL[0].res.match.locL[0].lid // empty')
38
+
39
+ if [ -z "$STATION_LID" ]; then
40
+ echo "Error: Could not find station: $STATION"
41
+ exit 1
42
+ fi
43
+
44
+ # Get departures
45
+ curl -s -X POST "https://fahrplan.oebb.at/bin/mgate.exe" \
46
+ -H "Content-Type: application/json" \
47
+ -d '{
48
+ "id":"1","ver":"1.67","lang":"deu",
49
+ "auth":{"type":"AID","aid":"OWDL4fE4ixNiPBBm"},
50
+ "client":{"id":"OEBB","type":"WEB","name":"webapp","l":"vs_webapp"},
51
+ "formatted":false,
52
+ "svcReqL":[{
53
+ "req":{
54
+ "stbLoc":{"lid":"'"$STATION_LID"'","type":"S"},
55
+ "date":"'"$DATE"'",
56
+ "time":"'"$TIME"'",
57
+ "type":"DEP",
58
+ "maxJny":'"$MAX"'
59
+ },
60
+ "meth":"StationBoard"
61
+ }]
62
+ }' | jq '
63
+ .svcResL[0].res as $res |
64
+ {
65
+ station: ($res.common.locL[0].name),
66
+ date: "'"$DATE"'",
67
+ departures: [
68
+ $res.jnyL[] | {
69
+ time: (.stbStop.dTimeS | "\(.[0:2]):\(.[2:4])"),
70
+ timeReal: (if .stbStop.dTimeR then (.stbStop.dTimeR | "\(.[0:2]):\(.[2:4])") else null end),
71
+ delay: (if .stbStop.dTimeR and .stbStop.dTimeS then
72
+ (((.stbStop.dTimeR[0:2] | tonumber) * 60 + (.stbStop.dTimeR[2:4] | tonumber)) -
73
+ ((.stbStop.dTimeS[0:2] | tonumber) * 60 + (.stbStop.dTimeS[2:4] | tonumber)))
74
+ else null end),
75
+ platform: .stbStop.dPltfS.txt,
76
+ train: ($res.common.prodL[.prodX].name // ""),
77
+ category: ($res.common.prodL[.prodX].prodCtx.catOutL // ""),
78
+ direction: .dirTxt,
79
+ cancelled: (.stbStop.dCncl // false)
80
+ }
81
+ ]
82
+ }
83
+ '
@@ -0,0 +1,33 @@
1
+ #!/bin/bash
2
+ # Get current service disruptions and alerts
3
+ # Usage: ./disruptions.sh [max-results]
4
+ #
5
+ # Example: ./disruptions.sh 20
6
+
7
+ MAX="${1:-20}"
8
+
9
+ curl -s -X POST "https://fahrplan.oebb.at/bin/mgate.exe" \
10
+ -H "Content-Type: application/json" \
11
+ -d '{
12
+ "id":"1","ver":"1.67","lang":"deu",
13
+ "auth":{"type":"AID","aid":"OWDL4fE4ixNiPBBm"},
14
+ "client":{"id":"OEBB","type":"WEB","name":"webapp","l":"vs_webapp"},
15
+ "formatted":false,
16
+ "svcReqL":[{
17
+ "req":{
18
+ "himFltrL":[{"type":"PROD","mode":"INC","value":"255"}],
19
+ "maxNum":'"$MAX"'
20
+ },
21
+ "meth":"HimSearch"
22
+ }]
23
+ }' | jq '
24
+ .svcResL[0].res.msgL[] | {
25
+ id: .hid,
26
+ title: .head,
27
+ text: (.text | gsub("<[^>]*>"; "")),
28
+ priority: .prio,
29
+ startDate: .sDate,
30
+ endDate: .eDate,
31
+ active: .act
32
+ }
33
+ '
@@ -0,0 +1,36 @@
1
+ #!/bin/bash
2
+ # Search ÖBB stations/stops by name
3
+ # Usage: ./search-station.sh <name>
4
+ #
5
+ # Returns: Station name, ID, and coordinates
6
+
7
+ QUERY="${1:-}"
8
+
9
+ if [ -z "$QUERY" ]; then
10
+ echo "Usage: $0 <station-name>"
11
+ echo "Example: $0 'Wien Hbf'"
12
+ exit 1
13
+ fi
14
+
15
+ curl -s -X POST "https://fahrplan.oebb.at/bin/mgate.exe" \
16
+ -H "Content-Type: application/json" \
17
+ -d '{
18
+ "id":"1","ver":"1.67","lang":"deu",
19
+ "auth":{"type":"AID","aid":"OWDL4fE4ixNiPBBm"},
20
+ "client":{"id":"OEBB","type":"WEB","name":"webapp","l":"vs_webapp"},
21
+ "formatted":false,
22
+ "svcReqL":[{
23
+ "req":{"input":{"field":"S","loc":{"name":"'"$QUERY"'","type":"ALL"},"maxLoc":10}},
24
+ "meth":"LocMatch"
25
+ }]
26
+ }' | jq -r '
27
+ .svcResL[0].res.match.locL[] |
28
+ select(.type == "S") |
29
+ {
30
+ name: .name,
31
+ id: .extId,
32
+ lid: .lid,
33
+ lat: ((.crd.y // 0) / 1000000),
34
+ lon: ((.crd.x // 0) / 1000000)
35
+ }
36
+ '