[Discord Integration] Native Discord Integration (#2140)

* Start of discord integration work

* more testing

* Discord client work

* More discord work

* Cleanup

* Handle retry timer response and max retries

* Update base retry timer

* Move Discord queue handler to UCS, add queuer to own thread

* Post merge

* Send up Zone::SendDiscordMessage

* Start of discord integration work

* more testing

* Discord client work

* More discord work

* Cleanup

* Move Discord queue handler to UCS, add queuer to own thread

* Post merge

* Push up tables

* Quest API stuff.

* Update 2022_05_07_discord_webhooks.sql

* Post merge fixes

* Push up manifest

* Flip logging signs in logic from copy / paste of inverse logic before

* Make sure we add new line to quest api sourced messages

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
This commit is contained in:
Chris Miles
2022-06-09 17:22:23 -05:00
committed by GitHub
parent 8ef3e87370
commit 4639405fdf
32 changed files with 1052 additions and 259 deletions
+1 -2
View File
@@ -888,9 +888,8 @@ Json::Value ApiSetLoggingLevel(EQ::Net::WebsocketServerConnection *connection, J
void RegisterApiLogEvent(std::unique_ptr<EQ::Net::WebsocketServer> &server)
{
LogSys.SetConsoleHandler(
[&](uint16 debug_level, uint16 log_category, const std::string &msg) {
[&](uint16 log_category, const std::string &msg) {
Json::Value data;
data["debug_level"] = debug_level;
data["log_category"] = log_category;
data["msg"] = msg;
server->DispatchEvent(EQ::Net::SubscriptionEventLog, data, 50);
+25 -10
View File
@@ -2465,7 +2465,7 @@ XS(XS__istaskenabled) {
} else {
Perl_croak(aTHX_ "Usage: quest::istaskenabled(int task_id)");
}
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
XSRETURN(1);
@@ -2483,7 +2483,7 @@ XS(XS__istaskactive) {
} else {
Perl_croak(aTHX_ "Usage: quest::istaskactive(int task_id)");
}
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
XSRETURN(1);
@@ -2502,7 +2502,7 @@ XS(XS__istaskactivityactive) {
} else {
Perl_croak(aTHX_ "Usage: quest::istaskactivityactive(int task_id, int activity_id)");
}
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
XSRETURN(1);
@@ -2818,7 +2818,7 @@ XS(XS__istaskappropriate) {
} else {
Perl_croak(aTHX_ "Usage: quest::istaskaappropriate(int task_id)");
}
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
XSRETURN(1);
@@ -3386,7 +3386,7 @@ XS(XS__CheckInstanceByCharID) {
uint16 instance_id = (int) SvUV(ST(0));
uint32 char_id = (int) SvUV(ST(1));
RETVAL = quest_manager.CheckInstanceByCharID(instance_id, char_id);
RETVAL = quest_manager.CheckInstanceByCharID(instance_id, char_id);
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
XSRETURN(1);
@@ -3660,7 +3660,7 @@ XS(XS__IsRunning) {
bool RETVAL;
dXSTARG;
RETVAL = quest_manager.IsRunning();
RETVAL = quest_manager.IsRunning();
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
XSRETURN(1);
@@ -8426,20 +8426,34 @@ XS(XS__commify) {
}
XS(XS__checknamefilter);
XS(XS__checknamefilter) {
XS(XS__checknamefilter)
{
dXSARGS;
if (items != 1) {
Perl_croak(aTHX_ "Usage: quest::checknamefilter(string name)");
}
dXSTARG;
std::string name = (std::string) SvPV_nolen(ST(0));
bool passes = database.CheckNameFilter(name);
ST(0) = boolSV(passes);
std::string name = (std::string) SvPV_nolen(ST(0));
bool passes = database.CheckNameFilter(name);
ST(0) = boolSV(passes);
sv_2mortal(ST(0));
XSRETURN(1);
}
XS(XS__discordsend);
XS(XS__discordsend) {
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: quest::discordsend(string webhook_name, string message)");
{
std::string webhook_name = (std::string) SvPV_nolen(ST(0));
std::string message = (std::string) SvPV_nolen(ST(1));
zone->SendDiscordMessage(webhook_name, message);
}
XSRETURN_EMPTY;
}
/*
This is the callback perl will look for to setup the
quest package's XSUBs
@@ -8704,6 +8718,7 @@ EXTERN_C XS(boot_quest) {
newXS(strcpy(buf, "disable_spawn2"), XS__disable_spawn2, file);
newXS(strcpy(buf, "disablerecipe"), XS__disablerecipe, file);
newXS(strcpy(buf, "disabletask"), XS__disabletask, file);
newXS(strcpy(buf, "discordsend"), XS__discordsend, file);
newXS(strcpy(buf, "doanim"), XS__doanim, file);
newXS(strcpy(buf, "echo"), XS__echo, file);
newXS(strcpy(buf, "emote"), XS__emote, file);
+8 -1
View File
@@ -3392,10 +3392,16 @@ std::string lua_commify(std::string number) {
return commify(number);
}
bool lua_check_name_filter(std::string name) {
bool lua_check_name_filter(std::string name)
{
return database.CheckNameFilter(name);
}
void lua_discord_send(std::string webhook_name, std::string message)
{
zone->SendDiscordMessage(webhook_name, message);
}
#define LuaCreateNPCParse(name, c_type, default_value) do { \
cur = table[#name]; \
if(luabind::type(cur) != LUA_TNIL) { \
@@ -3850,6 +3856,7 @@ luabind::scope lua_register_general() {
luabind::def("get_environmental_damage_name", &lua_get_environmental_damage_name),
luabind::def("commify", &lua_commify),
luabind::def("check_name_filter", &lua_check_name_filter),
luabind::def("discord_send", &lua_discord_send),
/*
Cross Zone
+9 -5
View File
@@ -24,12 +24,14 @@ Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net)
extern WorldServer worldserver;
extern QueryServ* QServ;
extern QueryServ *QServ;
QueryServ::QueryServ(){
QueryServ::QueryServ()
{
}
QueryServ::~QueryServ(){
QueryServ::~QueryServ()
{
}
void QueryServ::SendQuery(std::string Query)
@@ -44,7 +46,9 @@ void QueryServ::SendQuery(std::string Query)
void QueryServ::PlayerLogEvent(int Event_Type, int Character_ID, std::string Event_Desc)
{
std::string query = StringFormat(
"INSERT INTO `qs_player_events` (event, char_id, event_desc, time) VALUES (%i, %i, '%s', UNIX_TIMESTAMP(now()))",
Event_Type, Character_ID, EscapeString(Event_Desc).c_str());
"INSERT INTO `qs_player_events` (event, char_id, event_desc, time) VALUES (%i, %i, '%s', UNIX_TIMESTAMP(now()))",
Event_Type,
Character_ID,
EscapeString(Event_Desc).c_str());
SendQuery(query);
}
+2 -2
View File
@@ -21,7 +21,7 @@ enum PlayerGenericLogEventTypes {
Player_Log_Issued_Commands,
Player_Log_Money_Transactions,
Player_Log_Alternate_Currency_Transactions,
};
};
class QueryServ{
@@ -32,4 +32,4 @@ class QueryServ{
void PlayerLogEvent(int Event_Type, int Character_ID, std::string Event_Desc);
};
#endif /* QUERYSERV_ZONE_H */
#endif /* QUERYSERV_ZONE_H */
+3
View File
@@ -57,6 +57,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/shared_tasks.h"
#include "shared_task_zone_messaging.h"
#include "dialogue_window.h"
#include "queryserv.h"
extern EntityList entity_list;
extern Zone* zone;
@@ -208,6 +209,8 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
else {
LogInfo("World assigned Port: [{}] for this zone", sci->port);
ZoneConfig::SetZonePort(sci->port);
LogSys.SetDiscordHandler(&Zone::DiscordWebhookMessageHandler);
}
break;
}
+35 -1
View File
@@ -655,7 +655,7 @@ void Zone::LoadNewMerchantData(uint32 merchantid) {
void Zone::GetMerchantDataForZoneLoad() {
LogInfo("Loading Merchant Lists");
auto query = fmt::format(
SQL (
SELECT
@@ -1209,6 +1209,11 @@ bool Zone::Init(bool is_static) {
//MODDING HOOK FOR ZONE INIT
mod_init();
// logging origination information
LogSys.origination_info.zone_short_name = zone->short_name;
LogSys.origination_info.zone_long_name = zone->long_name;
LogSys.origination_info.instance_id = zone->instanceid;
return true;
}
@@ -2776,3 +2781,32 @@ void Zone::SendReloadMessage(std::string reload_type)
).c_str()
);
}
void Zone::SendDiscordMessage(int webhook_id, const std::string& message)
{
if (worldserver.Connected()) {
auto pack = new ServerPacket(ServerOP_DiscordWebhookMessage, sizeof(DiscordWebhookMessage_Struct) + 1);
auto *q = (DiscordWebhookMessage_Struct *) pack->pBuffer;
strn0cpy(q->message, message.c_str(), 2000);
q->webhook_id = webhook_id;
worldserver.SendPacket(pack);
safe_delete(pack);
}
}
void Zone::SendDiscordMessage(const std::string& webhook_name, const std::string &message)
{
bool not_found = true;
for (auto & w : LogSys.discord_webhooks) {
if (w.webhook_name == webhook_name) {
SendDiscordMessage(w.id, message + "\n");
not_found = false;
}
}
if (not_found) {
LogDiscord("[SendDiscordMessage] Did not find valid webhook by webhook name [{}]", webhook_name);
}
}
+43 -23
View File
@@ -35,6 +35,8 @@
#include "aa_ability.h"
#include "pathfinder_interface.h"
#include "global_loot_manager.h"
#include "queryserv.h"
#include "../common/discord/discord.h"
class DynamicZone;
@@ -147,9 +149,10 @@ public:
const char *GetSpellBlockedMessage(uint32 spell_id, const glm::vec3 &location);
EQ::Random random;
EQTime zone_time;
EQTime zone_time;
ZonePoint *GetClosestZonePoint(const glm::vec3 &location, const char *to_name, Client *client, float max_distance = 40000.0f);
ZonePoint *
GetClosestZonePoint(const glm::vec3 &location, const char *to_name, Client *client, float max_distance = 40000.0f);
inline bool BuffTimersSuspended() const { return newzone_data.SuspendBuffs != 0; };
inline bool HasMap() { return zonemap != nullptr; }
@@ -179,7 +182,7 @@ public:
void DumpMerchantList(uint32 npcid);
int SaveTempItem(uint32 merchantid, uint32 npcid, uint32 item, int32 charges, bool sold = false);
int32 MobsAggroCount() { return aggroedmobs; }
DynamicZone* GetDynamicZone();
DynamicZone *GetDynamicZone();
IPathfinder *pathing;
LinkedList<NPC_Emote_Struct *> NPCEmoteList;
@@ -187,31 +190,31 @@ public:
LinkedList<ZonePoint *> zone_point_list;
std::vector<ZonePointsRepository::ZonePoints> virtual_zone_point_list;
Map *zonemap;
Map *zonemap;
MercTemplate *GetMercTemplate(uint32 template_id);
NewZone_Struct newzone_data;
NewZone_Struct newzone_data;
QGlobalCache *CreateQGlobals()
{
qGlobals = new QGlobalCache();
return qGlobals;
}
QGlobalCache *GetQGlobals() { return qGlobals; }
SpawnConditionManager spawn_conditions;
SpawnGroupList spawn_group_list;
SpawnConditionManager spawn_conditions;
SpawnGroupList spawn_group_list;
std::list<AltCurrencyDefinition_Struct> AlternateCurrencies;
std::list<InternalVeteranReward> VeteranRewards;
std::map<uint32, LDoNTrapTemplate *> ldon_trap_list;
std::map<uint32, MercTemplate> merc_templates;
std::map<uint32, NPCType *> merctable;
std::map<uint32, NPCType *> npctable;
std::map<uint32, std::list<LDoNTrapTemplate *> > ldon_trap_entry_list;
std::map<uint32, std::list<MerchantList> > merchanttable;
std::map<uint32, std::list<MercSpellEntry> > merc_spells_list;
std::map<uint32, std::list<MercStanceInfo> > merc_stance_list;
std::map<uint32, std::list<TempMerchantList> > tmpmerchanttable;
std::map<uint32, std::string> adventure_entry_list_flavor;
std::map<uint32, ZoneEXPModInfo> level_exp_mod;
std::list<AltCurrencyDefinition_Struct> AlternateCurrencies;
std::list<InternalVeteranReward> VeteranRewards;
std::map<uint32, LDoNTrapTemplate *> ldon_trap_list;
std::map<uint32, MercTemplate> merc_templates;
std::map<uint32, NPCType *> merctable;
std::map<uint32, NPCType *> npctable;
std::map<uint32, std::list<LDoNTrapTemplate *> > ldon_trap_entry_list;
std::map<uint32, std::list<MerchantList> > merchanttable;
std::map<uint32, std::list<MercSpellEntry> > merc_spells_list;
std::map<uint32, std::list<MercStanceInfo> > merc_stance_list;
std::map<uint32, std::list<TempMerchantList> > tmpmerchanttable;
std::map<uint32, std::string> adventure_entry_list_flavor;
std::map<uint32, ZoneEXPModInfo> level_exp_mod;
std::pair<AA::Ability *, AA::Rank *> GetAlternateAdvancementAbilityAndRank(int id, int points_spent);
@@ -223,7 +226,7 @@ public:
std::vector<GridEntriesRepository::GridEntry> zone_grid_entries;
std::unordered_map<uint32, std::unique_ptr<DynamicZone>> dynamic_zone_cache;
std::unordered_map<uint32, std::unique_ptr<Expedition>> expedition_cache;
std::unordered_map<uint32, std::unique_ptr<Expedition>> expedition_cache;
time_t weather_timer;
Timer spawn2_timer;
@@ -344,10 +347,11 @@ public:
fmt::format(
"--- {}",
message_split[iter]
).c_str()
).c_str()
);
}
} else {
}
else {
entity_list.MessageStatus(
0,
AccountStatus::QuestTroupe,
@@ -357,6 +361,22 @@ public:
}
}
static void SendDiscordMessage(int webhook_id, const std::string& message);
static void SendDiscordMessage(const std::string& webhook_name, const std::string& message);
static void DiscordWebhookMessageHandler(uint16 log_category, int webhook_id, const std::string &message)
{
std::string message_prefix;
if (!LogSys.origination_info.zone_short_name.empty()) {
message_prefix = fmt::format(
"[**{}**] **Zone** [**{}**] ",
Logs::LogCategoryName[log_category],
LogSys.origination_info.zone_short_name
);
}
SendDiscordMessage(webhook_id, message_prefix + Discord::FormatDiscordMessage(log_category, message));
};
double GetMaxMovementUpdateRange() const { return max_movement_update_range; }
/**