WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   pattern matching (https://www.wowinterface.com/forums/showthread.php?t=48291)

Caellian 10-02-13 01:03 AM

pattern matching
 
Hey, anyone good at this could help me match this message so i can filter it ?

Playername-Realm is now roleicon Tank. (Changed by Playerame.)

roleicon is, well, the icon :) and Realm may contain spaces

Phanx 10-02-13 02:06 AM

First, you need to figure out which global string gets used. When filtering system messages, you should always use the relevant global string, so it works in all languages and automatically works if/when Blizzard changes the string. In this case, it's ROLE_CHANGED_INFORM_WITH_SOURCE, which in its raw state looks like "%s is now %s. (Changed by %s.)" in English, "%s ist nun %s. (Von %s geändert.)" in German, etc.

Second, you need to use some gsub magic to turn that string into a pattern you can use with string.find. Here's the function I use that will turn any Blizzard global string into a search pattern:

Code:

local function topattern(str)
        str = gsub(str, "%%%d?$?c", ".+")
        str = gsub(str, "%%%d?$?s", ".+")
        str = gsub(str, "%%%d?$?d", "%%d+")
        str = gsub(str, "([%(%)])", "%%%1")
        return str
end

Notes:

(a) If you're only working with a few strings, you may be tempted to just gsub them directly, but then if Blizzard changes them (for example, changes %s tokens to %1$s tokens, or adds a token) you have to update. The above function will automatically handle any such changes, unless Blizzard adds some new type of tokens.

(b) The above function doesn't add captures, so it's mainly for use with string.find -- is this a "X defated Y in a duel" message? -- and not with string.match -- what are the values of X and Y in this message?.

Back on topic -- to hide the messages:

Code:

local pattern = topattern(ROLE_CHANGED_INFORM_WITH_SOURCE)

ChatFrame_AddMessageEventFilter("CHAT_MSG_SYSTEM", function(frame, event, message, ...)
  return strfind(message, pattern)
end)

If you have a lot of messages to block (for example, if you wanted to block all the messages about how drunk other people are) I'd suggest putting them in an indexed table (faster than a hash table because you don't need a function call to iterate over it) and looping over it like so:

Code:

local patterns = {
  topattern(DRUNK_MESSAGE_ITEM_OTHER1),
  topattern(DRUNK_MESSAGE_ITEM_OTHER2),
  topattern(DRUNK_MESSAGE_ITEM_OTHER3),
  topattern(DRUNK_MESSAGE_ITEM_OTHER4),
  topattern(DRUNK_MESSAGE_OTHER1),
  topattern(DRUNK_MESSAGE_OTHER2),
  topattern(DRUNK_MESSAGE_OTHER3),
  topattern(DRUNK_MESSAGE_OTHER4),
}

ChatFrame_AddMessageEventFilter("CHAT_MSG_SYSTEM", function(frame, event, message, ...)
  for i = 1, #patterns do
      if strfind(message, patterns[i]) then
        return true
      end
  end
end)


Caellian 10-02-13 03:39 AM

This is absolutely perfect, and will simplify my filters file ten fold.

There's one system message i can't seem to find in the GlobalStrings though "Playername is not online."

Any idea how it's possible that it isn't there ? Could it be an addon sending a message through that channel or ?

Phanx 10-02-13 03:49 AM

Well, you could search your Addons folder for the phrase "not online". Some messages are sent pre-formed from the server, though, and don't have global strings, so you'll have to use hardcoded translations for them, unfortunately. :/

Caellian 10-02-13 04:06 AM

Did that, but:

Search "is not online." (0 hits in 0 files)

Ah well, that's no big deal, thanks a lot anyway !

Caellian 10-02-13 07:40 AM

So it should look like this but somehow, the role thingy isn't filtered

Code:

local patternize = function(text)
        text = gsub(text, "%%%d?$?c", ".+")
        text = gsub(text, "%%%d?$?s", ".+")
        text = gsub(text, "%%%d?$?d", "%%d+")
        text = gsub(text, "([%(%)])", "%%%1")

        return text
end

local patterns = {
        patternize(CLEARED_AFK),
        patternize(MARKED_AFK),
        patternize(CLEARED_DND),
        patternize(MARKED_DND),

        patternize(NEW_TITLE_EARNED),
        patternize(ERR_FRIEND_ONLINE_SS),
        patternize(BN_INLINE_TOAST_FRIEND_ONLINE),
        patternize(ERR_FRIEND_OFFLINE_S),
        patternize(BN_INLINE_TOAST_FRIEND_OFFLINE),
        patternize(ERR_LEARN_SPELL_S),
        patternize(ERR_LEARN_ABILITY_S),
        patternize(ERR_LEARN_PASSIVE_S),
        patternize(ERR_SPELL_UNLEARNED_S),
        patternize(ERR_PET_SPELL_UNLEARNED_S),
        patternize(ERR_GUILD_INTERNAL),
        patternize(ROLE_CHANGED_INFORM_WITH_SOURCE),
        patternize(ERR_INSTANCE_GROUP_ADDED_S),
        patternize(ERR_INSTANCE_GROUP_REMOVED_S)
}

ChatFrame_AddMessageEventFilter("CHAT_MSG_SYSTEM", function(frame, event, message, ...)
  for i = 1, #patterns do
      if strfind(message, patterns[i]) then
        return true
      end
  end
end)


Phanx 10-02-13 02:41 PM

Code:

ROLE_CHANGED_INFORM = "%s is now %s.";
ROLE_CHANGED_INFORM_WITH_SOURCE = "%s is now %s. (Changed by %s.)";

You've got #2 on your list, but you're missing #1.

Caellian 10-10-13 11:45 AM

Quote:

Originally Posted by Phanx (Post 285427)
Code:

ROLE_CHANGED_INFORM = "%s is now %s.";
ROLE_CHANGED_INFORM_WITH_SOURCE = "%s is now %s. (Changed by %s.)";

You've got #2 on your list, but you're missing #1.

Phanx, i think that you're pattern function doesn't catch this one at all :(

Phanx 10-11-13 02:14 AM

What? I meant that your code is missing a string, and that's why you're still seeing messages about roles being changed. There are two separate global strings for this:

Code:

ROLE_CHANGED_INFORM_WITH_SOURCE = "%s is now %s. (Changed by %s.)";
^ This string is used when one player changes another player's role, eg. the raid leader right-clicks on someone's unit frame, and sets them as a tank.

Code:

ROLE_CHANGED_INFORM = "%s is now %s.";
^ This string is used when a player sets their own role, or when their role is set automatically, eg. by the LFR system.

Your code only looks for the first string (changed by another player) and not the second one.

Caellian 10-11-13 03:56 AM

Oh i know, i do have both, but those just aren't filtered:

Code:

local topattern = function(text)
        text = gsub(text, "%%%d?$?c", ".+")
        text = gsub(text, "%%%d?$?s", ".+")
        text = gsub(text, "%%%d?$?d", "%%d+")
        text = gsub(text, "([%(%)])", "%%%1")

        return text
end

local patterns = {
        topattern(CLEARED_AFK),
        topattern(MARKED_AFK),
        topattern(CLEARED_DND),
        topattern(MARKED_DND),

        topattern(NEW_TITLE_EARNED),
        topattern(ERR_FRIEND_ONLINE_SS),
        topattern(BN_INLINE_TOAST_FRIEND_ONLINE),
        topattern(ERR_FRIEND_OFFLINE_S),
        topattern(BN_INLINE_TOAST_FRIEND_OFFLINE),
        topattern(ERR_LEARN_SPELL_S),
        topattern(ERR_LEARN_ABILITY_S),
        topattern(ERR_LEARN_PASSIVE_S),
        topattern(ERR_SPELL_UNLEARNED_S),
        topattern(ERR_PET_SPELL_UNLEARNED_S),
        topattern(ERR_GUILD_INTERNAL),
        topattern(ERR_INSTANCE_GROUP_ADDED_S),
        topattern(ERR_INSTANCE_GROUP_REMOVED_S),
        topattern(ERR_BG_PLAYER_LEFT_S),
        topattern(ERR_BG_PLAYER_JOINED_SS),
        topattern(ROLE_CHANGED_INFORM),
        topattern(ROLE_CHANGED_INFORM_WITH_SOURCE),
}


Phanx 10-11-13 08:09 PM

Use debug prints to figure out what the problem is.

Code:

local topattern = function(text)
        text = gsub(text, "%%%d?$?c", ".+")
        text = gsub(text, "%%%d?$?s", ".+")
        text = gsub(text, "%%%d?$?d", "%%d+")
        text = gsub(text, "([%(%)])", "%%%1")
        return text
end

local a = topattern(ROLE_CHANGED_INFORM)
local b = topattern(ROLE_CHANGED_INFORM_WITH_SOURCE)

ChatFrame_AddMessageEventFilter("CHAT_MSG_SYSTEM", function(frame, event, message)
        if strfind(message, " is now ") then
                -- Display the raw message text without transforming escapes:
                print("MESSAGE:", gsub(message, "\124", "\124\124"))
                -- Display the raw patterns + whether they matched:
                print(strfind(message, a) and "MATCH:" or "NO MATCH:", a)
                print(strfind(message, b) and "MATCH:" or "NO MATCH:", b)
        end
end)


Caellian 10-12-13 12:12 AM

Thing is, with this, absolutely nothing gets printed. How can that be ?

Lombra 10-12-13 02:32 AM

The first print is missing a closing parenthesis. You'll want to enable Lua errors to catch these kind of errors easily.

Caellian 10-12-13 02:33 AM

Quote:

Originally Posted by Lombra (Post 285774)
The first print is missing a closing parenthesis. You'll want to enable Lua errors to catch these kind of errors easily.


Well, no, obviously i fixed that before even trying :)

Lombra 10-12-13 02:37 AM

Then "if strfind(message, " is now ") then" must be failing. Print the message too, I guess, just to be sure.

Caellian 10-12-13 03:02 AM

Quote:

Originally Posted by Lombra (Post 285776)
Then "if strfind(message, " is now ") then" must be failing. Print the message too, I guess, just to be sure.

I changed it to "now" for testing purposes, here's the result:

Code:

NO MATCH: .+ is now .+.
NO MATCH: .+ is now .+. %(Changed by .+.%)


Lombra 10-12-13 03:34 AM

And what's the chat message?

Caellian 10-12-13 03:43 AM

Quote:

Originally Posted by Lombra (Post 285779)
And what's the chat message?

That's the part i don't get, since it has nothing to do with it.

Code:

MESSAGE: You are now queued in the Raid Finder. 0
Also, well i'm not sure yet, but it looks like it only doesn't work in battlegrounds, nothing gets printed at all.

Hard to tell for now. Doesn't make much sense tbh.

Rilgamon 10-12-13 04:11 AM

So a chat msg fits your "if" but the whole message is not in your patterns. Whats wrong ?

Caellian 10-12-13 04:15 AM

Quote:

Originally Posted by Rilgamon (Post 285781)
So a chat msg fits your "if" but the whole message is not in your patterns. Whats wrong ?

Well, i assumed those patterns where able to match just about every globalstrings.


All times are GMT -6. The time now is 06:52 AM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI