diff --git a/src/.idea/codeStyles/Project.xml b/src/.idea/codeStyles/Project.xml
index 213c5ea87..550d10440 100644
--- a/src/.idea/codeStyles/Project.xml
+++ b/src/.idea/codeStyles/Project.xml
@@ -23,7 +23,7 @@
-
+
diff --git a/src/httprpc.h b/src/httprpc.h
index d7414d594..49a6c9058 100644
--- a/src/httprpc.h
+++ b/src/httprpc.h
@@ -30,6 +30,7 @@ void StopHTTPRPC();
* Precondition; HTTP and RPC has been started.
*/
void StartREST(const util::Ref& context);
+void StartSTATIC(const util::Ref& context);
/** Interrupt RPC REST subsystem.
*/
void InterruptREST();
@@ -37,5 +38,6 @@ void InterruptREST();
* Precondition; HTTP and RPC has been stopped.
*/
void StopREST();
+void StopSTATIC();
#endif
diff --git a/src/httpserver.cpp b/src/httpserver.cpp
index 88d2dcb18..40fc14bd0 100644
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -392,15 +392,17 @@ bool InitHTTPServer(const util::Ref& context)
#endif
// Additional pocketnet seocket
- if (gArgs.GetBoolArg("-api", true))
+ if (gArgs.GetBoolArg("-api", DEFAULT_API_ENABLE))
{
g_webSocket = new HTTPWebSocket(eventBase, timeout, workQueuePublicDepth, workQueuePostDepth, true);
RegisterPocketnetWebRPCCommands(g_webSocket->m_table_rpc, g_webSocket->m_table_post_rpc);
+ }
- // Additional pocketnet static files socket
- g_staticSocket = new HTTPSocket(eventBase, timeout, workQueueStaticDepth, true);
+ if (gArgs.GetBoolArg("-rest", DEFAULT_REST_ENABLE))
g_restSocket = new HTTPSocket(eventBase, timeout, workQueueRestDepth, true);
- }
+
+ if (gArgs.GetBoolArg("-static", DEFAULT_STATIC_ENABLE))
+ g_staticSocket = new HTTPSocket(eventBase, timeout, workQueueStaticDepth, true);
if (!HTTPBindAddresses())
{
diff --git a/src/httpserver.h b/src/httpserver.h
index 445d75ea4..d65efd358 100644
--- a/src/httpserver.h
+++ b/src/httpserver.h
@@ -33,6 +33,10 @@ static const int DEFAULT_HTTP_STATIC_WORKQUEUE = 16;
static const int DEFAULT_HTTP_REST_WORKQUEUE = 16;
static const int DEFAULT_HTTP_SERVER_TIMEOUT = 30;
+static const bool DEFAULT_API_ENABLE = true;
+static const bool DEFAULT_REST_ENABLE = false;
+static const bool DEFAULT_STATIC_ENABLE = false;
+
struct evhttp_request;
class CService;
diff --git a/src/init.cpp b/src/init.cpp
index d31e025dd..c2a982459 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -100,8 +100,6 @@
static bool fFeeEstimatesInitialized = false;
static const bool DEFAULT_PROXYRANDOMIZE = true;
-static const bool DEFAULT_API_ENABLE = true;
-static const bool DEFAULT_REST_ENABLE = false;
static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
Statistic::RequestStatEngine gStatEngineInstance;
@@ -229,6 +227,7 @@ void Shutdown(NodeContext& node)
StopHTTPRPC();
StopREST();
+ StopSTATIC();
StopRPC();
StopHTTPServer();
@@ -628,6 +627,11 @@ void SetupServerArgs(NodeContext& node)
argsman.AddArg("-api", strprintf("Enable Public RPC api server (default: %u)", DEFAULT_API_ENABLE), ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
argsman.AddArg("-rest", strprintf("Accept public REST requests (default: %u)", DEFAULT_REST_ENABLE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::RPC);
+
+ argsman.AddArg("-static", strprintf("Accept public requests to static resources (default: %u)", DEFAULT_STATIC_ENABLE), ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
+ argsman.AddArg("-staticpath", "Path to static resources (default: GetDataDir()/wwwroot", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
+
+
argsman.AddArg("-rpcallowip=", "Allow JSON-RPC connections from specified source. Valid for are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
argsman.AddArg("-rpcauth=", "Username and HMAC-SHA-256 hashed password for JSON-RPC connections. The field comes in the format: :$. A canonical python script is included in share/rpcauth. The client then connects normally using the rpcuser=/rpcpassword= pair of arguments. This option can be specified multiple times", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::RPC);
argsman.AddArg("-rpcbind=[:port]", "Bind to given address to listen for JSON-RPC connections. Do not expose the RPC server to untrusted networks such as the public internet! This option is ignored unless -rpcallowip is also passed. Port is optional and overrides -rpcport. Use [host]:port notation for IPv6. This option can be specified multiple times (default: 127.0.0.1 and ::1 i.e., localhost)", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY | ArgsManager::SENSITIVE, OptionsCategory::RPC);
@@ -661,6 +665,7 @@ void SetupServerArgs(NodeContext& node)
argsman.AddArg("-sqltimeout", strprintf("Timeout for ReadOnly sql querys (default: %ds)", 10), ArgsManager::ALLOW_ANY, OptionsCategory::SQLITE);
argsman.AddArg("-sqlsharedcache", strprintf("Experimental: enable shared cache for sqlite connections (default: disabled)"), ArgsManager::ALLOW_ANY, OptionsCategory::SQLITE);
argsman.AddArg("-sqlcachesize", strprintf("Experimental: Cache size for SQLite connection in megabytes (default: %d mb)", 5), ArgsManager::ALLOW_ANY, OptionsCategory::SQLITE);
+ argsman.AddArg("-withoutweb", strprintf("Disable WEB part of database (default: %u)", false), ArgsManager::ALLOW_ANY, OptionsCategory::SQLITE);
#if HAVE_DECL_DAEMON
@@ -866,7 +871,7 @@ static void ThreadImport(ChainstateManager& chainman, const util::Ref& context,
}
// .. only web DB
- if (fReindex == 5 && args.GetBoolArg("-api", true))
+ if (fReindex == 5 && args.GetBoolArg("-api", DEFAULT_API_ENABLE))
{
LogPrintf("Building a Web database: 0%%\n");
@@ -971,14 +976,25 @@ static bool AppInitServers(const util::Ref& context, NodeContext& node)
const ArgsManager& args = *Assert(node.args);
RPCServer::OnStarted(&OnRPCStarted);
RPCServer::OnStopped(&OnRPCStopped);
+
if (!InitHTTPServer(context))
return false;
+
StartRPC();
+
node.rpc_interruption_point = RpcInterruptionPoint;
+
if (!StartHTTPRPC(context))
return false;
- if (args.GetBoolArg("-rest", DEFAULT_REST_ENABLE)) StartREST(context);
+
+ if (gArgs.GetBoolArg("-rest", DEFAULT_REST_ENABLE))
+ StartREST(context);
+
+ if (gArgs.GetBoolArg("-static", DEFAULT_STATIC_ENABLE))
+ StartSTATIC(context);
+
StartHTTPServer();
+
return true;
}
@@ -1626,7 +1642,8 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
PocketWeb::PocketFrontendInst.Init();
- if (args.GetBoolArg("-api", true))
+ // Always start WEB DB building thread
+ if (!args.GetBoolArg("-withoutweb", false))
PocketServices::WebPostProcessorInst.Start(threadGroup);
// ********************************************************* Step 4b: Additional settings
@@ -2297,7 +2314,8 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
// ********************************************************* Step 13: finished
// Start WebSocket server
- if (args.GetBoolArg("-api", true)) InitWS();
+ if (args.GetBoolArg("-api", DEFAULT_API_ENABLE))
+ InitWS();
gStatEngineInstance.Run(threadGroup, context);
diff --git a/src/net.h b/src/net.h
index 60cabe87e..f020d1128 100644
--- a/src/net.h
+++ b/src/net.h
@@ -54,8 +54,8 @@ static const int TIMEOUT_INTERVAL = 20 * 60;
static const int FEELER_INTERVAL = 120;
/** The maximum number of addresses from our addrman to return in response to a getaddr message. */
static constexpr size_t MAX_ADDR_TO_SEND = 1000;
-/** Maximum length of incoming protocol messages (no message over 4 MB is currently acceptable). */
-static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 4 * 1000 * 1000;
+/** Maximum length of incoming protocol messages (no message over 16 MB is currently acceptable). */
+static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 16000000;
/** Maximum length of the user agent string in `version` message */
static const unsigned int MAX_SUBVERSION_LENGTH = 256;
/** Maximum number of automatic outgoing nodes over which we'll relay everything (blocks, tx, addrs, etc) */
diff --git a/src/pocketdb/consensus/Reputation.h b/src/pocketdb/consensus/Reputation.h
index 0ede93c6e..31e6bb3df 100644
--- a/src/pocketdb/consensus/Reputation.h
+++ b/src/pocketdb/consensus/Reputation.h
@@ -282,8 +282,8 @@ namespace PocketConsensus
{ 1180000, 0, [](int height) { return make_shared(height); }},
{ 1324655, 65000, [](int height) { return make_shared(height); }},
{ 1324655, 75000, [](int height) { return make_shared(height); }},
- { 1680000, 761000, [](int height) { return make_shared(height); }},
- { 1680000, 772000, [](int height) { return make_shared(height); }},
+ { 1700000, 761000, [](int height) { return make_shared(height); }},
+ { 1700000, 772000, [](int height) { return make_shared(height); }},
};
public:
shared_ptr Instance(int height)
diff --git a/src/pocketdb/consensus/moderation/Flag.hpp b/src/pocketdb/consensus/moderation/Flag.hpp
index 43bbb12be..a36a1f5c0 100644
--- a/src/pocketdb/consensus/moderation/Flag.hpp
+++ b/src/pocketdb/consensus/moderation/Flag.hpp
@@ -137,7 +137,7 @@ namespace PocketConsensus
private:
const vector> m_rules = {
{ 0, -1, [](int height) { return make_shared(height); }},
- { 1680000, 761000, [](int height) { return make_shared(height); }},
+ { 1700000, 761000, [](int height) { return make_shared(height); }},
};
public:
shared_ptr Instance(int height)
diff --git a/src/pocketdb/repositories/web/SearchRepository.cpp b/src/pocketdb/repositories/web/SearchRepository.cpp
index 4bf789f07..c447ce988 100644
--- a/src/pocketdb/repositories/web/SearchRepository.cpp
+++ b/src/pocketdb/repositories/web/SearchRepository.cpp
@@ -231,152 +231,59 @@ namespace PocketDb
return result;
}
- UniValue SearchRepository::GetRecomendedAccountsBySubscriptions(const string& address, int cntOut)
+ //TODO (o1q): remove it
+ vector SearchRepository::GetRecommendedAccountByAddressSubscriptionsOld(const string& address, string& addressExclude, const vector& contentTypes, const string& lang, int cntOut, int nHeight, int depth, int cntSubscriptions)
{
auto func = __func__;
- UniValue result(UniValue::VARR);
+ vector ids;
if (address.empty())
- return result;
-
- string sql = R"sql(
- select
- recommendation.address,
- p.String2 as name,
- p.String3 as avatar
-
- , ifnull((
- select r.Value
- from Ratings r indexed by Ratings_Type_Id_Last_Height
- where r.Type=0 and r.Id=u.Id and r.Last=1)
- ,0) as Reputation
-
- , (
- select count(*)
- from Transactions subs indexed by Transactions_Type_Last_String2_Height
- where subs.Type in (302,303) and subs.Height is not null and subs.Last = 1 and subs.String2 = u.String1
- ) as SubscribersCount
- from (
- select
- t.String2 address
- from Transactions t indexed by Transactions_Type_Last_String1_String2_Height
- where t.Last = 1
- and t.Type in (302,303)
- and t.Height is not null
- and t.String2 != ?
- and t.String1 in (select s.String1
- from Transactions s indexed by Transactions_Type_Last_String2_Height
- where s.Type in (302,303)
- and s.Last = 1
- and s.Height is not null
- and s.String2 = ?)
- group by t.String2
- order by count(*) desc
- limit ?
- )recommendation
- cross join Transactions u indexed by Transactions_Type_Last_String1_Height_Id on u.String1 = recommendation.address
- and u.Type in (100,101,102)
- and u.Last=1
- and u.Height is not null
- cross join Payload p on p.TxHash = u.Hash
-
- )sql";
-
- TryTransactionStep(__func__, [&]()
- {
- auto stmt = SetupSqlStatement(sql);
-
- int i = 1;
- TryBindStatementText(stmt, i++, address);
- TryBindStatementText(stmt, i++, address);
- TryBindStatementInt(stmt, i++, cntOut);
-
- while (sqlite3_step(*stmt) == SQLITE_ROW)
- {
- UniValue record(UniValue::VOBJ);
- if (auto[ok, value] = TryGetColumnString(*stmt, 0); ok) record.pushKV("address", value);
- if (auto[ok, value] = TryGetColumnString(*stmt, 1); ok) record.pushKV("name", value);
- if (auto[ok, value] = TryGetColumnString(*stmt, 2); ok) record.pushKV("avatar", value);
- if (auto[ok, value] = TryGetColumnInt(*stmt, 3); ok) record.pushKV("reputation", value / 10.0);
- if (auto[ok, value] = TryGetColumnInt(*stmt, 4); ok) record.pushKV("subscribers_count", value);
- result.push_back(record);
- }
-
- FinalizeSqlStatement(*stmt);
- });
+ return ids;
- return result;
- }
+ string contentTypesFilter = join(vector(contentTypes.size(), "?"), ",");
- UniValue SearchRepository::GetRecomendedAccountsByScoresOnSimilarAccounts(const string& address, const vector& contentTypes, int nHeight, int depth, int cntOut)
- {
- auto func = __func__;
- UniValue result(UniValue::VARR);
+ string excludeAddressFilter = "?";
+ if (!addressExclude.empty())
+ excludeAddressFilter += ", ?";
- if (address.empty())
- return result;
+ string langFilter = "";
+ if (!lang.empty())
+ langFilter = "cross join Payload lang on lang.TxHash = u.Hash and lang.String1 = ?";
- string contentTypesFilter = join(vector(contentTypes.size(), "?"), ",");
+ int minReputation = 300;
string sql = R"sql(
- select recommendation.address,
- p.String2 as name,
- p.String3 as avatar
-
- , ifnull((
- select r.Value
- from Ratings r indexed by Ratings_Type_Id_Last_Height
- where r.Type=0 and r.Id=u.Id and r.Last=1)
- ,0) as Reputation
-
- , (
- select count(*)
- from Transactions subs indexed by Transactions_Type_Last_String2_Height
- where subs.Type in (302,303) and subs.Height is not null and subs.Last = 1 and subs.String2 = u.String1
- ) as SubscribersCount
- from (
- select
- tOtherContents.String1 as address
- from Transactions tOtherContents
- indexed by Transactions_Type_Last_String1_String2_Height
- where tOtherContents.String2 in (
- select tOtherLikes.String2 as OtherLikedContent
- from Transactions tOtherlikes
- where tOtherLikes.String1 in (
- select tLikes.String1 as Liker
- from Transactions tLikes
- where tLikes.String2 in (
- select tContents.String2 as BloggerContent
- from Transactions tContents
- where tContents.Type in ( )sql" + contentTypesFilter + R"sql( )
- and tContents.Last = 1
- and tContents.String1 = ?
- and tContents.Height >= ?
- )
- and tLikes.Type in (300)
- and tLikes.Last in (1, 0)
- and tLikes.Int1 > 3
- and tLikes.Height >= ?
- )
- and tOtherLikes.Type in (300)
- and tOtherLikes.Last in (1, 0)
- and tOtherLikes.Int1 > 3
- and tOtherLikes.Height >= ?
+ select Contents.String1
+ from Transactions Rates indexed by Transactions_Type_Last_String1_Height_Id
+ cross join Transactions Contents indexed by Transactions_Type_Last_String2_Height
+ on Contents.String2 = Rates.String2
+ and Contents.Last = 1
+ and Contents.Height > 0
+ and Contents.Type in ( )sql" + contentTypesFilter + R"sql( )
+ and Contents.String1 not in ( ? )
+ cross join Transactions u indexed by Transactions_Type_Last_String1_Height_Id
+ on u.String1 = Contents.String1
+ and u.Type in (100)
+ and u.Last = 1
+ and u.Height > 0
+ )sql" + langFilter + R"sql(
+ where Rates.Type in (300)
+ and Rates.Int1 = 5
+ and Rates.Height > ?
+ and Rates.Last in (0, 1)
+ and Rates.String1 in (
+ select subscribes.String2
+ from Transactions subscribes indexed by Transactions_Type_Last_String1_Height_Id
+ where subscribes.Type in (302, 303)
+ and subscribes.Last = 1
+ and subscribes.Height > 0
+ and subscribes.String1 = ?
+ limit ?
)
- and tOtherContents.Type in ( )sql" + contentTypesFilter + R"sql( )
- and tOtherContents.String1 != ?
- and tOtherContents.Last = 1
- and tOtherContents.Height >= ?
- group by tOtherContents.String1
- order by count(*) desc
- limit ?
- )recommendation
- cross join Transactions u indexed by Transactions_Type_Last_String1_Height_Id
- on u.String1 = recommendation.address
- and u.Type in (100,101,102)
- and u.Last=1
- and u.Height is not null
- cross join Payload p on p.TxHash = u.Hash
+ group by Contents.String1
+ having count(*) > 1
+ order by count (*) desc
+ limit ?
)sql";
TryTransactionStep(__func__, [&]()
@@ -386,253 +293,97 @@ namespace PocketDb
int i = 1;
for (const auto& contenttype: contentTypes)
TryBindStatementInt(stmt, i++, contenttype);
- TryBindStatementText(stmt, i++, address);
- TryBindStatementInt(stmt, i++, nHeight - depth);
- TryBindStatementInt(stmt, i++, nHeight - depth);
- TryBindStatementInt(stmt, i++, nHeight - depth);
- for (const auto& contenttype: contentTypes)
- TryBindStatementInt(stmt, i++, contenttype);
- TryBindStatementText(stmt, i++, address);
- TryBindStatementInt(stmt, i++, nHeight - depth);
- TryBindStatementInt(stmt, i++, cntOut);
-
- while (sqlite3_step(*stmt) == SQLITE_ROW)
- {
- UniValue record(UniValue::VOBJ);
- if (auto[ok, value] = TryGetColumnString(*stmt, 0); ok) record.pushKV("address", value);
- if (auto[ok, value] = TryGetColumnString(*stmt, 1); ok) record.pushKV("name", value);
- if (auto[ok, value] = TryGetColumnString(*stmt, 2); ok) record.pushKV("avatar", value);
- if (auto[ok, value] = TryGetColumnInt(*stmt, 3); ok) record.pushKV("reputation", value / 10.0);
- if (auto[ok, value] = TryGetColumnInt(*stmt, 4); ok) record.pushKV("subscribers_count", value);
- result.push_back(record);
- }
- FinalizeSqlStatement(*stmt);
- });
-
- return result;
- }
-
- UniValue SearchRepository::GetRecomendedAccountsByScoresFromAddress(const string& address, const vector& contentTypes, int nHeight, int depth, int cntOut)
- {
- auto func = __func__;
- UniValue result(UniValue::VARR);
+ TryBindStatementText(stmt, i++, address);
+ if (!addressExclude.empty())
+ TryBindStatementText(stmt, i++, addressExclude);
- if (address.empty())
- return result;
+ if (!lang.empty())
+ TryBindStatementText(stmt, i++, lang);
- string contentTypesFilter = join(vector(contentTypes.size(), "?"), ",");
+ TryBindStatementInt(stmt, i++, nHeight-depth);
- string sql = R"sql(
- select recommendation.address,
- p.String2 as name,
- p.String3 as avatar
-
- , ifnull((
- select r.Value
- from Ratings r indexed by Ratings_Type_Id_Last_Height
- where r.Type=0 and r.Id=u.Id and r.Last=1)
- ,0) as Reputation
-
- , (
- select count(*)
- from Transactions subs indexed by Transactions_Type_Last_String2_Height
- where subs.Type in (302,303) and subs.Height is not null and subs.Last = 1 and subs.String2 = u.String1
- ) as SubscribersCount
- from (
- select
- tOtherContents.String1 as address
- from Transactions tOtherContents
- indexed by Transactions_Type_Last_String2_Height
- where tOtherContents.String2 in (
- select tOtherLikes.String2 as OtherLikedContent
- from Transactions tOtherlikes
- where tOtherLikes.String1 in (
- select tLikes.String1 as Liker
- from Transactions tLikes
- where tLikes.String2 in (
- select tAddressLikes.String2 as ContentsLikedByAddress
- from Transactions tAddressLikes
- where tAddressLikes.String1 = ?
- and tAddressLikes.Type in (300)
- and tAddressLikes.Last in (1, 0)
- and tAddressLikes.Int1 > 3
- and tAddressLikes.Height >= ?
- )
- and tLikes.Type in (300)
- and tLikes.Last in (1, 0)
- and tLikes.Int1 > 3
- and tLikes.Height >= ?
- )
- and tOtherLikes.Type in (300)
- and tOtherLikes.Last in (1, 0)
- and tOtherLikes.Int1 > 3
- and tOtherLikes.Height >= ?
- )
- and tOtherContents.Type in ( )sql" + contentTypesFilter + R"sql( )
- and tOtherContents.String1 != ?
- and tOtherContents.Last = 1
- and tOtherContents.Height >= ?
- group by tOtherContents.String1
- order by count(*) desc
- limit ?
- )recommendation
- cross join Transactions u on u.String1 = recommendation.address
- and u.Type in (100,101,102)
- and u.Last=1
- and u.Height is not null
- cross join Payload p on p.TxHash = u.Hash
- )sql";
+ TryBindStatementText(stmt, i++, address);
- TryTransactionStep(__func__, [&]()
- {
- auto stmt = SetupSqlStatement(sql);
+ TryBindStatementInt(stmt, i++, cntSubscriptions);
- int i = 1;
- TryBindStatementText(stmt, i++, address);
- TryBindStatementInt(stmt, i++, nHeight - depth);
- TryBindStatementInt(stmt, i++, nHeight - depth);
- TryBindStatementInt(stmt, i++, nHeight - depth);
- for (const auto& contenttype: contentTypes)
- TryBindStatementInt(stmt, i++, contenttype);
- TryBindStatementText(stmt, i++, address);
- TryBindStatementInt(stmt, i++, nHeight - depth);
TryBindStatementInt(stmt, i++, cntOut);
while (sqlite3_step(*stmt) == SQLITE_ROW)
{
- UniValue record(UniValue::VOBJ);
- if (auto[ok, value] = TryGetColumnString(*stmt, 0); ok) record.pushKV("address", value);
- if (auto[ok, value] = TryGetColumnString(*stmt, 1); ok) record.pushKV("name", value);
- if (auto[ok, value] = TryGetColumnString(*stmt, 2); ok) record.pushKV("avatar", value);
- if (auto[ok, value] = TryGetColumnInt(*stmt, 3); ok) record.pushKV("reputation", value / 10.0);
- if (auto[ok, value] = TryGetColumnInt(*stmt, 4); ok) record.pushKV("subscribers_count", value);
- result.push_back(record);
+ if (auto[ok, value] = TryGetColumnString(*stmt, 0); ok)
+ ids.push_back(value);
}
FinalizeSqlStatement(*stmt);
});
- return result;
+ return ids;
}
- UniValue SearchRepository::GetRecomendedAccountsByTags(const vector& tags, int nHeight, int depth, int cntOut)
+ //TODO (o1q): remove it
+ vector SearchRepository::GetRecommendedContentByAddressSubscriptionsOld(const string& contentAddress, string& address, const vector& contentTypes, const string& lang, int cntOut, int nHeight, int depth, int cntSubscriptions)
{
auto func = __func__;
- UniValue result(UniValue::VARR);
-
- if (tags.empty())
- return result;
-
- string tagsFilter = join(vector(tags.size(), "?"), ",");
-
- string sql = R"sql(
- select
- recommendation.address,
- p.String2 as name,
- p.String3 as avatar
-
- , ifnull((
- select r.Value
- from Ratings r indexed by Ratings_Type_Id_Last_Height
- where r.Type=0 and r.Id=u.Id and r.Last=1)
- ,0) as Reputation
-
- , (
- select count(*)
- from Transactions subs indexed by Transactions_Type_Last_String2_Height
- where subs.Type in (302,303) and subs.Height is not null and subs.Last = 1 and subs.String2 = u.String1
- ) as SubscribersCount
- from (
- select authors.string1 address
- from (
- select c.String1
- from Transactions sc indexed by Transactions_Type_Last_Height_Id
- cross join Transactions c indexed by Transactions_Type_Last_String2_Height
- on c.String2 = sc.String2 and c.Type in (200, 201, 202) and c.Height > 0 and c.Last = 1
- and c.id in (select tm.ContentId
- from web.Tags tag indexed by Tags_Lang_Value_Id
- join web.TagsMap tm indexed by TagsMap_TagId_ContentId
- on tag.Id = tm.TagId
- where tag.Value in ( )sql" + join(vector(tags.size(), "?"), ",") + R"sql( ))
- where sc.Type in (300)
- and sc.Last in (0, 1)
- and sc.Height > ?
- and sc.Int1 = 5
- ) authors
- group by authors.string1
- order by count(*) desc
- limit ?
- )recommendation
- cross join Transactions u indexed by Transactions_Type_Last_String1_Height_Id on u.String1 = recommendation.address
- and u.Type in (100,101,102)
- and u.Last=1
- and u.Height is not null
- cross join Payload p on p.TxHash = u.Hash
-
- )sql";
-
- TryTransactionStep(__func__, [&]()
- {
- auto stmt = SetupSqlStatement(sql);
-
- int i = 1;
- for (const auto& tag: tags)
- TryBindStatementText(stmt, i++, tag);
- TryBindStatementInt(stmt, i++, nHeight - depth);
- TryBindStatementInt(stmt, i++, cntOut);
-
- while (sqlite3_step(*stmt) == SQLITE_ROW)
- {
- UniValue record(UniValue::VOBJ);
- if (auto[ok, value] = TryGetColumnString(*stmt, 0); ok) record.pushKV("address", value);
- if (auto[ok, value] = TryGetColumnString(*stmt, 1); ok) record.pushKV("name", value);
- if (auto[ok, value] = TryGetColumnString(*stmt, 2); ok) record.pushKV("avatar", value);
- if (auto[ok, value] = TryGetColumnInt(*stmt, 3); ok) record.pushKV("reputation", value / 10.0);
- if (auto[ok, value] = TryGetColumnInt(*stmt, 4); ok) record.pushKV("subscribers_count", value);
- result.push_back(record);
- }
+ vector ids;
- FinalizeSqlStatement(*stmt);
- });
+ if (contentAddress.empty())
+ return ids;
- return result;
- }
+ string contentTypesFilter = join(vector(contentTypes.size(), "?"), ",");
- UniValue SearchRepository::GetRecomendedContentsByScoresOnSimilarContents(const string& contentid, const vector& contentTypes, int depth, int cntOut)
- {
- auto func = __func__;
- UniValue result(UniValue::VARR);
+ string excludeAddressFilter = "?";
+ if (!address.empty())
+ excludeAddressFilter += ", ?";
- if (contentid.empty())
- return result;
+ string langFilter = "";
+ if (!lang.empty())
+ langFilter = "cross join Payload lang on lang.TxHash = Contents.Hash and lang.String1 = ?";
- string contentTypesFilter = join(vector(contentTypes.size(), "?"), ",");
+ int minReputation = 300;
string sql = R"sql(
- select OtherRaters.String2 OtherScoredContent, count(*) cnt
- from Transactions OtherRaters indexed by Transactions_Type_Last_String1_Height_Id
+ select recomendations.Id
+ from (
+ select Contents.String1,
+ Contents.Id,
+ Rates.String2,
+ count(*) count
+ from Transactions Rates indexed by Transactions_Type_Last_String1_Height_Id
cross join Transactions Contents indexed by Transactions_Type_Last_String2_Height
- on OtherRaters.String2 = Contents.String2 and Contents.Last = 1 and Contents.Type in ( )sql" + contentTypesFilter + R"sql( ) and Contents.Height > 0
- where OtherRaters.Type in (300)
- and OtherRaters.Int1 > 3
- and OtherRaters.Last in (1, 0)
- and OtherRaters.Height >= (select Height
- from Transactions indexed by Transactions_Type_Last_String2_Height
- where Type in ( )sql" + contentTypesFilter + R"sql( )
- and String2 = ?
- and Last = 1) - ?
- and OtherRaters.String1 in (
- select String1 as Rater
- from Transactions Raters indexed by Transactions_Type_Last_String2_Height
- where Raters.Type in (300)
- and Raters.Int1 > 3
- and Raters.String2 = ?
- and Raters.Last in (1, 0)
- )
- and OtherRaters.String2 != ?
- group by OtherRaters.String2
+ on Contents.String2 = Rates.String2
+ and Contents.Last = 1
+ and Contents.Height > 0
+ and Contents.Type in ( )sql" + contentTypesFilter + R"sql( )
+ and Contents.String1 not in ( )sql" + excludeAddressFilter + R"sql( )
+ )sql" + langFilter + R"sql(
+ where Rates.Type in (300)
+ and Rates.Int1 = 5
+ and Rates.Height > ?
+ and Rates.Last in (0, 1)
+ and Rates.String1 in (
+ select subscribers.String2
+ from Transactions subscribers indexed by Transactions_Type_Last_String1_Height_Id
+ cross join Transactions u indexed by Transactions_Type_Last_String1_Height_Id
+ on u.Type in (100)
+ and u.Last = 1 and u.Height > 0
+ and u.String1 = subscribers.String1
+ cross join Ratings r indexed by Ratings_Type_Id_Last_Value
+ on r.Id = u.Id
+ and r.Type = 0
+ and r.Last = 1
+ and r.Value > ?
+ where subscribers.Type in (302, 303)
+ and subscribers.Last = 1
+ and subscribers.Height > 0
+ and subscribers.String1 = ?
+ limit ?
+ )
+ group by Rates.String2
+ having count(*) > 1
order by count(*) desc
+ ) recomendations
+ group by recomendations.String1
limit ?
)sql";
@@ -643,95 +394,36 @@ namespace PocketDb
int i = 1;
for (const auto& contenttype: contentTypes)
TryBindStatementInt(stmt, i++, contenttype);
- for (const auto& contenttype: contentTypes)
- TryBindStatementInt(stmt, i++, contenttype);
- TryBindStatementText(stmt, i++, contentid);
- TryBindStatementInt(stmt, i++, depth);
- TryBindStatementText(stmt, i++, contentid);
- TryBindStatementText(stmt, i++, contentid);
- TryBindStatementInt(stmt, i++, cntOut);
-
- while (sqlite3_step(*stmt) == SQLITE_ROW)
- {
- UniValue record(UniValue::VOBJ);
- if (auto[ok, value] = TryGetColumnString(*stmt, 0); ok) record.pushKV("contentid", value);
- result.push_back(record);
- }
-
- FinalizeSqlStatement(*stmt);
- });
- return result;
- }
-
- UniValue SearchRepository::GetRecomendedContentsByScoresFromAddress(const string& address, const vector& contentTypes, int nHeight, int depth, int cntOut)
- {
- auto func = __func__;
- UniValue result(UniValue::VARR);
+ TryBindStatementText(stmt, i++, contentAddress);
+ if (!address.empty())
+ TryBindStatementText(stmt, i++, address);
- if (address.empty())
- return result;
+ if (!lang.empty())
+ TryBindStatementText(stmt, i++, lang);
- string contentTypesFilter = join(vector(contentTypes.size(), "?"), ",");
+ TryBindStatementInt(stmt, i++, nHeight-depth);
- string sql = R"sql(
- select OtherRaters.String2 as OtherScoredContent, count(*) cnt
- from Transactions OtherRaters indexed by Transactions_Type_Last_String1_Height_Id
- cross join Transactions Contents indexed by Transactions_Type_Last_String2_Height
- on OtherRaters.String2 = Contents.String2 and Contents.Last = 1 and Contents.Type in ( )sql" + contentTypesFilter + R"sql( ) and Contents.Height > 0
- where OtherRaters.String1 in (
- select Scores.String1 as Rater
- from Transactions Scores indexed by Transactions_Type_Last_String2_Height
- where Scores.String2 in (
- select addressScores.String2 as ContentsScoredByAddress
- from Transactions addressScores indexed by Transactions_Type_Last_String1_Height_Id
- where addressScores.String1 = ?
- and addressScores.Type in (300)
- and addressScores.Last in (1, 0)
- and addressScores.Int1 > 3
- and addressScores.Height >= ?
- )
- and Scores.Type in (300)
- and Scores.Last in (1, 0)
- and Scores.Int1 > 3
- and Scores.Height >= ?
- )
- and OtherRaters.Type in (300)
- and OtherRaters.Last in (1, 0)
- and OtherRaters.Int1 > 3
- and OtherRaters.Height >= ?
- group by OtherRaters.String2
- order by count(*) desc
- limit ?
- )sql";
+ TryBindStatementInt(stmt, i++, minReputation);
+ TryBindStatementText(stmt, i++, contentAddress);
- TryTransactionStep(__func__, [&]()
- {
- auto stmt = SetupSqlStatement(sql);
+ TryBindStatementInt(stmt, i++, cntSubscriptions);
- int i = 1;
- for (const auto& contenttype: contentTypes)
- TryBindStatementInt(stmt, i++, contenttype);
- TryBindStatementText(stmt, i++, address);
- TryBindStatementInt(stmt, i++, nHeight - depth);
- TryBindStatementInt(stmt, i++, nHeight - depth);
- TryBindStatementInt(stmt, i++, nHeight - depth);
TryBindStatementInt(stmt, i++, cntOut);
while (sqlite3_step(*stmt) == SQLITE_ROW)
{
- UniValue record(UniValue::VOBJ);
- if (auto[ok, value] = TryGetColumnString(*stmt, 0); ok) record.pushKV("contentid", value);
- result.push_back(record);
+ if (auto[ok, value] = TryGetColumnInt64(*stmt, 0); ok)
+ ids.push_back(value);
}
FinalizeSqlStatement(*stmt);
});
- return result;
+ return ids;
}
- vector SearchRepository::GetRecommendedAccountByAddressSubscriptions(const string& address, string& addressExclude, const vector& contentTypes, const string& lang, int cntOut, int nHeight, int depth, int cntSubscriptions)
+ vector SearchRepository::GetRecommendedAccountByAddressSubscriptions(const string& address, string& addressExclude, const vector& contentTypes, const string& lang, int cntOut, int nHeight, int depth)
{
auto func = __func__;
vector ids;
@@ -749,7 +441,10 @@ namespace PocketDb
if (!lang.empty())
langFilter = "cross join Payload lang on lang.TxHash = u.Hash and lang.String1 = ?";
- int minReputation = 30;
+ int minReputation = 300;
+ int limitSubscriptions = 30;
+ int limitSubscriptionsTotal = 30;
+ int cntRates = 1;
string sql = R"sql(
select Contents.String1
@@ -759,7 +454,7 @@ namespace PocketDb
and Contents.Last = 1
and Contents.Height > 0
and Contents.Type in ( )sql" + contentTypesFilter + R"sql( )
- and Contents.String1 not in ( ? )
+ and Contents.String1 not in ( )sql" + excludeAddressFilter + R"sql( )
cross join Transactions u indexed by Transactions_Type_Last_String1_Height_Id
on u.String1 = Contents.String1
and u.Type in (100)
@@ -770,17 +465,56 @@ namespace PocketDb
and Rates.Int1 = 5
and Rates.Height > ?
and Rates.Last in (0, 1)
- and Rates.String1 in (
- select subscribes.String2
- from Transactions subscribes indexed by Transactions_Type_Last_String1_Height_Id
- where subscribes.Type in (302, 303)
- and subscribes.Last = 1
- and subscribes.Height > 0
- and subscribes.String1 = ?
- limit ?
- )
+ and Rates.String1 in
+ (
+ select address
+ from (
+ select rnk, address
+ from (
+ select 1 as rnk, subscribes.String2 as address
+ from Transactions subscribes indexed by Transactions_String1_Last_Height
+ cross join Transactions u indexed by Transactions_Type_Last_String1_Height_Id
+ on u.Type in (100)
+ and u.Last = 1 and u.Height > 0
+ and u.String1 = subscribes.String2
+ cross join Ratings r indexed by Ratings_Type_Id_Last_Value
+ on r.Id = u.Id
+ and r.Type = 0
+ and r.Last = 1
+ and r.Value > ?
+ where subscribes.Type in (302, 303)
+ and subscribes.Last = 1
+ and subscribes.String1 = ?
+ and subscribes.Height is not null
+ order by subscribes.Height desc
+ limit ?
+ )
+ union
+ select rnk, address
+ from (
+ select 2 as rnk, subscribers.String1 as address
+ from Transactions subscribers indexed by Transactions_Type_Last_String2_Height
+ cross join Transactions u indexed by Transactions_Type_Last_String1_Height_Id
+ on u.Type in (100)
+ and u.Last = 1 and u.Height > 0
+ and u.String1 = subscribers.String1
+ cross join Ratings r indexed by Ratings_Type_Id_Last_Value
+ on r.Id = u.Id
+ and r.Type = 0
+ and r.Last = 1
+ and r.Value > ?
+ where subscribers.Type in (302, 303)
+ and subscribers.Last = 1
+ and subscribers.String2 = ?
+ and subscribers.Height is not null
+ order by random()
+ limit ?
+ ))
+ order by rnk
+ limit ?
+ )
group by Contents.String1
- having count(*) > 1
+ having count(*) > ?
order by count (*) desc
limit ?
)sql";
@@ -802,9 +536,17 @@ namespace PocketDb
TryBindStatementInt(stmt, i++, nHeight-depth);
+ TryBindStatementInt(stmt, i++, minReputation);
TryBindStatementText(stmt, i++, address);
+ TryBindStatementInt(stmt, i++, limitSubscriptions);
- TryBindStatementInt(stmt, i++, cntSubscriptions);
+ TryBindStatementInt(stmt, i++, minReputation);
+ TryBindStatementText(stmt, i++, address);
+ TryBindStatementInt(stmt, i++, limitSubscriptions);
+
+ TryBindStatementInt(stmt, i++, limitSubscriptionsTotal);
+
+ TryBindStatementInt(stmt, i++, cntRates);
TryBindStatementInt(stmt, i++, cntOut);
@@ -820,7 +562,7 @@ namespace PocketDb
return ids;
}
- vector SearchRepository::GetRecommendedContentByAddressSubscriptions(const string& contentAddress, string& address, const vector& contentTypes, const string& lang, int cntOut, int nHeight, int depth, int cntSubscriptions)
+ vector SearchRepository::GetRecommendedContentByAddressSubscriptions(const string& contentAddress, string& address, const vector& contentTypes, const string& lang, int cntOut, int nHeight, int depth)
{
auto func = __func__;
vector ids;
@@ -836,52 +578,87 @@ namespace PocketDb
string langFilter = "";
if (!lang.empty())
- langFilter = "cross join Payload lang on lang.TxHash = Contents.Hash and lang.String1 = ?";
+ langFilter = "cross join Payload lang indexed by Payload_String1_TxHash on lang.TxHash = Contents.Hash and lang.String1 = ?";
- int minReputation = 30;
+ int minReputation = 300;
+ int limitSubscriptions = 50;
+ int limitSubscriptionsTotal = 30;
+ int cntRates = 1;
string sql = R"sql(
select recomendations.Id
from (
- select Contents.String1,
- Contents.Id,
- Rates.String2,
- count(*) count
- from Transactions Rates indexed by Transactions_Type_Last_String1_Height_Id
- cross join Transactions Contents indexed by Transactions_Type_Last_String2_Height
- on Contents.String2 = Rates.String2
- and Contents.Last = 1
- and Contents.Height > 0
- and Contents.Type in ( )sql" + contentTypesFilter + R"sql( )
- and Contents.String1 not in ( )sql" + excludeAddressFilter + R"sql( )
- )sql" + langFilter + R"sql(
- where Rates.Type in (300)
- and Rates.Int1 = 5
- and Rates.Height > ?--0
- and Rates.Last in (0, 1)
- and Rates.String1 in (
- select subscribers.String2
- from Transactions subscribers indexed by Transactions_Type_Last_String1_Height_Id
- cross join Transactions u indexed by Transactions_Type_Last_String1_Height_Id
- on u.Type in (100)
- and u.Last = 1 and u.Height > 0
- and u.String1 = subscribers.String1
- cross join Ratings r indexed by Ratings_Type_Id_Last_Value
- on r.Id = u.Id
- and r.Type = 0
- and r.Last = 1
- and r.Value > ?
- where subscribers.Type in (302, 303)
- and subscribers.Last = 1
- and subscribers.Height > 0
- and subscribers.String1 = ?
- limit ?
- )
- group by Rates.String2
- having count(*) > 1
- order by count(*) desc
- ) recomendations
+ select Contents.String1,
+ Contents.Id,
+ --Rates.String2,
+ count(*) count
+ from Transactions Rates indexed by Transactions_Type_Last_String1_Height_Id
+ cross join Transactions Contents indexed by Transactions_Type_Last_String2_Height
+ on Contents.String2 = Rates.String2
+ and Contents.Last = 1
+ and Contents.Height > 0
+ and Contents.Type in ( )sql" + contentTypesFilter + R"sql( )
+ and Contents.String1 not in ( )sql" + excludeAddressFilter + R"sql( )
+ )sql" + langFilter + R"sql(
+ where Rates.Type in (300)
+ and Rates.Int1 = 5
+ and Rates.Height > ?
+ and Rates.Last in (0, 1)
+ and Rates.String1 in
+ (
+ select address
+ from (
+ select rnk, address
+ from (
+ select 1 as rnk, subscribes.String2 as address
+ from Transactions subscribes indexed by Transactions_String1_Last_Height
+ cross join Transactions u indexed by Transactions_Type_Last_String1_Height_Id
+ on u.Type in (100)
+ and u.Last = 1 and u.Height > 0
+ and u.String1 = subscribes.String2
+ cross join Ratings r indexed by Ratings_Type_Id_Last_Value
+ on r.Id = u.Id
+ and r.Type = 0
+ and r.Last = 1
+ and r.Value > ?
+ where subscribes.Type in (302, 303)
+ and subscribes.Last = 1
+ and subscribes.String1 = ?
+ and subscribes.Height is not null
+ order by subscribes.Height desc
+ limit ?
+ )
+ union
+ select rnk, address
+ from (
+ select 2 as rnk, subscribers.String1 as address
+ from Transactions subscribers indexed by Transactions_Type_Last_String2_Height
+ cross join Transactions u indexed by Transactions_Type_Last_String1_Height_Id
+ on u.Type in (100)
+ and u.Last = 1 and u.Height > 0
+ and u.String1 = subscribers.String1
+ cross join Ratings r indexed by Ratings_Type_Id_Last_Value
+ on r.Id = u.Id
+ and r.Type = 0
+ and r.Last = 1
+ and r.Value > ?
+ where subscribers.Type in (302, 303)
+ and subscribers.Last = 1
+ and subscribers.String2 = ?
+ and subscribers.Height is not null
+ order by random()
+ limit ?
+ ))
+ order by rnk
+ limit ?
+ )
+ --group by Rates.String2
+ group by Contents.Id
+ having count(*) > ?
+ order by count(*) desc
+ ) recomendations
group by recomendations.String1
+ order by recomendations.count desc
limit ?
)sql";
@@ -904,8 +681,15 @@ namespace PocketDb
TryBindStatementInt(stmt, i++, minReputation);
TryBindStatementText(stmt, i++, contentAddress);
+ TryBindStatementInt(stmt, i++, limitSubscriptions);
- TryBindStatementInt(stmt, i++, cntSubscriptions);
+ TryBindStatementInt(stmt, i++, minReputation);
+ TryBindStatementText(stmt, i++, contentAddress);
+ TryBindStatementInt(stmt, i++, limitSubscriptions);
+
+ TryBindStatementInt(stmt, i++, limitSubscriptionsTotal);
+
+ TryBindStatementInt(stmt, i++, cntRates);
TryBindStatementInt(stmt, i++, cntOut);
diff --git a/src/pocketdb/repositories/web/SearchRepository.h b/src/pocketdb/repositories/web/SearchRepository.h
index 2ee3f07f7..18ccf9083 100644
--- a/src/pocketdb/repositories/web/SearchRepository.h
+++ b/src/pocketdb/repositories/web/SearchRepository.h
@@ -34,15 +34,12 @@ namespace PocketDb
vector SearchUsersOld(const SearchRequest& request);
vector SearchUsers(const string& keyword);
- UniValue GetRecomendedAccountsBySubscriptions(const string& address, int cntOut = 10);
- UniValue GetRecomendedAccountsByScoresOnSimilarAccounts(const string& address, const vector& contentTypes, int nHeight, int depth = 1000, int cntOut = 10);
- UniValue GetRecomendedAccountsByScoresFromAddress(const string& address, const vector& contentTypes, int nHeight, int depth = 1000, int cntOut = 10);
- UniValue GetRecomendedAccountsByTags(const vector& tags, int nHeight, int depth = 1000, int cntOut = 10);
- UniValue GetRecomendedContentsByScoresOnSimilarContents(const string& contentid, const vector& contentTypes, int depth = 1000, int cntOut = 10);
- UniValue GetRecomendedContentsByScoresFromAddress(const string& address, const vector& contentTypes, int nHeight, int depth = 1000, int cntOut = 10);
-
- vector GetRecommendedAccountByAddressSubscriptions(const string& address, string& addressExclude, const vector& contentTypes, const string& lang, int cntOut, int nHeight, int depth = 129600 /* about 3 month */, int cntSubscriptions = 100);
- vector GetRecommendedContentByAddressSubscriptions(const string& contentAddress, string& address, const vector& contentTypes, const string& lang, int cntOut, int nHeight, int depth = 129600 /* about 3 month */, int cntSubscriptions = 100);
+ //TODO (o1q): remove it
+ vector GetRecommendedAccountByAddressSubscriptionsOld(const string& address, string& addressExclude, const vector& contentTypes, const string& lang, int cntOut, int nHeight, int depth = 129600 /* about 3 month */, int cntSubscriptions = 100);
+ vector GetRecommendedContentByAddressSubscriptionsOld(const string& contentAddress, string& address, const vector& contentTypes, const string& lang, int cntOut, int nHeight, int depth = 129600 /* about 3 month */, int cntSubscriptions = 100);
+
+ vector GetRecommendedAccountByAddressSubscriptions(const string& address, string& addressExclude, const vector& contentTypes, const string& lang, int cntOut, int nHeight, int depth = 129600 /* about 3 month */);
+ vector GetRecommendedContentByAddressSubscriptions(const string& contentAddress, string& address, const vector& contentTypes, const string& lang, int cntOut, int nHeight, int depth = 129600 /* about 3 month */);
vector GetRandomContentByAddress(const string& contentAddress, const vector& contentTypes, const string& lang, int cntOut);
};
diff --git a/src/pocketdb/repositories/web/WebRpcRepository.cpp b/src/pocketdb/repositories/web/WebRpcRepository.cpp
index a90b2b2f4..0c090ad8c 100644
--- a/src/pocketdb/repositories/web/WebRpcRepository.cpp
+++ b/src/pocketdb/repositories/web/WebRpcRepository.cpp
@@ -2921,19 +2921,19 @@ namespace PocketDb
string langFilter;
if (!lang.empty())
- langFilter += " join Payload p indexed by Payload_String1_TxHash on p.TxHash = t.Hash and p.String1 = ? ";
+ langFilter += " cross join Payload p indexed by Payload_String1_TxHash on p.TxHash = t.Hash and p.String1 = ? ";
string sql = R"sql(
select t.Id
- from Transactions t indexed by Transactions_Last_Id_Height
+ from Transactions t indexed by Transactions_Type_Last_Height_Id
- join Ratings cr indexed by Ratings_Type_Id_Last_Value
+ cross join Ratings cr indexed by Ratings_Type_Id_Last_Value
on cr.Type = 2 and cr.Last = 1 and cr.Id = t.Id and cr.Value > 0
)sql" + langFilter + R"sql(
- join Transactions u indexed by Transactions_Type_Last_String1_Height_Id
+ cross join Transactions u indexed by Transactions_Type_Last_String1_Height_Id
on u.Type in (100) and u.Last = 1 and u.Height > 0 and u.String1 = t.String1
left join Ratings ur indexed by Ratings_Type_Id_Last_Height
@@ -2941,7 +2941,7 @@ namespace PocketDb
where t.Type in )sql" + contentTypesWhere + R"sql(
and t.Last = 1
- and t.String3 is null
+ --and t.String3 is null
and t.Height > ?
and t.Height <= ?
@@ -2979,7 +2979,7 @@ namespace PocketDb
) )sql";
}
- sql += " order by t.Id desc ";
+ sql += " order by cr.Value desc ";
sql += " limit ? ";
// ---------------------------------------------
diff --git a/src/pocketdb/web/PocketContentRpc.cpp b/src/pocketdb/web/PocketContentRpc.cpp
index 7efcae99b..91400c1c2 100644
--- a/src/pocketdb/web/PocketContentRpc.cpp
+++ b/src/pocketdb/web/PocketContentRpc.cpp
@@ -100,17 +100,19 @@ namespace PocketWeb::PocketWebRpc
}
}
- // feed's address
if (request.params.size() > 10)
{
- RPCTypeCheckArgument(request.params[10], UniValue::VSTR);
- address_feed = request.params[10].get_str();
- if (!address_feed.empty())
+ // feed's address
+ if (request.params[10].isStr())
{
- CTxDestination dest = DecodeDestination(address_feed);
+ address_feed = request.params[10].get_str();
+ if (!address_feed.empty())
+ {
+ CTxDestination dest = DecodeDestination(address_feed);
- if (!IsValidDestination(dest))
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Pocketcoin address: ") + address_feed);
+ if (!IsValidDestination(dest))
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Pocketcoin address: ") + address_feed);
+ }
}
}
}
diff --git a/src/pocketdb/web/PocketFrontend.cpp b/src/pocketdb/web/PocketFrontend.cpp
index 81fd9ae5e..861108c3f 100644
--- a/src/pocketdb/web/PocketFrontend.cpp
+++ b/src/pocketdb/web/PocketFrontend.cpp
@@ -5,6 +5,7 @@
// https://www.apache.org/licenses/LICENSE-2.0
#include "pocketdb/web/PocketFrontend.h"
+#include "fs.h"
namespace PocketWeb
{
@@ -74,7 +75,20 @@ namespace PocketWeb
void PocketFrontend::Init()
{
- _rootPath = GetDataDir() / "static_files";
+ string _argPath = gArgs.GetArg("-staticpath", "wwwroot");
+ _rootPath = (_argPath == "wwwroot") ? GetDataDir() / "wwwroot" : _argPath;
+
+ // Create directory structure
+ try
+ {
+ if (!_rootPath.empty())
+ fs::create_directories(_rootPath);
+ }
+ catch (const fs::filesystem_error&)
+ {
+ if (!fs::exists(_rootPath) || !fs::is_directory(_rootPath))
+ throw;
+ }
auto testContent = shared_ptr(new StaticFile{
"/404.html",
@@ -156,12 +170,7 @@ namespace PocketWeb
if (!readOk)
{
if (!stopRecurse)
- {
- if (_path.find("explorer") == 0)
- return GetFile("/explorer/index.html", true);
-
return GetFile("/index.html", true);
- }
return NotFound();
}
diff --git a/src/pocketdb/web/PocketRpc.cpp b/src/pocketdb/web/PocketRpc.cpp
index e185ddda0..308f4d703 100644
--- a/src/pocketdb/web/PocketRpc.cpp
+++ b/src/pocketdb/web/PocketRpc.cpp
@@ -45,15 +45,6 @@ static const CRPCCommand commands[] =
{"search", "searchusers", &SearchUsers, {"keyword", "fieldtypes", "orderbyrank"}},
// Recomendations
- // TODO (o1q): Remove below methods when the client gui switches to new methods
- {"search", "getrecomendedaccountsbysubscriptions", &GetRecomendedAccountsBySubscriptions, {"address", "count"}},
- {"search", "getrecomendedaccountsbyscoresonsimilaraccounts", &GetRecomendedAccountsByScoresOnSimilarAccounts, {"address", "contenttypes", "height", "depth", "count"}},
- {"search", "getrecomendedaccountsbyscoresfromaddress", &GetRecomendedAccountsByScoresFromAddress, {"address", "contenttypes", "height", "depth", "count"}},
- {"search", "getrecomendedaccountsbytags", &GetRecomendedAccountsByTags, {"tags", "count"}},
- {"search", "getrecomendedcontentsbyscoresonsimilarcontents", &GetRecomendedContentsByScoresOnSimilarContents, {"contentid", "contenttypes", "depth", "count"}},
- {"search", "getrecomendedcontentsbyscoresfromaddress", &GetRecomendedContentsByScoresFromAddress, {"address", "contenttypes", "height", "depth", "count"}},
- // TODO (o1q): Remove above methods when the client gui switches to new (below) methods
- {"search", "getrecommendedcontentbycontentid", &GetRecommendedContentByContentId, {"contentid", "address", "contenttypes", "lang", "count"}},
{"search", "getrecommendedcontentbyaddress", &GetRecommendedContentByAddress, {"address", "addressExclude", "contenttypes", "lang", "count"}},
{"search", "getrecommendedaccountbyaddress", &GetRecommendedAccountByAddress, {"address", "addressExclude", "contenttypes", "lang", "count"}},
diff --git a/src/pocketdb/web/SearchRpc.cpp b/src/pocketdb/web/SearchRpc.cpp
index c6dc30110..276f5b241 100644
--- a/src/pocketdb/web/SearchRpc.cpp
+++ b/src/pocketdb/web/SearchRpc.cpp
@@ -322,442 +322,101 @@ namespace PocketWeb::PocketWebRpc
};
}
- #pragma region Recomendations OLD
- // TODO (o1q): Remove below methods when the client gui switches to new methods
- RPCHelpMan GetRecomendedAccountsBySubscriptions()
+ RPCHelpMan GetRecommendedContentByAddress()
{
- return RPCHelpMan{"getrecomendedaccountsbysubscriptions",
- "\nAccounts recommendations by subscriptions.\n",
- {
- {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "Address for recommendations"},
- {"count", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "Number of resulting records. Default 10"},
- },
- {
- // TODO (rpc): provide return description
- },
- RPCExamples{
- // TODO (team): examples
- HelpExampleCli("getrecomendedaccountsbysubscriptions", "") +
- HelpExampleRpc("getrecomendedaccountsbysubscriptions", "")
- },
- [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
+ return RPCHelpMan{"GetRecommendedContentByAddress",
+ "\n\n", // TODO (rpc): provide description
+ {
+ // TODO (rpc): args
+ },
+ {
+ // TODO (rpc): provide return description
+ },
+ RPCExamples{
+ // TODO (team): examples
+ HelpExampleCli("GetRecommendedContentByAddress", "") +
+ HelpExampleRpc("GetRecommendedContentByAddress", "")
+ },
+ [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheckArgument(request.params[0], UniValue::VSTR);
- string address = request.params[0].get_str();
- CTxDestination dest = DecodeDestination(address);
-
- if (!IsValidDestination(dest))
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Pocketcoin address: ") + address);
-
- int cntOut = 10;
- if (request.params.size() > 1 && request.params[1].isNum())
- cntOut = request.params[1].get_int();
+ // if (request.fHelp)
+ // throw runtime_error(
+ // "getrecommendedcontentbyaddress \"address\", \"addressExclude\", \"contenttypes\", \"lang\", count\n"
+ // "\nContents recommendations by content address.\n"
+ // "\nArguments:\n"
+ // "1. \"address\" (string) Address for recommendations\n"
+ // "2. \"addressExclude\" (string, optional) Address for exclude from recommendations\n"
+ // "3. \"contenttypes\" (string or array of strings, optional) type(s) of content posts/videos/articles\n"
+ // "3. \"lang\" (string, optional) Language for recommendations\n"
+ // "4. \"count\" (int, optional) Number of recommendations records and number of other contents from addres. Default 15\n"
+ // );
- return request.DbConnection()->SearchRepoInst->GetRecomendedAccountsBySubscriptions(address, cntOut);
- },
- };
- }
-
- RPCHelpMan GetRecomendedAccountsByScoresOnSimilarAccounts()
- {
- return RPCHelpMan{"getrecomendedaccountsbyscoresonsimilaraccounts",
- "\nAccounts recommendations by likes based on address.\n",
- {
- {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "Address for recommendations" },
- {"contenttypes", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "type(s) of content posts/video",
- {
- {"contenttype", RPCArg::Type::STR, RPCArg::Optional::NO, "" },
- }
- },
- {"height", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "Maximum search height. Default is current chain height" },
- {"depth", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "Depth of statistic. Default 1000 blocks" },
- {"count", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "Number of resulting records. Default 10" },
- },
- {
- // TODO (rpc): provide return description
- },
- RPCExamples{
- // TODO (team): examples
- HelpExampleCli("getrecomendedaccountsbyscoresonsimilaraccounts", "\"address\", \"contenttypes\", height, depth, count") +
- HelpExampleRpc("getrecomendedaccountsbyscoresonsimilaraccounts", "\"address\", \"contenttypes\", height, depth, count")
- },
- [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
- {
RPCTypeCheckArgument(request.params[0], UniValue::VSTR);
- string address = request.params[0].get_str();
- CTxDestination dest = DecodeDestination(address);
-
- if (!IsValidDestination(dest))
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Pocketcoin address: ") + address);
-
- vector contentTypes;
- ParseRequestContentTypes(request.params[1], contentTypes);
-
- int nHeight = ChainActive().Height();
- int depth = 1000;
- int cntOut = 10;
-
- if (request.params.size() > 2 && request.params[2].isNum() && request.params[2].get_int() > 0)
- nHeight = request.params[2].get_int();
-
- if (request.params.size() > 3 && request.params[3].isNum())
- depth = request.params[3].get_int();
-
- if (request.params.size() > 4 && request.params[4].isNum())
- cntOut = request.params[4].get_int();
-
- return request.DbConnection()->SearchRepoInst->GetRecomendedAccountsByScoresOnSimilarAccounts(address, contentTypes, nHeight, depth, cntOut);
- },
- };
- }
+ string address = "";
+ if (request.params.size() > 0 && request.params[0].isStr()) {
+ address = request.params[0].get_str();
+
+ if(!address.empty()) {
+ CTxDestination dest = DecodeDestination(address);
+ if (!IsValidDestination(dest))
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid address: ") + address);
+ }
+ }
- RPCHelpMan GetRecomendedAccountsByScoresFromAddress()
- {
- return RPCHelpMan{"getrecomendedaccountsbyscoresfromaddress",
- "\nAccounts recommendations by likes.\n",
- {
- {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "Address for recommendations" },
- {"contenttypes", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "type(s) of content posts/video",
- {
- {"contenttype", RPCArg::Type::STR, RPCArg::Optional::NO, "" }
- }
- },
- {"height", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "Maximum search height. Default is current chain height" },
- {"depth", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "Depth of statistic. Default 1000 blocks" },
- {"count", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "Number of resulting records. Default 10" },
- },
- {
- // TODO (rpc): provide return description
- },
- RPCExamples{
- // TODO (team): examples
- HelpExampleCli("getrecomendedaccountsbyscoresfromaddress", "\"address\", \"contenttypes\", height, depth, count") +
- HelpExampleRpc("getrecomendedaccountsbyscoresfromaddress", "\"address\", \"contenttypes\", height, depth, count")
- },
- [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
- {
- RPCTypeCheckArgument(request.params[0], UniValue::VSTR);
- string address = request.params[0].get_str();
- CTxDestination dest = DecodeDestination(address);
+ string addressExclude = "";
+ if (request.params.size() > 1 && request.params[1].isStr()) {
+ addressExclude = request.params[1].get_str();
- if (!IsValidDestination(dest))
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Pocketcoin address: ") + address);
+ if(!addressExclude.empty()) {
+ CTxDestination dest = DecodeDestination(addressExclude);
+ if (!IsValidDestination(dest))
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid address: ") + addressExclude);
+ }
+ }
vector contentTypes;
- ParseRequestContentTypes(request.params[1], contentTypes);
+ if(request.params.size()>2)
+ ParseRequestContentTypes(request.params[2], contentTypes);
- int nHeight = ChainActive().Height();
- int depth = 1000;
- int cntOut = 10;
-
- if (request.params.size() > 2 && request.params[2].isNum() && request.params[2].get_int() > 0)
- nHeight = request.params[2].get_int();
-
- if (request.params.size() > 3 && request.params[3].isNum())
- depth = request.params[3].get_int();
+ string lang = "";
+ if (request.params.size() > 3 && request.params[3].isStr())
+ lang = request.params[3].get_str();
+ int cntOut = 15;
if (request.params.size() > 4 && request.params[4].isNum())
cntOut = request.params[4].get_int();
- return request.DbConnection()->SearchRepoInst->GetRecomendedAccountsByScoresFromAddress(address, contentTypes, nHeight, depth, cntOut);
- },
- };
- }
-
- RPCHelpMan GetRecomendedAccountsByTags()
- {
- return RPCHelpMan{"getrecomendedaccountsbytags",
- "\nAccounts recommendations by tags.\n",
- {
- {"tags", RPCArg::Type::ARR, RPCArg::Optional::NO, "Tags for recommendations",
- {
- {"tag", RPCArg::Type::STR, RPCArg::Optional::NO, "" }
- }
- },
- {"count", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "Number of resulting records. Default 10" },
- },
- {
- // TODO (rpc): provide return description
- },
- RPCExamples{
- // TODO (team): examples
- HelpExampleCli("getrecomendedaccountsbytags", "\"tags\", count") +
- HelpExampleRpc("getrecomendedaccountsbytags", "\"tags\", count")
- },
- [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
- {
- vector tags;
- if (request.params.size() > 0)
- ParseRequestTags(request.params[0], tags);
-
- if (tags.empty())
- throw JSONRPCError(RPC_INVALID_PARAMETER, string("There are no tags in the input parameters."));
-
int nHeight = ChainActive().Height();
- int depth = 60 * 24 * 30; // about 1 month
-
- int cntOut = 10;
- if (request.params.size() > 1 && request.params[1].isNum())
- cntOut = request.params[1].get_int();
+ if (request.params.size() > 5 && request.params[5].isNum() && request.params[5].get_int() > 0)
+ nHeight = request.params[5].get_int();
- return request.DbConnection()->SearchRepoInst->GetRecomendedAccountsByTags(tags, nHeight, depth, cntOut);
- },
- };
- }
-
- RPCHelpMan GetRecomendedContentsByScoresOnSimilarContents()
- {
- return RPCHelpMan{"getrecomendedcontentsbyscoresonsimilarcontents",
- "\n\n", // TODO (team): provide description
- {
- {"contentid", RPCArg::Type::STR, RPCArg::Optional::NO, "Content hash for recommendations" },
- {"contenttypes", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "type(s) of content posts/video",
- {
- {"contenttype", RPCArg::Type::STR, RPCArg::Optional::NO, "" }
- }
- },
- {"depth", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "Depth of statistic. Default 1000 blocks" },
- {"count", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "Number of resulting records. Default 10" },
- },
- {
- // TODO (rpc): provide return description
- },
- RPCExamples{
- // TODO (team): examples
- HelpExampleCli("getrecomendedcontentsbyscoresonsimilarcontents", "\"contentid\", \"contenttypes\", depth, count") +
- HelpExampleRpc("getrecomendedcontentsbyscoresonsimilarcontents", "\"contentid\", \"contenttypes\", depth, count")
- },
- [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
- {
- RPCTypeCheckArgument(request.params[0], UniValue::VSTR);
- string contentid = request.params[0].get_str();
-
- vector contentTypes;
- ParseRequestContentTypes(request.params[1], contentTypes);
-
- int depth = 1000;
- int cntOut = 10;
-
- if (request.params.size() > 2 && request.params[2].isNum())
- depth = request.params[2].get_int();
-
- if (request.params.size() > 3 && request.params[3].isNum())
- cntOut = request.params[3].get_int();
-
- return request.DbConnection()->SearchRepoInst->GetRecomendedContentsByScoresOnSimilarContents(contentid, contentTypes, depth, cntOut);
- },
- };
- }
-
- RPCHelpMan GetRecomendedContentsByScoresFromAddress()
- {
- return RPCHelpMan{"getrecomendedcontentsbyscoresfromaddress",
- "\nContents recommendations for address by likes.\n", // TODO (team): provide description
- {
- {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "Address for recommendations" },
- {"contenttypes", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "type(s) of content posts/video",
- {
- {"contenttype", RPCArg::Type::STR, RPCArg::Optional::NO, "" }
- }
- },
- {"height", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "Maximum search height. Default is current chain height" },
- {"depth", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "Depth of statistic. Default 1000 blocks" },
- {"count", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "Number of resulting records. Default 10" },
- },
- {
- // TODO (rpc): provide return description
- },
- RPCExamples{
- // TODO (team): examples
- HelpExampleCli("getrecomendedcontentsbyscoresfromaddress", "\"address\", \"contenttypes\", height, depth, count") +
- HelpExampleRpc("getrecomendedcontentsbyscoresfromaddress", "\"address\", \"contenttypes\", height, depth, count")
- },
- [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
- {
- RPCTypeCheckArgument(request.params[0], UniValue::VSTR);
- string address = request.params[0].get_str();
- CTxDestination dest = DecodeDestination(address);
-
- if (!IsValidDestination(dest))
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Pocketcoin address: ") + address);
-
- vector contentTypes;
- ParseRequestContentTypes(request.params[1], contentTypes);
-
- int nHeight = ChainActive().Height();
- int depth = 1000;
- int cntOut = 10;
-
- if (request.params.size() > 2 && request.params[2].isNum() && request.params[2].get_int() > 0)
- nHeight = request.params[2].get_int();
+ int depth = (60 * 24 * 30 * 3); //about 3 month as default
+ if (request.params.size() > 6 && request.params[6].isNum())
+ {
+ depth = std::max(request.params[6].get_int(), (60 * 24 * 30 * 6)); // not greater than about 6 month
+ }
- if (request.params.size() > 3 && request.params[3].isNum())
- depth = request.params[3].get_int();
+ UniValue resultContent(UniValue::VARR);
+ auto ids = request.DbConnection()->SearchRepoInst->GetRecommendedContentByAddressSubscriptions(address, addressExclude, contentTypes, lang, cntOut, nHeight, depth);
+ if (!ids.empty())
+ {
+ auto contents = request.DbConnection()->WebRpcRepoInst->GetContentsData(ids, "");
+ resultContent.push_backV(contents);
+ }
- if (request.params.size() > 4 && request.params[4].isNum())
- cntOut = request.params[4].get_int();
+ ids = request.DbConnection()->SearchRepoInst->GetRandomContentByAddress(address, contentTypes, lang, cntOut);
+ if (!ids.empty())
+ {
+ auto contents = request.DbConnection()->WebRpcRepoInst->GetContentsData(ids, "");
+ resultContent.push_backV(contents);
+ }
- return request.DbConnection()->SearchRepoInst->GetRecomendedContentsByScoresFromAddress(address, contentTypes, nHeight, depth, cntOut);
+ UniValue result(UniValue::VOBJ);
+ result.pushKV("contents", resultContent);
+ return result;
},
};
}
- #pragma endregion
-
- RPCHelpMan GetRecommendedContentByContentId()
- {
- return RPCHelpMan{"GetRecommendedContentByContentId",
- "\n\n", // TODO (rpc): provide description
- {
- // TODO (rpc): args
- },
- {
- // TODO (rpc): provide return description
- },
- RPCExamples{
- // TODO (team): examples
- HelpExampleCli("GetRecommendedContentByContentId", "") +
- HelpExampleRpc("GetRecommendedContentByContentId", "")
- },
- [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
- {
- if (request.fHelp)
- throw runtime_error(
- "getrecommendedcontentbycontentid \"contentid\", \"address\", \"contenttypes\", \"lang\", count\n"
- "\nContents recommendations by contentid for address.\n"
- "\nArguments:\n"
- "1. \"contentid\" (string) Content Id Hash for recommendations\n"
- "2. \"address\" (string, optional) Address for which recommendations\n"
- "3. \"contenttypes\" (string or array of strings, optional) type(s) of content posts/videos/articles\n"
- "3. \"lang\" (string, optional) Language for recommendations\n"
- "4. \"count\" (int, optional) Number of resulting records. Default 15\n"
- );
-
- RPCTypeCheckArgument(request.params[0], UniValue::VSTR);
- string contenthash = request.params[0].get_str();
-
- string address = "";
- if (request.params.size() > 1 && request.params[1].isStr()) {
- address = request.params[1].get_str();
-
- if(!address.empty()) {
- CTxDestination dest = DecodeDestination(address);
- if (!IsValidDestination(dest))
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid address: ") + address);
- }
- }
-
- vector contentTypes;
- if(request.params.size()>2)
- ParseRequestContentTypes(request.params[2], contentTypes);
-
- string lang = "";
- if (request.params.size() > 3 && request.params[3].isStr())
- lang = request.params[3].get_str();
-
- int cntOut = 15;
- if (request.params.size() > 4 && request.params[4].isNum())
- cntOut = request.params[4].get_int();
-
- auto contentsAddresses = request.DbConnection()->WebRpcRepoInst->GetContentsAddresses(vector{contenthash});
-
- UniValue result(UniValue::VARR);
- auto ids = request.DbConnection()->SearchRepoInst->GetRecommendedContentByAddressSubscriptions(contentsAddresses[contenthash], address, contentTypes, lang, cntOut, ChainActive().Height(), (60 * 24 * 30 * 6), 100);
- if (!ids.empty())
- {
- auto contents = request.DbConnection()->WebRpcRepoInst->GetContentsData(ids, address);
- result.push_backV(contents);
- }
-
- return result;
- },
- };
- }
-
- RPCHelpMan GetRecommendedContentByAddress()
- {
- return RPCHelpMan{"GetRecommendedContentByAddress",
- "\n\n", // TODO (rpc): provide description
- {
- // TODO (rpc): args
- },
- {
- // TODO (rpc): provide return description
- },
- RPCExamples{
- // TODO (team): examples
- HelpExampleCli("GetRecommendedContentByAddress", "") +
- HelpExampleRpc("GetRecommendedContentByAddress", "")
- },
- [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
- {
- if (request.fHelp)
- throw runtime_error(
- "getrecommendedcontentbyaddress \"address\", \"addressExclude\", \"contenttypes\", \"lang\", count\n"
- "\nContents recommendations by content address.\n"
- "\nArguments:\n"
- "1. \"address\" (string) Address for recommendations\n"
- "2. \"addressExclude\" (string, optional) Address for exclude from recommendations\n"
- "3. \"contenttypes\" (string or array of strings, optional) type(s) of content posts/videos/articles\n"
- "3. \"lang\" (string, optional) Language for recommendations\n"
- "4. \"count\" (int, optional) Number of recommendations records and number of other contents from addres. Default 15\n"
- );
-
- RPCTypeCheckArgument(request.params[0], UniValue::VSTR);
- string address = "";
- if (request.params.size() > 0 && request.params[0].isStr()) {
- address = request.params[0].get_str();
-
- if(!address.empty()) {
- CTxDestination dest = DecodeDestination(address);
- if (!IsValidDestination(dest))
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid address: ") + address);
- }
- }
-
- string addressExclude = "";
- if (request.params.size() > 1 && request.params[1].isStr()) {
- addressExclude = request.params[1].get_str();
-
- if(!addressExclude.empty()) {
- CTxDestination dest = DecodeDestination(addressExclude);
- if (!IsValidDestination(dest))
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid address: ") + addressExclude);
- }
- }
-
- vector contentTypes;
- if(request.params.size()>2)
- ParseRequestContentTypes(request.params[2], contentTypes);
-
- string lang = "";
- if (request.params.size() > 3 && request.params[3].isStr())
- lang = request.params[3].get_str();
-
- int cntOut = 15;
- if (request.params.size() > 4 && request.params[4].isNum())
- cntOut = request.params[4].get_int();
-
- UniValue resultContent(UniValue::VARR);
- auto ids = request.DbConnection()->SearchRepoInst->GetRecommendedContentByAddressSubscriptions(address, addressExclude, contentTypes, lang, cntOut, ChainActive().Height(), (60 * 24 * 30 * 3), 20);
- if (!ids.empty())
- {
- auto contents = request.DbConnection()->WebRpcRepoInst->GetContentsData(ids, "");
- resultContent.push_backV(contents);
- }
-
- ids = request.DbConnection()->SearchRepoInst->GetRandomContentByAddress(address, contentTypes, lang, cntOut);
- if (!ids.empty())
- {
- auto contents = request.DbConnection()->WebRpcRepoInst->GetContentsData(ids, "");
- resultContent.push_backV(contents);
- }
-
- UniValue result(UniValue::VOBJ);
- result.pushKV("contents", resultContent);
- return result;
- },
- };
- }
RPCHelpMan GetRecommendedAccountByAddress()
{
@@ -774,66 +433,75 @@ namespace PocketWeb::PocketWebRpc
HelpExampleCli("GetRecommendedContentByAddress", "") +
HelpExampleRpc("GetRecommendedContentByAddress", "")
},
- [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
- {
- if (request.fHelp)
- throw runtime_error(
- "getrecommendedaccountbyaddress \"address\", \"addressExclude\", \"contenttypes\", \"lang\", count\n"
- "\nAccounts recommendations by address.\n"
- "\nArguments:\n"
- "1. \"address\" (string) Address for recommendations\n"
- "2. \"addressExclude\" (string, optional) Address for exclude from recommendations\n"
- "3. \"contenttypes\" (string or array of strings, optional) type(s) of content posts/videos/articles\n"
- "3. \"lang\" (string, optional) Language for recommendations\n"
- "4. \"count\" (int, optional) Number of recommendations records and number of other contents from addres. Default 15\n"
- );
-
- RPCTypeCheckArgument(request.params[0], UniValue::VSTR);
- string address = "";
- if (request.params.size() > 0 && request.params[0].isStr()) {
- address = request.params[0].get_str();
-
- if(!address.empty()) {
- CTxDestination dest = DecodeDestination(address);
- if (!IsValidDestination(dest))
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid address: ") + address);
- }
- }
-
- string addressExclude = "";
- if (request.params.size() > 1 && request.params[1].isStr()) {
- addressExclude = request.params[1].get_str();
-
- if(!addressExclude.empty()) {
- CTxDestination dest = DecodeDestination(addressExclude);
- if (!IsValidDestination(dest))
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid address: ") + addressExclude);
- }
- }
-
- vector contentTypes;
- if(request.params.size()>2)
- ParseRequestContentTypes(request.params[2], contentTypes);
-
- string lang = "";
- if (request.params.size() > 3 && request.params[3].isStr())
- lang = request.params[3].get_str();
-
- int cntOut = 15;
- if (request.params.size() > 4 && request.params[4].isNum())
- cntOut = request.params[4].get_int();
-
- UniValue result(UniValue::VARR);
- auto ids = request.DbConnection()->SearchRepoInst->GetRecommendedAccountByAddressSubscriptions(address, addressExclude, contentTypes, lang, cntOut, ChainActive().Height(), (60 * 24 * 30 * 3), 10);
- if (!ids.empty())
- {
- auto profiles = request.DbConnection()->WebRpcRepoInst->GetAccountProfiles(ids, true);
- for (const auto[id, record] : profiles)
- result.push_back(record);
- }
-
- return result;
- },
+ [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
+ {
+ // if (request.fHelp)
+ // throw runtime_error(
+ // "getrecommendedaccountbyaddress \"address\", \"addressExclude\", \"contenttypes\", \"lang\", count\n"
+ // "\nAccounts recommendations by address.\n"
+ // "\nArguments:\n"
+ // "1. \"address\" (string) Address for recommendations\n"
+ // "2. \"addressExclude\" (string, optional) Address for exclude from recommendations\n"
+ // "3. \"contenttypes\" (string or array of strings, optional) type(s) of content posts/videos/articles\n"
+ // "3. \"lang\" (string, optional) Language for recommendations\n"
+ // "4. \"count\" (int, optional) Number of recommendations records and number of other contents from addres. Default 15\n"
+ // );
+ RPCTypeCheckArgument(request.params[0], UniValue::VSTR);
+ string address = "";
+ if (request.params.size() > 0 && request.params[0].isStr()) {
+ address = request.params[0].get_str();
+
+ if(!address.empty()) {
+ CTxDestination dest = DecodeDestination(address);
+ if (!IsValidDestination(dest))
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid address: ") + address);
+ }
+ }
+
+ string addressExclude = "";
+ if (request.params.size() > 1 && request.params[1].isStr()) {
+ addressExclude = request.params[1].get_str();
+
+ if(!addressExclude.empty()) {
+ CTxDestination dest = DecodeDestination(addressExclude);
+ if (!IsValidDestination(dest))
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid address: ") + addressExclude);
+ }
+ }
+
+ vector contentTypes;
+ if(request.params.size()>2)
+ ParseRequestContentTypes(request.params[2], contentTypes);
+
+ string lang = "";
+ if (request.params.size() > 3 && request.params[3].isStr())
+ lang = request.params[3].get_str();
+
+ int cntOut = 15;
+ if (request.params.size() > 4 && request.params[4].isNum())
+ cntOut = request.params[4].get_int();
+
+ int nHeight = ChainActive().Height();
+ if (request.params.size() > 5 && request.params[5].isNum() && request.params[5].get_int() > 0)
+ nHeight = request.params[5].get_int();
+
+ int depth = (60 * 24 * 30 * 3); //about 3 month as default
+ if (request.params.size() > 6 && request.params[6].isNum())
+ {
+ depth = std::max(request.params[6].get_int(), (60 * 24 * 30 * 6)); // not greater than about 6 month
+ }
+
+ UniValue result(UniValue::VARR);
+ auto ids = request.DbConnection()->SearchRepoInst->GetRecommendedAccountByAddressSubscriptions(address, addressExclude, contentTypes, lang, cntOut, nHeight, depth);
+ if (!ids.empty())
+ {
+ auto profiles = request.DbConnection()->WebRpcRepoInst->GetAccountProfiles(ids, true);
+ for (const auto[id, record] : profiles)
+ result.push_back(record);
+ }
+
+ return result;
+ },
};
}
}
diff --git a/src/pocketdb/web/SearchRpc.h b/src/pocketdb/web/SearchRpc.h
index 79a877735..656bc160b 100644
--- a/src/pocketdb/web/SearchRpc.h
+++ b/src/pocketdb/web/SearchRpc.h
@@ -22,37 +22,7 @@ namespace PocketWeb::PocketWebRpc
RPCHelpMan SearchLinks();
RPCHelpMan SearchContents();
- #pragma region Recomendations OLD
- // TODO (o1q): Remove below methods when the client gui switches to new methods
- // Accounts recommendations based on subscriptions
- // Get some accounts that were followed by people who've followed this Account
- // This should be run only if Account already has followers
- RPCHelpMan GetRecomendedAccountsBySubscriptions();
-
- // Accounts recommendations based on scores on other Account
- // Get some Accounts that were scored by people who've scored this Account (not long ago - several blocks ago)
- RPCHelpMan GetRecomendedAccountsByScoresOnSimilarAccounts();
-
- // Accounts recommendations based on address scores
- // Get some Accounts that were scored by people who've scored like address (not long ago - several blocks ago)
- // Get address scores -> Get scored contents -> Get Scores to these contents -> Get scores accounts -> Get their scores -> Get their scored contents -> Get these contents Authors
- RPCHelpMan GetRecomendedAccountsByScoresFromAddress();
-
- // Accounts recommendations based on tags
- RPCHelpMan GetRecomendedAccountsByTags();
-
- // Contents recommendations by others contents
- // Get some contents that were liked by people who've seen this content (not long ago - several blocks ago)
- // This should be run only if Content already has >XXXX likes
- RPCHelpMan GetRecomendedContentsByScoresOnSimilarContents();
-
- // Contents recommendations by address scores
- // Get some contents that were liked by people who've scored like address (not long ago - several blocks ago)
- RPCHelpMan GetRecomendedContentsByScoresFromAddress();
- #pragma endregion
-
#pragma region Recomendations
- RPCHelpMan GetRecommendedContentByContentId();
RPCHelpMan GetRecommendedContentByAddress();
RPCHelpMan GetRecommendedAccountByAddress();
#pragma endregion
diff --git a/src/rest.cpp b/src/rest.cpp
index d982a6260..ddc360302 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -777,38 +777,8 @@ static bool rest_getutxos(const util::Ref& context, HTTPRequest* req, const std:
}
}
-static bool rest_topaddresses(const util::Ref& context, HTTPRequest* req, const std::string& strURIPart)
+static double getEmission(int height)
{
- if (!CheckWarmup(req))
- return false;
-
- auto[rf, uriParts] = ParseParams(strURIPart);
-
- int count = 30;
- if (!uriParts.empty())
- {
- count = std::stoi(uriParts[0]);
- if (count > 1000)
- count = 1000;
- }
-
- auto result = req->DbConnection()->WebRpcRepoInst->GetTopAddresses(count);
- req->WriteHeader("Content-Type", "application/json");
- req->WriteReply(HTTP_OK, result.write() + "\n");
- return true;
-}
-
-static bool rest_emission(const util::Ref& context, HTTPRequest* req, const std::string& strURIPart)
-{
- if (!CheckWarmup(req))
- return false;
-
- auto[rf, uriParts] = ParseParams(strURIPart);
-
- int height = ChainActive().Height();
- if (auto[ok, result] = TryGetParamInt(uriParts, 0); ok)
- height = result;
-
int first75 = 3750000;
int halvblocks = 2'100'000;
double emission = 0;
@@ -838,25 +808,73 @@ static bool rest_emission(const util::Ref& context, HTTPRequest* req, const std:
}
}
- switch (rf)
- {
- case RetFormat::JSON:
- {
- UniValue result(UniValue::VOBJ);
- result.pushKV("height", height);
- result.pushKV("emission", emission);
+ return emission;
+}
- req->WriteHeader("Content-Type", "application/json");
- req->WriteReply(HTTP_OK, result.write() + "\n");
- return true;
- }
- default:
- {
- req->WriteHeader("Content-Type", "text/plain");
- req->WriteReply(HTTP_OK, std::to_string(emission) + "\n");
- return true;
- }
+static bool get_static_status(HTTPRequest* req, const std::string& strURIPart)
+{
+ if (!CheckWarmup(req))
+ return false;
+
+ // TODO (brangr): join with PocketSystemRpc.cpp::GetNodeInfo
+
+ UniValue entry(UniValue::VOBJ);
+
+ // General information about instance
+ entry.pushKV("version", FormatVersion(CLIENT_VERSION));
+ entry.pushKV("time", GetAdjustedTime());
+ entry.pushKV("chain", Params().NetworkIDString());
+ entry.pushKV("proxy", true);
+
+ // Network information
+ uint64_t nNetworkWeight = GetPoSKernelPS();
+ entry.pushKV("netstakeweight", (uint64_t)nNetworkWeight);
+ entry.pushKV("emission", getEmission(ChainActive().Height()));
+
+ // Last block
+ CBlockIndex* pindex = ChainActive().Tip();
+ UniValue oblock(UniValue::VOBJ);
+ oblock.pushKV("height", pindex->nHeight);
+ oblock.pushKV("hash", pindex->GetBlockHash().GetHex());
+ oblock.pushKV("time", (int64_t)pindex->nTime);
+ oblock.pushKV("ntx", (int)pindex->nTx);
+ entry.pushKV("lastblock", oblock);
+
+ UniValue proxies(UniValue::VARR);
+ if (WSConnections) {
+ auto fillProxy = [&proxies](const std::pair& it) {
+ if (it.second.Service) {
+ UniValue proxy(UniValue::VOBJ);
+ proxy.pushKV("address", it.second.Address);
+ proxy.pushKV("ip", it.second.Ip);
+ proxy.pushKV("port", it.second.MainPort);
+ proxy.pushKV("portWss", it.second.WssPort);
+ proxies.push_back(proxy);
+ }
+ };
+ WSConnections->Iterate(fillProxy);
}
+ entry.pushKV("proxies", proxies);
+
+ // Ports information
+ int64_t nodePort = gArgs.GetArg("-port", Params().GetDefaultPort());
+ int64_t publicPort = gArgs.GetArg("-publicrpcport", BaseParams().PublicRPCPort());
+ int64_t staticPort = gArgs.GetArg("-staticrpcport", BaseParams().StaticRPCPort());
+ int64_t restPort = gArgs.GetArg("-restport", BaseParams().RestPort());
+ int64_t wssPort = gArgs.GetArg("-wsport", 8087); // TODO (brangr): move 8087 to BaseParams().WSPort()
+
+ UniValue ports(UniValue::VOBJ);
+ ports.pushKV("node", nodePort);
+ ports.pushKV("api", publicPort);
+ ports.pushKV("rest", restPort);
+ ports.pushKV("wss", wssPort);
+ ports.pushKV("http", staticPort);
+ ports.pushKV("https", staticPort);
+ entry.pushKV("ports", ports);
+
+ req->WriteHeader("Content-Type", "application/json");
+ req->WriteReply(HTTP_OK, entry.write() + "\n");
+ return true;
}
static bool debug_index_block(const util::Ref& context, HTTPRequest* req, const std::string& strURIPart)
@@ -998,6 +1016,9 @@ static bool get_static_web(const util::Ref& context, HTTPRequest* req, const std
return true;
}
+ if (strURIPart.find("status") == 0)
+ return get_static_status(req, strURIPart);
+
if (auto[code, file] = PocketWeb::PocketFrontendInst.GetFile(strURIPart); code == HTTP_OK)
{
req->WriteHeader("Content-Type", file->ContentType);
@@ -1075,25 +1096,26 @@ static const struct
{"/rest/headers/", rest_headers},
{"/rest/getutxos", rest_getutxos},
{"/rest/blockhashbyheight/", rest_blockhash_by_height},
- {"/rest/emission", rest_emission},
- {"/rest/getemission", rest_emission},
- {"/rest/topaddresses", rest_topaddresses},
- {"/rest/gettopaddresses", rest_topaddresses},
{"/rest/blockhash", rest_blockhash},
};
void StartREST(const util::Ref& context)
{
- if(g_restSocket)
+ if(g_restSocket) {
for (const auto& up : uri_prefixes) {
auto handler = [&context, up](HTTPRequest* req, const std::string& prefix) { return up.handler(context, req, prefix); };
g_restSocket->RegisterHTTPHandler(up.prefix, false, handler, g_restSocket->m_workQueue);
}
+ }
+}
+
+// Register web content route
+void StartSTATIC(const util::Ref& context)
+{
if(g_staticSocket)
{
auto handler = [&context](HTTPRequest* req, const std::string& prefix) { return get_static_web(context, req, prefix); };
g_staticSocket->RegisterHTTPHandler("/", false, handler, g_staticSocket->m_workQueue);
-
}
}
@@ -1105,8 +1127,11 @@ void StopREST()
{
if (g_restSocket)
for (auto uri_prefixe: uri_prefixes)
- g_restSocket->UnregisterHTTPHandler(uri_prefixe.prefix, false);
+ g_restSocket->UnregisterHTTPHandler(uri_prefixe.prefix, false);
+}
+void StopSTATIC()
+{
if (g_staticSocket)
g_staticSocket->UnregisterHTTPHandler("/", false);
}
diff --git a/src/rpc/cache.h b/src/rpc/cache.h
index 79514bd22..88bda9a37 100644
--- a/src/rpc/cache.h
+++ b/src/rpc/cache.h
@@ -36,6 +36,7 @@ class RPCCache
"gethierarchicalfeed",
"gethierarchicalstrip",
"gethotposts",
+ "gettopfeed",
"getuserprofile",
"getprofilefeed",
"getsubscribesfeed",
@@ -50,15 +51,15 @@ class RPCCache
"getusersubscribes",
"getusersubscribers",
"getuserblockings",
+ "gettopaccounts",
"getaddressscores",
"getpostscores",
"getstatisticbyhours",
"getstatisticbydays",
"getstatisticcontentbyhours",
"getstatisticcontentbydays",
- "getrecomendedaccountsbytags",
- "getrecomendedcontentsbyscoresonsimilarcontents",
- "getrecommendedcontentbycontentid",
+ "getrecommendedcontentbyaddress",
+ "getrecommendedaccountbyaddress",
"getaddressinfo",
"getcompactblock",
"getlastblocks",
diff --git a/src/validation.cpp b/src/validation.cpp
index 57427ccd7..146746b1a 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -54,6 +54,7 @@
#include
#include
+#include
#include "pocketdb/services/ChainPostProcessing.h"
#include "pocketdb/services/Accessor.h"
@@ -2511,7 +2512,7 @@ bool CChainState::ConnectBlock(const CBlock& block, const PocketBlockRef& pocket
// -----------------------------------------------------------------------------------------------------------------
// Extend WEB database
- if (gArgs.GetBoolArg("-api", true) && enablePocketConnect)
+ if (!gArgs.GetBoolArg("-withoutweb", false) && enablePocketConnect)
PocketServices::WebPostProcessorInst.Enqueue(block.GetHash().GetHex());
// -----------------------------------------------------------------------------------------------------------------