добавил новые типы связи - тоесть возможность добавлять убирать друга, контакт или подписку  (и тесты и всё работает)
This commit is contained in:
AidarKC 2026-01-06 00:24:24 +03:00
parent 94777c58c6
commit 7ba333bf6c
2 changed files with 77 additions and 9 deletions

View File

@ -12,17 +12,31 @@ import java.util.Objects;
* ConnectionBody type=3, ver=1. (Связь/отношение) * ConnectionBody type=3, ver=1. (Связь/отношение)
* *
* Идея: * Идея:
* - Это запись "у меня есть связь с X". * - Это запись "у меня есть связь с X" ИЛИ "я отменяю связь с X".
* - subType определяет вид связи: * - subType определяет вид связи и действие.
*
* subType (uint16):
* УСТАНОВИТЬ связь:
* 10 = FRIEND (друг) * 10 = FRIEND (друг)
* 20 = CONTACT (контакт) * 20 = CONTACT (контакт)
* 30 = FOLLOW (подписан на кого-то) * 30 = FOLLOW (подписан на кого-то)
* *
* ОТМЕНИТЬ связь (событие, которое снимает прошлую связь):
* 11 = UNFRIEND (больше не друг)
* 21 = UNCONTACT (больше не контакт)
* 31 = UNFOLLOW (больше не подписан)
*
* Важно про смысл:
* - Состояние связи вычисляется по последнему блоку данной категории:
* (toLogin, kind=FRIEND/CONTACT/FOLLOW)
* Если последний subType 10/20/30 => связь активна
* Если последний subType 11/21/31 => связь снята
*
* Формат bodyBytes (BigEndian): * Формат bodyBytes (BigEndian):
* [2] type=3 * [2] type=3
* [2] ver=1 * [2] ver=1
* *
* [2] subType (uint16) вид связи (10/20/30) * [2] subType (uint16) вид связи (10,20/30)
* *
* [1] toLoginLen (uint8) * [1] toLoginLen (uint8)
* [N] toLogin UTF-8 * [N] toLogin UTF-8
@ -50,10 +64,15 @@ public final class ConnectionBody implements BodyRecord, BodyHasTarget {
/** Удобный ключ для BodyRecordParser: (type<<16)|ver */ /** Удобный ключ для BodyRecordParser: (type<<16)|ver */
public static final int KEY = ((TYPE & 0xFFFF) << 16) | (VER & 0xFFFF); public static final int KEY = ((TYPE & 0xFFFF) << 16) | (VER & 0xFFFF);
// subType: // --- subType: SET ---
public static final short SUB_FRIEND = 10; public static final short SUB_FRIEND = 10;
public static final short SUB_CONTACT = 20; public static final short SUB_CONTACT = 20;
public static final short SUB_FOLLOW = 30; public static final short SUB_FOLLOW = 30;
// --- subType: UNSET (снятие/отмена связи) ---
public static final short SUB_UNFRIEND = 11; // больше не друг
public static final short SUB_UNCONTACT = 21; // больше не контакт
public static final short SUB_UNFOLLOW = 31; // больше не подписан
public final short subType; public final short subType;
@ -162,7 +181,31 @@ public final class ConnectionBody implements BodyRecord, BodyHasTarget {
} }
private static boolean isValidSubType(short st) { private static boolean isValidSubType(short st) {
return st == SUB_FRIEND || st == SUB_CONTACT || st == SUB_FOLLOW; return st == SUB_FRIEND || st == SUB_CONTACT || st == SUB_FOLLOW
|| st == SUB_UNFRIEND || st == SUB_UNCONTACT || st == SUB_UNFOLLOW;
}
/** true если это событие установки связи (10/20/30). */
public boolean isSetAction() {
return subType == SUB_FRIEND || subType == SUB_CONTACT || subType == SUB_FOLLOW;
}
/** true если это событие снятия связи (11/21/31). */
public boolean isUnsetAction() {
return subType == SUB_UNFRIEND || subType == SUB_UNCONTACT || subType == SUB_UNFOLLOW;
}
/**
* Нормализованный вид связи без действия:
* FRIEND / CONTACT / FOLLOW
*/
public short kind() {
return switch (subType) {
case SUB_FRIEND, SUB_UNFRIEND -> SUB_FRIEND;
case SUB_CONTACT, SUB_UNCONTACT -> SUB_CONTACT;
case SUB_FOLLOW, SUB_UNFOLLOW -> SUB_FOLLOW;
default -> throw new IllegalStateException("Unexpected subType: " + (subType & 0xFFFF));
};
} }
/* ===================================================================== */ /* ===================================================================== */
@ -247,14 +290,27 @@ public final class ConnectionBody implements BodyRecord, BodyHasTarget {
case SUB_FRIEND -> "FRIEND (10)"; case SUB_FRIEND -> "FRIEND (10)";
case SUB_CONTACT -> "CONTACT (20)"; case SUB_CONTACT -> "CONTACT (20)";
case SUB_FOLLOW -> "FOLLOW (30)"; case SUB_FOLLOW -> "FOLLOW (30)";
case SUB_UNFRIEND -> "UNFRIEND (11)";
case SUB_UNCONTACT -> "UNCONTACT (21)";
case SUB_UNFOLLOW -> "UNFOLLOW (31)";
default -> "UNKNOWN"; default -> "UNKNOWN";
}; };
String action = isSetAction() ? "SET" : (isUnsetAction() ? "UNSET" : "?");
String kindStr = switch (kind()) {
case SUB_FRIEND -> "FRIEND";
case SUB_CONTACT -> "CONTACT";
case SUB_FOLLOW -> "FOLLOW";
default -> "?";
};
return """ return """
ConnectionBody { ConnectionBody {
тип записи : CONNECTION (type=3, ver=1) тип записи : CONNECTION (type=3, ver=1)
ожидаемая линия : 3 ожидаемая линия : 3
subType : %s subType : %s
действие : %s
вид связи : %s
связь с login : "%s" связь с login : "%s"
блокчейн друга/цели : "%s" блокчейн друга/цели : "%s"
lastKnown globalNumber : %d lastKnown globalNumber : %d
@ -262,6 +318,8 @@ public final class ConnectionBody implements BodyRecord, BodyHasTarget {
} }
""".formatted( """.formatted(
st, st,
action,
kindStr,
toLogin, toLogin,
toBlockchainName, toBlockchainName,
toBlockGlobalNumber, toBlockGlobalNumber,
@ -281,7 +339,7 @@ public final class ConnectionBody implements BodyRecord, BodyHasTarget {
} }
/* ===================================================================== */ /* ===================================================================== */
/* ====================== BodyToFields контракт ========================= */ /* ====================== BodyHasTarget контракт ========================= */
/* ===================================================================== */ /* ===================================================================== */
@Override public String toLogin() { return toLogin; } @Override public String toLogin() { return toLogin; }

View File

@ -236,6 +236,16 @@ public class IT_03_AddBlock_NoAuth {
new byte[32] new byte[32]
), t); ), t);
// 6) USER2: Connection (UNFRIEND -> USER1) USER2 больше не друг USER1
if (TestConfig.DEBUG()) TestLog.stepTitle("USER2: Connection (UNFRIEND -> USER1)");
sender2.send(new ConnectionBody(
ConnectionBody.SUB_UNFRIEND,
TestConfig.LOGIN(), // to_login (USER1)
TestConfig.BCH_NAME(), // toBch (USER1 chain)
0,
new byte[32]
), t);
TestLog.pass("IT_03_AddBlock_NoAuth (combined): OK"); TestLog.pass("IT_03_AddBlock_NoAuth (combined): OK");
} }