Created
June 5, 2026 08:28
-
-
Save limhenry/19ab69682311dbaf4d1c32eb6ed89e8f to your computer and use it in GitHub Desktop.
Python Script to search for Beluga XL in the south of Hamburg
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const TOKEN_REFRESH_MARGIN = 30; | |
| let token = null; | |
| let expiresAt = null; | |
| const getToken = async () => { | |
| if (token && expiresAt && Date.now() < expiresAt) return token; | |
| return await refreshToken(); | |
| }; | |
| const refreshToken = async () => { | |
| const req = await fetch( | |
| 'https://auth.opensky-network.org/auth/realms/opensky-network/protocol/openid-connect/token', | |
| { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/x-www-form-urlencoded', | |
| }, | |
| body: new URLSearchParams({ | |
| grant_type: 'client_credentials', | |
| client_id: '', // move this to env | |
| client_secret: '', // move this to env | |
| }), | |
| }, | |
| ); | |
| const res = await req.json(); | |
| token = res.access_token; | |
| const expiresIn = Date.now() + res.expires_in * 1000; | |
| expiresAt = Date.now() + (expiresIn - TOKEN_REFRESH_MARGIN) * 1000; | |
| return token; | |
| }; | |
| const getFlight = async (icao24) => { | |
| const url = new URL('https://opensky-network.org/api/states/all'); | |
| url.searchParams.set('icao24', icao24.join(',')); | |
| url.searchParams.set('lamin', '51.12145'); // don't hard code this | |
| url.searchParams.set('lomin', '5.32383'); // don't hard code this | |
| url.searchParams.set('lamax', '53.75903'); // don't hard code this | |
| url.searchParams.set('lomax', '10.31003'); // don't hard code this | |
| const t = await getToken(); | |
| const req = await fetch(url, { | |
| headers: { | |
| Authorization: `Bearer ${t}`, | |
| }, | |
| }); | |
| const res = await req.json(); | |
| const states = res.states.map((state) => { | |
| return { | |
| icao24: state[0], | |
| callsign: state[1].trim(), | |
| origin_country: state[2], | |
| time_position: state[3], | |
| last_contact: state[4], | |
| longitude: state[5], | |
| latitude: state[6], | |
| baro_altitude: state[7], | |
| on_ground: state[8], | |
| velocity: state[9], | |
| true_track: state[10], | |
| vertical_rate: state[11], | |
| sensors: state[12], | |
| geo_altitude: state[13], | |
| squawk: state[14], | |
| spi: state[15], | |
| position_source: state[16], | |
| }; | |
| }); | |
| return { | |
| rateLimitRemaining: req.headers.get('X-Rate-Limit-Remaining'), | |
| time: res.time, | |
| states, | |
| }; | |
| }; | |
| // make this an endpoint with parameters for icao24, and call it from the frontend | |
| // beluga xl 3: 395d68 | |
| // beluga xl 4: 395d69 | |
| // beluga xl 6: 395d6e | |
| await getFlight(['395d68', '395d69', '395d6e']); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment