| | | 1 | | using System.Text.RegularExpressions; |
| | | 2 | | |
| | | 3 | | namespace Services.AiAssistant; |
| | | 4 | | |
| | | 5 | | /// <summary> |
| | | 6 | | /// Разбор артикула / product key (09146=FEB) из текста запроса. |
| | | 7 | | /// </summary> |
| | | 8 | | public static partial class AiArticleParser |
| | | 9 | | { |
| | | 10 | | [GeneratedRegex(@"\b([\w\.\-]+)=([\w]+)\b", RegexOptions.Compiled)] |
| | | 11 | | private static partial Regex ProductKeyRegex(); |
| | | 12 | | |
| | | 13 | | [GeneratedRegex(@"(?:товар|артикул|article|product\s*key)\s+([\w\.\-=]+)", RegexOptions.IgnoreCase | RegexOptions.Co |
| | | 14 | | private static partial Regex LabeledArticleRegex(); |
| | | 15 | | |
| | | 16 | | [GeneratedRegex(@"(?:для\s+)?артикул[ау]?\s+([\w\.\-=]+)", RegexOptions.IgnoreCase | RegexOptions.Compiled)] |
| | | 17 | | private static partial Regex ForArticleRegex(); |
| | | 18 | | |
| | | 19 | | public static (string Article, string? ManufacturerPrefix)? TryParseProductKey(string text) |
| | | 20 | | { |
| | 32 | 21 | | var pk = ProductKeyRegex().Match(text); |
| | 31 | 22 | | if (pk.Success) |
| | 7 | 23 | | return (pk.Groups[1].Value.Trim(), pk.Groups[2].Value.Trim()); |
| | | 24 | | |
| | 24 | 25 | | var forArt = ForArticleRegex().Match(text); |
| | 24 | 26 | | if (forArt.Success) |
| | | 27 | | { |
| | 10 | 28 | | var rawFor = forArt.Groups[1].Value.Trim(); |
| | 10 | 29 | | var eqFor = rawFor.IndexOf('='); |
| | 10 | 30 | | if (eqFor > 0) |
| | 1 | 31 | | return (rawFor[..eqFor].Trim(), rawFor[(eqFor + 1)..].Trim()); |
| | 9 | 32 | | return (rawFor, null); |
| | | 33 | | } |
| | | 34 | | |
| | 14 | 35 | | var labeled = LabeledArticleRegex().Match(text); |
| | 14 | 36 | | if (!labeled.Success) |
| | 5 | 37 | | return null; |
| | | 38 | | |
| | 9 | 39 | | var raw = labeled.Groups[1].Value.Trim(); |
| | 9 | 40 | | var eq = raw.IndexOf('='); |
| | 9 | 41 | | if (eq > 0) |
| | 1 | 42 | | return (raw[..eq].Trim(), raw[(eq + 1)..].Trim()); |
| | | 43 | | |
| | 8 | 44 | | return (raw, null); |
| | | 45 | | } |
| | | 46 | | |
| | | 47 | | [GeneratedRegex(@"\b(\d{5,}[\w\.\-]*)\b", RegexOptions.Compiled)] |
| | | 48 | | private static partial Regex BareArticleTokenRegex(); |
| | | 49 | | |
| | | 50 | | public static string? TryExtractBareArticleToken(string text) |
| | | 51 | | { |
| | 23 | 52 | | var m = BareArticleTokenRegex().Match(text); |
| | 22 | 53 | | return m.Success ? m.Groups[1].Value.Trim() : null; |
| | | 54 | | } |
| | | 55 | | |
| | | 56 | | public static string? TryParseBareArticle(string text) |
| | | 57 | | { |
| | 32 | 58 | | var forArt = ForArticleRegex().Match(text); |
| | 31 | 59 | | if (forArt.Success) |
| | | 60 | | { |
| | 11 | 61 | | var raw = forArt.Groups[1].Value.Trim(); |
| | 11 | 62 | | var eq = raw.IndexOf('='); |
| | 11 | 63 | | return eq > 0 ? raw[..eq].Trim() : raw; |
| | | 64 | | } |
| | | 65 | | |
| | 20 | 66 | | var labeled = LabeledArticleRegex().Match(text); |
| | 20 | 67 | | if (!labeled.Success) |
| | 10 | 68 | | return TryExtractBareArticleToken(text); |
| | | 69 | | |
| | 10 | 70 | | var rawLabeled = labeled.Groups[1].Value.Trim(); |
| | 10 | 71 | | var eqLabeled = rawLabeled.IndexOf('='); |
| | 10 | 72 | | return eqLabeled > 0 ? rawLabeled[..eqLabeled].Trim() : rawLabeled; |
| | | 73 | | } |
| | | 74 | | } |