Paste a trivia question, get the correct answer instantly.
OpenTDBLookup is a small Windows desktop app that maintains a local cache of every verified question on Open Trivia DB and looks up the correct answer the moment you paste a question. It was built because the ChillZone Discord trivia minigame uses OpenTDB questions verbatim and answering them by hand is suspenseful, slow, and frequently wrong.
- Instant lookup. Paste a question, see the correct answer with a 100ms-debounced search.
- Local cache. First launch performs a full scrape (a few minutes); subsequent launches load instantly.
- Weekly auto-refresh. Counts are checked at most every 7 days; only changed categories are re-fetched.
- Optional clipboard watcher. When enabled, pasting a recognized question into any other app auto-replaces the clipboard with the correct answer.
- Tray icon. Optional minimize-to-tray with quick toggle of the clipboard watcher.
- Hotkeys.
Ctrl+Lfocus input,Ctrl+Entercopy answer,Ctrl+Rrefresh,Escclear. - Dark theme by default.
- CLI:
OpenTDBLookup.exe --version(or-v) prints the binary's version and exits, useful when filing bug reports or scripting against a released artifact.
Two builds are published with each release:
OpenTDBLookup-vX.Y.Z-win-x64.exe(slim, ~16 MB) - default. Requires the .NET 10 runtime on the target machine.OpenTDBLookup-vX.Y.Z-win-x64-selfcontained.exe(portable, ~50 MB) - bundles the runtime. Use this when you can't or won't install .NET 10 on the target machine.
Steps:
- Download whichever
.exematches your situation from the Releases page. - Drop it anywhere on disk and double-click to run. No installer required.
- The first launch performs the initial scrape (~5-10 minutes; the OpenTDB API enforces a 5-second gap between requests).
- Once the dialog closes, paste a question into the input box. The correct answer appears below.
The cache lives in questions.json next to the executable. Logs land in logs/opentdb-*.log.
OpenTDBLookup talks to the public Open Trivia DB API:
| Purpose | URL |
|---|---|
| List categories | https://opentdb.com/api_category.php |
| Verified counts per category | https://opentdb.com/api_count_global.php |
| Per-category-difficulty count | https://opentdb.com/api_count.php?category=X |
| Fetch questions | https://opentdb.com/api.php?amount=N&category=X&difficulty=Y&token=T&encode=base64 |
| Request session token | https://opentdb.com/api_token.php?command=request |
| Reset session token | https://opentdb.com/api_token.php?command=reset&token=T |
Response codes: 0 success, 1 no results, 2 invalid parameter, 3 token not found, 4 token empty (re-request token), 5 rate limited (one IP per 5 seconds).
OpenTDBLookup always passes encode=base64 and decodes locally to avoid HTML-entity decode bugs. The API only returns verified questions.
Prerequisites:
- .NET 10 SDK
- Windows 10 / 11 (Avalonia targets
win-x64) - PowerShell 7+ (for the signing script)
git clone <repo-url>
cd OpenTDBLookup
dotnet restore
dotnet build
dotnet testTwo publish profiles are supported.
Slim - framework-dependent, requires .NET 10 on the target. Smallest binary, fastest startup. Use this for personal use and CI builds where you control the runtime:
dotnet publish OpenTDBLookup -c Release -r win-x64 --no-self-contained `
-p:PublishSingleFile=true `
-o ./publish/slimPortable - self-contained, bundles the .NET runtime. Larger binary; runs anywhere x64 Windows runs. Use this when you ship to machines you don't control:
dotnet publish OpenTDBLookup -c Release -r win-x64 --self-contained `
-p:PublishSingleFile=true `
-p:EnableCompressionInSingleFile=true `
-p:IncludeNativeLibrariesForSelfExtract=true `
-o ./publish/portablePublishReadyToRun is intentionally not used - it adds ~40 MB for ~200 ms of cold-start savings, which is the wrong trade for a desktop tool you click once per session.
Note: Public releases are currently unsigned because the project does not yet hold a public code-signing certificate. Windows SmartScreen will show an "unrecognized publisher" warning the first time you run a release binary. Verify integrity via the Sigstore-backed build provenance attestation:
gh attestation verify <binary> --owner Synertry(see Security) until a real cert lands.
The repo ships a single signing script at scripts/Sign-Binary.ps1 with two modes. The CI release pipeline already integrates with it; the moment the CODESIGN_PFX_B64 + CODESIGN_PASSWORD repo secrets are configured, signing turns on with no code change.
Place a code-signing cert in your user cert store. Three ways to point the script at it, in order of convenience:
# 1. Pass the thumbprint inline.
pwsh ./scripts/Sign-Binary.ps1 -Path ./publish/slim/OpenTDBLookup.exe `
-Thumbprint <sha1-thumbprint>
# 2. .env at the repo root (gitignored). Copy .env.example to .env and edit.
# The script auto-loads it on every invocation.
pwsh ./scripts/Sign-Binary.ps1 -Path ./publish/slim/OpenTDBLookup.exe
# 3. Persistent user-scope env var.
[Environment]::SetEnvironmentVariable('OPENTDB_CODESIGN_THUMBPRINT', '<sha1-thumbprint>', 'User')
pwsh ./scripts/Sign-Binary.ps1 -Path ./publish/slim/OpenTDBLookup.exeIf you already have your own personal signing wrapper (e.g. a Sign-File
alias around signtool), feel free to use that directly - the included
script is just a default for people who don't.
When the CODESIGN_PFX_B64 + CODESIGN_PASSWORD repo secrets exist, the Release workflow signs both built binaries before attaching them to the GitHub Release. When the secrets are absent (current default), the sign steps are skipped and the workflow publishes unsigned binaries plus SHA256SUMS.txt.
Secret contract:
CODESIGN_PFX_B64- base64-encoded PFX byte streamCODESIGN_PASSWORD- PFX password
Both are mapped to OPENTDB_CODESIGN_PFX_B64 / OPENTDB_CODESIGN_PASSWORD and consumed by the same script. The PFX is imported into the runner's cert store, signed by thumbprint, then removed; the temp file and cert are cleaned up in finally.
OpenTDBLookup/Assets/logo.ico is used both as the executable icon and the tray icon. Replace it with your own multi-resolution .ico to rebrand.
questions.jsoncorrupt? Delete it and relaunch; the app will perform a fresh scrape.- Clipboard watcher feels slow. Polling is intentionally throttled to 250 ms to avoid hammering the OS clipboard.
4 errors(or similar) in the log during scrape. OpenTDB's session-token endpoint is occasionally flaky; the app retries automatically.- Logs.
logs/opentdb-YYYY-MM-DD.log, daily rolling, 7 days retained.
This is intentionally a small app. The following are not implemented and will be politely declined as feature requests:
- Authentication / login
- Telemetry / analytics
- Auto-update
- Internationalization
- Mobile / Linux / macOS publish targets
MIT - see LICENSE.
- Open Trivia DB - the data source. Thanks to the community for verifying questions.
- Avalonia and FluentAvalonia for the UI stack.