Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ If applicable, add screenshots to help explain your problem.

**System (please complete the following information):**
- OS: [e.g. Windows]
- Python Version [e.g. 1.10]
- SDK: [Python, Node.js or Go]
- Language version: [e.g. Python 3.12, Node.js 22, Go 1.26]
- FlightRadarAPI version: [e.g. 1.6.0]

**Additional context**
Add any other context about the problem here.
4 changes: 3 additions & 1 deletion .github/ISSUE_TEMPLATE/questioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ If applicable, add screenshots to help explain your problem.
If applicable, please complete the following information:

1. OS: [e.g. Windows]
2. Python Version [e.g. 1.10]
2. SDK: [Python, Node.js or Go]
3. Language version: [e.g. Python 3.12, Node.js 22, Go 1.26]
4. FlightRadarAPI version: [e.g. 1.6.0]

**Additional context**
Add any other context about the problem here.
9 changes: 9 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ updates:
- "deps"
- "security"

- package-ecosystem: "gomod"
directory: "/go"
schedule:
interval: "weekly"
open-pull-requests-limit: 0
labels:
- "deps"
- "security"

- package-ecosystem: "github-actions"
directory: "/"
schedule:
Expand Down
91 changes: 91 additions & 0 deletions .github/workflows/go-package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: Go Package

on:
push:
branches:
- main
paths:
- 'go/**'
# ports_test.go reads these to keep the three SDKs aligned, so a change
# there has to run this workflow or the drift goes unnoticed.
- 'python/FlightRadarAPI/**'
- '.github/workflows/go-package.yml'
pull_request:
paths:
- 'go/**'
- 'python/FlightRadarAPI/**'
- '.github/workflows/go-package.yml'
schedule:
- cron: '0 0 */7 * *'
workflow_dispatch:

defaults:
run:
working-directory: ./go

jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
go-version: ['1.25.x', '1.26.x']
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- name: Set up Go ${{ matrix.go-version }}
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
with:
go-version: ${{ matrix.go-version }}
cache-dependency-path: go/go.sum
- name: Download dependencies
run: |
go mod download
go mod verify
- name: Check go.mod is tidy
run: |
go mod tidy
git diff --exit-code -- go.mod go.sum
- name: Lint
run: make lint
- name: Static analysis
if: matrix.go-version == '1.26.x'
run: make lint-strict
- name: Offline tests (PR gate)
# Coverage threshold lives in the Makefile ($(COVERAGE_MIN)); raise it
# there and it applies here too.
run: make test-coverage
- name: Race detector
run: make test-race
- name: Integration tests (live FR24)
uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3
with:
timeout_minutes: 10
max_attempts: 3
command: cd go && make test-integration
continue-on-error: ${{ github.event_name == 'push' }}
- name: Vulnerability scan (shipped dependencies)
if: matrix.go-version == '1.26.x'
run: make security
- name: Verify the package builds as a dependency
run: |
go build ./...
mkdir -p /tmp/consumer && cd /tmp/consumer
go mod init consumer
go mod edit -require=github.com/JeanExtreme002/FlightRadarAPI/go@v0.0.0
go mod edit -replace=github.com/JeanExtreme002/FlightRadarAPI/go=$GITHUB_WORKSPACE/go
cat > main.go <<'EOF'
package main

import (
"fmt"

"github.com/JeanExtreme002/FlightRadarAPI/go/flightradarapi"
)

func main() {
client := flightradarapi.New()
fmt.Println("Install OK:", len(client.GetZones()), "zones")
}
EOF
go mod tidy
go run .
34 changes: 28 additions & 6 deletions .github/workflows/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,46 @@ jobs:
const paths = files.map((f) => f.filename);
core.info(`Changed files (${paths.length}):\n ` + paths.join("\n "));

const goPackage = "go/flightradarapi/";

// Go keeps its tests inside the package, where python/ and nodejs/
// keep them in a sibling tests/ directory. Told apart here so a
// test-only PR gets "tests" and not "api".
const isGoTest = (f) =>
f.startsWith(goPackage) &&
(/_test\.go$/.test(f) || f.startsWith(goPackage + "testdata/"));

const isCore = (f) =>
f === "python/FlightRadarAPI/core.py" ||
f === "python/FlightRadarAPI/request.py" ||
f === "nodejs/FlightRadarAPI/core.js" ||
f === "nodejs/FlightRadarAPI/request.js";
f === "nodejs/FlightRadarAPI/request.js" ||
f === "go/flightradarapi/core.go" ||
f === "go/flightradarapi/request.go" ||
// The Go port owns the cookie jar its siblings get from their
// HTTP client, so it belongs to the same layer as request.go.
f === "go/flightradarapi/cookies.go";

const isEntities = (f) =>
/^(python|nodejs)\/FlightRadarAPI\/entities\//.test(f);
/^(python|nodejs)\/FlightRadarAPI\/entities\//.test(f) ||
// One package per directory in Go: the entities are files.
/^go\/flightradarapi\/(entity|airport|flight)\.go$/.test(f);

const isInPackage = (f) =>
/^(python|nodejs)\/FlightRadarAPI\//.test(f);
/^(python|nodejs)\/FlightRadarAPI\//.test(f) ||
(f.startsWith(goPackage) && !isGoTest(f));

const isTests = (f) => /^(python|nodejs)\/tests\//.test(f);
const isTests = (f) =>
/^(python|nodejs)\/tests\//.test(f) || isGoTest(f);

const isCi = (f) => f.startsWith(".github/");

const isDeps = (f) =>
f === "python/pyproject.toml" ||
f === "nodejs/package.json" ||
f === "nodejs/package-lock.json";
f === "nodejs/package-lock.json" ||
f === "go/go.mod" ||
f === "go/go.sum";

const isBuild = (f) =>
/(^|\/)Makefile$/.test(f) ||
Expand All @@ -69,6 +89,7 @@ jobs:

const isPython = (f) => f.startsWith("python/");
const isNode = (f) => f.startsWith("nodejs/");
const isGo = (f) => f.startsWith("go/");

const desired = new Set();

Expand All @@ -83,6 +104,7 @@ jobs:
if (isDocs(f)) desired.add("docs");
if (isPython(f)) desired.add("pkg:python");
if (isNode(f)) desired.add("pkg:node");
if (isGo(f)) desired.add("pkg:go");
}

// Dependabot PRs (we only enable Dependabot for security advisories).
Expand Down Expand Up @@ -119,7 +141,7 @@ jobs:
"api:core", "api:entities", "api", "tests",
"ci", "build", "feature", "docs",
"revert", "performance", "bug",
"deps", "security", "pkg:python", "pkg:node",
"deps", "security", "pkg:python", "pkg:node", "pkg:go",
]);

const { data: currentLabels } = await github.rest.issues.listLabelsOnIssue({
Expand Down
38 changes: 35 additions & 3 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,19 @@ jobs:
run: |
py_version=$(grep -oP '__version__\s*=\s*"\K[^"]+' python/FlightRadarAPI/__init__.py)
npm_version=$(node -p "require('./nodejs/package.json').version")
go_version=$(grep -oP 'const Version = "\K[^"]+' go/flightradarapi/doc.go)
echo "python=$py_version" >> "$GITHUB_OUTPUT"
echo "npm=$npm_version" >> "$GITHUB_OUTPUT"
echo "Python: $py_version | npm: $npm_version"
echo "go=$go_version" >> "$GITHUB_OUTPUT"
echo "Python: $py_version | npm: $npm_version | Go: $go_version"

- name: Check versions are in sync
# The Go module is published by the release tag itself, so it has no
# upload job below — only this check keeps its version honest.
run: |
if [ "${{ steps.versions.outputs.python }}" != "${{ steps.versions.outputs.npm }}" ]; then
echo "::error::Version mismatch: python=${{ steps.versions.outputs.python }} npm=${{ steps.versions.outputs.npm }}"
if [ "${{ steps.versions.outputs.python }}" != "${{ steps.versions.outputs.npm }}" ] \
|| [ "${{ steps.versions.outputs.python }}" != "${{ steps.versions.outputs.go }}" ]; then
echo "::error::Version mismatch: python=${{ steps.versions.outputs.python }} npm=${{ steps.versions.outputs.npm }} go=${{ steps.versions.outputs.go }}"
exit 1
fi

Expand All @@ -53,6 +58,33 @@ jobs:
exit 1
fi

tag-go-module:
needs: verify-versions
if: github.event_name == 'release'
runs-on: ubuntu-latest
permissions:
contents: write # Required to push the module tag
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
fetch-depth: 0

# A module in a subdirectory is released by a tag carrying that prefix, so
# `go get .../go@latest` sees nothing without this.
- name: Tag the Go module
env:
TAG: ${{ github.event.release.tag_name }}
run: |
version="${TAG#v}"
module_tag="go/v${version}"
if git rev-parse -q --verify "refs/tags/${module_tag}" >/dev/null; then
echo "${module_tag} already exists"
exit 0
fi
git tag "${module_tag}" "${TAG}"
git push origin "${module_tag}"
echo "Pushed ${module_tag}"

publish-pypi:
needs: verify-versions
if: github.event_name == 'release' || inputs.target == 'both' || inputs.target == 'pypi'
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ coverage.xml
# Node.js
node_modules/

# Go
coverage.out

# Version managers (local dev only)
.tool-versions
.python-version
Expand Down
39 changes: 29 additions & 10 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Contributing to FlightRadarAPI

Thanks for your interest. This repo ships two SDKs in parallel — Python and
Node.js — that must stay behavior-aligned, so most non-trivial changes touch
both sides.
Thanks for your interest. This repo ships three SDKs in parallel — Python,
Node.js and Go — that must stay behavior-aligned, so most non-trivial changes
touch every side.

## Development setup

Expand All @@ -25,25 +25,37 @@ make lint # eslint
make test-types # tsd
```

## Keeping Python and Node aligned
### Go
```bash
cd go
make deps
make test # offline suite (the PR gate)
make test-integration # live FR24 suite
make lint # gofmt + go vet
make lint-strict # adds staticcheck
```

When you change behavior, change it in both SDKs in the same PR unless there
## Keeping the SDKs aligned

When you change behavior, change it in every SDK in the same PR unless there
is a documented reason not to. Common targets that must stay in sync:

- Error taxonomy (`AirportNotFoundError`, `LoginError`, `CloudflareError`,
`FlightRadarError`).
- `RetryPolicy` semantics (which exceptions are transient, backoff math).
- Cloudflare detection rules.
- The public surface — `FlightRadar24API` methods, the `Countries` enum,
`FlightTrackerConfig` fields, and the `Entity` / `Airport` / `Flight`
attributes consumers depend on.
- The public surface — `FlightRadar24API` methods (`Client` in Go), the
`Countries` enum (`Country` constants in Go), `FlightTrackerConfig` fields,
and the `Entity` / `Airport` / `Flight` attributes consumers depend on.
`docs/go.md` documents where the Go surface deliberately differs.

## Style

- Python: flake8 + mypy.
- Node: eslint + tsd.
- Go: gofmt + go vet + staticcheck.
- Comments must explain **why**, not **what**. The codebase has a few exemplars in
`request.py`/`request.js` — read those before adding new comments.
`request.py`/`request.js`/`request.go` — read those before adding new comments.

## Commits and PRs

Expand All @@ -53,10 +65,17 @@ is a documented reason not to. Common targets that must stay in sync:

## Releases

Before publishing a new release, the version **must be bumped**. The version lives in two places:
Before publishing a new release, the version **must be bumped**. The version lives in three places:

- `python/FlightRadarAPI/__init__.py` (`__version__`)
- `nodejs/package.json` (`version`)
- `go/flightradarapi/doc.go` (`Version`)

The Go module needs no registry upload — the tag *is* the release. Because it
lives in a subdirectory, the Go toolchain only sees tags carrying that prefix,
so the `tag-go-module` job of `publish.yml` pushes `go/v1.6.0` alongside the
release tag. Nothing to do by hand; if that job is skipped, `go get
.../go@latest` finds no release and callers fall back to a pseudo-version.

## Reporting bugs and asking questions

Expand Down
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
# FlightRadarAPI
Unofficial SDK for [FlightRadar24](https://www.flightradar24.com/) for Python 3 and Node.js.
Unofficial SDK for [FlightRadar24](https://www.flightradar24.com/) for Python 3, Node.js and Go.

This SDK should only be used for your own educational purposes. If you are interested in accessing Flightradar24 data commercially, please contact business@fr24.com. See more information at [Flightradar24's terms and conditions](https://www.flightradar24.com/terms-and-conditions).

**Official FR24 API**: https://fr24api.flightradar24.com/

[![Python Package](https://github.com/JeanExtreme002/FlightRadarAPI/workflows/Python%20Package/badge.svg)](https://github.com/JeanExtreme002/FlightRadarAPI/actions)
[![Pypi](https://img.shields.io/pypi/v/FlightRadarAPI?logo=pypi)](https://pypi.org/project/FlightRadarAPI/)
[![Node.js Package](https://github.com/JeanExtreme002/FlightRadarAPI/actions/workflows/node-package.yml/badge.svg)](https://github.com/JeanExtreme002/FlightRadarAPI/actions)
[![Go Package](https://github.com/JeanExtreme002/FlightRadarAPI/actions/workflows/go-package.yml/badge.svg)](https://github.com/JeanExtreme002/FlightRadarAPI/actions)
[![License](https://img.shields.io/pypi/l/FlightRadarAPI)](https://github.com/JeanExtreme002/FlightRadarAPI)
[![Pypi](https://img.shields.io/pypi/v/FlightRadarAPI?logo=pypi)](https://pypi.org/project/FlightRadarAPI/)
[![Python Version](https://img.shields.io/badge/python-3.10+-8A2BE2)](https://pypi.org/project/FlightRadarAPI/)
[![Npm](https://img.shields.io/npm/v/flightradarapi?logo=npm&color=red)](https://www.npmjs.com/package/flightradarapi)
[![Node Version](https://img.shields.io/badge/node-18.17+-339933)](https://www.npmjs.com/package/flightradarapi)
[![Go Reference](https://pkg.go.dev/badge/github.com/JeanExtreme002/FlightRadarAPI/go.svg)](https://pkg.go.dev/github.com/JeanExtreme002/FlightRadarAPI/go/flightradarapi)
[![Go Version](https://img.shields.io/badge/go-1.25+-00ADD8)](https://go.dev/dl/)
[![Downloads](https://static.pepy.tech/personalized-badge/flightradarapi?period=total&units=international_system&left_color=grey&right_color=orange&left_text=downloads)](https://pypi.org/project/FlightRadarAPI/)
[![Frequency](https://img.shields.io/pypi/dm/flightradarapi?style=flat&label=frequency)](https://pypi.org/project/FlightRadarAPI/)

Expand All @@ -24,8 +29,13 @@ pip install FlightRadarAPI
npm install flightradarapi
```

**For Go:**
```
go get github.com/JeanExtreme002/FlightRadarAPI/go@latest
```

## Documentation
Explore the docs of FlightRadarAPI package, for Python or NodeJS, through [FlightRadarAPI Documentation](https://JeanExtreme002.github.io/FlightRadarAPI/) page.
Explore the docs of FlightRadarAPI package, for Python, NodeJS or Go, through [FlightRadarAPI Documentation](https://JeanExtreme002.github.io/FlightRadarAPI/) page.

## Project resources
**Contributing**: [`CONTRIBUTING.md`](CONTRIBUTING.md)<br>
Expand Down
Loading
Loading