Files
Operation-Blue-Laminate-v2/BlueLaminate/BlueLaminate.Core/SkinLand/SkinLandSlug.cs
2026-06-01 10:52:06 -05:00

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();
}
}