Skip to content

feat: implement Next Steam Achievement Picker feature — Completionist#2

Merged
ImBIOS merged 5 commits intomasterfrom
001-build-an-application
Sep 21, 2025
Merged

feat: implement Next Steam Achievement Picker feature — Completionist#2
ImBIOS merged 5 commits intomasterfrom
001-build-an-application

Conversation

@ImBIOS
Copy link
Copy Markdown
Owner

@ImBIOS ImBIOS commented Sep 21, 2025

Summary

Implements environment-based config loading, fixes achievement progress retrieval (0% bug), improves game/achievement selection logic, and adds GitHub Actions CI.

What & Why

  • Env-based config (dev-friendly): If present, .env is read and used to populate steamId and steamApiKey automatically for development. Values are persisted if DB is empty or fields are missing. This removes first-run friction.
  • Fix 0% achievements: For users with custom vanity profile names, the Steam Web API calls were made with the vanity string instead of a 64-bit SteamID, often yielding empty/0% results. We now resolve vanity IDs via ISteamUser/ResolveVanityURL before fetching data.
  • Skip games with nothing left to do: The picker now iterates candidate games and selects from the first game with unachieved achievements. Previously, selecting a game with all achievements done returned no pick.
  • CI: Adds a GitHub Actions workflow to lint, test, and type-check on PRs and pushes.

Changes

  • Config

    • Load .env if present via src/lib/env.ts.
    • Hydrate steamId and steamApiKey from env on first read when DB is empty/missing values, then persist.
    • Env keys supported: STEAM_ID, STEAMID64, STEAM_ID64, STEAM_STEAMID, STEAM_API_KEY, STEAM_WEB_API_KEY, STEAMKEY, OPENROUTER_API_KEY.
  • Steam service

    • Add resolveVanityUrl(apiKey, vanity) using ISteamUser/ResolveVanityURL.
    • Before calling owned games or achievements, if steamId is not 17 digits and API key exists, resolve vanity → use the resolved 64-bit ID.
  • Picker

    • Iterate candidate games; skip games where all achievements are done.
    • In --random mode, shuffle candidate games (Fisher–Yates) before iterating.
    • Continue to record pick history unchanged.
  • CI

    • .github/workflows/ci.yml: pnpm install, eslint, vitest (--run), and type-check.

Tests

  • Unit
    • Config: env fallback and persistence.
    • Picker: skipping games with no unachieved achievements, vanity ID resolution.
  • Contract/Integration
    • Existing suites cover CLI rendering and happy path flows.

Run locally:

pnpm install
pnpm lint
pnpm test -- --run
pnpm build

How to verify manually

  1. Create .env:
echo "STEAM_ID=7656119xxxxxxxxxx" >> .env
echo "STEAM_API_KEY=your_key_here" >> .env
  1. Try the picker:
pnpm exec tsx src/cli/index.ts pick --random
  1. Validate that an achievement is suggested for a game with remaining achievements. For games fully completed, picker should automatically consider the next game.

Performance considerations

  • Worst-case, the picker may fetch achievements for multiple candidate games until it finds one with unachieved items. For large libraries this adds API calls. Empirically acceptable for CLI usage; if needed, we can cache per-game completion state and/or bound the scan (follow-up).

Backward compatibility

  • .env is optional; nesta config continues to work. No breaking changes to CLI flags or DB schema.

Follow-ups (optional)

  • Cache per-game completion state to reduce repeated API calls.
  • Add a --max-scan N guard and a --next-game flag to quickly hop games.
  • Telemetry for slow API responses.

Checklist

  • Adds/updates tests
  • Lints and builds cleanly
  • CI green
  • No breaking CLI changes

Keywords: Completionist

…; ci: add GitHub Actions; tests: add unit tests
feat: env-based config loading, picker skip logic, vanity URL resolve; ci: add GitHub Actions; tests: add unit tests
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Sep 21, 2025

⚠️ No Changeset found

Latest commit: 1b28c76

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@ImBIOS ImBIOS changed the title feat: env-based config loading, picker skip logic, vanity URL resolve; ci: add GitHub Actions; tests: add unit tests feat: NeStA-Picker MVP v1 Sep 21, 2025
@ImBIOS ImBIOS changed the title feat: NeStA-Picker MVP v1 feat: implement Next Steam Achievement Picker feature Sep 21, 2025
- add new schemas for user, game, and achievement; enhance Steam service with schema validation
- improve config handling with Sury
- add tests for history and pick commands
- clean up unused imports and comments.
@ImBIOS ImBIOS changed the title feat: implement Next Steam Achievement Picker feature feat: implement Next Steam Achievement Picker feature — Completionist Sep 21, 2025
@ImBIOS ImBIOS requested a review from Copilot September 21, 2025 12:44
@ImBIOS ImBIOS merged commit 717e275 into master Sep 21, 2025
1 of 3 checks passed
@ImBIOS ImBIOS deleted the 001-build-an-application branch September 21, 2025 12:45
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements a comprehensive CLI-based Next Steam Achievement Picker feature with environment-based configuration, Steam API integration, and intelligent achievement selection logic.

  • Adds environment-based config loading with .env support for development
  • Fixes achievement progress retrieval for vanity profile URLs by resolving them to 64-bit SteamIDs
  • Improves game/achievement selection to skip completed games and find next actionable targets
  • Adds comprehensive testing suite and GitHub Actions CI workflow

Reviewed Changes

Copilot reviewed 56 out of 59 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
vitest.config.ts Test framework configuration with setup files
Multiple test files Comprehensive unit, integration and contract tests for services and CLI
src/services/steam.ts Steam Web API service with vanity URL resolution and achievement merging
src/services/picker.ts Core picker logic with game iteration and vanity ID support
src/services/config.ts Configuration service with environment variable fallback
src/lib/env.ts Environment file loader for development configuration
src/cli/ React-based CLI components using Ink framework
.github/workflows/ci.yml GitHub Actions workflow for CI/CD

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +19 to +23
// const status = res.statusCode ?? 0;
// if (status < 200 || status >= 300) {
// reject(new Error(`HTTP ${status} for ${url}`));
// return;
// }
Copy link

Copilot AI Sep 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The commented-out status code validation should either be removed entirely or implemented properly. Leaving commented code reduces maintainability and suggests incomplete error handling.

Suggested change
// const status = res.statusCode ?? 0;
// if (status < 200 || status >= 300) {
// reject(new Error(`HTTP ${status} for ${url}`));
// return;
// }
const status = res.statusCode ?? 0;
if (status < 200 || status >= 300) {
reject(new Error(`HTTP ${status} for ${url}`));
return;
}

Copilot uses AI. Check for mistakes.
apiKey,
)}&appid=${appId}`;

// http://api.steampowered.com/ISteamUserStats/GetPlayerAchievements/v0001/?appid=440&key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&steamid=76561197972495328
Copy link

Copilot AI Sep 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commented example URL with placeholder API key should be removed as it doesn't add value and clutters the code.

Suggested change
// http://api.steampowered.com/ISteamUserStats/GetPlayerAchievements/v0001/?appid=440&key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&steamid=76561197972495328

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,91 @@
// Ensure React reconciler sees a proper environment
process.env.NODE_ENV = process.env.NODE_ENV || 'test';
// React import not needed; components are created in tests
Copy link

Copilot AI Sep 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The comment on line 3 is unclear and potentially outdated. Consider clarifying why React import is not needed or remove the comment if it's no longer relevant.

Suggested change
// React import not needed; components are created in tests

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants