diff --git a/SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/channels/Net_GetMessageThread_Handler.java b/SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/channels/Net_GetMessageThread_Handler.java index 3c0b8570..6c3e7ffe 100644 --- a/SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/channels/Net_GetMessageThread_Handler.java +++ b/SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/channels/Net_GetMessageThread_Handler.java @@ -28,7 +28,7 @@ public class Net_GetMessageThread_Handler implements JsonMessageHandler { public Net_Response handle(Net_Request baseRequest, ConnectionContext ctx) { Net_GetMessageThread_Request req = (Net_GetMessageThread_Request) baseRequest; if (req.getMessage() == null || req.getMessage().getBlockchainName() == null || req.getMessage().getBlockNumber() == null) { - return NetExceptionResponseFactory.error(req, WireCodes.Status.BAD_REQUEST, "bad_fields", "Некорректные поля message"); + return NetExceptionResponseFactory.error(req, WireCodes.Status.BAD_REQUEST, "bad_fields", "Некорректные поля message"); } int depthUp = req.getDepthUp() == null ? 20 : Math.max(0, req.getDepthUp()); @@ -40,9 +40,9 @@ public class Net_GetMessageThread_Handler implements JsonMessageHandler { if (viewerLogin == null || viewerLogin.isBlank()) { viewerLogin = ChannelsReadSupport.canonicalLogin(c, req.getLogin()); } - PostRow focusRow = findByNumber(c, req.getMessage().getBlockchainName(), req.getMessage().getBlockNumber()); + PostRow focusRow = findFocusRow(c, req.getMessage()); if (focusRow == null) { - return NetExceptionResponseFactory.error(req, 404, "message_not_found", "Сообщение РЅРµ найдено"); + return NetExceptionResponseFactory.error(req, 404, "message_not_found", "Сообщение не найдено"); } Net_GetMessageThread_Response resp = new Net_GetMessageThread_Response(); @@ -67,10 +67,31 @@ public class Net_GetMessageThread_Handler implements JsonMessageHandler { return resp; } catch (Exception e) { log.error("GetMessageThread failed", e); - return NetExceptionResponseFactory.error(req, WireCodes.Status.INTERNAL_ERROR, "internal_error", "Внутренняя ошибка сервера"); + return NetExceptionResponseFactory.error(req, WireCodes.Status.INTERNAL_ERROR, "internal_error", "Внутренняя ошибка сервера"); } } + private PostRow findFocusRow(Connection c, Net_GetMessageThread_Request.MessageSelector selector) throws Exception { + String blockchainName = String.valueOf(selector.getBlockchainName() == null ? "" : selector.getBlockchainName()).trim(); + int blockNumber = selector.getBlockNumber(); + byte[] blockHash = parseOptionalHash(selector.getBlockHash()); + + if (blockHash != null) { + PostRow exact = findByNumberAndHash(c, blockchainName, blockNumber, blockHash); + if (exact != null) return exact; + } + + PostRow byNumber = findByNumber(c, blockchainName, blockNumber); + if (byNumber != null) return byNumber; + + if (blockHash != null) { + PostRow byHash = findByHash(c, blockHash); + if (byHash != null) return byHash; + } + + return null; + } + private List loadChildren(Connection c, PostRow parent, int depthDown, int childLimit, String viewerLogin) throws Exception { if (depthDown <= 0) return List.of(); List replies = findReplies(c, parent.bchName, parent.blockNumber, parent.blockHash, childLimit); @@ -123,6 +144,48 @@ public class Net_GetMessageThread_Handler implements JsonMessageHandler { } } + private PostRow findByNumberAndHash(Connection c, String bchName, int blockNumber, byte[] blockHash) throws Exception { + String sql = """ + SELECT login,bch_name,block_number,block_hash,block_bytes,to_bch_name,to_block_number,to_block_hash,line_code,msg_sub_type,this_line_number + FROM blocks + WHERE bch_name=? AND block_number=? AND block_hash=? + LIMIT 1 + """; + try (PreparedStatement ps = c.prepareStatement(sql)) { + ps.setString(1, bchName); + ps.setInt(2, blockNumber); + ps.setBytes(3, blockHash); + try (ResultSet rs = ps.executeQuery()) { + return rs.next() ? mapRow(rs) : null; + } + } + } + + private PostRow findByHash(Connection c, byte[] blockHash) throws Exception { + String sql = """ + SELECT login,bch_name,block_number,block_hash,block_bytes,to_bch_name,to_block_number,to_block_hash,line_code,msg_sub_type,this_line_number + FROM blocks + WHERE block_hash=? + LIMIT 1 + """; + try (PreparedStatement ps = c.prepareStatement(sql)) { + ps.setBytes(1, blockHash); + try (ResultSet rs = ps.executeQuery()) { + return rs.next() ? mapRow(rs) : null; + } + } + } + + private byte[] parseOptionalHash(String hex) { + String value = String.valueOf(hex == null ? "" : hex).trim(); + if (value.isEmpty()) return null; + try { + return ChannelsReadSupport.hexToBytes(value); + } catch (Exception ignored) { + return null; + } + } + private PostRow mapRow(ResultSet rs) throws Exception { PostRow row = new PostRow(); row.login = rs.getString("login"); diff --git a/SHiNE-server/src/test/java/test/it/cases/IT_06_ChannelsApi.java b/SHiNE-server/src/test/java/test/it/cases/IT_06_ChannelsApi.java index 80055668..f45208c5 100644 --- a/SHiNE-server/src/test/java/test/it/cases/IT_06_ChannelsApi.java +++ b/SHiNE-server/src/test/java/test/it/cases/IT_06_ChannelsApi.java @@ -57,11 +57,12 @@ public class IT_06_ChannelsApi { JsonNode first = messages.get(0); int blockNumber = first.path("messageRef").path("blockNumber").asInt(-1); String blockHash = first.path("messageRef").path("blockHash").asText(""); + String messageBlockchainName = first.path("authorBlockchainName").asText(""); - if (blockNumber > 0 && !blockHash.isBlank()) { + if (!messageBlockchainName.isBlank() && blockNumber >= 0 && !blockHash.isBlank()) { String threadResp = ws.call( "GetMessageThread", - JsonBuilders.getMessageThread(bchName, blockNumber, blockHash, 20, 2, 50), + JsonBuilders.getMessageThread(messageBlockchainName, blockNumber, blockHash, 20, 2, 50), t ); check200(r, threadResp, "GetMessageThread"); @@ -73,7 +74,7 @@ public class IT_06_ChannelsApi { } r.ok("GetMessageThread: payload shape OK"); } else { - r.ok("GetMessageThread: пропущено, у первого сообщения нет корректного ref"); + r.ok("GetMessageThread: пропущено, у первого сообщения нет полного messageRef/authorBlockchainName"); } } else { r.ok("GetMessageThread: пропущено, в канале нет сообщений"); diff --git a/VERSION.properties b/VERSION.properties index 6df3a14e..7068baa2 100644 --- a/VERSION.properties +++ b/VERSION.properties @@ -1,2 +1,2 @@ client.version=1.2.354 -server.version=1.2.327 +server.version=1.2.328