Thanks for your interest in contributing!
- Fork the repository
- Create a branch for your feature or fix
- Test your changes against both providers (datanodes.to and fuckingfast.co)
- Run the verification suite (below) — it is fast and catches the regressions that actually happened
- Submit a pull request describing what changed and why
Looking for something to pick up:
- good first issue — scoped small, with the files to touch and the acceptance criteria already written out
- help wanted — everything open to outside contributors, including the larger items
Each issue says up front whether it needs Windows. Several do not — documentation, CI and dependency
work all run anywhere, and the no-Chrome test suite stubs the browser and the network at the
moon_extract boundary so it runs on any OS.
Comment on an issue before you start, so two people don't write the same patch.
Two front-ends, one engine, one extraction layer.
moon_bridge.py loopback HTTP + token, launches Edge/Chrome --app, OS dialogs
web/ index.html · styles.css · app.js the GUI
moon_engine.py the engine with no GUI: start/stop/snapshot
moon_extract.py datanodes (real Chrome over CDP) · fuckingfast (curl_cffi)
BrowserGate: the launch, deferred until a datanodes link
moon_download.py download_file · Telemetry · ProxyPool
moon_cli.py argparse CLI, same engine, same extraction layer
Layers inside the engine:
- Extraction —
moon_extract.py, shared by all three front-ends - Download engine —
moon_download.py, shared by the GUI engine and CLI - Telemetry —
moon_download.py, 1 Hz snapshots,.txt+.jsonoutput - GUI —
web/over the loopback API, hosted bymoon_bridge.py
- Shared logic goes in
moon_extract.pyormoon_download.py, not copy-pasted between front-ends. If a change touches extraction, the Chrome lifecycle, downloading, telemetry or proxy rotation, it must land in one place and be visible from bothmoon_engine.pyandmoon_cli.py. - Never open a browser before you know you need one. Ask
BrowserGate.get()inside the provider branch that requires it. A launch at the top of a run is the bugtests/test_no_chrome.pyexists to prevent. - No new dependencies without a strong reason. The stack is deliberately small:
aiohttp,playwright,curl_cffi. - English only. Code, comments, log lines, dialog titles and docs. The GUI's EN/IT
dictionary in
web/app.jsis the one exception — that is the runtime language switch.
pytest tests/ -q # no browser for fuckingfast, exactly one for datanodes
python integration_http.py # browser -> loopback HTTP -> engine
python integration_web.py # pywebview path
python render_gui.py out/ # GUI renders + overflow audittests/test_no_chrome.py stubs Chrome and the network at the moon_extract boundary, so it
needs no browser, no display and no Playwright install.
Live testing: at least 10 links per provider, including one guaranteed-dead one so dead-link detection is exercised, and one session long enough (40+ files) to hit the concurrency paths.
Use the bug report template
and attach moontech_*.log (GUI) or moontech_cli_*.log (CLI). MOON_DEBUG=1 adds
extraction-level tracing.
- 4-space indentation, no tabs.
- f-strings over
%or.format(). - Top-level constants uppercase (
RECV_CHUNK,WRITE_BUF,DN_LANES). - No blanket
except:— name the exception, orexcept Exception:with a comment when the swallow is deliberate. - Comments explain why, not what. The gotchas in
moon_extract.pyare the model: each one states a specific fact that cost a debugging session. - Match the surrounding style. Read the nearby code first.