Giter Site home page Giter Site logo

warcraft's Introduction

Argent Pony Warcraft Client

The Argent Pony Warcraft Client is a .NET client for the Blizzard World of Warcraft APIs. It lets .NET applications easily access information about World of Warcraft characters, guilds, items, spells, and more. It is a .NET Standard 2.0 library, which means it supports a broad range of platforms, including .NET 8 (long term support), and .NET Framework 4.6.2+.

NuGet version build CodeQL

Documentation

Documentation is available at https://blizzard-net.github.io/warcraft/

Quick Start

Create a new Console Application in Visual Studio or via dotnet new.

dotnet new console --name QuickStart

Add the ArgentPonyWarcraftClient NuGet package to the project:

dotnet add QuickStart package ArgentPonyWarcraftClient

Update Program.cs in the new project as follows, subsituting your own client ID and secret from Blizzard's Getting Started instructions:

using System;
using System.Threading.Tasks;
using ArgentPonyWarcraftClient;

namespace QuickStart
{
    class Program
    {
        static async Task Main(string[] args)
        {
            // Secrets from https://develop.battle.net/documentation/guides/getting-started.
            string clientId = "MY-CLIENT-ID-GOES-HERE";
            string clientSecret = "MY-CLIENT-SECRET-GOES-HERE";
            var warcraftClient = new WarcraftClient(clientId, clientSecret);

            // Retrieve the character profile for Drinian of realm Norgannon.
            RequestResult<CharacterProfileSummary> result =
                await warcraftClient.GetCharacterProfileSummaryAsync("norgannon", "drinian", "profile-us");

            // If we got it, display the level.
            if (result.Success)
            {
                CharacterProfileSummary profile = result.Value;
                Console.WriteLine($"Level for {profile.Name}: {profile.Level}");
            }
        }
    }
}

Build and run the console application.

cd QuickStart
dotnet run

The console output displays the profile data that was retrieved from the Blizzard Character Profile API. The library supports many other APIs, too.

Level for Drinian: 70

warcraft's People

Contributors

danjagnow avatar willwolfram18 avatar travisboatman avatar bonesoul avatar yschuurmans avatar cancri55e avatar andyjmorgan avatar

Stargazers

 avatar  avatar Ruslan Kalashnikov avatar  avatar  avatar Artem avatar  avatar Milena avatar Jon avatar Mark Devlin avatar  avatar  avatar Michael Livingstone avatar Alex Bobryshev avatar  avatar Arkadiusz Pazoła avatar Cezar Cretu avatar Erik Shafer avatar Eric Batlle avatar FJ avatar KuriyamaMirai avatar Sean McLellan avatar Max avatar  avatar Robert Krency avatar  avatar  avatar  avatar norbertka avatar  avatar Anthony Ryckembusch avatar A avatar Joseph Esmaail avatar  avatar

Watchers

James Cloos avatar  avatar Robert Krency avatar  avatar  avatar Arkadiusz Pazoła avatar

warcraft's Issues

Add support for Auction API

Add support for the Auction API. Gathering auction data is a two step process that involves checking a timestamp to avoid downloading stale data unnecessarily.

Game Data API Usage

One of the big differences in the Game Data API json responses are the links.

For example...

{
    "_links": {
        "self": {
            "href": "https://us.api.battle.net/data/wow/connected-realm/11?namespace=dynamic-us"
        }
    },
    "id": 11,
    "has_queue": false,
    "status": {
        "type": "UP",
        "name": "Up"
    },
    "population": {
        "type": "FULL",
        "name": "Full"
    },
    "realms": [{
        "id": 11,
        "region": {
            "key": {
                "href": "https://us.api.battle.net/data/wow/region/1?namespace=dynamic-us"
            },
            "name": "North America",
            "id": 1
        },
        "connected_realm": {
            "href": "https://us.api.battle.net/data/wow/connected-realm/11?namespace=dynamic-us"
        },
        "name": "Tichondrius",
        "category": "United States",
        "locale": "enUS",
        "timezone": "America/Los_Angeles",
        "type": {
            "type": "PVP",
            "name": "PvP"
        },
        "is_tournament": false,
        "slug": "tichondrius"
    }],
    "mythic_leaderboards": {
        "href": "https://us.api.battle.net/data/wow/connected-realm/11/mythic-leaderboard/?namespace=dynamic-us"
    }
}

There are 4 links in this response. self, region/key, connected_realm and mythic_leaderboards.

These links are the API endpoints for whatever the json context may be. For example the mythic_leaderboards link will get the mythic leaderboards for the Tichondrius realm because Tichondrius is the realm that was requested.

These links can be useful in some scenarios. For example if I wasn't using an API wrapper. However I believe these links are not necessary to include in our API. Should we keep them or remove?

Summary Docs Convention Proposal

This is purely my personal opinion but I prefer to have summary docs to be indented like in InternalHttpClient.cs. So I wanted to get your opinion on the matter to.

Display Errors back to the Caller

Currently if you were to search for a spell, character, realm, or anything that doesn't exist the program will throw an exception. In WarcraftClient.cs line 955 response.EnsureSuccessStatusCode();. Although Blizzard's API will have the status code 404 it will still send a response back like so...

{
    "status": "nok",
    "reason": "unable to get spell information."
}

It would be nice to be able to send that information back to the caller so that if needed they can display the specific error reason. This is my proposal on how to make it happen and would love some feedback on it.

First create an Error.cs class with the Status and Reason properties. Then have all models inherit from it. The caller method can now check if the Status property is null, if so it succeeded. If not then they can grab the Reason property and display it back to the end-user.

This way feels a bit clunky, I don't really like it but it works.

Character Media API

Missing API - Character Media API
/profile/wow/character/{realmSlug}/{characterName}/character-media

{ "_links": { "self": { "href": "<URL>" } }, "character": { "key": { "href": "<URL>" }, "name": "<Name>", "id": <Id>, "realm": { "key": { "href": "<URL>" }, "name": "<Name>", "id": <Id>, "slug": "<realm>" } }, "avatar_url": "<URL>", "bust_url": "<URL>", "render_url": "<URL>" }

Cheers :)

Returning incorrect level

For some reason, the API seems to be returning an incorrect level for any character 100 and over.

12/02/2018 23:30:37 (52/98) Loading Emmara on Caelestrasz...
12/02/2018 23:30:39 Emmara is a level 13 Human Paladin on Caelestrasz .

That character should be returning 110 for their level.

App freezes when trying to access statistics

Now, I will 100% admit that I am new to using lists in C#, so I apologise if my code is bad.

Right now I have

long kills = x.Statistics.SubCategories[135].Statistics[107].Quantity;

The idea is to assign the total number of creature kills to the kills variable, but the API freezes the program when it gets here.

Api freezes if character doesn't exist.

I have the following code

Character x = await client.GetCharacterAsync(realm, charactername, CharacterFields.All);
if (x.Name == null)
{
Console.ForegroundColor = ConsoleColor.Red;
Program.Log($"Error retrieving {charactername}'s information.\nThey may not be level ten yet.\nProceeding to next character...");
Console.ForegroundColor = ConsoleColor.White;
Stats.Levels.lowlevel += 1;
Runtime.errorcharacters = Runtime.errorcharacters + $"Name: {charactername}; Realm: {realm}; Account: {account}\n";
return;
}

It works perfectly on characters that are at least level 10....

But nothing happens if the character is under level 10, or has been deleted. It just sits there. Mine sat there for over 10 minutes, when I want the api to trigger the if statement if the character doesn't exist on the armory.

Thanks.

Nuget installation error

When trying to install the latest version (5.1.0) with nuget I get the following error:
Ausnahme "System.AggregateException" beim Versuch, die Quelle "https://dotnet.myget.org/F/roslyn/api/v3/index.json" hinzuzufügen.
Der Dienstindex für die Quelle "https://dotnet.myget.org/F/roslyn/api/v3/index.json" konnte nicht geladen werden.
Der Antwortstatuscode gibt keinen Erfolg an: 404 (Feed does not exist.).

which roughly translates into: Exception "System.AggregateException" occured while trying to add source "https://dotnet.myget.org/F/roslyn/api/v3/index.json". Serviceindex for source "https://dotnet.myget.org/F/roslyn/api/v3/index.json" could not be loaded. Responsecode was not successful: 404 (Feed does not exist).

Any help would be appreciated.

GetCharactersAsync returns nothing

There is a fair to good chance that I am just using this wrong, but I am getting no characters returned , or even an error returned, when using GetCharactersAsync(string accessToken).

The RequestResult does have Success set to false, but the Error does not have it's properties populated and Value is null.

I stepped through the methods myself, and the Get method receives the correct URL with the users access token at the end, but then it gets its own token via GetOAuthToken and puts that token into the header.

When the access_token parameter and the Authorization header are different, I get an unauthorized response from Blizzard, but when I was stepping through the method and changed _token to be the same as the access_token parameter, I was able to retrieve all of the characters.

Is there somewhere else that I should be setting the _token object?

First test returns error 403

Hi, this code (clientId and clientSecret contains my newly created Client):

Dim clientId As String = "..."
Dim clientSecret As String = "..."
wc = New WarcraftClient(clientId, clientSecret, ArgentPonyWarcraftClient.Region.Europe, Locale.de_DE)
Dim result As RequestResult(Of Character) = Await wc.GetCharacterAsync("Dun Morogh", "Forgi", CharacterFields.All)

results in

System.Net.Http.HttpRequestException: 'Response code 403 (Forbidden) does not indicate success. Request: https://eu.api.blizzard.com/wow/character/Dun Morogh/Forgi?&locale=de_DE&fields=achievements,appearance,feed,guild,hunter pets,items,mounts,pets,pet slots,professions,progression,pvp,quests,reputation,statistics,stats,talents,titles,audit'

What am I doing wrong?

Add support for new Game Data and Profile Data API endpoints

Add support for new the new Game Data API and Profile API endpoints described here:

https://develop.battle.net/documentation/world-of-warcraft/community-api-migration-status

Game Data APIs

  • Achievements
  • Auction House
  • Battlegroups (deprecated)
  • Bosses
  • Challenge Mode Realm Leaderboard
  • Challenge Mode Region Leaderboard (deprecated)
  • Character Classes
  • Character Races
  • Guild Perks (deprecated)
  • Guild Rewards (deprecated)
  • Item
  • Item Classes
  • Item Set
  • Mounts
  • Pet Abilities
  • Pet Species
  • Pet Stats
  • Pet Types
  • Pets
  • PvP Leaderboards
  • Quest
  • Realm Status
  • Recipe
  • Spell
  • Talents
  • Zones

Profile APIs

  • User Characters
  • Character Profile
  • Character Achievements
  • Character Appearance
  • Character Audit (deprecated)
  • Character Feed (deprecated)
  • Character Guild
  • Character Hunter Pets
  • Character Items
  • Character Mounts
  • Character Pets
  • Character Pet Slots
  • Character Professions
  • Character Progression
  • Character PvP
  • Character Quests
  • Character Reputation
  • Character Statistics
  • Character Stats
  • Character Talents
  • Character Titles
  • Guild Profile
  • Guild Members
  • Guild Achievements
  • Guild News
  • Guild Challenge (deprecated)

Help wanted: Testing and improvements for 4.0 milestone

The library is almost ready for the 4.0 milestone. Now is the time to identify problems and make any final breaking changes. Please test the 4.0.0-alpha.7 preview release and add comments here or create new issues for any problems you find.

  • Do any of the methods produce errors for certain inputs (i.e., for JSON elements that are not always present)?
  • Are there any missing APIs that need to be covered?
  • Should any data types be changed (i.e., long to int in several places, or long to DateTime for timestamps)?
  • Are any classes, properties, or interfaces badly named? For example, does it make sense to have ItemReference and ItemReferenceWithoutName classes just because some APIs never return some properties?
  • Are convenience methods needed for retrieving related information or media?

Add Starcraft and Diablo API

The total number of Starcraft and Diablo API endpoints is eleven, 5 for Diablo and 6 for Stacraft. It would be very easy to implement. Just create a new Stacraft and Diablo client, add a few models, and use preexisting utilities. The only "problem" is that this is outside the scope of the project. And would change what this project it about. Would you want to look into doing this?

Character Media response has changed

Now contains an array of character assets (Asset[])

e.g.:

"assets": [
    {
      "key": "avatar",
      "value": "https://render-us.worldofwarcraft.com/character/realmSlug/24/id-avatar.jpg"
    },
    {
      "key": "inset",
      "value": "https://render-us.worldofwarcraft.com/character/realmSlug/24/id-inset.jpg"
    },
    {
      "key": "main",
      "value": "https://render-us.worldofwarcraft.com/character/realmSlug/24/id-main.jpg"
    },
    {
      "key": "main-raw",
      "value": "https://render-us.worldofwarcraft.com/character/realmSlug/24/id-main-raw.png"
    }
  ]

AppVeyor builds fail on pull request builds

AppVeyor builds do not decrypt secure variables for pull request builds. This is a good security feature, but inconvenient. Because the blizzardApiKey environment variable in appveyor.xml does not get decoded for those builds, the unit tests (integration tests) all fail.

You could determine whether to skip the tests by figuring out whether you are in an AppVeyor build and whether the API key is present as follows...

private readonly string _apiKey;
private readonly bool _skipTests;

public WarcraftClientTests()
{
    IConfigurationRoot configuration = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json", optional: true)
        .AddEnvironmentVariables()
        .Build();

    _apiKey = configuration["blizzardApiKey"];

    // Skip unit tests if this is an AppVeyor build and the API key is not present, which occurs
    // for pull requests builds.  See https://www.appveyor.com/docs/build-configuration/#secure-variables.
    bool isAppVeyorBuild = string.Equals(configuration["APPVEYOR"], "True", StringComparison.OrdinalIgnoreCase);
    _skipTests = isAppVeyorBuild && _apiKey == null;
}

... but then you would need to prefix every test with something like this:

if (_skipTests)
{
    return;
}

That would create the false confidence of showing green tests that were really just skipped.

An alternative would be to create an API key, store it in plain text, and hope that Blizzard doesn't shut it down. Another option would be to mock the Blizzard API, which would be fast and stable, but which would not tell you when the API changes. I'm not wild about any of those approaches. Suggestions welcome.

Use System.Text.Json

Migrating over to the new JSON library by Microsoft can have significant performance benefits compared to Newtonsoft.Json.

Scenario Speed Memory
Deserialization 2x faster Parity or lower
Serialization 1.5x faster Parity or lower
Document (read-only) 3-5x faster ~Allocation free for sizes < 1 MB
Reader 2-3x faster ~Allocation free (until you materialize values)
Writer 1.3-1.6x faster ~Allocation free

I have done some preliminary work. Migration has been straightforward however there are a few places where a custom converter is needed. Whereas Newtonsoft.Json had the feature built in.

Even though we have unit tests we should do some manual QA before releasing due to the major scope of this change.

Additionally, using this new JSON library requires netstandard2.0.

403

namespace Discord_bot_blizzard_api
{
    public class Program
    {
        public static void Main(string[] args)
        {
            GetWarcraftCharacterInfo();
            CreateHostBuilder(args).Build().Run();
            
        }

        private static async void GetWarcraftCharacterInfo()
        {
            string clientId = "my_client_id_was_there";
            string clientSecret = "my_client_secret_was_there";
            var warcraftClient = new WarcraftClient(clientId, clientSecret, Region.US, Locale.en_US);

            RequestResult<Character> result = await warcraftClient.GetCharacterAsync("Norgannon", "Drinian", CharacterFields.All);
// 403 error there, ofc I tried my character too, I checked right realm name, region etc via Blizzard API 's test page.
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

Question: Why use a singleton?

What's the purpose of maintaining a singleton instance of the HttpClient with the InternalHttpClient? Is this a performance gain, or some other reason? Why not instead do the HttpClient initialization in the WarcraftClient's constructor and have the class implement IDisposable and dispose of the client then?

Enable nullable reference types

I'm interested in adding nullable reference type support for the warcraft client project. This would help in communicating the fact that the API models are sometimes sparse. This would allow API consumers to be better aware of the fact that some values may be null when retrieved from blizzard, for example the SpellTooltip model has properties like PowerCost or CastTime that are sometimes omitted from the API responses or come back with a value of null, and describing those values as string? instead of string would make it slightly more visible to consumers.

Unable to mock WarcraftClient

First of all, nice work! I was trying to work on something similar, but this solution seems much nicer!

Description

Unfortunately the implementation doesn't support mocking, at the very least with the use of the Moq library. Without support for mocking, individuals won't be able to write unit tests for their code when they use this library, which may limit adoption.

Failed   If_Request_Is_Successful_Then_Guild_Name_Is_Returned
Error Message:
 System.NotSupportedException : Invalid setup on a non-virtual (overridable in VB) member: c => c.GetCharacterAsync(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<CharacterFields>())
Stack Trace:
   at Moq.Mock.ThrowIfSetupExpressionInvolvesUnsupportedMember(Expression setup, MethodInfo method) in C:\projects\moq4\Source\Mock.cs:line 954
   at Moq.Mock.SetupPexProtected[T,TResult](Mock`1 mock, Expression`1 expression, Condition condition) in C:\projects\moq4\Source\Mock.cs:line 543
   at Moq.Mock.Setup[T,TResult](Mock`1 mock, Expression`1 expression, Condition condition) in C:\projects\moq4\Source\Mock.cs:line 526
   at ArgentPonyTest.Test.<If_Request_Is_Successful_Then_Guild_Name_Is_Returned>d__3.MoveNext() in C:\Projects\Scratchpad\ArgentPonyTest\ArgentPonyTest\Test.cs:line 37
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at NUnit.Framework.Internal.AsyncInvocationRegion.AsyncTaskInvocationRegion.WaitForPendingOperationsToComplete(Object invocationResult) in C:\src\nunit\nunit\src\NUnitFramework\framework\Internal\AsyncInvocationRegion.cs:line 113
   at NUnit.Framework.Internal.Commands.TestMethodCommand.RunAsyncTestMethod(TestExecutionContext context) in C:\src\nunit\nunit\src\NUnitFramework\framework\Internal\Commands\TestMethodCommand.cs:line 96

Steps to reproduce

I created a minimal example of the issue here.

Possible Solutions

  • One option, which would be the simpler approach, is to change all methods to virtual. However this may be less than ideal because someone could inherit from the WarcraftClient and override those methods. Granted, that puts the error on the implementer, but the possibility exists.
  • Create simple interfaces which represent the methods on the WarcraftClient such as
public interface IWarcraftClient
{
    Task<RequestResult<Character>> GetCharacterAsync(string realm, string characterName, CharacterFields fields = CharacterFields.None);
}

public class WarcraftClient : IWarcraftClient
{
    // Existing code
}

This may be a better solution for 2 reasons:

  1. Interfaces are well supported by Moq meaning it solves the initial problem
  2. Mocking an interface doesn't require using the class's constructor.
    • What I mean by that is mentioned in this SO answer; if you're mocking the client, it's helpful to only need to mock the interface instead of the class itself.

I am happy to take on fixing this task, and would opt for implementing the second solution.

Wow China URL not right

Per there API doc they use gateway.battlenet.com.cn/{API path} for china
seems your code is calling cn.api.blizzard.com/{API path}
Which causes it to error out

CraftedItem in GetRecipeAsync is sometimes null

In the response body for GetRecipeAsync there is not always a field "crafted_item". Sometimes (ex. recipeId 38729, Monel-Hardened Boots) this field doesn't exist, instead there are two fields "alliance_crafted_item" and "horde_crafted_item".
It would be nice, if you could integrate these fields too.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.