1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
#!/bin/bash
read stop
# function to provide data to a for loop
_jq() {
echo ${json} | base64 --decode | jq -r ${1}
}
_liveresult() {
stops=$(curl --fail --silent https://admin.libertybus.je/api/v1/stops/"${stop}")
stopname=$(echo $stops | jq '.[].name')
livetimes=$(curl --fail --silent https://admin.libertybus.je/api/v1/soj/stop_updates/${stop})
exitcode=$?
# sort livetimes by service_number and eta
livetimes=$(echo ${livetimes} | jq 'sort_by((.service_number | sub("[^0-9]$"; "") | tonumber), (.service_number | sub("[^A-Z]$"; "") | tostring), .eta)')
livetimeslen=$(echo ${livetimes} | jq '. | length')
if [ $exitcode != 0 ]; then
echo "cURL error - exiting."
exit 1
elif [ $livetimeslen = 0 ]; then
echo "No results found."
exit 1
elif [[ ${stopname,,} == *"bus"* ]] || [[ ${stopname,,} == *"station"* ]] || [[ ${stopname,,} == *"stand"* ]]; then
_rejectbusstation
else
for json in $(echo "${livetimes}" | jq -r '.[] | @base64'); do
if [[ $(_jq '.service_number') != $outroute ]]; then
result=$(echo $result | sed 's/,$//')
result="$result | Dest: $(_jq '.destination')[$(_jq '.service_number')] - ETAs: $(_jq '.eta'), "
else
result="$result $(_jq '.eta'), "
fi
outroute=$(_jq '.service_number')
done
result=$(echo $result | sed 's/,$//' | sed 's/|//' )
echo -e $result
exit 0
fi
}
_stopsreturn() {
stops=$(curl --fail --silent https://admin.libertybus.je/api/v1/stops/"${stop}")
exitcode=$?
stopslen=$(echo ${stops} | jq '. | length')
# if length of $stops array is 1 then only one bus stop matches and we can return live times for that stop
if [ $exitcode != 0 ]; then
echo "cURL error - exiting."
exit 1
elif [ $stopslen = 1 ]; then
stop=$(echo ${stops} | jq '.[].stop_id')
_liveresult
elif [ $stopslen = 0 ]; then
echo "No results found."
exit 1
# multiple stops returned in $stops so we will return stop names and codes so user can retry
else
for json in $(echo "${stops}" | jq -r '.[] | @base64'); do
result="$result Stop: $(_jq '.name') - Code: $(_jq '.stop_id') |"
#result="$result Code: $(_jq '.stop_id') |"
done
result=$(echo $result | sed 's/ |$//')
echo -e $result
exit 0
fi
}
_rejectbusstation() {
echo "If you want to see when the next bus for a given route leaves the bus station then try ""!bus <route>"" where <route> is a valid bus route or try ""!bus -h"" for help."
exit 1
}
# function for now in case I need to reuse somewhere else...
_help() {
echo "Usage: '!bus <stop>' where <stop> is either the route number, 4 digit stop code, the full unique or partial bus stop name. If a bus stop name is used and there are multiple matches then a list of matching stops will be returned with their codes. -h --help - print this usage information."
exit 0
}
_nextbus() {
time=$(date +"%H:%M")
day=$(date +"%a" | tr [:upper:] [:lower:])
# set routeday to one of three timetable options
if [[ $(date +%u) -lt 6 ]]; then
routeday=mon_fri
else
routeday=$(date +"%a" | tr [:upper:] [:lower:])
fi
# select all stops from todays trips, where days_of_operation is true for tday, for a given service_number, where stop_name contains "Bus Station Stand"
nextbus=$(echo $timetables | jq -r --arg routeday "$routeday" --arg day "$day" --arg stop "$stop" '.timetables[] | select(.service_number == $stop) | .timetable.outbound[$routeday].trips[] | select(.days_of_operation[$day] == true) | .stops[] | select(.stop_name | contains("Bus Station Stand"))')
for json in $(echo "${nextbus}" | jq -r '. | @base64'); do
if [[ $(_jq '.departure_time') > $time ]]; then
echo "Route $stop leaving from $(_jq '.stop_name') at $(_jq '.departure_time')"
exit 0
fi
done
# if program didn't exit inside for loop then we know the next bus is on a future day so we need to check future days, unfortunately plenty of routes have days where no bus runs so we need to loop until we find the next day with a running bus
# for loop in range 7 used to prevent possible infinite loop with other methods - if there's not a bus for the next week then something is probably broken
for in in {1..7}; do
day=$(date --date="$i day" +"%a" | tr [:upper:] [:lower:])
case $day in
mon|tue|wed|thu|fri)
routeday=mon_fri;;
sat)
routeday=sat;;
sun)
routeday=sun;;
*) //
esac
nextbus=$(echo $timetables | jq -r --arg routeday "$routeday" --arg day "$day" --arg stop "$stop" '.timetables[] | select(.service_number == $stop) | .timetable.outbound[$routeday].trips[] | select(.days_of_operation[$day] == true) | .stops[] | select(.stop_name | contains("Bus Station Stand"))')
if [[ ! -z "${nextbus// }" ]]; then
echo $(echo "Route $stop leaving from $(echo $nextbus | jq -s '.[0].stop_name') at $(echo $nextbus | jq -s '.[0].departure_time') on $day" | sed 's/"//g')
exit 0
fi
done
# if program didn't exit inside for loop then something is probably broken
echo "Something broken - hopefully no one ever sees this..."
exit 1
}
timetables=$(curl --fail --silent https://admin.libertybus.je/cache/timetables/timetable_full.json)
services=$(echo $timetables | jq '.timetables[].service_number')
if [ "$stop" == "-h" ] || [ "$stop" == "--help" ] || [[ -z "${stop// }" ]]; then
_help
# checks if input pattern matches a 4 digit bus stop code
elif [[ "$stop" =~ ^-?[0-9]+$ ]] && [ $(echo ${#stop} == 4) ]; then
_liveresult
# checks if input is a valid bus route
elif [[ ${services[@]} =~ ${stop^^} ]]; then
_nextbus
elif [[ ${stop,,} == *"bus"* ]] || [[ ${stop,,} == *"station"* ]] || [[ ${stop,,} == *"stand"* ]]; then
_rejectbusstation
else
_stopsreturn
fi
|