steam_api_client 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +140 -1
- data/README.md +39 -10
- data/lib/steam_api_client/errors/api_error.rb +29 -0
- data/lib/steam_api_client/errors/missing_api_token.rb +11 -0
- data/lib/steam_api_client/failure_handler.rb +3 -0
- data/lib/steam_api_client/request.rb +13 -6
- data/lib/steam_api_client/requestors/app_global_achievements.rb +3 -3
- data/lib/steam_api_client/requestors/app_news.rb +1 -1
- data/lib/steam_api_client/requestors/game_current_players.rb +1 -1
- data/lib/steam_api_client/requestors/player_achievements.rb +1 -1
- data/lib/steam_api_client/requestors/player_friends.rb +1 -1
- data/lib/steam_api_client/requestors/player_game_stats.rb +1 -1
- data/lib/steam_api_client/requestors/player_level.rb +1 -1
- data/lib/steam_api_client/requestors/player_owned_games.rb +1 -1
- data/lib/steam_api_client/requestors/player_recent_games.rb +1 -1
- data/lib/steam_api_client/requestors/player_steamid.rb +1 -1
- data/lib/steam_api_client/requestors/player_summaries.rb +1 -1
- data/lib/steam_api_client/response.rb +9 -1
- data/lib/steam_api_client/structs/app_global_achievements.rb +2 -2
- data/lib/steam_api_client/structs/app_new.rb +1 -1
- data/lib/steam_api_client/structs/player_achievements.rb +1 -1
- data/lib/steam_api_client/structs/player_friends.rb +1 -1
- data/lib/steam_api_client/structs/player_game_stats.rb +9 -1
- data/lib/steam_api_client/structs/player_owned_games.rb +11 -5
- data/lib/steam_api_client/structs/player_recent_games.rb +1 -1
- data/lib/steam_api_client/structs/player_summary.rb +15 -3
- data/lib/steam_api_client/structs/requests/get_app_details.rb +1 -7
- data/lib/steam_api_client/structs/requests/get_app_global_achievements.rb +1 -7
- data/lib/steam_api_client/structs/requests/get_app_news.rb +1 -7
- data/lib/steam_api_client/structs/requests/get_game_current_players.rb +1 -7
- data/lib/steam_api_client/structs/requests/get_player_achievements.rb +1 -7
- data/lib/steam_api_client/structs/requests/get_player_friends.rb +2 -8
- data/lib/steam_api_client/structs/requests/get_player_game_stats.rb +1 -7
- data/lib/steam_api_client/structs/requests/get_player_level.rb +1 -7
- data/lib/steam_api_client/structs/requests/get_player_owned_games.rb +1 -7
- data/lib/steam_api_client/structs/requests/get_player_recent_games.rb +1 -7
- data/lib/steam_api_client/structs/requests/get_player_steamid.rb +1 -7
- data/lib/steam_api_client/structs/requests/get_player_summaries.rb +1 -7
- data/lib/steam_api_client/structs/types.rb +13 -4
- data/lib/steam_api_client/version.rb +1 -1
- data/lib/steam_api_client.rb +2 -0
- metadata +7 -17
- data/.dockerignore +0 -21
- data/.pronto.yml +0 -12
- data/.reek.yml +0 -25
- data/.rspec +0 -4
- data/.ruby-version +0 -1
- data/.standard.yml +0 -3
- data/.tool-versions +0 -1
- data/CLAUDE.md +0 -52
- data/CODE_OF_CONDUCT.md +0 -84
- data/Gemfile +0 -34
- data/Gemfile.lock +0 -220
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d0c5680dd7c5f04050858684ffdedba92a405af03105ff67d5ab5f83786a9be3
|
|
4
|
+
data.tar.gz: 18dace5a415dbae06ab33d22af1d8d2f89a692c18b33d0fde7632e9608860476
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '008e3f030129225f200f25063f45bc1df84a0abc0aba381d1c2a919ef99f9cfebba87a908a14ebfc6652a0d9ea9dfdd76e8a7dc5299762df648b03423879dc07'
|
|
7
|
+
data.tar.gz: 886f409484facc5b94264c94a488e07d85bcf0514c84b81b9541f395da769d53d9407b8af83b2dc8cfcf45cb8bae81a5044a4d8542074c3940a3cec9ccfa2a71
|
data/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,148 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
1
7
|
## [Unreleased]
|
|
2
8
|
|
|
9
|
+
## [0.10.0] - 2026-10-23
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- `player_game_stats` exposes the game's stats: `playerstats.stats`, a list of `name`/`value` pairs. Values keep the Integer or Float Steam sends (#71).
|
|
14
|
+
- `PlayerSummary` exposes `realname`, `timecreated`, `loccountrycode`, `avatarhash`, `primaryclanid` (an Integer, like other SteamIDs) and `personastateflags`. They're `nil` when the profile doesn't make them public (#71).
|
|
15
|
+
- `SteamApiClient::Errors::HttpTooManyRequests` (429), `HttpBadGateway` (502) and `HttpServiceUnavailable` (503), so rate limits and outages can be retried selectively. 429 and 503 errors expose `#retry_after`, the seconds from the `Retry-After` header (`nil` when absent). All three are `ApiError`s, like before (#27).
|
|
16
|
+
- `SteamApiClient::Errors::MissingApiToken`, raised before any request when an endpoint needs an API token and the client has none (nil or empty). Previously the request was sent and Steam's HTML "key is missing" page came back as `HttpBadRequest` (#25).
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Every response struct, including the nested element structs (`PlayerSummary`, `AppNew`, friends, games and achievements), inherits from `SteamApiClient::Structs::Base`, so they all accept string keys and respond to `build_from_response` (#28).
|
|
21
|
+
- GET requests (every endpoint) no longer send an empty JSON body (`"{}"`) and `Content-Type: application/json` (#26).
|
|
22
|
+
- Missing or invalid request parameters raise `ArgumentError` instead of a bare `StandardError` (#25). `ArgumentError` is a `StandardError`, so existing `rescue StandardError` code keeps working.
|
|
23
|
+
- **Breaking:** every `retrieve` method takes keyword arguments (#24), so IDs can't be swapped by position. Defaults are unchanged.
|
|
24
|
+
|
|
25
|
+
| Before | After |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `player_summaries.retrieve([id])` | `player_summaries.retrieve(steamids: [id])` |
|
|
28
|
+
| `player_steamid.retrieve("name")` | `player_steamid.retrieve(vanityurl: "name")` |
|
|
29
|
+
| `player_friends.retrieve(id, "friend")` | `player_friends.retrieve(steamid: id, relationship: "friend")` |
|
|
30
|
+
| `player_level.retrieve(id)` | `player_level.retrieve(steamid: id)` |
|
|
31
|
+
| `player_owned_games.retrieve(id, include_appinfo: true)` | `player_owned_games.retrieve(steamid: id, include_appinfo: true)` |
|
|
32
|
+
| `player_recent_games.retrieve(id, 10)` | `player_recent_games.retrieve(steamid: id, count: 10)` |
|
|
33
|
+
| `player_achievements.retrieve(appid, id)` | `player_achievements.retrieve(appid: appid, steamid: id)` |
|
|
34
|
+
| `player_game_stats.retrieve(appid, id)` | `player_game_stats.retrieve(appid: appid, steamid: id)` |
|
|
35
|
+
| `app_news.retrieve(appid, 5, 500)` | `app_news.retrieve(appid: appid, count: 5, maxlength: 500)` |
|
|
36
|
+
| `app_global_achievements.retrieve(appid)` | `app_global_achievements.retrieve(appid: appid)` |
|
|
37
|
+
| `game_current_players.retrieve(appid)` | `game_current_players.retrieve(appid: appid)` |
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- `player_owned_games` failed on real public libraries: it required `playtime_windows_forever`, `playtime_mac_forever`, `playtime_linux_forever` and `rtime_last_played`, which Steam doesn't send. They're optional now, and `playtime_2weeks`, `has_community_visible_stats`, `has_leaderboards` and `content_descriptorids` are exposed (#70).
|
|
42
|
+
- Responses with duplicate JSON keys parse the same on every `json` gem version, with the last value winning. json 3 rejects duplicate keys by default, which would have raised `ResponseParseError` (#19).
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
|
|
46
|
+
- Allows `dry-configurable` 1.2 and newer (`~> 1.1` instead of `~> 1.1.0`, which only allowed 1.1.x) (#19).
|
|
47
|
+
- **Breaking:** requires Ruby 3.3 or newer (#17). Ruby 3.0, 3.1 and 3.2 have reached end of life. CI now tests 3.3, 3.4 and 4.0.
|
|
48
|
+
- **Breaking:** response structs now validate their declared types (#15). Integer, Float and String fields convert Steam's values (Steam often sends numbers as strings), and a value that can't be converted raises `SteamApiClient::Errors::ResponseParseError` instead of passing through unchanged. `null` values still come through as `nil`.
|
|
49
|
+
- `PlayerSummary#steamid` is now an Integer, like every other SteamID in the gem (it was a String).
|
|
50
|
+
- `PlayerSummary#profilestate` is now an Integer (it was declared String; Steam sends `1`).
|
|
51
|
+
- Global achievement `percent` is now a Float (it held Steam's raw value, e.g. `"49.6"`).
|
|
52
|
+
- The gem homepage and README links point to `github.com/jpechaves/steam_api` instead of the old `sosolidkk` account (#22).
|
|
53
|
+
|
|
54
|
+
## [0.9.1] - 2026-10-23
|
|
55
|
+
|
|
56
|
+
### Fixed
|
|
57
|
+
|
|
58
|
+
- The gem no longer packages development files (`CLAUDE.md`, `CODE_OF_CONDUCT.md`, `Gemfile`, `Gemfile.lock` and tooling dotfiles). It ships only `lib/`, `LICENSE`, `README.md` and `CHANGELOG.md` (#37).
|
|
59
|
+
|
|
60
|
+
## [0.9.0] - 2026-10-23
|
|
61
|
+
|
|
62
|
+
First release published to RubyGems, as [`steam_api_client`](https://rubygems.org/gems/steam_api_client).
|
|
63
|
+
|
|
3
64
|
### Changed
|
|
4
65
|
|
|
5
66
|
- **Breaking:** renamed the gem from `steam_api` to `steam_api_client`, since `steam_api` is taken on RubyGems by an unrelated gem (#21). Update your Gemfile to `gem "steam_api_client"`, use `require "steam_api_client"`, and replace the `SteamApi` namespace with `SteamApiClient` (e.g. `SteamApiClient::Client`, `SteamApiClient::Errors::HttpTimeout`).
|
|
67
|
+
- **Breaking:** `Response#result` raises `SteamApiClient::Errors::ResponseParseError` instead of letting `Dry::Struct::Error` escape when a response can't be built into its struct, and for bodies that aren't a JSON object (#11). The original error is available as `#cause`.
|
|
68
|
+
- `gem push` requires MFA (`rubygems_mfa_required`).
|
|
69
|
+
- Removed the `activesupport`, `vcr` and `webmock` dependencies.
|
|
70
|
+
|
|
71
|
+
### Added
|
|
72
|
+
|
|
73
|
+
- Configurable HTTP timeouts: 10s per request and 5s to connect by default. Set them with `Client.configure` (`timeout`, `connect_timeout`) or `Client.new(timeout:, connect_timeout:)`. Timed-out requests raise `HttpTimeout` (#12).
|
|
74
|
+
- `AppDetails::Movie` exposes Steam's streaming trailer manifests: `dash_av1`, `dash_h264`, `hls_h264` (#9).
|
|
75
|
+
- CI: Standard Ruby lint, a RubyCritic score gate, and bundler-audit on push, PRs and weekly (#31).
|
|
76
|
+
|
|
77
|
+
### Fixed
|
|
78
|
+
|
|
79
|
+
- `app_details` raised `Dry::Struct::Error` for every app with trailers, because Steam no longer returns `webm`/`mp4` (#9).
|
|
80
|
+
- `app_details` raised `Dry::Struct::Error` for unavailable apps. It now returns `response.success == false` with `response.data == nil` (#10).
|
|
81
|
+
- The token set through `Client.configure` was never sent. `Client#api_token` now falls back to it.
|
|
82
|
+
- `require "steam_api"` didn't load `json`, so requests failed outside the test suite.
|
|
83
|
+
- The default request `body` used ActiveSupport methods (`as_json`, `deep_symbolize_keys`) after ActiveSupport was removed.
|
|
84
|
+
- The README examples used a positional `Client.new` argument instead of `api_token:`.
|
|
85
|
+
|
|
86
|
+
### Security
|
|
87
|
+
|
|
88
|
+
- Bumped `concurrent-ruby` to 1.3.8 and `json` to 2.21.2 in `Gemfile.lock` to resolve bundler-audit advisories (#31). This affects development and CI only. Apps using the gem resolve their own versions.
|
|
89
|
+
|
|
90
|
+
## Earlier versions
|
|
91
|
+
|
|
92
|
+
The versions below were bumped in `version.rb` during development but **never published or tagged**. They are reconstructed from the git history (the gem was named `steam` until 0.1.5 and `steam_api` until 0.9.0).
|
|
93
|
+
|
|
94
|
+
## [0.8.0] - 2025-04-13
|
|
95
|
+
|
|
96
|
+
- Fixed YARD comments, added `bin/setup`, completed the struct specs and added the first request spec.
|
|
97
|
+
- Updated dependencies.
|
|
98
|
+
|
|
99
|
+
## [0.7.0] - 2024-07-27
|
|
100
|
+
|
|
101
|
+
- Removed unused development tooling and ran Standard Ruby on the whole project. There was no 0.6.0.
|
|
102
|
+
|
|
103
|
+
## [0.5.0] - 2024-06-03
|
|
104
|
+
|
|
105
|
+
- Raised the required Ruby version (needed by `dry-core`) and updated the CI Ruby versions.
|
|
106
|
+
- More specs.
|
|
107
|
+
|
|
108
|
+
## [0.4.0] - 2024-04-14
|
|
109
|
+
|
|
110
|
+
- Updated gem metadata. More struct specs.
|
|
111
|
+
|
|
112
|
+
## [0.3.0] - 2024-01-20
|
|
113
|
+
|
|
114
|
+
- Added a GitHub Actions workflow and dropped Ruby 2.6.
|
|
115
|
+
- Added specs for errors, responses and base structs. Removed unused code.
|
|
116
|
+
|
|
117
|
+
## [0.2.2] - 2023-06-28
|
|
118
|
+
|
|
119
|
+
- Added `EndpointKindNotSupported` for unknown endpoint kinds.
|
|
120
|
+
- Fixed query params not being sent with requests.
|
|
121
|
+
- Clearer parameter names. Updated gems and the Ruby version. First specs for the client and the failure handler.
|
|
122
|
+
|
|
123
|
+
## [0.2.1] - 2023-02-26
|
|
124
|
+
|
|
125
|
+
- Added support for the Storefront API and the app details endpoint.
|
|
126
|
+
|
|
127
|
+
## [0.1.5] - 2023-01-15
|
|
128
|
+
|
|
129
|
+
- Renamed the gem from `steam` to `steam_api`. There were no 0.1.3 or 0.1.4.
|
|
130
|
+
|
|
131
|
+
## [0.1.2] - 2022-11-25
|
|
132
|
+
|
|
133
|
+
- Client, structs, and request/response/error handling, with `HttpForbidden` (403) and `HttpInternalServerError` (500).
|
|
134
|
+
- Endpoints: player summaries, app news, global achievement percentages, player achievements, user game stats, recently played games, resolve vanity URL, current player count, player level, owned games and friend list.
|
|
135
|
+
- Development tooling configuration.
|
|
136
|
+
|
|
137
|
+
## [0.1.1] - 2022-09-29
|
|
138
|
+
|
|
139
|
+
- Basic client configuration.
|
|
6
140
|
|
|
7
141
|
## [0.1.0] - 2022-09-28
|
|
8
142
|
|
|
9
|
-
- Initial
|
|
143
|
+
- Initial gem skeleton.
|
|
144
|
+
|
|
145
|
+
[Unreleased]: https://github.com/jpechaves/steam_api/compare/v0.10.0...HEAD
|
|
146
|
+
[0.10.0]: https://github.com/jpechaves/steam_api/compare/v0.9.1...v0.10.0
|
|
147
|
+
[0.9.1]: https://github.com/jpechaves/steam_api/compare/v0.9.0...v0.9.1
|
|
148
|
+
[0.9.0]: https://github.com/jpechaves/steam_api/releases/tag/v0.9.0
|
data/README.md
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
- [Running the Interactive Console](#running-the-interactive-console)
|
|
15
15
|
- [Running Tests](#running-tests)
|
|
16
16
|
- [Code Quality](#code-quality)
|
|
17
|
+
- [Releasing](#releasing)
|
|
17
18
|
- [Contributing](#contributing)
|
|
18
19
|
- [How to Contribute](#how-to-contribute)
|
|
19
20
|
- [License](#license)
|
|
@@ -21,6 +22,9 @@
|
|
|
21
22
|
|
|
22
23
|
# steam_api_client
|
|
23
24
|
|
|
25
|
+
[](https://rubygems.org/gems/steam_api_client)
|
|
26
|
+
[](https://github.com/jpechaves/steam_api/actions/workflows/ci.yml)
|
|
27
|
+
|
|
24
28
|
> Previously developed as `steam_api`. It is not related to the [`steam_api`](https://rubygems.org/gems/steam_api) gem on RubyGems.
|
|
25
29
|
|
|
26
30
|
A Ruby gem for interacting with the [Steam Web API](https://developer.valvesoftware.com/wiki/Steam_Web_API). This gem provides a structured and user-friendly way to fetch various types of data from Steam's API endpoints, such as game details, player information, and achievements.
|
|
@@ -35,22 +39,28 @@ A Ruby gem for interacting with the [Steam Web API](https://developer.valvesoftw
|
|
|
35
39
|
|
|
36
40
|
## Installation
|
|
37
41
|
|
|
38
|
-
Add
|
|
42
|
+
Add the gem to your application's Gemfile:
|
|
39
43
|
|
|
40
44
|
```ruby
|
|
45
|
+
gem "steam_api_client"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
and run `bundle install`. Or let Bundler do both:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
41
51
|
$ bundle add steam_api_client
|
|
42
52
|
```
|
|
43
53
|
|
|
44
|
-
|
|
54
|
+
Without Bundler, install it with:
|
|
45
55
|
|
|
46
56
|
```bash
|
|
47
57
|
$ gem install steam_api_client
|
|
48
58
|
```
|
|
49
59
|
|
|
50
|
-
|
|
60
|
+
and load it with:
|
|
51
61
|
|
|
52
|
-
```
|
|
53
|
-
|
|
62
|
+
```ruby
|
|
63
|
+
require "steam_api_client"
|
|
54
64
|
```
|
|
55
65
|
|
|
56
66
|
## Usage
|
|
@@ -86,7 +96,7 @@ client = SteamApiClient::Client.new(api_token: "your-API-token-value", timeout:
|
|
|
86
96
|
|
|
87
97
|
```ruby
|
|
88
98
|
client = SteamApiClient::Client.new(api_token: "your-API-token-value")
|
|
89
|
-
client.player_summaries.retrieve([76561198160009756])
|
|
99
|
+
client.player_summaries.retrieve(steamids: [76561198160009756])
|
|
90
100
|
```
|
|
91
101
|
|
|
92
102
|
#### Get App Details
|
|
@@ -102,8 +112,7 @@ For more examples, see the [Usage](#usage) section above.
|
|
|
102
112
|
|
|
103
113
|
### Requirements
|
|
104
114
|
|
|
105
|
-
- Ruby >= 3.
|
|
106
|
-
- Docker (optional, for consistent development environments)
|
|
115
|
+
- Ruby >= 3.3
|
|
107
116
|
|
|
108
117
|
### Initial Setup
|
|
109
118
|
|
|
@@ -137,9 +146,29 @@ We use [standardrb](https://github.com/standardrb/standard) for linting and code
|
|
|
137
146
|
$ bin/lint
|
|
138
147
|
```
|
|
139
148
|
|
|
149
|
+
### Releasing
|
|
150
|
+
|
|
151
|
+
Each pull request with a user-visible change adds a line under `## [Unreleased]` in `CHANGELOG.md`. Pull requests don't change the version.
|
|
152
|
+
|
|
153
|
+
To release the merged changes, open a release pull request:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
$ git checkout -b release/0.10.0
|
|
157
|
+
$ bin/bump minor # or patch / major: bumps version.rb and Gemfile.lock, moves [Unreleased] under "## [0.10.0] - <today>"
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Commit, open the pull request, and merge it. Then publish from `main`:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
$ bin/release # build and push the gem (asks for your RubyGems MFA code), then tag v<version> and push the tag
|
|
164
|
+
$ bin/release --dry-run # show what would happen without building, pushing or tagging
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
`bin/release` checks out and pulls `main` first, and refuses to run with uncommitted changes or without a CHANGELOG entry. Steps that are already done are skipped, so running it again for a released version does nothing.
|
|
168
|
+
|
|
140
169
|
## Contributing
|
|
141
170
|
|
|
142
|
-
Bug reports and pull requests are welcome on GitHub at [GitHub Repository](https://github.com/
|
|
171
|
+
Bug reports and pull requests are welcome on GitHub at [GitHub Repository](https://github.com/jpechaves/steam_api). This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Code of Conduct](https://github.com/jpechaves/steam_api/blob/main/CODE_OF_CONDUCT.md).
|
|
143
172
|
|
|
144
173
|
### How to Contribute
|
|
145
174
|
|
|
@@ -155,4 +184,4 @@ This gem is available as open source under the terms of the [MIT License](https:
|
|
|
155
184
|
|
|
156
185
|
## Code of Conduct
|
|
157
186
|
|
|
158
|
-
Everyone interacting in the Steam project's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [Code of Conduct](https://github.com/
|
|
187
|
+
Everyone interacting in the Steam project's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [Code of Conduct](https://github.com/jpechaves/steam_api/blob/main/CODE_OF_CONDUCT.md).
|
|
@@ -44,5 +44,34 @@ module SteamApiClient
|
|
|
44
44
|
|
|
45
45
|
# status_code: 500
|
|
46
46
|
class HttpInternalServerError < ApiError; end
|
|
47
|
+
|
|
48
|
+
# Reads the Retry-After header of rate limited / unavailable responses
|
|
49
|
+
module RetryAfter
|
|
50
|
+
# Seconds to wait before retrying. Retry-After is either a number of
|
|
51
|
+
# seconds or an HTTP date.
|
|
52
|
+
# @return [Integer, nil] nil when the header is missing or invalid
|
|
53
|
+
def retry_after
|
|
54
|
+
value = response.headers&.[]("Retry-After").to_s.strip
|
|
55
|
+
return Integer(value, 10) if value.match?(/\A\d+\z/)
|
|
56
|
+
return if value.empty?
|
|
57
|
+
|
|
58
|
+
[(Time.httpdate(value) - Time.now).ceil, 0].max
|
|
59
|
+
rescue ArgumentError
|
|
60
|
+
nil
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# status_code: 429. Steam rate limits frequent requests.
|
|
65
|
+
class HttpTooManyRequests < ApiError
|
|
66
|
+
include RetryAfter
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# status_code: 502
|
|
70
|
+
class HttpBadGateway < ApiError; end
|
|
71
|
+
|
|
72
|
+
# status_code: 503
|
|
73
|
+
class HttpServiceUnavailable < ApiError
|
|
74
|
+
include RetryAfter
|
|
75
|
+
end
|
|
47
76
|
end
|
|
48
77
|
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module SteamApiClient
|
|
2
|
+
module Errors
|
|
3
|
+
# Raised before a request is sent when the endpoint needs an API token
|
|
4
|
+
# and the client has none
|
|
5
|
+
class MissingApiToken < ::StandardError
|
|
6
|
+
def initialize(message = "This endpoint needs a Steam Web API token. Pass Client.new(api_token: ...) or set it with Client.configure { |config| config.api_token = ... }.")
|
|
7
|
+
super
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -30,12 +30,15 @@ module SteamApiClient
|
|
|
30
30
|
when 401 then raise SteamApiClient::Errors::HttpUnauthorized, response
|
|
31
31
|
when 403 then raise SteamApiClient::Errors::HttpForbidden, response
|
|
32
32
|
when 404 then raise SteamApiClient::Errors::HttpNotFound, response
|
|
33
|
+
when 429 then raise SteamApiClient::Errors::HttpTooManyRequests, response
|
|
33
34
|
end
|
|
34
35
|
end
|
|
35
36
|
|
|
36
37
|
def raise_response_5xx(response)
|
|
37
38
|
case response.status_code
|
|
38
39
|
when 500 then raise SteamApiClient::Errors::HttpInternalServerError, response
|
|
40
|
+
when 502 then raise SteamApiClient::Errors::HttpBadGateway, response
|
|
41
|
+
when 503 then raise SteamApiClient::Errors::HttpServiceUnavailable, response
|
|
39
42
|
end
|
|
40
43
|
end
|
|
41
44
|
|
|
@@ -6,6 +6,7 @@ module SteamApiClient
|
|
|
6
6
|
@response_struct = response_struct
|
|
7
7
|
@client = client
|
|
8
8
|
|
|
9
|
+
ensure_api_token!
|
|
9
10
|
build_request
|
|
10
11
|
end
|
|
11
12
|
|
|
@@ -23,6 +24,13 @@ module SteamApiClient
|
|
|
23
24
|
|
|
24
25
|
attr_accessor :request_struct, :response_struct, :client, :raw_request, :failure_handler
|
|
25
26
|
|
|
27
|
+
def ensure_api_token!
|
|
28
|
+
return unless request_struct.needs_authorization?
|
|
29
|
+
return unless client.api_token.to_s.empty?
|
|
30
|
+
|
|
31
|
+
raise SteamApiClient::Errors::MissingApiToken
|
|
32
|
+
end
|
|
33
|
+
|
|
26
34
|
def build_request
|
|
27
35
|
url = nil
|
|
28
36
|
|
|
@@ -67,20 +75,19 @@ module SteamApiClient
|
|
|
67
75
|
end
|
|
68
76
|
|
|
69
77
|
def build_options
|
|
70
|
-
{
|
|
78
|
+
options = {
|
|
71
79
|
method: request_struct.method,
|
|
72
|
-
headers:
|
|
73
|
-
body: request_struct.body.to_json,
|
|
80
|
+
headers: {},
|
|
74
81
|
followlocation: true,
|
|
75
82
|
timeout_ms: (client.timeout * 1000).to_i,
|
|
76
83
|
connecttimeout_ms: (client.connect_timeout * 1000).to_i,
|
|
77
84
|
# Required for sub-second timeouts and safe use of timeouts across threads
|
|
78
85
|
nosignal: true
|
|
79
86
|
}
|
|
80
|
-
|
|
87
|
+
# GET requests (every Steam endpoint so far) carry their params in the query string
|
|
88
|
+
return options if request_struct.method == :get
|
|
81
89
|
|
|
82
|
-
|
|
83
|
-
{"Content-Type" => "application/json"}
|
|
90
|
+
options.merge(headers: {"Content-Type" => "application/json"}, body: request_struct.body.to_json)
|
|
84
91
|
end
|
|
85
92
|
end
|
|
86
93
|
end
|
|
@@ -4,14 +4,14 @@ module SteamApiClient
|
|
|
4
4
|
# of an app in the Steam Web Api.
|
|
5
5
|
class AppGlobalAchievements < Base
|
|
6
6
|
# Get on the Api all global achievements info of an App in the Steam.
|
|
7
|
-
# @param [Integer]
|
|
7
|
+
# @param [Integer] appid The Steam app id (sent to Steam as `gameid`)
|
|
8
8
|
# @return [SteamApiClient::Structs::AppGlobalAchievements] instance with the
|
|
9
9
|
# player summary details.
|
|
10
|
-
def retrieve(
|
|
10
|
+
def retrieve(appid:)
|
|
11
11
|
build_request_and_run(
|
|
12
12
|
SteamApiClient::Structs::Requests::GetAppGlobalAchievements,
|
|
13
13
|
SteamApiClient::Structs::AppGlobalAchievements,
|
|
14
|
-
gameid:
|
|
14
|
+
gameid: appid
|
|
15
15
|
)
|
|
16
16
|
end
|
|
17
17
|
end
|
|
@@ -9,7 +9,7 @@ module SteamApiClient
|
|
|
9
9
|
# @param [Integer] maxlength The max length of the news content
|
|
10
10
|
# @return [SteamApiClient::Structs::AppNews] instance with the
|
|
11
11
|
# player summary details.
|
|
12
|
-
def retrieve(appid
|
|
12
|
+
def retrieve(appid:, count:, maxlength: 300)
|
|
13
13
|
build_request_and_run(
|
|
14
14
|
SteamApiClient::Structs::Requests::GetAppNews,
|
|
15
15
|
SteamApiClient::Structs::AppNews,
|
|
@@ -7,7 +7,7 @@ module SteamApiClient
|
|
|
7
7
|
# @param [Integer] appid The Steam app id
|
|
8
8
|
# @return [SteamApiClient::Structs::GameCurrentPlayers] instance with the
|
|
9
9
|
# game current players count.
|
|
10
|
-
def retrieve(appid)
|
|
10
|
+
def retrieve(appid:)
|
|
11
11
|
build_request_and_run(
|
|
12
12
|
SteamApiClient::Structs::Requests::GetGameCurrentPlayers,
|
|
13
13
|
SteamApiClient::Structs::GameCurrentPlayers,
|
|
@@ -8,7 +8,7 @@ module SteamApiClient
|
|
|
8
8
|
# @param [Integer] steamid The Steam user id
|
|
9
9
|
# @return [SteamApiClient::Structs::PlayerAchievements] instance with the
|
|
10
10
|
# player summary details.
|
|
11
|
-
def retrieve(appid
|
|
11
|
+
def retrieve(appid:, steamid:)
|
|
12
12
|
build_request_and_run(
|
|
13
13
|
SteamApiClient::Structs::Requests::GetPlayerAchievements,
|
|
14
14
|
SteamApiClient::Structs::PlayerAchievements,
|
|
@@ -8,7 +8,7 @@ module SteamApiClient
|
|
|
8
8
|
# @param [String] relationship Relationship filter. Possibles values: 'all', 'friend'.
|
|
9
9
|
# @return [SteamApiClient::Structs::PlayerFriends] instance with the
|
|
10
10
|
# player friends list.
|
|
11
|
-
def retrieve(steamid
|
|
11
|
+
def retrieve(steamid:, relationship: "all")
|
|
12
12
|
build_request_and_run(
|
|
13
13
|
SteamApiClient::Structs::Requests::GetPlayerFriends,
|
|
14
14
|
SteamApiClient::Structs::PlayerFriends,
|
|
@@ -8,7 +8,7 @@ module SteamApiClient
|
|
|
8
8
|
# @param [Integer] steamid The Steam user id
|
|
9
9
|
# @return [SteamApiClient::Structs::PlayerGameStats] instance with the
|
|
10
10
|
# player summary details.
|
|
11
|
-
def retrieve(appid
|
|
11
|
+
def retrieve(appid:, steamid:)
|
|
12
12
|
build_request_and_run(
|
|
13
13
|
SteamApiClient::Structs::Requests::GetPlayerGameStats,
|
|
14
14
|
SteamApiClient::Structs::PlayerGameStats,
|
|
@@ -6,7 +6,7 @@ module SteamApiClient
|
|
|
6
6
|
# @param [Integer] steamid The Steam user id
|
|
7
7
|
# @return [SteamApiClient::Structs::PlayerLevel] instance with the
|
|
8
8
|
# player level.
|
|
9
|
-
def retrieve(steamid)
|
|
9
|
+
def retrieve(steamid:)
|
|
10
10
|
build_request_and_run(
|
|
11
11
|
SteamApiClient::Structs::Requests::GetPlayerLevel,
|
|
12
12
|
SteamApiClient::Structs::PlayerLevel,
|
|
@@ -9,7 +9,7 @@ module SteamApiClient
|
|
|
9
9
|
# @param [Boolean] include_played_free_games Flag to include free games
|
|
10
10
|
# @return [SteamApiClient::Structs::PlayerOwnedGames] instance with the
|
|
11
11
|
# player owned games details.
|
|
12
|
-
def retrieve(steamid
|
|
12
|
+
def retrieve(steamid:, include_appinfo: false, include_played_free_games: false)
|
|
13
13
|
build_request_and_run(
|
|
14
14
|
SteamApiClient::Structs::Requests::GetPlayerOwnedGames,
|
|
15
15
|
SteamApiClient::Structs::PlayerOwnedGames,
|
|
@@ -8,7 +8,7 @@ module SteamApiClient
|
|
|
8
8
|
# @param [Integer] count - The number of games that should return
|
|
9
9
|
# @return [SteamApiClient::Structs::PlayerRecentGames] instance with the
|
|
10
10
|
# player summary details.
|
|
11
|
-
def retrieve(steamid
|
|
11
|
+
def retrieve(steamid:, count: 5)
|
|
12
12
|
build_request_and_run(
|
|
13
13
|
SteamApiClient::Structs::Requests::GetPlayerRecentGames,
|
|
14
14
|
SteamApiClient::Structs::PlayerRecentGames,
|
|
@@ -7,7 +7,7 @@ module SteamApiClient
|
|
|
7
7
|
# @param [String] vanityurl - The Steam user short url
|
|
8
8
|
# @return [SteamApiClient::Structs::PlayerSteamId] instance with the
|
|
9
9
|
# player SteamId.
|
|
10
|
-
def retrieve(vanityurl)
|
|
10
|
+
def retrieve(vanityurl:)
|
|
11
11
|
build_request_and_run(
|
|
12
12
|
SteamApiClient::Structs::Requests::GetPlayerSteamId,
|
|
13
13
|
SteamApiClient::Structs::PlayerSteamId,
|
|
@@ -7,7 +7,7 @@ module SteamApiClient
|
|
|
7
7
|
# @param [Array<Integer>] steamids - The Steam order's id
|
|
8
8
|
# @return [SteamApiClient::Structs::PlayerSummaries] instance with the
|
|
9
9
|
# player summary details.
|
|
10
|
-
def retrieve(steamids)
|
|
10
|
+
def retrieve(steamids:)
|
|
11
11
|
build_request_and_run(
|
|
12
12
|
SteamApiClient::Structs::Requests::GetPlayerSummaries,
|
|
13
13
|
SteamApiClient::Structs::PlayerSummaries,
|
|
@@ -25,6 +25,12 @@ module SteamApiClient
|
|
|
25
25
|
!success?
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
+
# Returns the HTTP response headers (case-insensitive)
|
|
29
|
+
# @return [Typhoeus::Response::Header, nil]
|
|
30
|
+
def headers
|
|
31
|
+
raw_response.headers
|
|
32
|
+
end
|
|
33
|
+
|
|
28
34
|
# Returns the HTTP status code
|
|
29
35
|
# @return [Integer]
|
|
30
36
|
def status_code
|
|
@@ -57,8 +63,10 @@ module SteamApiClient
|
|
|
57
63
|
|
|
58
64
|
attr_accessor :raw_response, :response_struct
|
|
59
65
|
|
|
66
|
+
# json 3 rejects duplicate keys by default; keep json 2's behavior (last one wins)
|
|
67
|
+
# so a response parses the same whichever json version the app uses
|
|
60
68
|
def parse_body
|
|
61
|
-
::JSON.parse(raw_response.body.to_s, symbolize_names: true)
|
|
69
|
+
::JSON.parse(raw_response.body.to_s, symbolize_names: true, allow_duplicate_key: true)
|
|
62
70
|
end
|
|
63
71
|
end
|
|
64
72
|
end
|
|
@@ -3,9 +3,9 @@ module SteamApiClient
|
|
|
3
3
|
# Struct that holds all App Global Achievements information
|
|
4
4
|
# @see https://developer.valvesoftware.com/wiki/Steam_Web_API#GetGlobalAchievementPercentagesForApp_.28v0002.29
|
|
5
5
|
class AppGlobalAchievements < Base
|
|
6
|
-
class InternalAppAchievementsAttributes <
|
|
6
|
+
class InternalAppAchievementsAttributes < Base
|
|
7
7
|
attribute :name, Types::String
|
|
8
|
-
attribute :percent, Types::
|
|
8
|
+
attribute :percent, Types::Float
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
attribute :achievementpercentages do
|
|
@@ -2,7 +2,7 @@ module SteamApiClient
|
|
|
2
2
|
module Structs
|
|
3
3
|
# Struct that holds an App news information
|
|
4
4
|
# @see https://developer.valvesoftware.com/wiki/Steam_Web_API#GetNewsForApp_.28v0002.29
|
|
5
|
-
class AppNew <
|
|
5
|
+
class AppNew < Base
|
|
6
6
|
attribute :gid, Types::String
|
|
7
7
|
attribute :title, Types::String
|
|
8
8
|
attribute :url, Types::String
|
|
@@ -3,7 +3,7 @@ module SteamApiClient
|
|
|
3
3
|
# Struct that holds all Player Achievements of an app information
|
|
4
4
|
# @see https://developer.valvesoftware.com/wiki/Steam_Web_API#GetPlayerAchievements_.28v0001.29
|
|
5
5
|
class PlayerAchievements < Base
|
|
6
|
-
class InternalPlayerAchievementsAttributes <
|
|
6
|
+
class InternalPlayerAchievementsAttributes < Base
|
|
7
7
|
attribute :apiname?, Types::String
|
|
8
8
|
attribute :achieved?, Types::Integer
|
|
9
9
|
attribute :unlocktime?, Types::Integer
|
|
@@ -2,7 +2,7 @@ module SteamApiClient
|
|
|
2
2
|
module Structs
|
|
3
3
|
# Struct that holds information of all friends the player has
|
|
4
4
|
# @see https://developer.valvesoftware.com/wiki/Steam_Web_API#GetFriendList_.28v0001.29
|
|
5
|
-
class InternalPlayerFriends <
|
|
5
|
+
class InternalPlayerFriends < Base
|
|
6
6
|
attribute :steamid?, Types::Integer
|
|
7
7
|
attribute :relationship?, Types::String
|
|
8
8
|
attribute :friend_since, Types::Integer
|
|
@@ -3,14 +3,22 @@ module SteamApiClient
|
|
|
3
3
|
# Struct that holds all Player Stats for a given game/appid
|
|
4
4
|
# @see https://developer.valvesoftware.com/wiki/Steam_Web_API#GetUserStatsForGame_.28v0002.29
|
|
5
5
|
class PlayerGameStats < Base
|
|
6
|
-
class InternalPlayerGameStatsAttributes <
|
|
6
|
+
class InternalPlayerGameStatsAttributes < Base
|
|
7
7
|
attribute :name?, Types::String
|
|
8
8
|
attribute :achieved?, Types::Integer
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
# A game-defined stat, e.g. "Scout.accum.iDamageDealt" => 26580
|
|
12
|
+
class Stat < Base
|
|
13
|
+
attribute :name, Types::String
|
|
14
|
+
# Integer or Float exactly as Steam sends it (coercing would truncate float stats)
|
|
15
|
+
attribute :value, (Types::Strict::Integer | Types::Strict::Float).optional
|
|
16
|
+
end
|
|
17
|
+
|
|
11
18
|
attribute :playerstats do
|
|
12
19
|
attribute :steamID?, Types::Coercible::Integer.optional.default(nil)
|
|
13
20
|
attribute :gameName?, Types::String
|
|
21
|
+
attribute :stats?, Types::Strict::Array.of(Stat)
|
|
14
22
|
attribute :achievements?, Types::Strict::Array.of(
|
|
15
23
|
InternalPlayerGameStatsAttributes
|
|
16
24
|
)
|
|
@@ -3,15 +3,21 @@ module SteamApiClient
|
|
|
3
3
|
# Struct that holds all user owned games
|
|
4
4
|
# @see https://developer.valvesoftware.com/wiki/Steam_Web_API#GetOwnedGames_.28v0001.29
|
|
5
5
|
class PlayerOwnedGames < Base
|
|
6
|
-
class InternalPlayerOwnedGames <
|
|
6
|
+
class InternalPlayerOwnedGames < Base
|
|
7
7
|
attribute :appid, Types::Integer
|
|
8
8
|
attribute :name?, Types::String
|
|
9
|
+
# Minutes played, in total and in the last two weeks (only sent when played recently)
|
|
9
10
|
attribute :playtime_forever, Types::Integer
|
|
11
|
+
attribute? :playtime_2weeks, Types::Integer
|
|
10
12
|
attribute :img_icon_url?, Types::String
|
|
11
|
-
attribute :
|
|
12
|
-
attribute :
|
|
13
|
-
attribute :
|
|
14
|
-
|
|
13
|
+
attribute? :has_community_visible_stats, Types::Bool
|
|
14
|
+
attribute? :has_leaderboards, Types::Bool
|
|
15
|
+
attribute? :content_descriptorids, Types::Array.of(Types::Integer)
|
|
16
|
+
# Steam doesn't send these for most libraries anymore
|
|
17
|
+
attribute? :playtime_windows_forever, Types::Integer
|
|
18
|
+
attribute? :playtime_mac_forever, Types::Integer
|
|
19
|
+
attribute? :playtime_linux_forever, Types::Integer
|
|
20
|
+
attribute? :rtime_last_played, Types::Integer
|
|
15
21
|
end
|
|
16
22
|
|
|
17
23
|
attribute :response do
|
|
@@ -3,7 +3,7 @@ module SteamApiClient
|
|
|
3
3
|
# Struct that holds all user recent played games
|
|
4
4
|
# @see https://developer.valvesoftware.com/wiki/Steam_Web_API#GetRecentlyPlayedGames_.28v0001.29
|
|
5
5
|
class PlayerRecentGames < Base
|
|
6
|
-
class InternalPlayerRecentGames <
|
|
6
|
+
class InternalPlayerRecentGames < Base
|
|
7
7
|
attribute :appid, Types::Integer
|
|
8
8
|
attribute :name, Types::String
|
|
9
9
|
attribute :playtime_2weeks, Types::Integer
|