-
Notifications
You must be signed in to change notification settings - Fork 0
/
SteamChecks.WebApi.cs
251 lines (224 loc) · 12 KB
/
SteamChecks.WebApi.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
using System;
using System.Linq;
using Newtonsoft.Json;
namespace Oxide.Plugins
{
public partial class SteamChecks
{
/// <summary>
/// Generic request to the Steam Web API
/// </summary>
/// <param name="steamRequestType"></param>
/// <param name="endpoint">The specific endpoint, e.g. GetSteamLevel/v1</param>
/// <param name="steamId64"></param>
/// <param name="callback">Callback returning the HTTP status code <see cref="StatusCode"></see> and a JSON JObject</param>
/// <param name="additionalArguments">Additional arguments, e.g. &foo=bar</param>
private void SteamWebRequest(SteamRequestType steamRequestType, string endpoint, string steamId64,
Action<int, string> callback, string additionalArguments = "")
{
var requestUrl = $"{apiURL}/{steamRequestType}/{endpoint}/?key={apiKey}&{(steamRequestType == SteamRequestType.IPlayerService ? "steamid" : "steamids")}={steamId64}{additionalArguments}";
webrequest.Enqueue(requestUrl, "", (httpCode, response) =>
{
callback(httpCode, httpCode == (int)StatusCode.Success ? response : null);
}, this, Core.Libraries.RequestMethod.GET, null, webTimeout);
}
/// <summary>
/// Get the Steam level of a user
/// </summary>
/// <param name="steamId64">The users steamId64</param>
/// <param name="callback">Callback with the statusCode <see cref="StatusCode"></see> and the steam level</param>
private void GetSteamLevel(string steamId64, Action<int, int> callback)
{
SteamWebRequest(SteamRequestType.IPlayerService, "GetSteamLevel/v1", steamId64,
(httpCode, response) =>
{
if (httpCode == (int)StatusCode.Success)
{
callback(httpCode, JsonConvert.DeserializeObject<SteamLevelApiResponse>(response).Response.player_level);
}
else
{
callback(httpCode, -1);
}
});
}
/// <summary>
/// Get information about hours played in Steam
/// </summary>
/// <param name="steamId64">steamId64 of the user</param>
/// <param name="callback">Callback with the statusCode <see cref="StatusCode"></see> and the <see cref="GameTimeInformation"></see></param>
/// <remarks>
/// Even when the user has his profile public, this can be hidden. This seems to be often the case.
/// When hidden, the statusCode will be <see cref="StatusCode.GameInfoHidden"></see>
/// </remarks>
private void GetPlaytimeInformation(string steamId64, Action<int, GameTimeInformation> callback)
{
SteamWebRequest(SteamRequestType.IPlayerService, "GetOwnedGames/v1", steamId64,
(httpCode, response) =>
{
var steamResponse = JsonConvert.DeserializeObject<SteamApiResponse>(response);
if (httpCode == (int)StatusCode.Success)
{
// We need to check if it is null, because the steam-user can hide game information
var gamesCount = steamResponse.Response.game_count;
if (gamesCount == null)
{
callback((int)StatusCode.GameInfoHidden, null);
return;
}
var playtimeRust = steamResponse.Response.games
.FirstOrDefault(x => x.appid == 252490)?.playtime_forever;
if (playtimeRust == null)
{
callback((int)StatusCode.GameInfoHidden, null);
return;
}
var playtimeAll = steamResponse.Response.games
.Sum(x => x.playtime_forever);
callback(httpCode, new GameTimeInformation((int)gamesCount, (int)playtimeRust, playtimeAll));
}
else
{
callback(httpCode, null);
}
}, "&include_appinfo=false"); // We don't need additional appinfos, like images
}
/// <summary>
/// Get Summary information about the player, like if his profile is visible
/// </summary>
/// <param name="steamId64">steamId64 of the user</param>
/// <param name="callback">Callback with the statusCode <see cref="StatusCode"></see> and the <see cref="PlayerSummary"></see></param>
private void GetSteamPlayerSummaries(string steamId64, Action<int, PlayerSummary> callback)
{
SteamWebRequest(SteamRequestType.ISteamUser, "GetPlayerSummaries/v2", steamId64,
(httpCode, response) =>
{
var steamResponse = JsonConvert.DeserializeObject<SteamApiResponse>(response);
if (httpCode == (int)StatusCode.Success)
{
if (steamResponse.Response.players.Count() != 1)
{
callback((int)StatusCode.PlayerNotFound, null);
return;
}
var playerInfo = steamResponse.Response.players[0];
var summary = new PlayerSummary
{
Visibility = (PlayerSummary.VisibilityType)playerInfo.communityvisibilitystate,
Profileurl = playerInfo.profileurl
};
// Account creation time can be only fetched, when the profile is public
if (summary.Visibility == PlayerSummary.VisibilityType.Public)
summary.Timecreated = playerInfo.timecreated;
else
summary.Timecreated = -1;
// We have to do a separate request to the steam community profile to get infos about limited and
// if they set up their profile
{
// Set defaults, which won't get the user kicked
summary.NoProfile = false;
summary.LimitedAccount = false;
webrequest.Enqueue($"https://steamcommunity.com/profiles/{steamId64}/?xml=1", "",
(httpCodeCommunity, responseCommunity) =>
{
if (httpCodeCommunity == (int)StatusCode.Success)
{
// XML parser is disabled in uMod, so have to use contains
// Has not set up their profile?
if (responseCommunity.Contains(
"This user has not yet set up their Steam Community profile."))
summary.NoProfile = true;
if (responseCommunity.Contains("<isLimitedAccount>1</isLimitedAccount>"))
summary.LimitedAccount = true;
callback(httpCode, summary);
}
else
{
ApiError(steamId64, "GetSteamPlayerSummaries - community xml",
httpCodeCommunity);
// We will send into the callback success, as the normal GetSteamPlayerSummaries worked in this case
// So it's information can be respected
callback((int)StatusCode.Success, summary);
}
}, this, Core.Libraries.RequestMethod.GET, null, webTimeout);
}
}
else
{
callback(httpCode, null);
}
});
}
/// <summary>
/// Utility function for printing a log when a HTTP API Error was encountered
/// </summary>
/// <param name="steamId">steamId64 for which user the request was</param>
/// <param name="function">function name in the plugin</param>
/// <param name="statusCode">see <see cref="StatusCode"></see></param>
private void ApiError(string steamId, string function, int statusCode)
{
var detailedError = $" SteamID: {steamId} - Function: {function} - ErrorCode: {(StatusCode)statusCode}";
LogWarning(Lang("ErrorHttp"), detailedError);
}
/// <summary>
/// Get all Steam Badges
/// </summary>
/// <param name="steamId64">steamId64 of the user</param>
/// <param name="callback">Callback with the statusCode <see cref="StatusCode"></see> and the result as JSON</param>
private void GetSteamBadges(string steamId64, Action<int,string> callback)
{
SteamWebRequest(SteamRequestType.IPlayerService, "GetBadges/v1", steamId64, callback);
}
/// <summary>
/// Fetched the level of a given badgeid from a JSON Web API result
/// </summary>
/// <param name="response"></param>
/// <param name="badgeId">ID of the badge, see <see cref="Badge"></see></param>
/// <returns>level of the badge, or 0 if badge not existing</returns>
private int ParseBadgeLevel(string response, Badge badgeId)
{
var steamResponse = JsonConvert.DeserializeObject<SteamBadgeApiResponse>(response);
return steamResponse.response.badges.FirstOrDefault(x => x.badgeid == (int)badgeId)?.level ?? 0;
}
/// <summary>
/// Get the information about the bans the player has
/// </summary>
/// <param name="steamId64">steamId64 of the user</param>
/// <param name="callback">Callback with the statusCode <see cref="StatusCode"></see> and the result as <see cref="PlayerBans"></see></param>
/// <remarks>
/// Getting the user bans is even possible, if the profile is private
/// </remarks>
private void GetPlayerBans(string steamId64, Action<int, PlayerBans> callback)
{
SteamWebRequest(SteamRequestType.ISteamUser, "GetPlayerBans/v1", steamId64,
(httpCode, response) =>
{
if (httpCode == (int)StatusCode.Success)
{
var steamResponse = JsonConvert.DeserializeObject<SteamBanApiResponse>(response);
if (steamResponse.players.Count() != 1)
{
callback((int)StatusCode.PlayerNotFound, null);
return;
}
var playerInfo = steamResponse.players[0];
var bans = new PlayerBans
{
CommunityBan = playerInfo.CommunityBanned,
VacBan = playerInfo.VACBanned,
VacBanCount = playerInfo.NumberOfVACBans,
LastBan = playerInfo.DaysSinceLastBan,
GameBanCount = playerInfo.NumberOfGameBans,
// can be none, probation or banned
EconomyBan = playerInfo.EconomyBan != "none"
};
callback(httpCode, bans);
}
else
{
callback(httpCode, null);
}
});
}
}
}