SHA256
Start server-side channel read RPC handlers and simplify API spec
This commit is contained in:
+12
@@ -45,6 +45,12 @@ import server.logic.ws_protocol.JSON.handlers.userParams.entyties.Net_UpsertUser
|
||||
// --- NEW: connections friends lists ---
|
||||
import server.logic.ws_protocol.JSON.handlers.connections.Net_GetFriendsLists_Handler;
|
||||
import server.logic.ws_protocol.JSON.handlers.connections.entyties.Net_GetFriendsLists_Request;
|
||||
import server.logic.ws_protocol.JSON.handlers.channels.Net_GetChannelMessages_Handler;
|
||||
import server.logic.ws_protocol.JSON.handlers.channels.Net_GetMessageThread_Handler;
|
||||
import server.logic.ws_protocol.JSON.handlers.channels.Net_ListSubscriptionsFeed_Handler;
|
||||
import server.logic.ws_protocol.JSON.handlers.channels.entyties.Net_GetChannelMessages_Request;
|
||||
import server.logic.ws_protocol.JSON.handlers.channels.entyties.Net_GetMessageThread_Request;
|
||||
import server.logic.ws_protocol.JSON.handlers.channels.entyties.Net_ListSubscriptionsFeed_Request;
|
||||
|
||||
// --- NEW: Ping ---
|
||||
import server.logic.ws_protocol.JSON.handlers.system.Net_GetServerInfo_Handler;
|
||||
@@ -85,6 +91,9 @@ public final class JsonHandlerRegistry {
|
||||
|
||||
// --- connections ---
|
||||
Map.entry("GetFriendsLists", new Net_GetFriendsLists_Handler()),
|
||||
Map.entry("ListSubscriptionsFeed", new Net_ListSubscriptionsFeed_Handler()),
|
||||
Map.entry("GetChannelMessages", new Net_GetChannelMessages_Handler()),
|
||||
Map.entry("GetMessageThread", new Net_GetMessageThread_Handler()),
|
||||
|
||||
// --- system ---
|
||||
Map.entry("Ping", new Net_Ping_Handler()),
|
||||
@@ -119,6 +128,9 @@ public final class JsonHandlerRegistry {
|
||||
|
||||
// --- connections ---
|
||||
Map.entry("GetFriendsLists", Net_GetFriendsLists_Request.class),
|
||||
Map.entry("ListSubscriptionsFeed", Net_ListSubscriptionsFeed_Request.class),
|
||||
Map.entry("GetChannelMessages", Net_GetChannelMessages_Request.class),
|
||||
Map.entry("GetMessageThread", Net_GetMessageThread_Request.class),
|
||||
|
||||
// --- system ---
|
||||
Map.entry("Ping", Net_Ping_Request.class),
|
||||
|
||||
+43
@@ -5,6 +5,7 @@ import blockchain.BchCryptoVerifier;
|
||||
import blockchain.MsgSubType;
|
||||
import blockchain.body.BodyHasLine;
|
||||
import blockchain.body.BodyHasTarget;
|
||||
import blockchain.body.CreateChannelBody;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import server.logic.ws_protocol.Base64Ws;
|
||||
@@ -25,6 +26,9 @@ import shine.db.entities.BlockEntry;
|
||||
import utils.blockchain.BlockchainNameUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
@@ -128,6 +132,7 @@ public final class Net_AddBlock_Handler implements JsonMessageHandler {
|
||||
case "prev_line_block_not_found" -> "Не найден блок prevLineNumber для проверки линии";
|
||||
case "bad_prev_line_hash" -> "Некорректный prevLineHash";
|
||||
case "db_error_prev_line_check" -> "Ошибка БД при проверке prevLine";
|
||||
case "channel_name_already_exists" -> "Канал с таким именем уже существует";
|
||||
case "internal_error" -> "Внутренняя ошибка сервера при записи блока";
|
||||
default -> "Ошибка: " + code;
|
||||
};
|
||||
@@ -228,6 +233,18 @@ public final class Net_AddBlock_Handler implements JsonMessageHandler {
|
||||
return new AddBlockResult(WireCodes.Status.BAD_REQUEST, "bad_block_body", serverLastNum, serverLastHashHex);
|
||||
}
|
||||
|
||||
if (block.body instanceof CreateChannelBody createChannelBody) {
|
||||
try {
|
||||
if (channelNameExists(blockchainName, createChannelBody.channelName)) {
|
||||
return new AddBlockResult(409, "channel_name_already_exists", serverLastNum, serverLastHashHex);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("AddBlock: channel_name_check_failed (blockchainName={}, channelName={})",
|
||||
blockchainName, createChannelBody.channelName, e);
|
||||
return new AddBlockResult(WireCodes.Status.INTERNAL_ERROR, "internal_error", serverLastNum, serverLastHashHex);
|
||||
}
|
||||
}
|
||||
|
||||
// 4.2) запрет дырок: blockNumber строго last+1
|
||||
int expectedBlockNumber = serverLastNum + 1;
|
||||
if (block.blockNumber != expectedBlockNumber) {
|
||||
@@ -378,6 +395,32 @@ public final class Net_AddBlock_Handler implements JsonMessageHandler {
|
||||
return Base64Ws.decode(b64);
|
||||
}
|
||||
|
||||
private boolean channelNameExists(String blockchainName, String channelName) throws Exception {
|
||||
String sql = """
|
||||
SELECT block_bytes
|
||||
FROM blocks
|
||||
WHERE bch_name = ? AND msg_type = 0 AND msg_sub_type = 1
|
||||
""";
|
||||
try (Connection c = shine.db.SqliteDbController.getInstance().getConnection();
|
||||
PreparedStatement ps = c.prepareStatement(sql)) {
|
||||
ps.setString(1, blockchainName);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
byte[] bytes = rs.getBytes("block_bytes");
|
||||
try {
|
||||
BchBlockEntry entry = new BchBlockEntry(bytes);
|
||||
if (entry.body instanceof CreateChannelBody ccb) {
|
||||
if (ccb.channelName.equalsIgnoreCase(channelName)) return true;
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
// ignore bad historic rows, uniqueness check is best effort
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static long safeAdd(long a, long b) {
|
||||
long r = a + b;
|
||||
if (((a ^ r) & (b ^ r)) < 0) throw new ArithmeticException("long overflow");
|
||||
|
||||
+240
@@ -0,0 +1,240 @@
|
||||
package server.logic.ws_protocol.JSON.handlers.channels;
|
||||
|
||||
import blockchain.BchBlockEntry;
|
||||
import blockchain.body.BodyRecord;
|
||||
import blockchain.body.CreateChannelBody;
|
||||
import blockchain.body.TextBody;
|
||||
import shine.db.MsgSubType;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
final class ChannelsReadSupport {
|
||||
static final int MSG_TYPE_TEXT = 1;
|
||||
static final int MSG_TYPE_TECH = 0;
|
||||
|
||||
private ChannelsReadSupport() {}
|
||||
|
||||
static String canonicalLogin(Connection c, String anyCaseLogin) throws SQLException {
|
||||
String sql = "SELECT login FROM solana_users WHERE login = ? COLLATE NOCASE LIMIT 1";
|
||||
try (PreparedStatement ps = c.prepareStatement(sql)) {
|
||||
ps.setString(1, anyCaseLogin);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
return rs.next() ? rs.getString("login") : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static String detectChannelName(Connection c, String ownerBch, int rootNumber) throws SQLException {
|
||||
if (rootNumber == 0) return "0";
|
||||
|
||||
String sql = "SELECT block_bytes FROM blocks WHERE bch_name=? AND block_number=? LIMIT 1";
|
||||
try (PreparedStatement ps = c.prepareStatement(sql)) {
|
||||
ps.setString(1, ownerBch);
|
||||
ps.setInt(2, rootNumber);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (!rs.next()) return null;
|
||||
byte[] bytes = rs.getBytes("block_bytes");
|
||||
BchBlockEntry e = new BchBlockEntry(bytes);
|
||||
BodyRecord body = e.body;
|
||||
if (body instanceof CreateChannelBody ccb) return ccb.channelName;
|
||||
return null;
|
||||
} catch (Exception ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int countPosts(Connection c, String ownerBch, int lineCode) throws SQLException {
|
||||
String sql = "SELECT COUNT(*) AS cnt FROM blocks WHERE bch_name=? AND msg_type=? AND msg_sub_type=? AND line_code=?";
|
||||
try (PreparedStatement ps = c.prepareStatement(sql)) {
|
||||
ps.setString(1, ownerBch);
|
||||
ps.setInt(2, MSG_TYPE_TEXT);
|
||||
ps.setInt(3, MsgSubType.TEXT_POST);
|
||||
ps.setInt(4, lineCode);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
return rs.next() ? rs.getInt("cnt") : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static PostBlock loadLastPost(Connection c, String ownerBch, int lineCode) throws SQLException {
|
||||
String sql = """
|
||||
SELECT login,bch_name,block_number,block_hash,block_bytes
|
||||
FROM blocks
|
||||
WHERE bch_name=? AND msg_type=? AND msg_sub_type=? AND line_code=?
|
||||
ORDER BY block_number DESC
|
||||
LIMIT 1
|
||||
""";
|
||||
try (PreparedStatement ps = c.prepareStatement(sql)) {
|
||||
ps.setString(1, ownerBch);
|
||||
ps.setInt(2, MSG_TYPE_TEXT);
|
||||
ps.setInt(3, MsgSubType.TEXT_POST);
|
||||
ps.setInt(4, lineCode);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (!rs.next()) return null;
|
||||
PostBlock pb = new PostBlock();
|
||||
pb.login = rs.getString("login");
|
||||
pb.bchName = rs.getString("bch_name");
|
||||
pb.blockNumber = rs.getInt("block_number");
|
||||
pb.blockHash = rs.getBytes("block_hash");
|
||||
pb.blockBytes = rs.getBytes("block_bytes");
|
||||
return pb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static PostBlock loadLastVersion(Connection c, String ownerBch, int originalBlockNumber, byte[] originalHash) throws SQLException {
|
||||
String sql = """
|
||||
SELECT login,bch_name,block_number,block_hash,block_bytes
|
||||
FROM blocks
|
||||
WHERE bch_name=? AND msg_type=? AND msg_sub_type=?
|
||||
AND to_bch_name=? AND to_block_number=? AND to_block_hash=?
|
||||
ORDER BY block_number DESC
|
||||
LIMIT 1
|
||||
""";
|
||||
try (PreparedStatement ps = c.prepareStatement(sql)) {
|
||||
ps.setString(1, ownerBch);
|
||||
ps.setInt(2, MSG_TYPE_TEXT);
|
||||
ps.setInt(3, MsgSubType.TEXT_EDIT_POST);
|
||||
ps.setString(4, ownerBch);
|
||||
ps.setInt(5, originalBlockNumber);
|
||||
ps.setBytes(6, originalHash);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (!rs.next()) return null;
|
||||
PostBlock pb = new PostBlock();
|
||||
pb.login = rs.getString("login");
|
||||
pb.bchName = rs.getString("bch_name");
|
||||
pb.blockNumber = rs.getInt("block_number");
|
||||
pb.blockHash = rs.getBytes("block_hash");
|
||||
pb.blockBytes = rs.getBytes("block_bytes");
|
||||
return pb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static TextInfo parseTextAndTime(byte[] blockBytes) {
|
||||
try {
|
||||
BchBlockEntry e = new BchBlockEntry(blockBytes);
|
||||
TextInfo ti = new TextInfo();
|
||||
ti.createdAtMs = e.timeMs;
|
||||
if (e.body instanceof TextBody tb) {
|
||||
ti.text = tb.message;
|
||||
}
|
||||
return ti;
|
||||
} catch (Exception ex) {
|
||||
return new TextInfo();
|
||||
}
|
||||
}
|
||||
|
||||
static List<PostBlock> channelPosts(Connection c, String ownerBch, int lineCode, int limit, boolean asc) throws SQLException {
|
||||
String order = asc ? "ASC" : "DESC";
|
||||
String sql = """
|
||||
SELECT login,bch_name,block_number,block_hash,block_bytes
|
||||
FROM blocks
|
||||
WHERE bch_name=? AND msg_type=? AND msg_sub_type=? AND line_code=?
|
||||
ORDER BY block_number """ + order + " LIMIT ?";
|
||||
try (PreparedStatement ps = c.prepareStatement(sql)) {
|
||||
ps.setString(1, ownerBch);
|
||||
ps.setInt(2, MSG_TYPE_TEXT);
|
||||
ps.setInt(3, MsgSubType.TEXT_POST);
|
||||
ps.setInt(4, lineCode);
|
||||
ps.setInt(5, limit);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
List<PostBlock> out = new ArrayList<>();
|
||||
while (rs.next()) {
|
||||
PostBlock pb = new PostBlock();
|
||||
pb.login = rs.getString("login");
|
||||
pb.bchName = rs.getString("bch_name");
|
||||
pb.blockNumber = rs.getInt("block_number");
|
||||
pb.blockHash = rs.getBytes("block_hash");
|
||||
pb.blockBytes = rs.getBytes("block_bytes");
|
||||
out.add(pb);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static List<PostBlock> versionsForPost(Connection c, String ownerBch, int originalBlock, byte[] originalHash) throws SQLException {
|
||||
String sql = """
|
||||
SELECT login,bch_name,block_number,block_hash,block_bytes
|
||||
FROM blocks
|
||||
WHERE bch_name=? AND msg_type=? AND msg_sub_type=?
|
||||
AND to_bch_name=? AND to_block_number=? AND to_block_hash=?
|
||||
ORDER BY block_number ASC
|
||||
""";
|
||||
try (PreparedStatement ps = c.prepareStatement(sql)) {
|
||||
ps.setString(1, ownerBch);
|
||||
ps.setInt(2, MSG_TYPE_TEXT);
|
||||
ps.setInt(3, MsgSubType.TEXT_EDIT_POST);
|
||||
ps.setString(4, ownerBch);
|
||||
ps.setInt(5, originalBlock);
|
||||
ps.setBytes(6, originalHash);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
List<PostBlock> out = new ArrayList<>();
|
||||
while (rs.next()) {
|
||||
PostBlock pb = new PostBlock();
|
||||
pb.login = rs.getString("login");
|
||||
pb.bchName = rs.getString("bch_name");
|
||||
pb.blockNumber = rs.getInt("block_number");
|
||||
pb.blockHash = rs.getBytes("block_hash");
|
||||
pb.blockBytes = rs.getBytes("block_bytes");
|
||||
out.add(pb);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int[] loadStats(Connection c, String bch, int blockNumber, byte[] blockHash) throws SQLException {
|
||||
String sql = "SELECT likes_count,replies_count FROM message_stats WHERE to_bch_name=? AND to_block_number=? AND to_block_hash=? LIMIT 1";
|
||||
try (PreparedStatement ps = c.prepareStatement(sql)) {
|
||||
ps.setString(1, bch);
|
||||
ps.setInt(2, blockNumber);
|
||||
ps.setBytes(3, blockHash);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (!rs.next()) return new int[] {0, 0};
|
||||
return new int[] {rs.getInt("likes_count"), rs.getInt("replies_count")};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static byte[] hexToBytes(String s) {
|
||||
if (s == null) return null;
|
||||
String x = s.trim();
|
||||
if ((x.length() & 1) != 0) throw new IllegalArgumentException("hex length must be even");
|
||||
byte[] out = new byte[x.length() / 2];
|
||||
for (int i = 0; i < out.length; i++) {
|
||||
int hi = Character.digit(x.charAt(i * 2), 16);
|
||||
int lo = Character.digit(x.charAt(i * 2 + 1), 16);
|
||||
if (hi < 0 || lo < 0) throw new IllegalArgumentException("bad hex");
|
||||
out[i] = (byte) ((hi << 4) | lo);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static String toHex(byte[] bytes) {
|
||||
if (bytes == null) return null;
|
||||
StringBuilder sb = new StringBuilder(bytes.length * 2);
|
||||
for (byte b : bytes) sb.append(String.format("%02x", b));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
static final class PostBlock {
|
||||
String login;
|
||||
String bchName;
|
||||
int blockNumber;
|
||||
byte[] blockHash;
|
||||
byte[] blockBytes;
|
||||
}
|
||||
|
||||
static final class TextInfo {
|
||||
String text = "";
|
||||
long createdAtMs = 0L;
|
||||
}
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
package server.logic.ws_protocol.JSON.handlers.channels;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import server.logic.ws_protocol.JSON.ConnectionContext;
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Response;
|
||||
import server.logic.ws_protocol.JSON.handlers.JsonMessageHandler;
|
||||
import server.logic.ws_protocol.JSON.handlers.channels.entyties.Net_GetChannelMessages_Request;
|
||||
import server.logic.ws_protocol.JSON.handlers.channels.entyties.Net_GetChannelMessages_Response;
|
||||
import server.logic.ws_protocol.JSON.utils.NetExceptionResponseFactory;
|
||||
import server.logic.ws_protocol.WireCodes;
|
||||
import shine.db.SqliteDbController;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Net_GetChannelMessages_Handler implements JsonMessageHandler {
|
||||
private static final Logger log = LoggerFactory.getLogger(Net_GetChannelMessages_Handler.class);
|
||||
|
||||
@Override
|
||||
public Net_Response handle(Net_Request baseRequest, ConnectionContext ctx) {
|
||||
Net_GetChannelMessages_Request req = (Net_GetChannelMessages_Request) baseRequest;
|
||||
if (req.getChannel() == null
|
||||
|| req.getChannel().getOwnerBlockchainName() == null
|
||||
|| req.getChannel().getOwnerBlockchainName().isBlank()
|
||||
|| req.getChannel().getChannelRootBlockNumber() == null) {
|
||||
return NetExceptionResponseFactory.error(req, WireCodes.Status.BAD_REQUEST, "bad_fields", "Некорректные поля channel");
|
||||
}
|
||||
|
||||
int limit = req.getLimit() == null ? 30 : req.getLimit();
|
||||
if (limit <= 0 || limit > 1000) {
|
||||
return NetExceptionResponseFactory.error(req, WireCodes.Status.BAD_REQUEST, "limit_too_large", "Некорректный limit");
|
||||
}
|
||||
|
||||
boolean asc = req.getSort() == null || !"desc".equalsIgnoreCase(req.getSort());
|
||||
|
||||
try (Connection c = SqliteDbController.getInstance().getConnection()) {
|
||||
String ownerBch = req.getChannel().getOwnerBlockchainName();
|
||||
int lineCode = req.getChannel().getChannelRootBlockNumber();
|
||||
|
||||
Net_GetChannelMessages_Response resp = new Net_GetChannelMessages_Response();
|
||||
resp.setOp(req.getOp());
|
||||
resp.setRequestId(req.getRequestId());
|
||||
resp.setStatus(WireCodes.Status.OK);
|
||||
|
||||
Net_GetChannelMessages_Response.Channel channel = new Net_GetChannelMessages_Response.Channel();
|
||||
channel.setOwnerBlockchainName(ownerBch);
|
||||
channel.setOwnerLogin(ownerBch.contains("-") ? ownerBch.substring(0, ownerBch.indexOf('-')) : ownerBch);
|
||||
channel.setChannelName(ChannelsReadSupport.detectChannelName(c, ownerBch, lineCode));
|
||||
Net_GetChannelMessages_Response.BlockRef rootRef = new Net_GetChannelMessages_Response.BlockRef();
|
||||
rootRef.setBlockNumber(lineCode);
|
||||
rootRef.setBlockHash(req.getChannel().getChannelRootBlockHash());
|
||||
channel.setChannelRoot(rootRef);
|
||||
resp.setChannel(channel);
|
||||
|
||||
List<ChannelsReadSupport.PostBlock> posts = ChannelsReadSupport.channelPosts(c, ownerBch, lineCode, limit, asc);
|
||||
List<Net_GetChannelMessages_Response.MessageItem> items = new ArrayList<>();
|
||||
|
||||
for (ChannelsReadSupport.PostBlock post : posts) {
|
||||
Net_GetChannelMessages_Response.MessageItem item = new Net_GetChannelMessages_Response.MessageItem();
|
||||
Net_GetChannelMessages_Response.BlockRef msgRef = new Net_GetChannelMessages_Response.BlockRef();
|
||||
msgRef.setBlockNumber(post.blockNumber);
|
||||
msgRef.setBlockHash(ChannelsReadSupport.toHex(post.blockHash));
|
||||
item.setMessageRef(msgRef);
|
||||
item.setAuthorLogin(post.login);
|
||||
item.setAuthorBlockchainName(post.bchName);
|
||||
|
||||
List<Net_GetChannelMessages_Response.VersionItem> versionsOut = new ArrayList<>();
|
||||
int index = 1;
|
||||
|
||||
ChannelsReadSupport.TextInfo postText = ChannelsReadSupport.parseTextAndTime(post.blockBytes);
|
||||
Net_GetChannelMessages_Response.VersionItem v1 = new Net_GetChannelMessages_Response.VersionItem();
|
||||
v1.setVersionIndex(index++);
|
||||
v1.setBlockNumber(post.blockNumber);
|
||||
v1.setBlockHash(ChannelsReadSupport.toHex(post.blockHash));
|
||||
v1.setText(postText.text);
|
||||
v1.setCreatedAtMs(postText.createdAtMs);
|
||||
versionsOut.add(v1);
|
||||
|
||||
List<ChannelsReadSupport.PostBlock> edits = ChannelsReadSupport.versionsForPost(c, ownerBch, post.blockNumber, post.blockHash);
|
||||
for (ChannelsReadSupport.PostBlock edit : edits) {
|
||||
ChannelsReadSupport.TextInfo editText = ChannelsReadSupport.parseTextAndTime(edit.blockBytes);
|
||||
Net_GetChannelMessages_Response.VersionItem ve = new Net_GetChannelMessages_Response.VersionItem();
|
||||
ve.setVersionIndex(index++);
|
||||
ve.setBlockNumber(edit.blockNumber);
|
||||
ve.setBlockHash(ChannelsReadSupport.toHex(edit.blockHash));
|
||||
ve.setText(editText.text);
|
||||
ve.setCreatedAtMs(editText.createdAtMs);
|
||||
versionsOut.add(ve);
|
||||
}
|
||||
|
||||
item.setVersions(versionsOut);
|
||||
item.setVersionsTotal(versionsOut.size());
|
||||
|
||||
Net_GetChannelMessages_Response.VersionItem lastV = versionsOut.get(versionsOut.size() - 1);
|
||||
item.setText(lastV.getText());
|
||||
item.setCreatedAtMs(postText.createdAtMs);
|
||||
|
||||
int[] stats = ChannelsReadSupport.loadStats(c, ownerBch, post.blockNumber, post.blockHash);
|
||||
item.setLikesCount(stats[0]);
|
||||
item.setRepliesCount(stats[1]);
|
||||
|
||||
items.add(item);
|
||||
}
|
||||
|
||||
resp.setMessages(items);
|
||||
return resp;
|
||||
} catch (Exception e) {
|
||||
log.error("GetChannelMessages failed", e);
|
||||
return NetExceptionResponseFactory.error(req, WireCodes.Status.INTERNAL_ERROR, "internal_error", "Внутренняя ошибка сервера");
|
||||
}
|
||||
}
|
||||
}
|
||||
+224
@@ -0,0 +1,224 @@
|
||||
package server.logic.ws_protocol.JSON.handlers.channels;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import server.logic.ws_protocol.JSON.ConnectionContext;
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Response;
|
||||
import server.logic.ws_protocol.JSON.handlers.JsonMessageHandler;
|
||||
import server.logic.ws_protocol.JSON.handlers.channels.entyties.Net_GetChannelMessages_Response;
|
||||
import server.logic.ws_protocol.JSON.handlers.channels.entyties.Net_GetMessageThread_Request;
|
||||
import server.logic.ws_protocol.JSON.handlers.channels.entyties.Net_GetMessageThread_Response;
|
||||
import server.logic.ws_protocol.JSON.utils.NetExceptionResponseFactory;
|
||||
import server.logic.ws_protocol.WireCodes;
|
||||
import shine.db.MsgSubType;
|
||||
import shine.db.SqliteDbController;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Net_GetMessageThread_Handler implements JsonMessageHandler {
|
||||
private static final Logger log = LoggerFactory.getLogger(Net_GetMessageThread_Handler.class);
|
||||
|
||||
@Override
|
||||
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");
|
||||
}
|
||||
|
||||
int depthUp = req.getDepthUp() == null ? 20 : Math.max(0, req.getDepthUp());
|
||||
int depthDown = req.getDepthDown() == null ? 2 : Math.max(0, req.getDepthDown());
|
||||
int childLimit = req.getLimitChildrenPerNode() == null ? 50 : Math.max(1, req.getLimitChildrenPerNode());
|
||||
|
||||
try (Connection c = SqliteDbController.getInstance().getConnection()) {
|
||||
PostRow focusRow = findByNumber(c, req.getMessage().getBlockchainName(), req.getMessage().getBlockNumber());
|
||||
if (focusRow == null) {
|
||||
return NetExceptionResponseFactory.error(req, 404, "message_not_found", "Сообщение не найдено");
|
||||
}
|
||||
|
||||
Net_GetMessageThread_Response resp = new Net_GetMessageThread_Response();
|
||||
resp.setOp(req.getOp());
|
||||
resp.setRequestId(req.getRequestId());
|
||||
resp.setStatus(WireCodes.Status.OK);
|
||||
|
||||
resp.setFocus(toNode(c, focusRow));
|
||||
|
||||
List<Net_GetMessageThread_Response.MessageNode> ancestors = new ArrayList<>();
|
||||
PostRow cur = focusRow;
|
||||
for (int i = 0; i < depthUp; i++) {
|
||||
if (cur.toBlockNumber == null || cur.toBchName == null) break;
|
||||
PostRow parent = findByNumber(c, cur.toBchName, cur.toBlockNumber);
|
||||
if (parent == null) break;
|
||||
ancestors.add(0, toNode(c, parent));
|
||||
cur = parent;
|
||||
}
|
||||
resp.setAncestors(ancestors);
|
||||
|
||||
resp.setDescendants(loadChildren(c, focusRow, depthDown, childLimit));
|
||||
return resp;
|
||||
} catch (Exception e) {
|
||||
log.error("GetMessageThread failed", e);
|
||||
return NetExceptionResponseFactory.error(req, WireCodes.Status.INTERNAL_ERROR, "internal_error", "Внутренняя ошибка сервера");
|
||||
}
|
||||
}
|
||||
|
||||
private List<Net_GetMessageThread_Response.MessageNodeTree> loadChildren(Connection c, PostRow parent, int depthDown, int childLimit) throws Exception {
|
||||
if (depthDown <= 0) return List.of();
|
||||
List<PostRow> replies = findReplies(c, parent.bchName, parent.blockNumber, parent.blockHash, childLimit);
|
||||
List<Net_GetMessageThread_Response.MessageNodeTree> out = new ArrayList<>();
|
||||
for (PostRow row : replies) {
|
||||
Net_GetMessageThread_Response.MessageNodeTree t = new Net_GetMessageThread_Response.MessageNodeTree();
|
||||
t.setNode(toNode(c, row));
|
||||
t.setChildren(loadChildren(c, row, depthDown - 1, childLimit));
|
||||
out.add(t);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private List<PostRow> findReplies(Connection c, String toBchName, int toBlockNumber, byte[] toBlockHash, int limit) 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
|
||||
FROM blocks
|
||||
WHERE msg_type=1 AND msg_sub_type=?
|
||||
AND to_bch_name=? AND to_block_number=? AND to_block_hash=?
|
||||
ORDER BY block_number ASC
|
||||
LIMIT ?
|
||||
""";
|
||||
try (PreparedStatement ps = c.prepareStatement(sql)) {
|
||||
ps.setInt(1, MsgSubType.TEXT_REPLY);
|
||||
ps.setString(2, toBchName);
|
||||
ps.setInt(3, toBlockNumber);
|
||||
ps.setBytes(4, toBlockHash);
|
||||
ps.setInt(5, limit);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
List<PostRow> out = new ArrayList<>();
|
||||
while (rs.next()) out.add(mapRow(rs));
|
||||
return out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private PostRow findByNumber(Connection c, String bchName, int blockNumber) 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
|
||||
FROM blocks
|
||||
WHERE bch_name=? AND block_number=?
|
||||
LIMIT 1
|
||||
""";
|
||||
try (PreparedStatement ps = c.prepareStatement(sql)) {
|
||||
ps.setString(1, bchName);
|
||||
ps.setInt(2, blockNumber);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
return rs.next() ? mapRow(rs) : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private PostRow mapRow(ResultSet rs) throws Exception {
|
||||
PostRow row = new PostRow();
|
||||
row.login = rs.getString("login");
|
||||
row.bchName = rs.getString("bch_name");
|
||||
row.blockNumber = rs.getInt("block_number");
|
||||
row.blockHash = rs.getBytes("block_hash");
|
||||
row.blockBytes = rs.getBytes("block_bytes");
|
||||
row.toBchName = rs.getString("to_bch_name");
|
||||
row.toBlockNumber = (Integer) rs.getObject("to_block_number");
|
||||
row.toBlockHash = rs.getBytes("to_block_hash");
|
||||
row.lineCode = (Integer) rs.getObject("line_code");
|
||||
row.msgSubType = rs.getInt("msg_sub_type");
|
||||
return row;
|
||||
}
|
||||
|
||||
private Net_GetMessageThread_Response.MessageNode toNode(Connection c, PostRow row) throws Exception {
|
||||
Net_GetMessageThread_Response.MessageNode node = new Net_GetMessageThread_Response.MessageNode();
|
||||
Net_GetChannelMessages_Response.BlockRef ref = new Net_GetChannelMessages_Response.BlockRef();
|
||||
ref.setBlockNumber(row.blockNumber);
|
||||
ref.setBlockHash(ChannelsReadSupport.toHex(row.blockHash));
|
||||
node.setMessageRef(ref);
|
||||
node.setAuthorLogin(row.login);
|
||||
node.setAuthorBlockchainName(row.bchName);
|
||||
|
||||
ChannelsReadSupport.TextInfo base = ChannelsReadSupport.parseTextAndTime(row.blockBytes);
|
||||
node.setCreatedAtMs(base.createdAtMs);
|
||||
|
||||
List<Net_GetChannelMessages_Response.VersionItem> versions = new ArrayList<>();
|
||||
Net_GetChannelMessages_Response.VersionItem first = new Net_GetChannelMessages_Response.VersionItem();
|
||||
first.setVersionIndex(1);
|
||||
first.setBlockNumber(row.blockNumber);
|
||||
first.setBlockHash(ChannelsReadSupport.toHex(row.blockHash));
|
||||
first.setText(base.text);
|
||||
first.setCreatedAtMs(base.createdAtMs);
|
||||
versions.add(first);
|
||||
|
||||
short editType = row.msgSubType == MsgSubType.TEXT_REPLY ? MsgSubType.TEXT_EDIT_REPLY : MsgSubType.TEXT_EDIT_POST;
|
||||
for (PostRow edit : findEdits(c, row.bchName, row.blockNumber, row.blockHash, editType)) {
|
||||
ChannelsReadSupport.TextInfo et = ChannelsReadSupport.parseTextAndTime(edit.blockBytes);
|
||||
Net_GetChannelMessages_Response.VersionItem v = new Net_GetChannelMessages_Response.VersionItem();
|
||||
v.setVersionIndex(versions.size() + 1);
|
||||
v.setBlockNumber(edit.blockNumber);
|
||||
v.setBlockHash(ChannelsReadSupport.toHex(edit.blockHash));
|
||||
v.setText(et.text);
|
||||
v.setCreatedAtMs(et.createdAtMs);
|
||||
versions.add(v);
|
||||
}
|
||||
|
||||
node.setVersions(versions);
|
||||
node.setVersionsTotal(versions.size());
|
||||
node.setText(versions.get(versions.size() - 1).getText());
|
||||
|
||||
int[] stats = ChannelsReadSupport.loadStats(c, row.bchName, row.blockNumber, row.blockHash);
|
||||
node.setLikesCount(stats[0]);
|
||||
node.setRepliesCount(stats[1]);
|
||||
|
||||
if (row.lineCode != null && row.lineCode >= 0) {
|
||||
Net_GetMessageThread_Response.ChannelInfo ci = new Net_GetMessageThread_Response.ChannelInfo();
|
||||
ci.setOwnerBlockchainName(row.bchName);
|
||||
Net_GetChannelMessages_Response.BlockRef root = new Net_GetChannelMessages_Response.BlockRef();
|
||||
root.setBlockNumber(row.lineCode);
|
||||
root.setBlockHash(null);
|
||||
ci.setChannelRoot(root);
|
||||
node.setChannelInfo(ci);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
private List<PostRow> findEdits(Connection c, String bch, int targetBlock, byte[] targetHash, int subType) 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
|
||||
FROM blocks
|
||||
WHERE bch_name=? AND msg_type=1 AND msg_sub_type=?
|
||||
AND to_bch_name=? AND to_block_number=? AND to_block_hash=?
|
||||
ORDER BY block_number ASC
|
||||
""";
|
||||
try (PreparedStatement ps = c.prepareStatement(sql)) {
|
||||
ps.setString(1, bch);
|
||||
ps.setInt(2, subType);
|
||||
ps.setString(3, bch);
|
||||
ps.setInt(4, targetBlock);
|
||||
ps.setBytes(5, targetHash);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
List<PostRow> out = new ArrayList<>();
|
||||
while (rs.next()) out.add(mapRow(rs));
|
||||
return out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class PostRow {
|
||||
String login;
|
||||
String bchName;
|
||||
int blockNumber;
|
||||
byte[] blockHash;
|
||||
byte[] blockBytes;
|
||||
String toBchName;
|
||||
Integer toBlockNumber;
|
||||
byte[] toBlockHash;
|
||||
Integer lineCode;
|
||||
int msgSubType;
|
||||
}
|
||||
}
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
package server.logic.ws_protocol.JSON.handlers.channels;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import server.logic.ws_protocol.JSON.ConnectionContext;
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Response;
|
||||
import server.logic.ws_protocol.JSON.handlers.JsonMessageHandler;
|
||||
import server.logic.ws_protocol.JSON.handlers.channels.entyties.Net_ListSubscriptionsFeed_Request;
|
||||
import server.logic.ws_protocol.JSON.handlers.channels.entyties.Net_ListSubscriptionsFeed_Response;
|
||||
import server.logic.ws_protocol.JSON.utils.NetExceptionResponseFactory;
|
||||
import server.logic.ws_protocol.WireCodes;
|
||||
import shine.db.MsgSubType;
|
||||
import shine.db.SqliteDbController;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Net_ListSubscriptionsFeed_Handler implements JsonMessageHandler {
|
||||
private static final Logger log = LoggerFactory.getLogger(Net_ListSubscriptionsFeed_Handler.class);
|
||||
|
||||
@Override
|
||||
public Net_Response handle(Net_Request baseRequest, ConnectionContext ctx) {
|
||||
Net_ListSubscriptionsFeed_Request req = (Net_ListSubscriptionsFeed_Request) baseRequest;
|
||||
if (req.getLogin() == null || req.getLogin().isBlank()) {
|
||||
return NetExceptionResponseFactory.error(req, WireCodes.Status.BAD_REQUEST, "bad_fields", "Некорректные поля: login");
|
||||
}
|
||||
|
||||
try (Connection c = SqliteDbController.getInstance().getConnection()) {
|
||||
String canonicalLogin = ChannelsReadSupport.canonicalLogin(c, req.getLogin().trim());
|
||||
if (canonicalLogin == null) {
|
||||
return NetExceptionResponseFactory.error(req, 404, "user_not_found", "Пользователь не найден");
|
||||
}
|
||||
|
||||
Net_ListSubscriptionsFeed_Response resp = new Net_ListSubscriptionsFeed_Response();
|
||||
resp.setOp(req.getOp());
|
||||
resp.setRequestId(req.getRequestId());
|
||||
resp.setStatus(WireCodes.Status.OK);
|
||||
resp.setLogin(canonicalLogin);
|
||||
|
||||
List<ChannelKey> own = loadOwnChannels(c, canonicalLogin);
|
||||
List<ChannelKey> followedUsersChannels = loadFollowedChannels(c, canonicalLogin, true);
|
||||
List<ChannelKey> followedChannels = loadFollowedChannels(c, canonicalLogin, false);
|
||||
|
||||
resp.setOwnedChannels(buildSummaries(c, own));
|
||||
resp.setFollowedUsersChannels(buildSummaries(c, followedUsersChannels));
|
||||
resp.setFollowedChannels(buildSummaries(c, followedChannels));
|
||||
|
||||
return resp;
|
||||
} catch (Exception e) {
|
||||
log.error("ListSubscriptionsFeed failed", e);
|
||||
return NetExceptionResponseFactory.error(req, WireCodes.Status.INTERNAL_ERROR, "internal_error", "Внутренняя ошибка сервера");
|
||||
}
|
||||
}
|
||||
|
||||
private List<Net_ListSubscriptionsFeed_Response.ChannelSummary> buildSummaries(Connection c, List<ChannelKey> keys) throws Exception {
|
||||
List<Net_ListSubscriptionsFeed_Response.ChannelSummary> out = new ArrayList<>();
|
||||
for (ChannelKey key : keys) {
|
||||
Net_ListSubscriptionsFeed_Response.ChannelSummary row = new Net_ListSubscriptionsFeed_Response.ChannelSummary();
|
||||
Net_ListSubscriptionsFeed_Response.ChannelRef channelRef = new Net_ListSubscriptionsFeed_Response.ChannelRef();
|
||||
channelRef.setOwnerLogin(key.ownerLogin);
|
||||
channelRef.setOwnerBlockchainName(key.ownerBch);
|
||||
channelRef.setChannelName(ChannelsReadSupport.detectChannelName(c, key.ownerBch, key.rootNumber));
|
||||
channelRef.setPersonal(key.rootNumber == 0);
|
||||
|
||||
Net_ListSubscriptionsFeed_Response.BlockRef rootRef = new Net_ListSubscriptionsFeed_Response.BlockRef();
|
||||
rootRef.setBlockNumber(key.rootNumber);
|
||||
rootRef.setBlockHash(ChannelsReadSupport.toHex(key.rootHash));
|
||||
channelRef.setChannelRoot(rootRef);
|
||||
|
||||
row.setChannel(channelRef);
|
||||
row.setMessagesCount(ChannelsReadSupport.countPosts(c, key.ownerBch, key.rootNumber));
|
||||
|
||||
ChannelsReadSupport.PostBlock lastPost = ChannelsReadSupport.loadLastPost(c, key.ownerBch, key.rootNumber);
|
||||
if (lastPost != null) {
|
||||
ChannelsReadSupport.PostBlock actual = ChannelsReadSupport.loadLastVersion(c, key.ownerBch, lastPost.blockNumber, lastPost.blockHash);
|
||||
if (actual == null) actual = lastPost;
|
||||
|
||||
ChannelsReadSupport.TextInfo textInfo = ChannelsReadSupport.parseTextAndTime(actual.blockBytes);
|
||||
Net_ListSubscriptionsFeed_Response.LastMessage lm = new Net_ListSubscriptionsFeed_Response.LastMessage();
|
||||
Net_ListSubscriptionsFeed_Response.BlockRef msgRef = new Net_ListSubscriptionsFeed_Response.BlockRef();
|
||||
msgRef.setBlockNumber(actual.blockNumber);
|
||||
msgRef.setBlockHash(ChannelsReadSupport.toHex(actual.blockHash));
|
||||
lm.setMessageRef(msgRef);
|
||||
lm.setText(textInfo.text);
|
||||
lm.setCreatedAtMs(textInfo.createdAtMs);
|
||||
lm.setAuthorLogin(actual.login);
|
||||
lm.setAuthorBlockchainName(actual.bchName);
|
||||
row.setLastMessage(lm);
|
||||
}
|
||||
|
||||
out.add(row);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private List<ChannelKey> loadOwnChannels(Connection c, String canonicalLogin) throws Exception {
|
||||
List<ChannelKey> out = new ArrayList<>();
|
||||
String bchSql = "SELECT blockchain_name FROM blockchain_state WHERE login=? ORDER BY blockchain_name";
|
||||
try (PreparedStatement bchPs = c.prepareStatement(bchSql)) {
|
||||
bchPs.setString(1, canonicalLogin);
|
||||
try (ResultSet bchRs = bchPs.executeQuery()) {
|
||||
while (bchRs.next()) {
|
||||
String bch = bchRs.getString("blockchain_name");
|
||||
out.add(new ChannelKey(canonicalLogin, bch, 0, new byte[32]));
|
||||
|
||||
String chSql = "SELECT block_number,block_hash FROM blocks WHERE bch_name=? AND msg_type=? AND msg_sub_type=? ORDER BY block_number";
|
||||
try (PreparedStatement chPs = c.prepareStatement(chSql)) {
|
||||
chPs.setString(1, bch);
|
||||
chPs.setInt(2, ChannelsReadSupport.MSG_TYPE_TECH);
|
||||
chPs.setInt(3, 1);
|
||||
try (ResultSet chRs = chPs.executeQuery()) {
|
||||
while (chRs.next()) {
|
||||
out.add(new ChannelKey(canonicalLogin, bch, chRs.getInt("block_number"), chRs.getBytes("block_hash")));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private List<ChannelKey> loadFollowedChannels(Connection c, String canonicalLogin, boolean onlyUserRoots) throws Exception {
|
||||
List<ChannelKey> out = new ArrayList<>();
|
||||
String sql = """
|
||||
SELECT cs.to_login, cs.to_bch_name, COALESCE(cs.to_block_number,0) AS root_number, cs.to_block_hash
|
||||
FROM connections_state cs
|
||||
WHERE cs.login=? AND cs.rel_type=?
|
||||
ORDER BY cs.to_login, cs.to_bch_name, root_number
|
||||
""";
|
||||
try (PreparedStatement ps = c.prepareStatement(sql)) {
|
||||
ps.setString(1, canonicalLogin);
|
||||
ps.setInt(2, MsgSubType.CONNECTION_FOLLOW);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
int rootNumber = rs.getInt("root_number");
|
||||
if (onlyUserRoots && rootNumber != 0) continue;
|
||||
if (!onlyUserRoots && rootNumber == 0) continue;
|
||||
out.add(new ChannelKey(
|
||||
rs.getString("to_login"),
|
||||
rs.getString("to_bch_name"),
|
||||
rootNumber,
|
||||
rs.getBytes("to_block_hash")
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private static final class ChannelKey {
|
||||
final String ownerLogin;
|
||||
final String ownerBch;
|
||||
final int rootNumber;
|
||||
final byte[] rootHash;
|
||||
|
||||
private ChannelKey(String ownerLogin, String ownerBch, int rootNumber, byte[] rootHash) {
|
||||
this.ownerLogin = ownerLogin;
|
||||
this.ownerBch = ownerBch;
|
||||
this.rootNumber = rootNumber;
|
||||
this.rootHash = rootHash;
|
||||
}
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package server.logic.ws_protocol.JSON.handlers.channels.entyties;
|
||||
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
||||
|
||||
public class Net_GetChannelMessages_Request extends Net_Request {
|
||||
private ChannelSelector channel;
|
||||
private Integer limit;
|
||||
private String sort;
|
||||
|
||||
public ChannelSelector getChannel() { return channel; }
|
||||
public void setChannel(ChannelSelector channel) { this.channel = channel; }
|
||||
|
||||
public Integer getLimit() { return limit; }
|
||||
public void setLimit(Integer limit) { this.limit = limit; }
|
||||
|
||||
public String getSort() { return sort; }
|
||||
public void setSort(String sort) { this.sort = sort; }
|
||||
|
||||
public static class ChannelSelector {
|
||||
private String ownerBlockchainName;
|
||||
private Integer channelRootBlockNumber;
|
||||
private String channelRootBlockHash;
|
||||
|
||||
public String getOwnerBlockchainName() { return ownerBlockchainName; }
|
||||
public void setOwnerBlockchainName(String ownerBlockchainName) { this.ownerBlockchainName = ownerBlockchainName; }
|
||||
|
||||
public Integer getChannelRootBlockNumber() { return channelRootBlockNumber; }
|
||||
public void setChannelRootBlockNumber(Integer channelRootBlockNumber) { this.channelRootBlockNumber = channelRootBlockNumber; }
|
||||
|
||||
public String getChannelRootBlockHash() { return channelRootBlockHash; }
|
||||
public void setChannelRootBlockHash(String channelRootBlockHash) { this.channelRootBlockHash = channelRootBlockHash; }
|
||||
}
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
package server.logic.ws_protocol.JSON.handlers.channels.entyties;
|
||||
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Response;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Net_GetChannelMessages_Response extends Net_Response {
|
||||
private Channel channel;
|
||||
private List<MessageItem> messages = new ArrayList<>();
|
||||
|
||||
public Channel getChannel() { return channel; }
|
||||
public void setChannel(Channel channel) { this.channel = channel; }
|
||||
|
||||
public List<MessageItem> getMessages() { return messages; }
|
||||
public void setMessages(List<MessageItem> messages) { this.messages = messages; }
|
||||
|
||||
public static class Channel {
|
||||
private String ownerLogin;
|
||||
private String ownerBlockchainName;
|
||||
private String channelName;
|
||||
private BlockRef channelRoot;
|
||||
|
||||
public String getOwnerLogin() { return ownerLogin; }
|
||||
public void setOwnerLogin(String ownerLogin) { this.ownerLogin = ownerLogin; }
|
||||
|
||||
public String getOwnerBlockchainName() { return ownerBlockchainName; }
|
||||
public void setOwnerBlockchainName(String ownerBlockchainName) { this.ownerBlockchainName = ownerBlockchainName; }
|
||||
|
||||
public String getChannelName() { return channelName; }
|
||||
public void setChannelName(String channelName) { this.channelName = channelName; }
|
||||
|
||||
public BlockRef getChannelRoot() { return channelRoot; }
|
||||
public void setChannelRoot(BlockRef channelRoot) { this.channelRoot = channelRoot; }
|
||||
}
|
||||
|
||||
public static class MessageItem {
|
||||
private BlockRef messageRef;
|
||||
private String authorLogin;
|
||||
private String authorBlockchainName;
|
||||
private long createdAtMs;
|
||||
private String text;
|
||||
private int likesCount;
|
||||
private int repliesCount;
|
||||
private int versionsTotal;
|
||||
private List<VersionItem> versions = new ArrayList<>();
|
||||
|
||||
public BlockRef getMessageRef() { return messageRef; }
|
||||
public void setMessageRef(BlockRef messageRef) { this.messageRef = messageRef; }
|
||||
|
||||
public String getAuthorLogin() { return authorLogin; }
|
||||
public void setAuthorLogin(String authorLogin) { this.authorLogin = authorLogin; }
|
||||
|
||||
public String getAuthorBlockchainName() { return authorBlockchainName; }
|
||||
public void setAuthorBlockchainName(String authorBlockchainName) { this.authorBlockchainName = authorBlockchainName; }
|
||||
|
||||
public long getCreatedAtMs() { return createdAtMs; }
|
||||
public void setCreatedAtMs(long createdAtMs) { this.createdAtMs = createdAtMs; }
|
||||
|
||||
public String getText() { return text; }
|
||||
public void setText(String text) { this.text = text; }
|
||||
|
||||
public int getLikesCount() { return likesCount; }
|
||||
public void setLikesCount(int likesCount) { this.likesCount = likesCount; }
|
||||
|
||||
public int getRepliesCount() { return repliesCount; }
|
||||
public void setRepliesCount(int repliesCount) { this.repliesCount = repliesCount; }
|
||||
|
||||
public int getVersionsTotal() { return versionsTotal; }
|
||||
public void setVersionsTotal(int versionsTotal) { this.versionsTotal = versionsTotal; }
|
||||
|
||||
public List<VersionItem> getVersions() { return versions; }
|
||||
public void setVersions(List<VersionItem> versions) { this.versions = versions; }
|
||||
}
|
||||
|
||||
public static class VersionItem {
|
||||
private int versionIndex;
|
||||
private int blockNumber;
|
||||
private String blockHash;
|
||||
private String text;
|
||||
private long createdAtMs;
|
||||
|
||||
public int getVersionIndex() { return versionIndex; }
|
||||
public void setVersionIndex(int versionIndex) { this.versionIndex = versionIndex; }
|
||||
|
||||
public int getBlockNumber() { return blockNumber; }
|
||||
public void setBlockNumber(int blockNumber) { this.blockNumber = blockNumber; }
|
||||
|
||||
public String getBlockHash() { return blockHash; }
|
||||
public void setBlockHash(String blockHash) { this.blockHash = blockHash; }
|
||||
|
||||
public String getText() { return text; }
|
||||
public void setText(String text) { this.text = text; }
|
||||
|
||||
public long getCreatedAtMs() { return createdAtMs; }
|
||||
public void setCreatedAtMs(long createdAtMs) { this.createdAtMs = createdAtMs; }
|
||||
}
|
||||
|
||||
public static class BlockRef {
|
||||
private int blockNumber;
|
||||
private String blockHash;
|
||||
|
||||
public int getBlockNumber() { return blockNumber; }
|
||||
public void setBlockNumber(int blockNumber) { this.blockNumber = blockNumber; }
|
||||
|
||||
public String getBlockHash() { return blockHash; }
|
||||
public void setBlockHash(String blockHash) { this.blockHash = blockHash; }
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package server.logic.ws_protocol.JSON.handlers.channels.entyties;
|
||||
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
||||
|
||||
public class Net_GetMessageThread_Request extends Net_Request {
|
||||
private MessageSelector message;
|
||||
private Integer depthUp;
|
||||
private Integer depthDown;
|
||||
private Integer limitChildrenPerNode;
|
||||
|
||||
public MessageSelector getMessage() { return message; }
|
||||
public void setMessage(MessageSelector message) { this.message = message; }
|
||||
|
||||
public Integer getDepthUp() { return depthUp; }
|
||||
public void setDepthUp(Integer depthUp) { this.depthUp = depthUp; }
|
||||
|
||||
public Integer getDepthDown() { return depthDown; }
|
||||
public void setDepthDown(Integer depthDown) { this.depthDown = depthDown; }
|
||||
|
||||
public Integer getLimitChildrenPerNode() { return limitChildrenPerNode; }
|
||||
public void setLimitChildrenPerNode(Integer limitChildrenPerNode) { this.limitChildrenPerNode = limitChildrenPerNode; }
|
||||
|
||||
public static class MessageSelector {
|
||||
private String blockchainName;
|
||||
private Integer blockNumber;
|
||||
private String blockHash;
|
||||
|
||||
public String getBlockchainName() { return blockchainName; }
|
||||
public void setBlockchainName(String blockchainName) { this.blockchainName = blockchainName; }
|
||||
|
||||
public Integer getBlockNumber() { return blockNumber; }
|
||||
public void setBlockNumber(Integer blockNumber) { this.blockNumber = blockNumber; }
|
||||
|
||||
public String getBlockHash() { return blockHash; }
|
||||
public void setBlockHash(String blockHash) { this.blockHash = blockHash; }
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package server.logic.ws_protocol.JSON.handlers.channels.entyties;
|
||||
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Response;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Net_GetMessageThread_Response extends Net_Response {
|
||||
private List<MessageNode> ancestors = new ArrayList<>();
|
||||
private MessageNode focus;
|
||||
private List<MessageNodeTree> descendants = new ArrayList<>();
|
||||
|
||||
public List<MessageNode> getAncestors() { return ancestors; }
|
||||
public void setAncestors(List<MessageNode> ancestors) { this.ancestors = ancestors; }
|
||||
|
||||
public MessageNode getFocus() { return focus; }
|
||||
public void setFocus(MessageNode focus) { this.focus = focus; }
|
||||
|
||||
public List<MessageNodeTree> getDescendants() { return descendants; }
|
||||
public void setDescendants(List<MessageNodeTree> descendants) { this.descendants = descendants; }
|
||||
|
||||
public static class MessageNode extends Net_GetChannelMessages_Response.MessageItem {
|
||||
private ChannelInfo channelInfo;
|
||||
|
||||
public ChannelInfo getChannelInfo() { return channelInfo; }
|
||||
public void setChannelInfo(ChannelInfo channelInfo) { this.channelInfo = channelInfo; }
|
||||
}
|
||||
|
||||
public static class ChannelInfo {
|
||||
private String ownerBlockchainName;
|
||||
private Net_GetChannelMessages_Response.BlockRef channelRoot;
|
||||
|
||||
public String getOwnerBlockchainName() { return ownerBlockchainName; }
|
||||
public void setOwnerBlockchainName(String ownerBlockchainName) { this.ownerBlockchainName = ownerBlockchainName; }
|
||||
|
||||
public Net_GetChannelMessages_Response.BlockRef getChannelRoot() { return channelRoot; }
|
||||
public void setChannelRoot(Net_GetChannelMessages_Response.BlockRef channelRoot) { this.channelRoot = channelRoot; }
|
||||
}
|
||||
|
||||
public static class MessageNodeTree {
|
||||
private MessageNode node;
|
||||
private List<MessageNodeTree> children = new ArrayList<>();
|
||||
|
||||
public MessageNode getNode() { return node; }
|
||||
public void setNode(MessageNode node) { this.node = node; }
|
||||
|
||||
public List<MessageNodeTree> getChildren() { return children; }
|
||||
public void setChildren(List<MessageNodeTree> children) { this.children = children; }
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package server.logic.ws_protocol.JSON.handlers.channels.entyties;
|
||||
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
||||
|
||||
public class Net_ListSubscriptionsFeed_Request extends Net_Request {
|
||||
private String login;
|
||||
private Integer limit;
|
||||
|
||||
public String getLogin() { return login; }
|
||||
public void setLogin(String login) { this.login = login; }
|
||||
|
||||
public Integer getLimit() { return limit; }
|
||||
public void setLimit(Integer limit) { this.limit = limit; }
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
package server.logic.ws_protocol.JSON.handlers.channels.entyties;
|
||||
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Response;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Net_ListSubscriptionsFeed_Response extends Net_Response {
|
||||
private String login;
|
||||
private List<ChannelSummary> ownedChannels = new ArrayList<>();
|
||||
private List<ChannelSummary> followedUsersChannels = new ArrayList<>();
|
||||
private List<ChannelSummary> followedChannels = new ArrayList<>();
|
||||
|
||||
public String getLogin() { return login; }
|
||||
public void setLogin(String login) { this.login = login; }
|
||||
|
||||
public List<ChannelSummary> getOwnedChannels() { return ownedChannels; }
|
||||
public void setOwnedChannels(List<ChannelSummary> ownedChannels) { this.ownedChannels = ownedChannels; }
|
||||
|
||||
public List<ChannelSummary> getFollowedUsersChannels() { return followedUsersChannels; }
|
||||
public void setFollowedUsersChannels(List<ChannelSummary> followedUsersChannels) { this.followedUsersChannels = followedUsersChannels; }
|
||||
|
||||
public List<ChannelSummary> getFollowedChannels() { return followedChannels; }
|
||||
public void setFollowedChannels(List<ChannelSummary> followedChannels) { this.followedChannels = followedChannels; }
|
||||
|
||||
public static class ChannelSummary {
|
||||
private ChannelRef channel;
|
||||
private int messagesCount;
|
||||
private LastMessage lastMessage;
|
||||
|
||||
public ChannelRef getChannel() { return channel; }
|
||||
public void setChannel(ChannelRef channel) { this.channel = channel; }
|
||||
|
||||
public int getMessagesCount() { return messagesCount; }
|
||||
public void setMessagesCount(int messagesCount) { this.messagesCount = messagesCount; }
|
||||
|
||||
public LastMessage getLastMessage() { return lastMessage; }
|
||||
public void setLastMessage(LastMessage lastMessage) { this.lastMessage = lastMessage; }
|
||||
}
|
||||
|
||||
public static class ChannelRef {
|
||||
private String ownerLogin;
|
||||
private String ownerBlockchainName;
|
||||
private String channelName;
|
||||
private boolean personal;
|
||||
private BlockRef channelRoot;
|
||||
|
||||
public String getOwnerLogin() { return ownerLogin; }
|
||||
public void setOwnerLogin(String ownerLogin) { this.ownerLogin = ownerLogin; }
|
||||
|
||||
public String getOwnerBlockchainName() { return ownerBlockchainName; }
|
||||
public void setOwnerBlockchainName(String ownerBlockchainName) { this.ownerBlockchainName = ownerBlockchainName; }
|
||||
|
||||
public String getChannelName() { return channelName; }
|
||||
public void setChannelName(String channelName) { this.channelName = channelName; }
|
||||
|
||||
public boolean isPersonal() { return personal; }
|
||||
public void setPersonal(boolean personal) { this.personal = personal; }
|
||||
|
||||
public BlockRef getChannelRoot() { return channelRoot; }
|
||||
public void setChannelRoot(BlockRef channelRoot) { this.channelRoot = channelRoot; }
|
||||
}
|
||||
|
||||
public static class LastMessage {
|
||||
private BlockRef messageRef;
|
||||
private String text;
|
||||
private long createdAtMs;
|
||||
private String authorLogin;
|
||||
private String authorBlockchainName;
|
||||
|
||||
public BlockRef getMessageRef() { return messageRef; }
|
||||
public void setMessageRef(BlockRef messageRef) { this.messageRef = messageRef; }
|
||||
|
||||
public String getText() { return text; }
|
||||
public void setText(String text) { this.text = text; }
|
||||
|
||||
public long getCreatedAtMs() { return createdAtMs; }
|
||||
public void setCreatedAtMs(long createdAtMs) { this.createdAtMs = createdAtMs; }
|
||||
|
||||
public String getAuthorLogin() { return authorLogin; }
|
||||
public void setAuthorLogin(String authorLogin) { this.authorLogin = authorLogin; }
|
||||
|
||||
public String getAuthorBlockchainName() { return authorBlockchainName; }
|
||||
public void setAuthorBlockchainName(String authorBlockchainName) { this.authorBlockchainName = authorBlockchainName; }
|
||||
}
|
||||
|
||||
public static class BlockRef {
|
||||
private int blockNumber;
|
||||
private String blockHash;
|
||||
|
||||
public int getBlockNumber() { return blockNumber; }
|
||||
public void setBlockNumber(int blockNumber) { this.blockNumber = blockNumber; }
|
||||
|
||||
public String getBlockHash() { return blockHash; }
|
||||
public void setBlockHash(String blockHash) { this.blockHash = blockHash; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user