Skip to content

Commit

Permalink
Hey folks, now it's possible to query for the achievements of a game,…
Browse files Browse the repository at this point in the history
… happy querying!

+ I included a simple demo-project, I will upgrade this over time too to represent a good demo.
  • Loading branch information
liebki committed Aug 11, 2022
1 parent c12263d commit e33a429
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 14 deletions.
8 changes: 7 additions & 1 deletion RawgNET.sln
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31919.166
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RawgNET", "RawgNET\RawgNET.csproj", "{F98FECB0-CF7C-4A17-8188-AB2CD440F6DF}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RawgNET", "RawgNET\RawgNET.csproj", "{F98FECB0-CF7C-4A17-8188-AB2CD440F6DF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RawgNetDemo", "RawgNetDemo\RawgNetDemo.csproj", "{6E47775F-8C05-443E-BB2B-A21D8D1F3DC2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -15,6 +17,10 @@ Global
{F98FECB0-CF7C-4A17-8188-AB2CD440F6DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F98FECB0-CF7C-4A17-8188-AB2CD440F6DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F98FECB0-CF7C-4A17-8188-AB2CD440F6DF}.Release|Any CPU.Build.0 = Release|Any CPU
{6E47775F-8C05-443E-BB2B-A21D8D1F3DC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6E47775F-8C05-443E-BB2B-A21D8D1F3DC2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6E47775F-8C05-443E-BB2B-A21D8D1F3DC2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6E47775F-8C05-443E-BB2B-A21D8D1F3DC2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
8 changes: 8 additions & 0 deletions RawgNET/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ namespace RawgNET
{
public class Game
{
public bool AchievementsAvailable { get; set; }
public List<Result>? Achievements { get; set; }

[JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)]
public long? Id { get; set; }

Expand Down Expand Up @@ -165,6 +168,11 @@ public class Game

[JsonProperty("description_raw", NullValueHandling = NullValueHandling.Ignore)]
public string DescriptionRaw { get; set; }

public override string ToString()
{
return $"{{{nameof(AchievementsAvailable)}={AchievementsAvailable}, {nameof(Achievements)}={Achievements}, {nameof(Id)}={Id}, {nameof(Slug)}={Slug}, {nameof(Name)}={Name}, {nameof(NameOriginal)}={NameOriginal}, {nameof(Description)}={Description}, {nameof(Metacritic)}={Metacritic}, {nameof(MetacriticPlatforms)}={MetacriticPlatforms}, {nameof(Released)}={Released}, {nameof(Tba)}={Tba}, {nameof(Updated)}={Updated}, {nameof(BackgroundImage)}={BackgroundImage}, {nameof(BackgroundImageAdditional)}={BackgroundImageAdditional}, {nameof(Website)}={Website}, {nameof(Rating)}={Rating}, {nameof(RatingTop)}={RatingTop}, {nameof(Ratings)}={Ratings}, {nameof(Reactions)}={Reactions}, {nameof(Added)}={Added}, {nameof(AddedByStatus)}={AddedByStatus}, {nameof(Playtime)}={Playtime}, {nameof(ScreenshotsCount)}={ScreenshotsCount}, {nameof(MoviesCount)}={MoviesCount}, {nameof(CreatorsCount)}={CreatorsCount}, {nameof(AchievementsCount)}={AchievementsCount}, {nameof(ParentAchievementsCount)}={ParentAchievementsCount}, {nameof(RedditUrl)}={RedditUrl}, {nameof(RedditName)}={RedditName}, {nameof(RedditDescription)}={RedditDescription}, {nameof(RedditLogo)}={RedditLogo}, {nameof(RedditCount)}={RedditCount}, {nameof(TwitchCount)}={TwitchCount}, {nameof(YoutubeCount)}={YoutubeCount}, {nameof(ReviewsTextCount)}={ReviewsTextCount}, {nameof(RatingsCount)}={RatingsCount}, {nameof(SuggestionsCount)}={SuggestionsCount}, {nameof(AlternativeNames)}={AlternativeNames}, {nameof(MetacriticUrl)}={MetacriticUrl}, {nameof(ParentsCount)}={ParentsCount}, {nameof(AdditionsCount)}={AdditionsCount}, {nameof(GameSeriesCount)}={GameSeriesCount}, {nameof(UserGame)}={UserGame}, {nameof(ReviewsCount)}={ReviewsCount}, {nameof(SaturatedColor)}={SaturatedColor}, {nameof(DominantColor)}={DominantColor}, {nameof(ParentPlatforms)}={ParentPlatforms}, {nameof(Platforms)}={Platforms}, {nameof(Stores)}={Stores}, {nameof(Developers)}={Developers}, {nameof(Genres)}={Genres}, {nameof(Tags)}={Tags}, {nameof(Publishers)}={Publishers}, {nameof(EsrbRating)}={EsrbRating}, {nameof(Clip)}={Clip}, {nameof(DescriptionRaw)}={DescriptionRaw}}}";
}
}

public partial class AddedByStatus
Expand Down
37 changes: 37 additions & 0 deletions RawgNET/GameAchievement.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Newtonsoft.Json;

namespace RawgNET
{
public class GameAchievement
{
[JsonProperty("count", NullValueHandling = NullValueHandling.Ignore)]
public long? Count { get; set; }

[JsonProperty("next", NullValueHandling = NullValueHandling.Ignore)]
public Uri Next { get; set; }

[JsonProperty("previous")]
public object Previous { get; set; }

[JsonProperty("results", NullValueHandling = NullValueHandling.Ignore)]
public List<Result> Results { get; set; }
}

public class Result
{
[JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)]
public long? Id { get; set; }

[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; set; }

[JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)]
public string Description { get; set; }

[JsonProperty("image", NullValueHandling = NullValueHandling.Ignore)]
public Uri Image { get; set; }

[JsonProperty("percent", NullValueHandling = NullValueHandling.Ignore)]
public string Percent { get; set; }
}
}
19 changes: 12 additions & 7 deletions RawgNET/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@

# RawgNET
An API-Wrapper to get a game including all it's data from https://rawg.io
A wrapper for the API of wrag.io, to get a game including all it's data

## Technologies

Expand All @@ -12,6 +11,9 @@ An API-Wrapper to get a game including all it's data from https://rawg.io

## Features

### New
- Thanks to sgamesdev, I got reminded that the achievements are missing, those are included by now

### General
- Get a "Game" object including the complete data like images, description and more..

Expand All @@ -20,12 +22,16 @@ An API-Wrapper to get a game including all it's data from https://rawg.io
## Example

```
using (RawgClient client = new(new RawgClientOptions("API KEY OF RAWG.IO")))
using (RawgClient client = new(new RawgClientOptions("YOUR KEY FROM https://rawg.io/login?forward=developer")))
{
Game game = client.GetGameData("NAME OF GAME");
string query = "gtav";
Console.WriteLine($"Querying for: {query}");
Game game = client.GetGameData(query, true);
if (!object.Equals(game, null))
{
Console.WriteLine("Imagelink: " + game.BackgroundImage);
Console.WriteLine($"Output for: {game.Name} | {game.NameOriginal}\n");
Console.WriteLine(game.ToString());
}
}
```
Expand All @@ -52,7 +58,6 @@ At https://rawg.io/apidocs just press the "Get API Key" button.

## Roadmap

- Speed up code
- Make code more clean
- Make code more clean especially the ""RawgRequest"" method!
- Export "Newtonsoft.Json" nuget package with library
- More to come..
121 changes: 119 additions & 2 deletions RawgNET/RawgAccessManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@ internal class RawgAccessManager
{
private const string RawgApiBaseUrl = "https://rawg.io/api/games/";

internal static Game RawgRequest(string name, string rawgkey)
/// <summary>
/// The main method, where we get our data from
/// </summary>
/// <param name="name">Name of the game we'd like to query</param>
/// <param name="rawgkey">Your API-Key</param>
/// <param name="getAchievements">If we want to query for the achievements (takes a second longer)</param>
/// <returns></returns>
internal static Game RawgRequest(string name, string rawgkey, bool getAchievements)
{
Game? GameReturnValue = null;
Task<Game> QueryTryGame = Task.Run(() => QueryGame(name, rawgkey));
Expand All @@ -29,10 +36,72 @@ internal static Game RawgRequest(string name, string rawgkey)
{
GameReturnValue.Metacritic = 0;
}

GameReturnValue.AchievementsAvailable = false;
GameReturnValue.Achievements = new();

if (getAchievements)
{
Task<GameAchievement> gameAchievementQuery = Task.Run(() => QueryAchievements(GameReturnValue.Slug, rawgkey));
QueryTryGame.Wait();

if (gameAchievementQuery.Result.Count > 0)
{
List<Result> AchievementList = new();
GameReturnValue.AchievementsAvailable = true;
AchievementList.AddRange(gameAchievementQuery.Result.Results);
AchievementList.AddRange(QueryAllAchievements(gameAchievementQuery, new()));
GameReturnValue.Achievements = AchievementList;
}
}
}
return GameReturnValue;
}

/// <summary>
/// Recursive method, to get every achievement of a game
/// </summary>
/// <param name="gameAchievementQuery">The previous Achievement-Object</param>
/// <param name="AchievementList">The previous Achievement-List</param>
/// <returns></returns>
private static List<Result> QueryAllAchievements(Task<GameAchievement> gameAchievementQuery, List<Result> AchievementList)
{
Task<GameAchievement> achievementQuery = Task.Run(() => QueryMoreAchievements(gameAchievementQuery.Result.Next.AbsoluteUri));
achievementQuery.Wait();
List<Result> AllAchievements = AchievementList;
AllAchievements.AddRange(achievementQuery.Result.Results);
if (achievementQuery.Result.Next?.AbsoluteUri.Contains("page=") == true)
{
QueryAllAchievements(achievementQuery, AllAchievements);
}
return AllAchievements;
}

private static async Task<GameAchievement> QueryMoreAchievements(string page)
{
string JsonResponse = "";
using (HttpClient Client = new())
{
Task<HttpResponseMessage> TaskResponse = Client.GetAsync(page);
TaskResponse.Wait();
JsonResponse = await TaskResponse.Result.Content.ReadAsStringAsync();
}
return DeserializeGameAchievementJson(JsonResponse);
}

private static async Task<GameAchievement> QueryAchievements(string gamename, string rawgkey)
{
string RawgRequestUrl = GameNameToAchievementQueryUrl(gamename, rawgkey);
string JsonResponse = "";
using (HttpClient Client = new())
{
Task<HttpResponseMessage> TaskResponse = Client.GetAsync(RawgRequestUrl);
TaskResponse.Wait();
JsonResponse = await TaskResponse.Result.Content.ReadAsStringAsync();
}
return DeserializeGameAchievementJson(JsonResponse);
}

private static async Task<GameFallback> QueryFallback(string gamename, string rawgkey)
{
string RawgRequestUrl = GameNameToQueryUrl(gamename, rawgkey);
Expand All @@ -59,6 +128,30 @@ private static async Task<Game> QueryGame(string gamename, string rawgkey)
return DeserializeGameJson(JsonResponse);
}

/// <summary>
/// Method to build a ready-to-query url (achievements)
/// </summary>
/// <param name="gamename">Name of the game we'd like to query</param>
/// <param name="rawgkey">Your API-Key</param>
/// <returns></returns>
private static string GameNameToAchievementQueryUrl(string gamename, string rawgkey)
{
string GameName = gamename;
GameName = GameName.ToLower();
if (gamename.Contains(' '))
{
GameName = GameName.Replace(" ", "-");
}
string reqUrl = RawgApiBaseUrl + GameName + $"/achievements?key={rawgkey}";
return reqUrl;
}

/// <summary>
/// Method to build a ready-to-query url (games)
/// </summary>
/// <param name="gamename">Name of the game we'd like to query</param>
/// <param name="rawgkey">Your API-Key</param>
/// <returns></returns>
private static string GameNameToQueryUrl(string gamename, string rawgkey)
{
string GameName = gamename;
Expand All @@ -67,10 +160,29 @@ private static string GameNameToQueryUrl(string gamename, string rawgkey)
{
GameName = GameName.Replace(" ", "-");
}
string reqUrl = RawgApiBaseUrl + GameName + "?search_precise=false&search_exact=false&key=" + rawgkey;
string reqUrl = RawgApiBaseUrl + GameName + $"?search_precise=false&search_exact=false&key={rawgkey}";
return reqUrl;
}

/// <summary>
/// This method gives us a GameAchievement-Object from a Json-String
/// </summary>
/// <param name="json">The Json-String</param>
/// <returns></returns>
private static GameAchievement? DeserializeGameAchievementJson(string json)
{
if (!object.Equals(json, null))
{
return JsonConvert.DeserializeObject<GameAchievement>(json);
}
return null;
}

/// <summary>
/// This method gives us a GameFallback-Object from a Json-String
/// </summary>
/// <param name="json">The Json-String</param>
/// <returns></returns>
private static GameFallback? DeserializeGameFallbackJson(string json)
{
if (!object.Equals(json, null))
Expand All @@ -80,6 +192,11 @@ private static string GameNameToQueryUrl(string gamename, string rawgkey)
return null;
}

/// <summary>
/// This method gives us a Game-Object from a Json-String
/// </summary>
/// <param name="json">The Json-String</param>
/// <returns></returns>
private static Game? DeserializeGameJson(string json)
{
if (!object.Equals(json, null))
Expand Down
10 changes: 8 additions & 2 deletions RawgNET/RawgClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,20 @@ public void Dispose()
GC.SuppressFinalize(this);
}

public Game GetGameData(string gamename)
/// <summary>
/// The publicy available method that is called
/// </summary>
/// <param name="gamename">Name of the game we'd like to query</param>
/// <param name="getAchievements">If we want to query for the achievements (takes a second longer)</param>
/// <returns></returns>
public Game GetGameData(string gamename, bool getAchievements)
{
Game game;
if (!object.Equals(options.APIKEY, null) && options.APIKEY.Length > 10)
{
if (!object.Equals(gamename, null) && gamename.Length > 1)
{
game = RawgAccessManager.RawgRequest(gamename, options.APIKEY);
game = RawgAccessManager.RawgRequest(gamename, options.APIKEY, getAchievements);
}
else
{
Expand Down
4 changes: 2 additions & 2 deletions RawgNET/RawgClientOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
{
public class RawgClientOptions
{
public RawgClientOptions(string? aPIKEY)
public RawgClientOptions(string? apikey)
{
APIKEY = aPIKEY;
APIKEY = apikey;
}

public string? APIKEY { get; set; }
Expand Down
23 changes: 23 additions & 0 deletions RawgNetDemo/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using RawgNET;

namespace RawgNetDemo
{
internal class Program
{
private static void Main(string[] args)
{
using (RawgClient client = new(new RawgClientOptions("YOUR KEY FROM https://rawg.io/login?forward=developer")))
{
string query = "gtav";
Console.WriteLine($"Querying for: {query}");

Game game = client.GetGameData(query, true);
if (!object.Equals(game, null))
{
Console.WriteLine($"Output for: {game.Name} | {game.NameOriginal}\n");
Console.WriteLine(game.ToString());
}
}
}
}
}
14 changes: 14 additions & 0 deletions RawgNetDemo/RawgNetDemo.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\RawgNET\RawgNET.csproj" />
</ItemGroup>

</Project>

0 comments on commit e33a429

Please sign in to comment.