koraktor/steam-condenser
Steam Condenser is a PHP library for working with Steam: query game servers via A2S, access Steam Community profiles and data, use the Steam Web API, and convert Steam IDs. It offers a simple object-oriented API for building Steam apps and bots.
Architecture fit. Steam Condenser is a PHP client library for three distinct surfaces: (1) Valve's Steam Web API, (2) Steam Community profile/group pages (historically via XML scraping plus OpenID), and (3) the UDP game-server protocols — A2S_INFO/A2S_PLAYER/A2S_RULES for Source and GoldSrc, the legacy master-server discovery protocol, and RCON. Architecturally it is a synchronous, socket-oriented library with its own class hierarchy (SteamSocket, GameServer, SourceServer, GoldSrcServer, SteamId, SteamCommunity, WebApi) rather than a Laravel-idiomatic package: no service provider, no config publishing, no facade, no contracts. It answers "how do I talk to a game server," not "how do I do that safely inside a request lifecycle." For a Laravel product the useful overlap is narrow but real: read-only server status (map, player count, max players, rules), and optionally RCON for admin actions. Everything Community-scraping-related should be treated as legacy and replaced by Web API calls.
Integration feasibility. Feasible with a fork, not as a straight Composer dependency. The last release is March 2015, the repository is archived, and there are zero Composer dependents — meaning almost no one has validated it against PHP 7/8 or modern Steam behaviour. Concretely, expect to fix: PHP 4-style constructors and other constructs removed in PHP 8.0; mcrypt-era assumptions removed in 7.2; dynamic-property deprecations in 8.2; and, more importantly, protocol drift — since 2020 Source servers commonly reply to A2S_INFO with an S2C_CHALLENGE that must be echoed back, which a 2015 client does not do, so naive getServerInfo() calls will time out on many modern servers. The legacy master-server query endpoint is also no longer a reliable discovery path. The Community XML endpoints the library targets have largely been superseded by the Web API and are rate-limited and privacy-gated. Budget a timeboxed spike (1–2 engineer-days) that proves A2S_INFO against a handful of real servers on your target PHP version before committing.
Technical risk. High and concentrated in three places. Protocol risk: challenge handling, master-server decommissioning, and Community scraping are all broken-by-default areas. Runtime risk: blocking UDP sockets in a PHP-FPM request will stall workers on unreachable hosts; the library's timeouts and exception surface are not designed for graceful degradation. Security risk: RCON credentials and Steam API keys flow through an unmaintained codebase with no CVE process; RCON over plaintext and any credential logging are on you. Licensing is the one low-risk dimension — BSD-3-Clause is permissive and fork-friendly, so vendoring is legally clean provided you retain notices. Counterweight: the score (1.665) and opportunity (3.02) confirm this is a low-maturity, low-adoption artifact; treat it as reference source code, not a dependency.
Key questions.
Stack fit. The library is framework-agnostic and therefore integratable but not integrated. Wrap it; do not sprinkle it. Define a narrow application-owned port — e.g. GameServerQuery (info(), players(), rules()) and ServerAdmin (rcon()), with DTOs (ServerStatus, PlayerList) at the boundary. Nothing above the adapter should import a SteamCondenser\* class. That single decision converts this from a scary dependency into a replaceable one and lets you swap implementations later without touching controllers or jobs.
Compatibility. Pin the fork to your PHP minor version and lock it with a path/VCS repository entry rather than Packagist. Verify the 1.0 line's transitive dependency on symfony/event-dispatcher (check composer.json in the tag you fork) — if it pins a 1.x Symfony, either upgrade it to a current Symfony or strip the event dispatcher entirely, since you likely don't need the observer machinery. Add a PHP 8 compatibility pass (constructors, each/create_function, dynamic properties), then a small protocol patch for S2C_CHALLENGE. Back both with a characterization test suite that replays captured UDP packets and HTTP fixtures — you cannot rely on live Steam endpoints in CI.
Migration path. Four steps. (1) Spike: fork into an internal namespace, get A2S_INFO working against real servers on your PHP version. (2) Isolate: introduce the port/DTO layer and a SteamCondenserAdapter behind it; all callers depend only on the interface. (3) Replace weakened paths: swap Community scraping for ISteamUser/GetPlayerSummaries, IPlayerService/* and ISteamUserStats/*; swap master-server discovery for IGameServersService/ISteamApps/GetServersAtAddress or a curated server list you own. (4) Exit option: if the fork becomes a burden, reimplement the A2S subset directly (it is a small binary protocol) or route queries through GameDig/a query microservice — the adapter boundary makes this a contained change.
Sequencing. Ship read-only server status first behind a queue-driven poller, on a feature flag, for a small server set. Add the Web API profile lookups second (low risk, high value, no UDP). Defer RCON to last, and only with an explicit decision record on credential handling, IP allowlisting, and audit logging. Keep the fork on your own release cadence with a FORKED_FROM note and upstream commit hash.
Maintenance. The upstream is archived; you inherit 100% of maintenance, including future protocol drift. Realistically that is a standing tax of a few engineer-days per year plus a re-verification when Valve changes the A2S handshake again. Mitigate by keeping the fork small — delete unused subsystems (Community scraping, master server, achievement parsing) so the surface you own is a few hundred lines of UDP query and RCON code you can reason about. Name an owner; an unowned fork is the worst outcome.
Support. No maintainer, no issue triage, and 210 stars' worth of Stack Overflow answers that predate the 2020 protocol change and are actively misleading. Your support story is internal documentation plus captured packet fixtures. Do not let the team's mental model of "how Steam queries work" be sourced from 2015 blog posts.
Scaling. The library is synchronous and blocking, so scale it with Laravel's queue, not with PHP-FPM concurrency. One job per server (or a small batch per job), aggressive short-TTL caching (30–120s for player counts), timeouts of 1–2s, and a circuit breaker that stops polling servers that repeatedly fail. Watch UDP egress and file-descriptor exhaustion under fan-out. Steam Web API calls need their own rate limiter and a key with headroom; Community-page scraping at volume is a fast route to an IP-level block, which is another reason to eliminate it.
Failure modes. Expect: silent timeouts returning null or stale data (design DTOs so "unknown" is a first-class state, never a 0 player count); malformed or truncated packet parsing throwing opaque exceptions; challenge-response failures being indistinguishable from a dead server unless you log the raw response; blocking calls wedging queue workers; and fatals from PHP-version drift in the fork after a base-image upgrade. Add structured logging of server address, protocol, round-trip time and outcome, plus a metric for query success rate per server — that is how you find out the protocol broke before users do.
Ramp-up. A mid-level Laravel engineer can be productive behind the adapter in under a day; understanding the UDP protocol and safely patching the fork is closer to one focused week, with the challenge-response handling and test fixtures being the bulk of it. Front-load the spike and the fixtures so the knowledge is captured in code rather than in one person's head.
How can I help you explore Laravel packages today?