Сократить служебные теги SHiNE и сохранить обратную совместимость

This commit is contained in:
AidarKC
2026-08-12 13:14:23 +04:00
parent 4d80ab639e
commit 8f32e82d14
15 changed files with 144 additions and 86 deletions
@@ -6,6 +6,8 @@ import java.util.Map;
public final class ChannelMetaTextParser {
public static final int MAX_TITLE_CHARS = 50;
public static final int MAX_DESCRIPTION_CHARS = 250;
private static final String LEGACY_PREFIX = "<SHiNE:";
private static final String SHORT_PREFIX = "<S:";
private ChannelMetaTextParser() {}
@@ -19,15 +21,16 @@ public final class ChannelMetaTextParser {
boolean seenAvatar = false;
int offset = 0;
while (text.startsWith("<SHiNE:", offset)) {
while (startsWithTagPrefix(text, offset)) {
int end = text.indexOf('>', offset);
if (end < 0) throw new IllegalArgumentException("bad_channel_meta_tag");
String body = text.substring(offset + "<SHiNE:".length(), end);
int prefixLength = tagPrefixLength(text, offset);
String body = text.substring(offset + prefixLength, end);
if (body.startsWith("title;")) {
if (seenTitle) throw new IllegalArgumentException("duplicate_channel_meta_title");
seenTitle = true;
title = parseTitleTag(body);
} else if (body.startsWith("avatar;")) {
} else if (body.startsWith("avatar;") || body.startsWith("ava;")) {
if (seenAvatar) throw new IllegalArgumentException("duplicate_channel_meta_avatar");
seenAvatar = true;
Avatar avatar = parseAvatarTag(body);
@@ -61,11 +64,14 @@ public final class ChannelMetaTextParser {
}
private static Avatar parseAvatarTag(String body) {
Map<String, String> fields = parseFields(body.substring("avatar;".length()));
String rawFields = body.startsWith("ava;")
? body.substring("ava;".length())
: body.substring("avatar;".length());
Map<String, String> fields = parseFields(rawFields);
if (!"1".equals(fields.get("v"))) throw new IllegalArgumentException("bad_channel_meta_avatar_version");
String ar = String.valueOf(fields.getOrDefault("ar", "")).trim();
String sha256 = String.valueOf(fields.getOrDefault("sha256", "")).trim().toLowerCase();
String sizeRaw = String.valueOf(fields.getOrDefault("size", "")).trim();
String sizeRaw = String.valueOf(fields.containsKey("sz") ? fields.get("sz") : fields.getOrDefault("size", "")).trim();
if (!ar.matches("^[A-Za-z0-9_-]{43}$")) throw new IllegalArgumentException("bad_channel_meta_avatar_ar");
if (!sha256.matches("^[0-9a-f]{64}$")) throw new IllegalArgumentException("bad_channel_meta_avatar_sha256");
long size;
@@ -78,6 +84,16 @@ public final class ChannelMetaTextParser {
return new Avatar(ar, sha256, size);
}
private static boolean startsWithTagPrefix(String text, int offset) {
return text.startsWith(LEGACY_PREFIX, offset) || text.startsWith(SHORT_PREFIX, offset);
}
private static int tagPrefixLength(String text, int offset) {
if (text.startsWith(LEGACY_PREFIX, offset)) return LEGACY_PREFIX.length();
if (text.startsWith(SHORT_PREFIX, offset)) return SHORT_PREFIX.length();
return 0;
}
private static Map<String, String> parseFields(String raw) {
Map<String, String> out = new HashMap<>();
for (String part : String.valueOf(raw == null ? "" : raw).split(";")) {