Thread Tools Display Modes
10-02-13, 01:03 AM   #1
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
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
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
10-02-13, 02:06 AM   #2
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
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)
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.

Last edited by Phanx : 10-02-13 at 02:13 AM.
  Reply With Quote
10-02-13, 03:39 AM   #3
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
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 ?
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
10-02-13, 03:49 AM   #4
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
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. :/
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
10-02-13, 04:06 AM   #5
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
Did that, but:

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

Ah well, that's no big deal, thanks a lot anyway !
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
10-02-13, 07:40 AM   #6
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
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)
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
10-02-13, 02:41 PM   #7
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
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.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
10-10-13, 11:45 AM   #8
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
Originally Posted by Phanx View Post
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
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
10-11-13, 02:14 AM   #9
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
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.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
10-11-13, 03:56 AM   #10
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
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),
}
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
10-11-13, 08:09 PM   #11
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
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)
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.

Last edited by Phanx : 10-13-13 at 02:34 AM.
  Reply With Quote
10-12-13, 12:12 AM   #12
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
Thing is, with this, absolutely nothing gets printed. How can that be ?
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
10-12-13, 02:32 AM   #13
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
The first print is missing a closing parenthesis. You'll want to enable Lua errors to catch these kind of errors easily.
__________________
Grab your sword and fight the Horde!
  Reply With Quote
10-12-13, 02:33 AM   #14
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
Originally Posted by Lombra View Post
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
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
10-12-13, 02:37 AM   #15
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
Then "if strfind(message, " is now ") then" must be failing. Print the message too, I guess, just to be sure.
__________________
Grab your sword and fight the Horde!
  Reply With Quote
10-12-13, 03:02 AM   #16
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
Originally Posted by Lombra View Post
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 .+.%)
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }

Last edited by Caellian : 10-12-13 at 03:19 AM.
  Reply With Quote
10-12-13, 03:34 AM   #17
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
And what's the chat message?
__________________
Grab your sword and fight the Horde!
  Reply With Quote
10-12-13, 03:43 AM   #18
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
Originally Posted by Lombra View Post
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.
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }

Last edited by Caellian : 10-12-13 at 04:09 AM.
  Reply With Quote
10-12-13, 04:11 AM   #19
Rilgamon
Premium Member
 
Rilgamon's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 822
So a chat msg fits your "if" but the whole message is not in your patterns. Whats wrong ?
__________________
The cataclysm broke the world ... and the pandas could not fix it!
  Reply With Quote
10-12-13, 04:15 AM   #20
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
Originally Posted by Rilgamon View Post
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.
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » pattern matching

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off