Перевести ядро на единый контракт источника
Карточка, очередь и отсев работают с SourceItem (SourceRef + SourceContent); Telegram-поля убраны из домена, персистентности, конвейера и wire, остались только в адаптере приёма. Tenant-миграции пересозданы с нуля. Фронт переведён на generic source/content с просмотрщиком вложений.
This commit is contained in:
@@ -17,15 +17,15 @@ public static class ContactsQualifier
|
||||
|
||||
private const int MaxContactLength = 300;
|
||||
|
||||
private const int MinTgNameLength = 4;
|
||||
private const int MinHandleLength = 4;
|
||||
|
||||
private const int MaxTgNameLength = 32;
|
||||
private const int MaxHandleLength = 32;
|
||||
|
||||
internal const int MaxNormalizedPhoneLength = 18;
|
||||
|
||||
private const string TgBotSuffix = "bot";
|
||||
private const string BotSuffix = "bot";
|
||||
|
||||
private static readonly IReadOnlySet<string> TgServiceNames = new HashSet<string>(StringComparer.Ordinal)
|
||||
private static readonly IReadOnlySet<string> ReservedProfileNames = new HashSet<string>(StringComparer.Ordinal)
|
||||
{
|
||||
"joinchat", "share", "s", "c", "addstickers", "addtheme", "proxy", "bg", "login",
|
||||
};
|
||||
@@ -35,9 +35,9 @@ public static class ContactsQualifier
|
||||
"teletype.in", "forms.gle", "docs.google.com", "youtube.com", "youtu.be", "clck.ru",
|
||||
};
|
||||
|
||||
private static readonly Regex TelegramNameRe = new(@"\A[A-Za-z0-9_]{4,32}\z", RegexOptions.CultureInvariant);
|
||||
private static readonly Regex ProfileHandleRe = new(@"\A[A-Za-z0-9_]{4,32}\z", RegexOptions.CultureInvariant);
|
||||
|
||||
private static readonly Regex TelegramLinkRe = new(
|
||||
private static readonly Regex ProfileLinkRe = new(
|
||||
@"\Ahttps?://(?:www\.)?t\.me/([A-Za-z0-9_]{4,32})/?\z",
|
||||
RegexOptions.CultureInvariant);
|
||||
|
||||
@@ -78,7 +78,7 @@ public static class ContactsQualifier
|
||||
/// <summary>
|
||||
/// Классифицирует один сырой контакт → {type, value} или null.
|
||||
/// </summary>
|
||||
/// <param name="raw">Сырое значение контакта («@user», «https://t.me/x», телефон, email, ссылка).</param>
|
||||
/// <param name="raw">Сырое значение контакта («@user», ссылка на профиль, телефон, email, ссылка).</param>
|
||||
/// <returns>Квалифицированный контакт <see cref="CardContactDto"/> либо null — пусто/мусор/бот/сервисная ссылка/ «постовый» сайт.</returns>
|
||||
public static CardContactDto? Qualify(string? raw)
|
||||
{
|
||||
@@ -91,7 +91,7 @@ public static class ContactsQualifier
|
||||
if (s.StartsWith('@'))
|
||||
{
|
||||
string name = s[1..].Trim();
|
||||
if (TelegramNameRe.IsMatch(name) && !name.EndsWith(TgBotSuffix, StringComparison.OrdinalIgnoreCase))
|
||||
if (ProfileHandleRe.IsMatch(name) && !name.EndsWith(BotSuffix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return new CardContactDto("tg", "@" + name);
|
||||
}
|
||||
@@ -99,12 +99,12 @@ public static class ContactsQualifier
|
||||
return null;
|
||||
}
|
||||
|
||||
Match link = TelegramLinkRe.Match(s);
|
||||
Match link = ProfileLinkRe.Match(s);
|
||||
if (link.Success)
|
||||
{
|
||||
string name = link.Groups[1].Value;
|
||||
if (!TgServiceNames.Contains(name.ToLowerInvariant())
|
||||
&& !name.EndsWith(TgBotSuffix, StringComparison.OrdinalIgnoreCase))
|
||||
if (!ReservedProfileNames.Contains(name.ToLowerInvariant())
|
||||
&& !name.EndsWith(BotSuffix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return new CardContactDto("tg", "@" + name);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user