WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   How to hook message from chat? (https://www.wowinterface.com/forums/showthread.php?t=43655)

Wishko 07-06-12 02:47 PM

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 :(

Haleth 07-06-12 02:54 PM

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.

Wishko 07-07-12 02:46 PM

Quote:

Originally Posted by Haleth (Post 257765)
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?

Seerah 07-07-12 02:52 PM

Those use different events.
http://wowprogramming.com/docs/events

p3lim 07-07-12 05:11 PM

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

Wishko 07-08-12 05:04 AM

Quote:

Originally Posted by Seerah (Post 257846)
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 :(

Quote:

Originally Posted by p3lim (Post 257862)
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?

Haleth 07-08-12 06:28 AM

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.

Phanx 07-09-12 01:32 AM

Quote:

Originally Posted by Wishko (Post 257883)
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.

Wishko 07-09-12 02:31 PM

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

Haleth 07-09-12 02:40 PM

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.

Phanx 07-09-12 02:55 PM

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.

Wishko 07-09-12 03:06 PM

Quote:

Originally Posted by Haleth (Post 257982)
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.

Quote:

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

Haleth 07-09-12 04:06 PM

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


Wishko 07-10-12 04:17 AM

Quote:

Originally Posted by Haleth (Post 257987)
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:
Quote:

local startPos, endPos = string.find(msg,mas[i]);
Quote:

if string.sub(msg,startPos,endPos) == mas[i] then

Phanx 07-10-12 05:06 AM

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


Wishko 07-10-12 01:36 PM

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! ;)


All times are GMT -6. The time now is 09:22 AM.

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