Skip to content

Commit

Permalink
add CrossWorldLinkShell
Browse files Browse the repository at this point in the history
  • Loading branch information
Koenari committed Jul 20, 2024
1 parent 65de056 commit 3fc1aa2
Show file tree
Hide file tree
Showing 10 changed files with 491 additions and 24 deletions.
26 changes: 26 additions & 0 deletions NetStone.Test/Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public class Tests

private const string TestCharacterIdFull = "24471319";
private const string TestCharacterIdEureka = "14556736";
private const string TestLinkshell = "18577348462979918";
private const string TestCWLS = "097b99377634f9980eb0cf0b4ff6cf86807feb2c";
private const string TestCharacterIdEureka2 = "6787158";
private const string TestCharacterIdBare = "9426169";

Expand Down Expand Up @@ -450,4 +452,28 @@ public async Task CheckCharacterCollectableNotFound()
var minions = await this.lodestone.GetCharacterMinion("0");
Assert.IsNull(minions);
}

[Test]
public async Task CheckCrossworldLinkShell()
{
var cwls = await this.lodestone.GetCrossworldLinkshell(TestCWLS);
//Assert.AreEqual("COR and Friends ", cwls?.Name);
Assert.AreEqual("Light", cwls.DataCenter);
Assert.AreEqual(2, cwls.NumPages);
while (cwls is not null)
{
foreach (var member in cwls.Members)
{
Console.WriteLine($"{member.Name} ({member.Rank}) {member.RankIcon}\n" +
$"Id: {member.Id}\n" +
$"Avatar: {member.Avatar}\n" +
$"Server: {member.Server}\n" +
$"LS Rank: {member.LinkshellRank}\n" +
$"LS Rank Icon: {member.LinkshellRankIcon}");

}
cwls = await cwls.GetNextPage();
}

}
}
11 changes: 11 additions & 0 deletions NetStone/Definitions/DefinitionsContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Threading.Tasks;
using NetStone.Definitions.Model;
using NetStone.Definitions.Model.Character;
using NetStone.Definitions.Model.CWLS;
using NetStone.Definitions.Model.FreeCompany;

namespace NetStone.Definitions;
Expand Down Expand Up @@ -83,6 +84,16 @@ public abstract class DefinitionsContainer : IDisposable
/// Definitions for Free company search
/// </summary>
public PagedDefinition<FreeCompanySearchEntryDefinition> FreeCompanySearch { get; protected set; }

/// <summary>
/// Definitions for cross world link shells
/// </summary>
public CrossWorldLinkShellDefinition CrossWorldLinkShell { get; protected set; }

/// <summary>
/// Definitions for cross world link shell memebrs
/// </summary>
public CrossWorldLinkShellMemberDefinition CrossWorldLinkShellMember { get; protected set; }

#endregion

Expand Down
21 changes: 21 additions & 0 deletions NetStone/Definitions/Model/CWLS/CrossWorldLinkShellDefinition.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Newtonsoft.Json;

namespace NetStone.Definitions.Model.CWLS;

/// <summary>
/// Definitions for cross world link shell
/// </summary>
public class CrossWorldLinkShellDefinition : IDefinition
{
/// <summary>
/// Name
/// </summary>
[JsonProperty("NAME")]
public DefinitionsPack Name { get; set; }

/// <summary>
/// Name
/// </summary>
[JsonProperty("DC")]
public DefinitionsPack DataCenter { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using Newtonsoft.Json;

namespace NetStone.Definitions.Model.CWLS;
/// <summary>
///
/// </summary>
public class CrossWorldLinkShellMemberDefinition : PagedDefinition<CrossWorldLinkShellMemberEntryDefinition>
{

}

/// <summary>
///
/// </summary>
public class CrossWorldLinkShellMemberEntryDefinition : PagedEntryDefinition
{
/// <summary>
/// Avatar
/// </summary>
[JsonProperty("AVATAR")] public DefinitionsPack Avatar { get; set; }

/// <summary>
/// ID
/// </summary>
[JsonProperty("ID")] public DefinitionsPack Id { get; set; }

/// <summary>
/// Name
/// </summary>
[JsonProperty("NAME")] public DefinitionsPack Name { get; set; }

/// <summary>
/// Rank
/// </summary>
[JsonProperty("RANK")] public DefinitionsPack Rank { get; set; }

/// <summary>
/// Rank Icon
/// </summary>
[JsonProperty("RANK_ICON")] public DefinitionsPack RankIcon { get; set; }

/// <summary>
/// Linkshell rank
/// </summary>
[JsonProperty("LINKSHELL_RANK")] public DefinitionsPack LinkshellRank { get; set; }

/// <summary>
/// Linkshell rank Icon
/// </summary>
[JsonProperty("LINKSHELL_RANK_ICON")] public DefinitionsPack LinkshellRankIcon { get; set; }

/// <summary>
/// Server
/// </summary>
[JsonProperty("SERVER")] public DefinitionsPack Server { get; set; }
}
4 changes: 4 additions & 0 deletions NetStone/Definitions/XivApiDefinitionsContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Threading.Tasks;
using NetStone.Definitions.Model;
using NetStone.Definitions.Model.Character;
using NetStone.Definitions.Model.CWLS;
using NetStone.Definitions.Model.FreeCompany;
using Newtonsoft.Json;

Expand Down Expand Up @@ -55,6 +56,9 @@ public override async Task Reload()

this.CharacterSearch = await GetDefinition<PagedDefinition<CharacterSearchEntryDefinition>>("search/character.json");
this.FreeCompanySearch = await GetDefinition<PagedDefinition<FreeCompanySearchEntryDefinition>>("search/freecompany.json");

this.CrossWorldLinkShell = await GetDefinition<CrossWorldLinkShellDefinition>("cwls/cwls.json");
this.CrossWorldLinkShellMember = await GetDefinition<CrossWorldLinkShellMemberDefinition>("cwls/members.json");
}

private async Task<T> GetDefinition<T>(string path) where T : IDefinition
Expand Down
11 changes: 11 additions & 0 deletions NetStone/LodestoneClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
using NetStone.Model.Parseables.Character.Achievement;
using NetStone.Model.Parseables.Character.ClassJob;
using NetStone.Model.Parseables.Character.Collectable;
using NetStone.Model.Parseables.CWLS;
using NetStone.Model.Parseables.CWLS.Members;
using NetStone.Model.Parseables.FreeCompany;
using NetStone.Model.Parseables.FreeCompany.Members;
using NetStone.Model.Parseables.Search.Character;
Expand Down Expand Up @@ -132,6 +134,15 @@ await GetParsed(
public async Task<CharacterSearchPage?> SearchCharacter(CharacterSearchQuery query, int page = 1) =>
await GetParsed($"/lodestone/character/{query.BuildQueryString()}&page={page}",
node => new CharacterSearchPage(this, node, this.Definitions.CharacterSearch, query));
/// <summary>
/// Get's a cross world link shell by it's id.
/// </summary>
/// <param name="id">The ID of the cross world linkshell.</param>
/// <param name="page"></param>
/// <returns><see cref="LodestoneCrossWorldLinkShell"/> class containing information about the cross world link shell</returns>
public async Task<LodestoneCrossWorldLinkShell?> GetCrossworldLinkshell(string id, int page = 1) =>
await GetParsed($"/lodestone/crossworld_linkshell/{id}?page={page}",
node => new LodestoneCrossWorldLinkShell(this, node, this.Definitions,id));

#endregion

Expand Down
119 changes: 119 additions & 0 deletions NetStone/Model/Parseables/CWLS/LodestoneCrossWorldLinkShell.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using HtmlAgilityPack;
using NetStone.Definitions;
using NetStone.Definitions.Model.CWLS;
using NetStone.Model.Parseables.CWLS.Members;

namespace NetStone.Model.Parseables.CWLS;

/// <summary>
/// Container class holding information about a cross world linkshell and it's members.
/// </summary>
public class LodestoneCrossWorldLinkShell : LodestoneParseable, IPaginatedResult<LodestoneCrossWorldLinkShell>
{
private readonly LodestoneClient client;

private readonly string cwlsId;

private readonly CrossWorldLinkShellDefinition cwlsDefinition;
private readonly CrossWorldLinkShellMemberDefinition pageDefinition;

/// <summary>
/// Container class for a parseable corss world linkshell page.
/// </summary>
/// <param name="client">The <see cref="LodestoneClient"/> to be used to fetch further information.</param>
/// <param name="rootNode">The root document node of the page.</param>
/// <param name="container">The <see cref="DefinitionsContainer"/> holding definitions to be used to access data.</param>
/// <param name="id">The ID of the cross world linkshell.</param>
public LodestoneCrossWorldLinkShell(LodestoneClient client, HtmlNode rootNode, DefinitionsContainer container, string id) : base(rootNode)
{
this.client = client;
this.cwlsId = id;
this.cwlsDefinition = container.CrossWorldLinkShell;
this.pageDefinition = container.CrossWorldLinkShellMember;
}

/// <summary>
/// Name
/// </summary>
public string Name => Parse(this.cwlsDefinition.Name);

/// <summary>
/// Datacenter
/// </summary>
public string DataCenter => Parse(this.cwlsDefinition.DataCenter);


private CrossWorldLinkShellMemberEntry[]? parsedResults;

/// <summary>
/// Unlocked achievements for character
/// </summary>
public IEnumerable<CrossWorldLinkShellMemberEntry> Members
{
get
{
if (this.parsedResults == null)
ParseSearchResults();

return this.parsedResults!;
}
}

private void ParseSearchResults()
{
var nodes = QueryContainer(this.pageDefinition);

this.parsedResults = new CrossWorldLinkShellMemberEntry[nodes.Length];
for (var i = 0; i < this.parsedResults.Length; i++)
{
this.parsedResults[i] = new CrossWorldLinkShellMemberEntry(nodes[i], this.pageDefinition.Entry);
}
}

private int? currentPageVal;

///<inheritdoc />
public int CurrentPage
{
get
{
if (!this.currentPageVal.HasValue)
ParsePagesCount();

return this.currentPageVal!.Value;
}
}

private int? numPagesVal;

/// <inheritdoc/>
public int NumPages
{
get
{
if (!this.numPagesVal.HasValue)
ParsePagesCount();

return this.numPagesVal!.Value;
}
}
private void ParsePagesCount()
{
var results = ParseRegex(this.pageDefinition.PageInfo);

this.currentPageVal = int.Parse(results["CurrentPage"].Value);
this.numPagesVal = int.Parse(results["NumPages"].Value);
}

/// <inheritdoc />
public async Task<LodestoneCrossWorldLinkShell?> GetNextPage()
{
if (this.CurrentPage == this.NumPages)
return null;

return await this.client.GetCrossworldLinkshell(this.cwlsId, this.CurrentPage + 1);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using HtmlAgilityPack;
using NetStone.Definitions.Model.CWLS;

namespace NetStone.Model.Parseables.CWLS.Members;

/// <summary>
/// Container class holding information about a cross-world linkshelll member.
/// </summary>
public class CrossWorldLinkShellMemberEntry : LodestoneParseable
{
private readonly CrossWorldLinkShellMemberEntryDefinition definition;
/// <summary>
/// Create instance of member entry for a given node
/// </summary>
/// <param name="rootNode">Root html node of this entry</param>
/// <param name="definition">Css and regex definition</param>
public CrossWorldLinkShellMemberEntry(HtmlNode rootNode, CrossWorldLinkShellMemberEntryDefinition definition) : base(rootNode)
{
this.definition = definition;
}

/// <summary>
/// Avatar
/// </summary>
public string Avatar => Parse(this.definition.Avatar);

/// <summary>
/// ID
/// </summary>
public string? Id => ParseHrefId(this.definition.Id);

/// <summary>
/// Name
/// </summary>
public string Name => Parse(this.definition.Name);

/// <summary>
/// Rank
/// </summary>
public string Rank => Parse(this.definition.Rank);

/// <summary>
/// Rank Icon
/// </summary>
public string RankIcon => Parse(this.definition.RankIcon);

/// <summary>
/// Linkshell rank
/// </summary>
public string LinkshellRank => Parse(this.definition.LinkshellRank);

/// <summary>
/// Linkshell rank Icon
/// </summary>
public string LinkshellRankIcon => Parse(this.definition.LinkshellRankIcon);

/// <summary>
/// Server
/// </summary>
public string Server => Parse(this.definition.Server);
}
Loading

0 comments on commit 3fc1aa2

Please sign in to comment.