Thread Tools Display Modes
07-06-12, 02:47 PM   #1
Wishko
A Murloc Raider
AddOn Author - Click to view addons
Join Date: Sep 2010
Posts: 7
How to hook message from chat?

Anybody writes message to chat, for example:

[Guild][Name]: chatmessage

How I can hook message text, sender name and channel name from chat?

Thanks!
P.S.: sorry for my english, it's very bad
  Reply With Quote
07-06-12, 02:54 PM   #2
Haleth
This Space For Rent
 
Haleth's Avatar
Featured
Join Date: Sep 2008
Posts: 1,173
http://wowprogramming.com/docs/events/CHAT_MSG_GUILD

Code:
local f = CreateFrame("Frame")
f:RegisterEvent("CHAT_MSG_GUILD")
f:SetScript("OnEvent", function(self, event, message, sender, ...)
	...
end)
Edit: You'd have to register say, channel, whisper etc. as well if you want those.

Last edited by Haleth : 07-06-12 at 03:02 PM.
  Reply With Quote
07-07-12, 02:46 PM   #3
Wishko
A Murloc Raider
AddOn Author - Click to view addons
Join Date: Sep 2010
Posts: 7
Originally Posted by Haleth View Post
http://wowprogramming.com/docs/events/CHAT_MSG_GUILD

Code:
local f = CreateFrame("Frame")
f:RegisterEvent("CHAT_MSG_GUILD")
f:SetScript("OnEvent", function(self, event, message, sender, ...)
	...
end)
Edit: You'd have to register say, channel, whisper etc. as well if you want those.
Very big thanks!
I can get name of channel (trade, lfg, general), but I can't get name of guild, party, raid, say (recieving nil from channelString, channelNumber, channelName). How to get them?
  Reply With Quote
07-07-12, 02:52 PM   #4
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
Those use different events.
http://wowprogramming.com/docs/events
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh

  Reply With Quote
07-07-12, 05:11 PM   #5
p3lim
A Pyroguard Emberseer
 
p3lim's Avatar
AddOn Author - Click to view addons
Join Date: Feb 2007
Posts: 1,710
What most people do is hook :AddMessage() on all chatframes (except combatlog), and parse that information.

It might be a bit advanced, but if you understand it, here is an example of how I do it in my chat addon:
Lua Code:
  1. local hooks = {}
  2. local abbrev = {
  3.     BATTLEGROUND = 'b',
  4.     OFFICER = 'o',
  5.     GUILD = 'g',
  6.     PARTY = 'p',
  7.     RAID = 'r',
  8. }
  9.  
  10. local function Abbreviate(channel)
  11.     -- Replaces channel name from the table above, or uses channel numbers
  12.     return string.format('|Hchannel:%s|h%s|h', channel, abbrev[channel] or channel:gsub('channel:', ''))
  13. end
  14.  
  15. local function AddMessage(self, message, ...)
  16.     message = message:gsub('|Hchannel:(.-)|h%[(.-)%]|h', Abbreviate)
  17.  
  18.     return hooks[self](self, message, ...)
  19. end
  20.  
  21. for index = 1, NUM_CHAT_WINDOWS do
  22.     if(index ~= 2) then
  23.         local frame = _G['ChatFrame'..index]
  24.         hooks[frame] = frame.AddMessage
  25.         frame.AddMessage = AddMessage
  26.     end
  27. end
  Reply With Quote
07-08-12, 05:04 AM   #6
Wishko
A Murloc Raider
AddOn Author - Click to view addons
Join Date: Sep 2010
Posts: 7
Originally Posted by Seerah View Post
Those use different events.
http://wowprogramming.com/docs/events
I try to use they, but after
RegisterEvent("CHAT_MSG_GUILD")

"channelString", channelNumber, "channelName" returns nil and nothing

Originally Posted by p3lim View Post
What most people do is hook :AddMessage() on all chatframes (except combatlog), and parse that information.

It might be a bit advanced, but if you understand it, here is an example of how I do it in my chat addon:
And I try to use this. When I send a message to the channel (for example 2. Trade) I get this: "2 22: text", it is correct?

Last edited by Wishko : 07-08-12 at 05:15 AM.
  Reply With Quote
07-08-12, 06:28 AM   #7
Haleth
This Space For Rent
 
Haleth's Avatar
Featured
Join Date: Sep 2008
Posts: 1,173
Pretty sure that channel info is only returned for a channel event (general, trade, etc). You already know where the message was received if it's a guild message.
  Reply With Quote
07-09-12, 01:32 AM   #8
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Wishko View Post
I try to use they, but after
RegisterEvent("CHAT_MSG_GUILD")

"channelString", channelNumber, "channelName" returns nil and nothing
You need to receive those arguments in your event handler. Different events pass different arguments. There is no "channelNumber" argument with the "CHAT_MSG_GUILD" event because guild chat does not have a number; only numbered channels like [2. Trade] have numbers.

If you want more specific help, you will need to show us your code, as is clearly stated in the only sticky thread at the top of this forum.
__________________
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
07-09-12, 02:31 PM   #9
Wishko
A Murloc Raider
AddOn Author - Click to view addons
Join Date: Sep 2010
Posts: 7
Lua Code:
  1. Button:RegisterEvent("CHAT_MSG_GUILD")
  2. Button:RegisterEvent("CHAT_MSG_OFFICER")
  3. Button:RegisterEvent("CHAT_MSG_BATTLEGROUND")
  4. Button:RegisterEvent("CHAT_MSG_BATTLEGROUND_LEADER")
  5. Button:RegisterEvent("CHAT_MSG_PARTY")
  6. Button:RegisterEvent("CHAT_MSG_RAID_LEADER")
  7. Button:RegisterEvent("CHAT_MSG_RAID")
  8. Button:RegisterEvent("CHAT_MSG_WHISPER")
  9. Button:RegisterEvent("CHAT_MSG_BN_WHISPER")
  10. Button:RegisterEvent("CHAT_MSG_CHANNEL")
  11. Button:RegisterEvent("CHAT_MSG_SAY")
  12.  
  13. Button:SetScript("OnEvent", function(self, event, msg, sender, _, chanString, _, _, _, chanNumber, chanName)
  14.     if message ~= nil then
  15.     local mas = {"!mop","!mists","!pandaria","!panda"}
  16.        for i=1,#mas do
  17.            local startPos, endPos = string.find(msg,mas[i]);
  18.            if startPos ~= nil then
  19.              if string.sub(msg,startPos,endPos) == mas[i] then
  20.                 if chanNumber > 0 then SendChatMessage(Report,"CHANNEL",nil,chanNumber) else SendChatMessage(Report,"GUILD")
  21.                end
  22.              end
  23.            end
  24.          end

I try to use this and can hook/send message to any channel, but I don't know how to distinguish message from SAY from message of GUILD
  Reply With Quote
07-09-12, 02:40 PM   #10
Haleth
This Space For Rent
 
Haleth's Avatar
Featured
Join Date: Sep 2008
Posts: 1,173
You can check if the event is CHAT_MSG_SAY or CHAT_MSG_GUILD (or something else) using the 'event' parameter.

Mind you, what you are doing is not a good idea. The way it is now, -everyone- running your addon will respond to this query - that can get quite spammy. You should allow people running the addon to send the info manually instead, or simply only register whispers.

Last edited by Haleth : 07-09-12 at 02:49 PM.
  Reply With Quote
07-09-12, 02:55 PM   #11
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Another major problem with your code is that you are creating a new table every time you receive any chat message. Creating tables is quite expensive in Lua; your code basically has a memory leak, and will consume endlessly increasing amounts of memory.

Perhaps you should describe what you actually want to do (in words, not with code), so we can suggest the best way to do it.
__________________
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
07-09-12, 03:06 PM   #12
Wishko
A Murloc Raider
AddOn Author - Click to view addons
Join Date: Sep 2010
Posts: 7
Originally Posted by Haleth View Post
You can check if the event is CHAT_MSG_SAY or CHAT_MSG_GUILD (or something else) using the 'event' parameter.

Mind you, what you are doing is not a good idea. The way it is now, -everyone- running your addon will respond to this query - that can get quite spammy. You should allow people running the addon to send the info manually instead, or simply only register whispers.
Thanks!
This addon can send the information manually, but I want to add such a feature so people can get information without my participation. And I do not think that many people will be spamming requests, also this feature can be disabled.
But in any case, I'll think about it.

Another major problem with your code is that you are creating a new table every time you receive any chat message. Creating tables is quite expensive in Lua; your code basically has a memory leak, and will consume endlessly increasing amounts of memory.

Perhaps you should describe what you actually want to do (in words, not with code), so we can suggest the best way to do it.
Oh, it is a little problem for me (english is not my native language).

I want an Addon send a "message" to the channel on which someone wrote "passphrase" (in my addon: "! Mop", "! Mists", "! Pandaria", "! Panda")

Like this:
[Guild][Player]: !mop
[Guild][MyAddon]: message

Last edited by Wishko : 07-09-12 at 03:15 PM.
  Reply With Quote
07-09-12, 04:06 PM   #13
Haleth
This Space For Rent
 
Haleth's Avatar
Featured
Join Date: Sep 2008
Posts: 1,173
As phanx said, there is no reason to define your table inside your function because it will simply be created again and again. Put it outside of your function - there'll be no change in functionality.

What I'd also suggest is not iterating over your table to see if your msg argument matches the contents of your table at that index.

Instead, declare a key-value table like this:

Code:
local mas = {
	["!mop"] = true,
	["!mists"] = true,
	["!pandaria"] = true,
	["!panda"] = true
}
Then, you can check simply check if the message is valid using this:

Code:
if mas[msg] then
	-- table contains the string
end
  Reply With Quote
07-10-12, 04:17 AM   #14
Wishko
A Murloc Raider
AddOn Author - Click to view addons
Join Date: Sep 2010
Posts: 7
Originally Posted by Haleth View Post
Then, you can check simply check if the message is valid using this:

Code:
if mas[msg] then
	-- table contains the string
end
How I can get a number of key value (msg) in table (mas)?
It's for this:
local startPos, endPos = string.find(msg,mas[i]);
if string.sub(msg,startPos,endPos) == mas[i] then
  Reply With Quote
07-10-12, 05:06 AM   #15
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
You do not need to use string.find, since it does not matter where in the message the keyword is located, only that it is in the keyrord.

Code:
if mas[msg] then
    -- the string msg is a key in the table mas, eg. the message could be "!panda" or "!mop"
end
You could also add some "safety checks" like changing the message to all-lowercase, and removing leading and trailing spaces before looking it up in the table:
Code:
msg = msg:lower():trim()
if mas[msg] then
    -- the string msg is a key in the table mas, eg. the message could be "!panda" or "!mop"
end
If you want to respond to messages that contain a keyword and other text, you can use do this:
Code:
msg = msg:lower()
for keyword in pairs(mas) do
    if msg:match(keyword) then
        -- the message contains this keyword
        break
    end
end
Again, lowercasing the string is important, since users might type "!MOP" or "!MoP" or "!mOP" or "!mop" or any combination, and you don't want to have to list every possible combination in your table. Finally, after you find the keyword, you should break out of the loop so you don't waste CPU time looking for a keyword after you already found one!

If you want to count how many keywords are in the message:
Code:
msg = msg:lower()
local count = 0
for keyword in pairs(mas) do
    if message:match(keyword) then
        count = count + 1
    end
end
-- the message contains count keywords
If you only want to identify messages that begin with a keyword:
Code:
msg = msg:lower():trim()
local firstWord = msg:match("^[^%s+]")
if mas[firstWord] then
    -- the message starts with the keyword firstWord
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.
  Reply With Quote
07-10-12, 01:36 PM   #16
Wishko
A Murloc Raider
AddOn Author - Click to view addons
Join Date: Sep 2010
Posts: 7
Lua Code:
  1. msg = msg:lower()
  2. for keyword in pairs(mas) do
  3.     if msg:match(keyword) then
  4.         -- the message contains this keyword
  5.         break
  6.     end
  7. end
Oh, very-very big thanks! I used this and it works perfectly!
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » How to hook message from chat?


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