56 lines
2.0 KiB
C#
56 lines
2.0 KiB
C#
using System.Text;
|
|
|
|
namespace BlueLaminate.Core.SkinLand;
|
|
|
|
/// <summary>
|
|
/// Builds a skin.land market URL from the catalogue's weapon + skin + wear. skin.land's
|
|
/// market routes are <c>/market/csgo/{slug}/</c> where the slug is simply
|
|
/// <c>{weapon}-{skin}-{wear}</c> kebab-cased — verified against the live site (e.g.
|
|
/// "M4A4" + "Global Offensive" + "Battle-Scarred" → <c>m4a4-global-offensive-battle-scarred</c>,
|
|
/// "AK-47" + "Redline" + "Field-Tested" → <c>ak-47-redline-field-tested</c>). No discovery
|
|
/// or stored mapping is needed.
|
|
/// <para>
|
|
/// StatTrak and Souvenir are <em>separate</em> pages on skin.land (<c>stattrak-</c>/
|
|
/// <c>souvenir-</c> prefixed slugs); this builds the base (non-special) page, which is the
|
|
/// unit v1 sweeps per <c>SkinCondition</c>.
|
|
/// </para>
|
|
/// </summary>
|
|
public static class SkinLandSlug
|
|
{
|
|
private const string MarketBase = "https://skin.land/market/csgo/";
|
|
|
|
/// <summary>"M4A4", "Global Offensive", "Battle-Scarred" → the full market URL.</summary>
|
|
public static string MarketUrl(string weapon, string skinName, string condition) =>
|
|
$"{MarketBase}{Slugify($"{weapon} {skinName} {condition}")}/";
|
|
|
|
/// <summary>
|
|
/// Lowercase, collapse every run of non-alphanumeric characters to a single hyphen,
|
|
/// and trim leading/trailing hyphens. So "AK-47 | Redline (Field-Tested)" and the
|
|
/// catalogue's "AK-47 Redline Field-Tested" both reduce to "ak-47-redline-field-tested".
|
|
/// </summary>
|
|
public static string Slugify(string value)
|
|
{
|
|
var sb = new StringBuilder(value.Length);
|
|
var pendingHyphen = false;
|
|
foreach (var ch in value)
|
|
{
|
|
if (char.IsLetterOrDigit(ch))
|
|
{
|
|
if (pendingHyphen && sb.Length > 0)
|
|
{
|
|
sb.Append('-');
|
|
}
|
|
|
|
sb.Append(char.ToLowerInvariant(ch));
|
|
pendingHyphen = false;
|
|
}
|
|
else
|
|
{
|
|
pendingHyphen = true;
|
|
}
|
|
}
|
|
|
|
return sb.ToString();
|
|
}
|
|
}
|