general fixes

This commit is contained in:
Sleepy Flower Girl
2021-11-26 11:55:13 -05:00
parent ad97ca11aa
commit cf92277f6a
5 changed files with 94 additions and 86 deletions

View File

@@ -324,19 +324,21 @@ namespace SleepyDiscord {
template<class Options = const AppCommand::EmptyOptions>
ObjectResponse<AppCommand> createGlobalAppCommand(
Snowflake<DiscordObject>::RawType applicationID, std::string name, std::string description, Options& options = AppCommand::emptyOptions,
bool defaultPermission = true, AppCommand::Type type = AppCommand::Type::NONE,
RequestSettings<ObjectResponse<AppCommand>> settings = {}
) {
return ObjectResponse<AppCommand>{ request(Post, path("applications/{application.id}/commands", { applicationID }), settings,
createApplicationCommandBody(name, description, options)) };
createApplicationCommandBody(name, description, options, defaultPermission, type)) };
}
template<class Options = const AppCommand::EmptyOptions>
ObjectResponse<AppCommand> editGlobalAppCommand(
Snowflake<DiscordObject>::RawType applicationID, Snowflake<AppCommand> commandID, std::string name, std::string description,
bool defaultPermission = true, AppCommand::Type type = AppCommand::Type::NONE,
Options& options = AppCommand::emptyOptions, RequestSettings<ObjectResponse<AppCommand>> settings = {}
) {
return ObjectResponse<AppCommand>{ request(Patch,
path("applications/{application.id}/commands/{command.id}", { applicationID, commandID }), settings,
createApplicationCommandBody(name, description, options, true)) };
createApplicationCommandBody(name, description, options, defaultPermission, type, true)) };
}
ArrayResponse<AppCommand> getGlobalAppCommands(Snowflake<DiscordObject>::RawType applicationID, RequestSettings<ArrayResponse<AppCommand>> settings = {});
ObjectResponse<AppCommand> getGlobalAppCommand(Snowflake<DiscordObject>::RawType applicationID, Snowflake<AppCommand> commandID, RequestSettings<ObjectResponse<AppCommand>> settings = {});
@@ -376,10 +378,11 @@ namespace SleepyDiscord {
template<class Options = const AppCommand::EmptyOptions>
ObjectResponse<AppCommand> createAppCommand(
Snowflake<DiscordObject>::RawType applicationID, Snowflake<Server> serverID, std::string name, std::string description,
Options& options = AppCommand::emptyOptions, RequestSettings<ObjectResponse<AppCommand>> settings = {}
Options& options = AppCommand::emptyOptions, bool defaultPermission = true, AppCommand::Type type = AppCommand::Type::NONE,
RequestSettings<ObjectResponse<AppCommand>> settings = {}
) {
if (serverID.empty()) return createGlobalAppCommand(applicationID, name, description, options, settings);
return createServerAppCommand(applicationID, serverID, name, description, options, settings);
if (serverID.empty()) return createGlobalAppCommand(applicationID, name, description, options, defaultPermission, type, settings);
return createServerAppCommand(applicationID, serverID, name, description, options, defaultPermission, type, settings);
}
template<class Options = const AppCommand::EmptyOptions>
ObjectResponse<AppCommand> editAppCommand(
@@ -393,6 +396,7 @@ namespace SleepyDiscord {
ArrayResponse<AppCommand> getAppCommands(Snowflake<DiscordObject>::RawType applicationID, Snowflake<Server> serverID, RequestSettings<ArrayResponse<AppCommand>> settings = {});
ObjectResponse<AppCommand> getAppCommand(Snowflake<DiscordObject>::RawType applicationID, Snowflake<Server> serverID, Snowflake<AppCommand> commandID, RequestSettings<ObjectResponse<AppCommand>> settings = {});
BoolResponse deleteAppCommand(Snowflake<DiscordObject>::RawType applicationID, Snowflake<Server> serverID, Snowflake<AppCommand> commandID, RequestSettings<BoolResponse> settings = {});
BoolResponse bulkOverwriteServerAppCommands(Snowflake<DiscordObject>::RawType applicationID, Snowflake<Server> serverID, std::vector<AppCommand> commands, RequestSettings<BoolResponse> settings = {});
//stage instances
ObjectResponse<User> createStageInstance(Snowflake<Channel> channelID, std::string topic, StageInstance::PrivacyLevel privacyLevel = StageInstance::PrivacyLevel::NotSet, RequestSettings<ObjectResponse<User>> settings = {});
@@ -654,7 +658,14 @@ namespace SleepyDiscord {
void processMessage(const WebSocketMessage message) override;
void processCloseCode(const int16_t code) override;
void heartbeat();
void sendHeartbeat();
void sendHeartbeat() {
const auto heartbeat = generateHeatbeat(lastSReceived);
const nonstd::string_view message(heartbeat.buffer.data(), heartbeat.length);
//to do switch sendL to string_view
sendL(std::string{ message.data(), message.length() });
wasHeartbeatAcked = false;
onHeartbeat();
}
void resetHeartbeatValues();
inline std::string getToken() { return *token.get(); }
inline void setToken(const std::string& value) { token = std::unique_ptr<std::string>(new std::string(value)); }
@@ -762,7 +773,7 @@ namespace SleepyDiscord {
int8_t useTrasportConnection = static_cast<int8_t>(-1); //-1 for not set
template<class Options>
std::string createApplicationCommandBody(std::string name, std::string description, Options& options, const bool allOptional = false) {
std::string createApplicationCommandBody(std::string name, std::string description, Options& options, const bool defaultPermission, AppCommand::Type type, const bool allOptional = false) {
rapidjson::Document doc;
doc.SetObject();
auto& allocator = doc.GetAllocator();
@@ -770,6 +781,10 @@ namespace SleepyDiscord {
doc.AddMember("name", rapidjson::Value::StringRefType{ name.c_str(), name.length() }, allocator);
if (allOptional || !description.empty())
doc.AddMember("description", rapidjson::Value::StringRefType{ description.c_str(), description.length() }, allocator);
if (allOptional || defaultPermission != true) //default is true
doc.AddMember("default_permission", defaultPermission, allocator);
if (allOptional || type != AppCommand::Type::NONE)
doc.AddMember("type", static_cast<GetEnumBaseType<AppCommand::Type>::Value>(type), allocator);
if (!options.empty()) {
rapidjson::Value arr{ rapidjson::Type::kArrayType };
for (auto& option : options) {
@@ -852,6 +867,70 @@ namespace SleepyDiscord {
}
);
}
//The number 10 comes from the largest unsigned int being 10 digits long
using DBuffer = std::array<char, 10>;
//The number 18 comes from 1 plus the length of {\"op\":1,\"d\":}
using HeartbeatBuffer = std::array<char, 18 + std::tuple_size<DBuffer>::value>;
struct Heartbeat {
HeartbeatBuffer buffer;
std::size_t length;
};
//no reason for this to be so optimized because I just felt like it one day
#ifdef __cpp_lib_array_constexpr
constexpr
#endif
Heartbeat generateHeatbeat(const unsigned int lastSReceived) {
DBuffer dBuffer{};
//can't find a number to std array so a custom one is made here
auto reverseNext = dBuffer.end();
auto trunc = lastSReceived;
do {
reverseNext -= 1;
*reverseNext = '0' + (trunc % 10);
trunc /= 10;
} while (trunc != 0);
const nonstd::string_view d{ &(*reverseNext),
std::size_t(dBuffer.end() - reverseNext) };
#define SLEEPY_HEARTBEAT_START "{"\
"\"op\":1,"\
"\"d\":"
#define SLEEPY_HEARTBEAT_END "}"
constexpr auto startBuffer = SLEEPY_HEARTBEAT_START;
constexpr auto endBuffer = SLEEPY_HEARTBEAT_END;
constexpr auto startLength = sizeof(SLEEPY_HEARTBEAT_START) - 1;
//this works because char is one btye
constexpr auto endLength = sizeof(SLEEPY_HEARTBEAT_END) - 1;
constexpr auto start = nonstd::string_view{ startBuffer, startLength };
constexpr auto end = nonstd::string_view{ endBuffer, endLength };
const std::array<nonstd::string_view, 3> toConcat{ {
start, d, end
} };
Heartbeat heartbeat = {};
HeartbeatBuffer& heartbeatBuffer = heartbeat.buffer;
std::size_t& index = heartbeat.length;
for (const auto& source : toConcat)
{
auto dest = heartbeatBuffer.begin() + index;
//memcpy not avaiable at compile time
for (std::size_t index = 0; index < source.length(); index += 1) {
dest[index] = source[index];
}
index += source.length();
}
return heartbeat;
}
};
template<> struct BaseDiscordClient::RequestModeType<Async> : BaseDiscordClient::RawRequestModeTypeHelper<Async, void> {

View File

@@ -41,6 +41,7 @@ namespace SleepyDiscord {
UNKNOWN_ENCRYPTION_MODE = 4016, //We didn't recognize your encryption.
//Sleepy Errors
RECONNECTING = 4900,
CONNECT_FAILED = 5000, //Failed to connect to the Discord api after 4 trys
EVENT_UNKNOWN = 5001, //Unexpected or unknown event occurred
GATEWAY_FAILED = 5002, //Could not get the gateway

View File

@@ -20,7 +20,8 @@ namespace SleepyDiscord {
public:
Webhook() = default;
Webhook(const json::Value & json);
Webhook(const nonstd::string_view & rawJSON);
Webhook(const nonstd::string_view& json) :
Webhook(json::fromJSON<Webhook>(json)) {}
enum WebhookType {
INCOMING = 1,

View File

@@ -397,7 +397,10 @@ namespace SleepyDiscord {
heartbeatInterval = 0;
disconnectWebsocket(status);
if (consecutiveReconnectsCount == 10) getTheGateway();
//it's recomemeded to get the gateway again after many reconnection tries
// but the chance of the gateway being different is very low so this line is
// commmented out as it seems to cause issues
//if (consecutiveReconnectsCount % 16 == 10 || theGateway.empty()) getTheGateway();
if (reconnectTimer.isValid())
reconnectTimer.stop();
reconnectTimer = schedule([this]() {
@@ -762,83 +765,6 @@ namespace SleepyDiscord {
heart = schedule(&BaseDiscordClient::heartbeat, heartbeatInterval);
}
//The number 10 comes from the largest unsigned int being 10 digits long
using DBuffer = std::array<char, 10>;
//The number 18 comes from 1 plus the length of {\"op\":1,\"d\":}
using HeartbeatBuffer = std::array<char, 18 + std::tuple_size<DBuffer>::value>;
struct Heartbeat {
HeartbeatBuffer buffer;
std::size_t length;
};
//please only call during compile time
constexpr std::size_t length(const char* str) {
return *str ? 1 + length(str + 1) : 0;
}
//no reason for this to be so optimized but I just felt like it one day
#ifdef __cpp_lib_array_constexpr
constexpr
#endif
Heartbeat generateHeatbeat(const unsigned int lastSReceived) {
DBuffer dBuffer {};
//can't find a number to std array so a custom one is made here
auto reverseNext = dBuffer.end();
auto trunc = lastSReceived;
do {
reverseNext -= 1;
*reverseNext = '0' + (trunc % 10);
trunc /= 10;
} while (trunc != 0);
const nonstd::string_view d{&(*reverseNext),
std::size_t(dBuffer.end() - reverseNext)};
constexpr auto startBuffer =
"{"
"\"op\":1,"
"\"d\":";
const
constexpr auto endBuffer =
"}";
constexpr auto startLength = length(startBuffer);
//this works because char is one btye
constexpr auto endLength = length(endBuffer);
constexpr auto start = nonstd::string_view{startBuffer, startLength};
constexpr auto end = nonstd::string_view{endBuffer, endLength};
const std::array<nonstd::string_view, 3> toConcat {{
start, d, end
}};
Heartbeat heartbeat = {};
HeartbeatBuffer& heartbeatBuffer = heartbeat.buffer;
std::size_t& index = heartbeat.length;
for (const auto& source : toConcat)
{
auto dest = heartbeatBuffer.begin() + index;
//memcpy not avaiable at compile time
for (std::size_t index = 0; index < source.length(); index += 1) {
dest[index] = source[index];
}
index += source.length();
}
return heartbeat;
}
void BaseDiscordClient::sendHeartbeat() {
const auto heartbeat = generateHeatbeat(lastSReceived);
const nonstd::string_view message(heartbeat.buffer.data(), heartbeat.length);
//to do switch sendL to string_view
sendL(std::string{message.data(), message.length()});
wasHeartbeatAcked = false;
onHeartbeat();
}
//
//Voice
//

View File

@@ -84,6 +84,7 @@ namespace SleepyDiscord {
case UNKNOWN_ENCRYPTION_MODE: onError(code, "We didn't recognize your encryption." ); break;
//Sleepy Errors
case RECONNECTING : onError(code, "Reconnect function used or bad connection detected" ); break;
case CONNECT_FAILED : onError(code, "Failed to connect to the Discord api after 4 trys" ); break;
case EVENT_UNKNOWN : onError(code, "Unexpected or unknown event occurred" ); break;
case GATEWAY_FAILED : onError(code, "Could not get the gateway" ); break;