mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-17 03:08:26 +00:00
[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:
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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
@@ -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; }
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user