mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 03:52:49 +01:00
refactor: use new style of composite commands for RPC gobject NNN
This commit is contained in:
parent
42e0b37cb2
commit
006242114f
@ -28,22 +28,17 @@
|
||||
#include <wallet/wallet.h>
|
||||
#endif // ENABLE_WALLET
|
||||
|
||||
static void gobject_count_help(const JSONRPCRequest& request)
|
||||
static RPCHelpMan gobject_count()
|
||||
{
|
||||
RPCHelpMan{"gobject count",
|
||||
return RPCHelpMan{"gobject count",
|
||||
"Count governance objects and votes\n",
|
||||
{
|
||||
{"mode", RPCArg::Type::STR, /* default */ "json", "Output format: json (\"json\") or string in free form (\"all\")"},
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_count(const JSONRPCRequest& request)
|
||||
RPCExamples{""},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
gobject_count_help(request);
|
||||
|
||||
std::string strMode{"json"};
|
||||
|
||||
if (!request.params[0].isNull()) {
|
||||
@ -51,29 +46,26 @@ static UniValue gobject_count(const JSONRPCRequest& request)
|
||||
}
|
||||
|
||||
if (strMode != "json" && strMode != "all")
|
||||
gobject_count_help(request);
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "mode can be 'json' or 'all'");
|
||||
|
||||
const NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
CHECK_NONFATAL(node.govman);
|
||||
return strMode == "json" ? node.govman->ToJson() : node.govman->ToString();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static void gobject_deserialize_help(const JSONRPCRequest& request)
|
||||
static RPCHelpMan gobject_deserialize()
|
||||
{
|
||||
RPCHelpMan{"gobject deserialize",
|
||||
return RPCHelpMan{"gobject deserialize",
|
||||
"Deserialize governance object from hex string to JSON\n",
|
||||
{
|
||||
{"hex_data", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "data in hex string form"},
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_deserialize(const JSONRPCRequest& request)
|
||||
RPCExamples{""},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
gobject_deserialize_help(request);
|
||||
|
||||
std::string strHex = request.params[0].get_str();
|
||||
|
||||
std::vector<unsigned char> v = ParseHex(strHex);
|
||||
@ -83,24 +75,21 @@ static UniValue gobject_deserialize(const JSONRPCRequest& request)
|
||||
u.read(s);
|
||||
|
||||
return u.write().c_str();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static void gobject_check_help(const JSONRPCRequest& request)
|
||||
static RPCHelpMan gobject_check()
|
||||
{
|
||||
RPCHelpMan{"gobject check",
|
||||
return RPCHelpMan{"gobject check",
|
||||
"Validate governance object data (proposal only)\n",
|
||||
{
|
||||
{"hex_data", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "data in hex string format"},
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_check(const JSONRPCRequest& request)
|
||||
RPCExamples{""},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
gobject_check_help(request);
|
||||
|
||||
// ASSEMBLE NEW GOVERNANCE OBJECT FROM USER PARAMETERS
|
||||
|
||||
uint256 hashParent;
|
||||
@ -126,12 +115,14 @@ static UniValue gobject_check(const JSONRPCRequest& request)
|
||||
objResult.pushKV("Object status", "OK");
|
||||
|
||||
return objResult;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
static void gobject_prepare_help(const JSONRPCRequest& request)
|
||||
static RPCHelpMan gobject_prepare()
|
||||
{
|
||||
RPCHelpMan{"gobject prepare",
|
||||
return RPCHelpMan{"gobject prepare",
|
||||
"Prepare governance object by signing and creating tx\n"
|
||||
+ HELP_REQUIRING_PASSPHRASE,
|
||||
{
|
||||
@ -144,17 +135,12 @@ static void gobject_prepare_help(const JSONRPCRequest& request)
|
||||
{"outputIndex", RPCArg::Type::NUM, /* default */ "", "The output index."},
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_prepare(const JSONRPCRequest& request)
|
||||
RPCExamples{""},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
|
||||
gobject_prepare_help(request);
|
||||
|
||||
EnsureWalletIsUnlocked(wallet.get());
|
||||
|
||||
// ASSEMBLE NEW GOVERNANCE OBJECT FROM USER PARAMETERS
|
||||
@ -246,25 +232,22 @@ static UniValue gobject_prepare(const JSONRPCRequest& request)
|
||||
govobj.GetDataAsPlainString(), govobj.GetHash().ToString(), tx->GetHash().ToString());
|
||||
|
||||
return tx->GetHash().ToString();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static void gobject_list_prepared_help(const JSONRPCRequest& request)
|
||||
static RPCHelpMan gobject_list_prepared()
|
||||
{
|
||||
RPCHelpMan{"gobject list-prepared",
|
||||
return RPCHelpMan{"gobject list-prepared",
|
||||
"Returns a list of governance objects prepared by this wallet with \"gobject prepare\" sorted by their creation time.\n"
|
||||
+ HELP_REQUIRING_PASSPHRASE,
|
||||
{
|
||||
{"count", RPCArg::Type::NUM, /* default */ "10", "Maximum number of objects to return."},
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_list_prepared(const JSONRPCRequest& request)
|
||||
RPCExamples{""},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
gobject_list_prepared_help(request);
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
EnsureWalletIsUnlocked(wallet.get());
|
||||
@ -288,12 +271,14 @@ static UniValue gobject_list_prepared(const JSONRPCRequest& request)
|
||||
}
|
||||
|
||||
return jsonArray;
|
||||
},
|
||||
};
|
||||
}
|
||||
#endif // ENABLE_WALLET
|
||||
|
||||
static void gobject_submit_help(const JSONRPCRequest& request)
|
||||
static RPCHelpMan gobject_submit()
|
||||
{
|
||||
RPCHelpMan{"gobject submit",
|
||||
return RPCHelpMan{"gobject submit",
|
||||
"Submit governance object to network\n",
|
||||
{
|
||||
{"parent-hash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "hash of the parent object, \"0\" is root"},
|
||||
@ -303,14 +288,9 @@ static void gobject_submit_help(const JSONRPCRequest& request)
|
||||
{"fee-txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "txid of the corresponding proposal fee transaction"},
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_submit(const JSONRPCRequest& request)
|
||||
RPCExamples{""},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
gobject_submit_help(request);
|
||||
|
||||
const NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
const ChainstateManager& chainman = EnsureChainman(node);
|
||||
CHECK_NONFATAL(node.dmnman);
|
||||
@ -411,6 +391,8 @@ static UniValue gobject_submit(const JSONRPCRequest& request)
|
||||
}
|
||||
|
||||
return govobj.GetHash().ToString();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static UniValue VoteWithMasternodes(const JSONRPCRequest& request, const std::map<uint256, CKey>& keys,
|
||||
@ -481,9 +463,9 @@ static UniValue VoteWithMasternodes(const JSONRPCRequest& request, const std::ma
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
static void gobject_vote_many_help(const JSONRPCRequest& request)
|
||||
static RPCHelpMan gobject_vote_many()
|
||||
{
|
||||
RPCHelpMan{"gobject vote-many",
|
||||
return RPCHelpMan{"gobject vote-many",
|
||||
"Vote on a governance object by all masternodes for which the voting key is present in the local wallet\n"
|
||||
+ HELP_REQUIRING_PASSPHRASE,
|
||||
{
|
||||
@ -492,14 +474,9 @@ static void gobject_vote_many_help(const JSONRPCRequest& request)
|
||||
{"vote-outcome", RPCArg::Type::STR, RPCArg::Optional::NO, "vote outcome, possible values: [yes|no|abstain]"},
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_vote_many(const JSONRPCRequest& request)
|
||||
RPCExamples{""},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
gobject_vote_many_help(request);
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
|
||||
@ -540,11 +517,13 @@ static UniValue gobject_vote_many(const JSONRPCRequest& request)
|
||||
});
|
||||
|
||||
return VoteWithMasternodes(request, votingKeys, hash, eVoteSignal, eVoteOutcome);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static void gobject_vote_alias_help(const JSONRPCRequest& request)
|
||||
static RPCHelpMan gobject_vote_alias()
|
||||
{
|
||||
RPCHelpMan{"gobject vote-alias",
|
||||
return RPCHelpMan{"gobject vote-alias",
|
||||
"Vote on a governance object by masternode's voting key (if present in local wallet)\n"
|
||||
+ HELP_REQUIRING_PASSPHRASE,
|
||||
{
|
||||
@ -554,14 +533,9 @@ static void gobject_vote_alias_help(const JSONRPCRequest& request)
|
||||
{"protx-hash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "masternode's proTxHash"},
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_vote_alias(const JSONRPCRequest& request)
|
||||
RPCExamples{""},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
gobject_vote_alias_help(request);
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
|
||||
@ -606,6 +580,8 @@ static UniValue gobject_vote_alias(const JSONRPCRequest& request)
|
||||
votingKeys.emplace(proTxHash, votingKey);
|
||||
|
||||
return VoteWithMasternodes(request, votingKeys, hash, eVoteSignal, eVoteOutcome);
|
||||
},
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -670,23 +646,18 @@ static UniValue ListObjects(CGovernanceManager& govman, const CDeterministicMNLi
|
||||
return objResult;
|
||||
}
|
||||
|
||||
static void gobject_list_help(const JSONRPCRequest& request)
|
||||
static RPCHelpMan gobject_list()
|
||||
{
|
||||
RPCHelpMan{"gobject list",
|
||||
return RPCHelpMan{"gobject list",
|
||||
"List governance objects (can be filtered by signal and/or object type)\n",
|
||||
{
|
||||
{"signal", RPCArg::Type::STR, /* default */ "valid", "cached signal, possible values: [valid|funding|delete|endorsed|all]"},
|
||||
{"type", RPCArg::Type::STR, /* default */ "all", "object type, possible values: [proposals|triggers|all]"},
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_list(const JSONRPCRequest& request)
|
||||
RPCExamples{""},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
gobject_list_help(request);
|
||||
|
||||
std::string strCachedSignal = "valid";
|
||||
if (!request.params[0].isNull()) {
|
||||
strCachedSignal = request.params[0].get_str();
|
||||
@ -707,25 +678,22 @@ static UniValue gobject_list(const JSONRPCRequest& request)
|
||||
CHECK_NONFATAL(node.govman);
|
||||
|
||||
return ListObjects(*node.govman, node.dmnman->GetListAtChainTip(), chainman, strCachedSignal, strType, 0);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static void gobject_diff_help(const JSONRPCRequest& request)
|
||||
static RPCHelpMan gobject_diff()
|
||||
{
|
||||
RPCHelpMan{"gobject diff",
|
||||
return RPCHelpMan{"gobject diff",
|
||||
"List differences since last diff or list\n",
|
||||
{
|
||||
{"signal", RPCArg::Type::STR, /* default */ "valid", "cached signal, possible values: [valid|funding|delete|endorsed|all]"},
|
||||
{"type", RPCArg::Type::STR, /* default */ "all", "object type, possible values: [proposals|triggers|all]"},
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_diff(const JSONRPCRequest& request)
|
||||
RPCExamples{""},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
gobject_diff_help(request);
|
||||
|
||||
std::string strCachedSignal = "valid";
|
||||
if (!request.params[0].isNull()) {
|
||||
strCachedSignal = request.params[0].get_str();
|
||||
@ -745,24 +713,21 @@ static UniValue gobject_diff(const JSONRPCRequest& request)
|
||||
CHECK_NONFATAL(node.dmnman && node.govman);
|
||||
|
||||
return ListObjects(*node.govman, node.dmnman->GetListAtChainTip(), chainman, strCachedSignal, strType, node.govman->GetLastDiffTime());
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static void gobject_get_help(const JSONRPCRequest& request)
|
||||
static RPCHelpMan gobject_get()
|
||||
{
|
||||
RPCHelpMan{"gobject get",
|
||||
return RPCHelpMan{"gobject get",
|
||||
"Get governance object by hash\n",
|
||||
{
|
||||
{"governance-hash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "object id"},
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_get(const JSONRPCRequest& request)
|
||||
RPCExamples{""},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
gobject_get_help(request);
|
||||
|
||||
// COLLECT VARIABLES FROM OUR USER
|
||||
uint256 hash(ParseHashV(request.params[0], "GovObj hash"));
|
||||
|
||||
@ -841,11 +806,13 @@ static UniValue gobject_get(const JSONRPCRequest& request)
|
||||
objResult.pushKV("fCachedDelete", pGovObj->IsSetCachedDelete());
|
||||
objResult.pushKV("fCachedEndorsed", pGovObj->IsSetCachedEndorsed());
|
||||
return objResult;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static void gobject_getcurrentvotes_help(const JSONRPCRequest& request)
|
||||
static RPCHelpMan gobject_getcurrentvotes()
|
||||
{
|
||||
RPCHelpMan{"gobject getcurrentvotes",
|
||||
return RPCHelpMan{"gobject getcurrentvotes",
|
||||
"Get only current (tallying) votes for a governance object hash (does not include old votes)\n",
|
||||
{
|
||||
{"governance-hash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "object id"},
|
||||
@ -853,14 +820,9 @@ static void gobject_getcurrentvotes_help(const JSONRPCRequest& request)
|
||||
{"vout", RPCArg::Type::STR, /* default */ "", "masternode collateral output index, required if <txid> present"},
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_getcurrentvotes(const JSONRPCRequest& request)
|
||||
RPCExamples{""},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
gobject_getcurrentvotes_help(request);
|
||||
|
||||
// COLLECT PARAMETERS FROM USER
|
||||
|
||||
uint256 hash(ParseHashV(request.params[0], "Governance hash"));
|
||||
@ -895,11 +857,13 @@ static UniValue gobject_getcurrentvotes(const JSONRPCRequest& request)
|
||||
}
|
||||
|
||||
return bResult;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
[[ noreturn ]] static void gobject_help()
|
||||
static RPCHelpMan gobject()
|
||||
{
|
||||
RPCHelpMan{"gobject",
|
||||
return RPCHelpMan{"gobject",
|
||||
"Set of commands to manage governance objects.\n"
|
||||
"\nAvailable commands:\n"
|
||||
" check - Validate governance object data (proposal only)\n"
|
||||
@ -919,12 +883,19 @@ static UniValue gobject_getcurrentvotes(const JSONRPCRequest& request)
|
||||
" vote-many - Vote on a governance object by all masternodes for which the voting key is in the wallet\n"
|
||||
#endif // ENABLE_WALLET
|
||||
,
|
||||
{},
|
||||
{
|
||||
{"command", RPCArg::Type::STR, RPCArg::Optional::NO, "The command to execute"},
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.Throw();
|
||||
RPCExamples{""},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Must be a valid command");
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
static UniValue gobject(const JSONRPCRequest& request)
|
||||
{
|
||||
const JSONRPCRequest new_request{request.strMethod == "gobject" ? request.squashed() : request};
|
||||
@ -952,6 +923,7 @@ static UniValue gobject(const JSONRPCRequest& request)
|
||||
|
||||
gobject submit 6e622bb41bad1fb18e7f23ae96770aeb33129e18bd9efe790522488e580a0a03 0 1 1464292854 "beer-reimbursement" 5b5b22636f6e7472616374222c207b2270726f6a6563745f6e616d65223a20225c22626565722d7265696d62757273656d656e745c22222c20227061796d656e745f61646472657373223a20225c225879324c4b4a4a64655178657948726e34744744514238626a6876464564615576375c22222c2022656e645f64617465223a202231343936333030343030222c20226465736372697074696f6e5f75726c223a20225c227777772e646173687768616c652e6f72672f702f626565722d7265696d62757273656d656e745c22222c2022636f6e74726163745f75726c223a20225c22626565722d7265696d62757273656d656e742e636f6d2f3030312e7064665c22222c20227061796d656e745f616d6f756e74223a20223233342e323334323232222c2022676f7665726e616e63655f6f626a6563745f6964223a2037342c202273746172745f64617465223a202231343833323534303030227d5d5d1
|
||||
*/
|
||||
/*
|
||||
return gobject_submit(new_request);
|
||||
#ifdef ENABLE_WALLET
|
||||
} else if (command == "gobjectvote-many") {
|
||||
@ -974,6 +946,7 @@ static UniValue gobject(const JSONRPCRequest& request)
|
||||
gobject_help();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
static UniValue voteraw(const JSONRPCRequest& request)
|
||||
{
|
||||
@ -1145,12 +1118,26 @@ static const CRPCCommand commands[] =
|
||||
/* Dash features */
|
||||
{ "dash", "getgovernanceinfo", &getgovernanceinfo, {} },
|
||||
{ "dash", "getsuperblockbudget", &getsuperblockbudget, {"index"} },
|
||||
{ "dash", "gobject", &gobject, {} },
|
||||
{ "dash", "gobject", &gobject, {"command"} },
|
||||
{ "dash", "gobject", "count", &gobject_count, {"mode"} },
|
||||
{ "dash", "gobject", "deserialize", &gobject_deserialize, {"hex_data"} },
|
||||
{ "dash", "gobject", "check", &gobject_check, {"hex_data"} },
|
||||
#ifdef ENABLE_WALLET
|
||||
{ "dash", "gobject", "prepare", &gobject_prepare, {"parent-hash", "revision", "time", "data-hex", "use-IS", "outputHash", "outputIndex"} },
|
||||
{ "dash", "gobject", "list-prepared", &gobject_list_prepared, {"count"} },
|
||||
{ "dash", "gobject", "vote-many", &gobject_vote_many, {"governance-hash", "vote", "vote-outcome"} },
|
||||
{ "dash", "gobject", "vote-alias", &gobject_vote_alias, {"governance-hash", "vote", "vote-outcome", "protx-hash"} },
|
||||
#endif
|
||||
{ "dash", "gobject", "submit", &gobject_submit, {"parent-hash", "revision", "time", "data-hex", "fee-txid"} },
|
||||
{ "dash", "gobject", "list", &gobject_list, {"signal", "type"} },
|
||||
{ "dash", "gobject", "diff", &gobject_diff, {"signal", "type"} },
|
||||
{ "dash", "gobject", "get", &gobject_get, {"governance-hash"} },
|
||||
{ "dash", "gobject", "getcurrentvotes", &gobject_getcurrentvotes, {"governance-hash", "txid", "vout"} },
|
||||
{ "dash", "voteraw", &voteraw, {"mn-collateral-tx-hash","mn-collateral-tx-index","governance-hash","vote-signal","vote-outcome","time","vote-sig"} },
|
||||
|
||||
};
|
||||
// clang-format on
|
||||
for (const auto& command : commands) {
|
||||
t.appendCommand(command.name, &command);
|
||||
t.appendCommand(command.name, command.subname, &command);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user