文件预览

journey.sh

查看 Tabussen 技能包中的文件内容。

文件内容

journey.sh

#!/bin/bash
# Tabussen/Ultra Journey Planner using ResRobot API
# Usage: ./journey.sh <from-id> <to-id> [datetime] [mode]

set -e

# Configuration
API_KEY="${RESROBOT_API_KEY:-YOUR_API_KEY_HERE}"
BASE_URL="https://api.resrobot.se/v2.1/trip"

# Arguments
FROM_ID="$1"
TO_ID="$2"
DATETIME="$3"
MODE="${4:-depart}"  # "depart" or "arrive"

# Validation
if [ -z "$FROM_ID" ] || [ -z "$TO_ID" ]; then
    echo "Usage: $0 <from-id> <to-id> [datetime] [mode]"
    echo ""
    echo "Arguments:"
    echo "  from-id   - Origin stop ID or coordinates (lat#lon)"
    echo "  to-id     - Destination stop ID or coordinates (lat#lon)"
    echo "  datetime  - Optional: '18:30', 'tomorrow 09:00', '2026-01-28 14:00'"
    echo "  mode      - Optional: 'depart' (default) or 'arrive'"
    echo ""
    echo "Examples:"
    echo "  $0 740066252 740025841                      # Now"
    echo "  $0 740066252 740025841 '08:30'              # Today 08:30"
    echo "  $0 740066252 740025841 'tomorrow 09:00'     # Tomorrow"
    echo "  $0 740066252 740025841 '18:00' arrive       # Arrive by 18:00"
    echo "  $0 '63.825#20.263' 740025841                # From coordinates"
    exit 1
fi

if [ "$API_KEY" = "YOUR_API_KEY_HERE" ]; then
    echo "ERROR: Please set RESROBOT_API_KEY environment variable"
    echo "Get your API key at: https://developer.trafiklab.se"
    exit 1
fi

# Build query parameters
PARAMS="format=json&accessId=${API_KEY}&passlist=1&numF=5"

# Handle origin (ID or coordinates)
if [[ "$FROM_ID" == *"#"* ]]; then
    # Coordinates format: lat#lon
    ORIGIN_LAT=$(echo "$FROM_ID" | cut -d'#' -f1)
    ORIGIN_LON=$(echo "$FROM_ID" | cut -d'#' -f2)
    PARAMS="${PARAMS}&originCoordLat=${ORIGIN_LAT}&originCoordLong=${ORIGIN_LON}"
else
    PARAMS="${PARAMS}&originId=${FROM_ID}"
fi

# Handle destination (ID or coordinates)
if [[ "$TO_ID" == *"#"* ]]; then
    # Coordinates format: lat#lon
    DEST_LAT=$(echo "$TO_ID" | cut -d'#' -f1)
    DEST_LON=$(echo "$TO_ID" | cut -d'#' -f2)
    PARAMS="${PARAMS}&destCoordLat=${DEST_LAT}&destCoordLong=${DEST_LON}"
else
    PARAMS="${PARAMS}&destId=${TO_ID}"
fi

# Parse datetime
if [ -n "$DATETIME" ]; then
    # Handle "tomorrow" keyword
    if [[ "$DATETIME" == tomorrow* ]]; then
        TOMORROW=$(date -v+1d +%Y-%m-%d 2>/dev/null || date -d "tomorrow" +%Y-%m-%d)
        TIME_PART=$(echo "$DATETIME" | sed 's/tomorrow //')
        if [ -n "$TIME_PART" ] && [ "$TIME_PART" != "tomorrow" ]; then
            PARAMS="${PARAMS}&date=${TOMORROW}&time=${TIME_PART}"
        else
            PARAMS="${PARAMS}&date=${TOMORROW}"
        fi
    # Handle full date format YYYY-MM-DD HH:MM
    elif [[ "$DATETIME" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2} ]]; then
        DATE_PART=$(echo "$DATETIME" | cut -d' ' -f1)
        TIME_PART=$(echo "$DATETIME" | cut -d' ' -f2)
        PARAMS="${PARAMS}&date=${DATE_PART}"
        if [ -n "$TIME_PART" ]; then
            PARAMS="${PARAMS}&time=${TIME_PART}"
        fi
    # Handle time only HH:MM
    elif [[ "$DATETIME" =~ ^[0-9]{2}:[0-9]{2}$ ]]; then
        PARAMS="${PARAMS}&time=${DATETIME}"
    fi
fi

# Handle arrive mode
if [ "$MODE" = "arrive" ]; then
    PARAMS="${PARAMS}&searchForArrival=1"
fi

# Make API request
RESPONSE=$(curl -s "${BASE_URL}?${PARAMS}")

# Check for errors
if echo "$RESPONSE" | jq -e '.errorCode' > /dev/null 2>&1; then
    ERROR_MSG=$(echo "$RESPONSE" | jq -r '.errorText // "Unknown error"')
    echo "API Error: $ERROR_MSG"
    exit 1
fi

# Check for trips
TRIP_COUNT=$(echo "$RESPONSE" | jq '.Trip | length // 0')

if [ "$TRIP_COUNT" -eq 0 ]; then
    echo "No journeys found"
    echo ""
    echo "Tips:"
    echo "  - Check that both stop IDs are valid"
    echo "  - Try a different time (some routes have limited frequency)"
    echo "  - Late night service may be limited"
    exit 0
fi

# Display planning period info
PERIOD_BEGIN=$(echo "$RESPONSE" | jq -r '.Trip[0].ServiceDays[0].planningPeriodBegin // "N/A"')
PERIOD_END=$(echo "$RESPONSE" | jq -r '.Trip[0].ServiceDays[0].planningPeriodEnd // "N/A"')

echo "========================================"
echo "JOURNEY OPTIONS"
echo "========================================"
echo "Planning period: $PERIOD_BEGIN to $PERIOD_END"
echo ""

# Process each trip
OPTION_NUM=0
echo "$RESPONSE" | jq -c '.Trip[]' | while read -r TRIP; do
    OPTION_NUM=$((OPTION_NUM + 1))
    
    # Get origin and destination from first and last leg
    ORIGIN_NAME=$(echo "$TRIP" | jq -r '.LegList.Leg[0].Origin.name')
    DEST_NAME=$(echo "$TRIP" | jq -r '.LegList.Leg[-1].Destination.name')
    
    # Get departure and arrival times
    DEPART_TIME=$(echo "$TRIP" | jq -r '.LegList.Leg[0].Origin.time')
    DEPART_DATE=$(echo "$TRIP" | jq -r '.LegList.Leg[0].Origin.date')
    ARRIVE_TIME=$(echo "$TRIP" | jq -r '.LegList.Leg[-1].Destination.time')
    ARRIVE_DATE=$(echo "$TRIP" | jq -r '.LegList.Leg[-1].Destination.date')
    
    # Count transfers (legs - 1, excluding walks)
    LEG_COUNT=$(echo "$TRIP" | jq '[.LegList.Leg[] | select(.type == "JNY")] | length')
    TRANSFERS=$((LEG_COUNT - 1))
    if [ "$TRANSFERS" -lt 0 ]; then
        TRANSFERS=0
    fi
    
    # Get duration
    DURATION=$(echo "$TRIP" | jq -r '.duration // "N/A"')
    # Convert ISO duration to readable format
    DURATION_READABLE=$(echo "$DURATION" | sed 's/PT//' | sed 's/H/h /' | sed 's/M/m/')
    
    echo "=============================================================="
    echo "OPTION $OPTION_NUM: $ORIGIN_NAME -> $DEST_NAME"
    echo "=============================================================="
    echo "Date:     $DEPART_DATE"
    echo "Depart:   $DEPART_TIME"
    echo "Arrive:   $ARRIVE_TIME"
    echo "Duration: $DURATION_READABLE"
    echo "Changes:  $TRANSFERS"
    echo ""
    echo "LEGS:"
    
    # Process each leg
    echo "$TRIP" | jq -c '.LegList.Leg[]' | while read -r LEG; do
        LEG_TYPE=$(echo "$LEG" | jq -r '.type')
        LEG_NAME=$(echo "$LEG" | jq -r '.name // "Walking"')
        
        ORIG_NAME=$(echo "$LEG" | jq -r '.Origin.name')
        ORIG_TIME=$(echo "$LEG" | jq -r '.Origin.time')
        DEST_NAME_LEG=$(echo "$LEG" | jq -r '.Destination.name')
        DEST_TIME=$(echo "$LEG" | jq -r '.Destination.time')
        
        if [ "$LEG_TYPE" = "WALK" ]; then
            DISTANCE=$(echo "$LEG" | jq -r '.dist // "unknown"')
            echo "  -> WALK ${DISTANCE}m"
            echo "     From: $ORIG_TIME $ORIG_NAME"
            echo "     To:   $DEST_TIME $DEST_NAME_LEG"
        else
            DIRECTION=$(echo "$LEG" | jq -r '.direction // "N/A"')
            # Product can be object or array, handle both
            OPERATOR=$(echo "$LEG" | jq -r 'if .Product | type == "array" then .Product[0].operator else .Product.operator end // "N/A"')
            TRANSPORT_NUM=$(echo "$LEG" | jq -r '.transportNumber // ""')
            TRANSPORT_CAT=$(echo "$LEG" | jq -r '.transportCategory // ""')
            
            echo "  -> $TRANSPORT_CAT $LEG_NAME"
            echo "     Operator: $OPERATOR"
            echo "     From: $ORIG_TIME $ORIG_NAME"
            echo "     To:   $DEST_TIME $DEST_NAME_LEG"
            echo "     Direction: $DIRECTION"
            
            # Show intermediate stops if available
            STOP_COUNT=$(echo "$LEG" | jq 'if .Stops.Stop then (.Stops.Stop | length) else 0 end')
            if [ "$STOP_COUNT" -gt 2 ]; then
                echo "     Stops: $STOP_COUNT (including start/end)"
            fi
        fi
        echo ""
    done
    
    echo ""
done

echo "========================================"
echo "Found $TRIP_COUNT journey option(s)"