Added support for player lookup on official hiscores.
This commit is contained in:
9
osrs-toolbox/APIs/Runescape/DataModels/Activity.cs
Normal file
9
osrs-toolbox/APIs/Runescape/DataModels/Activity.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace osrs_toolbox
|
||||
{
|
||||
public class Activity : IPlayerInfoProperty
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int Rank { get; set; }
|
||||
public int Score { get; set; }
|
||||
}
|
||||
}
|
9
osrs-toolbox/APIs/Runescape/DataModels/Boss.cs
Normal file
9
osrs-toolbox/APIs/Runescape/DataModels/Boss.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace osrs_toolbox
|
||||
{
|
||||
public class Boss : IPlayerInfoProperty
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int Rank { get; set; }
|
||||
public int Kills { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
namespace osrs_toolbox
|
||||
{
|
||||
public interface IPlayerInfoProperty
|
||||
{
|
||||
|
||||
}
|
||||
}
|
190
osrs-toolbox/APIs/Runescape/DataModels/PlayerInfo.cs
Normal file
190
osrs-toolbox/APIs/Runescape/DataModels/PlayerInfo.cs
Normal file
@@ -0,0 +1,190 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Reflection;
|
||||
|
||||
namespace osrs_toolbox
|
||||
{
|
||||
public class PlayerInfo
|
||||
{
|
||||
private static readonly Skill InitialSkillState = new Skill { Rank = -1, Level = 1, Experience = 1 };
|
||||
private static readonly Activity InitialActivityState = new Activity { Rank = -1, Score = -1 };
|
||||
private static readonly Boss InitialBossState = new Boss { Rank = -1, Kills = -1 };
|
||||
|
||||
public string Name { get; set; } = "";
|
||||
public PlayerInfoStatus Status { get; internal set; } = PlayerInfoStatus.Unknown;
|
||||
public PlayerType AccountType { get; internal set; } = PlayerType.Unknown;
|
||||
|
||||
//skills
|
||||
public Skill Overall { get; set; } = InitialSkillState;
|
||||
public Skill Attack { get; set; } = InitialSkillState;
|
||||
public Skill Defence { get; set; } = InitialSkillState;
|
||||
public Skill Strength { get; set; } = InitialSkillState;
|
||||
public Skill Hitpoints { get; set; } = InitialSkillState;
|
||||
public Skill Ranged { get; set; } = InitialSkillState;
|
||||
public Skill Prayer { get; set; } = InitialSkillState;
|
||||
public Skill Magic { get; set; } = InitialSkillState;
|
||||
public Skill Cooking { get; set; } = InitialSkillState;
|
||||
public Skill Woodcutting { get; set; } = InitialSkillState;
|
||||
public Skill Fletching { get; set; } = InitialSkillState;
|
||||
public Skill Fishing { get; set; } = InitialSkillState;
|
||||
public Skill Firemaking { get; set; } = InitialSkillState;
|
||||
public Skill Crafting { get; set; } = InitialSkillState;
|
||||
public Skill Smithing { get; set; } = InitialSkillState;
|
||||
public Skill Mining { get; set; } = InitialSkillState;
|
||||
public Skill Herblore { get; set; } = InitialSkillState;
|
||||
public Skill Agility { get; set; } = InitialSkillState;
|
||||
public Skill Thieving { get; set; } = InitialSkillState;
|
||||
public Skill Slayer { get; set; } = InitialSkillState;
|
||||
public Skill Farming { get; set; } = InitialSkillState;
|
||||
public Skill Runecrafting { get; set; } = InitialSkillState;
|
||||
public Skill Hunter { get; set; } = InitialSkillState;
|
||||
public Skill Construction { get; set; } = InitialSkillState;
|
||||
|
||||
//minigames
|
||||
public Activity LeaguePoints { get; set; } = InitialActivityState;
|
||||
public Activity BountyHunterRogues { get; set; } = InitialActivityState;
|
||||
public Activity BountyHunter { get; set; } = InitialActivityState;
|
||||
public Activity BountyHunterRoguesLegacy { get; set; } = InitialActivityState;
|
||||
public Activity BountyHunterLegacy { get; set; } = InitialActivityState;
|
||||
public Activity DeadManMode { get; set; } = InitialActivityState;
|
||||
public Activity TotalCluesScrolls { get; set; } = InitialActivityState;
|
||||
public Activity BeginnerClueScrolls { get; set; } = InitialActivityState;
|
||||
public Activity EasyClueScrolls { get; set; } = InitialActivityState;
|
||||
public Activity MediumClueScrolls { get; set; } = InitialActivityState;
|
||||
public Activity HardClueScrolls { get; set; } = InitialActivityState;
|
||||
public Activity EliteClueScrolls { get; set; } = InitialActivityState;
|
||||
public Activity MasterClueScrolls { get; set; } = InitialActivityState;
|
||||
public Activity LastManStanding { get; set; } = InitialActivityState;
|
||||
public Activity PvPArena { get; set; } = InitialActivityState;
|
||||
public Activity SoulWarsZeal { get; set; } = InitialActivityState;
|
||||
public Activity RiftsClosed { get; set; } = InitialActivityState;
|
||||
|
||||
//bosses
|
||||
public Boss AbyssalSire { get; set; } = InitialBossState;
|
||||
public Boss AlchemicalHydra { get; set; } = InitialBossState;
|
||||
public Boss Artio { get; set; } = InitialBossState;
|
||||
public Boss BarrowsChests { get; set; } = InitialBossState;
|
||||
public Boss Bryophyta { get; set; } = InitialBossState;
|
||||
public Boss Callisto { get; set; } = InitialBossState;
|
||||
public Boss Calvarion { get; set; } = InitialBossState;
|
||||
public Boss Cerberus { get; set; } = InitialBossState;
|
||||
public Boss ChambersofXeric { get; set; } = InitialBossState;
|
||||
public Boss ChambersofXericChallengeMode { get; set; } = InitialBossState;
|
||||
public Boss ChaosElemental { get; set; } = InitialBossState;
|
||||
public Boss ChaosFanatic { get; set; } = InitialBossState;
|
||||
public Boss CommanderZilyana { get; set; } = InitialBossState;
|
||||
public Boss CorporealBeast { get; set; } = InitialBossState;
|
||||
public Boss CrazyArchaeologist { get; set; } = InitialBossState;
|
||||
public Boss DagannothPrime { get; set; } = InitialBossState;
|
||||
public Boss DagannothRex { get; set; } = InitialBossState;
|
||||
public Boss DagannothSupreme { get; set; } = InitialBossState;
|
||||
public Boss DerangedArchaeologist { get; set; } = InitialBossState;
|
||||
public Boss DukeSucellus { get; set; } = InitialBossState;
|
||||
public Boss GeneralGraardor { get; set; } = InitialBossState;
|
||||
public Boss GiantMole { get; set; } = InitialBossState;
|
||||
public Boss GrotesqueGuardians { get; set; } = InitialBossState;
|
||||
public Boss Hespori { get; set; } = InitialBossState;
|
||||
public Boss KalphiteQueen { get; set; } = InitialBossState;
|
||||
public Boss KingBlackDragon { get; set; } = InitialBossState;
|
||||
public Boss Kraken { get; set; } = InitialBossState;
|
||||
public Boss Kree { get; set; } = InitialBossState;
|
||||
public Boss Kril { get; set; } = InitialBossState;
|
||||
public Boss Mimic { get; set; } = InitialBossState;
|
||||
public Boss Nex { get; set; } = InitialBossState;
|
||||
public Boss Nightmare { get; set; } = InitialBossState;
|
||||
public Boss PhosanisNightmare { get; set; } = InitialBossState;
|
||||
public Boss Obor { get; set; } = InitialBossState;
|
||||
public Boss PhantomMuspah { get; set; } = InitialBossState;
|
||||
public Boss Sarachnis { get; set; } = InitialBossState;
|
||||
public Boss Scorpia { get; set; } = InitialBossState;
|
||||
public Boss Skotizo { get; set; } = InitialBossState;
|
||||
public Boss Spindel { get; set; } = InitialBossState;
|
||||
public Boss Tempoross { get; set; } = InitialBossState;
|
||||
public Boss Gauntlet { get; set; } = InitialBossState;
|
||||
public Boss CorruptedGauntlet { get; set; } = InitialBossState;
|
||||
public Boss Leviathan { get; set; } = InitialBossState;
|
||||
public Boss Whisperer { get; set; } = InitialBossState;
|
||||
public Boss TheatreofBlood { get; set; } = InitialBossState;
|
||||
public Boss TheatreofBloodHardMode { get; set; } = InitialBossState;
|
||||
public Boss ThermonuclearSmokeDevil { get; set; } = InitialBossState;
|
||||
public Boss TombsOfAmascut { get; set; } = InitialBossState;
|
||||
public Boss TombsOfAmascutExpertMode { get; set; } = InitialBossState;
|
||||
public Boss Zuk { get; set; } = InitialBossState;
|
||||
public Boss Jad { get; set; } = InitialBossState;
|
||||
public Boss Vardorvis { get; set; } = InitialBossState;
|
||||
public Boss Venenatis { get; set; } = InitialBossState;
|
||||
public Boss Vetion { get; set; } = InitialBossState;
|
||||
public Boss Vorkath { get; set; } = InitialBossState;
|
||||
public Boss Wintertodt { get; set; } = InitialBossState;
|
||||
public Boss Yama { get; set; } = InitialBossState;
|
||||
public Boss Zalcano { get; set; } = InitialBossState;
|
||||
public Boss Zulrah { get; set; } = InitialBossState;
|
||||
|
||||
public PlayerInfo() { }
|
||||
|
||||
//returns all info in a big string.
|
||||
public string GetAllValuesToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append($"Player Name : {Name} \n");
|
||||
// retrieve the property information of the Player Info Class
|
||||
PropertyInfo[] properties = typeof(PlayerInfo).GetProperties();
|
||||
foreach (PropertyInfo info in properties)
|
||||
{
|
||||
if (info.PropertyType == typeof(Skill) || info.PropertyType == typeof(Activity))
|
||||
{
|
||||
// gets the value of the PropertyInfo (Skill/Minigame) and returns its Properties
|
||||
PropertyInfo[] SkillProperties = info.GetValue(this).GetType().GetProperties();
|
||||
//Skill Name
|
||||
sb.Append($"{info.Name} : ");
|
||||
// Add the Minigame/Skill Properties into the sb
|
||||
foreach (PropertyInfo SkillInfo in SkillProperties)
|
||||
{
|
||||
sb.Append($"{SkillInfo.Name} : {SkillInfo.GetValue(info.GetValue(this))}, ");
|
||||
}
|
||||
sb.Append("\n");
|
||||
}
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
//IEnumerable for looping over all Skills
|
||||
public IEnumerable<Skill> Skills()
|
||||
{
|
||||
PropertyInfo[] properties = typeof(PlayerInfo).GetProperties();
|
||||
|
||||
foreach (PropertyInfo info in properties.Where(info => info.PropertyType == typeof(Skill)))
|
||||
{
|
||||
Skill skill = (Skill)info.GetValue(this, null);
|
||||
yield return skill;
|
||||
}
|
||||
}
|
||||
|
||||
//IEnumberable for looping over all Minigames
|
||||
public IEnumerable<Activity> Minigames()
|
||||
{
|
||||
PropertyInfo[] properties = typeof(PlayerInfo).GetProperties();
|
||||
|
||||
foreach (PropertyInfo info in properties.Where(info => info.PropertyType == typeof(Activity)))
|
||||
{
|
||||
Activity skill = (Activity)info.GetValue(this, null);
|
||||
yield return skill;
|
||||
}
|
||||
}
|
||||
|
||||
//IEnumberable for looping over all Bosses
|
||||
public IEnumerable<Boss> Bosses()
|
||||
{
|
||||
PropertyInfo[] properties = typeof(PlayerInfo).GetProperties();
|
||||
|
||||
foreach (PropertyInfo info in properties.Where(info => info.PropertyType == typeof(Boss)))
|
||||
{
|
||||
Boss skill = (Boss)info.GetValue(this, null);
|
||||
yield return skill;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
namespace osrs_toolbox
|
||||
{
|
||||
public enum PlayerInfoStatus
|
||||
{
|
||||
Unknown,
|
||||
NotFound,
|
||||
Success
|
||||
}
|
||||
}
|
11
osrs-toolbox/APIs/Runescape/DataModels/PlayerType.cs
Normal file
11
osrs-toolbox/APIs/Runescape/DataModels/PlayerType.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace osrs_toolbox
|
||||
{
|
||||
public enum PlayerType
|
||||
{
|
||||
Main,
|
||||
Ironman,
|
||||
HardcoreIronman,
|
||||
UltimateIronman,
|
||||
Unknown
|
||||
}
|
||||
}
|
10
osrs-toolbox/APIs/Runescape/DataModels/Skill.cs
Normal file
10
osrs-toolbox/APIs/Runescape/DataModels/Skill.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace osrs_toolbox
|
||||
{
|
||||
public class Skill : IPlayerInfoProperty
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int Rank { get; set; }
|
||||
public int Level { get; set; }
|
||||
public int Experience { get; set; }
|
||||
}
|
||||
}
|
167
osrs-toolbox/APIs/Runescape/PlayerInfoService.cs
Normal file
167
osrs-toolbox/APIs/Runescape/PlayerInfoService.cs
Normal file
@@ -0,0 +1,167 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace osrs_toolbox
|
||||
{
|
||||
public class PlayerInfoService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private bool _throwMismatchException;
|
||||
|
||||
internal bool ThrowMismatchException
|
||||
{
|
||||
get => _throwMismatchException;
|
||||
set => _throwMismatchException = value;
|
||||
}
|
||||
|
||||
public PlayerInfoService(HttpClient httpClient, bool throwMismatchException = true)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_throwMismatchException = throwMismatchException;
|
||||
}
|
||||
|
||||
public async Task<PlayerInfo> GetPlayerInfoAsync(string userName)
|
||||
{
|
||||
bool playerFound = false;
|
||||
var playerInfo = new PlayerInfo { Name = userName };
|
||||
|
||||
//HttpResponseMessage response = null;
|
||||
HttpResponseMessage response = await _httpClient.GetAsync("https://secure.runescape.com/m=hiscore_oldschool/index_lite.ws?player=" + userName).ConfigureAwait(false);
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.NotFound)
|
||||
{
|
||||
playerInfo.Status = PlayerInfoStatus.NotFound;
|
||||
return playerInfo;
|
||||
}
|
||||
|
||||
PlayerInfo mainPlayerInfo = new PlayerInfo { Name = userName };
|
||||
PlayerInfo ironPlayerInfo = new PlayerInfo { Name = userName };
|
||||
PlayerInfo hcimPlayerInfo = new PlayerInfo { Name = userName };
|
||||
PlayerInfo uimPlayerInfo = new PlayerInfo { Name = userName };
|
||||
|
||||
return await ParseHttpResponse(playerInfo, response).ConfigureAwait(false);
|
||||
|
||||
HttpResponseMessage mainResponse = await _httpClient.GetAsync("https://secure.runescape.com/m=hiscore_oldschool/index_lite.ws?player=" + userName).ConfigureAwait(false);
|
||||
HttpResponseMessage ironResponse = await _httpClient.GetAsync("https://secure.runescape.com/m=hiscore_oldschool_ironman/index_lite.ws?player=" + userName).ConfigureAwait(false);
|
||||
HttpResponseMessage hcimResponse = await _httpClient.GetAsync("https://secure.runescape.com/m=hiscore_oldschool_hardcore_ironman/index_lite.ws?player=" + userName).ConfigureAwait(false);
|
||||
HttpResponseMessage uimResponse = await _httpClient.GetAsync("https://secure.runescape.com/m=hiscore_oldschool_ultimate/index_lite.ws?player=" + userName).ConfigureAwait(false);
|
||||
|
||||
if (mainResponse.StatusCode != HttpStatusCode.NotFound)
|
||||
{
|
||||
playerFound = true;
|
||||
mainPlayerInfo = await ParseHttpResponse(mainPlayerInfo, mainResponse).ConfigureAwait(false);
|
||||
}
|
||||
if (ironResponse.StatusCode != HttpStatusCode.NotFound)
|
||||
{
|
||||
playerFound = true;
|
||||
ironPlayerInfo = await ParseHttpResponse(ironPlayerInfo, ironResponse).ConfigureAwait(false);
|
||||
}
|
||||
if (hcimResponse.StatusCode != HttpStatusCode.NotFound)
|
||||
{
|
||||
playerFound = true;
|
||||
hcimPlayerInfo = await ParseHttpResponse(hcimPlayerInfo, hcimResponse).ConfigureAwait(false);
|
||||
}
|
||||
if (uimResponse.StatusCode != HttpStatusCode.NotFound)
|
||||
{
|
||||
playerFound = true;
|
||||
uimPlayerInfo = await ParseHttpResponse(uimPlayerInfo, uimResponse).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (!playerFound)
|
||||
{
|
||||
playerInfo.Status = PlayerInfoStatus.NotFound;
|
||||
return playerInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PlayerInfo>> GetPlayerInfoAsync(string[] userNames)
|
||||
{
|
||||
var tasks = userNames.Select(x => GetPlayerInfoAsync(x));
|
||||
return await Task.WhenAll(tasks)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<PlayerInfo> ParseHttpResponse(PlayerInfo playerInfo, HttpResponseMessage response)
|
||||
{
|
||||
var stream = await response.Content.ReadAsStreamAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
using var reader = new StreamReader(stream);
|
||||
|
||||
var properties = typeof(PlayerInfo).GetProperties()
|
||||
.Where(x => typeof(IPlayerInfoProperty).IsAssignableFrom(x.PropertyType)).ToArray();
|
||||
|
||||
if (properties.Count() != TotalLines(reader) && _throwMismatchException)
|
||||
throw new FormatException("Property mismatch; OSRS API Contains more properties than PlayerInfo class. Please contact Repository creator");
|
||||
|
||||
foreach (PropertyInfo info in properties)
|
||||
{
|
||||
string[] values = reader.ReadLine().Split(',');
|
||||
var property = ParseLine(values, info);
|
||||
|
||||
info.SetValue(playerInfo, property);
|
||||
}
|
||||
|
||||
playerInfo.Status = PlayerInfoStatus.Success;
|
||||
|
||||
return playerInfo;
|
||||
}
|
||||
|
||||
private int TotalLines(StreamReader reader)
|
||||
{
|
||||
int i = 0;
|
||||
while (reader.ReadLine() != null) i++;
|
||||
|
||||
reader.BaseStream.Position = 0;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
private IPlayerInfoProperty ParseLine(string[] data, PropertyInfo info)
|
||||
{
|
||||
if (info.PropertyType == typeof(Skill))
|
||||
{
|
||||
return new Skill
|
||||
{
|
||||
Name = info.Name,
|
||||
Rank = int.Parse(data[0]),
|
||||
Level = int.Parse(data[1]),
|
||||
Experience = int.Parse(data[2])
|
||||
};
|
||||
}
|
||||
|
||||
if (info.PropertyType == typeof(Activity))
|
||||
{
|
||||
return new Activity
|
||||
{
|
||||
Name = info.Name,
|
||||
Rank = int.Parse(data[0]),
|
||||
Score = int.Parse(data[1])
|
||||
};
|
||||
}
|
||||
|
||||
if (info.PropertyType == typeof(Boss))
|
||||
{
|
||||
return new Boss
|
||||
{
|
||||
Name = info.Name,
|
||||
Rank = int.Parse(data[0]),
|
||||
Kills = int.Parse(data[1])
|
||||
};
|
||||
}
|
||||
|
||||
throw new NotImplementedException($"Unimplemented type {info.PropertyType}");
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user