Skip to content

Commit 6dc9a94

Browse files
author
Justin Skiles
authored
Merge pull request #55 from MarkKoz/master
Added Support for the GetPublishedFileDetails Endpoint.
2 parents e388204 + a3b05a2 commit 6dc9a94

9 files changed

Lines changed: 296 additions & 11 deletions

src/SteamWebAPI2/AutoMapperConfiguration.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ public static void Initialize()
108108
CreateSteamWebResponseMap<AssetClassInfoResultContainer, AssetClassInfoResultModel>(x);
109109
CreateSteamWebResponseMap<AssetPriceResultContainer, AssetPriceResultModel>(x);
110110
CreateSteamWebResponseMap<SteamNewsResultContainer, SteamNewsResultModel>(x);
111+
CreateSteamWebResponseMap<PublishedFileDetailsResultContainer, IReadOnlyCollection<PublishedFileDetailsModel>>(x);
112+
CreateSteamWebResponseMap<PublishedFileDetailsResultContainer, PublishedFileDetailsModel>(x);
111113
CreateSteamWebResponseMap<UGCFileDetailsResultContainer, UGCFileDetailsModel>(x);
112114
CreateSteamWebResponseMap<PlayerSummaryResultContainer, PlayerSummaryModel>(x);
113115
CreateSteamWebResponseMap<PlayerSummaryResultContainer, IReadOnlyCollection<PlayerSummaryModel>>(x);
@@ -380,6 +382,21 @@ public static void Initialize()
380382

381383
#region Endpoint: SteamRemoteStorage
382384

385+
x.CreateMap<uint, PublishedFileVisibility>();
386+
x.CreateMap<PublishedFileDetails, PublishedFileDetailsModel>()
387+
.ForMember(dest => dest.FileUrl, opts => opts.MapFrom(source => new Uri(source.FileUrl)))
388+
.ForMember(dest => dest.PreviewUrl, opts => opts.MapFrom(source => new Uri(source.PreviewUrl)));
389+
x.CreateMap<PublishedFileDetailsResultContainer, IReadOnlyCollection<PublishedFileDetailsModel>>()
390+
.ConvertUsing(
391+
src => Mapper.Map<IList<PublishedFileDetails>, IReadOnlyCollection<PublishedFileDetailsModel>>(
392+
src.Result?.Result == 1 ? src.Result.Details : null)
393+
);
394+
x.CreateMap<PublishedFileDetailsResultContainer, PublishedFileDetailsModel>()
395+
.ConvertUsing(
396+
src => Mapper.Map<PublishedFileDetails, PublishedFileDetailsModel>(
397+
src.Result?.Result == 1 ? src.Result.Details?.SingleOrDefault() : null)
398+
);
399+
383400
x.CreateMap<UGCFileDetails, UGCFileDetailsModel>();
384401
x.CreateMap<UGCFileDetailsResultContainer, UGCFileDetailsModel>().ConvertUsing(
385402
src => Mapper.Map<UGCFileDetails, UGCFileDetailsModel>(src.Result)

src/SteamWebAPI2/Interfaces/ISteamRemoteStorage.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,16 @@
44

55
namespace SteamWebAPI2.Interfaces
66
{
7+
using System.Collections.Generic;
8+
79
public interface ISteamRemoteStorage
810
{
11+
Task<ISteamWebResponse<IReadOnlyCollection<PublishedFileDetailsModel>>> GetPublishedFileDetailsAsync(uint itemCount, IList<ulong> publishedFileIds);
12+
13+
Task<ISteamWebResponse<IReadOnlyCollection<PublishedFileDetailsModel>>> GetPublishedFileDetailsAsync(IList<ulong> publishedFileIds);
14+
15+
Task<ISteamWebResponse<PublishedFileDetailsModel>> GetPublishedFileDetailsAsync(ulong publishedFileId);
16+
917
Task<ISteamWebResponse<UGCFileDetailsModel>> GetUGCFileDetailsAsync(ulong ugcId, uint appId, ulong? steamId = null);
1018
}
1119
}

src/SteamWebAPI2/Interfaces/SteamRemoteStorage.cs

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
using Steam.Models;
22
using SteamWebAPI2.Models;
33
using SteamWebAPI2.Utilities;
4+
using System;
45
using System.Collections.Generic;
56
using System.Diagnostics;
7+
using System.Linq;
68
using System.Net.Http;
79
using System.Threading.Tasks;
810

@@ -23,6 +25,74 @@ public SteamRemoteStorage(string steamWebApiKey, ISteamWebInterface steamWebInte
2325
: steamWebInterface;
2426
}
2527

28+
/// <summary>
29+
/// Retrieves information about published files such as workshop items and screenshots.
30+
/// </summary>
31+
/// <param name="itemCount">The quantity of items for which to retrieve details.
32+
/// This can be smaller than the amount of items in <paramref name="publishedFileIds"/>, but not larger.</param>
33+
/// <param name="publishedFileIds">The list of IDs of files for which to retrieve details.</param>
34+
/// <returns>A collection of the details of each file or <c>null</c> if the request failed.</returns>
35+
/// <exception cref="ArgumentNullException">Thrown when <paramref name="publishedFileIds"/> is null.</exception>
36+
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="publishedFileIds"/> is empty or <paramref name="itemCount"/>is greater than the number of elements in <paramref name="publishedFileIds"/>.</exception>
37+
public async Task<ISteamWebResponse<IReadOnlyCollection<PublishedFileDetailsModel>>> GetPublishedFileDetailsAsync(uint itemCount, IList<ulong> publishedFileIds) {
38+
if (publishedFileIds == null)
39+
{
40+
throw new ArgumentNullException(nameof(publishedFileIds));
41+
}
42+
43+
if (!publishedFileIds.Any())
44+
{
45+
throw new ArgumentOutOfRangeException(nameof(publishedFileIds), $"{nameof(publishedFileIds)} is empty.");
46+
}
47+
48+
if (itemCount > publishedFileIds.Count)
49+
{
50+
throw new ArgumentOutOfRangeException(nameof(itemCount), itemCount, $"{nameof(itemCount)} cannot be greater than the number of elements in {nameof(publishedFileIds)}.");
51+
}
52+
53+
List<SteamWebRequestParameter> parameters = new List<SteamWebRequestParameter>();
54+
parameters.AddIfHasValue(itemCount, "itemcount");
55+
56+
for (int i = 0; i < publishedFileIds.Count; ++i)
57+
{
58+
parameters.AddIfHasValue(publishedFileIds[i], $"publishedfileids[{i}]");
59+
}
60+
61+
return await GetPublishedFileDetailsAsync<IReadOnlyCollection<PublishedFileDetailsModel>>(parameters);
62+
}
63+
64+
/// <summary>
65+
/// Retrieves information about published files such as workshop items and screenshots.
66+
/// </summary>
67+
/// <param name="publishedFileIds">The list of IDs of files for which to retrieve details.</param>
68+
/// <returns>A collection of the details of each file or <c>null</c> if the request failed.</returns>
69+
/// <exception cref="ArgumentNullException">Thrown when <paramref name="publishedFileIds"/> is null.</exception>
70+
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="publishedFileIds"/> is empty.</exception>
71+
public async Task<ISteamWebResponse<IReadOnlyCollection<PublishedFileDetailsModel>>> GetPublishedFileDetailsAsync(IList<ulong> publishedFileIds)
72+
{
73+
if (publishedFileIds == null)
74+
{
75+
throw new ArgumentNullException(nameof(publishedFileIds));
76+
}
77+
78+
return await GetPublishedFileDetailsAsync((uint)publishedFileIds.Count, publishedFileIds);
79+
}
80+
81+
/// <summary>
82+
/// Retrieves information about a published file such as a workshop item or screenshot.
83+
/// </summary>
84+
/// <param name="publishedFileId">The ID of the file for which to retrieve details.</param>
85+
/// <returns>The details of the file or <c>null</c> if the request failed.</returns>
86+
public async Task<ISteamWebResponse<PublishedFileDetailsModel>> GetPublishedFileDetailsAsync(ulong publishedFileId)
87+
{
88+
List<SteamWebRequestParameter> parameters = new List<SteamWebRequestParameter>();
89+
90+
parameters.AddIfHasValue(1, "itemcount");
91+
parameters.AddIfHasValue(publishedFileId, "publishedfileids[0]");
92+
93+
return await GetPublishedFileDetailsAsync<PublishedFileDetailsModel>(parameters);
94+
}
95+
2696
/// <summary>
2797
/// Returns information about how to download a user generated content based on a UGC ID, App ID, and Steam ID.
2898
/// </summary>
@@ -45,7 +115,7 @@ public async Task<ISteamWebResponse<UGCFileDetailsModel>> GetUGCFileDetailsAsync
45115
var steamWebResponse = await steamWebInterface.GetAsync<UGCFileDetailsResultContainer>("GetUGCFileDetails", 1, parameters);
46116

47117
var steamWebResponseModel = AutoMapperConfiguration.Mapper.Map<
48-
ISteamWebResponse<UGCFileDetailsResultContainer>,
118+
ISteamWebResponse<UGCFileDetailsResultContainer>,
49119
ISteamWebResponse<UGCFileDetailsModel>>(steamWebResponse);
50120

51121
return steamWebResponseModel;
@@ -55,5 +125,28 @@ public async Task<ISteamWebResponse<UGCFileDetailsModel>> GetUGCFileDetailsAsync
55125
return null;
56126
}
57127
}
128+
129+
/// <summary>
130+
/// Sends a request to GetPublishedFileDetails and maps the response's data to <typeparamref name="TData"/>.
131+
/// </summary>
132+
/// <typeparam name="TData">The type to which to map the data of the response.</typeparam>
133+
/// <param name="parameters">The parameters of the request.</param>
134+
/// <returns>The response of the request to the API or <c>null</c> if the request failed.</returns>
135+
private async Task<ISteamWebResponse<TData>> GetPublishedFileDetailsAsync<TData>(IList<SteamWebRequestParameter> parameters) {
136+
try
137+
{
138+
var steamWebResponse = await steamWebInterface.PostAsync<PublishedFileDetailsResultContainer>("GetPublishedFileDetails", 1, parameters);
139+
140+
var steamWebResponseModel = AutoMapperConfiguration.Mapper.Map<
141+
ISteamWebResponse<PublishedFileDetailsResultContainer>,
142+
ISteamWebResponse<TData>>(steamWebResponse);
143+
144+
return steamWebResponseModel;
145+
}
146+
catch (HttpRequestException)
147+
{
148+
return null;
149+
}
150+
}
58151
}
59152
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
using Newtonsoft.Json;
5+
6+
namespace SteamWebAPI2.Models
7+
{
8+
using SteamWebAPI2.Utilities.JsonConverters;
9+
10+
internal class PublishedFileDetailsResultContainer
11+
{
12+
[JsonProperty("response")]
13+
public PublishedFileDetailsResult Result { get; set; }
14+
}
15+
16+
internal class PublishedFileDetailsResult
17+
{
18+
[JsonProperty("result")]
19+
public uint Result { get; set; }
20+
21+
[JsonProperty("resultcount")]
22+
public uint Count { get; set; }
23+
24+
[JsonProperty("publishedfiledetails")]
25+
public IList<PublishedFileDetails> Details { get; set; }
26+
}
27+
28+
internal class PublishedFileDetails
29+
{
30+
[JsonProperty("publishedfileid")]
31+
public ulong PublishedFileId { get; set; }
32+
33+
[JsonProperty("result")]
34+
public uint Result { get; set; }
35+
36+
[JsonProperty("creator")]
37+
public ulong Creator { get; set; }
38+
39+
[JsonProperty("creator_app_id")]
40+
public uint CreatorAppId { get; set; }
41+
42+
[JsonProperty("consumer_app_id")]
43+
public uint ConsumerAppId { get; set; }
44+
45+
[JsonProperty("filename")]
46+
public string FileName { get; set; }
47+
48+
[JsonProperty("file_size")]
49+
public uint FileSize { get; set; }
50+
51+
[JsonProperty("file_url")]
52+
public string FileUrl { get; set; }
53+
54+
[JsonProperty("hcontent_file")]
55+
public ulong FileContentHandle { get; set; }
56+
57+
[JsonProperty("preview_url")]
58+
public string PreviewUrl { get; set; }
59+
60+
[JsonProperty("hcontent_preview")]
61+
public ulong PreviewContentHandle { get; set; }
62+
63+
[JsonProperty("title")]
64+
public string Title { get; set; }
65+
66+
[JsonProperty("description")]
67+
public string Description { get; set; }
68+
69+
[JsonProperty("time_created")]
70+
[JsonConverter(typeof(UnixTimeJsonConverter))]
71+
public DateTime TimeCreated { get; set; }
72+
73+
[JsonProperty("time_updated")]
74+
[JsonConverter(typeof(UnixTimeJsonConverter))]
75+
public DateTime TimeUpdated { get; set; }
76+
77+
[JsonProperty("visibility")]
78+
public uint Visibility { get; set; }
79+
80+
[JsonProperty("banned")]
81+
public bool Banned { get; set; }
82+
83+
[JsonProperty("ban_reason")]
84+
public string BanReason { get; set; }
85+
86+
[JsonProperty("subscriptions")]
87+
public ulong Subscriptions { get; set; }
88+
89+
[JsonProperty("favorited")]
90+
public ulong Favorited { get; set; }
91+
92+
[JsonProperty("lifetime_subscriptions")]
93+
public ulong LifetimeSubscriptions { get; set; }
94+
95+
[JsonProperty("lifetime_favorited")]
96+
public ulong LifetimeFavorited { get; set; }
97+
98+
[JsonProperty("views")]
99+
public ulong Views { get; set; }
100+
101+
[JsonProperty("tags")]
102+
[JsonConverter(typeof(TagsJsonConverter))]
103+
public IList<string> Tags { get; set; }
104+
}
105+
}

src/SteamWebAPI2/SteamWebAPI2.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<ItemGroup>
1515
<PackageReference Include="automapper" Version="6.1.1" />
1616
<PackageReference Include="newtonsoft.json" Version="10.0.3" />
17-
<PackageReference Include="Steam.Models" Version="3.0.4" />
17+
<PackageReference Include="Steam.Models" Version="3.0.6" />
1818
</ItemGroup>
1919

2020
</Project>

src/SteamWebAPI2/Utilities/ISteamWebHttpClient.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,16 @@ public interface ISteamWebHttpClient
88
/// <summary>
99
/// Performs an HTTP GET with the passed URL command.
1010
/// </summary>
11-
/// <param name="command">URL command for GET operation</param>
11+
/// <param name="uri">URL command for GET operation</param>
1212
/// <returns>String response such as JSON or XML</returns>
1313
Task<HttpResponseMessage> GetAsync(string uri);
1414

1515
/// <summary>
1616
/// Performs an HTTP POST with the passed URL command.
1717
/// </summary>
18-
/// <param name="command">URL command for POST operation</param>
18+
/// <param name="uri">URL command for POST operation</param>
19+
/// <param name="content">The HTTP request content sent to the server.</param>
1920
/// <returns>String response such as JSON or XML</returns>
20-
Task<HttpResponseMessage> PostAsync(string uri);
21+
Task<HttpResponseMessage> PostAsync(string uri, HttpContent content);
2122
}
2223
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Reflection;
4+
5+
using Newtonsoft.Json;
6+
7+
namespace SteamWebAPI2.Utilities.JsonConverters
8+
{
9+
/// <inheritdoc />
10+
/// <summary>
11+
/// Converts the tags stored in a list of dictionaries to a list of the values of the dictionary.
12+
/// <remarks>The keys seem to always be the string "tag".</remarks>
13+
/// </summary>
14+
internal class TagsJsonConverter : JsonConverter
15+
{
16+
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
17+
{
18+
throw new NotImplementedException();
19+
}
20+
21+
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
22+
{
23+
var original = serializer.Deserialize<List<Dictionary<string, string>>>(reader);
24+
var tags = new List<string>();
25+
26+
original.ForEach(tag => tags.AddRange(tag.Values));
27+
28+
return tags;
29+
}
30+
31+
public override bool CanWrite => false;
32+
33+
public override bool CanConvert(Type objectType)
34+
{
35+
return typeof(IList<IDictionary<string, string>>).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo());
36+
}
37+
}
38+
}

src/SteamWebAPI2/Utilities/SteamWebHttpClient.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,16 @@ public async Task<HttpResponseMessage> GetAsync(string command)
3838
/// Performs an HTTP POST with the passed URL command.
3939
/// </summary>
4040
/// <param name="command">URL command for POST operation</param>
41+
/// <param name="content">The HTTP request content sent to the server.</param>
4142
/// <returns>String response such as JSON or XML</returns>
42-
public async Task<HttpResponseMessage> PostAsync(string command)
43+
public async Task<HttpResponseMessage> PostAsync(string command, HttpContent content)
4344
{
4445
Debug.Assert(!String.IsNullOrWhiteSpace(command));
4546

4647
HttpClient httpClient = new HttpClient();
4748

48-
var response = await httpClient.PostAsync(command, null);
49-
49+
var response = await httpClient.PostAsync(command, content);
50+
5051
response.EnsureSuccessStatusCode();
5152

5253
if (response.Content == null)

0 commit comments

Comments
 (0)