diff --git a/common/eqemu_logsys.h b/common/eqemu_logsys.h index 3ec495413..11808d891 100644 --- a/common/eqemu_logsys.h +++ b/common/eqemu_logsys.h @@ -126,6 +126,7 @@ namespace Logs { ClientList, DiaWind, HTTP, + Saylink, MaxCategoryID /* Don't Remove this */ }; @@ -210,6 +211,7 @@ namespace Logs { "ClientList", "DialogueWindow", "HTTP", + "Saylink", }; } diff --git a/common/eqemu_logsys_log_aliases.h b/common/eqemu_logsys_log_aliases.h index a949f63a8..753417d81 100644 --- a/common/eqemu_logsys_log_aliases.h +++ b/common/eqemu_logsys_log_aliases.h @@ -686,6 +686,16 @@ OutF(LogSys, Logs::Detail, Logs::HTTP, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) +#define LogSaylink(message, ...) do {\ + if (LogSys.log_settings[Logs::Saylink].is_category_enabled == 1)\ + OutF(LogSys, Logs::General, Logs::Saylink, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogSaylinkDetail(message, ...) do {\ + if (LogSys.log_settings[Logs::Saylink].is_category_enabled == 1)\ + OutF(LogSys, Logs::Detail, Logs::Saylink, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + #define Log(debug_level, log_category, message, ...) do {\ if (LogSys.log_settings[log_category].is_category_enabled == 1)\ LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ diff --git a/common/say_link.cpp b/common/say_link.cpp index d5083384b..c6347d87c 100644 --- a/common/say_link.cpp +++ b/common/say_link.cpp @@ -102,13 +102,13 @@ const std::string &EQ::SayLinkEngine::GenerateLink() m_Link = ""; LogError("SayLinkEngine::GenerateLink() failed to generate a useable say link"); LogError(">> LinkType: {}, Lengths: [link: {}({}), body: {}({}), text: {}({})]", - m_LinkType, - m_Link.length(), - EQ::constants::SAY_LINK_MAXIMUM_SIZE, - m_LinkBody.length(), - EQ::constants::SAY_LINK_BODY_SIZE, - m_LinkText.length(), - EQ::constants::SAY_LINK_TEXT_SIZE + m_LinkType, + m_Link.length(), + EQ::constants::SAY_LINK_MAXIMUM_SIZE, + m_LinkBody.length(), + EQ::constants::SAY_LINK_BODY_SIZE, + m_LinkText.length(), + EQ::constants::SAY_LINK_TEXT_SIZE ); LogError(">> LinkBody: {}", m_LinkBody.c_str()); LogError(">> LinkText: {}", m_LinkText.c_str()); @@ -343,44 +343,137 @@ std::string EQ::SayLinkEngine::GenerateQuestSaylink(std::string saylink_text, bo std::string EQ::SayLinkEngine::InjectSaylinksIfNotExist(const char *message) { - std::string new_message = message; + std::string new_message = message; + int link_index = 0; + int saylink_index = 0; + std::vector links = {}; + std::vector saylinks = {}; + int saylink_length = 50; + std::string saylink_separator = "\u0012"; + std::string saylink_partial = "000"; - int link_index = 0; - std::vector links = {}; + LogSaylinkDetail("new_message pre pass 1 [{}]", new_message); + + // first pass - strip existing saylinks by putting placeholder anchors on them + for (auto &saylink: split_string(new_message, saylink_separator)) { + if (!saylink.empty() && saylink.length() > saylink_length && + saylink.find(saylink_partial) != std::string::npos) { + saylinks.emplace_back(saylink); + + LogSaylinkDetail("Found saylink [{}]", saylink); + + // replace with anchor + find_replace( + new_message, + fmt::format("{}", saylink), + fmt::format("", saylink_index) + ); + + saylink_index++; + } + } + + LogSaylinkDetail("new_message post pass 1 [{}]", new_message); // loop through brackets until none exist - while (new_message.find('[') != std::string::npos && new_message.find(']') != std::string::npos) { - std::string bracket_message = get_between(new_message, "[", "]"); + if (new_message.find('[') != std::string::npos) { + for (auto &b: split_string(new_message, "[")) { + if (!b.empty() && b.find(']') != std::string::npos) { + std::vector right_split = split_string(b, "]"); + if (!right_split.empty()) { + std::string bracket_message = trim(right_split[0]); - // already a saylink - // todo: improve this later - if (!bracket_message.empty() && bracket_message.length() > 50) { - links.emplace_back(bracket_message); + // we shouldn't see a saylink fragment here, ignore this bracket + if (bracket_message.find(saylink_partial) != std::string::npos) { + continue; + } + + // if non empty bracket contents + if (!bracket_message.empty()) { + LogSaylinkDetail("Found bracket_message [{}]", bracket_message); + + // already a saylink + // todo: improve this later + if (!bracket_message.empty() && + (bracket_message.length() > saylink_length || + bracket_message.find(saylink_separator) != std::string::npos)) { + links.emplace_back(bracket_message); + } + else { + links.emplace_back( + EQ::SayLinkEngine::GenerateQuestSaylink( + bracket_message, + false, + bracket_message + ) + ); + } + + // replace with anchor + find_replace( + new_message, + fmt::format("[{}]", bracket_message), + fmt::format("", link_index) + ); + + link_index++; + } + } + } } - else { - links.emplace_back(EQ::SayLinkEngine::GenerateQuestSaylink(bracket_message, false, bracket_message)); - } - - // replace with anchor - find_replace( - new_message, - fmt::format("[{}]", bracket_message), - fmt::format("", link_index) - ); - - link_index++; } + LogSaylinkDetail("new_message post pass 2 (post brackets) [{}]", new_message); + + // strip any current delimiters of saylinks + find_replace(new_message, saylink_separator, ""); + // pop links onto anchors link_index = 0; for (auto &link: links) { + + // strip any current delimiters of saylinks + find_replace(link, saylink_separator, ""); + find_replace( new_message, - fmt::format("", link_index), - fmt::format("[{}]", link) + fmt::format("", link_index), + fmt::format("[\u0012{}\u0012]", link) ); link_index++; } + LogSaylinkDetail("new_message post pass 3 (post prelink anchor pop) [{}]", new_message); + + // pop links onto anchors + saylink_index = 0; + for (auto &link: saylinks) { + // strip any current delimiters of saylinks + find_replace(link, saylink_separator, ""); + + // check to see if we did a double anchor pass (existing saylink that was also inside brackets) + // this means we found a saylink and we're checking to see if we're already encoded before double encoding + if (new_message.find(fmt::format("\u0012\u0012", saylink_index)) != std::string::npos) { + LogSaylinkDetail("Found encoded saylink at index [{}]", saylink_index); + + find_replace( + new_message, + fmt::format("\u0012\u0012", saylink_index), + fmt::format("\u0012{}\u0012", link) + ); + saylink_index++; + continue; + } + + find_replace( + new_message, + fmt::format("", saylink_index), + fmt::format("\u0012{}\u0012", link) + ); + saylink_index++; + } + + LogSaylinkDetail("new_message post pass 4 (post saylink anchor pop) [{}]", new_message); + return new_message; }