1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 08:47:17 +01:00

Compare commits

..

6 Commits

Author SHA1 Message Date
Sandu Liviu Catalin
f8ebb0e2b1 Update Net.hpp 2021-09-10 22:44:55 +03:00
Sandu Liviu Catalin
f49452c165 Remove SLongInt and ULongInt helper types.
Fix a bunch of bugs and mistakes discovered along the way.
2021-09-10 21:27:28 +03:00
Sandu Liviu Catalin
60467782e3 Make Discord voice support explicit. 2021-09-10 20:19:25 +03:00
Sandu Liviu Catalin
4f70f89b78 Basic Discord library layout.
Foundation for the discord library bindings. To be gradually exposed to the script.
2021-09-10 20:13:42 +03:00
Sandu Liviu Catalin
f6cb8ff8a1 Update SqBase.hpp 2021-09-10 20:08:23 +03:00
Sandu Liviu Catalin
4876b37f7f Officially declare the plugin as 64-bit only.
Due to various limitations, this plug-in no longer compiles on 32-bit platforms.
2021-09-10 20:06:25 +03:00
162 changed files with 60769 additions and 2121 deletions

View File

@ -1,14 +1,21 @@
cmake_minimum_required(VERSION 3.7)
project(SqMod)
# This plug-in only works on 64-bit
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
message(FATAL_ERROR "SqMod does not support 32-but platforms anymore.")
endif()
# Tell CMake where to find our scripts
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/vendor/POCO/cmake)
# Several plugin options
option(ENABLE_API21 "Build for 2.1 API." OFF)
option(ENABLE_DISCORD "Enable built-in Discord support" ON)
option(ENABLE_DISCORD_VOICE "Enable voice support in Discord library" OFF)
option(ENABLE_OFFICIAL "Enable compatibility with official legacy plug-in" ON)
option(FORCE_32BIT_BIN "Create a 32-bit executable binary if the compiler defaults to 64-bit." OFF)
#option(FORCE_32BIT_BIN "Create a 32-bit executable binary if the compiler defaults to 64-bit." OFF)
# This option should only be available in certain conditions
if(WIN32 AND MINGW)
option(COPY_DEPENDENCIES "Copy deppendent DLLs into the deps folder." OFF)

View File

@ -78,7 +78,6 @@ add_library(SqModule MODULE SqBase.hpp Main.cpp
Library/MMDB.cpp Library/MMDB.hpp
Library/Net.cpp Library/Net.hpp
Library/Numeric.cpp Library/Numeric.hpp
Library/Numeric/Long.cpp Library/Numeric/Long.hpp
Library/Numeric/Math.cpp Library/Numeric/Math.hpp
Library/Numeric/Random.cpp Library/Numeric/Random.hpp
Library/String.cpp Library/String.hpp
@ -133,6 +132,12 @@ if(WIN32 OR MINGW)
endif()
# Link to base libraries
target_link_libraries(SqModule Squirrel fmt::fmt SimpleINI TinyDir xxHash ConcurrentQueue SAJSON CPR PUGIXML CivetWeb maxminddb libzmq-static)
# Enable built-in Discord support
if(ENABLE_DISCORD)
target_link_libraries(SqModule DPP)
target_compile_definitions(SqModule PRIVATE VCMP_ENABLE_DISCORD=1)
target_sources(SqModule PRIVATE Library/DPP.cpp Library/DPP.hpp Library/DPPEv.cpp Library/DPPEv.hpp Library/DPPTy.cpp Library/DPPTy.hpp)
endif()
# Link to POCO libraries
target_link_libraries(SqModule Poco::Foundation Poco::Crypto Poco::Data Poco::Net Poco::JSON Poco::XML)
# Does POCO have SQLite support?

View File

@ -49,6 +49,9 @@ extern void TerminateRoutines();
extern void TerminateCommands();
extern void TerminateSignals();
extern void TerminateNet();
#ifdef VCMP_ENABLE_DISCORD
extern void TerminateDPP();
#endif
extern void TerminatePocoNet();
extern void TerminatePocoData();
@ -549,6 +552,11 @@ void Core::Terminate(bool shutdown)
// Release announcers
AnnounceTerminate();
cLogDbg(m_Verbosity >= 1, "Announcer terminated");
// Release DPP
#ifdef VCMP_ENABLE_DISCORD
TerminateDPP();
cLogDbg(m_Verbosity >= 1, "Discord terminated");
#endif
// Release network
TerminateNet();
cLogDbg(m_Verbosity >= 1, "Network terminated");

View File

@ -2,7 +2,6 @@
#include "Core/Common.hpp"
#include "Core/Buffer.hpp"
#include "Core/Utility.hpp"
#include "Library/Numeric/Long.hpp"
// ------------------------------------------------------------------------------------------------
#include <cerrno>
@ -313,46 +312,10 @@ SQInteger PopStackInteger(HSQUIRRELVM vm, SQInteger idx)
case OT_TABLE:
case OT_CLASS:
case OT_USERDATA:
{
return sq_getsize(vm, idx);
}
case OT_INSTANCE:
{
SQUserPointer tag;
// Attempt to retrieve the type tag
if (SQ_FAILED(sq_gettypetag(vm, -1, &tag)))
{
break;
}
// Is the instance SLongInt? (signed long)
else if (static_cast< AbstractStaticClassData * >(tag) == StaticClassTypeTag< SLongInt >::Get())
{
try
{
return ConvTo< SQInteger >::From(Var< const SLongInt & >(vm, idx).value.GetNum());
}
catch (...)
{
// Just ignore it...
}
}
// Is the instance ULongInt? (unsigned long)
else if (static_cast< AbstractStaticClassData * >(tag) == StaticClassTypeTag< ULongInt >::Get())
{
try
{
return ConvTo< SQInteger >::From(Var< const ULongInt & >(vm, idx).value.GetNum());
}
catch (...)
{
// Just ignore it...
}
}
else
{
// Attempt to get the size of the instance as a fall back
return sq_getsize(vm, idx);
}
// Attempt to get the size of the instance as a fall back
return sq_getsize(vm, idx);
}
default: break;
}
@ -406,41 +369,8 @@ SQFloat PopStackFloat(HSQUIRRELVM vm, SQInteger idx)
}
case OT_INSTANCE:
{
SQUserPointer tag;
// Attempt to retrieve the type tag
if (SQ_FAILED(sq_gettypetag(vm, -1, &tag)))
{
break;
}
// Is the instance SLongInt? (signed long)
else if (static_cast< AbstractStaticClassData * >(tag) == StaticClassTypeTag< SLongInt >::Get())
{
try
{
return ConvTo< SQFloat >::From(Var< const SLongInt & >(vm, idx).value.GetNum());
}
catch (...)
{
// Just ignore it...
}
}
// Is the instance ULongInt? (unsigned long)
else if (static_cast< AbstractStaticClassData * >(tag) == StaticClassTypeTag< ULongInt >::Get())
{
try
{
return ConvTo< SQFloat >::From(Var< const ULongInt & >(vm, idx).value.GetNum());
}
catch (...)
{
// Just ignore it...
}
}
else
{
// Attempt to get the size of the instance as a fall back
return ConvTo< SQFloat >::From(sq_getsize(vm, idx));
}
// Attempt to get the size of the instance as a fall back
return ConvTo< SQFloat >::From(sq_getsize(vm, idx));
}
default: break;
}

View File

@ -3,7 +3,6 @@
#include "Library/Chrono/Date.hpp"
#include "Library/Chrono/Timer.hpp"
#include "Library/Chrono/Timestamp.hpp"
#include "Library/Numeric/Long.hpp"
#include "Core/Utility.hpp"
// ------------------------------------------------------------------------------------------------
@ -243,33 +242,38 @@ int64_t Chrono::DateRangeToSeconds(uint16_t _year, uint8_t _month, uint8_t _day,
}
// ------------------------------------------------------------------------------------------------
static SLongInt SqGetEpochTimeMicro()
static SQRESULT SqGetEpochTimeMicro(HSQUIRRELVM vm)
{
return SLongInt(Chrono::GetEpochTimeMicro());
sq_pushinteger(vm, Chrono::GetEpochTimeMicro());
return 1;
}
// ------------------------------------------------------------------------------------------------
static SLongInt SqGetEpochTimeMilli()
static SQRESULT SqGetEpochTimeMilli(HSQUIRRELVM vm)
{
return SLongInt(Chrono::GetEpochTimeMilli());
sq_pushinteger(vm, Chrono::GetEpochTimeMilli());
return 1;
}
// ------------------------------------------------------------------------------------------------
static SLongInt SqGetCurrentSysTime()
static SQRESULT SqGetCurrentSysTime(HSQUIRRELVM vm)
{
return SLongInt(Chrono::GetCurrentSysTime());
sq_pushinteger(vm, Chrono::GetCurrentSysTime());
return 1;
}
// ------------------------------------------------------------------------------------------------
static SQInteger SqGetTickCount()
static SQRESULT SqGetTickCount(HSQUIRRELVM vm)
{
return ConvTo< SQInteger >::From(GetTickCount());
sq_pushinteger(vm, ConvTo< SQInteger >::From(GetTickCount()));
return 1;
}
// ------------------------------------------------------------------------------------------------
static SLongInt SqGetTickCount64()
static SQRESULT SqGetTickCount64(HSQUIRRELVM vm)
{
return SLongInt(GetTickCount64());
sq_pushinteger(vm, ConvTo< SQInteger >::From(GetTickCount64()));
return 1;
}
// ================================================================================================
@ -284,11 +288,11 @@ void Register_Chrono(HSQUIRRELVM vm)
Register_ChronoTimestamp(vm, cns);
cns
.Func(_SC("EpochMicro"), &SqGetEpochTimeMicro)
.Func(_SC("EpochMilli"), &SqGetEpochTimeMilli)
.Func(_SC("Current"), &SqGetCurrentSysTime)
.Func(_SC("TickCount"), &SqGetTickCount)
.Func(_SC("TickCount64"), &SqGetTickCount64)
.SquirrelFunc(_SC("EpochMicro"), &SqGetEpochTimeMicro)
.SquirrelFunc(_SC("EpochMilli"), &SqGetEpochTimeMilli)
.SquirrelFunc(_SC("Current"), &SqGetCurrentSysTime)
.SquirrelFunc(_SC("TickCount"), &SqGetTickCount)
.SquirrelFunc(_SC("TickCount64"), &SqGetTickCount64)
.Func(_SC("IsLeapYear"), &Chrono::IsLeapYear)
.Func(_SC("IsDateValid"), &Chrono::ValidDate)
.Func(_SC("DaysInYear"), &Chrono::DaysInYear)

View File

@ -4,7 +4,6 @@
#include "Library/Chrono/Time.hpp"
#include "Library/Chrono/Date.hpp"
#include "Library/Chrono/Datetime.hpp"
#include "Library/Numeric/Long.hpp"
// ------------------------------------------------------------------------------------------------
#include <chrono>
@ -15,13 +14,6 @@ namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMOD_DECL_TYPENAME(Typename, _SC("SqTimestamp"))
// ------------------------------------------------------------------------------------------------
Timestamp::Timestamp(const SLongInt & t)
: m_Timestamp(t.GetNum())
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
int32_t Timestamp::Cmp(const Timestamp & o) const
{
@ -52,36 +44,36 @@ void Timestamp::SetNow()
}
// ------------------------------------------------------------------------------------------------
SLongInt Timestamp::GetMicroseconds() const
SQInteger Timestamp::GetMicroseconds() const
{
return SLongInt(m_Timestamp);
return m_Timestamp;
}
// ------------------------------------------------------------------------------------------------
void Timestamp::SetMicroseconds(const SLongInt & amount)
void Timestamp::SetMicroseconds(SQInteger amount)
{
m_Timestamp = amount.GetNum();
m_Timestamp = amount;
}
// ------------------------------------------------------------------------------------------------
Timestamp & Timestamp::AddMicroseconds(const SLongInt & amount) { m_Timestamp += amount.GetNum(); return *this; }
Timestamp & Timestamp::SubMicroseconds(const SLongInt & amount) { m_Timestamp -= amount.GetNum(); return *this; }
Timestamp & Timestamp::AddMicroseconds(SQInteger amount) { m_Timestamp += amount; return *this; }
Timestamp & Timestamp::SubMicroseconds(SQInteger amount) { m_Timestamp -= amount; return *this; }
// ------------------------------------------------------------------------------------------------
SLongInt Timestamp::GetMilliseconds() const
SQInteger Timestamp::GetMilliseconds() const
{
return SLongInt(m_Timestamp / 1000L);
return m_Timestamp / 1000L;
}
// ------------------------------------------------------------------------------------------------
void Timestamp::SetMilliseconds(const SLongInt & amount)
void Timestamp::SetMilliseconds(SQInteger amount)
{
m_Timestamp = (amount.GetNum() * 1000L);
m_Timestamp = (amount * 1000L);
}
// ------------------------------------------------------------------------------------------------
Timestamp & Timestamp::AddMilliseconds(const SLongInt & amount) { m_Timestamp += (amount.GetNum() * 1000L); return *this; }
Timestamp & Timestamp::SubMilliseconds(const SLongInt & amount) { m_Timestamp -= (amount.GetNum() * 1000L); return *this; }
Timestamp & Timestamp::AddMilliseconds(SQInteger amount) { m_Timestamp += (amount * 1000L); return *this; }
Timestamp & Timestamp::SubMilliseconds(SQInteger amount) { m_Timestamp -= (amount * 1000L); return *this; }
// ------------------------------------------------------------------------------------------------
Time Timestamp::GetTime() const
@ -213,7 +205,7 @@ static Timestamp SqGetMicrosecondsRaw(int64_t amount)
}
// ------------------------------------------------------------------------------------------------
static Timestamp SqGetMicroseconds(const SLongInt & amount)
static Timestamp SqGetMicroseconds(SQInteger amount)
{
return Timestamp(amount);
}

View File

@ -40,11 +40,6 @@ public:
/* ... */
}
/* --------------------------------------------------------------------------------------------
*
*/
explicit Timestamp(const SLongInt & t);
/* --------------------------------------------------------------------------------------------
*
*/
@ -122,18 +117,18 @@ public:
/* --------------------------------------------------------------------------------------------
*
*/
SQMOD_NODISCARD SLongInt GetMicroseconds() const;
SQMOD_NODISCARD SQInteger GetMicroseconds() const;
/* --------------------------------------------------------------------------------------------
*
*/
void SetMicroseconds(const SLongInt & amount);
void SetMicroseconds(SQInteger amount);
/* --------------------------------------------------------------------------------------------
*
*/
Timestamp & AddMicroseconds(const SLongInt & amount);
Timestamp & SubMicroseconds(const SLongInt & amount);
Timestamp & AddMicroseconds(SQInteger amount);
Timestamp & SubMicroseconds(SQInteger amount);
/* --------------------------------------------------------------------------------------------
*
@ -160,18 +155,18 @@ public:
/* --------------------------------------------------------------------------------------------
*
*/
SQMOD_NODISCARD SLongInt GetMilliseconds() const;
SQMOD_NODISCARD SQInteger GetMilliseconds() const;
/* --------------------------------------------------------------------------------------------
*
*/
void SetMilliseconds(const SLongInt & amount);
void SetMilliseconds(SQInteger amount);
/* --------------------------------------------------------------------------------------------
*
*/
Timestamp & AddMilliseconds(const SLongInt & amount);
Timestamp & SubMilliseconds(const SLongInt & amount);
Timestamp & AddMilliseconds(SQInteger amount);
Timestamp & SubMilliseconds(SQInteger amount);
/* --------------------------------------------------------------------------------------------
*
@ -244,7 +239,7 @@ public:
*/
SQMOD_NODISCARD SQFloat GetMinutesF() const
{
return SQFloat(m_Timestamp / 60000000.0);
return SQFloat(m_Timestamp) / 60000000.0;
}
/* --------------------------------------------------------------------------------------------
@ -288,7 +283,7 @@ public:
*/
SQMOD_NODISCARD SQFloat GetHoursF() const
{
return SQFloat(m_Timestamp / 3600000000.0);
return SQFloat(m_Timestamp) / 3600000000.0;
}
/* --------------------------------------------------------------------------------------------
@ -332,7 +327,7 @@ public:
*/
SQMOD_NODISCARD SQFloat GetDaysF() const
{
return SQFloat(m_Timestamp / 86400000000.0);
return SQFloat(m_Timestamp) / 86400000000.0;
}
/* --------------------------------------------------------------------------------------------
@ -376,7 +371,7 @@ public:
*/
SQMOD_NODISCARD SQFloat GetYearsF() const
{
return SQFloat(m_Timestamp / 31557600000000.0);
return SQFloat(m_Timestamp) / 31557600000000.0;
}
/* --------------------------------------------------------------------------------------------
@ -466,7 +461,7 @@ public:
/* --------------------------------------------------------------------------------------------
*
*/
std::time_t ToTimeT() const;
SQMOD_NODISCARD std::time_t ToTimeT() const;
private:

800
module/Library/DPP.cpp Normal file
View File

@ -0,0 +1,800 @@
// ------------------------------------------------------------------------------------------------
#include "Library/DPP.hpp"
#include "Core/Signal.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstdio>
// ------------------------------------------------------------------------------------------------
#include <sqratConst.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMOD_DECL_TYPENAME(SqDppCluster, _SC("SqDppCluster"))
// ------------------------------------------------------------------------------------------------
void TerminateDPP()
{
// Go over all clusters and try to terminate them
for (DpCluster * inst = DpCluster::sHead; inst && inst->mNext != DpCluster::sHead; inst = inst->mNext)
{
inst->Terminate(); // Terminate() the cluster
}
}
// ------------------------------------------------------------------------------------------------
void ProcessDPP()
{
// Go over all clusters and allow them to process data
for (DpCluster * inst = DpCluster::sHead; inst && inst->mNext != DpCluster::sHead; inst = inst->mNext)
{
inst->Process();
}
}
// ------------------------------------------------------------------------------------------------
extern void Register_DPPTy(HSQUIRRELVM vm, Table & ns);
extern void Register_DPPEv(HSQUIRRELVM vm, Table & ns);
// ================================================================================================
void Register_DPP(HSQUIRRELVM vm)
{
Table ns(vm);
// --------------------------------------------------------------------------------------------
{
Table ens(vm);
Register_DPPEv(vm, ens);
ns.Bind(_SC("Events"), ens);
}
// Register base types
Register_DPPTy(vm, ns);
// --------------------------------------------------------------------------------------------
ns.Bind(_SC("Cluster"),
Class< DpCluster, NoCopy< DpCluster > >(vm, SqDppCluster::Str)
// Constructors
.Ctor< StackStrF & >()
.Ctor< StackStrF &, SQInteger >()
.Ctor< StackStrF &, SQInteger, SQInteger >()
.Ctor< StackStrF &, SQInteger, SQInteger, SQInteger >()
.Ctor< StackStrF &, SQInteger, SQInteger, SQInteger, SQInteger >()
.Ctor< StackStrF &, SQInteger, SQInteger, SQInteger, SQInteger, bool >()
.Ctor< StackStrF &, SQInteger, SQInteger, SQInteger, SQInteger, bool, const DpCachePolicy & >()
// Meta-methods
.SquirrelFunc(_SC("_typename"), &SqDppCluster::Fn)
// Member Properties
.Prop(_SC("On"), &DpCluster::GetEvents)
.Prop(_SC("UpTime"), &DpCluster::UpTime)
// Member Methods
.Func(_SC("Start"), &DpCluster::Start)
.Func(_SC("Log"), &DpCluster::Log)
.Func(_SC("GetDmChannel"), &DpCluster::GetDmChannel)
.Func(_SC("SetDmChannel"), &DpCluster::SetDmChannel)
.Func(_SC("SetPresence"), &DpCluster::SetPresence)
.Func(_SC("EnableEvent"), &DpCluster::EnableEvent)
.Func(_SC("DisableEvent"), &DpCluster::DisableEvent)
);
// --------------------------------------------------------------------------------------------
ns.Func(_SC("HasVoice"), dpp::utility::has_voice);
RootTable(vm).Bind(_SC("SqDiscord"), ns);
}
// ------------------------------------------------------------------------------------------------
SQMOD_NODISCARD LightObj EventToScriptObject(uint8_t type, uintptr_t data);
void EventInvokeCleanup(uint8_t type, uintptr_t data);
// ------------------------------------------------------------------------------------------------
void DpCluster::Process(bool force)
{
// Is there a valid connection?
if (!mC && !force)
{
return; // No point in going forward
}
DpInternalEvent event;
// Retrieve each event individually and process it
for (size_t count = mQueue.size_approx(), n = 0; n <= count; ++n)
{
// Try to get an event from the queue
if (mQueue.try_dequeue(event))
{
// Fetch the type of event
const auto type = event.GetType();
// Fetch the event itself
const auto data = event.GetData();
// Is this a valid event and is anyone listening to it?
if (event.mData == 0 || mEvents[type].first == nullptr || mEvents[type].first->IsEmpty())
{
continue; // Move on
}
// Transform the event instance into a script object
LightObj obj = EventToScriptObject(type, data);
// Allow the script to take ownership of the event instance now
event.Reset();
// Forward the call to the associated signal
(*mEvents[type].first)(obj);
// Allow the event instance to clean itself
EventInvokeCleanup(type, data);
}
}
}
/* ================================================================================================
* Event handlers.
*/
void DpCluster::OnVoiceStateUpdate(const dpp::voice_state_update_t & ev)
{
mQueue.enqueue(DpInternalEvent(DpEventID::VoiceStateUpdate, new DpVoiceStateUpdateEvent(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnLog(const dpp::log_t & ev)
{
mQueue.enqueue(DpInternalEvent(DpEventID::Log, new DpLogEvent(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnGuildJoinRequestDelete(const dpp::guild_join_request_delete_t & ev)
{
mQueue.enqueue(DpInternalEvent(DpEventID::GuildJoinRequestDelete, new DpGuildJoinRequestDeleteEvent(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnInteractionCreate(const dpp::interaction_create_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::InteractionCreate, new dpp::interaction_create_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnButtonClick(const dpp::button_click_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::ButtonClick, new dpp::button_click_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnSelectClick(const dpp::select_click_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::SelectClick, new dpp::select_click_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnGuildDelete(const dpp::guild_delete_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::GuildDelete, new dpp::guild_delete_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnChannelDelete(const dpp::channel_delete_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::ChannelDelete, new dpp::channel_delete_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnChannelUpdate(const dpp::channel_update_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::ChannelUpdate, new dpp::channel_update_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnReady(const dpp::ready_t & ev)
{
mQueue.enqueue(DpInternalEvent(DpEventID::Ready, new DpReadyEvent(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnMessageDelete(const dpp::message_delete_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::MessageDelete, new dpp::message_delete_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnApplicationCommandDelete(const dpp::application_command_delete_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::ApplicationCommandDelete, new dpp::application_command_delete_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnGuildMemberRemove(const dpp::guild_member_remove_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::GuildMemberRemove, new dpp::guild_member_remove_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnApplicationCommandCreate(const dpp::application_command_create_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::ApplicationCommandCreate, new dpp::application_command_create_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnResumed(const dpp::resumed_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::Resumed, new dpp::resumed_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnGuildRoleCreate(const dpp::guild_role_create_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::GuildRoleCreate, new dpp::guild_role_create_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnTypingStart(const dpp::typing_start_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::TypingStart, new dpp::typing_start_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnMessageReactionAdd(const dpp::message_reaction_add_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::MessageReactionAdd, new dpp::message_reaction_add_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnGuildMembersChunk(const dpp::guild_members_chunk_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::GuildMembersChunk, new dpp::guild_members_chunk_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnMessageReactionRemove(const dpp::message_reaction_remove_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::MessageReactionRemove, new dpp::message_reaction_remove_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnGuildCreate(const dpp::guild_create_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::GuildCreate, new dpp::guild_create_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnChannelCreate(const dpp::channel_create_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::ChannelCreate, new dpp::channel_create_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnMessageReactionRemoveEmoji(const dpp::message_reaction_remove_emoji_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::MessageReactionRemoveEmoji, new dpp::message_reaction_remove_emoji_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnMessageDeleteBulk(const dpp::message_delete_bulk_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::MessageDeleteBulk, new dpp::message_delete_bulk_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnGuildRoleUpdate(const dpp::guild_role_update_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::GuildRoleUpdate, new dpp::guild_role_update_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnGuildRoleDelete(const dpp::guild_role_delete_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::GuildRoleDelete, new dpp::guild_role_delete_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnChannelPinsUpdate(const dpp::channel_pins_update_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::ChannelPinsUpdate, new dpp::channel_pins_update_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnMessageReactionRemoveAll(const dpp::message_reaction_remove_all_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::MessageReactionRemoveAll, new dpp::message_reaction_remove_all_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnVoiceServerUpdate(const dpp::voice_server_update_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::VoiceServerUpdate, new dpp::voice_server_update_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnGuildEmojisUpdate(const dpp::guild_emojis_update_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::GuildEmojisUpdate, new dpp::guild_emojis_update_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnGuildStickersUpdate(const dpp::guild_stickers_update_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::GuildStickersUpdate, new dpp::guild_stickers_update_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnPresenceUpdate(const dpp::presence_update_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::PresenceUpdate, new dpp::presence_update_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnWebhooksUpdate(const dpp::webhooks_update_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::WebhooksUpdate, new dpp::webhooks_update_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnGuildMemberAdd(const dpp::guild_member_add_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::GuildMemberAdd, new dpp::guild_member_add_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnInviteDelete(const dpp::invite_delete_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::InviteDelete, new dpp::invite_delete_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnGuildUpdate(const dpp::guild_update_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::GuildUpdate, new dpp::guild_update_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnGuildIntegrationsUpdate(const dpp::guild_integrations_update_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::GuildIntegrationsUpdate, new dpp::guild_integrations_update_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnGuildMemberUpdate(const dpp::guild_member_update_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::GuildMemberUpdate, new dpp::guild_member_update_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnApplicationCommandUpdate(const dpp::application_command_update_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::ApplicationCommandUpdate, new dpp::application_command_update_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnInviteCreate(const dpp::invite_create_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::InviteCreate, new dpp::invite_create_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnMessageUpdate(const dpp::message_update_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::MessageUpdate, new dpp::message_update_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnUserUpdate(const dpp::user_update_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::UserUpdate, new dpp::user_update_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnMessageCreate(const dpp::message_create_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::MessageCreate, new dpp::message_create_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnGuildBanAdd(const dpp::guild_ban_add_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::GuildBanAdd, new dpp::guild_ban_add_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnGuildBanRemove(const dpp::guild_ban_remove_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::GuildBanRemove, new dpp::guild_ban_remove_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnIntegrationCreate(const dpp::integration_create_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::IntegrationCreate, new dpp::integration_create_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnIntegrationUpdate(const dpp::integration_update_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::IntegrationUpdate, new dpp::integration_update_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnIntegrationDelete(const dpp::integration_delete_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::IntegrationDelete, new dpp::integration_delete_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnThreadCreate(const dpp::thread_create_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::ThreadCreate, new dpp::thread_create_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnThreadUpdate(const dpp::thread_update_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::ThreadUpdate, new dpp::thread_update_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnThreadDelete(const dpp::thread_delete_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::ThreadDelete, new dpp::thread_delete_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnThreadListSync(const dpp::thread_list_sync_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::ThreadListSync, new dpp::thread_list_sync_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnThreadMemberUpdate(const dpp::thread_member_update_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::ThreadMemberUpdate, new dpp::thread_member_update_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnThreadMembersUpdate(const dpp::thread_members_update_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::ThreadMembersUpdate, new dpp::thread_members_update_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnVoiceBufferSend(const dpp::voice_buffer_send_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::VoiceBufferSend, new dpp::voice_buffer_send_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnVoiceUserTalking(const dpp::voice_user_talking_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::VoiceUserTalking, new dpp::voice_user_talking_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnVoiceReady(const dpp::voice_ready_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::VoiceReady, new dpp::voice_ready_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnVoiceReceive(const dpp::voice_receive_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::VoiceReceive, new dpp::voice_receive_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnVoiceTrackMarker(const dpp::voice_track_marker_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::VoiceTrackMarker, new dpp::voice_track_marker_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnStageInstanceCreate(const dpp::stage_instance_create_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::StageInstanceCreate, new dpp::stage_instance_create_t(ev)));
}
// ------------------------------------------------------------------------------------------------
void DpCluster::OnStageInstanceDelete(const dpp::stage_instance_delete_t & ev)
{
//mQueue.enqueue(DpInternalEvent(DpEventID::StageInstanceDelete, new dpp::stage_instance_delete_t(ev)));
}
// ------------------------------------------------------------------------------------------------
DpCluster & DpCluster::EnableEvent(SQInteger id)
{
switch (id)
{
case DpEventID::VoiceStateUpdate: mC->on_voice_state_update([this](auto && e) { OnVoiceStateUpdate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::Log: mC->on_log([this](auto && e) { OnLog(std::forward< decltype(e) >(e)); }); break;
case DpEventID::GuildJoinRequestDelete: mC->on_guild_join_request_delete([this](auto && e) { OnGuildJoinRequestDelete(std::forward< decltype(e) >(e)); }); break;
case DpEventID::InteractionCreate: mC->on_interaction_create([this](auto && e) { OnInteractionCreate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::ButtonClick: mC->on_button_click([this](auto && e) { OnButtonClick(std::forward< decltype(e) >(e)); }); break;
case DpEventID::SelectClick: mC->on_select_click([this](auto && e) { OnSelectClick(std::forward< decltype(e) >(e)); }); break;
case DpEventID::GuildDelete: mC->on_guild_delete([this](auto && e) { OnGuildDelete(std::forward< decltype(e) >(e)); }); break;
case DpEventID::ChannelDelete: mC->on_channel_delete([this](auto && e) { OnChannelDelete(std::forward< decltype(e) >(e)); }); break;
case DpEventID::ChannelUpdate: mC->on_channel_update([this](auto && e) { OnChannelUpdate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::Ready: mC->on_ready([this](auto && e) { OnReady(std::forward< decltype(e) >(e)); }); break;
case DpEventID::MessageDelete: mC->on_message_delete([this](auto && e) { OnMessageDelete(std::forward< decltype(e) >(e)); }); break;
case DpEventID::ApplicationCommandDelete: mC->on_application_command_delete([this](auto && e) { OnApplicationCommandDelete(std::forward< decltype(e) >(e)); }); break;
case DpEventID::GuildMemberRemove: mC->on_guild_member_remove([this](auto && e) { OnGuildMemberRemove(std::forward< decltype(e) >(e)); }); break;
case DpEventID::ApplicationCommandCreate: mC->on_application_command_create([this](auto && e) { OnApplicationCommandCreate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::Resumed: mC->on_resumed([this](auto && e) { OnResumed(std::forward< decltype(e) >(e)); }); break;
case DpEventID::GuildRoleCreate: mC->on_guild_role_create([this](auto && e) { OnGuildRoleCreate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::TypingStart: mC->on_typing_start([this](auto && e) { OnTypingStart(std::forward< decltype(e) >(e)); }); break;
case DpEventID::MessageReactionAdd: mC->on_message_reaction_add([this](auto && e) { OnMessageReactionAdd(std::forward< decltype(e) >(e)); }); break;
case DpEventID::GuildMembersChunk: mC->on_guild_members_chunk([this](auto && e) { OnGuildMembersChunk(std::forward< decltype(e) >(e)); }); break;
case DpEventID::MessageReactionRemove: mC->on_message_reaction_remove([this](auto && e) { OnMessageReactionRemove(std::forward< decltype(e) >(e)); }); break;
case DpEventID::GuildCreate: mC->on_guild_create([this](auto && e) { OnGuildCreate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::ChannelCreate: mC->on_channel_create([this](auto && e) { OnChannelCreate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::MessageReactionRemoveEmoji: mC->on_message_reaction_remove_emoji([this](auto && e) { OnMessageReactionRemoveEmoji(std::forward< decltype(e) >(e)); }); break;
case DpEventID::MessageDeleteBulk: mC->on_message_delete_bulk([this](auto && e) { OnMessageDeleteBulk(std::forward< decltype(e) >(e)); }); break;
case DpEventID::GuildRoleUpdate: mC->on_guild_role_update([this](auto && e) { OnGuildRoleUpdate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::GuildRoleDelete: mC->on_guild_role_delete([this](auto && e) { OnGuildRoleDelete(std::forward< decltype(e) >(e)); }); break;
case DpEventID::ChannelPinsUpdate: mC->on_channel_pins_update([this](auto && e) { OnChannelPinsUpdate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::MessageReactionRemoveAll: mC->on_message_reaction_remove_all([this](auto && e) { OnMessageReactionRemoveAll(std::forward< decltype(e) >(e)); }); break;
case DpEventID::VoiceServerUpdate: mC->on_voice_server_update([this](auto && e) { OnVoiceServerUpdate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::GuildEmojisUpdate: mC->on_guild_emojis_update([this](auto && e) { OnGuildEmojisUpdate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::GuildStickersUpdate: mC->on_guild_stickers_update([this](auto && e) { OnGuildStickersUpdate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::PresenceUpdate: mC->on_presence_update([this](auto && e) { OnPresenceUpdate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::WebhooksUpdate: mC->on_webhooks_update([this](auto && e) { OnWebhooksUpdate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::GuildMemberAdd: mC->on_guild_member_add([this](auto && e) { OnGuildMemberAdd(std::forward< decltype(e) >(e)); }); break;
case DpEventID::InviteDelete: mC->on_invite_delete([this](auto && e) { OnInviteDelete(std::forward< decltype(e) >(e)); }); break;
case DpEventID::GuildUpdate: mC->on_guild_update([this](auto && e) { OnGuildUpdate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::GuildIntegrationsUpdate: mC->on_guild_integrations_update([this](auto && e) { OnGuildIntegrationsUpdate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::GuildMemberUpdate: mC->on_guild_member_update([this](auto && e) { OnGuildMemberUpdate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::ApplicationCommandUpdate: mC->on_application_command_update([this](auto && e) { OnApplicationCommandUpdate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::InviteCreate: mC->on_invite_create([this](auto && e) { OnInviteCreate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::MessageUpdate: mC->on_message_update([this](auto && e) { OnMessageUpdate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::UserUpdate: mC->on_user_update([this](auto && e) { OnUserUpdate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::MessageCreate: mC->on_message_create([this](auto && e) { OnMessageCreate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::GuildBanAdd: mC->on_guild_ban_add([this](auto && e) { OnGuildBanAdd(std::forward< decltype(e) >(e)); }); break;
case DpEventID::GuildBanRemove: mC->on_guild_ban_remove([this](auto && e) { OnGuildBanRemove(std::forward< decltype(e) >(e)); }); break;
case DpEventID::IntegrationCreate: mC->on_integration_create([this](auto && e) { OnIntegrationCreate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::IntegrationUpdate: mC->on_integration_update([this](auto && e) { OnIntegrationUpdate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::IntegrationDelete: mC->on_integration_delete([this](auto && e) { OnIntegrationDelete(std::forward< decltype(e) >(e)); }); break;
case DpEventID::ThreadCreate: mC->on_thread_create([this](auto && e) { OnThreadCreate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::ThreadUpdate: mC->on_thread_update([this](auto && e) { OnThreadUpdate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::ThreadDelete: mC->on_thread_delete([this](auto && e) { OnThreadDelete(std::forward< decltype(e) >(e)); }); break;
case DpEventID::ThreadListSync: mC->on_thread_list_sync([this](auto && e) { OnThreadListSync(std::forward< decltype(e) >(e)); }); break;
case DpEventID::ThreadMemberUpdate: mC->on_thread_member_update([this](auto && e) { OnThreadMemberUpdate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::ThreadMembersUpdate: mC->on_thread_members_update([this](auto && e) { OnThreadMembersUpdate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::VoiceBufferSend: mC->on_voice_buffer_send([this](auto && e) { OnVoiceBufferSend(std::forward< decltype(e) >(e)); }); break;
case DpEventID::VoiceUserTalking: mC->on_voice_user_talking([this](auto && e) { OnVoiceUserTalking(std::forward< decltype(e) >(e)); }); break;
case DpEventID::VoiceReady: mC->on_voice_ready([this](auto && e) { OnVoiceReady(std::forward< decltype(e) >(e)); }); break;
case DpEventID::VoiceReceive: mC->on_voice_receive([this](auto && e) { OnVoiceReceive(std::forward< decltype(e) >(e)); }); break;
case DpEventID::VoiceTrackMarker: mC->on_voice_track_marker([this](auto && e) { OnVoiceTrackMarker(std::forward< decltype(e) >(e)); }); break;
case DpEventID::StageInstanceCreate: mC->on_stage_instance_create([this](auto && e) { OnStageInstanceCreate(std::forward< decltype(e) >(e)); }); break;
case DpEventID::StageInstanceDelete: mC->on_stage_instance_delete([this](auto && e) { OnStageInstanceDelete(std::forward< decltype(e) >(e)); }); break;
case DpEventID::Max: // Fall through
default: STHROWF("Invalid discord event identifier {}", id);
}
// Allow chaining
return *this;
}
// ------------------------------------------------------------------------------------------------
DpCluster & DpCluster::DisableEvent(SQInteger id)
{
switch (id)
{
case DpEventID::VoiceStateUpdate: mC->on_voice_state_update(std::function<void(const dpp::voice_state_update_t&)>{}); break;
case DpEventID::Log: mC->on_log(std::function<void(const dpp::log_t&)>{}); break;
case DpEventID::GuildJoinRequestDelete: mC->on_guild_join_request_delete(std::function<void(const dpp::guild_join_request_delete_t&)>{}); break;
case DpEventID::InteractionCreate: mC->on_interaction_create(std::function<void(const dpp::interaction_create_t&)>{}); break;
case DpEventID::ButtonClick: mC->on_button_click(std::function<void(const dpp::button_click_t&)>{}); break;
case DpEventID::SelectClick: mC->on_select_click(std::function<void(const dpp::select_click_t&)>{}); break;
case DpEventID::GuildDelete: mC->on_guild_delete(std::function<void(const dpp::guild_delete_t&)>{}); break;
case DpEventID::ChannelDelete: mC->on_channel_delete(std::function<void(const dpp::channel_delete_t&)>{}); break;
case DpEventID::ChannelUpdate: mC->on_channel_update(std::function<void(const dpp::channel_update_t&)>{}); break;
case DpEventID::Ready: mC->on_ready(std::function<void(const dpp::ready_t&)>{}); break;
case DpEventID::MessageDelete: mC->on_message_delete(std::function<void(const dpp::message_delete_t&)>{}); break;
case DpEventID::ApplicationCommandDelete: mC->on_application_command_delete(std::function<void(const dpp::application_command_delete_t&)>{}); break;
case DpEventID::GuildMemberRemove: mC->on_guild_member_remove(std::function<void(const dpp::guild_member_remove_t&)>{}); break;
case DpEventID::ApplicationCommandCreate: mC->on_application_command_create(std::function<void(const dpp::application_command_create_t&)>{}); break;
case DpEventID::Resumed: mC->on_resumed(std::function<void(const dpp::resumed_t&)>{}); break;
case DpEventID::GuildRoleCreate: mC->on_guild_role_create(std::function<void(const dpp::guild_role_create_t&)>{}); break;
case DpEventID::TypingStart: mC->on_typing_start(std::function<void(const dpp::typing_start_t&)>{}); break;
case DpEventID::MessageReactionAdd: mC->on_message_reaction_add(std::function<void(const dpp::message_reaction_add_t&)>{}); break;
case DpEventID::GuildMembersChunk: mC->on_guild_members_chunk(std::function<void(const dpp::guild_members_chunk_t&)>{}); break;
case DpEventID::MessageReactionRemove: mC->on_message_reaction_remove(std::function<void(const dpp::message_reaction_remove_t&)>{}); break;
case DpEventID::GuildCreate: mC->on_guild_create(std::function<void(const dpp::guild_create_t&)>{}); break;
case DpEventID::ChannelCreate: mC->on_channel_create(std::function<void(const dpp::channel_create_t&)>{}); break;
case DpEventID::MessageReactionRemoveEmoji: mC->on_message_reaction_remove_emoji(std::function<void(const dpp::message_reaction_remove_emoji_t&)>{}); break;
case DpEventID::MessageDeleteBulk: mC->on_message_delete_bulk(std::function<void(const dpp::message_delete_bulk_t&)>{}); break;
case DpEventID::GuildRoleUpdate: mC->on_guild_role_update(std::function<void(const dpp::guild_role_update_t&)>{}); break;
case DpEventID::GuildRoleDelete: mC->on_guild_role_delete(std::function<void(const dpp::guild_role_delete_t&)>{}); break;
case DpEventID::ChannelPinsUpdate: mC->on_channel_pins_update(std::function<void(const dpp::channel_pins_update_t&)>{}); break;
case DpEventID::MessageReactionRemoveAll: mC->on_message_reaction_remove_all(std::function<void(const dpp::message_reaction_remove_all_t&)>{}); break;
case DpEventID::VoiceServerUpdate: mC->on_voice_server_update(std::function<void(const dpp::voice_server_update_t&)>{}); break;
case DpEventID::GuildEmojisUpdate: mC->on_guild_emojis_update(std::function<void(const dpp::guild_emojis_update_t&)>{}); break;
case DpEventID::GuildStickersUpdate: mC->on_guild_stickers_update(std::function<void(const dpp::guild_stickers_update_t&)>{}); break;
case DpEventID::PresenceUpdate: mC->on_presence_update(std::function<void(const dpp::presence_update_t&)>{}); break;
case DpEventID::WebhooksUpdate: mC->on_webhooks_update(std::function<void(const dpp::webhooks_update_t&)>{}); break;
case DpEventID::GuildMemberAdd: mC->on_guild_member_add(std::function<void(const dpp::guild_member_add_t&)>{}); break;
case DpEventID::InviteDelete: mC->on_invite_delete(std::function<void(const dpp::invite_delete_t&)>{}); break;
case DpEventID::GuildUpdate: mC->on_guild_update(std::function<void(const dpp::guild_update_t&)>{}); break;
case DpEventID::GuildIntegrationsUpdate: mC->on_guild_integrations_update(std::function<void(const dpp::guild_integrations_update_t&)>{}); break;
case DpEventID::GuildMemberUpdate: mC->on_guild_member_update(std::function<void(const dpp::guild_member_update_t&)>{}); break;
case DpEventID::ApplicationCommandUpdate: mC->on_application_command_update(std::function<void(const dpp::application_command_update_t&)>{}); break;
case DpEventID::InviteCreate: mC->on_invite_create(std::function<void(const dpp::invite_create_t&)>{}); break;
case DpEventID::MessageUpdate: mC->on_message_update(std::function<void(const dpp::message_update_t&)>{}); break;
case DpEventID::UserUpdate: mC->on_user_update(std::function<void(const dpp::user_update_t&)>{}); break;
case DpEventID::MessageCreate: mC->on_message_create(std::function<void(const dpp::message_create_t&)>{}); break;
case DpEventID::GuildBanAdd: mC->on_guild_ban_add(std::function<void(const dpp::guild_ban_add_t&)>{}); break;
case DpEventID::GuildBanRemove: mC->on_guild_ban_remove(std::function<void(const dpp::guild_ban_remove_t&)>{}); break;
case DpEventID::IntegrationCreate: mC->on_integration_create(std::function<void(const dpp::integration_create_t&)>{}); break;
case DpEventID::IntegrationUpdate: mC->on_integration_update(std::function<void(const dpp::integration_update_t&)>{}); break;
case DpEventID::IntegrationDelete: mC->on_integration_delete(std::function<void(const dpp::integration_delete_t&)>{}); break;
case DpEventID::ThreadCreate: mC->on_thread_create(std::function<void(const dpp::thread_create_t&)>{}); break;
case DpEventID::ThreadUpdate: mC->on_thread_update(std::function<void(const dpp::thread_update_t&)>{}); break;
case DpEventID::ThreadDelete: mC->on_thread_delete(std::function<void(const dpp::thread_delete_t&)>{}); break;
case DpEventID::ThreadListSync: mC->on_thread_list_sync(std::function<void(const dpp::thread_list_sync_t&)>{}); break;
case DpEventID::ThreadMemberUpdate: mC->on_thread_member_update(std::function<void(const dpp::thread_member_update_t&)>{}); break;
case DpEventID::ThreadMembersUpdate: mC->on_thread_members_update(std::function<void(const dpp::thread_members_update_t&)>{}); break;
case DpEventID::VoiceBufferSend: mC->on_voice_buffer_send(std::function<void(const dpp::voice_buffer_send_t&)>{}); break;
case DpEventID::VoiceUserTalking: mC->on_voice_user_talking(std::function<void(const dpp::voice_user_talking_t&)>{}); break;
case DpEventID::VoiceReady: mC->on_voice_ready(std::function<void(const dpp::voice_ready_t&)>{}); break;
case DpEventID::VoiceReceive: mC->on_voice_receive(std::function<void(const dpp::voice_receive_t&)>{}); break;
case DpEventID::VoiceTrackMarker: mC->on_voice_track_marker(std::function<void(const dpp::voice_track_marker_t&)>{}); break;
case DpEventID::StageInstanceCreate: mC->on_stage_instance_create(std::function<void(const dpp::stage_instance_create_t&)>{}); break;
case DpEventID::StageInstanceDelete: mC->on_stage_instance_delete(std::function<void(const dpp::stage_instance_delete_t&)>{}); break;
case DpEventID::Max: // Fall through
default: STHROWF("Invalid discord event identifier {}", id);
}
// Allow chaining
return *this;
}
// ------------------------------------------------------------------------------------------------
void DpInternalEvent::Release()
{
// Make sure we actually manage something
if (mData == 0) return;
// Fetch the type of data
const auto type = GetType();
// Fetch the data itself
const auto data = GetData();
// Identify data type
switch (type)
{
case DpEventID::VoiceStateUpdate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::Log: delete reinterpret_cast< DpLogEvent * >(data); break;
case DpEventID::GuildJoinRequestDelete: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::InteractionCreate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ButtonClick: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::SelectClick: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildDelete: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ChannelDelete: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ChannelUpdate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::Ready: delete reinterpret_cast< DpReadyEvent * >(data); break;
case DpEventID::MessageDelete: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ApplicationCommandDelete: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildMemberRemove: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ApplicationCommandCreate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::Resumed: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildRoleCreate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::TypingStart: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::MessageReactionAdd: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildMembersChunk: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::MessageReactionRemove: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildCreate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ChannelCreate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::MessageReactionRemoveEmoji: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::MessageDeleteBulk: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildRoleUpdate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildRoleDelete: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ChannelPinsUpdate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::MessageReactionRemoveAll: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::VoiceServerUpdate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildEmojisUpdate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildStickersUpdate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::PresenceUpdate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::WebhooksUpdate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildMemberAdd: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::InviteDelete: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildUpdate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildIntegrationsUpdate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildMemberUpdate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ApplicationCommandUpdate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::InviteCreate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::MessageUpdate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::UserUpdate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::MessageCreate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildBanAdd: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildBanRemove: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::IntegrationCreate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::IntegrationUpdate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::IntegrationDelete: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ThreadCreate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ThreadUpdate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ThreadDelete: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ThreadListSync: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ThreadMemberUpdate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ThreadMembersUpdate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::VoiceBufferSend: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::VoiceUserTalking: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::VoiceReady: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::VoiceReceive: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::VoiceTrackMarker: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::StageInstanceCreate: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::StageInstanceDelete: delete reinterpret_cast< uint8_t * >(data); break;
case DpEventID::Max: // Fall through
default: LogFtl("Unrecognized discord event instance type"); assert(0); break;
}
// Forget about it
Reset();
}
// ------------------------------------------------------------------------------------------------
SQMOD_NODISCARD LightObj EventToScriptObject(uint8_t type, uintptr_t data)
{
switch (type)
{
case DpEventID::VoiceStateUpdate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::Log: return LightObj(reinterpret_cast< DpLogEvent * >(data));
case DpEventID::GuildJoinRequestDelete: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::InteractionCreate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::ButtonClick: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::SelectClick: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::GuildDelete: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::ChannelDelete: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::ChannelUpdate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::Ready: return LightObj(reinterpret_cast< DpReadyEvent * >(data));
case DpEventID::MessageDelete: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::ApplicationCommandDelete: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::GuildMemberRemove: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::ApplicationCommandCreate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::Resumed: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::GuildRoleCreate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::TypingStart: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::MessageReactionAdd: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::GuildMembersChunk: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::MessageReactionRemove: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::GuildCreate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::ChannelCreate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::MessageReactionRemoveEmoji: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::MessageDeleteBulk: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::GuildRoleUpdate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::GuildRoleDelete: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::ChannelPinsUpdate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::MessageReactionRemoveAll: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::VoiceServerUpdate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::GuildEmojisUpdate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::GuildStickersUpdate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::PresenceUpdate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::WebhooksUpdate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::GuildMemberAdd: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::InviteDelete: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::GuildUpdate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::GuildIntegrationsUpdate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::GuildMemberUpdate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::ApplicationCommandUpdate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::InviteCreate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::MessageUpdate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::UserUpdate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::MessageCreate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::GuildBanAdd: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::GuildBanRemove: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::IntegrationCreate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::IntegrationUpdate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::IntegrationDelete: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::ThreadCreate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::ThreadUpdate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::ThreadDelete: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::ThreadListSync: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::ThreadMemberUpdate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::ThreadMembersUpdate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::VoiceBufferSend: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::VoiceUserTalking: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::VoiceReady: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::VoiceReceive: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::VoiceTrackMarker: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::StageInstanceCreate: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::StageInstanceDelete: return LightObj(reinterpret_cast< uint8_t * >(data));
case DpEventID::Max: // Fall through
default: assert(0); return LightObj{};
}
}
// ------------------------------------------------------------------------------------------------
void EventInvokeCleanup(uint8_t type, uintptr_t data)
{
switch (type)
{
case DpEventID::VoiceStateUpdate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::Log: reinterpret_cast< DpLogEvent * >(data)->Cleanup(); break;
case DpEventID::GuildJoinRequestDelete: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::InteractionCreate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ButtonClick: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::SelectClick: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildDelete: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ChannelDelete: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ChannelUpdate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::Ready: reinterpret_cast< DpReadyEvent * >(data)->Cleanup(); break;
case DpEventID::MessageDelete: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ApplicationCommandDelete: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildMemberRemove: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ApplicationCommandCreate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::Resumed: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildRoleCreate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::TypingStart: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::MessageReactionAdd: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildMembersChunk: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::MessageReactionRemove: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildCreate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ChannelCreate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::MessageReactionRemoveEmoji: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::MessageDeleteBulk: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildRoleUpdate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildRoleDelete: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ChannelPinsUpdate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::MessageReactionRemoveAll: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::VoiceServerUpdate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildEmojisUpdate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildStickersUpdate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::PresenceUpdate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::WebhooksUpdate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildMemberAdd: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::InviteDelete: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildUpdate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildIntegrationsUpdate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildMemberUpdate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ApplicationCommandUpdate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::InviteCreate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::MessageUpdate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::UserUpdate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::MessageCreate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildBanAdd: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::GuildBanRemove: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::IntegrationCreate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::IntegrationUpdate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::IntegrationDelete: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ThreadCreate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ThreadUpdate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ThreadDelete: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ThreadListSync: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ThreadMemberUpdate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::ThreadMembersUpdate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::VoiceBufferSend: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::VoiceUserTalking: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::VoiceReady: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::VoiceReceive: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::VoiceTrackMarker: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::StageInstanceCreate: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::StageInstanceDelete: reinterpret_cast< uint8_t * >(data); break;
case DpEventID::Max: // Fall through
default: assert(0); return;
}
}
} // Namespace:: SqMod

428
module/Library/DPP.hpp Normal file
View File

@ -0,0 +1,428 @@
#pragma once
// ------------------------------------------------------------------------------------------------
#include "Library/DPPEv.hpp"
#include "Library/DPPTy.hpp"
#include "Core/Signal.hpp"
// ------------------------------------------------------------------------------------------------
#include <chrono>
#include <memory>
#include <functional>
// ------------------------------------------------------------------------------------------------
#include <concurrentqueue.h>
#include <dpp/dpp.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* WebSocket frame.
*/
struct DpInternalEvent
{
/* --------------------------------------------------------------------------------------------
* Event data.
*/
uint64_t mData{0llu};
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
DpInternalEvent() noexcept = default;
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
DpInternalEvent(uint64_t type, void * data) noexcept
: mData((type << 56u) | reinterpret_cast< uint64_t >(data))
{
}
/* --------------------------------------------------------------------------------------------
* Copy constructor (disabled).
*/
DpInternalEvent(const DpInternalEvent & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
DpInternalEvent(DpInternalEvent && o) noexcept
: mData(o.mData)
{
o.mData = 0llu; // Take ownership
}
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~DpInternalEvent()
{
Release();
}
/* --------------------------------------------------------------------------------------------
* Copy assignment operator (disabled).
*/
DpInternalEvent & operator = (const DpInternalEvent & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
DpInternalEvent & operator = (DpInternalEvent && o) noexcept
{
if (mData != o.mData)
{
// Release current information
Release();
// Replicate members
mData = o.mData;
// Take ownership
o.mData = 0llu;
}
return *this;
}
/* --------------------------------------------------------------------------------------------
* Forget about the managed event data.
*/
void Reset() noexcept
{
mData = 0llu;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the event type.
*/
SQMOD_NODISCARD uint8_t GetType() const noexcept
{
return static_cast< uint8_t >((mData >> 56u) & 0xFFllu);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the event data.
*/
SQMOD_NODISCARD uintptr_t GetData() const noexcept
{
return static_cast< uintptr_t >((~(0xFFllu << 56u)) & mData);
}
/* --------------------------------------------------------------------------------------------
* Release associated event data, if any.
*/
void Release();
};
/* ------------------------------------------------------------------------------------------------
* The cluster class represents a group of shards and a command queue for sending and receiving
* commands from discord via HTTP.
*/
struct DpCluster : public SqChainedInstances< DpCluster >
{
/* --------------------------------------------------------------------------------------------
* Queue of events generated from other threads.
*/
using EventQueue = moodycamel::ConcurrentQueue< DpInternalEvent >;
/* --------------------------------------------------------------------------------------------
* Managed cluster instance.
*/
std::unique_ptr< dpp::cluster > mC{nullptr};
/* --------------------------------------------------------------------------------------------
* Event queue.
*/
EventQueue mQueue{4096};
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
explicit DpCluster(StackStrF & token)
: mC(std::make_unique< dpp::cluster >(token.ToStr()))
, mQueue(4096)
{
Initialize();
}
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
DpCluster(StackStrF & token, SQInteger intents)
: mC(std::make_unique< dpp::cluster >(token.ToStr(), static_cast< uint32_t >(intents)))
, mQueue(4096)
{
Initialize();
}
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
DpCluster(StackStrF & token, SQInteger intents, SQInteger shards)
: mC(std::make_unique< dpp::cluster >(token.ToStr(), static_cast< uint32_t >(intents), static_cast< uint32_t >(shards)))
, mQueue(4096)
{
Initialize();
}
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
DpCluster(StackStrF & token, SQInteger intents, SQInteger shards, SQInteger cluster_id)
: mC(std::make_unique< dpp::cluster >(token.ToStr(), static_cast< uint32_t >(intents), static_cast< uint32_t >(shards), static_cast< uint32_t >(cluster_id)))
, mQueue(4096)
{
Initialize();
}
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
DpCluster(StackStrF & token, SQInteger intents, SQInteger shards, SQInteger cluster_id, SQInteger max_clusters)
: mC(std::make_unique< dpp::cluster >(token.ToStr(), static_cast< uint32_t >(intents), static_cast< uint32_t >(shards), static_cast< uint32_t >(cluster_id), static_cast< uint32_t >(max_clusters)))
, mQueue(4096)
{
Initialize();
}
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
DpCluster(StackStrF & token, SQInteger intents, SQInteger shards, SQInteger cluster_id, SQInteger max_clusters, bool compressed)
: mC(std::make_unique< dpp::cluster >(token.ToStr(), static_cast< uint32_t >(intents), static_cast< uint32_t >(shards), static_cast< uint32_t >(cluster_id), static_cast< uint32_t >(max_clusters), compressed))
, mQueue(4096)
{
Initialize();
}
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
DpCluster(StackStrF & token, SQInteger intents, SQInteger shards, SQInteger cluster_id, SQInteger max_clusters, bool compressed, const DpCachePolicy & cp)
: mC(std::make_unique< dpp::cluster >(token.ToStr(), static_cast< uint32_t >(intents), static_cast< uint32_t >(shards), static_cast< uint32_t >(cluster_id), static_cast< uint32_t >(max_clusters), compressed, cp.ToNative()))
, mQueue(4096)
{
Initialize();
}
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~DpCluster()
{
DropEvents();
// Forget about this instance
UnchainInstance();
}
/* --------------------------------------------------------------------------------------------
* Start the cluster, connecting all its shards. Returns once all shards are connected.
*/
DpCluster & Start()
{
LogInf("Before start...");
mC->start(true);
LogInf("After start...");
return *this;
}
/* --------------------------------------------------------------------------------------------
* Log a message to whatever log the user is using.
*/
DpCluster & Log(SQInteger severity, StackStrF & message)
{
mC->log(static_cast< dpp::loglevel >(severity), message.ToStr());
return *this;
}
/* --------------------------------------------------------------------------------------------
* Get the dm channel for a user id.
*/
SQMOD_NODISCARD dpp::snowflake GetDmChannel(dpp::snowflake user_id) const
{
return mC->get_dm_channel(static_cast< dpp::snowflake >(user_id));
}
/* --------------------------------------------------------------------------------------------
* Set the dm channel id for a user id.
*/
DpCluster & SetDmChannel(dpp::snowflake user_id, dpp::snowflake channel_id)
{
mC->set_dm_channel(user_id, channel_id);
return *this;
}
/* --------------------------------------------------------------------------------------------
* Returns the uptime of the cluster.
*/
SQMOD_NODISCARD dpp::utility::uptime UpTime() const
{
return mC->uptime();
}
/* --------------------------------------------------------------------------------------------
* Returns the uptime of the cluster.
*/
DpCluster & SetPresence(const DpPresence & p)
{
mC->set_presence(p);
return *this;
}
// --------------------------------------------------------------------------------------------
LightObj mSqEvents{}; // Table containing the emitted cluster events.
/* --------------------------------------------------------------------------------------------
* Retrieve the events table of this cluster.
*/
SQMOD_NODISCARD LightObj & GetEvents()
{
return mSqEvents;
}
/* --------------------------------------------------------------------------------------------
* Cluster signals.
*/
std::array< SignalPair, static_cast< size_t >(DpEventID::Max) > mEvents{};
/* --------------------------------------------------------------------------------------------
* Process the cluster.
*/
void Process(bool force = false);
/* --------------------------------------------------------------------------------------------
* Terminate the cluster.
*/
void Terminate()
{
// Delete the cluster instance
mC.reset();
// Release associated script objects
mSqEvents.Release();
// Release event signal objects
DropEvents();
}
/* --------------------------------------------------------------------------------------------
* Enable a certain event for the cluster.
*/
DpCluster & EnableEvent(SQInteger id);
/* --------------------------------------------------------------------------------------------
* Disable a certain event for the cluster.
*/
DpCluster & DisableEvent(SQInteger id);
private:
/* --------------------------------------------------------------------------------------------
* Initialize the cluster.
*/
void Initialize()
{
InitEvents();
// Remember this instance
ChainInstance();
}
/* --------------------------------------------------------------------------------------------
* Signal initialization.
*/
void InitEvents()
{
// Ignore the call if already initialized
if (!mSqEvents.IsNull())
{
return;
}
// Create a new table on the stack
sq_newtableex(SqVM(), 64);
// Grab the table object from the stack
mSqEvents = LightObj(-1, SqVM());
// Pop the table object from the stack
sq_pop(SqVM(), 1);
// Proceed to initializing the events
for (size_t i = 0; i < mEvents.size(); ++i)
{
InitSignalPair(mEvents[i], mSqEvents, DpEventID::NAME[i]);
}
}
/* --------------------------------------------------------------------------------------------
* Signal termination.
*/
void DropEvents()
{
for (auto & e : mEvents)
{
ResetSignalPair(e);
}
}
/* --------------------------------------------------------------------------------------------
* Event handlers.
*/
void OnVoiceStateUpdate(const dpp::voice_state_update_t & ev);
void OnLog(const dpp::log_t & ev);
void OnGuildJoinRequestDelete(const dpp::guild_join_request_delete_t & ev);
void OnInteractionCreate(const dpp::interaction_create_t & ev);
void OnButtonClick(const dpp::button_click_t & ev);
void OnSelectClick(const dpp::select_click_t & ev);
void OnGuildDelete(const dpp::guild_delete_t & ev);
void OnChannelDelete(const dpp::channel_delete_t & ev);
void OnChannelUpdate(const dpp::channel_update_t & ev);
void OnReady(const dpp::ready_t & ev);
void OnMessageDelete(const dpp::message_delete_t & ev);
void OnApplicationCommandDelete(const dpp::application_command_delete_t & ev);
void OnGuildMemberRemove(const dpp::guild_member_remove_t & ev);
void OnApplicationCommandCreate(const dpp::application_command_create_t & ev);
void OnResumed(const dpp::resumed_t & ev);
void OnGuildRoleCreate(const dpp::guild_role_create_t & ev);
void OnTypingStart(const dpp::typing_start_t & ev);
void OnMessageReactionAdd(const dpp::message_reaction_add_t & ev);
void OnGuildMembersChunk(const dpp::guild_members_chunk_t & ev);
void OnMessageReactionRemove(const dpp::message_reaction_remove_t & ev);
void OnGuildCreate(const dpp::guild_create_t & ev);
void OnChannelCreate(const dpp::channel_create_t & ev);
void OnMessageReactionRemoveEmoji(const dpp::message_reaction_remove_emoji_t & ev);
void OnMessageDeleteBulk(const dpp::message_delete_bulk_t & ev);
void OnGuildRoleUpdate(const dpp::guild_role_update_t & ev);
void OnGuildRoleDelete(const dpp::guild_role_delete_t & ev);
void OnChannelPinsUpdate(const dpp::channel_pins_update_t & ev);
void OnMessageReactionRemoveAll(const dpp::message_reaction_remove_all_t & ev);
void OnVoiceServerUpdate(const dpp::voice_server_update_t & ev);
void OnGuildEmojisUpdate(const dpp::guild_emojis_update_t & ev);
void OnGuildStickersUpdate(const dpp::guild_stickers_update_t & ev);
void OnPresenceUpdate(const dpp::presence_update_t & ev);
void OnWebhooksUpdate(const dpp::webhooks_update_t & ev);
void OnGuildMemberAdd(const dpp::guild_member_add_t & ev);
void OnInviteDelete(const dpp::invite_delete_t & ev);
void OnGuildUpdate(const dpp::guild_update_t & ev);
void OnGuildIntegrationsUpdate(const dpp::guild_integrations_update_t & ev);
void OnGuildMemberUpdate(const dpp::guild_member_update_t & ev);
void OnApplicationCommandUpdate(const dpp::application_command_update_t & ev);
void OnInviteCreate(const dpp::invite_create_t & ev);
void OnMessageUpdate(const dpp::message_update_t & ev);
void OnUserUpdate(const dpp::user_update_t & ev);
void OnMessageCreate(const dpp::message_create_t & ev);
void OnGuildBanAdd(const dpp::guild_ban_add_t & ev);
void OnGuildBanRemove(const dpp::guild_ban_remove_t & ev);
void OnIntegrationCreate(const dpp::integration_create_t & ev);
void OnIntegrationUpdate(const dpp::integration_update_t & ev);
void OnIntegrationDelete(const dpp::integration_delete_t & ev);
void OnThreadCreate(const dpp::thread_create_t & ev);
void OnThreadUpdate(const dpp::thread_update_t & ev);
void OnThreadDelete(const dpp::thread_delete_t & ev);
void OnThreadListSync(const dpp::thread_list_sync_t & ev);
void OnThreadMemberUpdate(const dpp::thread_member_update_t & ev);
void OnThreadMembersUpdate(const dpp::thread_members_update_t & ev);
void OnVoiceBufferSend(const dpp::voice_buffer_send_t & ev);
void OnVoiceUserTalking(const dpp::voice_user_talking_t & ev);
void OnVoiceReady(const dpp::voice_ready_t & ev);
void OnVoiceReceive(const dpp::voice_receive_t & ev);
void OnVoiceTrackMarker(const dpp::voice_track_marker_t & ev);
void OnStageInstanceCreate(const dpp::stage_instance_create_t & ev);
void OnStageInstanceDelete(const dpp::stage_instance_delete_t & ev);
};
} // Namespace:: SqMod

196
module/Library/DPPEv.cpp Normal file
View File

@ -0,0 +1,196 @@
// ------------------------------------------------------------------------------------------------
#include "Library/DPPEv.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstdio>
// ------------------------------------------------------------------------------------------------
#include <sqratConst.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMOD_DECL_TYPENAME(SqDppVoiceStateUpdateEventEvent, _SC("SqDppVoiceStateUpdateEventEvent"))
SQMOD_DECL_TYPENAME(SqDppGuildJoinRequestDeleteEvent, _SC("SqDppGuildJoinRequestDeleteEvent"))
SQMOD_DECL_TYPENAME(SqDppLogEvent, _SC("SqDppLogEvent"))
SQMOD_DECL_TYPENAME(SqDppReadyEvent, _SC("SqDppReadyEvent"))
// ------------------------------------------------------------------------------------------------
const std::array< const char *, static_cast< size_t >(DpEventID::Max) > DpEventID::NAME{
"VoiceStateUpdate",
"Log",
"GuildJoinRequestDelete",
"InteractionCreate",
"ButtonClick",
"SelectClick",
"GuildDelete",
"ChannelDelete",
"ChannelUpdate",
"Ready",
"MessageDelete",
"ApplicationCommandDelete",
"GuildMemberRemove",
"ApplicationCommandCreate",
"Resumed",
"GuildRoleCreate",
"TypingStart",
"MessageReactionAdd",
"GuildMembersChunk",
"MessageReactionRemove",
"GuildCreate",
"ChannelCreate",
"MessageReactionRemoveEmoji",
"MessageDeleteBulk",
"GuildRoleUpdate",
"GuildRoleDelete",
"ChannelPinsUpdate",
"MessageReactionRemoveAll",
"VoiceServerUpdate",
"GuildEmojisUpdate",
"GuildStickersUpdate",
"PresenceUpdate",
"WebhooksUpdate",
"GuildMemberAdd",
"InviteDelete",
"GuildUpdate",
"GuildIntegrationsUpdate",
"GuildMemberUpdate",
"ApplicationCommandUpdate",
"InviteCreate",
"MessageUpdate",
"UserUpdate",
"MessageCreate",
"GuildBanAdd",
"GuildBanRemove",
"IntegrationCreate",
"IntegrationUpdate",
"IntegrationDelete",
"ThreadCreate",
"ThreadUpdate",
"ThreadDelete",
"ThreadListSync",
"ThreadMemberUpdate",
"ThreadMembersUpdate",
"VoiceBufferSend",
"VoiceUserTalking",
"VoiceReady",
"VoiceReceive",
"VoiceTrackMarker",
"StageInstanceCreate",
"StageInstanceDelete"
};
// ------------------------------------------------------------------------------------------------
void Register_DPPEv(HSQUIRRELVM vm, Table & ns)
{
// --------------------------------------------------------------------------------------------
ns.Bind(_SC("VoiceStateUpdate"),
Class< DpVoiceStateUpdateEvent, NoConstructor< DpVoiceStateUpdateEvent > >(vm, SqDppVoiceStateUpdateEventEvent::Str)
// Meta-methods
.SquirrelFunc(_SC("_typename"), &SqDppVoiceStateUpdateEventEvent::Fn)
.Func(_SC("_tostring"), &DpVoiceStateUpdateEvent::GetRawEvent)
// Member Properties
.Prop(_SC("State"), &DpVoiceStateUpdateEvent::GetState)
);
// --------------------------------------------------------------------------------------------
ns.Bind(_SC("Log"),
Class< DpLogEvent, NoConstructor< DpLogEvent > >(vm, SqDppLogEvent::Str)
// Meta-methods
.SquirrelFunc(_SC("_typename"), &SqDppLogEvent::Fn)
.Func(_SC("_tostring"), &DpLogEvent::GetRawEvent)
// Member Properties
.Prop(_SC("RawEvent"), &DpLogEvent::GetRawEvent)
.Prop(_SC("Severity"), &DpLogEvent::GetSeverity)
.Prop(_SC("Message"), &DpLogEvent::GetMessage)
);
// --------------------------------------------------------------------------------------------
ns.Bind(_SC("Ready"),
Class< DpReadyEvent, NoConstructor< DpReadyEvent > >(vm, SqDppReadyEvent::Str)
// Meta-methods
.SquirrelFunc(_SC("_typename"), &SqDppReadyEvent::Fn)
.Func(_SC("_tostring"), &DpReadyEvent::GetRawEvent)
// Member Properties
.Prop(_SC("RawEvent"), &DpReadyEvent::GetRawEvent)
.Prop(_SC("SessionID"), &DpReadyEvent::GetSessionID)
.Prop(_SC("ShardID"), &DpReadyEvent::GetShardID)
);
// --------------------------------------------------------------------------------------------
ns.Bind(_SC("GuildJoinRequestDelete"),
Class< DpGuildJoinRequestDeleteEvent, NoConstructor< DpGuildJoinRequestDeleteEvent > >(vm, SqDppGuildJoinRequestDeleteEvent::Str)
// Meta-methods
.SquirrelFunc(_SC("_typename"), &SqDppGuildJoinRequestDeleteEvent::Fn)
.Func(_SC("_tostring"), &DpGuildJoinRequestDeleteEvent::GetRawEvent)
// Member Properties
.Prop(_SC("RawEvent"), &DpGuildJoinRequestDeleteEvent::GetRawEvent)
.Prop(_SC("GuildID"), &DpGuildJoinRequestDeleteEvent::GetGuildID)
.Prop(_SC("UserID"), &DpGuildJoinRequestDeleteEvent::GetUserID)
);
// --------------------------------------------------------------------------------------------
ConstTable(vm).Enum(_SC("SqDiscordEvent"), Enumeration(vm)
.Const(_SC("VoiceStateUpdate"), static_cast< SQInteger >(DpEventID::VoiceStateUpdate))
.Const(_SC("Log"), static_cast< SQInteger >(DpEventID::Log))
.Const(_SC("GuildJoinRequestDelete"), static_cast< SQInteger >(DpEventID::GuildJoinRequestDelete))
.Const(_SC("InteractionCreate"), static_cast< SQInteger >(DpEventID::InteractionCreate))
.Const(_SC("ButtonClick"), static_cast< SQInteger >(DpEventID::ButtonClick))
.Const(_SC("SelectClick"), static_cast< SQInteger >(DpEventID::SelectClick))
.Const(_SC("GuildDelete"), static_cast< SQInteger >(DpEventID::GuildDelete))
.Const(_SC("ChannelDelete"), static_cast< SQInteger >(DpEventID::ChannelDelete))
.Const(_SC("ChannelUpdate"), static_cast< SQInteger >(DpEventID::ChannelUpdate))
.Const(_SC("Ready"), static_cast< SQInteger >(DpEventID::Ready))
.Const(_SC("MessageDelete"), static_cast< SQInteger >(DpEventID::MessageDelete))
.Const(_SC("ApplicationCommandDelete"), static_cast< SQInteger >(DpEventID::ApplicationCommandDelete))
.Const(_SC("GuildMemberRemove"), static_cast< SQInteger >(DpEventID::GuildMemberRemove))
.Const(_SC("ApplicationCommandCreate"), static_cast< SQInteger >(DpEventID::ApplicationCommandCreate))
.Const(_SC("Resumed"), static_cast< SQInteger >(DpEventID::Resumed))
.Const(_SC("GuildRoleCreate"), static_cast< SQInteger >(DpEventID::GuildRoleCreate))
.Const(_SC("TypingStart"), static_cast< SQInteger >(DpEventID::TypingStart))
.Const(_SC("MessageReactionAdd"), static_cast< SQInteger >(DpEventID::MessageReactionAdd))
.Const(_SC("GuildMembersChunk"), static_cast< SQInteger >(DpEventID::GuildMembersChunk))
.Const(_SC("MessageReactionRemove"), static_cast< SQInteger >(DpEventID::MessageReactionRemove))
.Const(_SC("GuildCreate"), static_cast< SQInteger >(DpEventID::GuildCreate))
.Const(_SC("ChannelCreate"), static_cast< SQInteger >(DpEventID::ChannelCreate))
.Const(_SC("MessageReactionRemoveEmoji"), static_cast< SQInteger >(DpEventID::MessageReactionRemoveEmoji))
.Const(_SC("MessageDeleteBulk"), static_cast< SQInteger >(DpEventID::MessageDeleteBulk))
.Const(_SC("GuildRoleUpdate"), static_cast< SQInteger >(DpEventID::GuildRoleUpdate))
.Const(_SC("GuildRoleDelete"), static_cast< SQInteger >(DpEventID::GuildRoleDelete))
.Const(_SC("ChannelPinsUpdate"), static_cast< SQInteger >(DpEventID::ChannelPinsUpdate))
.Const(_SC("MessageReactionRemoveAll"), static_cast< SQInteger >(DpEventID::MessageReactionRemoveAll))
.Const(_SC("VoiceServerUpdate"), static_cast< SQInteger >(DpEventID::VoiceServerUpdate))
.Const(_SC("GuildEmojisUpdate"), static_cast< SQInteger >(DpEventID::GuildEmojisUpdate))
.Const(_SC("GuildStickersUpdate"), static_cast< SQInteger >(DpEventID::GuildStickersUpdate))
.Const(_SC("PresenceUpdate"), static_cast< SQInteger >(DpEventID::PresenceUpdate))
.Const(_SC("WebhooksUpdate"), static_cast< SQInteger >(DpEventID::WebhooksUpdate))
.Const(_SC("GuildMemberAdd"), static_cast< SQInteger >(DpEventID::GuildMemberAdd))
.Const(_SC("InviteDelete"), static_cast< SQInteger >(DpEventID::InviteDelete))
.Const(_SC("GuildUpdate"), static_cast< SQInteger >(DpEventID::GuildUpdate))
.Const(_SC("GuildIntegrationsUpdate"), static_cast< SQInteger >(DpEventID::GuildIntegrationsUpdate))
.Const(_SC("GuildMemberUpdate"), static_cast< SQInteger >(DpEventID::GuildMemberUpdate))
.Const(_SC("ApplicationCommandUpdate"), static_cast< SQInteger >(DpEventID::ApplicationCommandUpdate))
.Const(_SC("InviteCreate"), static_cast< SQInteger >(DpEventID::InviteCreate))
.Const(_SC("MessageUpdate"), static_cast< SQInteger >(DpEventID::MessageUpdate))
.Const(_SC("UserUpdate"), static_cast< SQInteger >(DpEventID::UserUpdate))
.Const(_SC("MessageCreate"), static_cast< SQInteger >(DpEventID::MessageCreate))
.Const(_SC("GuildBanAdd"), static_cast< SQInteger >(DpEventID::GuildBanAdd))
.Const(_SC("GuildBanRemove"), static_cast< SQInteger >(DpEventID::GuildBanRemove))
.Const(_SC("IntegrationCreate"), static_cast< SQInteger >(DpEventID::IntegrationCreate))
.Const(_SC("IntegrationUpdate"), static_cast< SQInteger >(DpEventID::IntegrationUpdate))
.Const(_SC("IntegrationDelete"), static_cast< SQInteger >(DpEventID::IntegrationDelete))
.Const(_SC("ThreadCreate"), static_cast< SQInteger >(DpEventID::ThreadCreate))
.Const(_SC("ThreadUpdate"), static_cast< SQInteger >(DpEventID::ThreadUpdate))
.Const(_SC("ThreadDelete"), static_cast< SQInteger >(DpEventID::ThreadDelete))
.Const(_SC("ThreadListSync"), static_cast< SQInteger >(DpEventID::ThreadListSync))
.Const(_SC("ThreadMemberUpdate"), static_cast< SQInteger >(DpEventID::ThreadMemberUpdate))
.Const(_SC("ThreadMembersUpdate"), static_cast< SQInteger >(DpEventID::ThreadMembersUpdate))
.Const(_SC("VoiceBufferSend"), static_cast< SQInteger >(DpEventID::VoiceBufferSend))
.Const(_SC("VoiceUserTalking"), static_cast< SQInteger >(DpEventID::VoiceUserTalking))
.Const(_SC("VoiceReady"), static_cast< SQInteger >(DpEventID::VoiceReady))
.Const(_SC("VoiceReceive"), static_cast< SQInteger >(DpEventID::VoiceReceive))
.Const(_SC("VoiceTrackMarker"), static_cast< SQInteger >(DpEventID::VoiceTrackMarker))
.Const(_SC("StageInstanceCreate"), static_cast< SQInteger >(DpEventID::StageInstanceCreate))
.Const(_SC("StageInstanceDelete"), static_cast< SQInteger >(DpEventID::StageInstanceDelete))
.Const(_SC("Max"), static_cast< SQInteger >(DpEventID::Max))
);
}
} // Namespace:: SqMod

383
module/Library/DPPEv.hpp Normal file
View File

@ -0,0 +1,383 @@
#pragma once
// ------------------------------------------------------------------------------------------------
#include "Library/DPPTy.hpp"
// ------------------------------------------------------------------------------------------------
#include <chrono>
#include <functional>
// ------------------------------------------------------------------------------------------------
#include <dpp/dpp.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Unique ID for each event.
*/
struct DpEventID
{
/* --------------------------------------------------------------------------------------------
* ID enumeration.
*/
enum Type
{
VoiceStateUpdate=0,
Log,
GuildJoinRequestDelete,
InteractionCreate,
ButtonClick,
SelectClick,
GuildDelete,
ChannelDelete,
ChannelUpdate,
Ready,
MessageDelete,
ApplicationCommandDelete,
GuildMemberRemove,
ApplicationCommandCreate,
Resumed,
GuildRoleCreate,
TypingStart,
MessageReactionAdd,
GuildMembersChunk,
MessageReactionRemove,
GuildCreate,
ChannelCreate,
MessageReactionRemoveEmoji,
MessageDeleteBulk,
GuildRoleUpdate,
GuildRoleDelete,
ChannelPinsUpdate,
MessageReactionRemoveAll,
VoiceServerUpdate,
GuildEmojisUpdate,
GuildStickersUpdate,
PresenceUpdate,
WebhooksUpdate,
GuildMemberAdd,
InviteDelete,
GuildUpdate,
GuildIntegrationsUpdate,
GuildMemberUpdate,
ApplicationCommandUpdate,
InviteCreate,
MessageUpdate,
UserUpdate,
MessageCreate,
GuildBanAdd,
GuildBanRemove,
IntegrationCreate,
IntegrationUpdate,
IntegrationDelete,
ThreadCreate,
ThreadUpdate,
ThreadDelete,
ThreadListSync,
ThreadMemberUpdate,
ThreadMembersUpdate,
VoiceBufferSend,
VoiceUserTalking,
VoiceReady,
VoiceReceive,
VoiceTrackMarker,
StageInstanceCreate,
StageInstanceDelete,
Max
};
/* --------------------------------------------------------------------------------------------
* String identification.
*/
static const std::array< const char *, static_cast< size_t >(Max) > NAME;
};
/* ------------------------------------------------------------------------------------------------
* Base class of an event handler.
*/
struct DpEventBase
{
/* --------------------------------------------------------------------------------------------
* Raw event text.
*/
std::string mRaw{};
/* --------------------------------------------------------------------------------------------
* Shard the event came from.
*/
dpp::discord_client * mFrom{nullptr};
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
DpEventBase() noexcept = default;
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
explicit DpEventBase(const dpp::event_dispatch_t & d) noexcept
: mRaw(d.raw_event), mFrom(d.from)
{
}
/* --------------------------------------------------------------------------------------------
* Copy constructor (disabled).
*/
DpEventBase(const DpEventBase &) noexcept = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor (disabled).
*/
DpEventBase(DpEventBase &&) noexcept = delete;
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
virtual ~DpEventBase() noexcept = default;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator (disabled).
*/
DpEventBase & operator = (const DpEventBase &) noexcept = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator (disabled).
*/
DpEventBase & operator = (DpEventBase &&) noexcept = delete;
/* --------------------------------------------------------------------------------------------
* Cleanup after the event was processed.
*/
virtual void Cleanup()
{
mFrom = nullptr;
}
};
/* ------------------------------------------------------------------------------------------------
* Voice state update event.
*/
struct DpVoiceStateUpdateEvent : public DpEventBase
{
// --------------------------------------------------------------------------------------------
dpp::voicestate mState{};
// --------------------------------------------------------------------------------------------
LightObj mSqState{};
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
explicit DpVoiceStateUpdateEvent(const dpp::voice_state_update_t & d) noexcept
: DpEventBase(d), mState(d.state), mSqState()
{
}
/* --------------------------------------------------------------------------------------------
* Validate the managed handle.
*/
void Validate() const { if (!mFrom) STHROWF("Invalid discord [Ready] event handle"); }
/* --------------------------------------------------------------------------------------------
* Validate the managed handle and retrieve a reference to it.
*/
SQMOD_NODISCARD DpVoiceStateUpdateEvent & Valid() { Validate(); return *this; }
/* --------------------------------------------------------------------------------------------
* Validate the managed handle and retrieve a const reference to it.
*/
SQMOD_NODISCARD const DpVoiceStateUpdateEvent & Valid() const { Validate(); return *this; }
/* --------------------------------------------------------------------------------------------
* Cleanup after the event was processed.
*/
void Cleanup() override
{
if (!mSqState.IsNull())
{
[[maybe_unused]] auto p = mSqState.CastI< DpVoiceState >()->mPtr.release();
// Release script resources
mSqState.Release();
}
// Allow the base to cleanup as well
DpEventBase::Cleanup();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the raw event.
*/
SQMOD_NODISCARD const std::string & GetRawEvent() const { return mRaw; }
/* --------------------------------------------------------------------------------------------
* Retrieve the voice state.
*/
SQMOD_NODISCARD LightObj & GetState()
{
if (Valid().mSqState.IsNull())
{
mSqState = LightObj{SqTypeIdentity< DpVoiceState >{}, SqVM(), &mState, false};
}
// Return the associated script object
return mSqState;
}
};
/* ------------------------------------------------------------------------------------------------
* Guild join request delete (user declined membership screening) event.
*/
struct DpGuildJoinRequestDeleteEvent : public DpEventBase
{
// --------------------------------------------------------------------------------------------
dpp::snowflake mGuildID{};
dpp::snowflake mUserID{};
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
explicit DpGuildJoinRequestDeleteEvent(const dpp::guild_join_request_delete_t & d) noexcept
: DpEventBase(d), mGuildID(d.guild_id), mUserID(d.user_id)
{
}
/* --------------------------------------------------------------------------------------------
* Validate the managed handle.
*/
void Validate() const { if (!mFrom) STHROWF("Invalid discord [GuildJoinRequestDelete] event handle"); }
/* --------------------------------------------------------------------------------------------
* Validate the managed handle and retrieve a reference to it.
*/
SQMOD_NODISCARD DpGuildJoinRequestDeleteEvent & Valid() { Validate(); return *this; }
/* --------------------------------------------------------------------------------------------
* Validate the managed handle and retrieve a const reference to it.
*/
SQMOD_NODISCARD const DpGuildJoinRequestDeleteEvent & Valid() const { Validate(); return *this; }
/* --------------------------------------------------------------------------------------------
* Cleanup after the event was processed.
*/
void Cleanup() override
{
// Allow the base to cleanup as well
DpEventBase::Cleanup();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the raw event.
*/
SQMOD_NODISCARD const std::string & GetRawEvent() const { return Valid().mRaw; }
/* --------------------------------------------------------------------------------------------
* Retrieve the guild id.
*/
SQMOD_NODISCARD dpp::snowflake GetGuildID() const { return Valid().mGuildID; }
/* --------------------------------------------------------------------------------------------
* Retrieve the user id.
*/
SQMOD_NODISCARD dpp::snowflake GetUserID() const { return Valid().mUserID; }
};
/* ------------------------------------------------------------------------------------------------
* Log message event.
*/
struct DpLogEvent : public DpEventBase
{
// --------------------------------------------------------------------------------------------
SQInteger mSeverity{0};
std::string mMessage{};
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
explicit DpLogEvent(const dpp::log_t & d) noexcept
: DpEventBase(d), mSeverity(d.severity), mMessage(d.message)
{
}
/* --------------------------------------------------------------------------------------------
* Cleanup after the event was processed.
*/
void Cleanup() override
{
// Allow the base to cleanup as well
DpEventBase::Cleanup();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the raw event.
*/
SQMOD_NODISCARD const std::string & GetRawEvent() const { return mRaw; }
/* --------------------------------------------------------------------------------------------
* Retrieve log severity.
*/
SQMOD_NODISCARD SQInteger GetSeverity() const { return mSeverity; }
/* --------------------------------------------------------------------------------------------
* Retrieve log message.
*/
SQMOD_NODISCARD const std::string & GetMessage() const { return mMessage; }
};
/* ------------------------------------------------------------------------------------------------
* Session ready event.
*/
struct DpReadyEvent : public DpEventBase
{
// --------------------------------------------------------------------------------------------
std::string mSessionID{};
uint32_t mShardID{};
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
explicit DpReadyEvent(const dpp::ready_t & d) noexcept
: DpEventBase(d)
, mSessionID(d.session_id)
, mShardID(d.shard_id)
{
}
/* --------------------------------------------------------------------------------------------
* Validate the managed handle.
*/
void Validate() const { if (!mFrom) STHROWF("Invalid discord [Ready] event handle"); }
/* --------------------------------------------------------------------------------------------
* Validate the managed handle and retrieve a reference to it.
*/
SQMOD_NODISCARD DpReadyEvent & Valid() { Validate(); return *this; }
/* --------------------------------------------------------------------------------------------
* Validate the managed handle and retrieve a const reference to it.
*/
SQMOD_NODISCARD const DpReadyEvent & Valid() const { Validate(); return *this; }
/* --------------------------------------------------------------------------------------------
* Cleanup after the event was processed.
*/
void Cleanup() override
{
// Allow the base to cleanup as well
DpEventBase::Cleanup();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the raw event.
*/
SQMOD_NODISCARD const std::string & GetRawEvent() const { return Valid().mRaw; }
/* --------------------------------------------------------------------------------------------
* Retrieve the session id.
*/
SQMOD_NODISCARD const std::string & GetSessionID() const { return Valid().mSessionID; }
/* --------------------------------------------------------------------------------------------
* Retrieve the shard id.
*/
SQMOD_NODISCARD SQInteger GetShardID() const { return static_cast< SQInteger >(Valid().mShardID); }
};
} // Namespace:: SqMod

257
module/Library/DPPTy.cpp Normal file
View File

@ -0,0 +1,257 @@
// ------------------------------------------------------------------------------------------------
#include "Library/DPPTy.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstdio>
// ------------------------------------------------------------------------------------------------
#include <sqratConst.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMOD_DECL_TYPENAME(SqDppCachePolicy, _SC("SqDppCachePolicy"))
SQMOD_DECL_TYPENAME(SqDppUptime, _SC("SqDppUptime"))
SQMOD_DECL_TYPENAME(SqDppIconHash, _SC("SqDppIconHash"))
SQMOD_DECL_TYPENAME(SqDppActivity, _SC("SqDppActivity"))
SQMOD_DECL_TYPENAME(SqDppPresence, _SC("SqDppPresence"))
SQMOD_DECL_TYPENAME(SqDppVoiceState, _SC("SqDppVoiceState"))
SQMOD_DECL_TYPENAME(SqDppGuild, _SC("SqDppGuild"))
// ------------------------------------------------------------------------------------------------
void Register_DPPConst(HSQUIRRELVM vm, Table & ns);
// ------------------------------------------------------------------------------------------------
void Register_DPPTy(HSQUIRRELVM vm, Table & ns)
{
Register_DPPConst(vm, ns);
// --------------------------------------------------------------------------------------------
ns.Bind(_SC("Uptime"),
Class< dpp::utility::uptime >(vm, SqDppUptime::Str)
// Constructors
.Ctor()
// Meta-methods
.SquirrelFunc(_SC("_typename"), &SqDppUptime::Fn)
.Func(_SC("_tostring"), &dpp::utility::uptime::to_string)
// Member Variables
.Var(_SC("Days"), &dpp::utility::uptime::days)
.Var(_SC("Hours"), &dpp::utility::uptime::hours)
.Var(_SC("Minutes"), &dpp::utility::uptime::mins)
.Var(_SC("Seconds"), &dpp::utility::uptime::secs)
// Member Methods
.Func(_SC("ToSeconds"), &dpp::utility::uptime::to_secs)
.Func(_SC("ToMilliseconds"), &dpp::utility::uptime::to_msecs)
);
// --------------------------------------------------------------------------------------------
ns.Bind(_SC("IconHash"),
Class< dpp::utility::iconhash >(vm, SqDppIconHash::Str)
// Constructors
.Ctor()
.Ctor< const std::string & >()
// Meta-methods
.SquirrelFunc(_SC("_typename"), &SqDppIconHash::Fn)
.Func(_SC("_tostring"), &dpp::utility::iconhash::to_string)
// Member Variables
.Var(_SC("High"), &dpp::utility::iconhash::first)
.Var(_SC("Low"), &dpp::utility::iconhash::second)
// Member Methods
.Func(_SC("Set"), &dpp::utility::iconhash::set)
);
// --------------------------------------------------------------------------------------------
ns.Bind(_SC("CachePolicy"),
Class< DpCachePolicy >(vm, SqDppCachePolicy::Str)
// Constructors
.Ctor()
.Ctor< SQInteger >()
.Ctor< SQInteger, SQInteger >()
.Ctor< SQInteger, SQInteger, SQInteger >()
// Meta-methods
.SquirrelFunc(_SC("_typename"), &SqDppCachePolicy::Fn)
// Member Variables
.Var(_SC("UserPolicy"), &DpCachePolicy::mUserPolicy)
.Var(_SC("EmojiPolicy"), &DpCachePolicy::mEmojiPolicy)
.Var(_SC("RolePolicy"), &DpCachePolicy::mRolePolicy)
);
// --------------------------------------------------------------------------------------------
ns.Bind(_SC("Activity"),
Class< DpActivity >(vm, SqDppActivity::Str)
// Constructors
.Ctor()
.Ctor< SQInteger, StackStrF &, StackStrF &, StackStrF & >()
// Meta-methods
.SquirrelFunc(_SC("_typename"), &SqDppActivity::Fn)
// Member Properties
.Prop(_SC("Name"), &DpActivity::GetName, &DpActivity::SetName)
.Prop(_SC("State"), &DpActivity::GetState, &DpActivity::SetState)
.Prop(_SC("URL"), &DpActivity::GetURL, &DpActivity::SetURL)
.Prop(_SC("Type"), &DpActivity::GetType, &DpActivity::SetType)
.Prop(_SC("CreatedAt"), &DpActivity::GetCreatedAt, &DpActivity::SetCreatedAt)
.Prop(_SC("Start"), &DpActivity::GetStart, &DpActivity::SetStart)
.Prop(_SC("End"), &DpActivity::GetEnd, &DpActivity::SetEnd)
// Member Methods
.Func(_SC("SetName"), &DpActivity::ApplyName)
.Func(_SC("SetState"), &DpActivity::ApplyState)
.Func(_SC("SetURL"), &DpActivity::ApplyURL)
.Func(_SC("SetType"), &DpActivity::ApplyType)
.Func(_SC("SetCreatedAt"), &DpActivity::ApplyCreatedAt)
.Func(_SC("SetStart"), &DpActivity::ApplyStart)
.Func(_SC("SetEnd"), &DpActivity::ApplyEnd)
);
// --------------------------------------------------------------------------------------------
ns.Bind(_SC("Presence"),
Class< DpPresence >(vm, SqDppPresence::Str)
// Constructors
.Ctor()
// Meta-methods
.SquirrelFunc(_SC("_typename"), &SqDppPresence::Fn)
// Member Properties
.Prop(_SC("UserID"), &DpPresence::GetUserID, &DpPresence::SetUserID)
.Prop(_SC("GuildID"), &DpPresence::GetGuildID, &DpPresence::SetGuildID)
.Prop(_SC("Flags"), &DpPresence::GetFlags, &DpPresence::SetFlags)
.Prop(_SC("ActivityCount"), &DpPresence::ActivityCount)
.Prop(_SC("DesktopStatus"), &DpPresence::GetDesktopStatus)
.Prop(_SC("WebStatus"), &DpPresence::GetWebStatus)
.Prop(_SC("MobileStatus"), &DpPresence::GetMobileStatus)
.Prop(_SC("Status"), &DpPresence::GetStatus)
// Member Methods
.Func(_SC("SetUserID"), &DpPresence::ApplyUserID)
.Func(_SC("SetGuildID"), &DpPresence::ApplyGuildID)
.Func(_SC("SetFlags"), &DpPresence::ApplyFlags)
.Func(_SC("AddActivity"), &DpPresence::AddActivity)
.Func(_SC("EachActivity"), &DpPresence::EachActivity)
.Func(_SC("ClearActivities"), &DpPresence::ClearActivities)
.Func(_SC("FilterActivities"), &DpPresence::FilterActivities)
.Func(_SC("BuildJSON"), &DpPresence::BuildJSON)
);
// --------------------------------------------------------------------------------------------
ns.Bind(_SC("VoiceState"),
Class< DpVoiceState, NoConstructor< DpVoiceState > >(vm, SqDppVoiceState::Str)
// Meta-methods
.SquirrelFunc(_SC("_typename"), &SqDppVoiceState::Fn)
.Func(_SC("_tojson"), &DpVoiceState::BuildJSON)
// Member Properties
.Prop(_SC("Valid"), &DpVoiceState::IsValid)
.Prop(_SC("GuildID"), &DpVoiceState::GetGuildID)
.Prop(_SC("ChannelID"), &DpVoiceState::GetChannelID)
.Prop(_SC("UserID"), &DpVoiceState::GetUserID)
.Prop(_SC("SessionID"), &DpVoiceState::GetSessionID)
.Prop(_SC("Flags"), &DpVoiceState::GetFlags, &DpVoiceState::SetFlags)
.Prop(_SC("JSON"), &DpVoiceState::BuildJSON)
.Prop(_SC("Deaf"), &DpVoiceState::IsDeaf)
.Prop(_SC("Mute"), &DpVoiceState::IsMute)
.Prop(_SC("SelfMute"), &DpVoiceState::IsSelfMute)
.Prop(_SC("SelfDeaf"), &DpVoiceState::IsSelfDeaf)
.Prop(_SC("SelfStream"), &DpVoiceState::SelfStream)
.Prop(_SC("SelfVideo"), &DpVoiceState::SelfVideo)
.Prop(_SC("Supressed"), &DpVoiceState::IsSupressed)
);
// --------------------------------------------------------------------------------------------
ns.Bind(_SC("Guild"),
Class< DpGuild, NoConstructor< DpGuild > >(vm, SqDppGuild::Str)
// Meta-methods
.SquirrelFunc(_SC("_typename"), &SqDppGuild::Fn)
// Member Properties
.Prop(_SC("Valid"), &DpGuild::IsValid)
);
}
// ------------------------------------------------------------------------------------------------
void Register_DPPConst(HSQUIRRELVM vm, Table & ns)
{
// --------------------------------------------------------------------------------------------
ConstTable(vm).Enum(_SC("SqDiscordLogLevel"), Enumeration(vm)
.Const(_SC("Trace"), static_cast< SQInteger >(dpp::ll_trace))
.Const(_SC("Debug"), static_cast< SQInteger >(dpp::ll_debug))
.Const(_SC("Info"), static_cast< SQInteger >(dpp::ll_info))
.Const(_SC("Warning"), static_cast< SQInteger >(dpp::ll_warning))
.Const(_SC("Error"), static_cast< SQInteger >(dpp::ll_error))
.Const(_SC("Critical"), static_cast< SQInteger >(dpp::ll_critical))
);
// --------------------------------------------------------------------------------------------
ConstTable(vm).Enum(_SC("SqDiscordImageType"), Enumeration(vm)
.Const(_SC("PNG"), static_cast< SQInteger >(dpp::i_png))
.Const(_SC("JPG"), static_cast< SQInteger >(dpp::i_jpg))
.Const(_SC("GIF"), static_cast< SQInteger >(dpp::i_gif))
);
// --------------------------------------------------------------------------------------------
ConstTable(vm).Enum(_SC("SqDiscordCachePolicy"), Enumeration(vm)
.Const(_SC("Aggressive"), static_cast< SQInteger >(dpp::cp_aggressive))
.Const(_SC("Lazy"), static_cast< SQInteger >(dpp::cp_lazy))
.Const(_SC("None"), static_cast< SQInteger >(dpp::cp_none))
);
// --------------------------------------------------------------------------------------------
ConstTable(vm).Enum(_SC("SqDiscordClusterIntents"), Enumeration(vm)
.Const(_SC("Guilds"), static_cast< SQInteger >(dpp::i_guilds))
.Const(_SC("GuildMembers"), static_cast< SQInteger >(dpp::i_guild_members))
.Const(_SC("GuildBans"), static_cast< SQInteger >(dpp::i_guild_bans))
.Const(_SC("GuildEmojis"), static_cast< SQInteger >(dpp::i_guild_emojis))
.Const(_SC("GuildIntegrations"), static_cast< SQInteger >(dpp::i_guild_integrations))
.Const(_SC("GuildWebhooks"), static_cast< SQInteger >(dpp::i_guild_webhooks))
.Const(_SC("GuildInvites"), static_cast< SQInteger >(dpp::i_guild_invites))
.Const(_SC("GuildVoiceStates"), static_cast< SQInteger >(dpp::i_guild_voice_states))
.Const(_SC("GuildPresences"), static_cast< SQInteger >(dpp::i_guild_presences))
.Const(_SC("GuildMessages"), static_cast< SQInteger >(dpp::i_guild_messages))
.Const(_SC("GuildMessageReactions"), static_cast< SQInteger >(dpp::i_guild_message_reactions))
.Const(_SC("GuildMessageTyping"), static_cast< SQInteger >(dpp::i_guild_message_typing))
.Const(_SC("DirectMessages"), static_cast< SQInteger >(dpp::i_direct_messages))
.Const(_SC("DirectMessageReactions"), static_cast< SQInteger >(dpp::i_direct_message_reactions))
.Const(_SC("DirectMessageTyping"), static_cast< SQInteger >(dpp::i_direct_message_typing))
.Const(_SC("Default"), static_cast< SQInteger >(dpp::i_default_intents))
.Const(_SC("Privileged"), static_cast< SQInteger >(dpp::i_privileged_intents))
.Const(_SC("All"), static_cast< SQInteger >(dpp::i_all_intents))
);
// --------------------------------------------------------------------------------------------
ConstTable(vm).Enum(_SC("SqDiscordPresenceFlags"), Enumeration(vm)
.Const(_SC("DesktopOnline"), static_cast< SQInteger >(dpp::p_desktop_online))
.Const(_SC("DesktopDND"), static_cast< SQInteger >(dpp::p_desktop_dnd))
.Const(_SC("DesktopIdle"), static_cast< SQInteger >(dpp::p_desktop_idle))
.Const(_SC("WebWnline"), static_cast< SQInteger >(dpp::p_web_online))
.Const(_SC("WebDND"), static_cast< SQInteger >(dpp::p_web_dnd))
.Const(_SC("WebIdle"), static_cast< SQInteger >(dpp::p_web_idle))
.Const(_SC("MobileOnline"), static_cast< SQInteger >(dpp::p_mobile_online))
.Const(_SC("MobileDND"), static_cast< SQInteger >(dpp::p_mobile_dnd))
.Const(_SC("MobileIdle"), static_cast< SQInteger >(dpp::p_mobile_idle))
.Const(_SC("StatusOnline"), static_cast< SQInteger >(dpp::p_status_online))
.Const(_SC("StatusDND"), static_cast< SQInteger >(dpp::p_status_dnd))
.Const(_SC("StatusIdle"), static_cast< SQInteger >(dpp::p_status_idle))
);
// --------------------------------------------------------------------------------------------
ConstTable(vm).Enum(_SC("SqDiscordPresenceStatus"), Enumeration(vm)
.Const(_SC("Offline"), static_cast< SQInteger >(dpp::ps_offline))
.Const(_SC("Online"), static_cast< SQInteger >(dpp::ps_online))
.Const(_SC("DND"), static_cast< SQInteger >(dpp::ps_dnd))
.Const(_SC("Idle"), static_cast< SQInteger >(dpp::ps_idle))
);
// --------------------------------------------------------------------------------------------
ConstTable(vm).Enum(_SC("SqDiscordDesktopStatusBits"), Enumeration(vm)
.Const(_SC("ShiftDesktop"), static_cast< SQInteger >(PF_SHIFT_DESKTOP))
.Const(_SC("ShiftWeb"), static_cast< SQInteger >(PF_SHIFT_WEB))
.Const(_SC("ShiftMobile"), static_cast< SQInteger >(PF_SHIFT_MOBILE))
.Const(_SC("ShiftMain"), static_cast< SQInteger >(PF_SHIFT_MAIN))
.Const(_SC("StatusMask"), static_cast< SQInteger >(PF_STATUS_MASK))
.Const(_SC("ClearDesktop"), static_cast< SQInteger >(PF_CLEAR_DESKTOP))
.Const(_SC("ClearWeb"), static_cast< SQInteger >(PF_CLEAR_WEB))
.Const(_SC("ClearMobile"), static_cast< SQInteger >(PF_CLEAR_MOBILE))
.Const(_SC("ClearStatus"), static_cast< SQInteger >(PF_CLEAR_STATUS))
);
// --------------------------------------------------------------------------------------------
ConstTable(vm).Enum(_SC("SqDiscordActivityType"), Enumeration(vm)
.Const(_SC("Game"), static_cast< SQInteger >(dpp::at_game))
.Const(_SC("Streaming"), static_cast< SQInteger >(dpp::at_streaming))
.Const(_SC("Listening"), static_cast< SQInteger >(dpp::at_listening))
.Const(_SC("Custom"), static_cast< SQInteger >(dpp::at_custom))
.Const(_SC("Competing"), static_cast< SQInteger >(dpp::at_competing))
);
// --------------------------------------------------------------------------------------------
ConstTable(vm).Enum(_SC("SqDiscordActivityFlags"), Enumeration(vm)
.Const(_SC("Instance"), static_cast< SQInteger >(dpp::af_instance))
.Const(_SC("Join"), static_cast< SQInteger >(dpp::af_join))
.Const(_SC("Spectate"), static_cast< SQInteger >(dpp::af_spectate))
.Const(_SC("JoinRequest"), static_cast< SQInteger >(dpp::af_join_request))
.Const(_SC("Sync"), static_cast< SQInteger >(dpp::af_sync))
.Const(_SC("Play"), static_cast< SQInteger >(dpp::af_play))
);
}
} // Namespace:: SqMod

702
module/Library/DPPTy.hpp Normal file
View File

@ -0,0 +1,702 @@
#pragma once
// ------------------------------------------------------------------------------------------------
#include "Core/Utility.hpp"
// ------------------------------------------------------------------------------------------------
#include <dpp/dpp.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Represents the caching policy of the cluster.
*/
struct DpCachePolicy
{
SQInteger mUserPolicy{dpp::cp_aggressive};
SQInteger mEmojiPolicy{dpp::cp_aggressive};
SQInteger mRolePolicy{dpp::cp_aggressive};
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
DpCachePolicy() noexcept = default;
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
explicit DpCachePolicy(SQInteger user) noexcept
: mUserPolicy(user), mEmojiPolicy(dpp::cp_aggressive), mRolePolicy(dpp::cp_aggressive)
{
}
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
DpCachePolicy(SQInteger user, SQInteger emoji) noexcept
: mUserPolicy(user), mEmojiPolicy(emoji), mRolePolicy(dpp::cp_aggressive)
{
}
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
DpCachePolicy(SQInteger user, SQInteger emoji, SQInteger role) noexcept
: mUserPolicy(user), mEmojiPolicy(emoji), mRolePolicy(role)
{
}
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
DpCachePolicy(const DpCachePolicy &) noexcept = default;
/* --------------------------------------------------------------------------------------------
* Convert to native cache policy type.
*/
SQMOD_NODISCARD dpp::cache_policy_t ToNative() const noexcept
{
return dpp::cache_policy_t{
static_cast< dpp::cache_policy_setting_t >(mUserPolicy),
static_cast< dpp::cache_policy_setting_t >(mEmojiPolicy),
static_cast< dpp::cache_policy_setting_t >(mRolePolicy)
};
}
};
/* ------------------------------------------------------------------------------------------------
* An activity is a representation of what a user is doing. It might be a game, or a website, or a movie. Whatever.
*/
struct DpActivity : public dpp::activity
{
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
DpActivity()
: dpp::activity()
{
}
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
DpActivity(SQInteger type, StackStrF & name, StackStrF & state, StackStrF & url)
: dpp::activity(static_cast< dpp::activity_type >(type), name.ToStr(), state.ToStr(), url.ToStr())
{
}
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
explicit DpActivity(const dpp::activity & o)
: dpp::activity(o)
{
}
/* --------------------------------------------------------------------------------------------
* Retrieve the name of the activity.
*/
SQMOD_NODISCARD const std::string & GetName() const noexcept
{
return dpp::activity::name;
}
/* --------------------------------------------------------------------------------------------
* Modify the name of the activity.
*/
void SetName(StackStrF & name)
{
dpp::activity::name = name.ToStr();
}
/* --------------------------------------------------------------------------------------------
* Modify the name of the activity.
*/
DpActivity & ApplyName(StackStrF & name)
{
SetName(name);
return *this;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the state of the activity.
*/
SQMOD_NODISCARD const std::string & GetState() const noexcept
{
return dpp::activity::state;
}
/* --------------------------------------------------------------------------------------------
* Modify the state of the activity.
*/
void SetState(StackStrF & state)
{
dpp::activity::state = state.ToStr();
}
/* --------------------------------------------------------------------------------------------
* Modify the state of the activity.
*/
DpActivity & ApplyState(StackStrF & state)
{
SetState(state);
return *this;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the url of the activity.
*/
SQMOD_NODISCARD const std::string & GetURL() const noexcept
{
return dpp::activity::url;
}
/* --------------------------------------------------------------------------------------------
* Modify the url of the activity.
*/
void SetURL(StackStrF & url)
{
dpp::activity::url = url.ToStr();
}
/* --------------------------------------------------------------------------------------------
* Modify the url of the activity.
*/
DpActivity & ApplyURL(StackStrF & url)
{
SetURL(url);
return *this;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the type of the activity.
*/
SQMOD_NODISCARD SQInteger GetType() const noexcept
{
return static_cast< SQInteger >(dpp::activity::type);
}
/* --------------------------------------------------------------------------------------------
* Modify the type of the activity.
*/
void SetType(SQInteger s)
{
dpp::activity::type = static_cast< dpp::activity_type >(s);
}
/* --------------------------------------------------------------------------------------------
* Modify the type of the activity.
*/
DpActivity & ApplyType(SQInteger s)
{
SetType(s);
return *this;
}
/* --------------------------------------------------------------------------------------------
* Retrieve when the activity was created.
*/
SQMOD_NODISCARD SQInteger GetCreatedAt() const noexcept
{
return static_cast< SQInteger >(std::chrono::duration_cast< std::chrono::seconds >(std::chrono::system_clock::from_time_t(dpp::activity::created_at).time_since_epoch()).count());
}
/* --------------------------------------------------------------------------------------------
* Modify when the activity was created.
*/
void SetCreatedAt(SQInteger s)
{
dpp::activity::created_at = std::chrono::system_clock::to_time_t(std::chrono::time_point< std::chrono::system_clock >{std::chrono::seconds{s}});
}
/* --------------------------------------------------------------------------------------------
* Modify when the activity was created.
*/
DpActivity & ApplyCreatedAt(SQInteger s)
{
SetCreatedAt(s);
return *this;
}
/* --------------------------------------------------------------------------------------------
* Retrieve when the activity was started.
*/
SQMOD_NODISCARD SQInteger GetStart() const noexcept
{
return static_cast< SQInteger >(std::chrono::duration_cast< std::chrono::seconds >(std::chrono::system_clock::from_time_t(dpp::activity::start).time_since_epoch()).count());
}
/* --------------------------------------------------------------------------------------------
* Modify when the activity was started.
*/
void SetStart(SQInteger s)
{
dpp::activity::start = std::chrono::system_clock::to_time_t(std::chrono::time_point< std::chrono::system_clock >{std::chrono::seconds{s}});
}
/* --------------------------------------------------------------------------------------------
* Modify when the activity was started.
*/
DpActivity & ApplyStart(SQInteger s)
{
SetStart(s);
return *this;
}
/* --------------------------------------------------------------------------------------------
* Retrieve when the activity was stopped.
*/
SQMOD_NODISCARD SQInteger GetEnd() const noexcept
{
return static_cast< SQInteger >(std::chrono::duration_cast< std::chrono::seconds >(std::chrono::system_clock::from_time_t(dpp::activity::end).time_since_epoch()).count());
}
/* --------------------------------------------------------------------------------------------
* Modify when the activity was stopped.
*/
void SetEnd(SQInteger s)
{
dpp::activity::end = std::chrono::system_clock::to_time_t(std::chrono::time_point< std::chrono::system_clock >{std::chrono::seconds{s}});
}
/* --------------------------------------------------------------------------------------------
* Modify when the activity was stopped.
*/
DpActivity & ApplyEnd(SQInteger s)
{
SetEnd(s);
return *this;
}
};
/* ------------------------------------------------------------------------------------------------
* Represents user presence, e.g. what game they are playing and if they are online.
*/
struct DpPresence : public dpp::presence
{
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
DpPresence()
: dpp::presence()
{
}
/* --------------------------------------------------------------------------------------------
* Retrieve the user that the presence applies to.
*/
SQMOD_NODISCARD dpp::snowflake GetUserID() const noexcept
{
return dpp::presence::user_id;
}
/* --------------------------------------------------------------------------------------------
* Modify the user that the presence applies to.
*/
void SetUserID(dpp::snowflake id)
{
dpp::presence::user_id = id;
}
/* --------------------------------------------------------------------------------------------
* Modify the user that the presence applies to.
*/
DpPresence & ApplyUserID(dpp::snowflake id)
{
SetUserID(id);
return *this;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the guild that the presence applies to.
*/
SQMOD_NODISCARD dpp::snowflake GetGuildID() const noexcept
{
return dpp::presence::guild_id;
}
/* --------------------------------------------------------------------------------------------
* Modify the guild that the presence applies to.
*/
void SetGuildID(dpp::snowflake id)
{
dpp::presence::guild_id = id;
}
/* --------------------------------------------------------------------------------------------
* Modify the guild that the presence applies to.
*/
DpPresence & ApplyGuildID(dpp::snowflake id)
{
SetGuildID(id);
return *this;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the presence bit-mask.
*/
SQMOD_NODISCARD SQInteger GetFlags() const noexcept
{
return static_cast< SQInteger >(dpp::presence::flags);
}
/* --------------------------------------------------------------------------------------------
* Modify the presence bit-mask.
*/
void SetFlags(SQInteger f)
{
dpp::presence::flags = static_cast< uint8_t >(f);
}
/* --------------------------------------------------------------------------------------------
* Modify the presence bit-mask.
*/
DpPresence & ApplyFlags(SQInteger f)
{
SetFlags(f);
return *this;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the number of activities.
*/
SQMOD_NODISCARD SQInteger ActivityCount() const
{
return static_cast< SQInteger >(dpp::presence::activities.size());
}
/* --------------------------------------------------------------------------------------------
* Add a new activity.
*/
DpPresence & AddActivity(const DpActivity & a)
{
dpp::presence::activities.push_back(a);
return *this;
}
/* --------------------------------------------------------------------------------------------
* Iterate all activities.
*/
DpPresence & EachActivity(Function & fn)
{
for (const auto & a : dpp::presence::activities)
{
fn.Execute(a);
}
return *this;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the number of activities.
*/
DpPresence & ClearActivities(const DpActivity & a)
{
dpp::presence::activities.clear();
return *this;
}
/* --------------------------------------------------------------------------------------------
* Filter activities.
*/
DpPresence & FilterActivities(Function & fn)
{
std::vector< dpp::activity > list;
list.reserve(dpp::presence::activities.size());
for (const auto & a : dpp::presence::activities)
{
auto ret = fn.Eval(a);
// (null || true) == keep & false == skip
if (!ret.IsNull() || !ret.template Cast< bool >())
{
list.push_back(a);
}
}
dpp::presence::activities.swap(list);
return *this;
}
/* --------------------------------------------------------------------------------------------
* Build JSON string from this object.
*/
SQMOD_NODISCARD std::string BuildJSON() const
{
return dpp::presence::build_json();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the users status on desktop.
*/
SQMOD_NODISCARD SQInteger GetDesktopStatus() const noexcept
{
return static_cast< SQInteger >(dpp::presence::desktop_status());
}
/* --------------------------------------------------------------------------------------------
* Retrieve the user's status on web.
*/
SQMOD_NODISCARD SQInteger GetWebStatus() const noexcept
{
return static_cast< SQInteger >(dpp::presence::web_status());
}
/* --------------------------------------------------------------------------------------------
* Retrieve the user's status on mobile.
*/
SQMOD_NODISCARD SQInteger GetMobileStatus() const noexcept
{
return static_cast< SQInteger >(dpp::presence::mobile_status());
}
/* --------------------------------------------------------------------------------------------
* Retrieve the user's status as shown to other users.
*/
SQMOD_NODISCARD SQInteger GetStatus() const noexcept
{
return static_cast< SQInteger >(dpp::presence::status());
}
};
/* ------------------------------------------------------------------------------------------------
* Represents the voice state of a user on a guild.
* These are stored in the DpGuild object, and accessible there, or via DpChannel::GetVoiceMembers.
*/
struct DpVoiceState
{
using Ptr = std::unique_ptr< dpp::voicestate >;
/* --------------------------------------------------------------------------------------------
* Referenced voice state instance.
*/
Ptr mPtr{nullptr};
/* --------------------------------------------------------------------------------------------
* Whether the referenced pointer is owned.
*/
bool mOwned{false};
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
DpVoiceState() noexcept = default;
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
explicit DpVoiceState(Ptr::pointer ptr, bool owned = false) noexcept
: mPtr(ptr), mOwned(owned)
{
}
/* --------------------------------------------------------------------------------------------
* Copy constructor (disabled).
*/
DpVoiceState(const DpVoiceState & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
DpVoiceState(DpVoiceState && o) noexcept = default;
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~DpVoiceState() noexcept
{
// Do we own this to try delete it?
if (!mOwned && mPtr) [[maybe_unused]] auto p = mPtr.release();
}
/* --------------------------------------------------------------------------------------------
* Copy assignment operator (disabled).
*/
DpVoiceState & operator = (const DpVoiceState & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
DpVoiceState & operator = (DpVoiceState && o) noexcept
{
if (this != &o)
{
// Do we own this to try delete it?
if (!mOwned && mPtr) [[maybe_unused]] auto p = mPtr.release();
// Transfer members values
mPtr = std::move(o.mPtr);
mOwned = o.mOwned;
}
return *this;
}
/* --------------------------------------------------------------------------------------------
* Validate the managed handle.
*/
void Validate() const { if (!mPtr) STHROWF("Invalid discord voice state handle"); }
/* --------------------------------------------------------------------------------------------
* Validate the managed handle and retrieve a const reference to it.
*/
SQMOD_NODISCARD Ptr::element_type & Valid() const { Validate(); return *mPtr; }
/* --------------------------------------------------------------------------------------------
* Check whether a valid instance is managed.
*/
SQMOD_NODISCARD bool IsValid() const { return static_cast< bool >(mPtr); }
/* --------------------------------------------------------------------------------------------
* Retrieve the guild id this voice state is for (optional).
*/
SQMOD_NODISCARD dpp::snowflake GetGuildID() const { return Valid().guild_id; }
/* --------------------------------------------------------------------------------------------
* Retrieve the guild id this voice state is for (optional).
*/
SQMOD_NODISCARD dpp::snowflake GetChannelID() const { return Valid().channel_id; }
/* --------------------------------------------------------------------------------------------
* Retrieve the guild id this voice state is for (optional).
*/
SQMOD_NODISCARD dpp::snowflake GetUserID() const { return Valid().user_id; }
/* --------------------------------------------------------------------------------------------
* Retrieve the guild id this voice state is for (optional).
*/
SQMOD_NODISCARD const std::string & GetSessionID() const { return Valid().session_id; }
/* --------------------------------------------------------------------------------------------
* Retrieve the guild id this voice state is for (optional).
*/
SQMOD_NODISCARD SQInteger GetFlags() const { return Valid().flags; }
/* --------------------------------------------------------------------------------------------
* Retrieve the guild id this voice state is for (optional).
*/
void SetFlags(SQInteger flags) const { Valid().flags = flags; }
/* --------------------------------------------------------------------------------------------
* Retrieve the guild id this voice state is for (optional).
*/
SQMOD_NODISCARD std::string BuildJSON() const { return Valid().build_json(); }
/* --------------------------------------------------------------------------------------------
* Check if user is deafened.
*/
SQMOD_NODISCARD bool IsDeaf() const { return Valid().is_deaf(); }
/* --------------------------------------------------------------------------------------------
* Check if user is muted.
*/
SQMOD_NODISCARD bool IsMute() const { return Valid().is_mute(); }
/* --------------------------------------------------------------------------------------------
* Check if user muted themselves.
*/
SQMOD_NODISCARD bool IsSelfMute() const { return Valid().is_self_mute(); }
/* --------------------------------------------------------------------------------------------
* Check if user deafened themselves.
*/
SQMOD_NODISCARD bool IsSelfDeaf() const { return Valid().is_self_deaf(); }
/* --------------------------------------------------------------------------------------------
* Check if user is streamig.
*/
SQMOD_NODISCARD bool SelfStream() const { return Valid().self_stream(); }
/* --------------------------------------------------------------------------------------------
* Check if user is in video.
*/
SQMOD_NODISCARD bool SelfVideo() const { return Valid().self_video(); }
/* --------------------------------------------------------------------------------------------
* Check if user is surpressed.
*/
SQMOD_NODISCARD bool IsSupressed() const { return Valid().is_supressed(); }
};
/* ------------------------------------------------------------------------------------------------
* Represents a guild on Discord (AKA a server)
*/
struct DpGuild
{
using Ptr = std::unique_ptr< dpp::guild >;
/* --------------------------------------------------------------------------------------------
* Referenced voice state instance.
*/
Ptr mPtr{nullptr};
/* --------------------------------------------------------------------------------------------
* Whether the referenced pointer is owned.
*/
bool mOwned{false};
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
DpGuild() noexcept = default;
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
explicit DpGuild(Ptr::pointer ptr, bool owned = false) noexcept
: mPtr(ptr), mOwned(owned)
{
}
/* --------------------------------------------------------------------------------------------
* Copy constructor (disabled).
*/
DpGuild(const DpGuild & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
DpGuild(DpGuild && o) noexcept = default;
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~DpGuild() noexcept
{
// Do we own this to try delete it?
if (!mOwned && mPtr) [[maybe_unused]] auto p = mPtr.release();
}
/* --------------------------------------------------------------------------------------------
* Copy assignment operator (disabled).
*/
DpGuild & operator = (const DpGuild & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
DpGuild & operator = (DpGuild && o) noexcept
{
if (this != &o)
{
// Do we own this to try delete it?
if (!mOwned && mPtr) [[maybe_unused]] auto p = mPtr.release();
// Transfer members values
mPtr = std::move(o.mPtr);
mOwned = o.mOwned;
}
return *this;
}
/* --------------------------------------------------------------------------------------------
* Validate the managed handle.
*/
void Validate() const { if (!mPtr) STHROWF("Invalid discord guild handle"); }
/* --------------------------------------------------------------------------------------------
* Validate the managed handle and retrieve a const reference to it.
*/
SQMOD_NODISCARD Ptr::element_type & Valid() const { Validate(); return *mPtr; }
/* --------------------------------------------------------------------------------------------
* Check whether a valid instance is managed.
*/
SQMOD_NODISCARD bool IsValid() const { return static_cast< bool >(mPtr); }
};
} // Namespace:: SqMod

View File

@ -1,6 +1,5 @@
// ------------------------------------------------------------------------------------------------
#include "Library/IO/Buffer.hpp"
#include "Library/Numeric/Long.hpp"
#include "Base/AABB.hpp"
#include "Base/Circle.hpp"
#include "Base/Color3.hpp"
@ -20,19 +19,7 @@ namespace SqMod {
SQMOD_DECL_TYPENAME(Typename, _SC("SqBuffer"))
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteInt64(const SLongInt & val)
{
Valid().Push< int64_t >(val.GetNum());
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteUint64(const ULongInt & val)
{
Valid().Push< uint64_t >(val.GetNum());
}
// ------------------------------------------------------------------------------------------------
SQInteger SqBuffer::WriteRawString(StackStrF & val)
SQInteger SqBuffer::WriteRawString(StackStrF & val) const
{
// Validate the managed buffer reference
Validate();
@ -50,7 +37,7 @@ SQInteger SqBuffer::WriteRawString(StackStrF & val)
}
// ------------------------------------------------------------------------------------------------
SQInteger SqBuffer::WriteClientString(StackStrF & val)
SQInteger SqBuffer::WriteClientString(StackStrF & val) const
{
// Validate the managed buffer reference
Validate();
@ -75,67 +62,67 @@ SQInteger SqBuffer::WriteClientString(StackStrF & val)
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteAABB(const AABB & val)
void SqBuffer::WriteAABB(const AABB & val) const
{
Valid().Push< AABB >(val);
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteCircle(const Circle & val)
void SqBuffer::WriteCircle(const Circle & val) const
{
Valid().Push< Circle >(val);
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteColor3(const Color3 & val)
void SqBuffer::WriteColor3(const Color3 & val) const
{
Valid().Push< Color3 >(val);
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteColor4(const Color4 & val)
void SqBuffer::WriteColor4(const Color4 & val) const
{
Valid().Push< Color4 >(val);
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteQuaternion(const Quaternion & val)
void SqBuffer::WriteQuaternion(const Quaternion & val) const
{
Valid().Push< Quaternion >(val);
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteSphere(const Sphere &val)
void SqBuffer::WriteSphere(const Sphere &val) const
{
Valid().Push< Sphere >(val);
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteVector2(const Vector2 & val)
void SqBuffer::WriteVector2(const Vector2 & val) const
{
Valid().Push< Vector2 >(val);
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteVector2i(const Vector2i & val)
void SqBuffer::WriteVector2i(const Vector2i & val) const
{
Valid().Push< Vector2i >(val);
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteVector3(const Vector3 & val)
void SqBuffer::WriteVector3(const Vector3 & val) const
{
Valid().Push< Vector3 >(val);
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteVector4(const Vector4 & val)
void SqBuffer::WriteVector4(const Vector4 & val) const
{
Valid().Push< Vector4 >(val);
}
// ------------------------------------------------------------------------------------------------
SLongInt SqBuffer::ReadInt64()
SQInteger SqBuffer::ReadInt64() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -144,11 +131,11 @@ SLongInt SqBuffer::ReadInt64()
// Advance the buffer cursor
m_Buffer->Advance< int64_t >(1);
// Return the requested information
return SLongInt(value);
return static_cast< SQInteger >(value);
}
// ------------------------------------------------------------------------------------------------
ULongInt SqBuffer::ReadUint64()
SQInteger SqBuffer::ReadUint64() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -157,11 +144,11 @@ ULongInt SqBuffer::ReadUint64()
// Advance the buffer cursor
m_Buffer->Advance< uint64_t >(1);
// Return the requested information
return ULongInt(value);
return static_cast< SQInteger >(value);
}
// ------------------------------------------------------------------------------------------------
LightObj SqBuffer::ReadRawString(SQInteger length)
LightObj SqBuffer::ReadRawString(SQInteger length) const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -201,7 +188,7 @@ LightObj SqBuffer::ReadRawString(SQInteger length)
}
// ------------------------------------------------------------------------------------------------
LightObj SqBuffer::ReadClientString()
LightObj SqBuffer::ReadClientString() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -228,7 +215,7 @@ LightObj SqBuffer::ReadClientString()
}
// ------------------------------------------------------------------------------------------------
AABB SqBuffer::ReadAABB()
AABB SqBuffer::ReadAABB() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -241,7 +228,7 @@ AABB SqBuffer::ReadAABB()
}
// ------------------------------------------------------------------------------------------------
Circle SqBuffer::ReadCircle()
Circle SqBuffer::ReadCircle() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -254,7 +241,7 @@ Circle SqBuffer::ReadCircle()
}
// ------------------------------------------------------------------------------------------------
Color3 SqBuffer::ReadColor3()
Color3 SqBuffer::ReadColor3() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -267,7 +254,7 @@ Color3 SqBuffer::ReadColor3()
}
// ------------------------------------------------------------------------------------------------
Color4 SqBuffer::ReadColor4()
Color4 SqBuffer::ReadColor4() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -280,7 +267,7 @@ Color4 SqBuffer::ReadColor4()
}
// ------------------------------------------------------------------------------------------------
Quaternion SqBuffer::ReadQuaternion()
Quaternion SqBuffer::ReadQuaternion() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -293,7 +280,7 @@ Quaternion SqBuffer::ReadQuaternion()
}
// ------------------------------------------------------------------------------------------------
Sphere SqBuffer::ReadSphere()
Sphere SqBuffer::ReadSphere() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -306,7 +293,7 @@ Sphere SqBuffer::ReadSphere()
}
// ------------------------------------------------------------------------------------------------
Vector2 SqBuffer::ReadVector2()
Vector2 SqBuffer::ReadVector2() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -319,7 +306,7 @@ Vector2 SqBuffer::ReadVector2()
}
// ------------------------------------------------------------------------------------------------
Vector2i SqBuffer::ReadVector2i()
Vector2i SqBuffer::ReadVector2i() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -332,7 +319,7 @@ Vector2i SqBuffer::ReadVector2i()
}
// ------------------------------------------------------------------------------------------------
Vector3 SqBuffer::ReadVector3()
Vector3 SqBuffer::ReadVector3() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -345,7 +332,7 @@ Vector3 SqBuffer::ReadVector3()
}
// ------------------------------------------------------------------------------------------------
Vector4 SqBuffer::ReadVector4()
Vector4 SqBuffer::ReadVector4() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -358,7 +345,7 @@ Vector4 SqBuffer::ReadVector4()
}
// ------------------------------------------------------------------------------------------------
SQInteger SqBuffer::GetCRC32(SQInteger n)
SQInteger SqBuffer::GetCRC32(SQInteger n) const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -371,7 +358,7 @@ SQInteger SqBuffer::GetCRC32(SQInteger n)
}
// ------------------------------------------------------------------------------------------------
SQInteger SqBuffer::GetADLER32(SQInteger n)
SQInteger SqBuffer::GetADLER32(SQInteger n) const
{
// Validate the managed buffer reference
ValidateDeeper();

View File

@ -176,7 +176,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Validate the managed memory buffer reference.
*/
Buffer & Valid() const
SQMOD_NODISCARD Buffer & Valid() const
{
Validate();
// Return the buffer
@ -186,7 +186,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Validate the managed memory buffer reference and the buffer itself.
*/
Buffer & ValidDeeper() const
SQMOD_NODISCARD Buffer & ValidDeeper() const
{
ValidateDeeper();
// Return the buffer
@ -204,7 +204,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Modify a certain element type at the specified position.
*/
void Set(SQInteger n, SQInteger v)
void Set(SQInteger n, SQInteger v) const
{
Valid().At(ConvTo< SzType >::From(n)) = ConvTo< Value >::From(v);
}
@ -220,7 +220,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Modify the element at the front of the buffer.
*/
void SetFront(SQInteger v)
void SetFront(SQInteger v) const
{
Valid().Front() = ConvTo< Value >::From(v);
}
@ -236,7 +236,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Modify the element after the first element in the buffer.
*/
void SetNext(SQInteger v)
void SetNext(SQInteger v) const
{
Valid().Next() = ConvTo< Value >::From(v);
}
@ -252,7 +252,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Modify the element at the back of the buffer.
*/
void SetBack(SQInteger v)
void SetBack(SQInteger v) const
{
Valid().Back() = ConvTo< Value >::From(v);
}
@ -268,7 +268,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Modify the element before the last element in the buffer.
*/
void SetPrev(SQInteger v)
void SetPrev(SQInteger v) const
{
Valid().Prev() = ConvTo< Value >::From(v);
}
@ -276,7 +276,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Reposition the edit cursor to the specified number of elements ahead.
*/
void Advance(SQInteger n)
void Advance(SQInteger n) const
{
Valid().Advance(ConvTo< SzType >::From(n));
}
@ -284,7 +284,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Reposition the edit cursor to the specified number of elements behind.
*/
void Retreat(SQInteger n)
void Retreat(SQInteger n) const
{
Valid().Retreat(ConvTo< SzType >::From(n));
}
@ -292,7 +292,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Reposition the edit cursor to a fixed position within the buffer.
*/
void Move(SQInteger n)
void Move(SQInteger n) const
{
Valid().Move(ConvTo< SzType >::From(n));
}
@ -300,7 +300,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Append a value to the current cursor location and advance the cursor.
*/
void Push(SQInteger v)
void Push(SQInteger v) const
{
Valid().Push(ConvTo< Value >::From(v));
}
@ -316,7 +316,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Modify the element at the cursor position.
*/
void SetCursor(SQInteger v)
void SetCursor(SQInteger v) const
{
Valid().Cursor() = ConvTo< Value >::From(v);
}
@ -332,7 +332,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Modify the element before the cursor position.
*/
void SetBefore(SQInteger v)
void SetBefore(SQInteger v) const
{
Valid().Before() = ConvTo< Value >::From(v);
}
@ -348,7 +348,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Modify the element after the cursor position.
*/
void SetAfter(SQInteger v)
void SetAfter(SQInteger v) const
{
Valid().After() = ConvTo< Value >::From(v);
}
@ -396,7 +396,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Grow the size of the internal buffer by the specified amount of bytes.
*/
void Grow(SQInteger n)
void Grow(SQInteger n) const
{
return Valid().Grow(ConvTo< SzType >::From(n) * sizeof(Value));
}
@ -425,65 +425,71 @@ public:
/* --------------------------------------------------------------------------------------------
* Write a signed 8 bit integer to the buffer.
*/
void WriteInt8(SQInteger val)
void WriteInt8(SQInteger val) const
{
Valid().Push< int8_t >(ConvTo< int8_t >::From(val));
Valid().Push< int8_t >(static_cast< int8_t >(val));
}
/* --------------------------------------------------------------------------------------------
* Write an unsigned 8 bit integer to the buffer.
*/
void WriteUint8(SQInteger val)
void WriteUint8(SQInteger val) const
{
Valid().Push< uint8_t >(ConvTo< uint8_t >::From(val));
Valid().Push< uint8_t >(static_cast< uint8_t >(val));
}
/* --------------------------------------------------------------------------------------------
* Write a signed 16 bit integer to the buffer.
*/
void WriteInt16(SQInteger val)
void WriteInt16(SQInteger val) const
{
Valid().Push< int16_t >(ConvTo< int16_t >::From(val));
Valid().Push< int16_t >(static_cast< int16_t >(val));
}
/* --------------------------------------------------------------------------------------------
* Write an unsigned 16 bit integer to the buffer.
*/
void WriteUint16(SQInteger val)
void WriteUint16(SQInteger val) const
{
Valid().Push< uint16_t >(ConvTo< uint16_t >::From(val));
Valid().Push< uint16_t >(static_cast< uint16_t >(val));
}
/* --------------------------------------------------------------------------------------------
* Write a signed 32 bit integer to the buffer.
*/
void WriteInt32(SQInteger val)
void WriteInt32(SQInteger val) const
{
Valid().Push< int32_t >(ConvTo< int32_t >::From(val));
Valid().Push< int32_t >(static_cast< int32_t >(val));
}
/* --------------------------------------------------------------------------------------------
* Write an unsigned 32 bit integer to the buffer.
*/
void WriteUint32(SQInteger val)
void WriteUint32(SQInteger val) const
{
Valid().Push< uint32_t >(ConvTo< uint32_t >::From(val));
Valid().Push< uint32_t >(static_cast< uint32_t >(val));
}
/* --------------------------------------------------------------------------------------------
* Write a signed 64 bit integer to the buffer.
*/
void WriteInt64(const SLongInt & val);
void WriteInt64(SQInteger val) const
{
Valid().Push< int64_t >(static_cast< int64_t >(val));
}
/* --------------------------------------------------------------------------------------------
* Write an unsigned 64 bit integer to the buffer.
*/
void WriteUint64(const ULongInt & val);
void WriteUint64(SQInteger val) const
{
Valid().Push< uint64_t >(static_cast< uint64_t >(val));
}
/* --------------------------------------------------------------------------------------------
* Write a 32 bit float to the buffer.
*/
void WriteFloat32(SQFloat val)
void WriteFloat32(SQFloat val) const
{
Valid().Push< float >(ConvTo< float >::From(val));
}
@ -491,7 +497,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Write a 64 bit float to the buffer.
*/
void WriteFloat64(SQFloat val)
void WriteFloat64(SQFloat val) const
{
Valid().Push< double >(ConvTo< double >::From(val));
}
@ -499,67 +505,67 @@ public:
/* --------------------------------------------------------------------------------------------
* Write a raw string to the buffer.
*/
SQInteger WriteRawString(StackStrF & val);
SQInteger WriteRawString(StackStrF & val) const;
/* --------------------------------------------------------------------------------------------
* Write a client encoded string to the buffer.
*/
SQInteger WriteClientString(StackStrF & val);
SQInteger WriteClientString(StackStrF & val) const;
/* --------------------------------------------------------------------------------------------
* Write a AABB to the buffer.
*/
void WriteAABB(const AABB & val);
void WriteAABB(const AABB & val) const;
/* --------------------------------------------------------------------------------------------
* Write a Circle to the buffer.
*/
void WriteCircle(const Circle & val);
void WriteCircle(const Circle & val) const;
/* --------------------------------------------------------------------------------------------
* Write a Color3 to the buffer.
*/
void WriteColor3(const Color3 & val);
void WriteColor3(const Color3 & val) const;
/* --------------------------------------------------------------------------------------------
* Write a Color4 to the buffer.
*/
void WriteColor4(const Color4 & val);
void WriteColor4(const Color4 & val) const;
/* --------------------------------------------------------------------------------------------
* Write a Quaternion to the buffer.
*/
void WriteQuaternion(const Quaternion & val);
void WriteQuaternion(const Quaternion & val) const;
/* --------------------------------------------------------------------------------------------
* Write a Sphere to the buffer.
*/
void WriteSphere(const Sphere &val);
void WriteSphere(const Sphere &val) const;
/* --------------------------------------------------------------------------------------------
* Write a Vector2 to the buffer.
*/
void WriteVector2(const Vector2 & val);
void WriteVector2(const Vector2 & val) const;
/* --------------------------------------------------------------------------------------------
* Write a Vector2i to the buffer.
*/
void WriteVector2i(const Vector2i & val);
void WriteVector2i(const Vector2i & val) const;
/* --------------------------------------------------------------------------------------------
* Write a Vector3 to the buffer.
*/
void WriteVector3(const Vector3 & val);
void WriteVector3(const Vector3 & val) const;
/* --------------------------------------------------------------------------------------------
* Write a Vector4 to the buffer.
*/
void WriteVector4(const Vector4 & val);
void WriteVector4(const Vector4 & val) const;
/* --------------------------------------------------------------------------------------------
* Write a signed 8 bit integer from the buffer.
*/
SQInteger ReadInt8()
SQMOD_NODISCARD SQInteger ReadInt8() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -574,7 +580,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Read an unsigned 8 bit integer from the buffer.
*/
SQInteger ReadUint8()
SQMOD_NODISCARD SQInteger ReadUint8() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -589,7 +595,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Read a signed 16 bit integer from the buffer.
*/
SQInteger ReadInt16()
SQMOD_NODISCARD SQInteger ReadInt16() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -604,7 +610,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Read an unsigned 16 bit integer from the buffer.
*/
SQInteger ReadUint16()
SQMOD_NODISCARD SQInteger ReadUint16() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -619,7 +625,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Read a signed 32 bit integer from the buffer.
*/
SQInteger ReadInt32()
SQMOD_NODISCARD SQInteger ReadInt32() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -634,7 +640,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Read an unsigned 32 bit integer from the buffer.
*/
SQInteger ReadUint32()
SQMOD_NODISCARD SQInteger ReadUint32() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -649,17 +655,17 @@ public:
/* --------------------------------------------------------------------------------------------
* Read a signed 64 bit integer from the buffer.
*/
SLongInt ReadInt64();
SQMOD_NODISCARD SQInteger ReadInt64() const;
/* --------------------------------------------------------------------------------------------
* Read an unsigned 64 bit integer from the buffer.
*/
ULongInt ReadUint64();
SQMOD_NODISCARD SQInteger ReadUint64() const;
/* --------------------------------------------------------------------------------------------
* Read a 32 bit float from the buffer.
*/
SQFloat ReadFloat32()
SQMOD_NODISCARD SQFloat ReadFloat32() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -674,7 +680,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Read a 64 bit float from the buffer.
*/
SQFloat ReadFloat64()
SQMOD_NODISCARD SQFloat ReadFloat64() const
{
// Validate the managed buffer reference
ValidateDeeper();
@ -689,72 +695,72 @@ public:
/* --------------------------------------------------------------------------------------------
* Read a raw string from the buffer.
*/
LightObj ReadRawString(SQInteger length);
SQMOD_NODISCARD LightObj ReadRawString(SQInteger length) const;
/* --------------------------------------------------------------------------------------------
* Read a string from the buffer.
*/
LightObj ReadClientString();
SQMOD_NODISCARD LightObj ReadClientString() const;
/* --------------------------------------------------------------------------------------------
* Read a AABB from the buffer.
*/
AABB ReadAABB();
SQMOD_NODISCARD AABB ReadAABB() const;
/* --------------------------------------------------------------------------------------------
* Read a Circle from the buffer.
*/
Circle ReadCircle();
SQMOD_NODISCARD Circle ReadCircle() const;
/* --------------------------------------------------------------------------------------------
* Read a Color3 from the buffer.
*/
Color3 ReadColor3();
SQMOD_NODISCARD Color3 ReadColor3() const;
/* --------------------------------------------------------------------------------------------
* Read a Color4 from the buffer.
*/
Color4 ReadColor4();
SQMOD_NODISCARD Color4 ReadColor4() const;
/* --------------------------------------------------------------------------------------------
* Read a Quaternion from the buffer.
*/
Quaternion ReadQuaternion();
SQMOD_NODISCARD Quaternion ReadQuaternion() const;
/* --------------------------------------------------------------------------------------------
* Read a Sphere from the buffer.
*/
Sphere ReadSphere();
SQMOD_NODISCARD Sphere ReadSphere() const;
/* --------------------------------------------------------------------------------------------
* Read a Vector2 from the buffer.
*/
Vector2 ReadVector2();
SQMOD_NODISCARD Vector2 ReadVector2() const;
/* --------------------------------------------------------------------------------------------
* Read a Vector2i from the buffer.
*/
Vector2i ReadVector2i();
SQMOD_NODISCARD Vector2i ReadVector2i() const;
/* --------------------------------------------------------------------------------------------
* Read a Vector3 from the buffer.
*/
Vector3 ReadVector3();
SQMOD_NODISCARD Vector3 ReadVector3() const;
/* --------------------------------------------------------------------------------------------
* Read a Vector4 from the buffer.
*/
Vector4 ReadVector4();
SQMOD_NODISCARD Vector4 ReadVector4() const;
/* --------------------------------------------------------------------------------------------
* Compute the CRC-32 checksums on the data in the buffer.
*/
SQInteger GetCRC32(SQInteger n);
SQMOD_NODISCARD SQInteger GetCRC32(SQInteger n) const;
/* --------------------------------------------------------------------------------------------
* Compute the Adler-32 checksums on the data in the buffer.
*/
SQInteger GetADLER32(SQInteger n);
SQMOD_NODISCARD SQInteger GetADLER32(SQInteger n) const;
};
} // Namespace:: SqMod

View File

@ -36,7 +36,7 @@ static SQChar * Bin128ToDec(const uint32_t N[4])
// Add s[] to itself in decimal, doubling it
for (j = sizeof(s) - 2; j >= 0; j--)
{
s[j] += s[j] - '0' + carry;
s[j] += s[j] - '0' + carry; // NOLINT(cppcoreguidelines-narrowing-conversions)
carry = (s[j] > '9');
@ -265,7 +265,7 @@ SQFloat GetEntryAsFloat(const MMDB_entry_data_s & ed)
}
// ------------------------------------------------------------------------------------------------
LightObj GetEntryAsLong(const MMDB_entry_data_s & ed)
SQInteger GetEntryAsLong(const MMDB_entry_data_s & ed)
{
uint64_t value = 0;
// Identify the type of entry data
@ -315,7 +315,7 @@ LightObj GetEntryAsLong(const MMDB_entry_data_s & ed)
STHROWF("Unsupported conversion from ({}) to (long)", AsTypeStr(ed.type));
}
// Return a long integer instance with the requested value
return LightObj(SqTypeIdentity< ULongInt >{}, SqVM(), value);
return static_cast< SQInteger >(value);
}
// ------------------------------------------------------------------------------------------------
@ -338,7 +338,7 @@ LightObj GetEntryAsString(const MMDB_entry_data_s & ed)
sq_pushstring(vm, fmt::format("{}", ed.double_value).c_str(), -1);
} break;
case MMDB_DATA_TYPE_BYTES: {
sq_pushstring(vm, reinterpret_cast< const SQChar * >(ed.bytes), ed.data_size / sizeof(SQChar));
sq_pushstring(vm, reinterpret_cast< const SQChar * >(ed.bytes), static_cast< SQInteger >(ed.data_size) / sizeof(SQChar));
} break;
case MMDB_DATA_TYPE_UINT16: {
sq_pushstring(vm, fmt::format("{}", ed.uint16).c_str(), -1);
@ -1051,7 +1051,7 @@ Object LookupResult::GetEntryDataList()
// ------------------------------------------------------------------------------------------------
SQInteger LookupResult::GetValue(HSQUIRRELVM vm)
{
const int32_t top = sq_gettop(vm);
const auto top = sq_gettop(vm);
// The lookup result instance
LookupResult * lookup;
// Attempt to extract the lookup result instance
@ -1294,7 +1294,7 @@ Object SearchNode::GetRightRecordEntryDataList()
// ------------------------------------------------------------------------------------------------
SQInteger SearchNode::GetRecordEntryData(HSQUIRRELVM vm, bool right)
{
const int32_t top = sq_gettop(vm);
const auto top = sq_gettop(vm);
// The search node result instance
SearchNode * node;
// Attempt to extract the search node result instance

View File

@ -5,7 +5,6 @@
// ------------------------------------------------------------------------------------------------
#include "Library/IO/Buffer.hpp"
#include "Library/Numeric/Long.hpp"
// ------------------------------------------------------------------------------------------------
#include <vector>
@ -76,7 +75,7 @@ SQFloat GetEntryAsFloat(const MMDB_entry_data_s & ed);
/* ------------------------------------------------------------------------------------------------
* Retrieve the value from the specified entry data as a long integer.
*/
LightObj GetEntryAsLong(const MMDB_entry_data_s & ed);
SQInteger GetEntryAsLong(const MMDB_entry_data_s & ed);
/* ------------------------------------------------------------------------------------------------
* Retrieve the value from the specified entry data as a string.
@ -811,7 +810,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the value from the current element as a long integer.
*/
SQMOD_NODISCARD LightObj GetLong() const
SQMOD_NODISCARD SQInteger GetLong() const
{
return GetEntryAsLong(SQMOD_GET_VALID(*this));
}
@ -1105,7 +1104,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the value from the current element as a long integer.
*/
SQMOD_NODISCARD LightObj GetLong() const
SQMOD_NODISCARD SQInteger GetLong() const
{
return GetEntryAsLong(SQMOD_GET_VALID_ELEM(*this)->entry_data);
}
@ -1492,9 +1491,9 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the build epoch.
*/
SQMOD_NODISCARD Object GetBuildEpoch() const
SQMOD_NODISCARD SQInteger GetBuildEpoch() const
{
return Object(SqTypeIdentity< ULongInt >{}, SqVM(), ConvTo< uint64_t >::From(SQMOD_GET_VALID(*this)->build_epoch));
return ConvTo< SQInteger >::From(SQMOD_GET_VALID(*this)->build_epoch);
}
/* --------------------------------------------------------------------------------------------
@ -1662,17 +1661,17 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the left record value.
*/
Object GetLeftRecord()
SQInteger GetLeftRecord()
{
return Object(SqTypeIdentity< ULongInt >{}, SqVM(), ConvTo< uint64_t >::From(SQMOD_GET_VALID(*this).left_record));
return ConvTo< SQInteger >::From(SQMOD_GET_VALID(*this).left_record);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the right record value.
*/
Object GetRightRecord()
SQInteger GetRightRecord()
{
return Object(SqTypeIdentity< ULongInt >{}, SqVM(), ConvTo< uint64_t >::From(SQMOD_GET_VALID(*this).right_record));
return ConvTo< SQInteger >::From(SQMOD_GET_VALID(*this).right_record);
}
/* --------------------------------------------------------------------------------------------

View File

@ -534,7 +534,7 @@ bool DbConvTo< bool >::From(const SQChar * value, unsigned long length, enum_fie
}
// ------------------------------------------------------------------------------------------------
bool DbConvTo< char >::From(const SQChar * value, unsigned long length, enum_field_types type, const SQChar * tn)
char DbConvTo< char >::From(const SQChar * value, unsigned long length, enum_field_types type, const SQChar * tn)
{
return ConvertToSInt< char >(value, length, type, tn);
}
@ -636,7 +636,7 @@ void ConnHnd::Create(const Account & acc)
SQMOD_THROW_CURRENT(*this, "Cannot connect to database");
}
// Attempt configure the auto-commit option
else if (mysql_autocommit(mPtr, mAutoCommit) != 0)
else if (mysql_autocommit(mPtr, static_cast< StmtBind::BoolType >(mAutoCommit)) != 0)
{
SQMOD_THROW_CURRENT(*this, "Cannot configure auto-commit");
}
@ -1555,7 +1555,7 @@ void Account::SetSSL(const SQChar * key, const SQChar * cert, const SQChar * ca,
Table Account::GetOptionsTable() const
{
// Allocate an empty table
Table tbl(SqVM(), m_Options.size());
Table tbl(SqVM(), static_cast< SQInteger >(m_Options.size()));
// Insert every option into the table
for (const auto & opt : m_Options)
{
@ -1694,7 +1694,7 @@ const ConnRef & Connection::GetCreated() const
#endif // _DEBUG
// ------------------------------------------------------------------------------------------------
Object Connection::Insert(const SQChar * query)
SQInteger Connection::Insert(const SQChar * query)
{
// Make sure the specified query is valid
if (!query || *query == '\0')
@ -1707,7 +1707,7 @@ Object Connection::Insert(const SQChar * query)
SQMOD_THROW_CURRENT(*m_Handle, "Unable to execute MySQL query");
}
// Return the identifier of the inserted row
return Object(SqTypeIdentity< ULongInt >{}, SqVM(), mysql_insert_id(m_Handle->mPtr));
return static_cast< SQInteger >(mysql_insert_id(m_Handle->mPtr));
}
// ------------------------------------------------------------------------------------------------
@ -1784,12 +1784,11 @@ SQInteger Connection::ExecuteF(HSQUIRRELVM vm)
// Attempt to execute the specified query
try
{
Var< ULongInt >::push(vm, ULongInt(conn->m_Handle->Execute(val.mPtr, static_cast<unsigned long>(val.mLen))));
sq_pushinteger(vm, static_cast< SQInteger >(conn->m_Handle->Execute(val.mPtr, static_cast< unsigned long >(val.mLen))));
}
catch (const Sqrat::Exception & e)
catch (const std::exception & e)
{
// Propagate the error
return sq_throwerror(vm, e.what());
return sq_throwerror(vm, e.what()); // Propagate the error
}
// This function returned a value
return 1;
@ -1851,12 +1850,11 @@ SQInteger Connection::InsertF(HSQUIRRELVM vm)
SQMOD_THROW_CURRENT(*(conn->m_Handle), "Unable to execute MySQL query");
}
// Return the identifier of the inserted row
Var< ULongInt >::push(vm, ULongInt(mysql_insert_id(conn->m_Handle->mPtr)));
sq_pushinteger(vm, static_cast< SQInteger >(mysql_insert_id(conn->m_Handle->mPtr)));
}
catch (const Sqrat::Exception & e)
catch (const std::exception & e)
{
// Propagate the error
return sq_throwerror(vm, e.what());
return sq_throwerror(vm, e.what()); // Propagate the error
}
// This function returned a value
return 1;
@ -2361,7 +2359,7 @@ SQInteger Field::GetUint32() const
}
// ------------------------------------------------------------------------------------------------
Object Field::GetInt64() const
SQInteger Field::GetInt64() const
{
SQMOD_VALIDATE_STEPPED(*this);
// Obtain the initial stack size
@ -2369,18 +2367,16 @@ Object Field::GetInt64() const
// Should we retrieve the value from the bind wrapper?
if (m_Handle->mStatement)
{
return Object(SqTypeIdentity< SLongInt >{}, SqVM(),
ConvTo< int64_t >::From(m_Handle->mBinds[m_Index].mInt64));
return ConvTo< SQInteger >::From(m_Handle->mBinds[m_Index].mInt64);
}
// Retrieve the value directly from the row
return Object(SqTypeIdentity< SLongInt >{}, SqVM(),
DbConvTo< int64_t >::From(m_Handle->mRow[m_Index],
return DbConvTo< SQInteger >::From(m_Handle->mRow[m_Index],
m_Handle->mLengths[m_Index],
m_Handle->mFields[m_Index].type));
m_Handle->mFields[m_Index].type);
}
// ------------------------------------------------------------------------------------------------
Object Field::GetUint64() const
SQInteger Field::GetUint64() const
{
SQMOD_VALIDATE_STEPPED(*this);
// Obtain the initial stack size
@ -2388,14 +2384,12 @@ Object Field::GetUint64() const
// Should we retrieve the value from the bind wrapper?
if (m_Handle->mStatement)
{
return Object(SqTypeIdentity< ULongInt >{}, SqVM(),
ConvTo< uint64_t >::From(m_Handle->mBinds[m_Index].mUint64));
return ConvTo< SQInteger >::From(m_Handle->mBinds[m_Index].mUint64);
}
// Retrieve the value directly from the row
return Object(SqTypeIdentity< ULongInt >{}, SqVM(),
DbConvTo< uint64_t >::From(m_Handle->mRow[m_Index],
return DbConvTo< SQInteger >::From(m_Handle->mRow[m_Index],
m_Handle->mLengths[m_Index],
m_Handle->mFields[m_Index].type));
m_Handle->mFields[m_Index].type);
}
// ------------------------------------------------------------------------------------------------
@ -2997,23 +2991,23 @@ void Statement::SetUint64(uint32_t idx, SQInteger val) const
}
// ------------------------------------------------------------------------------------------------
void Statement::SetSLongInt(uint32_t idx, const SLongInt & val) const
void Statement::SetSLongInt(uint32_t idx, SQInteger val) const
{
SQMOD_VALIDATE_PARAM(*this, idx);
// Attempt to set the input value
m_Handle->mBinds[idx].SetInput(MYSQL_TYPE_LONGLONG, &(m_Handle->mMyBinds[idx]));
// Attempt to assign the numeric value inside the specified object
m_Handle->mBinds[idx].mInt64 = val.GetNum();
m_Handle->mBinds[idx].mInt64 = val;
}
// ------------------------------------------------------------------------------------------------
void Statement::SetULongInt(uint32_t idx, const ULongInt & val) const
void Statement::SetULongInt(uint32_t idx, SQInteger val) const
{
SQMOD_VALIDATE_PARAM(*this, idx);
// Attempt to set the input value
m_Handle->mBinds[idx].SetInput(MYSQL_TYPE_LONGLONG, &(m_Handle->mMyBinds[idx]));
// Attempt to assign the numeric value inside the specified object
m_Handle->mBinds[idx].mUint64 = val.GetNum();
m_Handle->mBinds[idx].mUint64 = static_cast< uint64_t >(val);
// Specify that this value is unsigned
m_Handle->mMyBinds[idx].is_unsigned = true;
}

View File

@ -5,7 +5,6 @@
// ------------------------------------------------------------------------------------------------
#include "Library/IO/Buffer.hpp"
#include "Library/Numeric/Long.hpp"
#include "Library/Chrono.hpp"
#include "Library/Chrono/Date.hpp"
#include "Library/Chrono/Datetime.hpp"
@ -196,7 +195,7 @@ template < > struct DbConvTo< bool >
*/
template < > struct DbConvTo< char >
{
SQMOD_NODISCARD static bool From(const SQChar * value, unsigned long length, enum_field_types type, const SQChar * tn = _SC("char"));
SQMOD_NODISCARD static char From(const SQChar * value, unsigned long length, enum_field_types type, const SQChar * tn = _SC("char"));
};
/* ------------------------------------------------------------------------------------------------
@ -560,7 +559,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the used buffer.
*/
char * GetBuffer()
SQMOD_NODISCARD char * GetBuffer()
{
return mData ? mData.Data() : reinterpret_cast< char * >(&mUint64);
}
@ -1457,7 +1456,7 @@ public:
{
// Attempt to toggle auto-commit if necessary
if (SQMOD_GET_CREATED(*this)->mAutoCommit != toggle &&
mysql_autocommit(m_Handle->mPtr, toggle) != 0)
mysql_autocommit(m_Handle->mPtr, static_cast< StmtBind::BoolType >(toggle)) != 0)
{
SQMOD_THROW_CURRENT(*m_Handle, "Cannot toggle auto-commit");
}
@ -1486,15 +1485,15 @@ public:
/* --------------------------------------------------------------------------------------------
* Execute a query on the server.
*/
Object Execute(const SQChar * query)
SQInteger Execute(const SQChar * query)
{
return Object(SqTypeIdentity< ULongInt >{}, SqVM(), SQMOD_GET_CREATED(*this)->Execute(query));
return static_cast< SQInteger >(SQMOD_GET_CREATED(*this)->Execute(query));
}
/* --------------------------------------------------------------------------------------------
* Execute a query on the server.
*/
Object Insert(const SQChar * query);
SQInteger Insert(const SQChar * query);
/* --------------------------------------------------------------------------------------------
* Execute a query on the server.
@ -1866,12 +1865,12 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced field as a signed 64 bit integer value.
*/
SQMOD_NODISCARD Object GetInt64() const;
SQMOD_NODISCARD SQInteger GetInt64() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced field as an unsigned 64 bit integer value.
*/
SQMOD_NODISCARD Object GetUint64() const;
SQMOD_NODISCARD SQInteger GetUint64() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced field as a 32 bit floating point value.
@ -2111,17 +2110,17 @@ public:
/* --------------------------------------------------------------------------------------------
* Returns the current position of the row cursor for the last Next().
*/
SQMOD_NODISCARD Object RowIndex() const
SQMOD_NODISCARD SQInteger RowIndex() const
{
return Object(SqTypeIdentity< ULongInt >{}, SqVM(), SQMOD_GET_CREATED(*this)->RowIndex());
return static_cast< SQInteger >(SQMOD_GET_CREATED(*this)->RowIndex());
}
/* --------------------------------------------------------------------------------------------
* Returns the number of rows in the result set.
*/
SQMOD_NODISCARD Object RowCount() const
SQMOD_NODISCARD SQInteger RowCount() const
{
return Object(SqTypeIdentity< ULongInt >{}, SqVM(), SQMOD_GET_CREATED(*this)->RowCount());
return static_cast< SQInteger >(SQMOD_GET_CREATED(*this)->RowCount());
}
/* --------------------------------------------------------------------------------------------
@ -2143,9 +2142,9 @@ public:
/* --------------------------------------------------------------------------------------------
* Seeks to an arbitrary row in a query result set.
*/
SQMOD_NODISCARD bool SetLongRowIndex(const ULongInt & index) const
SQMOD_NODISCARD bool SetLongRowIndex(SQInteger index) const
{
return SQMOD_GET_CREATED(*this)->SetRowIndex(index.GetNum());
return SQMOD_GET_CREATED(*this)->SetRowIndex(static_cast< uint64_t >(index));
}
/* --------------------------------------------------------------------------------------------
@ -2422,7 +2421,7 @@ public:
// Do we have a valid handle?
if (m_Handle)
{
m_Handle->mQuery;
return m_Handle->mQuery;
}
// Default to an empty string
return NullString();
@ -2517,12 +2516,12 @@ public:
/* --------------------------------------------------------------------------------------------
* Assign a signed long integer to a parameter.
*/
void SetSLongInt(uint32_t idx, const SLongInt & val) const;
void SetSLongInt(uint32_t idx, SQInteger val) const;
/* --------------------------------------------------------------------------------------------
* Assign an unsigned long integer to a parameter.
*/
void SetULongInt(uint32_t idx, const ULongInt & val) const;
void SetULongInt(uint32_t idx, SQInteger val) const;
/* --------------------------------------------------------------------------------------------
* Assign a native integer to a parameter.

View File

@ -272,14 +272,6 @@ struct WebSocketClient : public SqChainedInstances< WebSocketClient >
*/
WebSocketClient & operator = (WebSocketClient &&) = delete;
/* --------------------------------------------------------------------------------------------
* Retrieve the associated user tag.
*/
SQMOD_NODISCARD const String & GetTag() const
{
return mTag;
}
/* --------------------------------------------------------------------------------------------
* Return whether the associated connection handle is valid.
*/
@ -297,6 +289,14 @@ struct WebSocketClient : public SqChainedInstances< WebSocketClient >
return mClosing.load();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the associated user tag.
*/
SQMOD_NODISCARD const String & GetTag() const
{
return mTag;
}
/* --------------------------------------------------------------------------------------------
* Modify the associated user tag.
*/

View File

@ -5,14 +5,12 @@
namespace SqMod {
// ------------------------------------------------------------------------------------------------
extern void Register_LongInt(HSQUIRRELVM vm);
extern void Register_Math(HSQUIRRELVM vm);
extern void Register_Random(HSQUIRRELVM vm);
// ================================================================================================
void Register_Numeric(HSQUIRRELVM vm)
{
Register_LongInt(vm);
Register_Math(vm);
Register_Random(vm);
}

View File

@ -1,376 +0,0 @@
// ------------------------------------------------------------------------------------------------
#include "Library/Numeric/Long.hpp"
#include "Library/Numeric/Random.hpp"
#include "Base/DynArg.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstdio>
#include <cstdlib>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMOD_DECL_TYPENAME(TypenameS, _SC("SLongInt"))
SQMOD_DECL_TYPENAME(TypenameU, _SC("ULongInt"))
// ------------------------------------------------------------------------------------------------
LongInt< signed long long >::LongInt(const SQChar * text)
: m_Data(0), m_Text()
{
m_Data = std::strtoll(text, nullptr, 10);
}
// ------------------------------------------------------------------------------------------------
LongInt< signed long long >::LongInt(const SQChar * text, uint32_t base)
: m_Data(0), m_Text()
{
m_Data = std::strtoll(text, nullptr, base);
}
// ------------------------------------------------------------------------------------------------
LongInt< signed long long > & LongInt< signed long long >::operator = (const SQChar * text)
{
m_Data = std::strtoll(text, nullptr, 10);
return *this;
}
// ------------------------------------------------------------------------------------------------
const SQChar * LongInt< signed long long >::ToString()
{
if (std::snprintf(m_Text, sizeof(m_Text), "%llu", m_Data) < 0)
{
m_Text[0] = 0;
}
return m_Text;
}
// ------------------------------------------------------------------------------------------------
void LongInt< signed long long >::Random()
{
m_Data = GetRandomInt64();
}
// ------------------------------------------------------------------------------------------------
void LongInt< signed long long >::Random(Type n)
{
m_Data = GetRandomInt64(n);
}
// ------------------------------------------------------------------------------------------------
void LongInt< signed long long >::Random(Type m, Type n)
{
m_Data = GetRandomInt64(m, n);
}
// ------------------------------------------------------------------------------------------------
LongInt< unsigned long long >::LongInt(const SQChar * text)
: m_Data(0), m_Text()
{
m_Data = std::strtoull(text, nullptr, 10);
}
// ------------------------------------------------------------------------------------------------
LongInt< unsigned long long >::LongInt(const SQChar * text, uint32_t base)
: m_Data(0), m_Text()
{
m_Data = std::strtoull(text, nullptr, base);
}
// ------------------------------------------------------------------------------------------------
LongInt< unsigned long long > & LongInt< unsigned long long >::operator = (const SQChar * text)
{
m_Data = std::strtoull(text, nullptr, 10);
return *this;
}
// ------------------------------------------------------------------------------------------------
const SQChar * LongInt< unsigned long long >::ToString()
{
if (std::snprintf(m_Text, sizeof(m_Text), "%llu", m_Data) < 0)
{
m_Text[0] = 0;
}
return m_Text;
}
// ------------------------------------------------------------------------------------------------
void LongInt< unsigned long long >::Random()
{
m_Data = GetRandomUint64();
}
// ------------------------------------------------------------------------------------------------
void LongInt< unsigned long long >::Random(Type n)
{
m_Data = GetRandomUint64(n);
}
// ------------------------------------------------------------------------------------------------
void LongInt< unsigned long long >::Random(Type m, Type n)
{
m_Data = GetRandomUint64(m, n);
}
// ------------------------------------------------------------------------------------------------
signed long long PopStackSLong(HSQUIRRELVM vm, SQInteger idx)
{
// Identify which type must be extracted
switch (sq_gettype(vm, idx))
{
case OT_INTEGER:
{
SQInteger val;
sq_getinteger(vm, idx, &val);
return static_cast< signed long long >(val);
}
case OT_FLOAT:
{
SQFloat val;
sq_getfloat(vm, idx, &val);
return ConvTo< signed long long >::From(val);
}
case OT_BOOL:
{
SQBool val;
sq_getbool(vm, idx, &val);
return static_cast< signed long long >(val);
}
case OT_STRING:
{
const SQChar * val = nullptr;
// Attempt to retrieve and convert the string
if (SQ_SUCCEEDED(sq_getstring(vm, idx, &val)) && val != nullptr && *val != '\0')
{
return std::strtoll(val, nullptr, 10);
}
} break;
case OT_ARRAY:
case OT_TABLE:
case OT_CLASS:
case OT_USERDATA:
{
return static_cast< signed long long >(sq_getsize(vm, idx));
}
case OT_INSTANCE:
{
// Attempt to treat the value as a signed long instance
try
{
return Var< const SLongInt & >(vm, idx).value.GetNum();
}
catch (...)
{
// Just ignore it...
}
// Attempt to treat the value as a unsigned long instance
try
{
return ConvTo< signed long long >::From(Var< const ULongInt & >(vm, idx).value.GetNum());
}
catch (...)
{
// Just ignore it...
}
// Attempt to get the size of the instance as a fall back
return static_cast< signed long long >(sq_getsize(vm, idx));
}
default: break;
}
// Default to 0
return 0;
}
// ------------------------------------------------------------------------------------------------
unsigned long long PopStackULong(HSQUIRRELVM vm, SQInteger idx)
{
// Identify which type must be extracted
switch (sq_gettype(vm, idx))
{
case OT_INTEGER:
{
SQInteger val;
sq_getinteger(vm, idx, &val);
return ConvTo< unsigned long long >::From(val);
}
case OT_FLOAT:
{
SQFloat val;
sq_getfloat(vm, idx, &val);
return ConvTo< unsigned long long >::From(val);
}
case OT_BOOL:
{
SQBool val;
sq_getbool(vm, idx, &val);
return ConvTo< unsigned long long >::From(val);
}
case OT_STRING:
{
const SQChar * val = nullptr;
// Attempt to retrieve and convert the string
if (SQ_SUCCEEDED(sq_getstring(vm, idx, &val)) && val != nullptr && *val != '\0')
{
return std::strtoull(val, nullptr, 10);
}
} break;
case OT_ARRAY:
case OT_TABLE:
case OT_CLASS:
case OT_USERDATA:
{
return ConvTo< unsigned long long >::From(sq_getsize(vm, idx));
}
case OT_INSTANCE:
{
// Attempt to treat the value as a signed long instance
try
{
return ConvTo< unsigned long long >::From(Var< const SLongInt & >(vm, idx).value.GetNum());
}
catch (...)
{
// Just ignore it...
}
// Attempt to treat the value as a unsigned long instance
try
{
return Var< const ULongInt & >(vm, idx).value.GetNum();
}
catch (...)
{
// Just ignore it...
}
// Attempt to get the size of the instance as a fall back
return ConvTo< unsigned long long >::From(sq_getsize(vm, idx));
}
default: break;
}
// Default to 0
return 0;
}
// ------------------------------------------------------------------------------------------------
const SLongInt & GetSLongInt()
{
static SLongInt l;
l.SetNum(0);
return l;
}
const SLongInt & GetSLongInt(signed long long n)
{
static SLongInt l;
l.SetNum(n);
return l;
}
const SLongInt & GetSLongInt(const SQChar * s)
{
static SLongInt l;
l = s;
return l;
}
const ULongInt & GetULongInt()
{
static ULongInt l;
l.SetNum(0);
return l;
}
const ULongInt & GetULongInt(unsigned long long n)
{
static ULongInt l;
l.SetNum(n);
return l;
}
const ULongInt & GetULongInt(const SQChar * s)
{
static ULongInt l;
l = s;
return l;
}
// ================================================================================================
void Register_LongInt(HSQUIRRELVM vm)
{
RootTable(vm).Bind(TypenameS::Str,
Class< SLongInt >(vm, TypenameS::Str)
// Constructors
.Ctor()
.Ctor< SLongInt::Type >()
.template Ctor< const char *, SQInteger >()
// Properties
.Prop(_SC("Str"), &SLongInt::GetCStr, &SLongInt::SetStr)
.Prop(_SC("Num"), &SLongInt::GetSNum, &SLongInt::SetNum)
// Core Meta-methods
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< SLongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, SLongInt, ULongInt >)
.SquirrelFunc(_SC("_typename"), &TypenameS::Fn)
.Func(_SC("_tostring"), &SLongInt::ToString)
// Core Functions
.Func(_SC("tointeger"), &SLongInt::ToSqInteger)
.Func(_SC("tofloat"), &SLongInt::ToSqFloat)
.Func(_SC("tostring"), &SLongInt::ToSqString)
.Func(_SC("tobool"), &SLongInt::ToSqBool)
.Func(_SC("tochar"), &SLongInt::ToSqChar)
// Meta-methods
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< SLongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, SLongInt, ULongInt >)
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< SLongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, SLongInt, ULongInt >)
.SquirrelFunc(_SC("_mul"), &SqDynArgFwd< SqDynArgMulFn< SLongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, SLongInt, ULongInt >)
.SquirrelFunc(_SC("_div"), &SqDynArgFwd< SqDynArgDivFn< SLongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, SLongInt, ULongInt >)
.SquirrelFunc(_SC("_modulo"), &SqDynArgFwd< SqDynArgModFn< SLongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, SLongInt, ULongInt >)
.Func< SLongInt (SLongInt::*)(void) const >(_SC("_unm"), &SLongInt::operator -)
// Functions
.Func(_SC("GetStr"), &SLongInt::GetCStr)
.Func(_SC("SetStr"), &SLongInt::SetStr)
.Func(_SC("GetNum"), &SLongInt::GetSNum)
.Func(_SC("SetNum"), &SLongInt::SetNum)
// Overloads
.Overload< void (SLongInt::*)(void) >(_SC("Random"), &SLongInt::Random)
.Overload< void (SLongInt::*)(SLongInt::Type) >(_SC("Random"), &SLongInt::Random)
.Overload< void (SLongInt::*)(SLongInt::Type, SLongInt::Type) >(_SC("Random"), &SLongInt::Random)
);
RootTable(vm).Bind(TypenameU::Str,
Class< ULongInt >(vm, TypenameU::Str)
// Constructors
.Ctor()
.Ctor< ULongInt::Type >()
.Ctor< const char *, SQInteger >()
// Properties
.Prop(_SC("Str"), &ULongInt::GetCStr, &ULongInt::SetStr)
.Prop(_SC("Num"), &ULongInt::GetSNum, &ULongInt::SetNum)
// Core Meta-methods
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< ULongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, ULongInt, SLongInt >)
.SquirrelFunc(_SC("_typename"), &TypenameU::Fn)
.Func(_SC("_tostring"), &ULongInt::ToString)
// Core Functions
.Func(_SC("tointeger"), &ULongInt::ToSqInteger)
.Func(_SC("tofloat"), &ULongInt::ToSqFloat)
.Func(_SC("tostring"), &ULongInt::ToSqString)
.Func(_SC("tobool"), &ULongInt::ToSqBool)
.Func(_SC("tochar"), &ULongInt::ToSqChar)
// Meta-methods
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< ULongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, ULongInt, SLongInt >)
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< ULongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, ULongInt, SLongInt >)
.SquirrelFunc(_SC("_mul"), &SqDynArgFwd< SqDynArgMulFn< ULongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, ULongInt, SLongInt >)
.SquirrelFunc(_SC("_div"), &SqDynArgFwd< SqDynArgDivFn< ULongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, ULongInt, SLongInt >)
.SquirrelFunc(_SC("_modulo"), &SqDynArgFwd< SqDynArgModFn< ULongInt >, SQInteger, SQFloat, bool, std::nullptr_t, const SQChar *, ULongInt, SLongInt >)
.Func< ULongInt (ULongInt::*)(void) const >(_SC("_unm"), &ULongInt::operator -)
// Functions
.Func(_SC("GetStr"), &ULongInt::GetCStr)
.Func(_SC("SetStr"), &ULongInt::SetStr)
.Func(_SC("GetNum"), &ULongInt::GetSNum)
.Func(_SC("SetNum"), &ULongInt::SetNum)
// Overloads
.Overload< void (ULongInt::*)(void) >(_SC("Random"), &ULongInt::Random)
.Overload< void (ULongInt::*)(ULongInt::Type) >(_SC("Random"), &ULongInt::Random)
.Overload< void (ULongInt::*)(ULongInt::Type, ULongInt::Type) >(_SC("Random"), &ULongInt::Random)
);
}
} // Namespace:: SqMod

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,5 @@
// ------------------------------------------------------------------------------------------------
#include "Library/Numeric/Math.hpp"
#include "Library/Numeric/Long.hpp"
// ------------------------------------------------------------------------------------------------
#include <cmath>
@ -66,7 +65,7 @@ static SQInteger SqRemainder(HSQUIRRELVM vm)
// Are we both arguments integers?
else if ((sq_gettype(vm, 2) == OT_INTEGER) && sq_gettype(vm, 3) == OT_INTEGER)
{ // NOLINT(bugprone-branch-clone)
sq_pushinteger(vm, std::remainder(PopStackInteger(vm, 2), PopStackInteger(vm, 3)));
sq_pushinteger(vm, static_cast< SQInteger >(std::remainder(PopStackInteger(vm, 2), PopStackInteger(vm, 3))));
}
// Is the first argument float?
else if ((sq_gettype(vm, 2) == OT_FLOAT))
@ -76,7 +75,7 @@ static SQInteger SqRemainder(HSQUIRRELVM vm)
// Is the first argument integer?
else if ((sq_gettype(vm, 2) == OT_INTEGER))
{
sq_pushinteger(vm, std::remainder(PopStackInteger(vm, 2), PopStackInteger(vm, 3)));
sq_pushinteger(vm, static_cast< SQInteger >(std::remainder(PopStackInteger(vm, 2), PopStackInteger(vm, 3))));
}
// Default to both arguments as float so we don't loos precision from the float one
else
@ -184,18 +183,7 @@ static SQInteger SqNanL(HSQUIRRELVM vm)
return val.mRes; // Propagate the error!
}
// Fetch the arguments from the stack and perform the requested operation
try
{
Var< SLongInt * >::push(vm, new SLongInt(std::nanl(val.mPtr)));
}
catch (const std::exception & e)
{
return sq_throwerror(vm, e.what());
}
catch (...)
{
return sq_throwerror(vm, _SC("Failed to create a long integer instance"));
}
sq_pushinteger(vm, static_cast< SQInteger >(std::nanl(val.mPtr)));
// Specify that we have a value on the stack
return 1;
}
@ -659,11 +647,11 @@ static SQInteger SqRoundI(HSQUIRRELVM vm)
// Fetch the arguments from the stack and perform the requested operation
if (sq_gettype(vm, 2) == OT_FLOAT)
{
sq_pushinteger(vm, ConvTo< SQInteger >::From(std::llround(PopStackFloat(vm, 2))));
sq_pushinteger(vm, static_cast< SQInteger >(std::llround(PopStackFloat(vm, 2))));
}
else
{
sq_pushinteger(vm, ConvTo< SQInteger >::From(std::llround(PopStackInteger(vm, 2))));
sq_pushinteger(vm, static_cast< SQInteger >(std::llround(PopStackInteger(vm, 2))));
}
// Specify that we have a value on the stack
return 1;
@ -678,24 +666,13 @@ static SQInteger SqRoundL(HSQUIRRELVM vm)
return sq_throwerror(vm, "Wrong number of arguments");
}
// Fetch the arguments from the stack and perform the requested operation
try
if (sq_gettype(vm, 2) == OT_FLOAT)
{
if (sq_gettype(vm, 2) == OT_FLOAT)
{
Var< SLongInt * >::push(vm, new SLongInt(std::llround(PopStackFloat(vm, 2))));
}
else
{
Var< SLongInt * >::push(vm, new SLongInt(std::llround(PopStackInteger(vm, 2))));
}
sq_pushinteger(vm, static_cast< SQInteger >(std::llround(PopStackFloat(vm, 2))));
}
catch (const std::exception & e)
else
{
return sq_throwerror(vm, e.what());
}
catch (...)
{
return sq_throwerror(vm, _SC("Failed to create a long integer instance"));
sq_pushinteger(vm, static_cast< SQInteger >(std::llround(PopStackInteger(vm, 2))));
}
// Specify that we have a value on the stack
return 1;
@ -760,7 +737,7 @@ static SQInteger SqLdexp(HSQUIRRELVM vm)
return sq_throwerror(vm, "Wrong number of arguments");
}
// Fetch the arguments from the stack and perform the requested operation
sq_pushfloat(vm, std::ldexp(PopStackFloat(vm, 2), PopStackInteger(vm, 3)));
sq_pushfloat(vm, std::ldexp(PopStackFloat(vm, 2), static_cast< int >(PopStackInteger(vm, 3))));
// Specify that we have a value on the stack
return 1;
}
@ -811,9 +788,9 @@ static SQInteger SqScalbn(HSQUIRRELVM vm)
}
// Fetch the arguments from the stack and perform the requested operation
#ifdef _SQ64
sq_pushfloat(vm, std::scalbln(PopStackFloat(vm, 2), PopStackInteger(vm, 3)));
sq_pushfloat(vm, std::scalbln(PopStackFloat(vm, 2), static_cast< int >(PopStackInteger(vm, 3))));
#else
sq_pushfloat(vm, std::scalbn(PopStackFloat(vm, 2), PopStackInteger(vm, 3)));
sq_pushfloat(vm, std::scalbn(PopStackFloat(vm, 2), static_cast< int >(PopStackInteger(vm, 3))));
#endif // _SQ64
// Specify that we have a value on the stack
return 1;
@ -1066,7 +1043,7 @@ static SQInteger SqDigits1(HSQUIRRELVM vm)
return sq_throwerror(vm, "Wrong number of arguments");
}
// Fetch the integer value from the stack
int64_t n = std::llabs(PopStackSLong(vm, 2));
int64_t n = std::llabs(PopStackInteger(vm, 2));
// Start with 0 digits
uint8_t d = 0;
// Identify the number of digits
@ -1090,7 +1067,7 @@ static SQInteger SqDigits0(HSQUIRRELVM vm)
return sq_throwerror(vm, "Wrong number of arguments");
}
// Fetch the integer value from the stack
int64_t n = std::llabs(PopStackSLong(vm, 2));
int64_t n = std::llabs(PopStackInteger(vm, 2));
// Start with 0 digits
uint8_t d = 0;
// Identify the number of digits

View File

@ -1,7 +1,7 @@
#pragma once
// ------------------------------------------------------------------------------------------------
#include "Core/Common.hpp"
#include "Core/Utility.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {

View File

@ -424,21 +424,21 @@ int32_t ReleaseMemory(int32_t bytes)
}
// ------------------------------------------------------------------------------------------------
Object GetMemoryUsage()
SQInteger GetMemoryUsage()
{
// Obtain the initial stack size
const StackGuard sg;
// Push a long integer instance with the requested value on the stack
return Object(new SLongInt(sqlite3_memory_used()));
return sqlite3_memory_used();
}
// ------------------------------------------------------------------------------------------------
Object GetMemoryHighwaterMark(bool reset)
SQInteger GetMemoryHighwaterMark(bool reset)
{
// Obtain the initial stack size
const StackGuard sg;
// Push a long integer instance with the requested value on the stack
return Object(new SLongInt(sqlite3_memory_highwater(reset)));
return sqlite3_memory_highwater(reset);
}
// ------------------------------------------------------------------------------------------------
@ -1585,11 +1585,11 @@ void SQLiteParameter::SetUint32(SQInteger value)
}
// ------------------------------------------------------------------------------------------------
void SQLiteParameter::SetInt64(const Object & value)
void SQLiteParameter::SetInt64(SQInteger value)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_int64(m_Handle->mPtr, m_Index, value.Cast< const SLongInt & >().GetNum());
m_Handle->mStatus = sqlite3_bind_int64(m_Handle->mPtr, m_Index, value);
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
@ -1598,11 +1598,11 @@ void SQLiteParameter::SetInt64(const Object & value)
}
// ------------------------------------------------------------------------------------------------
void SQLiteParameter::SetUint64(const Object & value)
void SQLiteParameter::SetUint64(SQInteger value)
{
SQMOD_VALIDATE_CREATED(*this);
// Attempt to bind the specified value
m_Handle->mStatus = sqlite3_bind_int64(m_Handle->mPtr, m_Index, value.Cast< const ULongInt & >().GetNum());
m_Handle->mStatus = sqlite3_bind_int64(m_Handle->mPtr, m_Index, value);
// Validate the result
if (m_Handle->mStatus != SQLITE_OK)
{
@ -2315,11 +2315,11 @@ SQFloat SQLiteColumn::GetFloat() const
}
// ------------------------------------------------------------------------------------------------
Object SQLiteColumn::GetLong() const
SQInteger SQLiteColumn::GetLong() const
{
SQMOD_VALIDATE_ROW(*this);
// Return the requested information
return Object(new SLongInt(sqlite3_column_int64(m_Handle->mPtr, m_Index)));
return sqlite3_column_int64(m_Handle->mPtr, m_Index);
}
// ------------------------------------------------------------------------------------------------

View File

@ -5,7 +5,6 @@
// ------------------------------------------------------------------------------------------------
#include "Library/IO/Buffer.hpp"
#include "Library/Numeric/Long.hpp"
#include "Library/Chrono/Date.hpp"
#include "Library/Chrono/Datetime.hpp"
#include "Library/Chrono/Time.hpp"
@ -95,12 +94,12 @@ Object GetStatementObj(const StmtRef & stmt);
/* ------------------------------------------------------------------------------------------------
* Tests if a certain query string is empty.
*/
bool IsQueryEmpty(const SQChar * str);
SQMOD_NODISCARD bool IsQueryEmpty(const SQChar * str);
/* ------------------------------------------------------------------------------------------------
* Retrieve the string representation of a certain status code.
*/
const SQChar * GetErrStr(int32_t status);
SQMOD_NODISCARD const SQChar * GetErrStr(int32_t status);
/* ------------------------------------------------------------------------------------------------
* Set a specific heap limit.
@ -115,32 +114,32 @@ int32_t ReleaseMemory(int32_t bytes);
/* ------------------------------------------------------------------------------------------------
* Retrieve the current memory usage.
*/
Object GetMemoryUsage();
SQMOD_NODISCARD SQInteger GetMemoryUsage();
/* ------------------------------------------------------------------------------------------------
* Retrieve the memory high watermark.
*/
Object GetMemoryHighwaterMark(bool reset);
SQMOD_NODISCARD SQInteger GetMemoryHighwaterMark(bool reset);
/* ------------------------------------------------------------------------------------------------
* Retrieve the escaped version of the specified string.
*/
LightObj EscapeString(StackStrF & str);
SQMOD_NODISCARD LightObj EscapeString(StackStrF & str);
/* ------------------------------------------------------------------------------------------------
* Retrieve the escaped version of the specified string using the supplied format specifier.
*/
LightObj EscapeStringEx(SQChar spec, StackStrF & str);
SQMOD_NODISCARD LightObj EscapeStringEx(SQChar spec, StackStrF & str);
/* ------------------------------------------------------------------------------------------------
* Convert the values from the specified array to a list of column names string.
*/
LightObj ArrayToQueryColumns(Array & arr);
SQMOD_NODISCARD LightObj ArrayToQueryColumns(Array & arr);
/* ------------------------------------------------------------------------------------------------
* Convert the keys from the specified array to a list of column names string.
*/
LightObj TableToQueryColumns(Table & tbl);
SQMOD_NODISCARD LightObj TableToQueryColumns(Table & tbl);
/* ------------------------------------------------------------------------------------------------
* The structure that holds the data associated with a certain connection.
@ -701,9 +700,9 @@ public:
/* --------------------------------------------------------------------------------------------
* Get the row-id of the most recent successful INSERT into the database from the current connection.
*/
SQMOD_NODISCARD Object GetLastInsertRowID() const
SQMOD_NODISCARD SQInteger GetLastInsertRowID() const
{
return Object(new SLongInt(sqlite3_last_insert_rowid(SQMOD_GET_CREATED(*this)->mPtr)));
return sqlite3_last_insert_rowid(SQMOD_GET_CREATED(*this)->mPtr);
}
/* --------------------------------------------------------------------------------------------
@ -1148,12 +1147,12 @@ public:
/* --------------------------------------------------------------------------------------------
* Attempt to bind a signed 64 bit integer value at the referenced parameter index.
*/
void SetInt64(const Object & value);
void SetInt64(SQInteger value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind an unsigned 64 bit integer value at the referenced parameter index.
*/
void SetUint64(const Object & value);
void SetUint64(SQInteger value);
/* --------------------------------------------------------------------------------------------
* Attempt to bind a native floating point value at the referenced parameter index.
@ -1538,7 +1537,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a long integer.
*/
SQMOD_NODISCARD Object GetLong() const;
SQMOD_NODISCARD SQInteger GetLong() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced column as a string.
@ -2101,7 +2100,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Attempt to bind a signed 64 bit integer value at the specified parameter index.
*/
SQLiteStatement & SetInt64(const Object & param, const Object & value)
SQLiteStatement & SetInt64(const Object & param, SQInteger value)
{
SQLiteParameter(SQMOD_GET_CREATED(*this), param).SetInt64(value);
// Allow chaining of operations
@ -2111,7 +2110,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Attempt to bind an unsigned 64 bit integer value at the specified parameter index.
*/
SQLiteStatement & SetUint64(const Object & param, const Object & value)
SQLiteStatement & SetUint64(const Object & param, SQInteger value)
{
SQLiteParameter(SQMOD_GET_CREATED(*this), param).SetUint64(value);
// Allow chaining of operations

View File

@ -108,99 +108,99 @@ bool XmlNode::RemoveAttrInst(const XmlAttribute & attr)
}
// ------------------------------------------------------------------------------------------------
LightObj XmlAttribute::AsLong(const SLongInt & def) const
SQInteger XmlAttribute::AsLong(SQInteger def) const
{
return LightObj(SqTypeIdentity< SLongInt >{}, SqVM(), m_Attr.as_llong(def.GetNum()));
return m_Attr.as_llong(def);
}
// ------------------------------------------------------------------------------------------------
LightObj XmlAttribute::AsUlong(const ULongInt & def) const
SQInteger XmlAttribute::AsUlong(SQInteger def) const
{
return LightObj(SqTypeIdentity< ULongInt >{}, SqVM(), m_Attr.as_ullong(def.GetNum()));
return static_cast< SQInteger >(m_Attr.as_ullong(static_cast< uint64_t >(def)));
}
// ------------------------------------------------------------------------------------------------
bool XmlAttribute::ApplyLong(const SLongInt & value)
bool XmlAttribute::ApplyLong(SQInteger value)
{
return m_Attr.set_value(value.GetNum());
return m_Attr.set_value(value);
}
// ------------------------------------------------------------------------------------------------
bool XmlAttribute::ApplyUlong(const ULongInt & value)
bool XmlAttribute::ApplyUlong(SQInteger value)
{
return m_Attr.set_value(value.GetNum());
return m_Attr.set_value(value);
}
// ------------------------------------------------------------------------------------------------
LightObj XmlAttribute::GetLong() const
SQInteger XmlAttribute::GetLong() const
{
return LightObj(SqTypeIdentity< SLongInt >{}, SqVM(), m_Attr.as_llong());
return m_Attr.as_llong();
}
// ------------------------------------------------------------------------------------------------
void XmlAttribute::SetLong(const SLongInt & value)
void XmlAttribute::SetLong(SQInteger value)
{
m_Attr = value.GetNum();
m_Attr = value;
}
// ------------------------------------------------------------------------------------------------
LightObj XmlAttribute::GetUlong() const
SQInteger XmlAttribute::GetUlong() const
{
return LightObj(SqTypeIdentity< ULongInt >{}, SqVM(), m_Attr.as_ullong());
return static_cast< SQInteger >(m_Attr.as_ullong());
}
// ------------------------------------------------------------------------------------------------
void XmlAttribute::SetUlong(const ULongInt & value)
void XmlAttribute::SetUlong(SQInteger value)
{
m_Attr = value.GetNum();
m_Attr = static_cast< uint64_t >(value);
}
// ------------------------------------------------------------------------------------------------
LightObj XmlText::AsLong(const SLongInt & def) const
SQInteger XmlText::AsLong(SQInteger def) const
{
return LightObj(SqTypeIdentity< SLongInt >{}, SqVM(), m_Text.as_llong(def.GetNum()));
return m_Text.as_llong(def);
}
// ------------------------------------------------------------------------------------------------
LightObj XmlText::AsUlong(const ULongInt & def) const
SQInteger XmlText::AsUlong(SQInteger def) const
{
return LightObj(SqTypeIdentity< ULongInt >{}, SqVM(), m_Text.as_ullong(def.GetNum()));
return static_cast< SQInteger >(m_Text.as_ullong(static_cast< uint64_t >(def)));
}
// ------------------------------------------------------------------------------------------------
bool XmlText::ApplyLong(const SLongInt & value)
bool XmlText::ApplyLong(SQInteger value)
{
return m_Text.set(value.GetNum());
return m_Text.set(value);
}
// ------------------------------------------------------------------------------------------------
bool XmlText::ApplyUlong(const ULongInt & value)
bool XmlText::ApplyUlong(SQInteger value)
{
return m_Text.set(value.GetNum());
return m_Text.set(static_cast< uint64_t >(value));
}
// ------------------------------------------------------------------------------------------------
LightObj XmlText::GetLong() const
SQInteger XmlText::GetLong() const
{
return LightObj(SqTypeIdentity< SLongInt >{}, SqVM(), m_Text.as_llong());
return m_Text.as_llong();
}
// ------------------------------------------------------------------------------------------------
void XmlText::SetLong(const SLongInt & value)
void XmlText::SetLong(SQInteger value)
{
m_Text = value.GetNum();
m_Text = value;
}
// ------------------------------------------------------------------------------------------------
LightObj XmlText::GetUlong() const
SQInteger XmlText::GetUlong() const
{
return LightObj(SqTypeIdentity< SLongInt >{}, SqVM(), m_Text.as_ullong());
return static_cast< SQInteger >(m_Text.as_ullong());
}
// ------------------------------------------------------------------------------------------------
void XmlText::SetUlong(const ULongInt & value)
void XmlText::SetUlong(SQInteger value)
{
m_Text = value.GetNum();
m_Text = static_cast< uint64_t >(value);
}
// ------------------------------------------------------------------------------------------------

View File

@ -3,9 +3,6 @@
// ------------------------------------------------------------------------------------------------
#include "Core/Utility.hpp"
// ------------------------------------------------------------------------------------------------
#include "Library/Numeric/Long.hpp"
// ------------------------------------------------------------------------------------------------
#include <pugixml.hpp>
#include <utility>
@ -1420,12 +1417,12 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the value as a long integer or the specified default value if empty.
*/
SQMOD_NODISCARD LightObj AsLong(const SLongInt & def) const;
SQMOD_NODISCARD SQInteger AsLong(SQInteger def) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value as a unsigned long integer or the specified default value if empty.
*/
SQMOD_NODISCARD LightObj AsUlong(const ULongInt & def) const;
SQMOD_NODISCARD SQInteger AsUlong(SQInteger def) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value as a boolean or the specified default value if empty.
@ -1478,12 +1475,12 @@ public:
/* --------------------------------------------------------------------------------------------
* Modify the value as a long integer.
*/
bool ApplyLong(const SLongInt & value);
bool ApplyLong(SQInteger value);
/* --------------------------------------------------------------------------------------------
* Modify the value as a unsigned long integer.
*/
bool ApplyUlong(const ULongInt & value);
bool ApplyUlong(SQInteger value);
/* --------------------------------------------------------------------------------------------
* Modify the value as a boolean.
@ -1576,22 +1573,22 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the value as a long integer.
*/
SQMOD_NODISCARD LightObj GetLong() const;
SQMOD_NODISCARD SQInteger GetLong() const;
/* --------------------------------------------------------------------------------------------
* Modify the value as a long integer.
*/
void SetLong(const SLongInt & value);
void SetLong(SQInteger value);
/* --------------------------------------------------------------------------------------------
* Retrieve the value as a unsigned long integer.
*/
SQMOD_NODISCARD LightObj GetUlong() const;
SQMOD_NODISCARD SQInteger GetUlong() const;
/* --------------------------------------------------------------------------------------------
* Modify the value as a unsigned long integer.
*/
void SetUlong(const ULongInt & value);
void SetUlong(SQInteger value);
/* --------------------------------------------------------------------------------------------
* Retrieve the value as a boolean.
@ -1772,12 +1769,12 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the value as a long integer or the specified default value if empty.
*/
SQMOD_NODISCARD LightObj AsLong(const SLongInt & def) const;
SQMOD_NODISCARD SQInteger AsLong(SQInteger def) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value as a unsigned long integer or the specified default value if empty.
*/
SQMOD_NODISCARD LightObj AsUlong(const ULongInt & def) const;
SQMOD_NODISCARD SQInteger AsUlong(SQInteger def) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value as a boolean or the specified default value if empty.
@ -1830,12 +1827,12 @@ public:
/* --------------------------------------------------------------------------------------------
* Modify the value as a long integer.
*/
bool ApplyLong(const SLongInt & value);
bool ApplyLong(SQInteger value);
/* --------------------------------------------------------------------------------------------
* Modify the value as a unsigned long integer.
*/
bool ApplyUlong(const ULongInt & value);
bool ApplyUlong(SQInteger value);
/* --------------------------------------------------------------------------------------------
* Modify the value as a boolean.
@ -1928,22 +1925,22 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the value as a long integer.
*/
SQMOD_NODISCARD LightObj GetLong() const;
SQMOD_NODISCARD SQInteger GetLong() const;
/* --------------------------------------------------------------------------------------------
* Modify the value as a long integer.
*/
void SetLong(const SLongInt & value);
void SetLong(SQInteger value);
/* --------------------------------------------------------------------------------------------
* Retrieve the value as a unsigned long integer.
*/
SQMOD_NODISCARD LightObj GetUlong() const;
SQMOD_NODISCARD SQInteger GetUlong() const;
/* --------------------------------------------------------------------------------------------
* Modify the value as a unsigned long integer.
*/
void SetUlong(const ULongInt & value);
void SetUlong(SQInteger value);
/* --------------------------------------------------------------------------------------------
* Retrieve the value as a boolean.

View File

@ -24,6 +24,9 @@ extern void ProcessRoutines();
extern void ProcessTasks();
extern void ProcessThreads();
extern void ProcessNet();
#ifdef VCMP_ENABLE_DISCORD
extern void ProcessDPP();
#endif
/* ------------------------------------------------------------------------------------------------
* Will the scripts be reloaded at the end of the current event?
@ -172,6 +175,10 @@ static void OnServerFrame(float elapsed_time)
ProcessThreads();
// Process network
ProcessNet();
// Process DPP
#ifdef VCMP_ENABLE_DISCORD
ProcessDPP();
#endif
// Process log messages from other threads
Logger::Get().ProcessQueue();
// See if a reload was requested

View File

@ -4,7 +4,6 @@
#include "Base/Color3.hpp"
#include "Base/Vector2.hpp"
#include "Entity/Player.hpp"
#include "Library/Numeric/Long.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
@ -173,9 +172,9 @@ void SendPluginCommand(uint32_t identifier, StackStrF & payload)
}
// ------------------------------------------------------------------------------------------------
const ULongInt & GetTime()
SQInteger GetTime()
{
return GetULongInt(_Func->GetTime());
return static_cast< SQInteger >(_Func->GetTime());
}
// ------------------------------------------------------------------------------------------------
@ -218,7 +217,7 @@ const SQChar * GetPluginAuthor()
}
// ------------------------------------------------------------------------------------------------
int32_t GetPluginID()
uint32_t GetPluginID()
{
return _Info->pluginId;
}
@ -242,7 +241,7 @@ uint32_t GetServerFlags()
}
// ------------------------------------------------------------------------------------------------
int32_t GetMaxPlayers()
uint32_t GetMaxPlayers()
{
return _Func->GetMaxPlayers();
}
@ -468,7 +467,7 @@ int32_t GetTimeRate()
}
// ------------------------------------------------------------------------------------------------
void SetTimeRate(uint32_t rate)
void SetTimeRate(int32_t rate)
{
_Func->SetTimeRate(rate);
}

View File

@ -49,7 +49,7 @@ void SendPluginCommand(uint32_t identifier, StackStrF & payload);
/* ------------------------------------------------------------------------------------------------
* Retrieve the server time.
*/
const ULongInt & GetTime();
SQInteger GetTime();
/* ------------------------------------------------------------------------------------------------
* Send a log message to the server.
@ -84,7 +84,7 @@ SQMOD_NODISCARD const SQChar * GetPluginAuthor();
/* ------------------------------------------------------------------------------------------------
* Retrieve the id of the host Squirrel plug-in.
*/
SQMOD_NODISCARD int32_t GetPluginID();
SQMOD_NODISCARD uint32_t GetPluginID();
/* ------------------------------------------------------------------------------------------------
* Retrieve the port onto which the server was binded.
@ -99,7 +99,7 @@ SQMOD_NODISCARD uint32_t GetServerFlags();
/* ------------------------------------------------------------------------------------------------
* Retrieve the maximum number of clients allowed on the server.
*/
SQMOD_NODISCARD int32_t GetMaxPlayers();
SQMOD_NODISCARD uint32_t GetMaxPlayers();
/* ------------------------------------------------------------------------------------------------
* Modify the maximum number of clients allowed on the server.
@ -205,7 +205,7 @@ SQMOD_NODISCARD int32_t GetTimeRate();
/* ------------------------------------------------------------------------------------------------
* Modify the current time-rate.
*/
void SetTimeRate(uint32_t rate);
void SetTimeRate(int32_t rate);
/* ------------------------------------------------------------------------------------------------
* Retrieve the game hour.

View File

@ -3,7 +3,6 @@
#include "Base/Color3.hpp"
#include "Base/Vector2.hpp"
#include "Entity/Player.hpp"
#include "Library/Numeric/Long.hpp"
// ------------------------------------------------------------------------------------------------
#include "Misc/Functions.hpp"

View File

@ -44,6 +44,9 @@ extern void Register_System(HSQUIRRELVM vm);
extern void Register_Utils(HSQUIRRELVM vm);
extern void Register_XML(HSQUIRRELVM vm);
extern void Register_ZMQ(HSQUIRRELVM vm);
#ifdef VCMP_ENABLE_DISCORD
extern void Register_DPP(HSQUIRRELVM vm);
#endif
#ifdef SQMOD_POCO_HAS_SQLITE
extern void Register_SQLite(HSQUIRRELVM vm);
#endif
@ -110,6 +113,9 @@ bool RegisterAPI(HSQUIRRELVM vm)
Register_Utils(vm);
Register_XML(vm);
Register_ZMQ(vm);
#ifdef VCMP_ENABLE_DISCORD
Register_DPP(vm);
#endif
#ifdef SQMOD_POCO_HAS_SQLITE
Register_SQLite(vm);
#endif

View File

@ -32,20 +32,21 @@
* OS IDENTIFICATION
*/
#if defined(_WIN32) || defined(__WIN32__) || defined(_WIN) || defined(__WIN__)
// Windows x32
#define SQMOD_OS_WINDOWS
#define SQMOD_OS_32
#define SQMOD_OS_WINDOWS32
#define SQMOD_ARCHITECTURE 1
#define SQMOD_PLATFORM 1
#elif defined(_WIN64) || defined(__WIN64__)
#if defined(_WIN64) || defined(__WIN64__)
// Windows x64
#define SQMOD_OS_WINDOWS
#define SQMOD_OS_64
#define SQMOD_OS_WINDOWS64
#define SQMOD_ARCHITECTURE 2
#define SQMOD_PLATFORM 1
#elif defined(_WIN32) || defined(__WIN32__) || defined(_WIN) || defined(__WIN__)
#error Squirrel Module does not support 32-bit Windows anymore
// Windows x32
//#define SQMOD_OS_WINDOWS
//#define SQMOD_OS_32
//#define SQMOD_OS_WINDOWS32
//#define SQMOD_ARCHITECTURE 1
//#define SQMOD_PLATFORM 1
#elif defined(linux) || defined(__linux) || defined(__linux__)
// Linux
#define SQMOD_OS_LINUX
@ -53,13 +54,14 @@
#if __x86_64__ || __ppc64__
#define SQMOD_OS_64
#define SQMOD_OS_LINUX64
#define SQMOD_ARCHITECTURE 2
#define SQMOD_ARCHITECTURE 2
#define SQMOD_PLATFORM 2
#else
#define SQMOD_OS_32
#define SQMOD_OS_LINUX32
#define SQMOD_ARCHITECTURE 1
#define SQMOD_PLATFORM 2
#error Squirrel Module does not support 32-bit Linux anymore
//#define SQMOD_OS_32
//#define SQMOD_OS_LINUX32
//#define SQMOD_ARCHITECTURE 1
//#define SQMOD_PLATFORM 2
#endif
#endif
#else
@ -423,7 +425,7 @@ enum EntityType
#define SQMOD_CONCAT(a,b) SQMOD_CONCAT_(a,b)
// ------------------------------------------------------------------------------------------------
#ifdef _WIN32
#ifdef SQMOD_OS_WINDOWS
#define sqmod_stricmp(a,b) stricmp(a,b)
#define sqmod_strnicmp(a,b,n) strnicmp(a,b,n)
#else

View File

@ -52,3 +52,7 @@ if (WIN32 OR MINGW)
set(ZMQ_HAVE_IPC OFF CACHE INTERNAL "" FORCE)
endif()
add_subdirectory(ZMQ)
# Should we include DPP?
if (ENABLE_DISCORD)
add_subdirectory(DPP)
endif()

174
vendor/DPP/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,174 @@
# Create the DPP library
add_library(DPP STATIC
include/dpp/nlohmann/json.hpp
include/dpp/nlohmann/json_fwd.hpp
include/dpp/auditlog.h
include/dpp/ban.h
include/dpp/cache.h
include/dpp/channel.h
include/dpp/cluster.h
include/dpp/commandhandler.h
include/dpp/discord.h
include/dpp/discordclient.h
include/dpp/discordevents.h
include/dpp/discordvoiceclient.h
include/dpp/dispatcher.h
include/dpp/dpp.h
include/dpp/dtemplate.h
include/dpp/emoji.h
include/dpp/event.h
include/dpp/export.h
include/dpp/guild.h
include/dpp/httplib.h
include/dpp/integration.h
include/dpp/intents.h
include/dpp/invite.h
include/dpp/json_fwd.hpp
include/dpp/message.h
include/dpp/presence.h
include/dpp/prune.h
include/dpp/queues.h
include/dpp/role.h
include/dpp/slashcommand.h
include/dpp/sslclient.h
include/dpp/stringops.h
include/dpp/user.h
include/dpp/version.h
include/dpp/voiceregion.h
include/dpp/voicestate.h
include/dpp/webhook.h
include/dpp/wsclient.h
src/dpp/ban.cpp
src/dpp/cache.cpp
src/dpp/channel.cpp
src/dpp/cluster.cpp
src/dpp/commandhandler.cpp
src/dpp/discordclient.cpp
src/dpp/discordevents.cpp
src/dpp/discordvoiceclient.cpp
src/dpp/dispatcher.cpp
src/dpp/dtemplate.cpp
src/dpp/emoji.cpp
src/dpp/guild.cpp
src/dpp/httplib.cpp
src/dpp/integration.cpp
src/dpp/invite.cpp
src/dpp/managed.cpp
src/dpp/message.cpp
src/dpp/presence.cpp
src/dpp/prune.cpp
src/dpp/queues.cpp
src/dpp/role.cpp
src/dpp/slashcommand.cpp
src/dpp/sslclient.cpp
src/dpp/user.cpp
src/dpp/utility.cpp
src/dpp/voiceregion.cpp
src/dpp/voicestate.cpp
src/dpp/webhook.cpp
src/dpp/wsclient.cpp
src/dpp/auditlog.cpp
src/dpp/events/application_command_update.cpp
src/dpp/events/channel_create.cpp
src/dpp/events/channel_delete.cpp
src/dpp/events/channel_pins_update.cpp
src/dpp/events/channel_update.cpp
src/dpp/events/guild_ban_add.cpp
src/dpp/events/guild_ban_remove.cpp
src/dpp/events/guild_create.cpp
src/dpp/events/guild_delete.cpp
src/dpp/events/guild_emojis_update.cpp
src/dpp/events/guild_integrations_update.cpp
src/dpp/events/guild_join_request_delete.cpp
src/dpp/events/guild_member_add.cpp
src/dpp/events/guild_member_remove.cpp
src/dpp/events/guild_member_update.cpp
src/dpp/events/guild_members_chunk.cpp
src/dpp/events/guild_role_create.cpp
src/dpp/events/guild_role_delete.cpp
src/dpp/events/guild_role_update.cpp
src/dpp/events/guild_stickers_update.cpp
src/dpp/events/guild_update.cpp
src/dpp/events/integration_create.cpp
src/dpp/events/integration_delete.cpp
src/dpp/events/integration_update.cpp
src/dpp/events/interaction_create.cpp
src/dpp/events/invite_create.cpp
src/dpp/events/invite_delete.cpp
src/dpp/events/logger.cpp
src/dpp/events/message_create.cpp
src/dpp/events/message_delete.cpp
src/dpp/events/message_delete_bulk.cpp
src/dpp/events/message_reaction_add.cpp
src/dpp/events/message_reaction_remove.cpp
src/dpp/events/message_reaction_remove_all.cpp
src/dpp/events/message_reaction_remove_emoji.cpp
src/dpp/events/message_update.cpp
src/dpp/events/presence_update.cpp
src/dpp/events/ready.cpp
src/dpp/events/resumed.cpp
src/dpp/events/stage_instance_create.cpp
src/dpp/events/stage_instance_delete.cpp
src/dpp/events/thread_create.cpp
src/dpp/events/thread_delete.cpp
src/dpp/events/thread_list_sync.cpp
src/dpp/events/thread_member_update.cpp
src/dpp/events/thread_members_update.cpp
src/dpp/events/thread_update.cpp
src/dpp/events/typing_start.cpp
src/dpp/events/user_update.cpp
src/dpp/events/voice_server_update.cpp
src/dpp/events/voice_state_update.cpp
src/dpp/events/webhooks_update.cpp
src/dpp/events/application_command_create.cpp
src/dpp/events/application_command_delete.cpp
)
# Configure include folders
target_include_directories(DPP PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src)
target_include_directories(DPP PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/dpp)
target_include_directories(DPP PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
# Link to built-in third-party libraries
target_link_libraries(DPP PUBLIC fmt::fmt)
# Project defines
target_compile_definitions(DPP PUBLIC DPP_BUILD=1)
# Platform defines
if(WIN32)
target_compile_definitions(DPP PRIVATE _WIN32_WINNT=0x0601 OPENSSL_SYS_WIN32=1 _WINSOCK_DEPRECATED_NO_WARNINGS=1 WIN32_LEAN_AND_MEAN=1 _CRT_SECURE_NO_WARNINGS=1 _CRT_NONSTDC_NO_DEPRECATE=1)
if (MINGW)
target_compile_definitions(DPP PUBLIC WIN32=1)
endif()
target_link_libraries(DPP PRIVATE Crypt32)
endif()
# Third-party library preferences
set(THREADS_PREFER_PTHREAD_FLAG ON)
# Find required third-party libraries
find_package(Threads REQUIRED)
find_package(ZLIB REQUIRED)
find_package(OpenSSL REQUIRED)
# Link to required third-party libraries
target_link_libraries(DPP PUBLIC Threads::Threads ZLIB::ZLIB OpenSSL::Crypto OpenSSL::SSL)
# Include the custom module folder
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/cmake/")
# Enable voice support in discord library
if (ENABLE_DISCORD_VOICE)
# Look for sodium and opus libraries
include("cmake/FindSodium.cmake")
include("cmake/FindOpus.cmake")
# Was the opus library found?
if(DEFINED OPUS_FOUND)
message(STATUS "Opus library was found")
# Link to opus library
target_include_directories(DPP PUBLIC ${OPUS_INCLUDE_DIRS})
target_link_libraries(DPP PUBLIC ${OPUS_LIBRARIES})
# Was the sodium library found?
if(DEFINED sodium_VERSION_STRING)
message(STATUS "Sodium library was found")
message(STATUS "DPP voice support enabled")
# Let the code know about this
target_compile_definitions(DPP PRIVATE HAVE_VOICE=1)
# Link to sodium library
target_include_directories(DPP PUBLIC ${sodium_INCLUDE_DIR})
target_link_libraries(DPP PUBLIC ${sodium_LIBRARY_RELEASE})
endif()
endif()
endif()

201
vendor/DPP/LICENSE vendored Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

36
vendor/DPP/cmake/FindOpus.cmake vendored Normal file
View File

@ -0,0 +1,36 @@
# OPUS_FOUND - system has opus
# OPUS_INCLUDE_DIRS - the opus include directory
# OPUS_LIBRARIES - The libraries needed to use opus
find_path(OPUS_INCLUDE_DIRS
NAMES opus/opus.h
PATH_SUFFIXES include
)
if(OPUS_INCLUDE_DIRS)
set(HAVE_OPUS_OPUS_H 1)
endif()
if(OPUS_USE_STATIC_LIBS)
find_library(OPUS_LIBRARIES NAMES "libopus.a")
else()
find_library(OPUS_LIBRARIES NAMES opus)
endif()
if(OPUS_LIBRARIES)
if(OPUS_USE_STATIC_LIBS)
find_library(LIBM NAMES "libm.a" "libm.tbd")
else()
find_library(LIBM NAMES m)
endif()
if(LIBM)
list(APPEND OPUS_LIBRARIES ${LIBM})
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Opus
DEFAULT_MSG
OPUS_INCLUDE_DIRS OPUS_LIBRARIES HAVE_OPUS_OPUS_H
)
mark_as_advanced(OPUS_INCLUDE_DIRS OPUS_LIBRARIES HAVE_OPUS_OPUS_H)

293
vendor/DPP/cmake/FindSodium.cmake vendored Normal file
View File

@ -0,0 +1,293 @@
# Written in 2016 by Henrik Steffen Gaßmann <henrik@gassmann.onl>
#
# To the extent possible under law, the author(s) have dedicated all copyright
# and related and neighboring rights to this software to the public domain
# worldwide. This software is distributed without any warranty.
#
# You should have received a copy of the CC0 Public Domain Dedication along with
# this software. If not, see
#
# http://creativecommons.org/publicdomain/zero/1.0/
#
# ##############################################################################
# Tries to find the local libsodium installation.
#
# On Windows the sodium_DIR environment variable is used as a default hint which
# can be overridden by setting the corresponding cmake variable.
#
# Once done the following variables will be defined:
#
# sodium_FOUND sodium_INCLUDE_DIR sodium_LIBRARY_DEBUG sodium_LIBRARY_RELEASE
# sodium_VERSION_STRING
#
# Furthermore an imported "sodium" target is created.
#
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
set(_GCC_COMPATIBLE 1)
endif()
# static library option
if(NOT DEFINED sodium_USE_STATIC_LIBS)
option(sodium_USE_STATIC_LIBS "enable to statically link against sodium" OFF)
endif()
if(NOT (sodium_USE_STATIC_LIBS EQUAL sodium_USE_STATIC_LIBS_LAST))
unset(sodium_LIBRARY CACHE)
unset(sodium_LIBRARY_DEBUG CACHE)
unset(sodium_LIBRARY_RELEASE CACHE)
unset(sodium_DLL_DEBUG CACHE)
unset(sodium_DLL_RELEASE CACHE)
set(sodium_USE_STATIC_LIBS_LAST
${sodium_USE_STATIC_LIBS}
CACHE INTERNAL "internal change tracking variable")
endif()
# ##############################################################################
# UNIX
if(UNIX)
# import pkg-config
find_package(PkgConfig QUIET)
if(PKG_CONFIG_FOUND)
pkg_check_modules(sodium_PKG QUIET libsodium)
endif()
if(sodium_USE_STATIC_LIBS)
if(sodium_PKG_STATIC_LIBRARIES)
foreach(_libname ${sodium_PKG_STATIC_LIBRARIES})
if(NOT _libname MATCHES "^lib.*\\.a$") # ignore strings already ending
# with .a
list(INSERT sodium_PKG_STATIC_LIBRARIES 0 "lib${_libname}.a")
endif()
endforeach()
list(REMOVE_DUPLICATES sodium_PKG_STATIC_LIBRARIES)
else()
# if pkgconfig for libsodium doesn't provide static lib info, then
# override PKG_STATIC here..
set(sodium_PKG_STATIC_LIBRARIES libsodium.a)
endif()
set(XPREFIX sodium_PKG_STATIC)
else()
if(sodium_PKG_LIBRARIES STREQUAL "")
set(sodium_PKG_LIBRARIES sodium)
endif()
set(XPREFIX sodium_PKG)
endif()
find_path(sodium_INCLUDE_DIR sodium.h HINTS ${${XPREFIX}_INCLUDE_DIRS})
find_library(sodium_LIBRARY_DEBUG
NAMES ${${XPREFIX}_LIBRARIES}
HINTS ${${XPREFIX}_LIBRARY_DIRS})
find_library(sodium_LIBRARY_RELEASE
NAMES ${${XPREFIX}_LIBRARIES}
HINTS ${${XPREFIX}_LIBRARY_DIRS})
# ############################################################################
# Windows
elseif(WIN32)
set(sodium_DIR "$ENV{sodium_DIR}" CACHE FILEPATH "sodium install directory")
mark_as_advanced(sodium_DIR)
find_path(sodium_INCLUDE_DIR sodium.h
HINTS ${sodium_DIR}
PATH_SUFFIXES include)
if(MSVC)
# detect target architecture
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/arch.cpp" [=[
#if defined _M_IX86
#error ARCH_VALUE x86_32
#elif defined _M_X64
#error ARCH_VALUE x86_64
#endif
#error ARCH_VALUE unknown
]=])
try_compile(_UNUSED_VAR "${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_CURRENT_BINARY_DIR}/arch.cpp"
OUTPUT_VARIABLE _COMPILATION_LOG)
string(REGEX
REPLACE ".*ARCH_VALUE ([a-zA-Z0-9_]+).*"
"\\1"
_TARGET_ARCH
"${_COMPILATION_LOG}")
# construct library path
if(_TARGET_ARCH STREQUAL "x86_32")
string(APPEND _PLATFORM_PATH "Win32")
elseif(_TARGET_ARCH STREQUAL "x86_64")
string(APPEND _PLATFORM_PATH "x64")
else()
message(
FATAL_ERROR
"the ${_TARGET_ARCH} architecture is not supported by Findsodium.cmake."
)
endif()
string(APPEND _PLATFORM_PATH "/$$CONFIG$$")
if(MSVC_VERSION LESS 1900)
math(EXPR _VS_VERSION "${MSVC_VERSION} / 10 - 60")
else()
math(EXPR _VS_VERSION "${MSVC_VERSION} / 10 - 50")
endif()
string(APPEND _PLATFORM_PATH "/v${_VS_VERSION}")
if(sodium_USE_STATIC_LIBS)
string(APPEND _PLATFORM_PATH "/static")
else()
string(APPEND _PLATFORM_PATH "/dynamic")
endif()
string(REPLACE "$$CONFIG$$"
"Debug"
_DEBUG_PATH_SUFFIX
"${_PLATFORM_PATH}")
string(REPLACE "$$CONFIG$$"
"Release"
_RELEASE_PATH_SUFFIX
"${_PLATFORM_PATH}")
find_library(sodium_LIBRARY_DEBUG libsodium.lib
HINTS ${sodium_DIR}
PATH_SUFFIXES ${_DEBUG_PATH_SUFFIX})
find_library(sodium_LIBRARY_RELEASE libsodium.lib
HINTS ${sodium_DIR}
PATH_SUFFIXES ${_RELEASE_PATH_SUFFIX})
if(NOT sodium_USE_STATIC_LIBS)
set(CMAKE_FIND_LIBRARY_SUFFIXES_BCK ${CMAKE_FIND_LIBRARY_SUFFIXES})
set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll")
find_library(sodium_DLL_DEBUG libsodium
HINTS ${sodium_DIR}
PATH_SUFFIXES ${_DEBUG_PATH_SUFFIX})
find_library(sodium_DLL_RELEASE libsodium
HINTS ${sodium_DIR}
PATH_SUFFIXES ${_RELEASE_PATH_SUFFIX})
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_BCK})
endif()
elseif(_GCC_COMPATIBLE)
if(sodium_USE_STATIC_LIBS)
find_library(sodium_LIBRARY_DEBUG libsodium.a
HINTS ${sodium_DIR}
PATH_SUFFIXES lib)
find_library(sodium_LIBRARY_RELEASE libsodium.a
HINTS ${sodium_DIR}
PATH_SUFFIXES lib)
else()
find_library(sodium_LIBRARY_DEBUG libsodium.dll.a
HINTS ${sodium_DIR}
PATH_SUFFIXES lib)
find_library(sodium_LIBRARY_RELEASE libsodium.dll.a
HINTS ${sodium_DIR}
PATH_SUFFIXES lib)
file(GLOB _DLL
LIST_DIRECTORIES false
RELATIVE "${sodium_DIR}/bin"
"${sodium_DIR}/bin/libsodium*.dll")
find_library(sodium_DLL_DEBUG ${_DLL} libsodium
HINTS ${sodium_DIR}
PATH_SUFFIXES bin)
find_library(sodium_DLL_RELEASE ${_DLL} libsodium
HINTS ${sodium_DIR}
PATH_SUFFIXES bin)
endif()
else()
message(FATAL_ERROR "this platform is not supported by FindSodium.cmake")
endif()
# ############################################################################
# unsupported
else()
message(FATAL_ERROR "this platform is not supported by FindSodium.cmake")
endif()
# ##############################################################################
# common stuff
# extract sodium version
if(sodium_INCLUDE_DIR)
set(_VERSION_HEADER "${sodium_INCLUDE_DIR}/sodium/version.h")
if(EXISTS "${_VERSION_HEADER}")
file(READ "${_VERSION_HEADER}" _VERSION_HEADER_CONTENT)
string(
REGEX
REPLACE
".*#define[ \t]*SODIUM_VERSION_STRING[ \t]*\"([^\n]*)\".*"
"\\1"
sodium_VERSION_STRING
"${_VERSION_HEADER_CONTENT}")
set(sodium_VERSION_STRING "${sodium_VERSION_STRING}")
endif()
endif()
# communicate results
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(sodium
REQUIRED_VARS
sodium_LIBRARY_RELEASE
sodium_LIBRARY_DEBUG
sodium_INCLUDE_DIR
VERSION_VAR
sodium_VERSION_STRING)
# mark file paths as advanced
mark_as_advanced(sodium_INCLUDE_DIR)
mark_as_advanced(sodium_LIBRARY_DEBUG)
mark_as_advanced(sodium_LIBRARY_RELEASE)
if(WIN32)
mark_as_advanced(sodium_DLL_DEBUG)
mark_as_advanced(sodium_DLL_RELEASE)
endif()
# create imported target
if(sodium_USE_STATIC_LIBS)
set(_LIB_TYPE STATIC)
else()
set(_LIB_TYPE SHARED)
endif()
add_library(sodium ${_LIB_TYPE} IMPORTED)
set_target_properties(sodium
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
"${sodium_INCLUDE_DIR}"
IMPORTED_LINK_INTERFACE_LANGUAGES
"C")
if(sodium_USE_STATIC_LIBS)
set_target_properties(sodium
PROPERTIES INTERFACE_COMPILE_DEFINITIONS
"SODIUM_STATIC"
IMPORTED_LOCATION
"${sodium_LIBRARY_RELEASE}"
IMPORTED_LOCATION_DEBUG
"${sodium_LIBRARY_DEBUG}")
else()
if(UNIX)
set_target_properties(sodium
PROPERTIES IMPORTED_LOCATION
"${sodium_LIBRARY_RELEASE}"
IMPORTED_LOCATION_DEBUG
"${sodium_LIBRARY_DEBUG}")
elseif(WIN32)
set_target_properties(sodium
PROPERTIES IMPORTED_IMPLIB
"${sodium_LIBRARY_RELEASE}"
IMPORTED_IMPLIB_DEBUG
"${sodium_LIBRARY_DEBUG}")
if(NOT (sodium_DLL_DEBUG MATCHES ".*-NOTFOUND"))
set_target_properties(sodium
PROPERTIES IMPORTED_LOCATION_DEBUG
"${sodium_DLL_DEBUG}")
endif()
if(NOT (sodium_DLL_RELEASE MATCHES ".*-NOTFOUND"))
set_target_properties(sodium
PROPERTIES IMPORTED_LOCATION_RELWITHDEBINFO
"${sodium_DLL_RELEASE}"
IMPORTED_LOCATION_MINSIZEREL
"${sodium_DLL_RELEASE}"
IMPORTED_LOCATION_RELEASE
"${sodium_DLL_RELEASE}")
endif()
endif()
endif()

165
vendor/DPP/include/dpp/auditlog.h vendored Normal file
View File

@ -0,0 +1,165 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <dpp/discord.h>
#include <dpp/json_fwd.hpp>
#include <optional>
namespace dpp {
/**
* @brief Defines types of audit log entry
*/
enum audit_type {
/// Guild update
ae_guild_update = 1,
/// Channel create
ae_channel_create = 10,
/// Channel update
ae_channel_update = 11,
/// Channel delete
ae_channel_delete = 12,
/// Channel overwrite create
ae_channel_overwrite_create = 13,
/// Channel overwrite update
ae_channel_overwrite_update = 14,
/// Channel overwrite delete
ae_channel_overwrite_delete = 15,
/// Channel member kick
ae_member_kick = 20,
/// Channel member prune
ae_member_prune = 21,
/// Channel member ban add
ae_member_ban_add = 22,
/// Channel member ban remove
ae_member_ban_remove = 23,
/// Guild member update
ae_member_update = 24,
/// Guild member role update
ae_member_role_update = 25,
/// Guild member move
ae_member_move = 26,
/// Guild member voice disconnect
ae_member_disconnect = 27,
/// Guild bot add
ae_bot_add = 28,
/// Guild role create
ae_role_create = 30,
/// Guild role update
ae_role_update = 31,
/// Guild role delete
ae_role_delete = 32,
/// Guild invite create
ae_invite_create = 40,
/// Guild invite update
ae_invite_update = 41,
/// Guild invite delete
ae_invite_delete = 42,
/// Guild webhook create
ae_webhook_create = 50,
/// Guild webhook update
ae_webhook_update = 51,
/// Guild webhook delete
ae_webhook_delete = 52,
/// Guild emoji create
ae_emoji_create = 60,
/// Guild emoji update
ae_emoji_update = 61,
/// Guild emoji delete
ae_emoji_delete = 62,
/// Guild message delete
ae_message_delete = 72,
/// Guild message bulk delete
ae_message_bulk_delete = 73,
/// Guild message pin
ae_message_pin = 74,
/// Guild message unpin
ae_message_unpin = 75,
/// Guild integration create
ae_integration_create = 80,
/// Guild integration update
ae_integration_update = 81,
/// Guild integration delete
ae_integration_delete = 82
};
/**
* @brief Defines audit log changes
*/
struct CoreExport audit_change {
/// Optional: Serialised new value of the key
std::string new_value;
/// Optional: Serialised old value of the key
std::string old_value;
/// name of audit log change key
std::string key;
};
/**
* @brief Extra information for an audit log entry
*/
struct CoreExport audit_extra {
std::string delete_member_days; //!< number of days after which inactive members were kicked
std::string members_removed; //!< number of members removed by the prune
snowflake channel_id; //!< channel in which the entities were targeted
snowflake message_id; //!< id of the message that was targeted
std::string count; //!< number of entities that were targeted
snowflake id; //!< id of the overwritten entity
std::string type; //!< type of overwritten entity - "0" for "role" or "1" for "member"
std::string role_name; //!< name of the role if type is "0" (not present if type is "1")
};
/**
* @brief An individual audit log entry
*/
struct CoreExport audit_entry {
snowflake id; //!< id of the entry
snowflake target_id; //!< id of the affected entity (webhook, user, role, etc.) (may be empty)
std::vector<audit_change> changes; //!< Optional: changes made to the target_id
snowflake user_id; //!< the user who made the changes (may be empty)
audit_type event; //!< type of action that occurred
std::optional<audit_extra> options; //!< Optional: additional info for certain action types
std::string reason; //!< Optional: the reason for the change (0-512 characters)
};
/**
* @brief The auditlog class represents the audit log entry of a guild.
*/
class CoreExport auditlog {
public:
std::vector<audit_entry> entries; //!< Audit log entries
/** Constructor */
auditlog();
/** Destructor */
~auditlog();
/** Read class values from json object
* @param j A json object to read from
* @return A reference to self
*/
auditlog& fill_from_json(nlohmann::json* j);
};
};

64
vendor/DPP/include/dpp/ban.h vendored Normal file
View File

@ -0,0 +1,64 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <dpp/discord.h>
#include <dpp/json_fwd.hpp>
namespace dpp {
/**
* @brief The ban class represents a ban on a guild.
*
*/
class CoreExport ban {
public:
/** The ban reason */
std::string reason;
/** User ID the ban applies to */
snowflake user_id;
/** Constructor */
ban();
/** Destructor */
~ban();
/** Read class values from json object
* @param j A json object to read from
* @return A reference to self
*/
ban& fill_from_json(nlohmann::json* j);
/**
* @brief Build json representation of a ban
*
* @return std::string stringified json
*/
std::string build_json() const;
};
/** A group of bans
*/
typedef std::unordered_map<snowflake, ban> ban_map;
};

127
vendor/DPP/include/dpp/cache.h vendored Normal file
View File

@ -0,0 +1,127 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <dpp/discord.h>
#include <map>
#include <mutex>
namespace dpp {
/**
* @brief A set of cached managed objects
*/
typedef std::unordered_map<uint64_t, managed*> cache_container;
/**
* @brief A cache object maintains a cache of dpp::managed objects.
* This is for example users, channels or guilds.
*/
class CoreExport cache {
private:
/** Mutex to protect the cache */
std::mutex cache_mutex;
/** Cached items */
cache_container* cache_map;
public:
/**
* @brief Construct a new cache object
*/
cache();
/**
* @brief Destroy the cache object
*/
~cache();
/** Store an object in the cache.
* @param object object to store
*/
void store(managed* object);
/** Remove an object from the cache.
* @param object object to remove
*/
void remove(managed* object);
/** Find an object in the cache by id.
* @param id Object id to find
*/
managed* find(snowflake id);
/** Return a count of the number of items in the cache.
*/
uint64_t count();
/**
* @brief Return the cache's locking mutex. Use this whenever
* you manipulate or iterate raw elements in the cache!
*
* @return The mutex used to protect the container
*/
std::mutex& get_mutex();
/**
* @brief Get the container map
* @warning Be sure to use cache::get_mutex() correctly if you
* manipulate or iterate the map returned by this method! If you do
* not, this is not thread safe and will casue crashes!
* @see cache::get_mutex
*
* @return cache_container& A reference to the cache's container map
*/
cache_container& get_container();
/**
* @brief "Rehash" a cache by cleaning out used RAM
* @warning May be time consuming!
*/
void rehash();
/**
* @brief Get "real" size in RAM of the cache
*
* @return size_t
*/
size_t bytes();
};
/** Run garbage collection across all caches removing deleted items
* that have been deleted over 60 seconds ago.
*/
void CoreExport garbage_collection();
#define cache_decl(type, setter, getter, counter) CoreExport type * setter (snowflake id); CoreExport cache * getter (); CoreExport uint64_t counter ();
/* Declare major caches */
cache_decl(user, find_user, get_user_cache, get_user_count);
cache_decl(guild, find_guild, get_guild_cache, get_guild_count);
cache_decl(role, find_role, get_role_cache, get_role_count);
cache_decl(channel, find_channel, get_channel_cache, get_channel_count);
cache_decl(emoji, find_emoji, get_emoji_cache, get_emoji_count);
};

302
vendor/DPP/include/dpp/channel.h vendored Normal file
View File

@ -0,0 +1,302 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <dpp/json_fwd.hpp>
namespace dpp {
/** @brief Flag integers as received from and sent to discord */
enum channel_type {
GUILD_TEXT = 0, //!< a text channel within a server
DM = 1, //!< a direct message between users
GUILD_VOICE = 2, //!< a voice channel within a server
GROUP_DM = 3, //!< a direct message between multiple users
GUILD_CATEGORY = 4, //!< an organizational category that contains up to 50 channels
GUILD_NEWS = 5, //!< a channel that users can follow and crosspost into their own server
GUILD_STORE = 6, //!< a channel in which game developers can sell their game on Discord
GUILD_NEWS_THREAD = 10, //!< a temporary sub-channel within a GUILD_NEWS channel
GUILD_PUBLIC_THREAD = 11, //!< a temporary sub-channel within a GUILD_TEXT channel
GUILD_PRIVATE_THREAD = 12, //!< a temporary sub-channel within a GUILD_TEXT channel that is only viewable by those invited and those with the MANAGE_THREADS permission
GUILD_STAGE = 13 //!< a "stage" channel, like a voice channel with one authorised speaker
};
/** @brief Our flags as stored in the object */
enum channel_flags {
/// NSFW Gated Channel
c_nsfw = 0b00000001,
/// Text channel
c_text = 0b00000010,
/// Direct Message
c_dm = 0b00000100,
/// Voice channel
c_voice = 0b00001000,
/// Group
c_group = 0b00010000,
/// Category
c_category = 0b00100000,
/// News channel
c_news = 0b01000000,
/// Store page
c_store = 0b10000000,
/// Stage channel
c_stage = 0b11000000,
/// News thread
c_news_thread = 0b11100000,
/// Public thread
c_public_thread = 0b11110000,
/// Private thread
c_private_thread = 0b11111000
};
/**
* @brief channel permission overwrite types
*/
enum overwrite_type : uint8_t {
/// Role
ot_role = 0,
/// Member
ot_member = 1
};
/**
* @brief channel permission overwrites
*/
struct CoreExport permission_overwrite {
/// Overwrite id
snowflake id;
/// Overwrite type
uint8_t type;
/// Allow mask
uint64_t allow;
/// Deny mask
uint64_t deny;
};
/**
* @brief metadata for threads
*/
struct CoreExport thread_metadata {
/// Whether a thread is archived
bool archived;
/// When the thread was archived
time_t archive_timestamp;
/// The duration after a thread will archive
uint16_t auto_archive_duration;
/// Whether a thread is locked
bool locked;
};
/**
* @brief represents membership of a user with a thread
*/
struct CoreExport thread_member
{
/// ID of the thread member is part of
snowflake thread_id;
/// ID of the member
snowflake user_id;
/// When the user joined the thread
time_t joined;
/// Flags bitmap
uint32_t flags;
/**
* @brief Read struct values from a json object
* @param j json to read values from
* @return A reference to self
*/
thread_member& fill_from_json(nlohmann::json* j);
};
/** @brief A group of thread member objects*/
typedef std::unordered_map<snowflake, thread_member> thread_member_map;
/** @brief A definition of a discord channel */
class CoreExport channel : public managed {
public:
/** Flags bitmap */
uint8_t flags;
/** Guild id of the guild that owns the channel */
snowflake guild_id;
/** Sorting position, lower number means higher up the list */
uint16_t position;
/** Channel name */
std::string name;
/** Channel topic */
std::string topic;
/** ID of last message to be sent to the channel */
snowflake last_message_id;
/** Maximum user limit for voice channels (0-99) */
uint8_t user_limit;
/** Rate limit in kilobits per second for voice channels */
uint16_t rate_limit_per_user;
/** User ID of owner for group DMs */
snowflake owner_id;
/** Parent ID (category) */
snowflake parent_id;
/** Timestamp of last pinned message */
time_t last_pin_timestamp;
/** DM recipients */
std::vector<snowflake> recipients;
/** Permission overwrites to apply to base permissions */
std::vector<permission_overwrite> permission_overwrites;
/** Approximate count of messages in a thread (threads) */
uint8_t message_count;
/** Approximate count of members in a thread (threads) */
uint8_t member_count;
/** Thread metadata (threads) */
thread_metadata metadata;
/** Constructor */
channel();
/** Destructor */
virtual ~channel();
/** Read class values from json object
* @param j A json object to read from
* @return A reference to self
*/
channel& fill_from_json(nlohmann::json* j);
/**
* @brief Build json for this channel object
*
* @param with_id include the ID in the json
* @return std::string JSON string
*/
std::string build_json(bool with_id = false) const;
/**
* @brief Get the user permissions for a user on this channel
*
* @param member The user to return permissions for
* @return uint64_t Permissions bitmask made of bits in role_permissions.
* Note that if the user is not on the channel or the guild is
* not in the cache, the function will always return 0.
*/
uint64_t get_user_permissions(const class user* member) const;
/**
* @brief Return a map of members on the channel, built from the guild's
* member list based on which members have the VIEW_CHANNEL permission.
* Does not return reliable information for voice channels, use
* dpp::channel::get_voice_members() instead for this.
* @return A map of guild members keyed by user id.
*/
std::map<snowflake, class guild_member*> get_members();
/**
* @brief Get a map of members in this channel, if it is a voice channel.
* The map is keyed by snowflake id of the user.
*
* @return std::map<snowflake, voicestate> The voice members of the channel
*/
std::map<snowflake, voicestate> get_voice_members();
/**
* @brief Returns true if the channel is NSFW gated
*
* @return true if NSFW
*/
bool is_nsfw() const;
/**
* @brief Returns true if the channel is a text channel
*
* @return true if text channel
*/
bool is_text_channel() const;
/**
* @brief Returns true if the channel is a DM
*
* @return true if is a DM
*/
bool is_dm() const;
/**
* @brief Returns true if the channel is a voice channel
*
* @return true if voice channel
*/
bool is_voice_channel() const;
/**
* @brief Returns true if the channel is a group DM channel
*
* @return true if group DM
*/
bool is_group_dm() const;
/**
* @brief Returns true if the channel is a category
*
* @return true if a category
*/
bool is_category() const;
/**
* @brief Returns true if the channel is a news channel
*
* @return true if news channel
*/
bool is_news_channel() const;
/**
* @brief Returns true if the channel is a store channel
*
* @return true if store channel
*/
bool is_store_channel() const;
/**
* @brief Returns true if the channel is a stage channel
*
* @return true if stage channel
*/
bool is_stage_channel() const;
};
/**
* @brief A group of channels
*/
typedef std::unordered_map<snowflake, channel> channel_map;
};

2138
vendor/DPP/include/dpp/cluster.h vendored Normal file

File diff suppressed because it is too large Load Diff

285
vendor/DPP/include/dpp/commandhandler.h vendored Normal file
View File

@ -0,0 +1,285 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <dpp/discord.h>
#include <dpp/json_fwd.hpp>
#include <unordered_map>
#include <vector>
#include <functional>
#include <variant>
namespace dpp {
/**
* @brief Represents a received parameter.
* We use variant so that multiple non-related types can be contained within.
*/
typedef std::variant<std::string, dpp::role, dpp::channel, dpp::user, int32_t, bool> command_parameter;
/**
* @brief Parameter types when registering a command.
* We don't pass these in when triggering the command in the handler, because it is
* expected the developer added the command so they know what types to expect for each named
* parameter.
*/
enum parameter_type {
pt_string, //!< String value
pt_role, //!< Role object
pt_channel, //!< Channel object
pt_user, //!< User object
pt_integer, //!< 32 bit signed integer
pt_boolean //!< boolean
};
/**
* @brief Details of a command parameter used in registration.
* Note that for non-slash commands optional parameters can only be at the end of
* the list of parameters.
*/
struct CoreExport param_info {
/**
* @brief Type of parameter
*/
parameter_type type;
/**
* @brief True if the parameter is optional.
* For non-slash commands optional parameters may only be on the end of the list.
*/
bool optional;
/**
* @brief Description of command. Displayed only for slash commands
*/
std::string description;
/**
* @brief Allowed multiple choice options.
* The key name is the string passed to the command handler
* and the key value is its description displayed to the user.
*/
std::map<std::string, std::string> choices;
/**
* @brief Construct a new param_info object
*
* @param t Type of parameter
* @param o True if parameter is optional
* @param description The parameter description
* @param opts The options for a multiple choice parameter
*/
param_info(parameter_type t, bool o, const std::string &description, const std::map<std::string, std::string> &opts = {});
};
/**
* @brief Parameter list used during registration.
* Note that use of vector/pair is important here to preserve parameter order,
* as opposed to unordered_map (which doesnt guarantee any order at all) and
* std::map, which reorders keys alphabetically.
*/
typedef std::vector<std::pair<std::string, param_info>> parameter_registration_t;
/**
* @brief Parameter list for a called command.
* See dpp::parameter_registration_t for an explaination as to why vector is used.
*/
typedef std::vector<std::pair<std::string, command_parameter>> parameter_list_t;
/**
* @brief Represents the sending source of a command.
* This is passed to any command handler and should be passed back to
* commandhandler::reply(), allowing the reply method to route any replies back
* to the origin, which may be a slash command or a message. Both require different
* response facilities but we want this to be transparent if you use the command
* handler class.
*/
struct CoreExport command_source {
/**
* @brief Sending guild id
*/
snowflake guild_id = 0;
/**
* @brief Source channel id
*/
snowflake channel_id = 0;
/**
* @brief Command ID of a slash command
*/
snowflake command_id = 0;
/**
* @brief Token for sending a slash command reply
*/
std::string command_token;
/**
* @brief The user who issued the command
*/
user* issuer;
};
/**
* @brief The function definition for a command handler. Expects a command name string,
* and a list of command parameters.
*/
typedef std::function<void(const std::string&, const parameter_list_t&, command_source)> command_handler;
/**
* @brief Represents the details of a command added to the command handler class.
*/
struct CoreExport command_info_t {
/**
* @brief Function reference for the handler. This is std::function so it can represent
* a class member, a lambda or a raw C function pointer.
*/
command_handler func;
/**
* @brief Parameters requested for the command, with their types
*/
parameter_registration_t parameters;
/**
* @brief Guild ID the command exists on, or 0 to be present on all guilds
*/
snowflake guild_id;
};
/**
* @brief The commandhandler class represents a group of commands, prefixed or slash commands with handling functions.
*
*/
class CoreExport commandhandler {
/**
* @brief Commands in the handler
*/
std::unordered_map<std::string, command_info_t> commands;
/**
* @brief Valid prefixes
*/
std::vector<std::string> prefixes;
/**
* @brief Set to true automatically if one of the prefixes added is "/"
*/
bool slash_commands_enabled;
/**
* @brief Cluster we are attached to for issuing REST calls
*/
class cluster* owner;
/**
* @brief Application ID
*/
snowflake app_id;
/**
* @brief Returns true if the string has a known prefix on the start.
* Modifies string to remove prefix if it returns true.
*
* @param str String to check and modify
* @return true string contained a prefix, prefix removed from string
* @return false string did not contain a prefix
*/
bool string_has_prefix(std::string &str);
public:
/**
* @brief Construct a new commandhandler object
*
* @param o Owning cluster to attach to
* @param auto_hook_events Set to true to automatically hook the on_interaction_create
* and on_message events. Only do this if you have no other use for these events than
* commands that are handled by the command handler (this is usually the case).
* @param application_id The application id of the bot. If not specified, the class will
* look within the cluster object and use cluster::me::id instead.
*/
commandhandler(class cluster* o, bool auto_hook_events = true, snowflake application_id = 0);
/**
* @brief Destroy the commandhandler object
*/
~commandhandler();
/**
* @brief Set the application id after construction
*
* @param o Owning cluster to attach to
*/
commandhandler& set_owner(class cluster* o);
/**
* @brief Add a prefix to the command handler
*
* @param prefix Prefix to be handled by the command handler
* @return commandhandler& reference to self
*/
commandhandler& add_prefix(const std::string &prefix);
/**
* @brief Add a command to the command handler
*
* @param command Command to be handled.
* Note that if any one of your prefixes is "/" this will attempt to register
* a global command using the API and you will receive notification of this command
* via an interaction event.
*
* @param handler Handler function
* @param parameters Parameters to use for the command
* @return commandhandler& reference to self
*/
commandhandler& add_command(const std::string &command, const parameter_registration_t &parameters, command_handler handler, const std::string &description = "", snowflake guild_id = 0);
/**
* @brief Route a command from the on_message_create function.
* Call this method from within your on_message_create with the received
* dpp::message object.
*
* @param msg message to parse
*/
void route(const class dpp::message& msg);
/**
* @brief Route a command from the on_interaction_create function.
* Call this method from your on_interaction_create with the received
* dpp::interaction_create_t object.
*
* @param event command interaction event to parse
*/
void route(const class interaction_create_t & event);
/**
* @brief Reply to a command.
* You should use this method rather than cluster::message_create as
* the way you reply varies between slash commands and message commands.
* Note you should ALWAYS reply. Slash commands will emit an ugly error
* to the user if you do not emit some form of reply within 3 seconds.
*
* @param m message to reply with.
* @param interaction true if the reply is generated by an interaction
*/
void reply(const dpp::message &m, command_source source);
};
};

283
vendor/DPP/include/dpp/discord.h vendored Normal file
View File

@ -0,0 +1,283 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <string>
#include <vector>
#include <unordered_map>
#include <map>
#include <functional>
/**
* @brief The main namespace for D++ functions. classes and types
*/
namespace dpp {
/** @brief A 64 bit unsigned value representing many things on discord.
* Discord calls the value a 'snowflake' value.
*/
typedef uint64_t snowflake;
/** @brief The managed class is the base class for various types that can
* be stored in a cache that are identified by a dpp::snowflake id
*/
class CoreExport managed {
public:
/** Unique ID of object */
snowflake id;
/** Constructor, initialises id to 0 */
managed(const snowflake = 0);
/** Default destructor */
virtual ~managed() = default;
};
/** @brief Supported image types for profile pictures */
enum image_type {
/// image/png
i_png,
/// image/jpeg
i_jpg,
/// image/gif
i_gif
};
/** @brief Log levels */
enum loglevel {
/// Trace
ll_trace = 0,
/// Debug
ll_debug,
/// Information
ll_info,
/// Warning
ll_warning,
/// Error
ll_error,
/// Critical
ll_critical
};
/** @brief Utility helper functions, generally for logging */
namespace utility {
typedef std::function<void(const std::string& output)> cmd_result_t;
/**
* @brief Run a commandline program asyncronously. The command line program
* is spawned in a separate std::thread, and when complete, its output from
* stdout is passed to the callback function in its string prameter. For eample
* ```
* dpp::utility::exec("ls", [](const std::string& output) {
* std::cout << "Output of 'ls': " << output << "\n";
* });
* ```
*
* @param cmd The command to run.
* @param parameters Command line parameters. Each will be escaped using std::quoted.
* @param callback The callback to call on completion.
*/
void CoreExport exec(const std::string& cmd, std::vector<std::string> parameters = {}, cmd_result_t callback = {});
/**
* @brief Returns urrent date and time
*
* @return std::string Current date and time
*/
std::string CoreExport current_date_time();
/**
* @brief Convert a dpp::loglevel enum value to a string
*
* @param in log level to convert
* @return std::string string form of log level
*/
std::string CoreExport loglevel(dpp::loglevel in);
/**
* @brief Store a 128 bit icon hash (profile picture, server icon etc)
* as a 128 bit binary value made of two uint64_t.
* Has a constructor to build one from a string, and a method to fetch
* the value back in string form.
*/
struct CoreExport iconhash {
uint64_t first; //!< High 64 bits
uint64_t second; //!< Low 64 bits
/**
* @brief Construct a new iconcash object
*/
iconhash();
/**
* @brief Construct a new iconhash object
*
* @param hash String hash to construct from.
* Must contain a 32 character hex string.
*
* @throws std::length_error if the provided
* string is not exactly 32 characters long.
*/
iconhash(const std::string &hash);
/**
* @brief Assign from std::string
*
* @param assignment string to assign from.
*
* @throws std::length_error if the provided
* string is not exactly 32 characters long.
*/
iconhash& operator=(const std::string &assignment);
/**
* @brief Change value of iconhash object
*
* @param hash String hash to change to.
* Must contain a 32 character hex string.
*
* @throws std::length_error if the provided
* string is not exactly 32 characters long.
*/
void set(const std::string &hash);
/**
* @brief Convert iconhash back to 32 character
* string value.
*
* @return std::string Hash value
*/
std::string to_string() const;
};
/**
* @brief Return the current time with fractions of seconds.
* This is a unix epoch time with the fractional seconds part
* after the decimal place.
*
* @return double time with fractional seconds
*/
double CoreExport time_f();
/**
* @brief Returns true if D++ was built with voice support
*
* @return bool True if voice support is compiled in (libsodium/libopus)
*/
bool CoreExport has_voice();
/**
* @brief Convert a byte count to display value
*
* @param c number of bytes
* @return std::string display value suffixed with M, G, T where neccessary
*/
std::string CoreExport bytes(uint64_t c);
/**
* @brief A class used to represent an uptime in hours, minutes,
* seconds and days, with helper functions to convert from time_t
* and display as a string.
*/
struct CoreExport uptime {
uint16_t days; //!< Number of days
uint8_t hours; //!< Number of hours
uint8_t mins; //!< Number of minutes
uint8_t secs; //!< Number of seconds
/**
* @brief Construct a new uptime object
*/
uptime();
/**
* @brief Construct a new uptime object
*
* @param diff A time_t to initialise the object from
*/
uptime(time_t diff);
/**
* @brief Get uptime as string
*
* @return std::string Uptime as string
*/
std::string to_string();
/**
* @brief Get uptime as seconds
*
* @return uint64_t Uptime as seconds
*/
uint64_t to_secs();
/**
* @brief Get uptime as milliseconds
*
* @return uint64_t Uptime as milliseconds
*/
uint64_t to_msecs();
};
/**
* @brief Output hex values of a section of memory for debugging
*
* @param data The start of the data to display
* @param length The length of data to display
*/
void CoreExport debug_dump(uint8_t* data, size_t length);
/**
* @brief Returns the length of a UTF-8 string in codepoints
*
* @param str string to count length of
* @return size_t length of string (0 for invalid utf8)
*/
size_t CoreExport utf8len(const std::string &str);
/**
* @brief Return substring of a UTF-8 encoded string in codepoints
*
* @param str string to return substring from
* @param start start codepoint offset
* @param length length in codepoints
* @return std::string Substring in UTF-8 or emtpy string if invalid UTF-8 passed in
*/
std::string CoreExport utf8substr(const std::string& str, std::string::size_type start, std::string::size_type length);
};
};
#include <dpp/voicestate.h>
#include <dpp/role.h>
#include <dpp/user.h>
#include <dpp/channel.h>
#include <dpp/guild.h>
#include <dpp/invite.h>
#include <dpp/dtemplate.h>
#include <dpp/emoji.h>
#include <dpp/ban.h>
#include <dpp/prune.h>
#include <dpp/voiceregion.h>
#include <dpp/integration.h>
#include <dpp/webhook.h>
#include <dpp/presence.h>
#include <dpp/intents.h>
#include <dpp/slashcommand.h>
#include <dpp/auditlog.h>

358
vendor/DPP/include/dpp/discordclient.h vendored Normal file
View File

@ -0,0 +1,358 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <string>
#include <map>
#include <vector>
#include <dpp/json_fwd.hpp>
#include <dpp/wsclient.h>
#include <dpp/dispatcher.h>
#include <dpp/cluster.h>
#include <dpp/discordvoiceclient.h>
#include <queue>
#include <thread>
#include <deque>
#include <mutex>
using json = nlohmann::json;
#define DISCORD_API_VERSION "9"
#define DEFAULT_GATEWAY "gateway.discord.gg"
#define API_PATH "/api/v" DISCORD_API_VERSION
namespace dpp {
// Forward declarations
class cluster;
/** This is an opaque class containing zlib library specific structures.
* We define it this way so that the public facing D++ library doesnt require
* the zlib headers be available to build against it.
*/
class zlibcontext;
/**
* @brief Represents a connection to a voice channel.
* A client can only connect to one voice channel per guild at a time, so these are stored in a map
* in the dpp::discord_client keyed by guild_id.
*/
class CoreExport voiceconn {
/**
* @brief Owning dpp::discord_client instance
*/
class discord_client* creator;
public:
/**
* @brief Voice Channel ID
*/
snowflake channel_id;
/**
* @brief Websocket hostname for status
*/
std::string websocket_hostname;
/**
* @brief Voice Voice session ID
*/
std::string session_id;
/**
* @brief Voice websocket token
*/
std::string token;
/**
* @brief voice websocket client
*/
class discord_voice_client* voiceclient;
/**
* @brief Construct a new voiceconn object
*/
voiceconn() = default;
/**
* @brief Construct a new voiceconn object
*
* @param o owner
* @param _channel_id voice channel id
*/
voiceconn(class discord_client* o, snowflake _channel_id);
/**
* @brief Destroy the voiceconn object
*/
~voiceconn();
/**
* @brief return true if the connection is ready to connect
* (has hostname, token and session id)
*
* @return true if ready to connect
*/
bool is_ready();
/**
* @brief return true if the connection is active (websocket exists)
*
* @return true if has an active websocket
*/
bool is_active();
/**
* @brief Create websocket object and connect it.
* Needs hosname, token and session_id to be set or does nothing.
*
* @param guild_id Guild to connect to the voice channel on
*/
void connect(snowflake guild_id);
/**
* @brief Disconnect from the currently connected voice channel
*/
void disconnect();
};
/** @brief Implements a discord client. Each discord_client connects to one shard and derives from a websocket client. */
class CoreExport discord_client : public websocket_client
{
/** Mutex for message queue */
std::mutex queue_mutex;
/** Queue of outbound messages */
std::deque<std::string> message_queue;
/** Thread this shard is executing on */
std::thread* runner;
/** Run shard loop under a thread */
void ThreadRun();
/** If true, stream compression is enabled */
bool compressed;
/** ZLib decompression buffer */
unsigned char* decomp_buffer;
/** Decompressed string */
std::string decompressed;
/** Frame decompression stream */
zlibcontext* zlib;
/** Total decompressed received bytes */
uint64_t decompressed_total;
/** Last connect time of cluster */
time_t connect_time;
/** Time last ping sent to websocket */
double ping_start;
/**
* @brief Initialise ZLib
*/
void SetupZLib();
/**
* @brief Shut down ZLib
*/
void EndZLib();
public:
/** Owning cluster */
class dpp::cluster* creator;
/** Heartbeat interval for sending heartbeat keepalive */
uint32_t heartbeat_interval;
/** Last heartbeat */
time_t last_heartbeat;
/** Shard ID of this client */
uint32_t shard_id;
/** Total number of shards */
uint32_t max_shards;
/** Thread ID */
std::thread::native_handle_type thread_id;
/** Last sequence number received, for resumes and pings */
uint64_t last_seq;
/** Discord bot token */
std::string token;
/** Privileged gateway intents */
uint32_t intents;
/** Discord session id */
std::string sessionid;
/** Mutex for voice connections map */
std::mutex voice_mutex;
/** Resume count */
uint32_t resumes;
/** Reconnection count */
uint32_t reconnects;
/** Websocket latency in fractional seconds */
double websocket_ping;
/** True if READY or RESUMED has been received */
bool ready;
/** Last heartbeat ACK (opcode 11) */
time_t last_heartbeat_ack;
/** List of voice channels we are connecting to keyed by guild id */
std::unordered_map<snowflake, voiceconn*> connecting_voice_channels;
/** Log a message to whatever log the user is using.
* The logged message is passed up the chain to the on_log event in user code which can then do whatever
* it wants to do with it.
* @param severity The log level from dpp::loglevel
* @param msg The log message to output
*/
virtual void log(dpp::loglevel severity, const std::string &msg) const;
/** Handle an event (opcode 0)
* @param event Event name, e.g. MESSAGE_CREATE
* @param j JSON object for the event content
* @param raw Raw JSON event string
*/
virtual void HandleEvent(const std::string &event, json &j, const std::string &raw);
/**
* @brief Get the Guild Count for this shard
*
* @return uint64_t guild count
*/
uint64_t get_guild_count();
/**
* @brief Get the Member Count for this shard
*
* @return uint64_t member count
*/
uint64_t get_member_count();
/**
* @brief Get the Channel Count for this shard
*
* @return uint64_t channel count
*/
uint64_t get_channel_count();
/** Fires every second from the underlying socket I/O loop, used for sending heartbeats */
virtual void one_second_timer();
/**
* @brief Queue a message to be sent via the websocket
*
* @param j The JSON data of the message to be sent
* @param to_front If set to true, will place the message at the front of the queue not the back
* (this is for urgent messages such as heartbeat, presence, so they can take precedence over
* chunk requests etc)
*/
void QueueMessage(const std::string &j, bool to_front = false);
/**
* @brief Clear the outbound message queue
*
*/
void ClearQueue();
/**
* @brief Get the size of the outbound message queue
*
* @return The size of the queue
*/
size_t GetQueueSize();
/**
* @brief Returns true if the shard is connected
*
* @return True if connected
*/
bool is_connected();
/**
* @brief Returns the connection time of the shard
*
* @return dpp::utility::uptime Detail of how long the shard has been connected for
*/
dpp::utility::uptime get_uptime();
/** Constructor takes shard id, max shards and token.
* @param _cluster The owning cluster for this shard
* @param _shard_id The ID of the shard to start
* @param _max_shards The total number of shards across all clusters
* @param _token The bot token to use for identifying to the websocket
* @param intents Privileged intents to use, a bitmask of values from dpp::intents
* @param compressed True if the received data will be gzip compressed
*/
discord_client(dpp::cluster* _cluster, uint32_t _shard_id, uint32_t _max_shards, const std::string &_token, uint32_t intents = 0, bool compressed = true);
/** Destructor */
virtual ~discord_client();
/** Get decompressed total bytes received */
uint64_t get_decompressed_bytes_in();
/** Handle JSON from the websocket.
* @param buffer The entire buffer content from the websocket client
* @returns True if a frame has been handled
*/
virtual bool HandleFrame(const std::string &buffer);
/** Handle a websocket error.
* @param errorcode The error returned from the websocket
*/
virtual void Error(uint32_t errorcode);
/** Start and monitor I/O loop */
void Run();
/**
* @brief Connect to a voice channel
*
* @param guild_id Guild where the voice channel is
* @param channel_id Channel ID of the voice channel
*/
void connect_voice(snowflake guild_id, snowflake channel_id);
/**
* @brief Disconnect from the connected voice channel on a guild
*
* @param guild_id The guild who's voice channel you wish to disconnect from
*/
void disconnect_voice(snowflake guild_id);
voiceconn* get_voice(snowflake guild_id);
};
};

148
vendor/DPP/include/dpp/discordevents.h vendored Normal file
View File

@ -0,0 +1,148 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/json_fwd.hpp>
namespace dpp {
/** @brief Returns a snowflake id from a json field value, if defined, else returns 0
* @param j nlohmann::json instance to retrieve value from
* @param keyname key name to check for a value
* @return found value
*/
uint64_t SnowflakeNotNull(const nlohmann::json* j, const char *keyname);
/** @brief Sets a snowflake id from a json field value, if defined, else does nothing
* @param j nlohmann::json instance to retrieve value from
* @param keyname key name to check for a value
* @param v Value to change
*/
void SetSnowflakeNotNull(const nlohmann::json* j, const char *keyname, uint64_t &v);
/** @brief Returns a string from a json field value, if defined, else returns an empty string.
* @param j nlohmann::json instance to retrieve value from
* @param keyname key name to check for a value
* @return found value
*/
std::string StringNotNull(const nlohmann::json* j, const char *keyname);
/** @brief Sets a string from a json field value, if defined, else does nothing
* @param j nlohmann::json instance to retrieve value from
* @param keyname key name to check for a value
* @param v Value to change
*/
void SetStringNotNull(const nlohmann::json* j, const char *keyname, std::string &v);
/** @brief Returns a 64 bit unsigned integer from a json field value, if defined, else returns 0.
* DO NOT use this for snowflakes, as usually snowflakes are wrapped in a string!
* @param j nlohmann::json instance to retrieve value from
* @param keyname key name to check for a value
* @return found value
*/
uint64_t Int64NotNull(const nlohmann::json* j, const char *keyname);
/** @brief Sets an unsigned 64 bit integer from a json field value, if defined, else does nothing
* @param j nlohmann::json instance to retrieve value from
* @param keyname key name to check for a value
* @param v Value to change
*/
void SetInt64NotNull(const nlohmann::json* j, const char *keyname, uint64_t &v);
/** @brief Returns a 32 bit unsigned integer from a json field value, if defined, else returns 0
* @param j nlohmann::json instance to retrieve value from
* @param keyname key name to check for a value
* @return found value
*/
uint32_t Int32NotNull(const nlohmann::json* j, const char *keyname);
/** @brief Sets an unsigned 32 bit integer from a json field value, if defined, else does nothing
* @param j nlohmann::json instance to retrieve value from
* @param keyname key name to check for a value
* @param v Value to change
*/
void SetInt32NotNull(const nlohmann::json* j, const char *keyname, uint32_t &v);
/** @brief Returns a 16 bit unsigned integer from a json field value, if defined, else returns 0
* @param j nlohmann::json instance to retrieve value from
* @param keyname key name to check for a value
* @return found value
*/
uint16_t Int16NotNull(const nlohmann::json* j, const char *keyname);
/** @brief Sets an unsigned 16 bit integer from a json field value, if defined, else does nothing
* @param j nlohmann::json instance to retrieve value from
* @param keyname key name to check for a value
* @param v Value to change
*/
void SetInt16NotNull(const nlohmann::json* j, const char *keyname, uint16_t &v);
/** @brief Returns an 8 bit unsigned integer from a json field value, if defined, else returns 0
* @param j nlohmann::json instance to retrieve value from
* @param keyname key name to check for a value
* @return found value
*/
uint8_t Int8NotNull(const nlohmann::json* j, const char *keyname);
/** @brief Sets an unsigned 8 bit integer from a json field value, if defined, else does nothing
* @param j nlohmann::json instance to retrieve value from
* @param keyname key name to check for a value
* @param v Value to change
*/
void SetInt8NotNull(const nlohmann::json* j, const char *keyname, uint8_t &v);
/** @brief Returns a boolean value from a json field value, if defined, else returns false
* @param j nlohmann::json instance to retrieve value from
* @param keyname key name to check for a value
* @return found value
*/
bool BoolNotNull(const nlohmann::json* j, const char *keyname);
/** @brief Sets a boolean from a json field value, if defined, else does nothing
* @param j nlohmann::json instance to retrieve value from
* @param keyname key name to check for a value
* @param v Value to change
*/
void SetBoolNotNull(const nlohmann::json* j, const char *keyname, bool &v);
/** @brief Returns a time_t from an ISO8601 timestamp field in a json value, if defined, else returns
* epoch value of 0.
* @param j nlohmann::json instance to retrieve value from
* @param keyname key name to check for a value
* @return found value
*/
time_t TimestampNotNull(const nlohmann::json* j, const char *keyname);
/** @brief Sets an timestamp from a json field value containing an ISO8601 string, if defined, else does nothing
* @param j nlohmann::json instance to retrieve value from
* @param keyname key name to check for a value
* @param v Value to change
*/
void SetTimestampNotNull(const nlohmann::json* j, const char *keyname, time_t &v);
/** @brief Base64 encode data into a string.
* @param buf Raw binary buffer
* @param buffer_length Buffer length to encode
* @return The base64 encoded string
*/
std::string base64_encode(unsigned char const* buf, unsigned int buffer_length);
};

View File

@ -0,0 +1,513 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <errno.h>
#ifdef _WIN32
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <io.h>
#else
#include <resolv.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <string>
#include <map>
#include <vector>
#include <dpp/json_fwd.hpp>
#include <dpp/wsclient.h>
#include <dpp/dispatcher.h>
#include <dpp/cluster.h>
#include <queue>
#include <thread>
#include <deque>
#include <mutex>
#ifdef HAVE_VOICE
#include <sodium.h>
#include <opus/opus.h>
#endif
using json = nlohmann::json;
namespace dpp {
// Forward declaration
class cluster;
#define AUDIO_TRACK_MARKER (uint16_t)0xFFFF
/** @brief Implements a discord voice connection.
* Each discord_voice_client connects to one voice channel and derives from a websocket client.
*/
class CoreExport discord_voice_client : public websocket_client
{
/** Mutex for outbound packet stream */
std::mutex stream_mutex;
/** Mutex for message queue */
std::mutex queue_mutex;
/** Queue of outbound messages */
std::deque<std::string> message_queue;
/** Thread this connection is executing on */
std::thread* runner;
/** Run shard loop under a thread */
void ThreadRun();
/** Last connect time of voice session */
time_t connect_time;
/**
* @brief IP of UDP/RTP endpoint
*/
std::string ip;
/**
* @brief Port number of UDP/RTP endpoint
*/
uint16_t port;
/**
* @brief SSRC value
*/
uint64_t ssrc;
/**
* @brief List of supported audio encoding modes
*/
std::vector<std::string> modes;
/** Output buffer. Each string is a UDP packet.
* Generally these will be RTP.
*/
std::vector<std::string> outbuf;
/** Input buffer. Each string is a received UDP
* packet. These will usually be RTP.
*/
std::vector<std::string> inbuf;
/** If true, audio packet sending is paused
*/
bool paused;
#ifdef HAVE_VOICE
/** libopus encoder
*/
OpusEncoder* encoder;
/** libopus decoder
*/
OpusDecoder* decoder;
/** libopus repacketizer
* (merges frames into one packet)
*/
OpusRepacketizer* repacketizer;
#endif
/** File descriptor for UDP connection
*/
SOCKET fd;
/** Socket address of voice server
*/
struct sockaddr_in servaddr;
/** Secret key for encrypting voice.
* If it has been sent, this is non-null and points to a
* sequence of exactly 32 bytes.
*/
uint8_t* secret_key;
/** Sequence number of outbound audio. This is incremented
* once per frame sent.
*/
uint16_t sequence;
/** Timestamp value used in outbound audio. Each packet
* has the timestamp value which is incremented to match
* how many frames are sent.
*/
uint32_t timestamp;
/** This is set to true if we have started sending audio.
* When this moves from false to true, this causes the
* client to send the 'talking' notification to the websocket.
*/
bool sending;
/** Number of track markers in the buffer. For example if there
* are two track markers in the buffer there are 3 tracks.
* Special case:
* If the buffer is empty, there are zero tracks in the
* buffer.
*/
uint32_t tracks;
/** Meta data associated with each track.
* Arbitrary string that the user can set via
* dpp::discord_voice_client::AddMarker
*/
std::vector<std::string> track_meta;
/** Encoding buffer for opus repacketizer and encode
*/
uint8_t encode_buffer[65536];
/**
* @brief Send data to UDP socket immediately.
*
* @param data data to send
* @param length length of data to send
* @return int bytes sent. Will return -1 if we cannot send
*/
int UDPSend(const char* data, size_t length);
/**
* @brief Receieve data from UDP socket immediately.
*
* @param data data to receive
* @param max_length size of data receiving buffer
* @return int bytes received. -1 if there is an error
* (e.g. EAGAIN)
*/
int UDPRecv(char* data, size_t max_length);
/**
* @brief This hooks the ssl_client, returning the file
* descriptor if we want to send buffered data, or
* -1 if there is nothing to send
*
* @return int file descriptor or -1
*/
int WantWrite();
/**
* @brief This hooks the ssl_client, returning the file
* descriptor if we want to receive buffered data, or
* -1 if we are not wanting to receive
*
* @return int file descriptor or -1
*/
int WantRead();
/**
* @brief Called by ssl_client when the socket is ready
* for writing, at this point we pick the head item off
* the buffer and send it. So long as it doesnt error
* completely, we pop it off the head of the queue.
*/
void WriteReady();
/**
* @brief Called by ssl_client when there is data to be
* read. At this point we insert that data into the
* input queue.
*/
void ReadReady();
/**
* @brief Send data to the UDP socket, using the buffer.
*
* @param packet packet data
* @param len length of packet
*/
void Send(const char* packet, size_t len);
/**
* @brief Queue a message to be sent via the websocket
*
* @param j The JSON data of the message to be sent
* @param to_front If set to true, will place the message at the front of the queue not the back
* (this is for urgent messages such as heartbeat, presence, so they can take precedence over
* chunk requests etc)
*/
void QueueMessage(const std::string &j, bool to_front = false);
/**
* @brief Clear the outbound message queue
*
*/
void ClearQueue();
/**
* @brief Get the size of the outbound message queue
*
* @return The size of the queue
*/
size_t GetQueueSize();
/**
* @brief Encode a byte buffer using opus codec.
* Multiple opus frames (2880 bytes each) will be encoded into one packet for sending.
*
* @param input Input data as raw bytes of PCM data
* @param inDataSize Input data length
* @param output Output data as an opus encoded packet
* @param outDataSize Output data length, should be at least equal to the input size.
* Will be adjusted on return to the actual compressed data size.
* @return size_t The compressed data size that was encoded.
*/
size_t encode(uint8_t *input, size_t inDataSize, uint8_t *output, size_t &outDataSize);
public:
/** Owning cluster */
class dpp::cluster* creator;
/* This needs to be static, we only initialise libsodium once per program start,
* so initialising it on first use in a voice connection is best.
*/
static bool sodium_initialised;
/** True when the thread is shutting down */
bool terminating;
/** Heartbeat interval for sending heartbeat keepalive */
uint32_t heartbeat_interval;
/** Last heartbeat */
time_t last_heartbeat;
/** Thread ID */
std::thread::native_handle_type thread_id;
/** Discord voice session token */
std::string token;
/** Discord voice session id */
std::string sessionid;
/** Server ID */
snowflake server_id;
/** Channel ID */
snowflake channel_id;
/** Log a message to whatever log the user is using.
* The logged message is passed up the chain to the on_log event in user code which can then do whatever
* it wants to do with it.
* @param severity The log level from dpp::loglevel
* @param msg The log message to output
*/
virtual void log(dpp::loglevel severity, const std::string &msg);
/** Fires every second from the underlying socket I/O loop, used for sending heartbeats */
virtual void one_second_timer();
/**
* @brief voice client is ready to stream audio.
* The voice client is considered ready if it has a secret key.
*
* @return true if ready to stream audio
*/
bool is_ready();
/**
* @brief Returns true if the voice client is connected to the websocket
*
* @return True if connected
*/
bool is_connected();
/**
* @brief Returns the connection time of the voice client
*
* @return dpp::utility::uptime Detail of how long the voice client has been connected for
*/
dpp::utility::uptime get_uptime();
/** Constructor takes shard id, max shards and token.
* @param _cluster The owning cluster for this shard
* @param _server_id The server id to identify voice connection as
* @param _token The voice session token to use for identifying to the websocket
* @param _session_id The voice session id to identify with
* @param _host The voice server hostname to connect to (hostname:port format)
*/
discord_voice_client(dpp::cluster* _cluster, snowflake _channel_id, snowflake _server_id, const std::string &_token, const std::string &_session_id, const std::string &_host);
/** Destructor */
virtual ~discord_voice_client();
/** Handle JSON from the websocket.
* @param buffer The entire buffer content from the websocket client
* @returns True if a frame has been handled
*/
virtual bool HandleFrame(const std::string &buffer);
/** Handle a websocket error.
* @param errorcode The error returned from the websocket
*/
virtual void Error(uint32_t errorcode);
/** Start and monitor I/O loop */
void Run();
/**
* @brief Send audio to the voice channel.
*
* You should send an audio packet of n11520 bytes.
* Note that this function can be costly as it has to opus encode
* the PCM audio on the fly, and also encrypt it with libsodium.
*
* @note Because this function encrypts and encodes packets before
* pushing them onto the output queue, if you have a complete stream
* ready to send and know its length it is advisable to call this
* method multiple times to enqueue the entire stream audio so that
* it is all encoded at once. Constantly calling this from the
* dpp::on_voice_buffer_send callback can and will eat a TON of cpu!
*
* @param audio_data Raw PCM audio data. Channels are interleaved,
* with each channel's amplitude being a 16 bit value.
* @param length The length of the audio data. The length should
* be a multiple of 4 (2x 16 bit stero channels) with a maximum
* length of 11520, which is a complete opus frame at highest
* quality.
* @param use_opus Some containers such as .ogg may contain OPUS
* encoded data already. In this case, we don't need to encode the
* frames using opus here. We can set use_opus to false and bypass the
* codec, only applying libsodium to the stream.
*/
void send_audio(uint16_t* audio_data, const size_t length, bool use_opus = true);
/**
* @brief Pause sending of audio
*
* @param pause True to pause, false to resume
*/
void pause_audio(bool pause);
/**
* @brief Immediately stop all audio.
* Clears the packet queue.
*/
void stop_audio();
/**
* @brief Returns true if we are playing audio
*
* @return true if audio is playing
*/
bool is_playing();
/**
* @brief Get the number of seconds remaining
* of the audio output buffer
*
* @return float number of seconds remaining
*/
float get_secs_remaining();
/**
* @brief Get the number of tracks remaining
* in the output buffer.
* This is calculated by the number of track
* markers plus one.
* @return uint32_t Number of tracks in the
* buffer
*/
uint32_t get_tracks_remaining();
/**
* @brief Get the time remaining to send the
* audio output buffer in hours:minutes:seconds
*
* @return dpp::utility::uptime length of buffer
*/
dpp::utility::uptime get_remaining();
/**
* @brief Insert a track marker into the audio
* output buffer.
* A track marker is an arbitrary flag in the
* buffer contents that indictes the end of some
* block of audio of significance to the sender.
* This may be a song from a streaming site, or
* some voice audio/speech, a sound effect, or
* whatever you choose. You can later skip
* to the next marker using the
* dpp::discord_voice_client::skip_to_next_marker
* function.
* @param metadata Arbitrary information related to this
* track
*/
void insert_marker(const std::string& metadata = "");
/**
* @brief Skip tp the next track marker,
* previously inserted by using the
* dpp::discord_voice_client::insert_marker
* function. If there are no markers in the
* output buffer, then this skips to the end
* of the buffer and is equivalent to the
* dpp::discord_voice_client::stop_audio
* function.
* @note It is possible to use this function
* while the output stream is paused.
*/
void skip_to_next_marker();
/**
* @brief Get the metdata string associated with each inserted marker.
*
* @return const std::vector<std::string>& list of metadata strings
*/
const std::vector<std::string> get_marker_metadata();
/**
* @brief Returns true if the audio is paused.
* You can unpause with
* dpp::discord_voice_client::pause_audio.
*
* @return true if paused
*/
bool is_paused();
/**
* @brief Discord external IP detection.
* @return std::string Your external IP address
* @note This is a blocking operation that waits
* for a single packet from Discord's voice servers.
*/
std::string discover_ip();
};
};

1189
vendor/DPP/include/dpp/dispatcher.h vendored Normal file

File diff suppressed because it is too large Load Diff

36
vendor/DPP/include/dpp/dpp.h vendored Normal file
View File

@ -0,0 +1,36 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <dpp/version.h>
#include <string>
#include <map>
#include <vector>
#include <fstream>
#include <iostream>
#include <ctime>
#include <dpp/dispatcher.h>
#include <dpp/discordclient.h>
#include <dpp/discord.h>
#include <dpp/cluster.h>
#include <dpp/cache.h>
#include <dpp/queues.h>
#include <dpp/commandhandler.h>

94
vendor/DPP/include/dpp/dtemplate.h vendored Normal file
View File

@ -0,0 +1,94 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <dpp/discord.h>
#include <dpp/json_fwd.hpp>
namespace dpp {
/**
* @brief Represents a guild template
*/
class CoreExport dtemplate {
public:
/**
* @brief Template code
*/
std::string code;
/**
* @brief Template name
*/
std::string name;
/**
* @brief Template description
*/
std::string description;
/**
* @brief Usage counter
*/
uint32_t usage_count;
/**
* @brief User ID of creator
*/
snowflake creator_id;
/**
* @brief Creation date/time
*
*/
time_t created_at;
/**
* @brief Last update date/time
*/
time_t updated_at;
/**
* @brief Guild id the template is created from
*/
snowflake source_guild_id;
/**
* @brief True if needs synchronising
*/
bool is_dirty;
/**
* @brief Construct a new dtemplate object
*/
dtemplate();
/**
* @brief Destroy the dtemplate object
*/
~dtemplate();
/** Read class values from json object
* @param j A json object to read from
* @return A reference to self
*/
dtemplate& fill_from_json(nlohmann::json* j);
std::string build_json() const;
};
/** A container of invites */
typedef std::unordered_map<snowflake, dtemplate> dtemplate_map;
};

155
vendor/DPP/include/dpp/emoji.h vendored Normal file
View File

@ -0,0 +1,155 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <dpp/discord.h>
#include <dpp/json_fwd.hpp>
namespace dpp {
#define MAX_EMOJI_SIZE 256 * 1024
/**
* @brief Flags for dpp::emoji
*/
enum emoji_flags {
/// Emoji requires colons
e_require_colons = 0b00000001,
/// Managed (introduced by application)
e_managed = 0b00000010,
/// Animated
e_animated = 0b00000100,
/// Available (false if the guild doesn't meet boosting criteria, etc)
e_available = 0b00001000,
};
/**
* @brief Represents an emoji for a dpp::guild
*/
class CoreExport emoji : public managed {
public:
/**
* @brief Emoji name
*/
std::string name;
/**
* @brief User id who uploaded the emoji
*/
snowflake user_id;
/**
* @brief Flags for the emoji from dpp::emoji_flags
*/
uint8_t flags;
/**
* @brief Image data for the emoji if uploading
*/
std::string* image_data;
/**
* @brief Construct a new emoji object
*/
emoji();
/**
* @brief Construct a new emoji object with name, ID and flags
*
* @param name The emoji's name
* @param id ID, if it has one (unicode does not)
* @param flags Emoji flags (emoji_flags)
*/
emoji(const std::string, const snowflake = 0, const uint8_t = 0);
/**
* @brief Destroy the emoji object
*/
virtual ~emoji();
/**
* @brief Read class values from json object
*
* @param j A json object to read from
* @return A reference to self
*/
emoji& fill_from_json(nlohmann::json* j);
/**
* @brief Build the json for this object
*
* @param with_id include the id in the JSON
* @return std::string json data
*/
std::string build_json(bool with_id = false) const;
/**
* @brief Emoji requires colons
*
* @return true Requires colons
* @return false Does not require colons
*/
bool requires_colons() const;
/**
* @brief Emoji is managed
*
* @return true Is managed
* @return false Is not managed
*/
bool is_managed() const;
/**
* @brief Emoji is animated
*
* @return true Is animated
* @return false Is noy animated
*/
bool is_animated() const;
/**
* @brief Is available
*
* @return true Is available
* @return false Is unavailable
*/
bool is_available() const;
/**
* @brief Load an image into the object as base64
*
* @param image_blob Image binary data
* @param type Type of image
* @return emoji& Reference to self
*/
emoji& load_image(const std::string &image_blob, image_type type);
/**
* @brief Format to name if unicode, name:id if has id or a:name:id if animated
*
* @return Formatted name for reactions
*/
std::string format() const;
};
/**
* @brief Group of emojis
*/
typedef std::unordered_map<snowflake, emoji> emoji_map;
};

139
vendor/DPP/include/dpp/event.h vendored Normal file
View File

@ -0,0 +1,139 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <dpp/discord.h>
#include <dpp/json_fwd.hpp>
#define event_decl(x) class x : public event { public: virtual void handle(dpp::discord_client* client, nlohmann::json &j, const std::string &raw); };
namespace dpp {
class discord_client;
/**
* @brief The events namespace holds the internal event handlers for each websocket event.
* These are handled internally and also dispatched to the user code if the event is hooked.
*/
namespace events {
/**
* @brief An event object represents an event handled internally, passed from the websocket e.g. MESSAGE_CREATE.
*/
class CoreExport event {
public:
/** Pure virtual method for event handler code
* @param client The creating shard
* @param j The json data of the event
* @param raw The raw event json
*/
virtual void handle(class discord_client* client, nlohmann::json &j, const std::string &raw) = 0;
};
/* Internal logger */
event_decl(logger);
/* Guilds */
event_decl(guild_create);
event_decl(guild_update);
event_decl(guild_delete);
event_decl(guild_ban_add);
event_decl(guild_ban_remove);
event_decl(guild_emojis_update);
event_decl(guild_integrations_update);
event_decl(guild_join_request_delete);
event_decl(guild_stickers_update);
/* Stage channels */
event_decl(stage_instance_create);
event_decl(stage_instance_delete);
/* Guild members */
event_decl(guild_member_add);
event_decl(guild_member_remove);
event_decl(guild_members_chunk);
event_decl(guild_member_update);
/* Guild roles */
event_decl(guild_role_create);
event_decl(guild_role_update);
event_decl(guild_role_delete);
/* Session state */
event_decl(resumed);
event_decl(ready);
/* Channels */
event_decl(channel_create);
event_decl(channel_update);
event_decl(channel_delete);
event_decl(channel_pins_update);
/* Threads */
event_decl(thread_create);
event_decl(thread_update);
event_decl(thread_delete);
event_decl(thread_list_sync);
event_decl(thread_member_update);
event_decl(thread_members_update);
/* Messages */
event_decl(message_create);
event_decl(message_update);
event_decl(message_delete);
event_decl(message_delete_bulk);
/* Presence/typing */
event_decl(presence_update);
event_decl(typing_start);
/* Users (outside of guild) */
event_decl(user_update);
/* Message reactions */
event_decl(message_reaction_add);
event_decl(message_reaction_remove);
event_decl(message_reaction_remove_all);
event_decl(message_reaction_remove_emoji);
/* Invites */
event_decl(invite_create);
event_decl(invite_delete);
/* Voice */
event_decl(voice_state_update);
event_decl(voice_server_update);
/* Webhooks */
event_decl(webhooks_update);
/* Slash commands */
event_decl(application_command_create);
event_decl(application_command_update);
event_decl(application_command_delete);
event_decl(interaction_create);
/* Integrations */
event_decl(integration_create);
event_decl(integration_update);
event_decl(integration_delete);
}};

43
vendor/DPP/include/dpp/export.h vendored Normal file
View File

@ -0,0 +1,43 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#ifdef DPP_BUILD
#ifdef _WIN32
#define CoreExport __declspec(dllexport)
#else
#define CoreExport
#endif
#else
#ifdef _WIN32
#define CoreExport __declspec(dllimport)
/* This is required otherwise fmt::format requires additional file linkage to your project */
#define FMT_HEADER_ONLY
#else
#define CoreExport
#endif
#endif
#ifndef _WIN32
#define SOCKET int
#else
#include <WinSock2.h>
#endif

432
vendor/DPP/include/dpp/guild.h vendored Normal file
View File

@ -0,0 +1,432 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <mutex>
#include <string>
#include <unordered_map>
#include <map>
#include <dpp/voicestate.h>
namespace dpp {
/**
* @brief Represents voice regions for guilds and channels.
* @note Largely deprecated in favour of per-channel regions.
*/
enum region : uint8_t {
r_brazil, //!< Brazil
r_central_europe, //!< Central Europe
r_hong_kong, //!< Hong Kong
r_india, //!< India
r_japan, //!< Japan
r_russia, //!< Russia
r_singapore, //!< Singapore
r_south_africa, //!< South Africa
r_sydney, //!< Sydney
r_us_central, //!< US Central
r_us_east, //!< US East Coast
r_us_south, //!< US South
r_us_west, //!< US West Coast
r_western_europe //!< Western Europe
};
/**
* @brief The various flags that represent the status of a dpp::guild object
*/
enum guild_flags {
/** Large guild */
g_large = 0b000000000000000000001,
/** Unavailable guild (inaccessible due to an outage) */
g_unavailable = 0b000000000000000000010,
/** Guild has widget enabled */
g_widget_enabled = 0b000000000000000000100,
/** Guild can have an invite splash image */
g_invite_splash = 0b000000000000000001000,
/** Guild can have VIP regions */
g_vip_regions = 0b000000000000000010000,
/** Guild can have a vanity url */
g_vanity_url = 0b000000000000000100000,
/** Guild is verified */
g_verified = 0b000000000000001000000,
/** Guild is partnered */
g_partnered = 0b000000000000010000000,
/** Community features enabled */
g_community = 0b000000000000100000000,
/** Guild has commerce features enabled */
g_commerce = 0b000000000001000000000,
/** Guild has news features enabled */
g_news = 0b000000000010000000000,
/** Guild is discoverable in discovery */
g_discoverable = 0b000000000100000000000,
/** Guild is featureable */
g_featureable = 0b000000001000000000000,
/** Guild can have an animated icon (doesn't mean it actually has one though) */
g_animated_icon = 0b000000010000000000000,
/** Guild can have a banner image */
g_banner = 0b000000100000000000000,
/** Guild has a welcome screen */
g_welcome_screen_enabled = 0b000001000000000000000,
/** Guild has a member verification gate */
g_member_verification_gate = 0b000010000000000000000,
/** Guild has a preview */
g_preview_enabled = 0b000100000000000000000,
/** Guild join notifications are off */
g_no_join_notifications = 0b001000000000000000000,
/** Guild boost notifications are off */
g_no_boost_notifications = 0b010000000000000000000,
/** Guild has an actual animated icon (set by the icon hash starting with 'a_') */
g_has_animated_icon = 0b100000000000000000000
};
/**
* @brief Various flags that can be used to indicate the status of a guild member
*/
enum guild_member_flags {
/** Member deafened */
gm_deaf = 0b00001,
/** Member muted */
gm_mute = 0b00010,
/** Member pending verification by membership screening */
gm_pending = 0b00100
};
/**
* @brief Represents dpp::user membership upon a dpp::guild
*/
class CoreExport guild_member {
public:
/** Nickname, or nullptr if they don't have a nickname on this guild */
std::string nickname;
/** Guild id */
snowflake guild_id;
/** User id */
snowflake user_id;
/** List of roles this user has on this guild */
std::vector<snowflake> roles;
/** Date and time the user joined the guild */
time_t joined_at;
/** Boosting since */
time_t premium_since;
/** A set of flags built from the bitmask defined by dpp::guild_member_flags */
uint8_t flags;
/** Default constructor */
guild_member();
/** Fill this object from a json object.
* @param j The json object to get data from
* @param g_id The guild id to associate the member with
* @param u_id The user id to associate the member with
*/
guild_member& fill_from_json(nlohmann::json* j, snowflake g_id, snowflake u_id);
/** Build json string for the member object */
std::string build_json() const;
/** Returns true if the user is deafened */
bool is_deaf() const;
/** Returns true if the user is muted */
bool is_muted() const;
/** Returns true if pending verification by membership screening */
bool is_pending() const;
};
/** @brief Guild members container
*/
typedef std::unordered_map<snowflake, guild_member> members_container;
/**
* @brief Represents a guild on Discord (AKA a server)
*/
class CoreExport guild : public managed {
public:
/** Shard ID of the guild */
uint16_t shard_id;
/** Flags bitmask as defined by values within dpp::guild_flags */
uint32_t flags;
/** Guild name */
std::string name;
/** Server description for communities */
std::string description;
/** Vanity url code for verified or partnered servers and boost level 3 */
std::string vanity_url_code;
/** Guild icon hash */
utility::iconhash icon;
/** Guild splash hash */
utility::iconhash splash;
/** Guild discovery splash hash */
utility::iconhash discovery_splash;
/** Snowflake id of guild owner */
snowflake owner_id;
/** Guild voice region */
region voice_region;
/** Snowflake ID of AFK voice channel or 0 */
snowflake afk_channel_id;
/** Voice AFK timeout before moving users to AFK channel */
uint8_t afk_timeout;
/** Snowflake ID of widget channel, or 0 */
snowflake widget_channel_id;
/** Verification level of server */
uint8_t verification_level;
/** Setting for how notifications are to be delivered to users */
uint8_t default_message_notifications;
/** Wether or not explicit content filtering is enable and what setting it is */
uint8_t explicit_content_filter;
/** If multi factor authentication is required for moderators or not */
uint8_t mfa_level;
/** ID of creating application, if any, or 0 */
snowflake application_id;
/** ID of system channel where discord update messages are sent */
snowflake system_channel_id;
/** ID of rules channel for communities */
snowflake rules_channel_id;
/** Approximate member count. May be sent as zero */
uint32_t member_count;
/** Server banner hash */
utility::iconhash banner;
/** Boost level */
uint8_t premium_tier;
/** Number of boosters */
uint16_t premium_subscription_count;
/** Public updates channel id or 0 */
snowflake public_updates_channel_id;
/** Maximum users in a video channel, or 0 */
uint16_t max_video_channel_users;
/** Roles defined on this server */
std::vector<snowflake> roles;
/** List of channels on this server */
std::vector<snowflake> channels;
/** List of threads on this server */
std::vector<snowflake> threads;
/** List of guild members. Note that when you first receive the
* guild create event, this may be empty or near empty.
* This depends upon your dpp::intents and the size of your bot.
* It will be filled by guild member chunk requests.
*/
members_container members;
/** List of members in voice channels in the guild.
*/
std::map<snowflake, voicestate> voice_members;
/** List of emojis
*/
std::vector<snowflake> emojis;
/** Default constructor, zeroes all values */
guild();
/**
* @brief Destroy the guild object
*/
virtual ~guild() = default;
/** Read class values from json object
* @param shard originating shard
* @param j A json object to read from
* @return A reference to self
*/
guild& fill_from_json(class discord_client* shard, nlohmann::json* j);
/** Build a JSON string from this object.
* @param with_id True if an ID is to be included in the JSON
*/
std::string build_json(bool with_id = false) const;
/**
* @brief Get the base permissions for a member on this guild,
* before permission overwrites are applied.
*
* @param member member to get permissions for
* @return uint64_t permissions bitmask
*/
uint64_t base_permissions(const class user* member) const;
/**
* @brief Get the permission overwrites for a member
* merged into a bitmask.
*
* @param base_permissions base permissions before overwrites,
* from channel::base_permissions
* @param member Member to fetch permissions for
* @param channel Channel to fetch permissions against
* @return uint64_t Merged permissions bitmask of overwrites.
*/
uint64_t permission_overwrites(const uint64_t base_permissions, const user* member, const channel* channel) const;
/**
* @brief Rehash members map
*/
void rehash_members();
/**
* @brief Connect to a voice channel another guild member is in
*
* @param user_id User id to join
* @return True if the user specified is in a vc, false if they aren't
*/
bool connect_member_voice(snowflake user_id);
/** Is a large server (>250 users) */
bool is_large() const;
/** Is unavailable due to outage (most other fields will be blank or outdated */
bool is_unavailable() const;
/** Widget is enabled for this server */
bool widget_enabled() const;
/** Guild has an invite splash */
bool has_invite_splash() const;
/** Guild has VIP regions */
bool has_vip_regions() const;
/** Guild can have a vanity url */
bool has_vanity_url() const;
/** Guild is a verified server */
bool is_verified() const;
/** Guild is a discord partner server */
bool is_partnered() const;
/** Guild has enabled community */
bool is_community() const;
/** Guild has enabled commerce channels */
bool has_commerce() const;
/** Guild has news channels */
bool has_news() const;
/** Guild is discoverable */
bool is_discoverable() const;
/** Guild is featureable */
bool is_featureable() const;
/** Guild is allowed an animated icon */
bool has_animated_icon() const;
/** Guild has a banner image */
bool has_banner() const;
/** Guild has enabled welcome screen */
bool is_welcome_screen_enabled() const;
/** Guild has enabled membership screening */
bool has_member_verification_gate() const;
/** Guild has preview enabled */
bool is_preview_enabled() const;
/** Server icon is actually an animated gif */
bool has_animated_icon_hash() const;
};
/** A container of guilds */
typedef std::unordered_map<snowflake, guild> guild_map;
/**
* @brief Represents a guild widget, simple web widget of member list
*/
class CoreExport guild_widget {
public:
/**
* @brief True if enabled
*/
bool enabled;
/**
* @brief Channel widget points to
*/
snowflake channel_id;
/**
* @brief Construct a new guild widget object
*/
guild_widget();
/**
* @brief Build a guild widget from json
*
* @param j json to build from
* @return guild_widget& reference to self
*/
guild_widget& fill_from_json(nlohmann::json* j);
/**
* @brief Build json for a guild widget
*
* @return std::string guild widget stringified json
*/
std::string build_json() const;
};
/**
* @brief helper function to deserialize a guild_member from json
*
* @see https://github.com/nlohmann/json#arbitrary-types-conversions
*
* @param j output json object
* @param gm guild_member to be deserialized
*/
void from_json(const nlohmann::json& j, guild_member& gm);
/** A container of guild members */
typedef std::unordered_map<snowflake, guild_member> guild_member_map;
};

1452
vendor/DPP/include/dpp/httplib.h vendored Normal file

File diff suppressed because it is too large Load Diff

132
vendor/DPP/include/dpp/integration.h vendored Normal file
View File

@ -0,0 +1,132 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <dpp/json_fwd.hpp>
namespace dpp {
/**
* @brief Integration types
*/
enum integration_type {
/// Twitch integration
i_twitch,
/// YouTube integration
i_youtube,
/// Discord integration
i_discord
};
/**
* @brief Integration flags
*/
enum integration_flags {
/// Integration enabled
if_enabled = 0b00000001,
/// Integration synching
if_syncing = 0b00000010,
/// Emoji integration
if_emoticons = 0b00000100,
/// Integration revoked
if_revoked = 0b00001000,
/// Kick users when their subscription expires
if_expire_kick = 0b00010000,
};
/**
* @brief An application that has been integrated
*/
struct CoreExport integration_app {
/// Inegration id
snowflake id;
/// Name
std::string name;
/// Icon
std::string icon;
/// Description
std::string description;
/// Integration summary
std::string summary;
/// Pointer to bot user
user* bot;
};
/** Represents an integration within a dpp::guild */
class CoreExport integration : public managed {
public:
/** Integration name */
std::string name;
/** Integration type */
integration_type type;
/** Integration flags from dpp::integration_flags */
uint8_t flags;
/** Role id */
snowflake role_id;
/** User id */
snowflake user_id;
/** Expiry grace period */
uint32_t expire_grace_period;
/** Sync time */
time_t synced_at;
/** Subscriber count */
uint32_t subscriber_count;
/* Account id */
std::string account_id;
/* Account name */
std::string account_name;
/* Integration application */
integration_app app;
/** Default constructor */
integration();
/** Default destructor */
~integration();
/** Read class values from json object
* @param j A json object to read from
* @return A reference to self
*/
integration& fill_from_json(nlohmann::json* j);
/** Build a json string from this object.
* @return JSON string of the object
*/
std::string build_json() const;
/** True if emoticons are enabled */
bool emoticons_enabled() const;
/** True if integration is enabled */
bool is_enabled() const;
/** True if is syncing */
bool is_syncing() const;
/** True if has been revoked */
bool is_revoked() const;
/** True if expiring kicks the user */
bool expiry_kicks_user() const;
};
/** A group of integrations */
typedef std::unordered_map<snowflake, integration> integration_map;
};

71
vendor/DPP/include/dpp/intents.h vendored Normal file
View File

@ -0,0 +1,71 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
namespace dpp {
/**
* @brief intents are a bitmask of allowed events on your websocket.
*
* Some of these are known as Privileged intents (GUILD_MEMBERS and GUILD_PRESENCES)
* and require verification of a bot over 100 servers by discord via submission of
* your real life ID.
*/
enum intents {
/// Intent for receipt of guild information
i_guilds = (1 << 0),
/// Intent for receipt of guild members
i_guild_members = (1 << 1),
/// Intent for receipt of guild bans
i_guild_bans = (1 << 2),
/// Intent for receipt of guild emojis
i_guild_emojis = (1 << 3),
/// Intent for receipt of guild integrations
i_guild_integrations = (1 << 4),
/// Intent for receipt of guild webhooks
i_guild_webhooks = (1 << 5),
/// Intent for receipt of guild invites
i_guild_invites = (1 << 6),
/// Intent for receipt of guild voice states
i_guild_voice_states = (1 << 7),
/// Intent for receipt of guild presences
i_guild_presences = (1 << 8),
/// Intent for receipt of guild messages
i_guild_messages = (1 << 9),
/// Intent for receipt of guild message reactions
i_guild_message_reactions = (1 << 10),
/// Intent for receipt of guild message typing notifications
i_guild_message_typing = (1 << 11),
/// Intent for receipt of direct messages (DMs)
i_direct_messages = (1 << 12),
/// Intent for receipt of direct message reactions
i_direct_message_reactions = (1 << 13),
/// Intent for receipt of direct message typing notifications
i_direct_message_typing = (1 << 14),
/// Default D++ intents (all non-privileged intents)
i_default_intents = dpp::i_guilds | dpp::i_guild_bans | dpp::i_guild_emojis | dpp::i_guild_integrations | dpp::i_guild_webhooks | dpp::i_guild_invites | dpp::i_guild_voice_states | dpp::i_guild_messages | dpp::i_guild_message_reactions | dpp::i_guild_message_typing | dpp::i_direct_messages | dpp::i_direct_message_typing | dpp::i_direct_message_reactions,
// Privileged intents requiring ID
i_privileged_intents = dpp::i_guild_members | dpp::i_guild_presences,
// Every single intent
i_all_intents = dpp::i_default_intents | dpp::i_privileged_intents
};
};

94
vendor/DPP/include/dpp/invite.h vendored Normal file
View File

@ -0,0 +1,94 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <dpp/discord.h>
#include <dpp/json_fwd.hpp>
namespace dpp {
/**
* @brief Represents an invite to a discord guild or channel
*/
class CoreExport invite {
public:
/** Invite code
*/
std::string code;
/** Guild for the invite
*/
snowflake guild_id;
/** Channel id for invite
*/
snowflake channel_id;
/** User ID of invite creator
*/
snowflake inviter_id;
/** Target user ID of invite, for invites sent via DM
*/
snowflake target_user_id;
/** Target user type (generally this is always 1, "stream")
*/
uint8_t target_user_type;
/** Approximate number of online users
*/
uint32_t approximate_presence_count;
/** Approximate total users online and offline
*/
uint32_t approximate_member_count;
/** Maximum age of invite
*/
uint32_t max_age;
/** Maximum number of uses
*/
uint32_t max_uses;
/** True if a temporary invite which grants access for a limited time
*/
bool temporary;
/** True if this invite should not replace or "attach to" similar invites
*/
bool unique;
/** Constructor
*/
invite();
/** Destructor
*/
~invite();
/** Read class values from json object
* @param j A json object to read from
* @return A reference to self
*/
invite& fill_from_json(nlohmann::json* j);
/** Build JSON from this object.
* @return The JSON text of the invite
*/
std::string build_json() const;
};
/** A container of invites */
typedef std::unordered_map<std::string, invite> invite_map;
};

78
vendor/DPP/include/dpp/json_fwd.hpp vendored Normal file
View File

@ -0,0 +1,78 @@
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
#include <cstdint> // int64_t, uint64_t
#include <map> // map
#include <memory> // allocator
#include <string> // string
#include <vector> // vector
/*!
@brief namespace for Niels Lohmann
@see https://github.com/nlohmann
@since version 1.0.0
*/
namespace nlohmann
{
/*!
@brief default JSONSerializer template argument
This serializer ignores the template arguments and uses ADL
([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
for serialization.
*/
template<typename T = void, typename SFINAE = void>
struct adl_serializer;
template<template<typename U, typename V, typename... Args> class ObjectType =
std::map,
template<typename U, typename... Args> class ArrayType = std::vector,
class StringType = std::string, class BooleanType = bool,
class NumberIntegerType = std::int64_t,
class NumberUnsignedType = std::uint64_t,
class NumberFloatType = double,
template<typename U> class AllocatorType = std::allocator,
template<typename T, typename SFINAE = void> class JSONSerializer =
adl_serializer,
class BinaryType = std::vector<std::uint8_t>>
class basic_json;
/*!
@brief JSON Pointer
A JSON pointer defines a string syntax for identifying a specific value
within a JSON document. It can be used with functions `at` and
`operator[]`. Furthermore, JSON pointers are the base for JSON patches.
@sa [RFC 6901](https://tools.ietf.org/html/rfc6901)
@since version 2.0.0
*/
template<typename BasicJsonType>
class json_pointer;
/*!
@brief default JSON class
This type is the default specialization of the @ref basic_json class which
uses the standard template types.
@since version 1.0.0
*/
using json = basic_json<>;
template<class Key, class T, class IgnoredLess, class Allocator>
struct ordered_map;
/*!
@brief ordered JSON class
This type preserves the insertion order of object keys.
@since version 3.9.0
*/
using ordered_json = basic_json<nlohmann::ordered_map>;
} // namespace nlohmann
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_

1111
vendor/DPP/include/dpp/message.h vendored Normal file

File diff suppressed because it is too large Load Diff

26137
vendor/DPP/include/dpp/nlohmann/json.hpp vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,78 @@
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
#include <cstdint> // int64_t, uint64_t
#include <map> // map
#include <memory> // allocator
#include <string> // string
#include <vector> // vector
/*!
@brief namespace for Niels Lohmann
@see https://github.com/nlohmann
@since version 1.0.0
*/
namespace nlohmann
{
/*!
@brief default JSONSerializer template argument
This serializer ignores the template arguments and uses ADL
([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
for serialization.
*/
template<typename T = void, typename SFINAE = void>
struct adl_serializer;
template<template<typename U, typename V, typename... Args> class ObjectType =
std::map,
template<typename U, typename... Args> class ArrayType = std::vector,
class StringType = std::string, class BooleanType = bool,
class NumberIntegerType = std::int64_t,
class NumberUnsignedType = std::uint64_t,
class NumberFloatType = double,
template<typename U> class AllocatorType = std::allocator,
template<typename T, typename SFINAE = void> class JSONSerializer =
adl_serializer,
class BinaryType = std::vector<std::uint8_t>>
class basic_json;
/*!
@brief JSON Pointer
A JSON pointer defines a string syntax for identifying a specific value
within a JSON document. It can be used with functions `at` and
`operator[]`. Furthermore, JSON pointers are the base for JSON patches.
@sa [RFC 6901](https://tools.ietf.org/html/rfc6901)
@since version 2.0.0
*/
template<typename BasicJsonType>
class json_pointer;
/*!
@brief default JSON class
This type is the default specialization of the @ref basic_json class which
uses the standard template types.
@since version 1.0.0
*/
using json = basic_json<>;
template<class Key, class T, class IgnoredLess, class Allocator>
struct ordered_map;
/*!
@brief ordered JSON class
This type preserves the insertion order of object keys.
@since version 3.9.0
*/
using ordered_json = basic_json<nlohmann::ordered_map>;
} // namespace nlohmann
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_

252
vendor/DPP/include/dpp/presence.h vendored Normal file
View File

@ -0,0 +1,252 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <dpp/discord.h>
#include <dpp/json_fwd.hpp>
namespace dpp {
/**
* @brief Presence flags bitmask
*/
enum presence_flags {
/// Desktop: Online
p_desktop_online = 0b00000001,
/// Desktop: DND
p_desktop_dnd = 0b00000010,
/// Desktop: Idle
p_desktop_idle = 0b00000011,
/// Web: Online
p_web_online = 0b00000100,
/// Web: DND
p_web_dnd = 0b00001000,
/// Web: Idle
p_web_idle = 0b00001100,
/// Mobile: Online
p_mobile_online = 0b00010000,
/// Mobile: DND
p_mobile_dnd = 0b00100000,
/// Mobile: Idle
p_mobile_idle = 0b00110000,
/// General: Online
p_status_online = 0b01000000,
/// General: DND
p_status_dnd = 0b10000000,
/// General: Idle
p_status_idle = 0b11000000
};
/**
* @brief Online presence status values
*/
enum presence_status : uint8_t {
/// Offline
ps_offline = 0,
/// Online
ps_online = 1,
/// DND
ps_dnd = 2,
/// Idle
ps_idle = 3
};
/**
* @brief Bit shift for desktop status
*/
#define PF_SHIFT_DESKTOP 0
/** Bit shift for web status */
#define PF_SHIFT_WEB 2
/** Bit shift for mobile status */
#define PF_SHIFT_MOBILE 4
/** Bit shift for main status */
#define PF_SHIFT_MAIN 6
/** Bit mask for status */
#define PF_STATUS_MASK 0b00000011
/** Bit mask for clearing desktop status */
#define PF_CLEAR_DESKTOP 0b11111100
/** Bit mask for clearing web status */
#define PF_CLEAR_WEB 0b11110011
/** Bit mask for clearing mobile status */
#define PF_CLEAR_MOBILE 0b11001111
/** Bit mask for clearing main status */
#define PF_CLEAR_STATUS 0b00111111
/**
* @brief Game types
*/
enum activity_type : uint8_t {
/// "Playing ..."
at_game = 0,
/// "Streaming ..."
at_streaming = 1,
/// "Listening to..."
at_listening = 2,
/// "Watching..."
at_custom = 3,
/// "Competing in..."
at_competing = 4
};
/**
* @brief Activity types for rich presence
*/
enum activity_flags {
/// In an instance
af_instance = 0b00000001,
/// Joining
af_join = 0b00000010,
/// Spectating
af_spectate = 0b00000100,
/// Sending join request
af_join_request = 0b00001000,
/// Synchronising
af_sync = 0b00010000,
/// Playing
af_play = 0b00100000
};
/**
* @brief An activity is a representation of what a user is doing. It might be a game, or a website, or a movie. Whatever.
*/
class CoreExport activity {
public:
/** Name of ativity
* e.g. "Fortnite"
*/
std::string name;
/** State of activity.
* e.g. "Waiting in lobby"
*/
std::string state;
/** URL.
* Only applicable for certain sites such a YouTube
* Alias: details
*/
std::string url;
/** Activity type
*/
activity_type type;
/** Time activity was created
*/
time_t created_at;
/** Start time. e.g. when game was started
*/
time_t start;
/** End time, e.g. for songs on spotify
*/
time_t end;
/** Creating application (e.g. a linked account on the user's client)
*/
snowflake application_id;
/** Flags bitmask from activity_flags
*/
uint8_t flags;
activity() = default;
/**
* @brief Construct a new activity
*
* @param typ
* @param nam
* @param stat
* @param url_
*/
activity(const activity_type typ, const std::string& nam, const std::string& stat, const std::string& url_);
};
/**
* @brief Represents user presence, e.g. what game they are playing and if they are online
*/
class CoreExport presence {
public:
/** The user the presence applies to */
snowflake user_id;
/** Guild ID. Apparently, Discord supports this internally but the client doesnt... */
snowflake guild_id;
/** Flags bitmask containing presence_flags */
uint8_t flags;
/** List of activities */
std::vector<activity> activities;
/** Constructor */
presence();
/**
* @brief Construct a new presence object with some parameters for sending to a websocket
*
* @param status
* @param type
* @param activity_description
*/
presence(presence_status status, activity_type type, const std::string& activity_description);
/**
* @brief Construct a new presence object with some parameters for sending to a websocket
*
* @param status
* @param a Activity itself
*/
presence(presence_status status, activity a);
/** Destructor */
~presence();
/** Fill this object from json.
* @param j JSON object to fill from
* @return A reference to self
*/
presence& fill_from_json(nlohmann::json* j);
/** Build JSON from this object.
* @return The JSON text of the presence
*/
std::string build_json() const;
/** The users status on desktop
* @return The user's status on desktop
*/
presence_status desktop_status() const;
/** The user's status on web
* @return The user's status on web
*/
presence_status web_status() const;
/** The user's status on mobile
* @return The user's status on mobile
*/
presence_status mobile_status() const;
/** The user's status as shown to other users
* @return The user's status as shown to other users
*/
presence_status status() const;
};
/** A container of presences */
typedef std::unordered_map<std::string, presence> presence_map;
};

57
vendor/DPP/include/dpp/prune.h vendored Normal file
View File

@ -0,0 +1,57 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <dpp/discord.h>
#include <dpp/json_fwd.hpp>
namespace dpp {
/**
* @brief Defines a request to count prunable users, or start a prune operation
*/
struct CoreExport prune {
/** Number of days to include in the prune
*/
uint32_t days = 0;
/** Roles to include in the prune (empty to include everyone)
*/
std::vector<snowflake> include_roles;
/** True if the count of pruneable users should be returned
* (discord recommend not using this on big guilds)
*/
bool compute_prune_count;
/** Fill this object from json.
* @param j JSON object to fill from
* @return A reference to self
*/
prune& fill_from_json(nlohmann::json* j);
/** Build JSON from this object.
* @param with_prune_count True if the prune count boolean is to be set in the built JSON
* @return The JSON text of the prune object
*/
std::string build_json(bool with_prune_count) const;
};
};

270
vendor/DPP/include/dpp/queues.h vendored Normal file
View File

@ -0,0 +1,270 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <unordered_map>
#include <string>
#include <queue>
#include <map>
#include <thread>
#include <mutex>
#include <vector>
#include <functional>
namespace dpp {
/** Encodes a url parameter similar to php urlencode() */
std::string url_encode(const std::string &value);
/** Error values. Don't change the order or add extra values here,
* as they map onto the error values of cpp-httplib
*/
enum http_error {
/// Request successful
h_success = 0,
/// Status unknown
h_unknown,
/// Connect failed
h_connection,
/// Invalid local ip address
h_bind_ip_address,
/// Read error
h_read,
/// Write error
h_write,
/// Too many 30x redirects
h_exceed_redirect_count,
/// Request cancelled
h_canceled,
/// SSL connection error
h_ssl_connection,
/// SSL cert loading error
h_ssl_loading_certs,
/// SSL server verification error
h_ssl_server_verification,
/// Unsupported multipart boundary characters
h_unsupported_multipart_boundary_chars,
/// Compression error
h_compression,
};
/**
* @brief The result of any HTTP request. Contains the headers, vital
* rate limit figures, and returned request body.
*/
struct CoreExport http_request_completion_t {
/** HTTP headers of response */
std::map<std::string, std::string> headers;
/** HTTP status, e.g. 200 = OK, 404 = Not found, 429 = Rate limited */
uint16_t status = 0;
/** Error status (e.g. if the request could not connect at all) */
http_error error = h_success;
/** Ratelimit bucket */
std::string ratelimit_bucket;
/** Ratelimit limit of requests */
uint64_t ratelimit_limit = 0;
/** Ratelimit remaining requests */
uint64_t ratelimit_remaining = 0;
/** Ratelimit reset after (seconds) */
uint64_t ratelimit_reset_after = 0;
/** Ratelimit retry after (seconds) */
uint64_t ratelimit_retry_after = 0;
/** True if this request has caused us to be globally rate limited */
bool ratelimit_global = false;
/** Reply body */
std::string body;
};
/**
* @brief Results of HTTP requests are called back to these std::function types.
* @note Returned http_completion_events are called ASYNCRONOUSLY in your
* code which means they execute in a separate thread. The completion events
* arrive in order.
*/
typedef std::function<void(const http_request_completion_t&)> http_completion_event;
/** Various types of http method supported by the Discord API
*/
enum http_method {
/// GET
m_get,
/// POST
m_post,
/// PUT
m_put,
/// PATCH
m_patch,
/// DELETE
m_delete
};
/**
* @brief A HTTP request.
*
* You should instantiate one of these objects via its constructor,
* and pass a pointer to it into an instance of request_queue. Although you can
* directly call the Run() method of the object and it will make a HTTP call, be
* aware that if you do this, it will be a **BLOCKING call** (not asynchronous) and
* will not respect rate limits, as both of these functions are managed by the
* request_queue class.
*/
class CoreExport http_request {
/** Completion callback */
http_completion_event complete_handler;
/** True if request has been made */
bool completed;
public:
/** Endpoint name e.g. /api/users */
std::string endpoint;
/** Major and minor parameters */
std::string parameters;
/** Postdata for POST and PUT */
std::string postdata;
/** HTTP method for request */
http_method method;
/** Upload file name (server side) */
std::string file_name;
/** Upload file contents (binary) */
std::string file_content;
/** Constructor. When constructing one of these objects it should be passed to request_queue::post_request().
* @param _endpoint The API endpoint, e.g. /api/guilds
* @param _parameters Major and minor parameters for the endpoint e.g. a user id or guild id
* @param completion completion event to call when done
* @param _postdata Data to send in POST and PUT requests
* @param method The HTTP method to use from dpp::http_method
* @param filename The filename (server side) of any uploaded file
* @param filecontent The binary content of any uploaded file for the request
*/
http_request(const std::string &_endpoint, const std::string &_parameters, http_completion_event completion, const std::string &_postdata = "", http_method method = m_get, const std::string &filename = "", const std::string &filecontent = "");
/** Destructor */
~http_request();
/** Call the completion callback, if the request is complete.
* @param c callback to call
*/
void complete(const http_request_completion_t &c);
/** Execute the HTTP request and mark the request complete.
* @param owner creating cluster
*/
http_request_completion_t Run(const class cluster* owner);
/** Returns true if the request is complete */
bool is_completed();
};
/** A rate limit bucket. The library builds one of these for
* each endpoint.
*/
struct CoreExport bucket_t {
/** Request limit */
uint64_t limit;
/** Requests remaining */
uint64_t remaining;
/** Ratelimit of this bucket resets after this many seconds */
uint64_t reset_after;
/** Ratelimit of this bucket can be retried after this many seconds */
uint64_t retry_after;
/** Timestamp this buckets counters were updated */
time_t timestamp;
};
/**
* @brief The request_queue class manages rate limits and marshalls HTTP requests that have
* been built as http_request objects.
*
* It ensures asynchronous delivery of events and queueing of requests.
*
* It will spawn two threads, one to make outbound HTTP requests and push the returned
* results into a queue, and the second to call the callback methods with these results.
* They are separated so that if the user decides to take a long time processing a reply
* in their callback it won't affect when other requests are sent, and if a HTTP request
* takes a long time due to latency, it won't hold up user processing.
*
* There is usually only one request_queue object in each dpp::cluster, which is used
* internally for the various REST methods such as sending messages.
*/
class CoreExport request_queue {
private:
/** The cluster that owns this request_queue */
const class cluster* creator;
/** Mutexes for thread safety */
std::mutex in_mutex;
std::mutex out_mutex;
/** In and out threads */
std::thread* in_thread;
std::thread* out_thread;
/** Ratelimit bucket counters */
std::map<std::string, bucket_t> buckets;
/** Queue of requests to be made */
std::map<std::string, std::vector<http_request*>> requests_in;
/** Completed requests queue */
std::queue<std::pair<http_request_completion_t*, http_request*>> responses_out;
/** Completed requests to delete */
std::multimap<time_t, std::pair<http_request_completion_t*, http_request*>> responses_to_delete;
/** Set to true if the threads should terminate */
bool terminating;
/** True if globally rate limited - makes the entire request thread wait */
bool globally_ratelimited;
/** How many seconds we are globally rate limited for, if globally_ratelimited is true */
uint64_t globally_limited_for;
/** Ports for notifications of request completion.
* Why are we using sockets here instead of std::condition_variable? Because
* in the future we will want to notify across clusters of completion and state,
* and we can't do this across processes with condition variables.
*/
int in_queue_port;
int out_queue_port;
int in_queue_listen_sock;
int in_queue_connect_sock;
int out_queue_listen_sock;
int out_queue_connect_sock;
/** Thread loop functions */
void in_loop();
void out_loop();
/** Notify request thread of a new request */
void emit_in_queue_signal();
/** Notify completion thread of new completed request */
void emit_out_queue_signal();
public:
/** Constructor
* @param owner The creating cluster
*/
request_queue(const class cluster* owner);
/** Destructor */
~request_queue();
/** Put a http_request into the request queue. You should ALWAYS "new" an object
* to pass to here -- don't submit an object that's on the stack!
* @param req request to add
*/
void post_request(http_request *req);
};
};

202
vendor/DPP/include/dpp/role.h vendored Normal file
View File

@ -0,0 +1,202 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <dpp/json_fwd.hpp>
namespace dpp {
/** Various flags related to dpp::role */
enum role_flags {
r_hoist = 0b00000001, //!< Hoisted role
r_managed = 0b00000010, //!< Managed role (introduced by a bot or application)
r_mentionable = 0b00000100, //!< Mentionable with an @ping
r_premium_subscriber = 0b00001000, //!< This is set for the role given to nitro
};
/**
* @brief Represents the various discord permissions
*/
enum role_permissions : uint64_t {
p_create_instant_invite = 0x00000001, //!< allows creationboosters of instant invites
p_kick_members = 0x00000002, //!< allows kicking members
p_ban_members = 0x00000004, //!< allows banning members
p_administrator = 0x00000008, //!< allows all permissions and bypasses channel permission overwrites
p_manage_channels = 0x00000010, //!< allows management and editing of channels
p_manage_guild = 0x00000020, //!< allows management and editing of the guild
p_add_reactions = 0x00000040, //!< allows for the addition of reactions to messages
p_view_audit_log = 0x00000080, //!< allows for viewing of audit logs
p_priority_speaker = 0x00000100, //!< allows for using priority speaker in a voice channel
p_stream = 0x00000200, //!< allows the user to go live
p_view_channel = 0x00000400, //!< allows guild members to view a channel, which includes reading messages in text channels
p_send_messages = 0x00000800, //!< allows for sending messages in a channel
p_send_tts_messages = 0x00001000, //!< allows for sending of /tts messages
p_manage_messages = 0x00002000, //!< allows for deletion of other users messages
p_embed_links = 0x00004000, //!< links sent by users with this permission will be auto-embedded
p_attach_files = 0x0000008000, //!< allows for uploading images and files
p_read_message_history = 0x0000010000, //!< allows for reading of message history
p_mention_everyone = 0x0000020000, //!< allows for using the @everyone and the @here tag to notify users in a channel
p_use_external_emojis = 0x0000040000, //!< allows the usage of custom emojis from other servers
p_view_guild_insights = 0x0000080000, //!< allows for viewing guild insights
p_connect = 0x0000100000, //!< allows for joining of a voice channel
p_speak = 0x0000200000, //!< allows for speaking in a voice channel
p_mute_members = 0x0000400000, //!< allows for muting members in a voice channel
p_deafen_members = 0x0000800000, //!< allows for deafening of members in a voice channel
p_move_members = 0x0001000000, //!< allows for moving of members between voice channels
p_use_vad = 0x0002000000, //!< allows for using voice-activity-detection in a voice channel
p_change_nickname = 0x0004000000, //!< allows for modification of own nickname
p_manage_nicknames = 0x0008000000, //!< allows for modification of other users nicknames
p_manage_roles = 0x0010000000, //!< allows management and editing of roles
p_manage_webhooks = 0x0020000000, //!< allows management and editing of webhooks
p_manage_emojis = 0x0040000000, //!< allows management and editing of emojis
p_use_slash_commands = 0x0080000000, //!< allows members to use slash commands
p_request_to_speak = 0x0100000000, //!< allows for requesting to speak in stage channels. (Discord: This permission is under active development and may be changed or removed.)
p_manage_threads = 0x0400000000, //!< allows for deleting and archiving threads, and viewing all private threads
p_use_public_threads = 0x0800000000, //!< allows for creating and participating in thread
p_use_private_threads = 0x1000000000, //!< allows for creating and participating in private thread
};
/**
* @brief Represents a role within a dpp::guild
*/
class CoreExport role : public managed {
public:
/** Role name */
std::string name;
/** Guild id */
snowflake guild_id;
/** Role colour */
uint32_t colour;
/** Role position */
uint8_t position;
/** Role permissions bitmask values from dpp::role_permissions */
uint64_t permissions;
/** Role flags from dpp::role_flags */
uint8_t flags;
/** Integration id if any (e.g. role is a bot's role created when it was invited) */
snowflake integration_id;
/** Bot id if any (e.g. role is a bot's role created when it was invited) */
snowflake bot_id;
/** Default constructor */
role();
/** Default destructor */
virtual ~role();
/** Fill this role from json.
* @param guild_id the guild id to place in the json
* @param j The json data
* @return A reference to self
*/
role& fill_from_json(snowflake guild_id, nlohmann::json* j);
/** Build a json string from this object.
* @param with_id true if the ID is to be included in the json text
* @return The json of the role
*/
std::string build_json(bool with_id = false) const;
/** True if the role is hoisted */
bool is_hoisted() const;
/** True if the role is mentionable */
bool is_mentionable() const;
/** True if the role is managed (belongs to a bot or application) */
bool is_managed() const;
/** True if has create instant invite permission */
bool has_create_instant_invite() const;
/** True if has the kick members permission */
bool has_kick_members() const;
/** True if has the ban members permission */
bool has_ban_members() const;
/** True if has the administrator permission */
bool has_administrator() const;
/** True if has the manage channels permission */
bool has_manage_channels() const;
/** True if has the manage guild permission */
bool has_manage_guild() const;
/** True if has the add reactions permission */
bool has_add_reactions() const;
/** True if has the view audit log permission */
bool has_view_audit_log() const;
/** True if has the priority speaker permission */
bool has_priority_speaker() const;
/** True if has the stream permission */
bool has_stream() const;
/** True if has the view channel permission */
bool has_view_channel() const;
/** True if has the send messages permission */
bool has_send_messages() const;
/** True if has the send TTS messages permission */
bool has_send_tts_messages() const;
/** True if has the manage messages permission */
bool has_manage_messages() const;
/** True if has the embed links permission */
bool has_embed_links() const;
/** True if has the attach files permission */
bool has_attach_files() const;
/** True if has the read message history permission */
bool has_read_message_history() const;
/** True if has the mention \@everyone and \@here permission */
bool has_mention_everyone() const;
/** True if has the use external emojis permission */
bool has_use_external_emojis() const;
/** True if has the view guild insights permission */
bool has_view_guild_insights() const;
/** True if has the connect voice permission */
bool has_connect() const;
/** True if has the speak permission */
bool has_speak() const;
/** True if has the mute members permission */
bool has_mute_members() const;
/** True if has the deafen members permission */
bool has_deafen_members() const;
/** True if has the move members permission */
bool has_move_members() const;
/** True if has use voice activity detection permission */
bool has_use_vad() const;
/** True if has the change nickname permission */
bool has_change_nickname() const;
/** True if has the manage nicknames permission */
bool has_manage_nicknames() const;
/** True if has the manage roles permission */
bool has_manage_roles() const;
/** True if has the manage webhooks permission */
bool has_manage_webhooks() const;
/** True if has the manage emojis permission */
bool has_manage_emojis() const;
/** True if has the use slash commands permission*/
bool has_use_slash_commands() const;
/** True if has the request to speak permission*/
bool has_request_to_speak() const;
/** True if has the manage threads permission*/
bool has_manage_threads() const;
/** True if has the use public threads permission*/
bool has_use_public_threads() const;
/** True if has the use private threads permission*/
bool has_use_private_threads() const;
};
/** A group of roles */
typedef std::unordered_map<snowflake, role> role_map;
};

555
vendor/DPP/include/dpp/slashcommand.h vendored Normal file
View File

@ -0,0 +1,555 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <variant>
#include <dpp/discord.h>
#include <dpp/json_fwd.hpp>
#include <dpp/message.h>
namespace dpp {
/**
* @brief Represents command option types.
* These are the possible parameter value types.
*/
enum command_option_type : uint8_t {
/** A sub-command */
co_sub_command = 1,
/** A sub-command group */
co_sub_command_group = 2,
/** A string value */
co_string = 3,
/** An integer value */
co_integer = 4,
/** A boolean value */
co_boolean = 5,
/** A user snowflake id */
co_user = 6,
/** A channel snowflake id */
co_channel = 7,
/** A role snowflake id */
co_role = 8
};
/**
* @brief This type is a variant that can hold any of the potential
* native data types represented by the enum above.
* It is used in interactions.
*/
typedef std::variant<std::string, int32_t, bool, snowflake> command_value;
/**
* @brief This struct represents choices in a multiple choice option
* for a command parameter.
* It has both a string name, and a value parameter which is a variant,
* meaning it can hold different potential types (see dpp::command_value)
* that you can retrieve with std::get().
*/
struct CoreExport command_option_choice {
std::string name; //!< Option name (1-32 chars)
command_value value; //!< Option value
/**
* @brief Construct a new command option choice object
*/
command_option_choice() = default;
/**
* @brief Construct a new command option choice object
*
* @param n name to initialise with
* @param v value to initialise with
*/
command_option_choice(const std::string &n, command_value v);
};
/**
* @brief helper function to serialize a command_option_choice to json
*
* @see https://github.com/nlohmann/json#arbitrary-types-conversions
*
* @param j output json object
* @param choice command_option_choice to be serialized
*/
void to_json(nlohmann::json& j, const command_option_choice& choice);
/**
* @brief Each command option is a command line parameter.
* It can have a type (see dpp::command_option_type), a name,
* a description, can be required or optional, and can have
* zero or more choices (for multiple choice), plus options.
* Adding options acts like sub-commands and can contain more
* options.
*/
struct CoreExport command_option {
command_option_type type; //!< Option type (what type of value is accepted)
std::string name; //!< Option name (1-32 chars)
std::string description; //!< Option description (1-100 chars)
bool required; //!< True if this is a mandatory parameter
std::vector<command_option_choice> choices; //!< List of choices for multiple choice command
std::vector<command_option> options; //!< Sub-commands
/**
* @brief Construct a new command option object
*/
command_option() = default;
/**
* @brief Construct a new command option object
*
* @param t Option type
* @param name Option name
* @param description Option description
* @param required True if this is a mandatory parameter
*/
command_option(command_option_type t, const std::string &name, const std::string &description, bool required = false);
/**
* @brief Add a multiple choice option
*
* @param o choice to add
* @return command_option& returns a reference to self for chaining of calls
*/
command_option& add_choice(const command_option_choice &o);
/**
* @brief Add a sub-command option
*
* @param o Sub-command option to add
* @return command_option& return a reference to self for chaining of calls
*/
command_option& add_option(const command_option &o);
};
/**
* @brief helper function to serialize a command_option to json
*
* @see https://github.com/nlohmann/json#arbitrary-types-conversions
*
* @param j output json object
* @param opt command_option to be serialized
*/
void to_json(nlohmann::json& j, const command_option& opt);
/**
* @brief Response types when responding to an interaction within on_interaction_create.
* Do not use ir_acknowledge or ir::channel_message, as these are deprecated in the
* Discord API spec. They are listed in this enum for completeness.
*/
enum interaction_response_type {
ir_pong = 1, //!< ACK a Ping
ir_acknowledge = 2, //!< DEPRECATED ACK a command without sending a message, eating the user's input
ir_channel_message = 3, //!< DEPRECATED respond with a message, eating the user's input
ir_channel_message_with_source = 4, //!< respond to an interaction with a message
ir_deferred_channel_message_with_source = 5, //!< ACK an interaction and edit a response later, the user sees a loading state
ir_deferred_update_message = 6, //!< for components, ACK an interaction and edit the original message later; the user does not see a loading state
ir_update_message = 7 //!< for components, edit the message the component was attached to
};
/**
* @brief A response to an interaction, used to reply to a command and initiate
* a message, which can be hidden from others (ephemeral) or visible to all.
*
* The dpp::interaction_response object wraps a dpp::message object. To set the
* message as 'ephemeral' (e.g. only the command issuer can see it) you should
* add the dpp::m_ephemeral flag to the dpp::message::flags field. e.g.:
*
* `mymessage.flags |= dpp::m_ephemeral;`
*/
struct CoreExport interaction_response {
/**
* @brief Response type from dpp::interaction_response_type.
* Should be one of ir_pong, ir_channel_message_with_source,
* or ir_deferred_channel_message_with_source.
*/
interaction_response_type type;
/**
* @brief A message object. This pointer is always valid
* while the containing interaction_response exists.
*/
struct message* msg;
/**
* @brief Construct a new interaction response object
*/
interaction_response();
/**
* @brief Construct a new interaction response object
*
* @param t Type of reply
* @param m Message to reply with
*/
interaction_response(interaction_response_type t, const struct message& m);
/**
* @brief Fill object properties from JSON
*
* @param j JSON to fill from
* @return interaction_response& Reference to self
*/
interaction_response& fill_from_json(nlohmann::json* j);
/**
* @brief Build a json string for this object
*
* @return std::string JSON string
*/
std::string build_json() const;
/**
* @brief Destroy the interaction response object
*/
~interaction_response();
};
/**
* @brief Resolved snowflake ids to usernames.
* TODO: Needs implementation. Not needed something that
* functions as we have cache.
*/
struct CoreExport command_resolved {
};
/**
* @brief Values in the command interaction.
* These are the values specified by the user when actually issuing
* the command on a channel or in DM.
*/
struct CoreExport command_data_option {
std::string name; //!< the name of the parameter
command_option_type type; //!< value of ApplicationCommandOptionType
command_value value; //!< Optional: the value of the pair
std::vector<command_data_option> options; //!< Optional: present if this option is a group or subcommand
dpp::snowflake target_id; //!< Non-zero target ID for context menu actions
};
/**
* @brief helper function to deserialize a command_data_option from json
*
* @see https://github.com/nlohmann/json#arbitrary-types-conversions
*
* @param j output json object
* @param cdo command_data_option to be deserialized
*/
void from_json(const nlohmann::json& j, command_data_option& cdo);
/** Types of interaction in the dpp::interaction class
*/
enum interaction_type {
it_ping = 1, //!< ping
it_application_command = 2, //!< application command (slash command)
it_component_button = 3 //!< button click (component interaction)
};
/**
* @brief Details of a command within an interaction.
* This subobject represents the application command associated
* with the interaction.
*/
struct CoreExport command_interaction {
snowflake id; //!< the ID of the invoked command
std::string name; //!< the name of the invoked command
command_resolved resolved; //!< Optional: converted users + roles + channels
std::vector<command_data_option> options; //!< Optional: the params + values from the user
};
/**
* @brief helper function to deserialize a command_interaction from json
*
* @see https://github.com/nlohmann/json#arbitrary-types-conversions
*
* @param j output json object
* @param ci command_interaction to be deserialized
*/
void from_json(const nlohmann::json& j, command_interaction& ci);
enum component_type_t {
cotype_button = 2,
cotype_select = 3
};
/**
* @brief A button click for a button component
*/
struct CoreExport component_interaction {
uint8_t component_type;
std::string custom_id;
std::vector<std::string> values;
};
/**
* @brief helper function to deserialize a component_interaction from json
*
* @see https://github.com/nlohmann/json#arbitrary-types-conversions
*
* @param j output json object
* @param bi button_interaction to be deserialized
*/
void from_json(const nlohmann::json& j, component_interaction& bi);
/**
* @brief An interaction represents a user running a command and arrives
* via the dpp::cluster::on_interaction_create event.
*/
class CoreExport interaction : public managed {
public:
snowflake application_id; //!< id of the application this interaction is for
uint8_t type; //!< the type of interaction
std::variant<command_interaction, component_interaction> data; //!< Optional: the command data payload
snowflake guild_id; //!< Optional: the guild it was sent from
snowflake channel_id; //!< Optional: the channel it was sent from
snowflake message_id; //!< Originating message id
guild_member member; //!< Optional: guild member data for the invoking user, including permissions
user usr; //!< Optional: user object for the invoking user, if invoked in a DM
std::string token; //!< a continuation token for responding to the interaction
uint8_t version; //!< read-only property, always 1
/**
* @brief Fill object properties from JSON
*
* @param j JSON to fill from
* @return interaction& Reference to self
*/
interaction& fill_from_json(nlohmann::json* j);
/**
* @brief Build a json string for this object
*
* @param with_id True if to include the ID in the JSON
* @return std::string JSON string
*/
std::string build_json(bool with_id = false) const;
};
/**
* @brief helper function to deserialize an interaction from json
*
* @see https://github.com/nlohmann/json#arbitrary-types-conversions
*
* @param j output json object
* @param i interaction to be deserialized
*/
void from_json(const nlohmann::json& j, interaction& i);
/**
* @brief type of permission in the dpp::command_permission class
*/
enum command_permission_type {
cpt_role = 1,
cpt_user = 2,
};
/**
* @brief Application command permissions allow you to enable or
* disable commands for specific users or roles within a guild
*/
class CoreExport command_permission {
public:
snowflake id; //!< the ID of the role or uses
command_permission_type type; //!< the type of permission
bool permission; //!< true to allow, false, to disallow
};
/**
* @brief helper function to serialize a command_permission to json
*
* @see https://github.com/nlohmann/json#arbitrary-types-conversions
*
* @param j output json object
* @param cp command_permission to be serialized
*/
void to_json(nlohmann::json& j, const command_permission& cp);
/**
* @brief Returned when fetching the permissions for a command in a guild.
*/
class CoreExport guild_command_permissions {
public:
snowflake id; //!< the id of the command
snowflake application_id; //!< the id of the application the command belongs to
snowflake guild_id; //!< the id of the guild
std::vector<command_permission> permissions; //!< the permissions for the command in the guild
};
/**
* @brief helper function to serialize a guild_command_permissions to json
*
* @see https://github.com/nlohmann/json#arbitrary-types-conversions
*
* @param j output json object
* @param gcp guild_command_permissions to be serialized
*/
void to_json(nlohmann::json& j, const guild_command_permissions& gcp);
enum slashcommand_contextmenu_type {
ctxm_none = 0,
ctxm_chat_input = 1, //!< DEFAULT, these are the slash commands you're used to
ctxm_user = 2, //!< Add command to user context menu
ctxm_message = 3 //!< Add command to message context menu
};
/**
* @brief Represents an application command, created by your bot
* either globally, or on a guild.
*/
class CoreExport slashcommand : public managed {
public:
/**
* @brief Application id (usually matches your bots id)
*/
snowflake application_id;
/**
* @brief Context menu type, defaults to none
*
*/
slashcommand_contextmenu_type type;
/**
* @brief Command name (1-32 chars)
*/
std::string name;
/**
* @brief Command description (1-100 chars)
*/
std::string description;
/**
* @brief Command options (parameters)
*/
std::vector<command_option> options;
/**
* @brief whether the command is enabled by default when the app is added to a guild
*/
bool default_permission;
/**
* @brief command permissions
*/
std::vector<command_permission> permissions;
/**
* @brief Construct a new slashcommand object
*/
slashcommand();
/**
* @brief Destroy the slashcommand object
*/
~slashcommand();
/**
* @brief Add an option (parameter)
*
* @param o option (parameter) to add
* @return slashcommand& reference to self for chaining of calls
*/
slashcommand& add_option(const command_option &o);
/**
* @brief Set the type of the slash command (only for context menu entries)
*
* @param _type Type of context menu entry this command represents
* @return slashcommand& reference to self for chaining of calls
*/
slashcommand& set_type(slashcommand_contextmenu_type _type);
/**
* @brief Set the name of the command
*
* @param n name of command
* @return slashcommand& reference to self for chaining of calls
*/
slashcommand& set_name(const std::string &n);
/**
* @brief Set the description of the command
*
* @param d description
* @return slashcommand& reference to self for chaining of calls
*/
slashcommand& set_description(const std::string &d);
/**
* @brief Set the application id of the command
*
* @param i application id
* @return slashcommand& reference to self for chaining of calls
*/
slashcommand& set_application_id(snowflake i);
/**
* @brief Adds a permission to the command
*
* @param p permission to add
* @return slashcommand& reference to self for chaining of calls
*/
slashcommand& add_permission(const command_permission& p);
/**
* @brief Disable default permissions, command will be unusable unless
* permissions are overriden with add_permission and
* dpp::guild_command_edit_permissions
*
* @return slashcommand& reference to self for chaining of calls
*/
slashcommand& disable_default_permissions();
/**
* @brief Fill object properties from JSON
*
* @param j JSON to fill from
* @return slashcommand& Reference to self
*/
slashcommand& fill_from_json(nlohmann::json* j);
/**
* @brief Build a json string for this object
*
* @param with_id True if to include the ID in the JSON
* @return std::string JSON string
*/
std::string build_json(bool with_id = false) const;
};
/**
* @brief helper function to serialize a slashcommand to json
*
* @see https://github.com/nlohmann/json#arbitrary-types-conversions
*
* @param j output json object
* @param cmd slashcommand to be serialized
*/
void to_json(nlohmann::json& j, const slashcommand& cmd);
/**
* @brief A group of application slash commands
*/
typedef std::unordered_map<snowflake, slashcommand> slashcommand_map;
};

165
vendor/DPP/include/dpp/sslclient.h vendored Normal file
View File

@ -0,0 +1,165 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <string>
#include <functional>
#include <dpp/discord.h>
namespace dpp {
/** This is an opaque class containing openssl library specific structures.
* We define it this way so that the public facing D++ library doesnt require
* the openssl headers be available to build against it.
*/
class opensslcontext;
/**
* @brief Implements a simple non-blocking SSL stream client.
*
* Note that although the design is non-blocking the Run() method will
* execute in an infinite loop until the socket disconnects. This is intended
* to be run within a std::thread.
*/
class CoreExport ssl_client
{
protected:
/** Input buffer received from openssl */
std::string buffer;
/** Output buffer for sending to openssl */
std::string obuffer;
/** True if in nonblocking mode. The socket switches to nonblocking mode
* once ReadLoop is called.
*/
bool nonblocking;
/** Raw file descriptor of connection */
SOCKET sfd;
/** Openssl opaque contexts */
opensslcontext* ssl;
/** SSL cipher in use */
std::string cipher;
/** For timers */
time_t last_tick;
/** Hostname connected to */
std::string hostname;
/** Port connected to */
std::string port;
/** Bytes out */
uint64_t bytes_out;
/** Bytes in */
uint64_t bytes_in;
/** Called every second */
virtual void one_second_timer();
/** Start connection */
virtual void Connect();
public:
/** Get total bytes sent */
uint64_t get_bytes_out();
/** Get total bytes received */
uint64_t get_bytes_in();
/** Get SSL cipher name */
std::string get_cipher();
/**
* @brief Attaching an additional file descriptor to this function will send notifications when there is data to read.
*
* NOTE: Only hook this if you NEED it as it can increase CPU usage of the thread!
* Returning -1 means that you don't want to be notified.
*/
std::function<int()> custom_readable_fd;
/**
* @brief Attaching an additional file descriptor to this function will send notifications when you are able to write
* to the socket.
*
* NOTE: Only hook this if you NEED it as it can increase CPU usage of the thread! You should toggle this
* to -1 when you do not have anything to write otherwise it'll keep triggering repeatedly (it is level triggered).
*/
std::function<int()> custom_writeable_fd;
/**
* @brief This event will be called when you can read from the custom fd
*/
std::function<void()> custom_readable_ready;
/**
* @brief This event will be called when you can write to a custom fd
*/
std::function<void()> custom_writeable_ready;
/**
* @brief Connect to a specified host and port. Throws std::runtime_error on fatal error.
* @param _hostname The hostname to connect to
* @param _port the Port number to connect to
*/
ssl_client(const std::string &_hostname, const std::string &_port = "443");
/**
* @brief Nonblocking I/O loop
*/
void read_loop();
/**
* @brief Destroy the ssl_client object
*/
virtual ~ssl_client();
/**
* @brief Handle input from the input buffer.
* @param buffer the buffer content. Will be modified removing any processed front elements
*/
virtual bool handle_buffer(std::string &buffer);
/**
* @brief Write to the output buffer.
* @param data Data to be written to the buffer
*/
virtual void write(const std::string &data);
/**
* @brief Close SSL connection
*/
virtual void close();
/**
* @brief Log a message
*
* @param severity severity of log message
* @param msg Log message to send
*/
virtual void log(dpp::loglevel severity, const std::string &msg) const;
};
};

128
vendor/DPP/include/dpp/stringops.h vendored Normal file
View File

@ -0,0 +1,128 @@
/************************************************************************************
*
* D++ - A Lightweight C++ Library for Discord
*
* stringops.h taken from TriviaBot
*
* Copyright 2004 Craig Edwards <support@sporks.gg>
*
* Core based on Sporks, the Learning Discord Bot, Craig Edwards (c) 2019.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <string>
#include <iomanip>
#include <locale>
#include <algorithm>
#include <sstream>
#include <iostream>
/**
* @brief Convert a string to lowercase using tolower()
*
* @tparam T type of string
* @param s String to lowercase
* @return std::basic_string<T> lowercased string
*/
template <typename T> std::basic_string<T> lowercase(const std::basic_string<T>& s)
{
std::basic_string<T> s2 = s;
std::transform(s2.begin(), s2.end(), s2.begin(), tolower);
return std::move(s2);
}
/**
* @brief Convert a string to uppercase using toupper()
*
* @tparam T type of string
* @param s String to uppercase
* @return std::basic_string<T> uppercased string
*/
template <typename T> std::basic_string<T> uppercase(const std::basic_string<T>& s)
{
std::basic_string<T> s2 = s;
std::transform(s2.begin(), s2.end(), s2.begin(), toupper);
return std::move(s2);
}
/**
* @brief trim from end of string (right)
*
* @param s String to trim
* @return std::string trimmed string
*/
inline std::string rtrim(std::string s)
{
s.erase(s.find_last_not_of(" \t\n\r\f\v") + 1);
return s;
}
/**
* @brief trim from beginning of string (left)
*
* @param s string to trim
* @return std::string trimmed string
*/
inline std::string ltrim(std::string s)
{
s.erase(0, s.find_first_not_of(" \t\n\r\f\v"));
return s;
}
/**
* @brief Trim from both ends of string (right then left)
*
* @param s string to trim
* @return std::string trimmed string
*/
inline std::string trim(std::string s)
{
return ltrim(rtrim(s));
}
/**
* @brief Add commas to a string (or dots) based on current locale server-side
*
* @tparam T type of numeric value
* @param value Value
* @return std::string number with commas added
*/
template<class T> std::string Comma(T value)
{
std::stringstream ss;
ss.imbue(std::locale(""));
ss << std::fixed << value;
return ss.str();
}
/**
* @brief Convert any value from a string to another type using stringstream.
* The optional second parameter indicates the format of the input string,
* e.g. std::dec for decimal, std::hex for hex, std::oct for octal.
*
* @tparam T Type to convert to
* @param s String to convert from
* @param f Numeric base, e.g. `std::dec` or `std::hex`
* @return T Returned numeric value
*/
template <typename T> T from_string(const std::string &s, std::ios_base & (*f)(std::ios_base&))
{
T t;
std::istringstream iss(s);
iss >> f, iss >> t;
return t;
}

249
vendor/DPP/include/dpp/user.h vendored Normal file
View File

@ -0,0 +1,249 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <dpp/json_fwd.hpp>
namespace dpp {
/**
* @brief Various bitmask flags used to represent information about a dpp::user
*/
enum user_flags {
/// User is a bot
u_bot = 0b00000000000000000000001,
/// User is a system user (Clyde!)
u_system = 0b00000000000000000000010,
/// User has multi-factor authentication enabled
u_mfa_enabled = 0b00000000000000000000100,
/// User is verified (verified email address)
u_verified = 0b00000000000000000001000,
/// User has full nitro
u_nitro_full = 0b00000000000000000010000,
/// User has nitro classic
u_nitro_classic = 0b00000000000000000100000,
/// User is discord staff
u_discord_employee = 0b00000000000000001000000,
/// User owns a partnered server
u_partnered_owner = 0b00000000000000010000000,
/// User is a member of hypesquad events
u_hypesquad_events = 0b00000000000000100000000,
/// User has BugHunter level 1
u_bughunter_1 = 0b00000000000001000000000,
/// User is a member of House Bravery
u_house_bravery = 0b00000000000010000000000,
/// User is a member of House Brilliance
u_house_brilliance = 0b00000000000100000000000,
/// User is a member of House Balance
u_house_balanace = 0b00000000001000000000000,
/// User is an early supporter
u_early_supporter = 0b00000000010000000000000,
/// User is a team user
u_team_user = 0b00000000100000000000000,
/// User is has Bug Hunter level 2
u_bughunter_2 = 0b00000001000000000000000,
/// User is a verified bot
u_verified_bot = 0b00000010000000000000000,
/// User has the Early Verified Bot Developer badge
u_verified_bot_dev = 0b00000100000000000000000,
/// User's icon is animated
u_animated_icon = 0b00001000000000000000000,
/// User is a certified moderator
u_certified_moderator = 0b00010000000000000000000
};
/**
* @brief Represents a user on discord. May or may not be a member of a dpp::guild.
*/
class CoreExport user : public managed {
public:
/** Discord username */
std::string username;
/** Discriminator (aka tag), 4 digits usually displayed with leading zeroes */
uint16_t discriminator;
/** Avatar hash */
utility::iconhash avatar;
/** Flags built from a bitmask of values in dpp::user_flags */
uint32_t flags;
/** Reference count of how many guilds this user is in */
uint8_t refcount;
/**
* @brief Construct a new user object
*/
user();
/**
* @brief Destroy the user object
*/
virtual ~user();
/** Fill this record from json.
* @param j The json to fill this record from
* @return Reference to self
*/
user& fill_from_json(nlohmann::json* j);
/**
* @brief Get the avatar url of the user object
*
* @return std::string avatar url
*/
std::string get_avatar_url() const;
/**
* @brief User is a bot
*
* @return True if the user is a bot
*/
bool is_bot() const;
/**
* @brief User is a system user (Clyde)
*
* @return true if user is a system user
*/
bool is_system() const;
/**
* @brief User has multi-factor authentication enabled
*
* @return true if multi-factor is enabled
*/
bool is_mfa_enabled() const;
/**
* @brief Return true if user has verified account
*
* @return true if verified
*/
bool is_verified() const;
/**
* @brief Return true if user has full nitro.
* This is mutually exclusive with full nitro.
*
* @return true if user has full nitro
*/
bool has_nitro_full() const;
/**
* @brief Return true if user has nitro classic.
* This is mutually exclusive with nitro classic.
*
* @return true if user has nitro classic
*/
bool has_nitro_classic() const;
/**
* @brief Return true if user is a discord employee
*
* @return true if user is discord staff
*/
bool is_discord_employee() const;
/**
* @brief Return true if user owns a partnered server
*
* @return true if user has partnered server
*/
bool is_partnered_owner() const;
/**
* @brief Return true if user has hypesquad events
*
* @return true if has hypesquad events
*/
bool has_hypesquad_events() const;
/**
* @brief Return true if user has the bughunter level 1 badge
*
* @return true if has bughunter level 1
*/
bool is_bughunter_1() const;
/**
* @brief Return true if user is in house bravery
*
* @return true if in house bravery
*/
bool is_house_bravery() const;
/**
* @brief Return true if user is in house brilliance
*
* @return true if in house brilliance
*/
bool is_house_brilliance() const;
/**
* @brief Return true if user is in house balance
*
* @return true if in house brilliance
*/
bool is_house_balanace() const;
/**
* @brief Return true if user is an early supporter
*
* @return true if early supporter
*/
bool is_early_supporter() const;
/**
* @brief Return true if user is a team user
*
* @return true if a team user
*/
bool is_team_user() const;
/**
* @brief Return true if user has the bughunter level 2 badge
*
* @return true if has bughunter level 2
*/
bool is_bughunter_2() const;
/**
* @brief Return true if user has the verified bot badge
*
* @return true if verified bot
*/
bool is_verified_bot() const;
/**
* @brief Return true if user is an early verified bot developer
*
* @return true if verified bot developer
*/
bool is_verified_bot_dev() const;
/**
* @brief Return true if user is a certified moderator
*
* @return true if certified moderator
*/
bool is_certified_moderator() const;
/**
* @brief Return true if user has an animated icon
*
* @return true if icon is animated (gif)
*/
bool has_animated_icon() const;
};
/**
* @brief helper function to deserialize a user from json
*
* @see https://github.com/nlohmann/json#arbitrary-types-conversions
*
* @param j output json object
* @param u user to be deserialized
*/
void from_json(const nlohmann::json& j, user& u);
/** A group of users */
typedef std::unordered_map<snowflake, user> user_map;
};

31
vendor/DPP/include/dpp/version.h vendored Normal file
View File

@ -0,0 +1,31 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#if !defined(DPP_VERSION_LONG)
#define DPP_VERSION_LONG 0x00090003
#define DPP_VERSION_SHORT 090003
#define DPP_VERSION_TEXT "D++ 9.0.3 (05-Sep-2021)"
#define DPP_VERSION_MAJOR ((DPP_VERSION_LONG & 0x00ff0000) >> 16)
#define DPP_VERSION_MINOR ((DPP_VERSION_LONG & 0x0000ff00) >> 8)
#define DPP_VERSION_PATCH (DPP_VERSION_LONG & 0x000000ff)
#endif

117
vendor/DPP/include/dpp/voiceregion.h vendored Normal file
View File

@ -0,0 +1,117 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <dpp/discord.h>
#include <dpp/json_fwd.hpp>
namespace dpp {
/**
* @brief Flags related to a voice region
*/
enum voiceregion_flags {
v_optimal = 0x00000001,
v_deprecated = 0x00000010,
v_custom = 0x00000100,
v_vip = 0x00001000
};
/**
* @brief Represents a voice region on discord
*/
class CoreExport voiceregion {
public:
/**
* @brief Voice server ID
*/
std::string id;
/**
* @brief Voice server name
*/
std::string name;
/**
* @brief Flags bitmap
*/
uint8_t flags;
/**
* @brief Construct a new voiceregion object
*/
voiceregion();
/**
* @brief Destroy the voiceregion object
*/
~voiceregion();
/**
* @brief Fill object properties from JSON
*
* @param j JSON to fill from
* @return voiceregion& Reference to self
*/
voiceregion& fill_from_json(nlohmann::json* j);
/**
* @brief Build a json string for this object
*
* @return std::string JSON string
*/
std::string build_json() const;
/**
* @brief True if is the optimal voice server
*
* @return true if optimal
*/
bool is_optimal() const;
/**
* @brief True if is a deprecated voice server
*
* @return true if deprecated
*/
bool is_deprecated() const;
/**
* @brief True if is a custom voice server
*
* @return true if custom
*/
bool is_custom() const;
/**
* @brief True if is a VIP voice server
*
* @return true if VIP
*/
bool is_vip() const;
};
/**
* @brief A group of voice regions
*/
typedef std::unordered_map<std::string, voiceregion> voiceregion_map;
};

105
vendor/DPP/include/dpp/voicestate.h vendored Normal file
View File

@ -0,0 +1,105 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <dpp/json_fwd.hpp>
namespace dpp {
/**
* @brief Bit mask flags relating to voice states
*/
enum voicestate_flags {
vs_deaf = 0b00000001, //!< Deafened
vs_mute = 0b00000010, //!< Muted
vs_self_mute = 0b00000100, //!< Self Muted
vs_self_deaf = 0b00001000, //!< Self Deafened
vs_self_stream = 0b00010000, //!< Self Streaming
vs_self_video = 0b00100000, //!< Self Video
vs_supress = 0b01000000 //!< Supression
};
/**
* @brief Represents the voice state of a user on a guild
* These are stored in the dpp::guild object, and accessible there,
* or via dpp::channel::get_voice_members
*/
class CoreExport voicestate {
public:
class discord_client* shard; //!< Owning shard
snowflake guild_id; //!< Optional: the guild id this voice state is for
snowflake channel_id; //!< the channel id this user is connected to (may be empty)
snowflake user_id; //!< the user id this voice state is for
std::string session_id; //!< the session id for this voice state
uint8_t flags; //!< Voice state flags
/**
* @brief Construct a new voicestate object
*/
voicestate();
/**
* @brief Destroy the voicestate object
*/
~voicestate();
/**
* @brief Fill voicestate object from json data
*
* @param j JSON data to fill from
* @return voicestate& Reference to self
*/
voicestate& fill_from_json(nlohmann::json* j);
/**
* @brief Build json representation of the object
*
* @return std::string JSON string
*/
std::string build_json() const;
/// Return true if user is deafened
bool is_deaf() const;
/// Return true if user is muted
bool is_mute() const;
/// Return true if user muted themselves
bool is_self_mute() const;
/// Return true if user deafened themselves
bool is_self_deaf() const;
/// Return true if the user is streamig
bool self_stream() const;
/// Return true if the user is in video
bool self_video() const;
/// Return true if user is surpressed.
/// "HELP HELP I'M BEING SUPRESSED!"
bool is_supressed() const;
};
/** A container of voicestates */
typedef std::unordered_map<std::string, voicestate> voicestate_map;
};

92
vendor/DPP/include/dpp/webhook.h vendored Normal file
View File

@ -0,0 +1,92 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <dpp/discord.h>
#include <dpp/json_fwd.hpp>
namespace dpp {
/**
* @brief Defines types of webhook
*/
enum webhook_type {
w_incoming = 1, //!< Incoming webhook
w_channel_follower = 2 //!< Channel following webhook
};
/**
* @brief Represents a discord webhook
*/
class CoreExport webhook : public managed {
public:
uint8_t type; //!< the type of the webhook
snowflake guild_id; //!< Optional: the guild id this webhook is for
snowflake channel_id; //!< the channel id this webhook is for
snowflake user_id; //!< Optional: the user this webhook was created by (not returned when getting a webhook with its token)
std::string name; //!< the default name of the webhook (may be empty)
std::string avatar; //!< the default avatar of the webhook (may be empty)
std::string token; //!< Optional: the secure token of the webhook (returned for Incoming Webhooks)
snowflake application_id; //!< the bot/OAuth2 application that created this webhook (may be empty)
std::string* image_data; //!< base64 encoded image data if uploading a new image
/**
* @brief Construct a new webhook object
*/
webhook();
/**
* @brief Destroy the webhook object
*/
~webhook();
/**
* @brief Fill in object from json data
*
* @param j JSON data
* @return webhook& Reference to self
*/
webhook& fill_from_json(nlohmann::json* j);
/**
* @brief Build JSON string from object
*
* @param with_id Include the ID of the webhook in the json
* @return std::string JSON encoded object
*/
std::string build_json(bool with_id = false) const;
/**
* @brief Base64 encode image data and allocate it to image_data
*
* @param image_blob Binary image data
* @param type Image type
* @return webhook& Reference to self
*/
webhook& load_image(const std::string &image_blob, image_type type);
};
/**
* @brief A group of webhooks
*/
typedef std::unordered_map<snowflake, webhook> webhook_map;
};

156
vendor/DPP/include/dpp/wsclient.h vendored Normal file
View File

@ -0,0 +1,156 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <string>
#include <map>
#include <vector>
#include <variant>
#include <dpp/sslclient.h>
namespace dpp {
/**
* @brief Websocket connection status
*/
enum ws_state {
/** Sending/receiving HTTP headers prior to protocol switch */
HTTP_HEADERS,
/** Connected, upgraded and sending/receiving frames */
CONNECTED
};
/**
* @brief Low-level websocket opcodes for frames
*/
enum ws_opcode
{
OP_CONTINUATION = 0x00, //!< Continuation
OP_TEXT = 0x01, //!< Text frame
OP_BINARY = 0x02, //!< Binary frame
OP_CLOSE = 0x08, //!< Close notification with close code
OP_PING = 0x09, //!< Low level ping
OP_PONG = 0x0a //!< Low level pong
};
/**
* @brief Implements a websocket client based on the SSL client
*/
class CoreExport websocket_client : public ssl_client
{
/** Connection key used in the HTTP headers */
std::string key;
/** Current websocket state */
ws_state state;
/** Path part of URL for websocket */
std::string path;
/** HTTP headers received on connecting/upgrading */
std::map<std::string, std::string> HTTPHeaders;
/** Parse headers for a websocket frame from the buffer.
* @param buffer The buffer to operate on. Will modify the string removing completed items from the head of the queue
*/
bool parseheader(std::string &buffer);
/** Unpack a frame and pass completed frames up the stack.
* @param buffer The buffer to operate on. Gets modified to remove completed frames on the head of the buffer
* @param offset The offset to start at (reserved for future use)
* @param first True if is the first element (reserved for future use)
*/
bool unpack(std::string &buffer, uint32_t offset, bool first = true);
/** Fill a header for outbound messages
* @param outbuf The raw frame to fill
* @param sendlength The size of the data to encapsulate
* @param ws_opcode the opcode to send in the header
*/
size_t FillHeader(unsigned char* outbuf, size_t sendlength, ws_opcode opcode);
/** Handle ping and pong requests.
* @param ping True if this is a ping, false if it is a pong
* @param payload The ping payload, to be returned as-is for a ping
*/
void HandlePingPong(bool ping, const std::string &payload);
protected:
/** (Re)connect */
virtual void Connect();
/** Get websocket state
* @return websocket state
*/
ws_state GetState();
public:
/** Connect to a specific websocket server.
* @param hostname Hostname to connect to
* @param port Port to connect to
* @param urlpath The URL path components of the HTTP request to send
*/
websocket_client(const std::string &hostname, const std::string &port = "443", const std::string &urlpath = "");
/** Destructor */
virtual ~websocket_client();
/**
* @brief Write to websocket. Encapsulates data in frames if the status is CONNECTED.
*
* @param data The data to send.
*/
virtual void write(const std::string &data);
/**
* @brief Processes incoming frames from the SSL socket input buffer.
*
* @param buffer The buffer contents. Can modify this value removing the head elements when processed.
*/
virtual bool handle_buffer(std::string &buffer);
/**
* @brief Close websocket
*/
virtual void close();
/**
* @brief Receives raw frame content only without headers
*
* @param buffer The buffer contents
* @return True if the frame was successfully handled. False if no valid frame is in the buffer.
*/
virtual bool HandleFrame(const std::string &buffer);
/**
* @brief Called upon error frame.
*
* @param errorcode The error code from the websocket server
*/
virtual void Error(uint32_t errorcode);
/** Fires every second from the underlying socket I/O loop, used for sending webscocket pings */
virtual void one_second_timer();
};
};

77
vendor/DPP/src/dpp/auditlog.cpp vendored Normal file
View File

@ -0,0 +1,77 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#include <dpp/auditlog.h>
#include <dpp/discordevents.h>
#include <dpp/discord.h>
#include <dpp/nlohmann/json.hpp>
namespace dpp {
using json = nlohmann::json;
auditlog::auditlog()
{
}
auditlog::~auditlog() {
}
auditlog& auditlog::fill_from_json(nlohmann::json* j) {
for (auto & ai : (*j)["audit_log_entries"]) {
audit_entry ae;
ae.id = SnowflakeNotNull(&ai, "id");
ae.event = (audit_type)Int8NotNull(&ai, "action_type");
ae.user_id = SnowflakeNotNull(&ai, "user_id");
ae.target_id = SnowflakeNotNull(&ai, "target_id");
ae.reason = StringNotNull(&ai, "reason");
if (j->find("changes") != j->end()) {
auto &c = ai["changes"];
for (auto & change : c) {
audit_change ac;
ac.key = StringNotNull(&change, "key");
if (change.find("new_value") != change.end()) {
ac.new_value = change["new_value"].dump();
}
if (change.find("old_value") != change.end()) {
ac.old_value = change["old_value"].dump();
}
}
}
if (j->find("options") != j->end()) {
auto &o = ai["options"];
audit_extra opts;
opts.channel_id = SnowflakeNotNull(&o, "channel_id");
opts.count = StringNotNull(&o, "count");
opts.delete_member_days = StringNotNull(&o, "delete_member_days");
opts.id = SnowflakeNotNull(&o, "id");
opts.members_removed = StringNotNull(&o, "members_removed");
opts.message_id = SnowflakeNotNull(&o, "message_id");
opts.role_name = StringNotNull(&o, "role_name");
opts.type = StringNotNull(&o, "type");
ae.options = opts;
}
this->entries.push_back(ae);
}
return *this;
}
};

52
vendor/DPP/src/dpp/ban.cpp vendored Normal file
View File

@ -0,0 +1,52 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#include <dpp/ban.h>
#include <dpp/discordevents.h>
#include <dpp/discord.h>
#include <dpp/nlohmann/json.hpp>
namespace dpp {
using json = nlohmann::json;
ban::ban() : user_id(0)
{
}
ban::~ban() {
}
ban& ban::fill_from_json(nlohmann::json* j) {
reason = StringNotNull(j, "reason");
if (j->find("user") != j->end()) {
json & user = (*j)["user"];
user_id = SnowflakeNotNull(&user, "id");
}
return *this;
}
std::string ban::build_json() const {
/* This is an unused stub, because sending a ban is simple as a user id and a reason */
return "{}";
}
};

161
vendor/DPP/src/dpp/cache.cpp vendored Normal file
View File

@ -0,0 +1,161 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#include <dpp/discord.h>
#include <mutex>
#include <iostream>
#include <variant>
#include <dpp/cache.h>
#include <dpp/guild.h>
namespace dpp {
std::unordered_map<managed*, time_t> deletion_queue;
std::mutex deletion_mutex;
#define cache_helper(type, cache_name, setter, getter, counter) \
cache* cache_name = nullptr; \
type * setter (snowflake id) { \
return cache_name ? ( type * ) cache_name ->find(id) : nullptr; \
} \
cache* getter () { \
if (! cache_name ) { \
cache_name = new cache(); \
} \
return cache_name ; \
} \
uint64_t counter () { \
return ( cache_name ? cache_name ->count() : 0 ); \
}
/* Because other threads and systems may run for a short while after an event is received, we don't immediately
* delete pointers when objects are replaced. We put them into a queue, and periodically delete pointers in the
* queue. This also rehashes unordered_maps to ensure they free their memory.
*/
void garbage_collection() {
time_t now = time(NULL);
bool repeat = false;
{
std::lock_guard<std::mutex> delete_lock(deletion_mutex);
do {
repeat = false;
for (auto g = deletion_queue.begin(); g != deletion_queue.end(); ++g) {
if (now > g->second + 60) {
delete g->first;
deletion_queue.erase(g);
repeat = true;
break;
}
}
} while (repeat);
if (deletion_queue.size() == 0) {
deletion_queue = {};
}
}
dpp::get_user_cache()->rehash();
dpp::get_channel_cache()->rehash();
dpp::get_guild_cache()->rehash();
dpp::get_role_cache()->rehash();
dpp::get_emoji_cache()->rehash();
}
cache::cache() {
cache_map = new cache_container();
}
cache::~cache() {
delete cache_map;
}
uint64_t cache::count() {
std::lock_guard<std::mutex> lock(this->cache_mutex);
return cache_map->size();
}
std::mutex& cache::get_mutex() {
return this->cache_mutex;
}
cache_container& cache::get_container() {
return *(this->cache_map);
}
void cache::store(managed* object) {
if (!object) {
return;
}
std::lock_guard<std::mutex> lock(this->cache_mutex);
auto existing = cache_map->find(object->id);
if (existing == cache_map->end()) {
(*cache_map)[object->id] = object;
} else if (object != existing->second) {
/* Flag old pointer for deletion and replace */
std::lock_guard<std::mutex> delete_lock(deletion_mutex);
deletion_queue[existing->second] = time(NULL);
(*cache_map)[object->id] = object;
}
}
size_t cache::bytes() {
std::lock_guard<std::mutex> lock(cache_mutex);
return sizeof(this) + (cache_map->bucket_count() * sizeof(size_t));
}
void cache::rehash() {
std::lock_guard<std::mutex> lock(cache_mutex);
cache_container* n = new cache_container();
n->reserve(cache_map->size());
for (auto t = cache_map->begin(); t != cache_map->end(); ++t) {
n->insert(*t);
}
delete cache_map;
cache_map = n;
}
void cache::remove(managed* object) {
if (!object) {
return;
}
std::lock_guard<std::mutex> lock(cache_mutex);
std::lock_guard<std::mutex> delete_lock(deletion_mutex);
auto existing = cache_map->find(object->id);
if (existing != cache_map->end()) {
cache_map->erase(existing);
deletion_queue[object] = time(NULL);
}
}
managed* cache::find(snowflake id) {
std::lock_guard<std::mutex> lock(cache_mutex);
auto r = cache_map->find(id);
if (r != cache_map->end()) {
return r->second;
}
return nullptr;
}
cache_helper(user, user_cache, find_user, get_user_cache, get_user_count);
cache_helper(channel, channel_cache, find_channel, get_channel_cache, get_channel_count);
cache_helper(role, role_cache, find_role, get_role_cache, get_role_count);
cache_helper(guild, guild_cache, find_guild, get_guild_cache, get_guild_count);
cache_helper(emoji, emoji_cache, find_emoji, get_emoji_cache, get_emoji_count);
};

245
vendor/DPP/src/dpp/channel.cpp vendored Normal file
View File

@ -0,0 +1,245 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#include <dpp/discord.h>
#include <dpp/cache.h>
#include <dpp/guild.h>
#include <dpp/user.h>
#include <dpp/discordevents.h>
#include <dpp/stringops.h>
#include <dpp/nlohmann/json.hpp>
using json = nlohmann::json;
namespace dpp {
thread_member& thread_member::fill_from_json(nlohmann::json* j) {
SetSnowflakeNotNull(j, "id", this->thread_id);
SetSnowflakeNotNull(j, "user_id", this->user_id);
SetTimestampNotNull(j, "join_timestamp", this->joined);
SetInt32NotNull(j, "flags", this->flags);
return *this;
}
channel::channel() :
managed(),
flags(0),
guild_id(0),
position(0),
last_message_id(0),
user_limit(0),
rate_limit_per_user(0),
owner_id(0),
parent_id(0),
last_pin_timestamp(0),
message_count(0),
member_count(0)
{
}
channel::~channel()
{
}
bool channel::is_nsfw() const {
return flags & dpp::c_nsfw;
}
bool channel::is_text_channel() const {
return flags & dpp::c_text;
}
bool channel::is_dm() const {
return flags & dpp::c_dm;
}
bool channel::is_voice_channel() const {
return flags & dpp::c_voice;
}
bool channel::is_group_dm() const {
return (flags & (dpp::c_dm | dpp::c_group)) == (dpp::c_dm | dpp::c_group);
}
bool channel::is_category() const {
return flags & dpp::c_category;
}
bool channel::is_stage_channel() const {
return (flags & dpp::c_stage) == dpp::c_stage;
}
bool channel::is_news_channel() const {
/* Important: Stage/News overlap to pack more values in a byte */
return !is_stage_channel() && (flags & dpp::c_news);
}
bool channel::is_store_channel() const {
/* Important: Stage/Store overlap to pack more values in a byte */
return !is_stage_channel() && (flags & dpp::c_store);
}
channel& channel::fill_from_json(json* j) {
this->id = SnowflakeNotNull(j, "id");
SetSnowflakeNotNull(j, "guild_id", this->guild_id);
SetInt16NotNull(j, "position", this->position);
SetStringNotNull(j, "name", this->name);
SetStringNotNull(j, "topic", this->topic);
SetSnowflakeNotNull(j, "last_message_id", this->last_message_id);
SetInt8NotNull(j, "user_limit", this->user_limit);
SetInt16NotNull(j, "rate_limit_per_user", this->rate_limit_per_user);
SetSnowflakeNotNull(j, "owner_id", this->owner_id);
SetSnowflakeNotNull(j, "parent_id", this->parent_id);
//this->last_pin_timestamp
uint8_t type = Int8NotNull(j, "type");
this->flags |= BoolNotNull(j, "nsfw") ? dpp::c_nsfw : 0;
this->flags |= (type == GUILD_TEXT) ? dpp::c_text : 0;
this->flags |= (type == GUILD_VOICE) ? dpp::c_voice : 0;
this->flags |= (type == DM) ? dpp::c_dm : 0;
this->flags |= (type == GROUP_DM) ? (dpp::c_group | dpp::c_dm) : 0;
this->flags |= (type == GUILD_CATEGORY) ? dpp::c_category : 0;
this->flags |= (type == GUILD_NEWS) ? dpp::c_news : 0;
this->flags |= (type == GUILD_STORE) ? dpp::c_store : 0;
this->flags |= (type == GUILD_STAGE) ? dpp::c_stage : 0;
this->flags |= (type == GUILD_NEWS_THREAD) ? dpp::c_news_thread : 0;
this->flags |= (type == GUILD_PUBLIC_THREAD) ? dpp::c_public_thread : 0;
this->flags |= (type == GUILD_PRIVATE_THREAD) ? dpp::c_private_thread : 0;
if (j->find("recipients") != j->end()) {
recipients = {};
for (auto & r : (*j)["recipients"]) {
recipients.push_back(from_string<uint64_t>(r["id"].get<std::string>(), std::dec));
}
}
if (j->find("permission_overwrites") != j->end()) {
permission_overwrites = {};
for (auto & overwrite : (*j)["permission_overwrites"]) {
permission_overwrite po;
po.id = SnowflakeNotNull(&overwrite, "id");
po.allow = SnowflakeNotNull(&overwrite, "allow");
po.deny = SnowflakeNotNull(&overwrite, "deny");
po.type = Int8NotNull(&overwrite, "type");
permission_overwrites.push_back(po);
}
}
if (type == GUILD_NEWS_THREAD || type == GUILD_PUBLIC_THREAD || type == GUILD_PRIVATE_THREAD) {
SetInt8NotNull(j, "message_count", this->message_count);
SetInt8NotNull(j, "memeber_count", this->member_count);
dpp::thread_metadata metadata;
auto json_metadata = (*j)["thread_metadata"];
metadata.archived = BoolNotNull(&json_metadata, "archived");
metadata.archive_timestamp = TimestampNotNull(&json_metadata, "archive_timestamp");
metadata.auto_archive_duration = Int16NotNull(&json_metadata, "auto_archive_duration");
metadata.locked = BoolNotNull(&json_metadata, "locked");
}
return *this;
}
std::string channel::build_json(bool with_id) const {
json j;
if (with_id) {
j["id"] = std::to_string(id);
}
j["guild_id"] = std::to_string(guild_id);
j["position"] = position;
j["name"] = name;
j["topic"] = topic;
if (is_voice_channel()) {
j["user_limit"] = user_limit;
j["rate_limit_per_user"] = rate_limit_per_user;
}
if (!is_dm()) {
if (parent_id) {
j["parent_id"] = parent_id;
}
if (is_text_channel()) {
j["type"] = GUILD_TEXT;
} else if (is_voice_channel()) {
j["type"] = GUILD_VOICE;
} else if (is_category()) {
j["type"] = GUILD_CATEGORY;
} else if (is_stage_channel()) {
/* Order is important, as GUILD_STAGE overlaps NEWS and STORE */
j["type"] = GUILD_STAGE;
} else if (is_news_channel()) {
j["type"] = GUILD_NEWS;
} else if (is_store_channel()) {
j["type"] = GUILD_STORE;
}
j["nsfw"] = is_nsfw();
} else {
if (is_group_dm()) {
j["type"] = GROUP_DM;
} else {
j["type"] = DM;
}
}
return j.dump();
}
uint64_t channel::get_user_permissions(const user* member) const
{
if (member == nullptr)
return 0;
guild* g = dpp::find_guild(guild_id);
if (g == nullptr)
return 0;
return g->permission_overwrites(g->base_permissions(member), member, this);
}
std::map<snowflake, guild_member*> channel::get_members() {
std::map<snowflake, guild_member*> rv;
guild* g = dpp::find_guild(guild_id);
if (g) {
for (auto m = g->members.begin(); m != g->members.end(); ++m) {
user* u = dpp::find_user(m->second.user_id);
if (u) {
if (get_user_permissions(u) & p_view_channel) {
rv[m->second.user_id] = &(m->second);
}
}
}
}
return rv;
}
std::map<snowflake, voicestate> channel::get_voice_members() {
std::map<snowflake, voicestate> rv;
guild* g = dpp::find_guild(guild_id);
if (g) {
for (auto & m : g->voice_members) {
if (m.second.channel_id == this->id) {
rv[m.second.user_id] = m.second;
}
}
}
return rv;
}
};

1943
vendor/DPP/src/dpp/cluster.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

360
vendor/DPP/src/dpp/commandhandler.cpp vendored Normal file
View File

@ -0,0 +1,360 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#include <dpp/discord.h>
#include <dpp/commandhandler.h>
#include <dpp/cache.h>
#include <dpp/cluster.h>
#include <dpp/dispatcher.h>
#include <dpp/stringops.h>
#include <dpp/nlohmann/json.hpp>
#include <fmt/format.h>
#include <sstream>
namespace dpp {
param_info::param_info(parameter_type t, bool o, const std::string &d, const std::map<std::string, std::string> &opts) : type(t), optional(o), description(d), choices(opts)
{
}
commandhandler::commandhandler(cluster* o, bool auto_hook_events, snowflake application_id) : slash_commands_enabled(false), owner(o), app_id(application_id)
{
if (!application_id && o->me.id) {
app_id = o->me.id;
}
if (auto_hook_events) {
o->on_interaction_create([this](const dpp::interaction_create_t &event) {
this->route(event);
});
o->on_message_create([this](const dpp::message_create_t & event) {
this->route(*event.msg);
});
}
}
commandhandler& commandhandler::set_owner(cluster* o)
{
owner = o;
return *this;
}
commandhandler::~commandhandler()
{
}
commandhandler& commandhandler::add_prefix(const std::string &prefix)
{
prefixes.push_back(prefix);
if (prefix == "/") {
if (!slash_commands_enabled) {
/* Register existing slash commands */
slash_commands_enabled = true;
} else {
slash_commands_enabled = true;
}
}
return *this;
}
commandhandler& commandhandler::add_command(const std::string &command, const parameter_registration_t &parameters, command_handler handler, const std::string &description, snowflake guild_id)
{
command_info_t i;
i.func = handler;
i.guild_id = guild_id;
i.parameters = parameters;
commands[lowercase(command)] = i;
if (slash_commands_enabled) {
if (this->app_id == 0) {
if (owner->me.id == 0) {
throw dpp::exception("Command handler not ready (i don't know my application ID)");
} else {
this->app_id = owner->me.id;
}
}
dpp::slashcommand newcommand;
/* Create a new global command on ready event */
newcommand.set_name(lowercase(command)).set_description(description).set_application_id(this->app_id);
for (auto& parameter : parameters) {
command_option_type cot;
switch (parameter.second.type) {
case pt_boolean:
cot = co_boolean;
break;
case pt_integer:
cot = co_integer;
break;
case pt_string:
cot = co_string;
break;
case pt_user:
cot = co_user;
break;
case pt_role:
cot = co_role;
break;
case pt_channel:
cot = co_channel;
break;
}
command_option opt(cot, parameter.first, parameter.second.description, !parameter.second.optional);
if (!parameter.second.choices.empty()) {
for (auto& c : parameter.second.choices) {
opt.add_choice(dpp::command_option_choice(c.second, c.first));
}
}
newcommand.add_option(opt);
}
/* Register the command */
if (guild_id) {
owner->guild_command_create(newcommand, guild_id, [command, this](const dpp::confirmation_callback_t &callback) {
if (callback.is_error()) {
this->owner->log(dpp::ll_error, fmt::format("Failed to register guild slash command '{}': {}", command, callback.http_info.body));
}
});
} else {
owner->global_command_create(newcommand, [command, this](const dpp::confirmation_callback_t &callback) {
if (callback.is_error()) {
this->owner->log(dpp::ll_error, fmt::format("Failed to register global slash command '{}': {}", command, callback.http_info.body));
}
});
}
}
return *this;
}
bool commandhandler::string_has_prefix(std::string &str)
{
size_t str_length = utility::utf8len(str);
for (auto& p : prefixes) {
size_t prefix_length = utility::utf8len(p);
if (utility::utf8substr(str, 0, prefix_length) == p) {
str.erase(str.begin(), str.begin() + prefix_length);
return true;
}
}
return false;
}
void commandhandler::route(const dpp::message& msg)
{
std::string msg_content = msg.content;
if (string_has_prefix(msg_content)) {
/* Put the string into stringstream to parse parameters at spaces.
* We use stringstream as it handles multiple spaces etc nicely.
*/
std::stringstream ss(msg_content);
std::string command;
ss >> command;
/* Prefixed command, the prefix was removed */
auto found_cmd = commands.find(lowercase(command));
if (found_cmd != commands.end()) {
/* Filter out guild specific commands that are not for the current guild */
if (found_cmd->second.guild_id && found_cmd->second.guild_id != msg.guild_id) {
return;
}
parameter_list_t call_params;
/* Command found; parse parameters */
for (auto& p : found_cmd->second.parameters) {
command_parameter param;
/* Check for end of stream */
if (!ss) {
/* If it's an optional param, we dont care */
if (!p.second.optional) {
/* Trigger missing parameter handler? */
}
break;
}
switch (p.second.type) {
case pt_string: {
std::string x;
ss >> x;
param = x;
}
break;
case pt_role: {
std::string x;
ss >> x;
if (x.length() > 4 && x[0] == '<' && x[1] == '&') {
snowflake rid = from_string<uint64_t>(x.substr(2, x.length() - 1), std::dec);
role* r = dpp::find_role(rid);
if (r) {
param = *r;
}
}
}
break;
case pt_channel: {
std::string x;
ss >> x;
if (x.length() > 4 && x[0] == '<' && x[1] == '#') {
snowflake cid = from_string<uint64_t>(x.substr(2, x.length() - 1), std::dec);
channel* c = dpp::find_channel(cid);
if (c) {
param = *c;
}
}
}
break;
case pt_user: {
std::string x;
ss >> x;
if (x.length() > 4 && x[0] == '<' && x[1] == '@') {
snowflake uid = from_string<uint64_t>(x.substr(2, x.length() - 1), std::dec);
user* u = dpp::find_user(uid);
if (u) {
param = *u;
}
}
}
break;
case pt_integer: {
int32_t x = 0;
ss >> x;
param = x;
}
case pt_boolean: {
std::string x;
bool y = false;
ss >> x;
x = lowercase(x);
if (x == "yes" || x == "1" || x == "true") {
y = true;
}
param = y;
}
break;
}
/* Add parameter to the list */
call_params.push_back(std::make_pair(p.first, param));
}
/* Call command handler */
command_source source;
source.command_id = 0;
source.guild_id = msg.guild_id;
source.channel_id = msg.channel_id;
source.issuer = msg.author;
found_cmd->second.func(command, call_params, source);
}
}
}
void commandhandler::route(const interaction_create_t & event)
{
/* We don't need to check for prefixes here, slash command interactions
* dont have prefixes at all.
*/
command_interaction cmd = std::get<command_interaction>(event.command.data);
auto found_cmd = commands.find(lowercase(cmd.name));
if (found_cmd != commands.end()) {
/* Command found; parse parameters */
parameter_list_t call_params;
for (auto& p : found_cmd->second.parameters) {
command_parameter param;
const command_value& slash_parameter = event.get_parameter(p.first);
if (p.second.optional && slash_parameter.valueless_by_exception()) {
/* Missing optional parameter, skip this */
continue;
}
try {
switch (p.second.type) {
case pt_string: {
std::string s = std::get<std::string>(slash_parameter);
param = s;
}
break;
case pt_role: {
snowflake rid = std::get<snowflake>(slash_parameter);
role* r = dpp::find_role(rid);
if (r) {
param = *r;
}
}
break;
case pt_channel: {
snowflake cid = std::get<snowflake>(slash_parameter);
channel* c = dpp::find_channel(cid);
if (c) {
param = *c;
}
}
break;
case pt_user: {
snowflake uid = std::get<snowflake>(slash_parameter);
user* u = dpp::find_user(uid);
if (u) {
param = *u;
}
}
break;
case pt_integer: {
int32_t i = std::get<int32_t>(slash_parameter);
param = i;
}
case pt_boolean: {
bool b = std::get<bool>(slash_parameter);
param = b;
}
break;
}
}
catch (const std::bad_variant_access& e) {
/* Missing optional parameter, skip this */
continue;
}
/* Add parameter to the list */
call_params.push_back(std::make_pair(p.first, param));
}
/* Call command handler */
command_source source;
source.command_id = event.command.id;
source.command_token = event.command.token;
source.guild_id = event.command.guild_id;
source.channel_id = event.command.channel_id;
source.issuer = (user*)&event.command.usr;
found_cmd->second.func(cmd.name, call_params, source);
}
}
void commandhandler::reply(const dpp::message &m, command_source source)
{
dpp::message msg = m;
msg.guild_id = source.guild_id;
msg.channel_id = source.channel_id;
if (!source.command_token.empty() && source.command_id) {
owner->interaction_response_create(source.command_id, source.command_token, dpp::interaction_response(ir_channel_message_with_source, msg));
} else {
owner->message_create(msg);
}
}
};

625
vendor/DPP/src/dpp/discordclient.cpp vendored Normal file
View File

@ -0,0 +1,625 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#include <string>
#include <iostream>
#include <fstream>
#ifndef WIN32
#include <unistd.h>
#endif
#include <dpp/discordclient.h>
#include <dpp/cache.h>
#include <dpp/cluster.h>
#include <thread>
#include <dpp/nlohmann/json.hpp>
#include <fmt/format.h>
#include <zlib.h>
#define PATH_UNCOMPRESSED "/?v=" DISCORD_API_VERSION "&encoding=json"
#define PATH_COMPRESSED "/?v=" DISCORD_API_VERSION "&encoding=json&compress=zlib-stream"
#define DECOMP_BUFFER_SIZE 512 * 1024
namespace dpp {
/* This is an internal class, defined externally as just a forward declaration for an opaque pointer.
* This is because we don't want an external dependency on zlib's headers
*/
class zlibcontext {
public:
z_stream d_stream;
};
discord_client::discord_client(dpp::cluster* _cluster, uint32_t _shard_id, uint32_t _max_shards, const std::string &_token, uint32_t _intents, bool comp)
: websocket_client(DEFAULT_GATEWAY, "443", comp ? PATH_COMPRESSED : PATH_UNCOMPRESSED),
creator(_cluster),
shard_id(_shard_id),
max_shards(_max_shards),
token(_token),
last_heartbeat(time(NULL)),
heartbeat_interval(0),
reconnects(0),
resumes(0),
last_seq(0),
sessionid(""),
intents(_intents),
runner(nullptr),
compressed(comp),
decompressed_total(0),
decomp_buffer(nullptr),
ready(false),
ping_start(0.0),
websocket_ping(0.0)
{
zlib = new zlibcontext();
Connect();
}
discord_client::~discord_client()
{
if (runner) {
runner->join();
delete runner;
}
delete zlib;
}
uint64_t discord_client::get_decompressed_bytes_in()
{
return decompressed_total;
}
void discord_client::SetupZLib()
{
if (compressed) {
zlib->d_stream.zalloc = (alloc_func)0;
zlib->d_stream.zfree = (free_func)0;
zlib->d_stream.opaque = (voidpf)0;
if (inflateInit(&(zlib->d_stream)) != Z_OK) {
throw dpp::exception("Can't initialise stream compression!");
}
this->decomp_buffer = new unsigned char[DECOMP_BUFFER_SIZE];
}
}
void discord_client::EndZLib()
{
if (compressed) {
inflateEnd(&(zlib->d_stream));
if (this->decomp_buffer) {
delete[] this->decomp_buffer;
this->decomp_buffer = nullptr;
}
}
}
void discord_client::ThreadRun()
{
SetupZLib();
do {
bool error = false;
ready = false;
message_queue.clear();
ssl_client::read_loop();
ssl_client::close();
EndZLib();
SetupZLib();
do {
error = false;
try {
ssl_client::Connect();
websocket_client::Connect();
}
catch (const std::exception &e) {
log(dpp::ll_error, std::string("Error establishing connection, retry in 5 seconds: ") + e.what());
ssl_client::close();
std::this_thread::sleep_for(std::chrono::seconds(5));
error = true;
}
} while (error);
} while(true);
}
void discord_client::Run()
{
this->runner = new std::thread(&discord_client::ThreadRun, this);
this->thread_id = runner->native_handle();
}
bool discord_client::HandleFrame(const std::string &buffer)
{
std::string& data = (std::string&)buffer;
/* gzip compression is a special case */
if (compressed) {
/* Check that we have a complete compressed frame */
if ((uint8_t)buffer[buffer.size() - 4] == 0x00 && (uint8_t)buffer[buffer.size() - 3] == 0x00 && (uint8_t)buffer[buffer.size() - 2] == 0xFF
&& (uint8_t)buffer[buffer.size() - 1] == 0xFF) {
/* Decompress buffer */
decompressed.clear();
zlib->d_stream.next_in = (Bytef *)buffer.c_str();
zlib->d_stream.avail_in = buffer.size();
do {
int have = 0;
zlib->d_stream.next_out = (Bytef*)decomp_buffer;
zlib->d_stream.avail_out = DECOMP_BUFFER_SIZE;
int ret = inflate(&(zlib->d_stream), Z_NO_FLUSH);
have = DECOMP_BUFFER_SIZE - zlib->d_stream.avail_out;
switch (ret)
{
case Z_NEED_DICT:
case Z_STREAM_ERROR:
this->Error(6000);
this->close();
return true;
break;
case Z_DATA_ERROR:
this->Error(6001);
this->close();
return true;
break;
case Z_MEM_ERROR:
this->Error(6002);
this->close();
return true;
break;
case Z_OK:
this->decompressed.append((const char*)decomp_buffer, have);
this->decompressed_total += have;
break;
default:
/* Stub */
break;
}
} while (zlib->d_stream.avail_out == 0);
data = decompressed;
} else {
/* No complete compressed frame yet */
return false;
}
}
log(dpp::ll_trace, fmt::format("R: {}", data));
json j;
try {
j = json::parse(data);
}
catch (const std::exception &e) {
log(dpp::ll_error, fmt::format("discord_client::HandleFrame {} [{}]", e.what(), data));
return true;
}
if (j.find("s") != j.end() && !j["s"].is_null()) {
last_seq = j["s"].get<uint64_t>();
}
if (j.find("op") != j.end()) {
uint32_t op = j["op"];
switch (op) {
case 9:
/* Reset session state and fall through to 10 */
op = 10;
log(dpp::ll_debug, fmt::format("Failed to resume session {}, will reidentify", sessionid));
this->sessionid = "";
this->last_seq = 0;
/* No break here, falls through to state 10 to cause a reidentify */
case 10:
/* Need to check carefully for the existence of this before we try to access it! */
if (j.find("d") != j.end() && j["d"].find("heartbeat_interval") != j["d"].end() && !j["d"]["heartbeat_interval"].is_null()) {
this->heartbeat_interval = j["d"]["heartbeat_interval"].get<uint32_t>();
}
if (last_seq && !sessionid.empty()) {
/* Resume */
log(dpp::ll_debug, fmt::format("Resuming session {} with seq={}", sessionid, last_seq));
json obj = {
{ "op", 6 },
{ "d", {
{"token", this->token },
{"session_id", this->sessionid },
{"seq", this->last_seq }
}
}
};
this->write(obj.dump());
resumes++;
} else {
/* Full connect */
while (time(NULL) < creator->last_identify + 5) {
uint32_t wait = (creator->last_identify + 5) - time(NULL);
log(dpp::ll_debug, fmt::format("Waiting {} seconds before identifying for session...", wait));
std::this_thread::sleep_for(std::chrono::seconds(wait));
}
log(dpp::ll_debug, "Connecting new session...");
json obj = {
{ "op", 2 },
{
"d",
{
{ "token", this->token },
{ "properties",
{
{ "$os", "Linux" },
{ "$browser", "D++" },
{ "$device", "D++" }
}
},
{ "shard", json::array({ shard_id, max_shards }) },
{ "compress", false },
{ "large_threshold", 250 }
}
}
};
if (this->intents) {
obj["d"]["intents"] = this->intents;
}
this->write(obj.dump());
this->connect_time = creator->last_identify = time(NULL);
reconnects++;
}
this->last_heartbeat_ack = time(nullptr);
websocket_ping = 0;
break;
case 0: {
std::string event = j.find("t") != j.end() && !j["t"].is_null() ? j["t"] : "";
HandleEvent(event, j, data);
}
break;
case 7:
log(dpp::ll_debug, fmt::format("Reconnection requested, closing socket {}", sessionid));
message_queue.clear();
shutdown(sfd, 2);
#ifdef _WIN32
if (sfd >= 0 && sfd < FD_SETSIZE) {
closesocket(sfd);
}
#else
::close(sfd);
#endif
break;
/* Heartbeat ack */
case 11:
this->last_heartbeat_ack = time(nullptr);
websocket_ping = utility::time_f() - ping_start;
break;
}
}
return true;
}
dpp::utility::uptime discord_client::get_uptime()
{
return dpp::utility::uptime(time(NULL) - connect_time);
}
bool discord_client::is_connected()
{
return (this->GetState() == CONNECTED) && (this->ready);
}
void discord_client::Error(uint32_t errorcode)
{
std::map<uint32_t, std::string> errortext = {
{ 1000, "Socket shutdown" },
{ 1001, "Client is leaving" },
{ 1002, "Endpoint received a malformed frame" },
{ 1003, "Endpoint received an unsupported frame" },
{ 1004, "Reserved code" },
{ 1005, "Expected close status, received none" },
{ 1006, "No close code frame has been receieved" },
{ 1007, "Endpoint received inconsistent message (e.g. malformed UTF-8)" },
{ 1008, "Generic error" },
{ 1009, "Endpoint won't process large frame" },
{ 1010, "Client wanted an extension which server did not negotiate" },
{ 1011, "Internal server error while operating" },
{ 1012, "Server/service is restarting" },
{ 1013, "Temporary server condition forced blocking client's request" },
{ 1014, "Server acting as gateway received an invalid response" },
{ 1015, "Transport Layer Security handshake failure" },
{ 4000, "Unknown error" },
{ 4001, "Unknown opcode" },
{ 4002, "Decode error" },
{ 4003, "Not authenticated" },
{ 4004, "Authentication failed" },
{ 4005, "Already authenticated" },
{ 4007, "Invalid seq" },
{ 4008, "Rate limited" },
{ 4009, "Session timed out" },
{ 4010, "Invalid shard" },
{ 4011, "Sharding required" },
{ 4012, "Invalid API version" },
{ 4013, "Invalid intent(s)" },
{ 4014, "Disallowed intent(s)" },
{ 6000, "ZLib Stream Error" },
{ 6001, "ZLib Data Error" },
{ 6002, "ZLib Memory Error" },
{ 6666, "Hell freezing over" }
};
std::string error = "Unknown error";
auto i = errortext.find(errorcode);
if (i != errortext.end()) {
error = i->second;
}
log(dpp::ll_warning, fmt::format("OOF! Error from underlying websocket: {}: {}", errorcode, error));
}
void discord_client::log(dpp::loglevel severity, const std::string &msg) const
{
if (creator->dispatch.log) {
/* Pass to user if theyve hooked the event */
dpp::log_t logmsg(nullptr, msg);
logmsg.severity = severity;
logmsg.message = msg;
creator->dispatch.log(logmsg);
}
}
void discord_client::QueueMessage(const std::string &j, bool to_front)
{
std::lock_guard<std::mutex> locker(queue_mutex);
if (to_front) {
message_queue.push_front(j);
} else {
message_queue.push_back(j);
}
}
void discord_client::ClearQueue()
{
std::lock_guard<std::mutex> locker(queue_mutex);
message_queue.clear();
}
size_t discord_client::GetQueueSize()
{
std::lock_guard<std::mutex> locker(queue_mutex);
return message_queue.size();
}
void discord_client::one_second_timer()
{
websocket_client::one_second_timer();
/* Every minute, rehash all containers from first shard.
* We can't just get shard with the id 0 because this won't
* work on a clustered environment
*/
auto shards = creator->get_shards();
auto first_iter = shards.begin();
if (first_iter != shards.end()) {
dpp::discord_client* first_shard = first_iter->second;
if ((time(NULL) % 60) == 0 && first_shard == this) {
dpp::garbage_collection();
}
}
/* This all only triggers if we are connected (have completed websocket, and received READY or RESUMED) */
if (this->is_connected()) {
/* If we stopped getting heartbeat acknowledgements, this means the connections is dead.
* This can happen to TCP connections which is why we have heartbeats in the first place.
* Miss two ACKS, forces a reconnection.
*/
if ((time(nullptr) - this->last_heartbeat_ack) > heartbeat_interval * 2) {
log(dpp::ll_warning, fmt::format("Missed heartbeat ACK, forcing reconnection to session {}", sessionid));
message_queue.clear();
shutdown(sfd, 2);
#ifdef _WIN32
if (sfd >= 0 && sfd < FD_SETSIZE) {
closesocket(sfd);
}
#else
::close(sfd);
#endif
return;
}
/* Rate limit outbound messages, 1 every odd second, 2 every even second */
for (int x = 0; x < (time(NULL) % 2) + 1; ++x) {
std::lock_guard<std::mutex> locker(queue_mutex);
if (message_queue.size()) {
std::string message = message_queue.front();
message_queue.pop_front();
/* Checking here with .find() saves us having to deserialise the json
* to find pings in our queue. The assumption is that the format of the
* ping isn't going to change.
*/
if (message.find("\"op\":1}") != std::string::npos) {
ping_start = utility::time_f();
}
this->write(message);
}
}
/* Send pings (heartbeat opcodes) before each interval. We send them slightly more regular than expected,
* just to be safe.
*/
if (this->heartbeat_interval && this->last_seq) {
/* Check if we're due to emit a heartbeat */
if (time(NULL) > last_heartbeat + ((heartbeat_interval / 1000.0) * 0.75)) {
QueueMessage(json({{"op", 1}, {"d", last_seq}}).dump(), true);
last_heartbeat = time(NULL);
}
}
}
}
uint64_t discord_client::get_guild_count() {
uint64_t total = 0;
dpp::cache* c = dpp::get_guild_cache();
dpp::cache_container& gc = c->get_container();
/* IMPORTANT: We must lock the container to iterate it */
std::lock_guard<std::mutex> lock(c->get_mutex());
for (auto g = gc.begin(); g != gc.end(); ++g) {
dpp::guild* gp = (dpp::guild*)g->second;
if (gp->shard_id == this->shard_id) {
total++;
}
}
return total;
}
uint64_t discord_client::get_member_count() {
uint64_t total = 0;
dpp::cache* c = dpp::get_guild_cache();
dpp::cache_container& gc = c->get_container();
/* IMPORTANT: We must lock the container to iterate it */
std::lock_guard<std::mutex> lock(c->get_mutex());
for (auto g = gc.begin(); g != gc.end(); ++g) {
dpp::guild* gp = (dpp::guild*)g->second;
if (gp->shard_id == this->shard_id) {
if (creator->cache_policy.user_policy == dpp::cp_aggressive) {
/* We can use actual member count if we are using full user caching */
total += gp->members.size();
} else {
/* Otherwise we use approximate guild member counts from guild_create */
total += gp->member_count;
}
}
}
return total;
}
uint64_t discord_client::get_channel_count() {
uint64_t total = 0;
dpp::cache* c = dpp::get_guild_cache();
dpp::cache_container& gc = c->get_container();
/* IMPORTANT: We must lock the container to iterate it */
std::lock_guard<std::mutex> lock(c->get_mutex());
for (auto g = gc.begin(); g != gc.end(); ++g) {
dpp::guild* gp = (dpp::guild*)g->second;
if (gp->shard_id == this->shard_id) {
total += gp->channels.size();
}
}
return total;
}
void discord_client::connect_voice(snowflake guild_id, snowflake channel_id) {
#ifdef HAVE_VOICE
std::lock_guard<std::mutex> lock(voice_mutex);
if (connecting_voice_channels.find(guild_id) == connecting_voice_channels.end()) {
connecting_voice_channels[guild_id] = new voiceconn(this, channel_id);
/* Once sent, this expects two events (in any order) on the websocket:
* VOICE_SERVER_UPDATE and VOICE_STATUS_UPDATE
*/
log(ll_debug, fmt::format("Sending op 4, guild {}", guild_id));
QueueMessage(json({
{ "op", 4 },
{ "d", {
{ "guild_id", std::to_string(guild_id) },
{ "channel_id", std::to_string(channel_id) },
{ "self_mute", false },
{ "self_deaf", false },
}
}
}).dump(), false);
}
#endif
}
void discord_client::disconnect_voice(snowflake guild_id) {
#ifdef HAVE_VOICE
std::lock_guard<std::mutex> lock(voice_mutex);
auto v = connecting_voice_channels.find(guild_id);
if (v != connecting_voice_channels.end()) {
log(ll_debug, fmt::format("Disconnecting voice, guild: {}", guild_id));
QueueMessage(json({
{ "op", 4 },
{ "d", {
{ "guild_id", std::to_string(guild_id) },
{ "channel_id", json::value_t::null },
{ "self_mute", false },
{ "self_deaf", false },
}
}
}).dump(), false);
delete v->second;
v->second = nullptr;
connecting_voice_channels.erase(v);
}
#endif
}
voiceconn* discord_client::get_voice(snowflake guild_id) {
#ifdef HAVE_VOICE
std::lock_guard<std::mutex> lock(voice_mutex);
auto v = connecting_voice_channels.find(guild_id);
if (v != connecting_voice_channels.end()) {
return v->second;
}
#endif
return nullptr;
}
voiceconn::voiceconn(discord_client* o, snowflake _channel_id) : creator(o), channel_id(_channel_id), voiceclient(nullptr) {
}
bool voiceconn::is_ready() {
return (!websocket_hostname.empty() && !session_id.empty() && !token.empty());
}
bool voiceconn::is_active() {
return voiceclient != nullptr;
}
void voiceconn::disconnect() {
if (this->is_active()) {
voiceclient->terminating = true;
voiceclient->close();
delete voiceclient;
voiceclient = nullptr;
}
}
voiceconn::~voiceconn() {
this->disconnect();
}
void voiceconn::connect(snowflake guild_id) {
if (this->is_ready() && !this->is_active()) {
/* This is wrapped in a thread because instantiating discord_voice_client can initiate a blocking SSL_connect() */
auto t = std::thread([guild_id, this]() {
try {
this->creator->log(ll_debug, fmt::format("Connecting voice for guild {} channel {}", guild_id, this->channel_id));
this->voiceclient = new discord_voice_client(creator->creator, this->channel_id, guild_id, this->token, this->session_id, this->websocket_hostname);
/* Note: Spawns thread! */
this->voiceclient->Run();
}
catch (std::exception &e) {
this->creator->log(ll_error, fmt::format("Can't connect to voice websocket (guild_id: {}, channel_id: {}): {}", guild_id, this->channel_id, e.what()));
}
});
t.detach();
}
}
};

325
vendor/DPP/src/dpp/discordevents.cpp vendored Normal file
View File

@ -0,0 +1,325 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#define _XOPEN_SOURCE
#include <string>
#include <iostream>
#include <fstream>
#include <time.h>
#include <stdlib.h>
#include <dpp/discordclient.h>
#include <dpp/discord.h>
#include <dpp/event.h>
#include <dpp/cache.h>
#include <dpp/stringops.h>
#include <dpp/nlohmann/json.hpp>
#include <fmt/format.h>
#ifdef _WIN32
#include <time.h>
#include <iomanip>
#include <sstream>
char* strptime(const char* s, const char* f, struct tm* tm) {
std::istringstream input(s);
input.imbue(std::locale(setlocale(LC_ALL, nullptr)));
input >> std::get_time(tm, f);
if (input.fail()) {
return const_cast< char* >("");
}
return (char*)(s + input.tellg());
}
#endif
namespace dpp {
uint64_t SnowflakeNotNull(const json* j, const char *keyname) {
/* Snowflakes are a special case. Pun intended.
* Because discord drinks the javascript kool-aid, they have to send 64 bit integers as strings as js can't deal with them
* even though we can. So, all snowflakes are sent and received wrapped as string values and must be read by nlohmann::json
* as string types, then converted from string to uint64_t. Checks for existence of the value, and that it is a string containing
* a number. If not, then this function returns 0.
*/
auto k = j->find(keyname);
if (k != j->end()) {
return !k->is_null() && k->is_string() ? strtoull(k->get<std::string>().c_str(), nullptr, 10) : 0;
} else {
return 0;
}
}
void SetSnowflakeNotNull(const json* j, const char *keyname, uint64_t &v) {
auto k = j->find(keyname);
if (k != j->end()) {
v = !k->is_null() && k->is_string() ? strtoull(k->get<std::string>().c_str(), nullptr, 10) : 0;
}
}
std::string StringNotNull(const json* j, const char *keyname) {
/* Returns empty string if the value is not a string, or is null or not defined */
auto k = j->find(keyname);
if (k != j->end()) {
return !k->is_null() && k->is_string() ? k->get<std::string>() : "";
} else {
return "";
}
}
void SetStringNotNull(const json* j, const char *keyname, std::string &v) {
/* Returns empty string if the value is not a string, or is null or not defined */
auto k = j->find(keyname);
if (k != j->end()) {
v = !k->is_null() && k->is_string() ? k->get<std::string>() : "";
}
}
uint64_t Int64NotNull(const json* j, const char *keyname) {
auto k = j->find(keyname);
if (k != j->end()) {
return !k->is_null() && !k->is_string() ? k->get<uint64_t>() : 0;
} else {
return 0;
}
}
void SetInt64NotNull(const json* j, const char *keyname, uint64_t &v) {
auto k = j->find(keyname);
if (k != j->end()) {
v = !k->is_null() && !k->is_string() ? k->get<uint64_t>() : 0;
}
}
uint32_t Int32NotNull(const json* j, const char *keyname) {
auto k = j->find(keyname);
if (k != j->end()) {
return !k->is_null() && !k->is_string() ? k->get<uint32_t>() : 0;
} else {
return 0;
}
}
void SetInt32NotNull(const json* j, const char *keyname, uint32_t &v) {
auto k = j->find(keyname);
if (k != j->end()) {
v = !k->is_null() && !k->is_string() ? k->get<uint32_t>() : 0;
}
}
uint16_t Int16NotNull(const json* j, const char *keyname) {
auto k = j->find(keyname);
if (k != j->end()) {
return !k->is_null() && !k->is_string() ? k->get<uint16_t>() : 0;
} else {
return 0;
}
}
void SetInt16NotNull(const json* j, const char *keyname, uint16_t &v) {
auto k = j->find(keyname);
if (k != j->end()) {
v = !k->is_null() && !k->is_string() ? k->get<uint16_t>() : 0;
}
}
uint8_t Int8NotNull(const json* j, const char *keyname) {
auto k = j->find(keyname);
if (k != j->end()) {
return !k->is_null() && !k->is_string() ? k->get<uint8_t>() : 0;
} else {
return 0;
}
}
void SetInt8NotNull(const json* j, const char *keyname, uint8_t &v) {
auto k = j->find(keyname);
if (k != j->end()) {
v = !k->is_null() && !k->is_string() ? k->get<uint8_t>() : 0;
}
}
bool BoolNotNull(const json* j, const char *keyname) {
auto k = j->find(keyname);
if (k != j->end()) {
return !k->is_null() ? (k->get<bool>() == true) : false;
} else {
return false;
}
}
void SetBoolNotNull(const json* j, const char *keyname, bool &v) {
auto k = j->find(keyname);
if (k != j->end()) {
v = !k->is_null() ? (k->get<bool>() == true) : false;
}
}
std::string base64_encode(unsigned char const* buf, unsigned int buffer_length) {
/* Quick and dirty base64 encode */
static const char to_base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
size_t ret_size = buffer_length + 2;
ret_size = 4 * ret_size / 3;
std::string ret;
ret.reserve(ret_size);
for (unsigned int i=0; i<ret_size/4; ++i)
{
size_t index = i*3;
unsigned char b3[3];
b3[0] = buf[index+0];
b3[1] = buf[index+1];
b3[2] = buf[index+2];
ret.push_back(to_base64[ ((b3[0] & 0xfc) >> 2) ]);
ret.push_back(to_base64[ ((b3[0] & 0x03) << 4) + ((b3[1] & 0xf0) >> 4) ]);
ret.push_back(to_base64[ ((b3[1] & 0x0f) << 2) + ((b3[2] & 0xc0) >> 6) ]);
ret.push_back(to_base64[ ((b3[2] & 0x3f)) ]);
}
return ret;
}
time_t TimestampNotNull(const json* j, const char* keyname)
{
/* Parses discord ISO 8061 timestamps to time_t, accounting for local time adjustment.
* Note that discord timestamps contain a decimal seconds part, which time_t and struct tm
* can't handle. We strip these out.
*/
time_t retval = 0;
if (j->find(keyname) != j->end() && !(*j)[keyname].is_null() && (*j)[keyname].is_string()) {
tm timestamp = {};
std::string timedate = (*j)[keyname].get<std::string>();
if (timedate.find('+') != std::string::npos && timedate.find('.') != std::string::npos) {
std::string tzpart = timedate.substr(timedate.find('+'), timedate.length());
timedate = timedate.substr(0, timedate.find('.')) + tzpart ;
strptime(timedate.substr(0, 19).c_str(), "%FT%TZ%z", &timestamp);
timestamp.tm_isdst = 0;
retval = mktime(&timestamp);
} else {
strptime(timedate.substr(0, 19).c_str(), "%F %T", &timestamp);
retval = mktime(&timestamp);
}
}
return retval;
}
void SetTimestampNotNull(const json* j, const char* keyname, time_t &v)
{
/* Parses discord ISO 8061 timestamps to time_t, accounting for local time adjustment.
* Note that discord timestamps contain a decimal seconds part, which time_t and struct tm
* can't handle. We strip these out.
*/
time_t retval = 0;
if (j->find(keyname) != j->end() && !(*j)[keyname].is_null() && (*j)[keyname].is_string()) {
tm timestamp = {};
std::string timedate = (*j)[keyname].get<std::string>();
if (timedate.find('+') != std::string::npos && timedate.find('.') != std::string::npos) {
std::string tzpart = timedate.substr(timedate.find('+'), timedate.length());
timedate = timedate.substr(0, timedate.find('.')) + tzpart ;
strptime(timedate.substr(0, 19).c_str(), "%FT%TZ%z", &timestamp);
timestamp.tm_isdst = 0;
retval = mktime(&timestamp);
} else {
strptime(timedate.substr(0, 19).c_str(), "%F %T", &timestamp);
retval = mktime(&timestamp);
}
v = retval;
}
}
std::map<std::string, dpp::events::event*> eventmap = {
{ "__LOG__", new dpp::events::logger() },
{ "GUILD_CREATE", new dpp::events::guild_create() },
{ "GUILD_UPDATE", new dpp::events::guild_update() },
{ "GUILD_DELETE", new dpp::events::guild_delete() },
{ "GUILD_MEMBER_UPDATE", new dpp::events::guild_member_update() },
{ "RESUMED", new dpp::events::resumed() },
{ "READY", new dpp::events::ready() },
{ "CHANNEL_CREATE", new dpp::events::channel_create() },
{ "CHANNEL_UPDATE", new dpp::events::channel_update() },
{ "CHANNEL_DELETE", new dpp::events::channel_delete() },
{ "PRESENCE_UPDATE", new dpp::events::presence_update() },
{ "TYPING_START", new dpp::events::typing_start() },
{ "MESSAGE_CREATE", new dpp::events::message_create() },
{ "MESSAGE_UPDATE", new dpp::events::message_update() },
{ "MESSAGE_DELETE", new dpp::events::message_delete() },
{ "MESSAGE_DELETE_BULK", new dpp::events::message_delete_bulk() },
{ "MESSAGE_REACTION_ADD", new dpp::events::message_reaction_add() },
{ "MESSAGE_REACTION_REMOVE", new dpp::events::message_reaction_remove() },
{ "MESSAGE_REACTION_REMOVE_ALL", new dpp::events::message_reaction_remove_all() },
{ "MESSAGE_REACTION_REMOVE_EMOJI", new dpp::events::message_reaction_remove_emoji() },
{ "CHANNEL_PINS_UPDATE", new dpp::events::channel_pins_update() },
{ "GUILD_BAN_ADD", new dpp::events::guild_ban_add() },
{ "GUILD_BAN_REMOVE", new dpp::events::guild_ban_remove() },
{ "GUILD_EMOJIS_UPDATE", new dpp::events::guild_emojis_update() },
{ "GUILD_INTEGRATIONS_UPDATE", new dpp::events::guild_integrations_update() },
{ "INTEGRATION_CREATE", new dpp::events::integration_create() },
{ "INTEGRATION_UPDATE", new dpp::events::integration_update() },
{ "INTEGRATION_DELETE", new dpp::events::integration_delete() },
{ "GUILD_MEMBER_ADD", new dpp::events::guild_member_add() },
{ "GUILD_MEMBER_REMOVE", new dpp::events::guild_member_remove() },
{ "GUILD_MEMBERS_CHUNK", new dpp::events::guild_members_chunk() },
{ "GUILD_ROLE_CREATE", new dpp::events::guild_role_create() },
{ "GUILD_ROLE_UPDATE", new dpp::events::guild_role_update() },
{ "GUILD_ROLE_DELETE", new dpp::events::guild_role_delete() },
{ "VOICE_STATE_UPDATE", new dpp::events::voice_state_update() },
{ "VOICE_SERVER_UPDATE", new dpp::events::voice_server_update() },
{ "WEBHOOKS_UPDATE", new dpp::events::webhooks_update() },
{ "INVITE_CREATE", new dpp::events::invite_create() },
{ "INVITE_DELETE", new dpp::events::invite_delete() },
{ "APPLICATION_COMMAND_CREATE", new dpp::events::application_command_create() },
{ "APPLICATION_COMMAND_UPDATE", new dpp::events::application_command_update() },
{ "APPLICATION_COMMAND_DELETE", new dpp::events::application_command_delete() },
{ "INTERACTION_CREATE", new dpp::events::interaction_create() },
{ "USER_UPDATE", new dpp::events::user_update() },
{ "GUILD_JOIN_REQUEST_DELETE", new dpp::events::guild_join_request_delete() },
{ "STAGE_INSTANCE_CREATE", new dpp::events::stage_instance_create() },
{ "STAGE_INSTANCE_DELETE", new dpp::events::stage_instance_delete() },
{ "THREAD_CREATE", new dpp::events::thread_create() },
{ "THREAD_UPDATE", new dpp::events::thread_update() },
{ "THREAD_DELETE", new dpp::events::thread_delete() },
{ "THREAD_LIST_SYNC", new dpp::events::thread_list_sync() },
{ "THREAD_MEMBER_UPDATE", new dpp::events::thread_member_update() },
{ "THREAD_MEMBERS_UPDATE", new dpp::events::thread_members_update() },
{ "GUILD_APPLICATION_COMMAND_COUNTS_UPDATE", nullptr },
{ "GUILD_STICKERS_UPDATE", new dpp::events::guild_stickers_update() },
{ "APPLICATION_COMMAND_PERMISSIONS_UPDATE", nullptr },
};
void discord_client::HandleEvent(const std::string &event, json &j, const std::string &raw)
{
auto ev_iter = eventmap.find(event);
if (ev_iter != eventmap.end()) {
/* A handler with nullptr is silently ignored. We don't plan to make a handler for it
* so this usually some user-only thing thats crept into the API and shown to bots
* that we dont care about.
*/
if (ev_iter->second != nullptr) {
ev_iter->second->handle(this, j, raw);
}
} else {
log(dpp::ll_debug, fmt::format("Unhandled event: {}, {}", event, j.dump()));
}
}
};

View File

@ -0,0 +1,747 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#include <string>
#include <iostream>
#include <fstream>
#ifndef WIN32
#include <unistd.h>
#include <arpa/inet.h>
#endif
#include <dpp/discordvoiceclient.h>
#include <dpp/cache.h>
#include <dpp/cluster.h>
#include <thread>
#include <dpp/nlohmann/json.hpp>
#include <fmt/format.h>
#include <zlib.h>
namespace dpp {
std::string external_ip;
/**
* @brief Represents an RTP packet. Size should always be exactly 12.
*/
struct rtp_header {
uint16_t constant;
uint16_t sequence;
uint32_t timestamp;
uint32_t ssrc;
rtp_header(uint16_t _seq, uint32_t _ts, uint32_t _ssrc) : constant(htons(0x8078)), sequence(htons(_seq)), timestamp(htonl(_ts)), ssrc(htonl(_ssrc)) {
}
};
bool discord_voice_client::sodium_initialised = false;
discord_voice_client::discord_voice_client(dpp::cluster* _cluster, snowflake _channel_id, snowflake _server_id, const std::string &_token, const std::string &_session_id, const std::string &_host)
: websocket_client(_host.substr(0, _host.find(":")), _host.substr(_host.find(":") + 1, _host.length()), "/?v=4"),
creator(_cluster),
channel_id(_channel_id),
server_id(_server_id),
token(_token),
last_heartbeat(time(NULL)),
heartbeat_interval(0),
sessionid(_session_id),
runner(nullptr),
terminating(false),
fd(-1),
secret_key(nullptr),
sequence(0),
timestamp(0),
sending(false),
paused(false),
tracks(0)
{
#if HAVE_VOICE
if (!discord_voice_client::sodium_initialised) {
if (sodium_init() < 0) {
throw dpp::exception("discord_voice_client::discord_voice_client; sodium_init() failed");
}
int opusError = 0;
encoder = opus_encoder_create(48000, 2, OPUS_APPLICATION_VOIP, &opusError);
if (opusError) {
throw dpp::exception(fmt::format("discord_voice_client::discord_voice_client; opus_encoder_create() failed: {}", opusError));
}
opusError = 0;
decoder = opus_decoder_create(48000, 2, &opusError);
if (opusError) {
throw dpp::exception(fmt::format("discord_voice_client::discord_voice_client; opus_decoder_create() failed: {}", opusError));
}
repacketizer = opus_repacketizer_create();
discord_voice_client::sodium_initialised = true;
}
Connect();
#endif
}
discord_voice_client::~discord_voice_client()
{
if (runner) {
this->terminating = true;
runner->join();
delete runner;
runner = nullptr;
}
#if HAVE_VOICE
if (encoder) {
opus_encoder_destroy(encoder);
encoder = nullptr;
}
if (decoder) {
opus_decoder_destroy(decoder);
decoder = nullptr;
}
if (repacketizer) {
opus_repacketizer_destroy(repacketizer);
repacketizer = nullptr;
}
#endif
if (secret_key) {
delete[] secret_key;
secret_key = nullptr;
}
}
bool discord_voice_client::is_ready() {
return secret_key != nullptr;
}
bool discord_voice_client::is_playing() {
std::lock_guard<std::mutex> lock(this->stream_mutex);
return (!this->outbuf.empty());
}
void discord_voice_client::ThreadRun()
{
do {
ssl_client::read_loop();
ssl_client::close();
if (!terminating) {
ssl_client::Connect();
websocket_client::Connect();
}
} while(!terminating);
}
void discord_voice_client::Run()
{
this->runner = new std::thread(&discord_voice_client::ThreadRun, this);
this->thread_id = runner->native_handle();
}
int discord_voice_client::UDPSend(const char* data, size_t length)
{
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(this->port);
servaddr.sin_addr.s_addr = inet_addr(this->ip.c_str());
return sendto(this->fd, data, length, 0, (const struct sockaddr*)&servaddr, sizeof(sockaddr_in));
}
int discord_voice_client::UDPRecv(char* data, size_t max_length)
{
struct sockaddr sa;
socklen_t sl;
return recvfrom(this->fd, data, max_length, 0, (struct sockaddr*)&sa, &sl);
}
bool discord_voice_client::HandleFrame(const std::string &data)
{
log(dpp::ll_trace, fmt::format("R: {}", data));
json j;
try {
j = json::parse(data);
}
catch (const std::exception &e) {
log(dpp::ll_error, fmt::format("discord_voice_client::HandleFrame {} [{}]", e.what(), data));
return true;
}
if (j.find("op") != j.end()) {
uint32_t op = j["op"];
switch (op) {
/* Voice resume */
case 9:
log(ll_debug, "Voice connection resumed");
break;
/* Voice HELLO */
case 8: {
if (j.find("d") != j.end() && j["d"].find("heartbeat_interval") != j["d"].end() && !j["d"]["heartbeat_interval"].is_null()) {
this->heartbeat_interval = j["d"]["heartbeat_interval"].get<uint32_t>();
}
if (modes.size()) {
log(dpp::ll_debug, "Resuming voice session...");
json obj = {
{ "op", 7 },
{
"d",
{
{ "server_id", std::to_string(this->server_id) },
{ "session_id", this->sessionid },
{ "token", this->token },
}
}
};
this->write(obj.dump());
} else {
log(dpp::ll_debug, "Connecting new voice session...");
json obj = {
{ "op", 0 },
{
"d",
{
{ "user_id", creator->me.id },
{ "server_id", std::to_string(this->server_id) },
{ "session_id", this->sessionid },
{ "token", this->token },
}
}
};
this->write(obj.dump());
}
this->connect_time = time(NULL);
}
break;
/* Session description */
case 4: {
json &d = j["d"];
secret_key = new uint8_t[32];
size_t ofs = 0;
for (auto & c : d["secret_key"]) {
*(secret_key + ofs) = (uint8_t)c;
ofs++;
if (ofs > 31) {
break;
}
}
if (creator->dispatch.voice_ready) {
voice_ready_t rdy(nullptr, data);
rdy.voice_client = this;
rdy.voice_channel_id = this->channel_id;
creator->dispatch.voice_ready(rdy);
}
}
break;
/* Voice ready */
case 2: {
/* Video stream stuff comes in this frame too, but we can't use it (YET!) */
json &d = j["d"];
this->ip = d["ip"].get<std::string>();
this->port = d["port"].get<uint16_t>();
this->ssrc = d["ssrc"].get<uint64_t>();
// Modes
for (auto & m : d["modes"]) {
this->modes.push_back(m.get<std::string>());
}
log(ll_debug, fmt::format("Voice websocket established; UDP endpoint: {}:{} [ssrc={}] with {} modes", ip, port, ssrc, modes.size()));
external_ip = discover_ip();
int newfd = -1;
if ((newfd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) {
sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(sockaddr_in));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(0);
if (bind(newfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
throw dpp::exception("Can't bind() client UDP socket");
}
#ifdef _WIN32
u_long mode = 1;
int result = ioctlsocket(newfd, FIONBIO, &mode);
if (result != NO_ERROR)
throw dpp::exception("Can't switch socket to non-blocking mode!");
#else
int ofcmode;
ofcmode = fcntl(newfd, F_GETFL, 0);
ofcmode |= O_NDELAY;
if (fcntl(newfd, F_SETFL, ofcmode)) {
throw dpp::exception("Can't switch socket to non-blocking mode!");
}
#endif
/* Hook select() in the ssl_client to add a new file descriptor */
this->fd = newfd;
this->custom_writeable_fd = std::bind(&discord_voice_client::WantWrite, this);
this->custom_readable_fd = std::bind(&discord_voice_client::WantRead, this);
this->custom_writeable_ready = std::bind(&discord_voice_client::WriteReady, this);
this->custom_readable_ready = std::bind(&discord_voice_client::ReadReady, this);
int bound_port = 0;
struct sockaddr_in sin;
socklen_t len = sizeof(sin);
if (getsockname(this->fd, (struct sockaddr *)&sin, &len) > -1) {
bound_port = ntohs(sin.sin_port);
}
log(ll_debug, fmt::format("External IP address: {}", external_ip));
this->write(json({
{ "op", 1 },
{ "d", {
{ "protocol", "udp" },
{ "data", {
{ "address", external_ip },
{ "port", bound_port },
{ "mode", "xsalsa20_poly1305" }
}
}
}
}
}).dump());
}
}
break;
}
}
return true;
}
void discord_voice_client::pause_audio(bool pause) {
this->paused = pause;
}
bool discord_voice_client::is_paused() {
return this->paused;
}
float discord_voice_client::get_secs_remaining() {
std::lock_guard<std::mutex> lock(this->stream_mutex);
/* Audio stream sends one packet every 60ms which means there are 16.666 packets per second */
return (outbuf.size() / 16.666666);
}
dpp::utility::uptime discord_voice_client::get_remaining() {
float fp_secs = get_secs_remaining();
return dpp::utility::uptime((time_t)ceil(fp_secs));
}
void discord_voice_client::stop_audio() {
std::lock_guard<std::mutex> lock(this->stream_mutex);
outbuf.clear();
}
void discord_voice_client::Send(const char* packet, size_t len) {
std::lock_guard<std::mutex> lock(this->stream_mutex);
outbuf.push_back(std::string(packet, len));
}
void discord_voice_client::ReadReady()
{
/* XXX Decoding of voice not currently supported.
* Audio stream will always be a nullptr until then.
* See: https://github.com/discord/discord-api-docs/issues/365
* See also: https://github.com/discord/discord-api-docs/issues/1337
*/
uint8_t buffer[65535];
int r = this->UDPRecv((char*)buffer, sizeof(buffer));
if (r > 0 && creator->dispatch.voice_receive) {
voice_receive_t vr(nullptr, std::string((const char*)buffer, r));
vr.voice_client = this;
vr.audio = nullptr;
vr.audio_size = 0;
creator->dispatch.voice_receive(vr);
}
}
void discord_voice_client::WriteReady()
{
bool call_event = false;
bool track_marker_found = false;
uint64_t bufsize = 0;
{
std::lock_guard<std::mutex> lock(this->stream_mutex);
if (!this->paused && outbuf.size()) {
if (outbuf[0].size() == 2 && ((uint16_t)(*(outbuf[0].data()))) == AUDIO_TRACK_MARKER) {
outbuf.erase(outbuf.begin());
track_marker_found = true;
if (tracks > 0)
tracks--;
}
if (outbuf.size()) {
if (this->UDPSend(outbuf[0].data(), outbuf[0].length()) == outbuf[0].length()) {
outbuf.erase(outbuf.begin());
call_event = true;
bufsize = outbuf.size();
}
}
}
}
if (call_event) {
std::this_thread::sleep_for(std::chrono::milliseconds(60));
if (creator->dispatch.voice_buffer_send) {
voice_buffer_send_t snd(nullptr, "");
snd.buffer_size = bufsize;
snd.voice_client = this;
creator->dispatch.voice_buffer_send(snd);
}
}
if (track_marker_found) {
if (creator->dispatch.voice_track_marker) {
voice_track_marker_t vtm(nullptr, "");
vtm.voice_client = this;
{
std::lock_guard<std::mutex> lock(this->stream_mutex);
if (track_meta.size()) {
vtm.track_meta = track_meta[0];
track_meta.erase(track_meta.begin());
}
}
creator->dispatch.voice_track_marker(vtm);
}
}
}
dpp::utility::uptime discord_voice_client::get_uptime()
{
return dpp::utility::uptime(time(NULL) - connect_time);
}
bool discord_voice_client::is_connected()
{
return (this->GetState() == CONNECTED);
}
int discord_voice_client::WantWrite() {
std::lock_guard<std::mutex> lock(this->stream_mutex);
if (!this->paused && outbuf.size()) {
return fd;
} else {
return -1;
}
}
int discord_voice_client::WantRead() {
return fd;
}
void discord_voice_client::Error(uint32_t errorcode)
{
std::map<uint32_t, std::string> errortext = {
{ 1000, "Socket shutdown" },
{ 1001, "Client is leaving" },
{ 1002, "Endpoint received a malformed frame" },
{ 1003, "Endpoint received an unsupported frame" },
{ 1004, "Reserved code" },
{ 1005, "Expected close status, received none" },
{ 1006, "No close code frame has been receieved" },
{ 1007, "Endpoint received inconsistent message (e.g. malformed UTF-8)" },
{ 1008, "Generic error" },
{ 1009, "Endpoint won't process large frame" },
{ 1010, "Client wanted an extension which server did not negotiate" },
{ 1011, "Internal server error while operating" },
{ 1012, "Server/service is restarting" },
{ 1013, "Temporary server condition forced blocking client's request" },
{ 1014, "Server acting as gateway received an invalid response" },
{ 1015, "Transport Layer Security handshake failure" },
{ 4001, "Unknown opcode" },
{ 4002, "Failed to decode payload" },
{ 4003, "Not authenticated" },
{ 4004, "Authentication failed" },
{ 4005, "Already authenticated" },
{ 4006, "Session no longer valid" },
{ 4009, "Session timeout" },
{ 4011, "Server not found" },
{ 4012, "Unknown protocol" },
{ 4014, "Disconnected" },
{ 4015, "Voice server crashed" },
{ 4016, "Unknown encryption mode" }
};
std::string error = "Unknown error";
auto i = errortext.find(errorcode);
if (i != errortext.end()) {
error = i->second;
}
log(dpp::ll_warning, fmt::format("Voice session error: {} on channel {}: {}", errorcode, channel_id, error));
/* Errors 4004...4016 except 4014 are fatal and cause termination of the voice session */
if (errorcode >= 4003 && errorcode != 4014) {
stop_audio();
this->terminating = true;
log(dpp::ll_error, "This is a non-recoverable error, giving up on voice connection");
}
}
void discord_voice_client::log(dpp::loglevel severity, const std::string &msg)
{
creator->log(severity, msg);
}
void discord_voice_client::QueueMessage(const std::string &j, bool to_front)
{
std::lock_guard<std::mutex> locker(queue_mutex);
if (to_front) {
message_queue.push_front(j);
} else {
message_queue.push_back(j);
}
}
void discord_voice_client::ClearQueue()
{
std::lock_guard<std::mutex> locker(queue_mutex);
message_queue.clear();
}
size_t discord_voice_client::GetQueueSize()
{
std::lock_guard<std::mutex> locker(queue_mutex);
return message_queue.size();
}
const std::vector<std::string> discord_voice_client::get_marker_metadata() {
std::lock_guard<std::mutex> locker(queue_mutex);
return track_meta;
}
void discord_voice_client::one_second_timer()
{
if (terminating) {
throw dpp::exception("Terminating voice connection");
}
/* Rate limit outbound messages, 1 every odd second, 2 every even second */
if (this->GetState() == CONNECTED) {
for (int x = 0; x < (time(NULL) % 2) + 1; ++x) {
std::lock_guard<std::mutex> locker(queue_mutex);
if (message_queue.size()) {
std::string message = message_queue.front();
message_queue.pop_front();
this->write(message);
}
}
if (this->heartbeat_interval) {
/* Check if we're due to emit a heartbeat */
if (time(NULL) > last_heartbeat + ((heartbeat_interval / 1000.0) * 0.75)) {
QueueMessage(json({{"op", 3}, {"d", rand()}}).dump(), true);
last_heartbeat = time(NULL);
}
}
}
}
size_t discord_voice_client::encode(uint8_t *input, size_t inDataSize, uint8_t *output, size_t &outDataSize)
{
#if HAVE_VOICE
outDataSize = 0;
int mEncFrameBytes = 11520;
int mEncFrameSize = 2880;
if (0 == (inDataSize % mEncFrameBytes)) {
bool isOk = true;
size_t cur = 0;
uint8_t *out = encode_buffer;
memset(out, 0, sizeof(encode_buffer));
repacketizer = opus_repacketizer_init(repacketizer);
for (size_t i = 0; i < (inDataSize / mEncFrameBytes); ++ i) {
const opus_int16* pcm = (opus_int16*)(input + i * mEncFrameBytes);
int ret = opus_encode(encoder, pcm, mEncFrameSize, out, 65536);
if (ret > 0) {
int retval = opus_repacketizer_cat(repacketizer, out, ret);
if (retval != OPUS_OK) {
isOk = false;
log(ll_warning, fmt::format("opus_repacketizer_cat(): {}", opus_strerror(retval)));
break;
}
out += ret;
cur += ret;
} else {
isOk = false;
log(ll_warning, fmt::format("opus_encode(): {}", opus_strerror(ret)));
break;
}
}
if (isOk) {
int ret = opus_repacketizer_out(repacketizer, output, 65536);
if (ret > 0) {
outDataSize = ret;
} else {
log(ll_warning, fmt::format("opus_repacketizer_out(): {}", opus_strerror(ret)));
}
}
} else {
throw dpp::exception(fmt::format("Invalid input data length: {}, must be n times of {}", inDataSize, mEncFrameBytes));
}
#endif
return outDataSize;
}
void discord_voice_client::insert_marker(const std::string& metadata) {
/* Insert a track marker. A track marker is a single 16 bit value of 0xFFFF.
* This is too small to be a valid RTP packet so the send function knows not
* to actually send it, and instead to skip it
*/
uint16_t tm = AUDIO_TRACK_MARKER;
Send((const char*)&tm, sizeof(uint16_t));
{
std::lock_guard<std::mutex> lock(this->stream_mutex);
track_meta.push_back(metadata);
tracks++;
}
}
uint32_t discord_voice_client::get_tracks_remaining() {
std::lock_guard<std::mutex> lock(this->stream_mutex);
if (outbuf.size() == 0)
return 0;
else
return tracks + 1;
}
void discord_voice_client::skip_to_next_marker() {
std::lock_guard<std::mutex> lock(this->stream_mutex);
/* Keep popping the first entry off the outbuf until the first entry is a track marker */
while (outbuf.size() && outbuf[0].size() != sizeof(uint16_t) && ((uint16_t)(*(outbuf[0].data()))) != AUDIO_TRACK_MARKER) {
outbuf.erase(outbuf.begin());
}
if (outbuf.size()) {
/* Remove the actual track marker out of the buffer */
outbuf.erase(outbuf.begin());
}
if (tracks > 0)
tracks--;
if (track_meta.size()) {
track_meta.erase(track_meta.begin());
}
}
void discord_voice_client::send_audio(uint16_t* audio_data, const size_t length, bool use_opus) {
#if HAVE_VOICE
const size_t max_frame_bytes = 11520;
uint8_t pad[max_frame_bytes] = { 0 };
if (length > max_frame_bytes && use_opus) {
std::string s_audio_data((const char*)audio_data, length);
while (s_audio_data.length() > max_frame_bytes) {
std::string packet(s_audio_data.substr(0, max_frame_bytes));
s_audio_data.erase(s_audio_data.begin(), s_audio_data.begin() + max_frame_bytes);
if (packet.size() < max_frame_bytes) {
packet.resize(max_frame_bytes, 0);
}
send_audio((uint16_t*)packet.data(), max_frame_bytes, use_opus);
}
return;
}
int frameSize = 2880;
opus_int32 encodedAudioMaxLength = length;
std::vector<uint8_t> encodedAudioData(encodedAudioMaxLength);
size_t encodedAudioLength = encodedAudioMaxLength;
if (use_opus) {
encodedAudioLength = this->encode((uint8_t*)audio_data, length, encodedAudioData.data(), encodedAudioLength);
} else {
}
++sequence;
const int headerSize = 12;
const int nonceSize = 24;
rtp_header header(sequence, timestamp, ssrc);
int8_t nonce[nonceSize];
std::memcpy(nonce, &header, sizeof(header));
std::memset(nonce + sizeof(header), 0, sizeof(nonce) - sizeof(header));
std::vector<uint8_t> audioDataPacket(sizeof(header) + encodedAudioLength + crypto_secretbox_MACBYTES);
std::memcpy(audioDataPacket.data(), &header, sizeof(header));
crypto_secretbox_easy(audioDataPacket.data() + sizeof(header), encodedAudioData.data(), encodedAudioLength, (const unsigned char*)nonce, secret_key);
Send((const char*)audioDataPacket.data(), audioDataPacket.size());
timestamp += frameSize;
if (!this->sending) {
this->QueueMessage(json({
{"op", 5},
{"d", {
{"speaking", 1},
{"delay", 0},
{"ssrc", ssrc}
}}
}).dump(), true);
sending = true;
}
#endif
}
std::string discord_voice_client::discover_ip() {
SOCKET newfd = -1;
unsigned char packet[74] = { 0 };
(*(uint16_t*)(packet)) = htons(0x01);
(*(uint16_t*)(packet + 2)) = htons(70);
(*(uint32_t*)(packet + 4)) = htonl(this->ssrc);
if ((newfd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) {
sockaddr_in servaddr;
socklen_t sl = sizeof(servaddr);
memset(&servaddr, 0, sizeof(sockaddr_in));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(0);
if (bind(newfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
log(ll_warning, "Could not bind socket for IP discovery");
return "";
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(this->port);
servaddr.sin_addr.s_addr = inet_addr(this->ip.c_str());
if (::connect(newfd, (const struct sockaddr*)&servaddr, sizeof(sockaddr_in)) < 0) {
log(ll_warning, "Could not connect socket for IP discovery");
return "";
}
if (send(newfd, (const char*)packet, 74, 0) == -1) {
log(ll_warning, "Could not send packet for IP discovery");
return "";
}
if (recv(newfd, (char*)packet, 74, 0) == -1) {
log(ll_warning, "Could not receive packet for IP discovery");
return "";
}
shutdown(newfd, 2);
#ifdef _WIN32
if (newfd >= 0 && newfd < FD_SETSIZE) {
closesocket(newfd);
}
#else
::close(newfd);
#endif
//utility::debug_dump(packet, 74);
return std::string((const char*)(packet + 8));
}
return "";
}
};

155
vendor/DPP/src/dpp/dispatcher.cpp vendored Normal file
View File

@ -0,0 +1,155 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#include <dpp/discord.h>
#include <dpp/slashcommand.h>
#include <dpp/dispatcher.h>
#include <dpp/cluster.h>
#include <fmt/format.h>
#include <variant>
#define event_ctor(a, b) a::a(discord_client* client, const std::string &raw) : b(client, raw) {}
namespace dpp {
event_dispatch_t::event_dispatch_t(discord_client* client, const std::string &raw) : from(client), raw_event(raw)
{
}
void interaction_create_t::reply(interaction_response_type t, const message & m) const
{
from->creator->interaction_response_create(this->command.id, this->command.token, dpp::interaction_response(t, m));
}
void interaction_create_t::reply(interaction_response_type t, const std::string & mt) const
{
this->reply(t, dpp::message(this->command.channel_id, mt, mt_application_command));
}
void interaction_create_t::get_original_response(command_completion_event_t callback) const
{
from->creator->post_rest(API_PATH "/webhooks", std::to_string(command.application_id), command.token + "/messages/@original", m_get, "", [callback](json &j, const http_request_completion_t& http) {
if (callback) {
callback(confirmation_callback_t("message", message().fill_from_json(&j), http));
}
});
}
void interaction_create_t::edit_response(const message & m) const
{
from->creator->interaction_response_edit(this->command.token, m);
}
void interaction_create_t::edit_response(const std::string & mt) const
{
this->edit_response(dpp::message(this->command.channel_id, mt, mt_application_command));
}
const command_value& interaction_create_t::get_parameter(const std::string& name) const
{
/* Dummy STATIC return value for unknown options so we arent returning a value off the stack */
static command_value dummy_value = {};
const command_interaction& ci = std::get<command_interaction>(command.data);
for (auto i = ci.options.begin(); i != ci.options.end(); ++i) {
if (i->name == name) {
return i->value;
}
}
return dummy_value;
}
const command_value& button_click_t::get_parameter(const std::string& name) const
{
/* Buttons don't have parameters, so override this */
static command_value dummy_b_value = {};
return dummy_b_value;
}
const command_value& select_click_t::get_parameter(const std::string& name) const
{
/* Selects don't have parameters, so override this */
static command_value dummy_b_value = {};
return dummy_b_value;
}
/* Standard default constructors that call the parent constructor, for events */
event_ctor(guild_join_request_delete_t, event_dispatch_t);
event_ctor(stage_instance_create_t, event_dispatch_t);
event_ctor(stage_instance_delete_t, event_dispatch_t);
event_ctor(log_t, event_dispatch_t);
event_ctor(voice_state_update_t, event_dispatch_t);
event_ctor(interaction_create_t, event_dispatch_t);
event_ctor(button_click_t, interaction_create_t);
event_ctor(select_click_t, interaction_create_t);
event_ctor(guild_delete_t, event_dispatch_t);
event_ctor(channel_delete_t, event_dispatch_t);
event_ctor(channel_update_t, event_dispatch_t);
event_ctor(ready_t, event_dispatch_t);
event_ctor(message_delete_t, event_dispatch_t);
event_ctor(application_command_delete_t, event_dispatch_t);
event_ctor(application_command_create_t, event_dispatch_t);
event_ctor(resumed_t, event_dispatch_t);
event_ctor(guild_role_create_t, event_dispatch_t);
event_ctor(typing_start_t, event_dispatch_t);
event_ctor(message_reaction_add_t, event_dispatch_t);
event_ctor(message_reaction_remove_t, event_dispatch_t);
event_ctor(guild_create_t, event_dispatch_t);
event_ctor(channel_create_t, event_dispatch_t);
event_ctor(message_reaction_remove_emoji_t, event_dispatch_t);
event_ctor(message_delete_bulk_t, event_dispatch_t);
event_ctor(guild_role_update_t, event_dispatch_t);
event_ctor(guild_role_delete_t, event_dispatch_t);
event_ctor(channel_pins_update_t, event_dispatch_t);
event_ctor(message_reaction_remove_all_t, event_dispatch_t);
event_ctor(voice_server_update_t, event_dispatch_t);
event_ctor(guild_emojis_update_t, event_dispatch_t);
event_ctor(presence_update_t, event_dispatch_t);
event_ctor(webhooks_update_t, event_dispatch_t);
event_ctor(guild_member_add_t, event_dispatch_t);
event_ctor(invite_delete_t, event_dispatch_t);
event_ctor(guild_update_t, event_dispatch_t);
event_ctor(guild_integrations_update_t, event_dispatch_t);
event_ctor(guild_member_update_t, event_dispatch_t);
event_ctor(application_command_update_t, event_dispatch_t);
event_ctor(invite_create_t, event_dispatch_t);
event_ctor(message_update_t, event_dispatch_t);
event_ctor(user_update_t, event_dispatch_t);
event_ctor(message_create_t, event_dispatch_t);
event_ctor(guild_ban_add_t, event_dispatch_t);
event_ctor(guild_ban_remove_t, event_dispatch_t);
event_ctor(integration_create_t, event_dispatch_t);
event_ctor(integration_update_t, event_dispatch_t);
event_ctor(integration_delete_t, event_dispatch_t);
event_ctor(guild_member_remove_t, event_dispatch_t);
event_ctor(guild_members_chunk_t, event_dispatch_t);
event_ctor(thread_create_t, event_dispatch_t);
event_ctor(thread_update_t, event_dispatch_t);
event_ctor(thread_delete_t, event_dispatch_t);
event_ctor(thread_list_sync_t, event_dispatch_t);
event_ctor(thread_member_update_t, event_dispatch_t);
event_ctor(thread_members_update_t, event_dispatch_t);
event_ctor(voice_buffer_send_t, event_dispatch_t);
event_ctor(voice_user_talking_t, event_dispatch_t);
event_ctor(voice_ready_t, event_dispatch_t);
event_ctor(voice_receive_t, event_dispatch_t);
event_ctor(voice_track_marker_t, event_dispatch_t);
event_ctor(guild_stickers_update_t, event_dispatch_t);
};

64
vendor/DPP/src/dpp/dtemplate.cpp vendored Normal file
View File

@ -0,0 +1,64 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#include <dpp/dtemplate.h>
#include <dpp/discordevents.h>
#include <dpp/nlohmann/json.hpp>
using json = nlohmann::json;
namespace dpp {
dtemplate::dtemplate() : code(""), name(""), description(""), usage_count(0), creator_id(0), source_guild_id(0)
{
}
dtemplate::~dtemplate() {
}
dtemplate& dtemplate::fill_from_json(nlohmann::json* j) {
code = StringNotNull(j, "code");
name = StringNotNull(j, "name");
description = StringNotNull(j, "description");
usage_count = Int32NotNull(j, "usage_count");
creator_id = SnowflakeNotNull(j, "creator_id");
created_at = TimestampNotNull(j, "created_at");
updated_at = TimestampNotNull(j, "updated_at");
source_guild_id = SnowflakeNotNull(j, "source_guild_id");
is_dirty = BoolNotNull(j, "is_dirty");
return *this;
}
std::string dtemplate::build_json() const {
json j({
{"code", code},
{"name", name},
{"description", description},
{"usage_count", usage_count},
{"creator_id", creator_id},
{"updated_at", updated_at},
{"source_guild_id", source_guild_id,
"is_dirty", is_dirty}
});
return j.dump();
}
};

116
vendor/DPP/src/dpp/emoji.cpp vendored Normal file
View File

@ -0,0 +1,116 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#include <dpp/emoji.h>
#include <dpp/discordevents.h>
#include <dpp/discord.h>
#include <dpp/nlohmann/json.hpp>
#include <dpp/dispatcher.h>
namespace dpp {
using json = nlohmann::json;
emoji::emoji() : managed(), user_id(0), flags(0), image_data(nullptr)
{
}
emoji::emoji(const std::string n, const snowflake i, const uint8_t f)
: managed(i), user_id(0), flags(f), image_data(nullptr), name(n)
{
}
emoji::~emoji() {
if (image_data) {
delete image_data;
}
}
emoji& emoji::fill_from_json(nlohmann::json* j) {
id = SnowflakeNotNull(j, "id");
name = StringNotNull(j, "name");
if (j->find("user") != j->end()) {
json & user = (*j)["user"];
user_id = SnowflakeNotNull(&user, "id");
}
if (BoolNotNull(j, "require_colons"))
flags |= e_require_colons;
if (BoolNotNull(j, "managed"))
flags |= e_managed;
if (BoolNotNull(j, "animated"))
flags |= e_animated;
if (BoolNotNull(j, "available"))
flags |= e_available;
return *this;
}
std::string emoji::build_json(bool with_id) const {
json j;
if (with_id) {
j["id"] = std::to_string(id);
}
j["name"] = name;
if (image_data) {
j["image"] = *image_data;
}
return j.dump();
}
bool emoji::requires_colons() const {
return flags & e_require_colons;
}
bool emoji::is_managed() const {
return flags & e_managed;
}
bool emoji::is_animated() const {
return flags & e_animated;
}
bool emoji::is_available() const {
return flags & e_available;
}
emoji& emoji::load_image(const std::string &image_blob, image_type type) {
static std::map<image_type, std::string> mimetypes = {
{ i_gif, "image/gif" },
{ i_jpg, "image/jpeg" },
{ i_png, "image/png" }
};
if (image_blob.size() > MAX_EMOJI_SIZE) {
throw dpp::exception("Emoji file exceeds discord limit of 256 kilobytes");
}
if (image_data) {
/* If there's already image data defined, free the old data, to prevent a memory leak */
delete image_data;
}
image_data = new std::string("data:" + mimetypes[type] + ";base64," + base64_encode((unsigned char const*)image_blob.data(), image_blob.length()));
return *this;
}
std::string emoji::format() const
{
return id ? (name + ":" + std::to_string(id)) : name;
}
};

View File

@ -0,0 +1,48 @@
#include <dpp/discord.h>
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#include <dpp/event.h>
#include <string>
#include <iostream>
#include <fstream>
#include <dpp/discordclient.h>
#include <dpp/discord.h>
#include <dpp/cache.h>
#include <dpp/stringops.h>
#include <dpp/nlohmann/json.hpp>
using json = nlohmann::json;
namespace dpp { namespace events {
using namespace dpp;
/**
* @brief Handle event
*
* @param client Websocket client (current shard)
* @param j JSON data for the event
* @param raw Raw JSON string
*/
void application_command_create::handle(discord_client* client, json &j, const std::string &raw) {
}
}};

View File

@ -0,0 +1,48 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#include <dpp/discord.h>
#include <dpp/event.h>
#include <string>
#include <iostream>
#include <fstream>
#include <dpp/discordclient.h>
#include <dpp/discord.h>
#include <dpp/cache.h>
#include <dpp/stringops.h>
#include <dpp/nlohmann/json.hpp>
using json = nlohmann::json;
namespace dpp { namespace events {
using namespace dpp;
/**
* @brief Handle event
*
* @param client Websocket client (current shard)
* @param j JSON data for the event
* @param raw Raw JSON string
*/
void application_command_delete::handle(discord_client* client, json &j, const std::string &raw) {
}
}};

View File

@ -0,0 +1,48 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#include <dpp/discord.h>
#include <dpp/event.h>
#include <string>
#include <iostream>
#include <fstream>
#include <dpp/discordclient.h>
#include <dpp/discord.h>
#include <dpp/cache.h>
#include <dpp/stringops.h>
#include <dpp/nlohmann/json.hpp>
using json = nlohmann::json;
namespace dpp { namespace events {
using namespace dpp;
/**
* @brief Handle event
*
* @param client Websocket client (current shard)
* @param j JSON data for the event
* @param raw Raw JSON string
*/
void application_command_update::handle(discord_client* client, json &j, const std::string &raw) {
}
}};

View File

@ -0,0 +1,75 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#include <dpp/discord.h>
#include <dpp/event.h>
#include <string>
#include <iostream>
#include <fstream>
#include <dpp/discordclient.h>
#include <dpp/discordevents.h>
#include <dpp/discord.h>
#include <dpp/cache.h>
#include <dpp/stringops.h>
#include <dpp/nlohmann/json.hpp>
#include <fmt/format.h>
using json = nlohmann::json;
namespace dpp { namespace events {
using namespace dpp;
/**
* @brief Handle event
*
* @param client Websocket client (current shard)
* @param j JSON data for the event
* @param raw Raw JSON string
*/
void channel_create::handle(discord_client* client, json &j, const std::string &raw) {
json& d = j["d"];
dpp::channel* c = dpp::find_channel(SnowflakeNotNull(&d, "id"));
if (!c) {
c = new dpp::channel();
}
c->fill_from_json(&d);
dpp::get_channel_cache()->store(c);
if (c->recipients.size()) {
for (auto & u : c->recipients) {
client->log(dpp::ll_debug, fmt::format("Got a DM channel {} for user {}", c->id, u));
client->creator->set_dm_channel(u, c->id);
}
}
dpp::guild* g = dpp::find_guild(c->guild_id);
if (g) {
g->channels.push_back(c->id);
if (client->creator->dispatch.channel_create) {
dpp::channel_create_t cc(client, raw);
cc.created = c;
cc.creating_guild = g;
client->creator->dispatch.channel_create(cc);
}
}
}
}};

View File

@ -0,0 +1,69 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#include <dpp/discord.h>
#include <dpp/event.h>
#include <string>
#include <iostream>
#include <fstream>
#include <dpp/discordclient.h>
#include <dpp/discordevents.h>
#include <dpp/discord.h>
#include <dpp/cache.h>
#include <dpp/stringops.h>
#include <dpp/nlohmann/json.hpp>
using json = nlohmann::json;
namespace dpp { namespace events {
using namespace dpp;
/**
* @brief Handle event
*
* @param client Websocket client (current shard)
* @param j JSON data for the event
* @param raw Raw JSON string
*/
void channel_delete::handle(discord_client* client, json &j, const std::string &raw) {
json& d = j["d"];
dpp::channel* c = dpp::find_channel(SnowflakeNotNull(&d, "id"));
if (c) {
dpp::guild* g = dpp::find_guild(c->guild_id);
if (g) {
auto gc = std::find(g->channels.begin(), g->channels.end(), c->id);
if (gc != g->channels.end()) {
g->channels.erase(gc);
}
if (client->creator->dispatch.channel_delete) {
dpp::channel_delete_t cd(client, raw);
cd.deleted = c;
cd.deleting_guild = g;
client->creator->dispatch.channel_delete(cd);
}
}
dpp::get_channel_cache()->remove(c);
}
}
}};

View File

@ -0,0 +1,61 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#include <dpp/discord.h>
#include <dpp/event.h>
#include <string>
#include <iostream>
#include <fstream>
#include <dpp/discordclient.h>
#include <dpp/discord.h>
#include <dpp/cache.h>
#include <dpp/stringops.h>
#include <dpp/nlohmann/json.hpp>
#include <dpp/discordevents.h>
using json = nlohmann::json;
namespace dpp { namespace events {
using namespace dpp;
/**
* @brief Handle event
*
* @param client Websocket client (current shard)
* @param j JSON data for the event
* @param raw Raw JSON string
*/
void channel_pins_update::handle(discord_client* client, json &j, const std::string &raw) {
if (client->creator->dispatch.channel_pins_update) {
json& d = j["d"];
dpp::channel_pins_update_t cpu(client, raw);
cpu.pin_channel = dpp::find_channel(SnowflakeNotNull(&d, "channel_id"));
cpu.pin_guild = dpp::find_guild(SnowflakeNotNull(&d, "guild_id"));
cpu.timestamp = TimestampNotNull(&d, "last_pin_timestamp");
client->creator->dispatch.channel_pins_update(cpu);
}
}
}};

View File

@ -0,0 +1,59 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#include <dpp/discord.h>
#include <dpp/event.h>
#include <string>
#include <iostream>
#include <fstream>
#include <dpp/discordclient.h>
#include <dpp/discord.h>
#include <dpp/cache.h>
#include <dpp/stringops.h>
#include <dpp/nlohmann/json.hpp>
using json = nlohmann::json;
namespace dpp { namespace events {
using namespace dpp;
/**
* @brief Handle event
*
* @param client Websocket client (current shard)
* @param j JSON data for the event
* @param raw Raw JSON string
*/
void channel_update::handle(discord_client* client, json &j, const std::string &raw) {
json& d = j["d"];
dpp::channel* c = dpp::find_channel(from_string<uint64_t>(d["id"].get<std::string>(), std::dec));
if (c) {
c->fill_from_json(&d);
if (client->creator->dispatch.channel_update) {
dpp::channel_update_t cu(client, raw);
cu.updated = c;
cu.updating_guild = dpp::find_guild(c->guild_id);
client->creator->dispatch.channel_update(cu);
}
}
}
}};

View File

@ -0,0 +1,57 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#include <dpp/discord.h>
#include <dpp/event.h>
#include <string>
#include <iostream>
#include <fstream>
#include <dpp/discordclient.h>
#include <dpp/discord.h>
#include <dpp/cache.h>
#include <dpp/stringops.h>
#include <dpp/nlohmann/json.hpp>
#include <dpp/discordevents.h>
using json = nlohmann::json;
namespace dpp { namespace events {
using namespace dpp;
/**
* @brief Handle event
*
* @param client Websocket client (current shard)
* @param j JSON data for the event
* @param raw Raw JSON string
*/
void guild_ban_add::handle(discord_client* client, json &j, const std::string &raw) {
if (client->creator->dispatch.guild_ban_add) {
json &d = j["d"];
dpp::guild_ban_add_t gba(client, raw);
gba.banning_guild = dpp::find_guild(SnowflakeNotNull(&d, "guild_id"));
gba.banned = dpp::user().fill_from_json(&(d["user"]));
client->creator->dispatch.guild_ban_add(gba);
}
}
}};

View File

@ -0,0 +1,57 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#include <dpp/discord.h>
#include <dpp/event.h>
#include <string>
#include <iostream>
#include <fstream>
#include <dpp/discordclient.h>
#include <dpp/discord.h>
#include <dpp/cache.h>
#include <dpp/stringops.h>
#include <dpp/nlohmann/json.hpp>
#include <dpp/discordevents.h>
using json = nlohmann::json;
namespace dpp { namespace events {
using namespace dpp;
/**
* @brief Handle event
*
* @param client Websocket client (current shard)
* @param j JSON data for the event
* @param raw Raw JSON string
*/
void guild_ban_remove::handle(discord_client* client, json &j, const std::string &raw) {
if (client->creator->dispatch.guild_ban_remove) {
json &d = j["d"];
dpp::guild_ban_remove_t gbr(client, raw);
gbr.unbanning_guild = dpp::find_guild(SnowflakeNotNull(&d, "guild_id"));
gbr.unbanned = dpp::user().fill_from_json(&(d["user"]));
client->creator->dispatch.guild_ban_remove(gbr);
}
}
}};

View File

@ -0,0 +1,149 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#include <dpp/discord.h>
#include <dpp/event.h>
#include <string>
#include <iostream>
#include <fstream>
#include <dpp/discordclient.h>
#include <dpp/discordevents.h>
#include <dpp/discord.h>
#include <dpp/cache.h>
#include <dpp/stringops.h>
#include <dpp/nlohmann/json.hpp>
using json = nlohmann::json;
namespace dpp { namespace events {
using namespace dpp;
/**
* @brief Handle event
*
* @param client Websocket client (current shard)
* @param j JSON data for the event
* @param raw Raw JSON string
*/
void guild_create::handle(discord_client* client, json &j, const std::string &raw) {
json& d = j["d"];
bool newguild = false;
if (SnowflakeNotNull(&d, "id") == 0)
return;
dpp::guild* g = dpp::find_guild(SnowflakeNotNull(&d, "id"));
if (!g) {
g = new dpp::guild();
newguild = true;
}
g->fill_from_json(client, &d);
g->shard_id = client->shard_id;
if (!g->is_unavailable() && newguild) {
if (client->creator->cache_policy.role_policy != dpp::cp_none) {
/* Store guild roles */
g->roles.clear();
g->roles.reserve(d["roles"].size());
for (auto & role : d["roles"]) {
dpp::role *r = dpp::find_role(SnowflakeNotNull(&role, "id"));
if (!r) {
r = new dpp::role();
}
r->fill_from_json(g->id, &role);
dpp::get_role_cache()->store(r);
g->roles.push_back(r->id);
}
}
/* Store guild channels */
g->channels.clear();
g->channels.reserve(d["channels"].size());
for (auto & channel : d["channels"]) {
dpp::channel* c = dpp::find_channel(SnowflakeNotNull(&channel, "id"));
if (!c) {
c = new dpp::channel();
}
c->fill_from_json(&channel);
c->guild_id = g->id;
dpp::get_channel_cache()->store(c);
g->channels.push_back(c->id);
}
/* Store guild threads */
g->threads.clear();
g->threads.reserve(d["threads"].size());
for (auto & channel : d["threads"]) {
g->threads.push_back(SnowflakeNotNull(&channel, "id"));
}
/* Store guild members */
if (client->creator->cache_policy.user_policy == cp_aggressive) {
g->members.reserve(d["members"].size());
for (auto & user : d["members"]) {
snowflake userid = SnowflakeNotNull(&(user["user"]), "id");
/* Only store ones we don't have already otherwise gm will leak */
if (g->members.find(userid) == g->members.end()) {
dpp::user* u = dpp::find_user(userid);
if (!u) {
u = new dpp::user();
u->fill_from_json(&(user["user"]));
dpp::get_user_cache()->store(u);
} else {
u->refcount++;
}
dpp::guild_member gm;
gm.fill_from_json(&(user["user"]), g->id, userid);
g->members[userid] = gm;
}
}
}
if (client->creator->cache_policy.emoji_policy != dpp::cp_none) {
/* Store emojis */
g->emojis.reserve(d["emojis"].size());
g->emojis = {};
for (auto & emoji : d["emojis"]) {
dpp::emoji* e = dpp::find_emoji(SnowflakeNotNull(&emoji, "id"));
if (!e) {
e = new dpp::emoji();
e->fill_from_json(&emoji);
dpp::get_emoji_cache()->store(e);
}
g->emojis.push_back(e->id);
}
}
}
dpp::get_guild_cache()->store(g);
if (newguild && g->id && (client->intents & dpp::i_guild_members)) {
if (client->creator->cache_policy.user_policy == cp_aggressive) {
json chunk_req = json({{"op", 8}, {"d", {{"guild_id",std::to_string(g->id)},{"query",""},{"limit",0}}}});
if (client->intents & dpp::i_guild_presences) {
chunk_req["d"]["presences"] = true;
}
client->QueueMessage(chunk_req.dump());
}
}
if (client->creator->dispatch.guild_create) {
dpp::guild_create_t gc(client, raw);
gc.created = g;
client->creator->dispatch.guild_create(gc);
}
}
}};

Some files were not shown because too many files have changed in this diff Show More