[Saylinks] Fix auto saylink injection edge cases (#1620)

* Fix auto saylink injection edge cases

* Add even more resiliency to edge cases

* Move to split based injection

* Add some constants
This commit is contained in:
Chris Miles 2021-10-19 22:25:13 -05:00 committed by GitHub
parent 3dcddcba04
commit d197ee631e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 135 additions and 30 deletions

View File

@ -126,6 +126,7 @@ namespace Logs {
ClientList, ClientList,
DiaWind, DiaWind,
HTTP, HTTP,
Saylink,
MaxCategoryID /* Don't Remove this */ MaxCategoryID /* Don't Remove this */
}; };
@ -210,6 +211,7 @@ namespace Logs {
"ClientList", "ClientList",
"DialogueWindow", "DialogueWindow",
"HTTP", "HTTP",
"Saylink",
}; };
} }

View File

@ -686,6 +686,16 @@
OutF(LogSys, Logs::Detail, Logs::HTTP, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ OutF(LogSys, Logs::Detail, Logs::HTTP, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0) } 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 {\ #define Log(debug_level, log_category, message, ...) do {\
if (LogSys.log_settings[log_category].is_category_enabled == 1)\ if (LogSys.log_settings[log_category].is_category_enabled == 1)\
LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\

View File

@ -344,43 +344,136 @@ std::string EQ::SayLinkEngine::GenerateQuestSaylink(std::string saylink_text, bo
std::string EQ::SayLinkEngine::InjectSaylinksIfNotExist(const char *message) std::string EQ::SayLinkEngine::InjectSaylinksIfNotExist(const char *message)
{ {
std::string new_message = message; std::string new_message = message;
int link_index = 0; int link_index = 0;
int saylink_index = 0;
std::vector<std::string> links = {}; std::vector<std::string> links = {};
std::vector<std::string> saylinks = {};
int saylink_length = 50;
std::string saylink_separator = "\u0012";
std::string saylink_partial = "000";
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:{}>", saylink_index)
);
saylink_index++;
}
}
LogSaylinkDetail("new_message post pass 1 [{}]", new_message);
// loop through brackets until none exist // loop through brackets until none exist
while (new_message.find('[') != std::string::npos && new_message.find(']') != std::string::npos) { if (new_message.find('[') != std::string::npos) {
std::string bracket_message = get_between(new_message, "[", "]"); for (auto &b: split_string(new_message, "[")) {
if (!b.empty() && b.find(']') != std::string::npos) {
std::vector<std::string> right_split = split_string(b, "]");
if (!right_split.empty()) {
std::string bracket_message = trim(right_split[0]);
// 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 // already a saylink
// todo: improve this later // todo: improve this later
if (!bracket_message.empty() && bracket_message.length() > 50) { if (!bracket_message.empty() &&
(bracket_message.length() > saylink_length ||
bracket_message.find(saylink_separator) != std::string::npos)) {
links.emplace_back(bracket_message); links.emplace_back(bracket_message);
} }
else { else {
links.emplace_back(EQ::SayLinkEngine::GenerateQuestSaylink(bracket_message, false, bracket_message)); links.emplace_back(
EQ::SayLinkEngine::GenerateQuestSaylink(
bracket_message,
false,
bracket_message
)
);
} }
// replace with anchor // replace with anchor
find_replace( find_replace(
new_message, new_message,
fmt::format("[{}]", bracket_message), fmt::format("[{}]", bracket_message),
fmt::format("<link:{}>", link_index) fmt::format("<prelink:{}>", link_index)
); );
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 // pop links onto anchors
link_index = 0; link_index = 0;
for (auto &link: links) { for (auto &link: links) {
// strip any current delimiters of saylinks
find_replace(link, saylink_separator, "");
find_replace( find_replace(
new_message, new_message,
fmt::format("<link:{}>", link_index), fmt::format("<prelink:{}>", link_index),
fmt::format("[{}]", link) fmt::format("[\u0012{}\u0012]", link)
); );
link_index++; 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<saylink:{}>\u0012", saylink_index)) != std::string::npos) {
LogSaylinkDetail("Found encoded saylink at index [{}]", saylink_index);
find_replace(
new_message,
fmt::format("\u0012<saylink:{}>\u0012", saylink_index),
fmt::format("\u0012{}\u0012", link)
);
saylink_index++;
continue;
}
find_replace(
new_message,
fmt::format("<saylink:{}>", saylink_index),
fmt::format("\u0012{}\u0012", link)
);
saylink_index++;
}
LogSaylinkDetail("new_message post pass 4 (post saylink anchor pop) [{}]", new_message);
return new_message; return new_message;
} }