A library for coordinating pre-send chat message token replacement/transformers between addons.
Requires LibStub
To embed this library into your addon, add it to your .pkgmeta file.
package-as: MySuperCoolAddon
externals:
Libs/LibChatFilter: https://github.com/Ghostopheles/LibChatFilter
Then load the included lib.xml file in your .toc, after loading LibStub.
## Name: MySuperCoolAddon
...
Libs/LibStub/LibStub.lua
Libs/LibChatFilter/lib.xml
If you really wanna be bold and run this without embedding it into an addon, you can download the latest packaged release or if you're the type to live on the bleeding edge, grab the latest dev release.
Note
Registered mutators will not run during chat lockdown.
For token replacement and the like.
These run first - before finalizers, and in the order in which they're registered.
local LibChatFilter = LibStub:GetLibrary("LibChatFilter");
local importantToken = "$FFXIV";
local importantMessage = [[Did you know that the critically acclaimed MMORPG Final Fantasy XIV
has a free trial, and includes the entirety of A Realm Reborn AND the award-winning Heavensward expansion
up to level 60 with no restrictions on playtime? Sign up, and enjoy Eorzea today!]];
local function myImportantTransform(text, context)
return text:gsub(importantToken, importantMessage);
end
LibChatFilter.RegisterTransform(myImportantTransform);For addons that need to step in just before the message is sent.
These run after transforms, in the order in which they're registered.
local LibChatFilter = LibStub:GetLibrary("LibChatFilter");
function ChatManager.OnPreSend(message, context)
local chatType = context.chatType;
local chunkSize = CHAT_TYPE_TO_CHUNK_SIZE[chatType];
if not ChatManager.ShouldHandleChat(chatType) or message:len() < chunkSize then
return;
end
HARDWARE_INPUT = true;
local target = context.target;
local language = context.language;
local chunks = Chunker.SplitMessage(message, chunkSize, chatType);
-- cancel out the hardware input flag since it'll be consumed before the queue starts queuing
if QueueHandler:DoesChatTypeRequireHardwareInput(chatType) then
HARDWARE_INPUT = false;
end
for i = 2, #chunks do -- skipping first index because of below
local chunk = chunks[i];
QueueHandler:QueueMessage(chunk, chatType, language, target);
end
QueueHandler:Start();
-- returning the first chunk so it gets sent by the ongoing 'message send' flow
return chunks[1];
end
LibChatFilter.RegisterFinalizer(ChatManager.OnPreSend);Warning
Errors thrown in a mutator are forwarded to the default error handler, and false-y returns are ignored, retaining the previous message values.
By default, all mutators only affect the text that gets sent out, and not the text that gets stored in the chat history buffer (the thing you use when you press the up arrow).
To override this behavior, you can pass a Track parameter to the register function. This can either be a single enum value, or a bitmask of multiple values.
local function myTransform(text, context)
...
end
-- will modify both the 'sent' message, and the one stored in the chat history.
local track = Flags_CreateMask(LibChatFilter.Track.SEND, LibChatFilter.Track.HISTORY);
LibChatFilter.RegisterTransform(myTransform, track);There are two 'exclusive' slots provided for addons that need to run at the very end of their relevant stage.
As an example of an exclusive transform, the addon Languages needs to replace the outgoing message with one translated into a specific dialect/language, so it needs to run after any transformations have already taken place.
An example of an exclusive finalizer would be an addon like Chattery that needs to take the final message and chop it up into smaller messages so that they can be sent in sequence.
Only one exclusive can be set per stage by passing either LibChatFilter.Stage.EXCLUSIVE_TRANSFORM or LibChatFilter.Stage.EXCLUSIVE_FINALIZE for the stage parameter.
Warning
If you attempt to register an exclusive hook when one already exists, the registration function will return false and an error message.
By design, addons that will use these slots will already be largely incompatible with each other, so it's recommended to handle these conflicts before reaching the registration stage.
See the types stub file.