388 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			388 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
local _, shared = ...
 | 
						||
---@cast shared HeimdallShared
 | 
						||
local ModuleName = "Commander"
 | 
						||
 | 
						||
---@class HeimdallCommanderConfig
 | 
						||
---@field enabled boolean
 | 
						||
---@field debug boolean
 | 
						||
---@field channels string[]
 | 
						||
---@field commander string
 | 
						||
---@field commands table<string, boolean>
 | 
						||
 | 
						||
local helpMessages = {
 | 
						||
	ru = {
 | 
						||
		"1) who - пишет вам никнеймы текущих врагов и локу.",
 | 
						||
		"2) classes - покажет классы врагов и число.",
 | 
						||
		"3) howmany - общее число врагов (дурик 4 . огри 2 ) ",
 | 
						||
		"4) + - атоинвайт в сбор пати и сброса кд.",
 | 
						||
		"5) ++ -автоинвайт в пати аликов (если нужен рефрак)",
 | 
						||
		"6 ) note Никнейм текст - добавление заметки.",
 | 
						||
		"7) note Никнейм - посмотреть последние заметки.",
 | 
						||
		"8) note Никнейм 5 - посмотреть конкретную заметку.",
 | 
						||
		"9) note Никнейм 1..5 - посмотреть заметки от 1 до 5",
 | 
						||
		"10) note Никнейм delete 1 - удалить заметку номер 1",
 | 
						||
		"11) note Никнейм delete 1..5 - удалить заметки 1 до 5",
 | 
						||
	},
 | 
						||
	en = {
 | 
						||
		"1) who - reports currently tracked stinkies in orgrimmar and durotar",
 | 
						||
		"2) classes - reports stinkies grouped by class",
 | 
						||
		"3) howmany - reports stinkies grouped by zone",
 | 
						||
		"4) + - automatically invites to group with duel rogue for cd reset",
 | 
						||
		"5) ++ - automatically invites to alliance group",
 | 
						||
		"6) note <name> <note> - adds a note for the specified character.",
 | 
						||
		"7) note <name> - lists the last N notes for the character.",
 | 
						||
		"8) note <name> i - lists the i-th note for the character.",
 | 
						||
		"9) note <name> i..j - lists notes from i to j for the character.",
 | 
						||
		"10) note <name> delete i - deletes the i-th note for the character.",
 | 
						||
		"11) note <name> delete i..j - deletes notes from i to j for the character.",
 | 
						||
	},
 | 
						||
}
 | 
						||
 | 
						||
---@class Commander
 | 
						||
shared.Commander = {
 | 
						||
	Init = function()
 | 
						||
		---@param text string
 | 
						||
		---@param size number
 | 
						||
		---@return string[]
 | 
						||
		local function Partition(text, size)
 | 
						||
			local words = {}
 | 
						||
			for word in text:gmatch("[^,]+") do
 | 
						||
				words[#words + 1] = word
 | 
						||
			end
 | 
						||
 | 
						||
			local ret = {}
 | 
						||
			local currentChunk = ""
 | 
						||
 | 
						||
			for _, word in ipairs(words) do
 | 
						||
				if #currentChunk + #word + 1 <= size then
 | 
						||
					currentChunk = currentChunk .. (currentChunk == "" and word or " " .. word)
 | 
						||
				else
 | 
						||
					if #currentChunk > 0 then ret[#ret + 1] = currentChunk end
 | 
						||
					currentChunk = word
 | 
						||
				end
 | 
						||
			end
 | 
						||
 | 
						||
			if #currentChunk > 0 then ret[#ret + 1] = currentChunk end
 | 
						||
 | 
						||
			return ret
 | 
						||
		end
 | 
						||
		---@param arr table<string, Player>
 | 
						||
		---@return string[]
 | 
						||
		local function Count(arr)
 | 
						||
			local ret = {}
 | 
						||
			for _, player in pairs(arr) do
 | 
						||
				if shared.Whoer.ShouldNotifyForZone(player.zone) then ret[player.zone] = (ret[player.zone] or 0) + 1 end
 | 
						||
			end
 | 
						||
			local text = {}
 | 
						||
			for zone, count in pairs(ret) do
 | 
						||
				text[#text + 1] = string.format("%s: %d", zone, count)
 | 
						||
			end
 | 
						||
			return text
 | 
						||
		end
 | 
						||
		---@param arr table<string, Player>
 | 
						||
		---@return string[]
 | 
						||
		local function CountPartitioned(arr)
 | 
						||
			local count = Count(arr)
 | 
						||
			local text = {}
 | 
						||
			---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack
 | 
						||
			for _, line in pairs(Partition(strjoin(", ", unpack(count)), 200)) do
 | 
						||
				text[#text + 1] = line
 | 
						||
			end
 | 
						||
			return text
 | 
						||
		end
 | 
						||
		---@param arr table<string, Player>
 | 
						||
		---@return string[]
 | 
						||
		local function Who(arr)
 | 
						||
			local ret = {}
 | 
						||
			for _, player in pairs(arr) do
 | 
						||
				if shared.Whoer.ShouldNotifyForZone(player.zone) then
 | 
						||
					ret[#ret + 1] = string.format(
 | 
						||
						"%s/%s (%s) %s",
 | 
						||
						player.name,
 | 
						||
						player.class,
 | 
						||
						player.zone,
 | 
						||
						player.stinky and "(!!!!)" or ""
 | 
						||
					)
 | 
						||
				end
 | 
						||
			end
 | 
						||
			if Heimdall_Data.config.commander.debug then
 | 
						||
				print(string.format("[%s] Command result: %s", ModuleName, strjoin(", ", unpack(ret))))
 | 
						||
			end
 | 
						||
			return ret
 | 
						||
		end
 | 
						||
		---@param arr table<string, Player>
 | 
						||
		---@return string[]
 | 
						||
		local function WhoPartitioned(arr)
 | 
						||
			local who = Who(arr)
 | 
						||
			local text = {}
 | 
						||
			---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack
 | 
						||
			for _, line in pairs(Partition(strjoin(", ", unpack(who)), 200)) do
 | 
						||
				text[#text + 1] = "who: " .. line
 | 
						||
			end
 | 
						||
			return text
 | 
						||
		end
 | 
						||
		---@param arr table<string, Player>
 | 
						||
		---@return string[]
 | 
						||
		local function CountClass(arr)
 | 
						||
			local ret = {}
 | 
						||
			for _, player in pairs(arr) do
 | 
						||
				if shared.Whoer.ShouldNotifyForZone(player.zone) then
 | 
						||
					ret[player.class] = (ret[player.class] or 0) + 1
 | 
						||
				end
 | 
						||
			end
 | 
						||
			local text = {}
 | 
						||
			for class, count in pairs(ret) do
 | 
						||
				text[#text + 1] = string.format("%s: %d", class, count)
 | 
						||
			end
 | 
						||
			if Heimdall_Data.config.commander.debug then
 | 
						||
				print(string.format("[%s] Message text: %s", ModuleName, strjoin(", ", unpack(text))))
 | 
						||
			end
 | 
						||
			return text
 | 
						||
		end
 | 
						||
		---@param arr table<string, Player>
 | 
						||
		---@return string[]
 | 
						||
		local function CountClassPartitioned(arr)
 | 
						||
			local countClass = CountClass(arr)
 | 
						||
			local text = {}
 | 
						||
			---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack
 | 
						||
			for _, line in pairs(Partition(strjoin(", ", unpack(countClass)), 200)) do
 | 
						||
				text[#text + 1] = line
 | 
						||
			end
 | 
						||
			return text
 | 
						||
		end
 | 
						||
		local function CountClassPartitionedStinkies()
 | 
						||
			if Heimdall_Data.config.commander.debug then
 | 
						||
				print(string.format("[%s] Executing: CountClassPartitionedStinkies", ModuleName))
 | 
						||
			end
 | 
						||
			local res = CountClassPartitioned(HeimdallStinkies)
 | 
						||
			if #res == 0 then return { "No stinkies found" } end
 | 
						||
			return res
 | 
						||
		end
 | 
						||
		local function WhoPartitionedStinkies()
 | 
						||
			if Heimdall_Data.config.commander.debug then
 | 
						||
				print(string.format("[%s] Executing: WhoPartitionedStinkies", ModuleName))
 | 
						||
				shared.dumpTable(HeimdallStinkies)
 | 
						||
			end
 | 
						||
			local res = WhoPartitioned(HeimdallStinkies)
 | 
						||
			if #res == 0 then return { "No stinkies found" } end
 | 
						||
			return res
 | 
						||
		end
 | 
						||
		local function CountPartitionedStinkies()
 | 
						||
			if Heimdall_Data.config.commander.debug then
 | 
						||
				print(string.format("[%s] Executing: CountPartitionedStinkies", ModuleName))
 | 
						||
			end
 | 
						||
			local res = CountPartitioned(HeimdallStinkies)
 | 
						||
			if #res == 0 then return { "No stinkies found" } end
 | 
						||
			return res
 | 
						||
		end
 | 
						||
		local function HelpRu()
 | 
						||
			if Heimdall_Data.config.commander.debug then print(string.format("[%s] Executing: HelpRu", ModuleName)) end
 | 
						||
			return helpMessages.ru
 | 
						||
		end
 | 
						||
		local function HelpEn()
 | 
						||
			if Heimdall_Data.config.commander.debug then print(string.format("[%s] Executing: HelpEn", ModuleName)) end
 | 
						||
			return helpMessages.en
 | 
						||
		end
 | 
						||
		local groupInviteFrame = CreateFrame("Frame")
 | 
						||
		groupInviteFrame:SetScript("OnEvent", function(self, event, ...)
 | 
						||
			if Heimdall_Data.config.commander.debug then print(string.format("[%s] Event received", ModuleName)) end
 | 
						||
			AcceptGroup()
 | 
						||
			groupInviteFrame:UnregisterEvent("PARTY_INVITE_REQUEST")
 | 
						||
			C_Timer.NewTimer(0.1, function()
 | 
						||
				if Heimdall_Data.config.commander.debug then
 | 
						||
					print(string.format("[%s] Click event triggered", ModuleName))
 | 
						||
				end
 | 
						||
				_G["StaticPopup1Button1"]:Click()
 | 
						||
			end, 1)
 | 
						||
		end)
 | 
						||
		local function JoinGroup()
 | 
						||
			if Heimdall_Data.config.commander.debug then
 | 
						||
				print(string.format("[%s] JoinGroup command received", ModuleName))
 | 
						||
			end
 | 
						||
			groupInviteFrame:RegisterEvent("PARTY_INVITE_REQUEST")
 | 
						||
			C_Timer.NewTimer(10, function() groupInviteFrame:UnregisterEvent("PARTY_INVITE_REQUEST") end, 1)
 | 
						||
			return { "+" }
 | 
						||
		end
 | 
						||
		local function LeaveGroup()
 | 
						||
			if Heimdall_Data.config.commander.debug then
 | 
						||
				print(string.format("[%s] LeaveGroup command received", ModuleName))
 | 
						||
			end
 | 
						||
			LeaveParty()
 | 
						||
			return {}
 | 
						||
		end
 | 
						||
		---@param target string
 | 
						||
		local function FollowTarget(target)
 | 
						||
			if Heimdall_Data.config.commander.debug then
 | 
						||
				print(string.format("[%s] Following target: %s", ModuleName, target))
 | 
						||
			end
 | 
						||
			if not target then return end
 | 
						||
			FollowUnit(target)
 | 
						||
			return {}
 | 
						||
		end
 | 
						||
 | 
						||
		---@param args string[]
 | 
						||
		local function MacroTarget(args)
 | 
						||
			if Heimdall_Data.config.commander.debug then
 | 
						||
				---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack
 | 
						||
				print(string.format("[%s] Macroing: %s", ModuleName, strjoin(" ", unpack(args))))
 | 
						||
			end
 | 
						||
			if #args < 2 or #args % 2 ~= 0 then
 | 
						||
				if #args < 2 or #args % 2 ~= 0 then
 | 
						||
					if Heimdall_Data.config.commander.debug then
 | 
						||
						print(string.format("[%s] Invalid number of arguments for MacroTarget", ModuleName))
 | 
						||
					end
 | 
						||
					return {}
 | 
						||
				end
 | 
						||
			end
 | 
						||
			table.remove(args, 1)
 | 
						||
 | 
						||
			for i = 1, #args do
 | 
						||
				local stinky = strtrim(args[i])
 | 
						||
				local name = stinky:match("([^/]+)")
 | 
						||
				local class = stinky:match("/([^ $]+)")
 | 
						||
				if Heimdall_Data.config.commander.debug then
 | 
						||
					print(string.format("[%s] Adding stinky: %s/%s", ModuleName, name, tostring(class)))
 | 
						||
				end
 | 
						||
				shared.StinkyTracker.Track({
 | 
						||
					name = name,
 | 
						||
					class = class or "unknown",
 | 
						||
					seenAt = GetTime(),
 | 
						||
					hostile = true,
 | 
						||
				})
 | 
						||
				if Heimdall_Data.config.commander.debug then
 | 
						||
					print(string.format("[%s] Added stinky: %s/%s", ModuleName, name, tostring(class)))
 | 
						||
				end
 | 
						||
			end
 | 
						||
			return {}
 | 
						||
		end
 | 
						||
 | 
						||
		---@param args string[]
 | 
						||
		local function IgnoreMacroTarget(args)
 | 
						||
			if Heimdall_Data.config.commander.debug then
 | 
						||
				---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack
 | 
						||
				print(string.format("[%s] Macroing: %s", ModuleName, strjoin(" ", unpack(args))))
 | 
						||
			end
 | 
						||
			if #args < 1 then
 | 
						||
				if Heimdall_Data.config.commander.debug then
 | 
						||
					print(string.format("[%s] Invalid number of arguments for IgnoreMacroTarget", ModuleName))
 | 
						||
				end
 | 
						||
				return {}
 | 
						||
			end
 | 
						||
			table.remove(args, 1)
 | 
						||
 | 
						||
			for i = 1, #args do
 | 
						||
				local stinky = strtrim(args[i])
 | 
						||
				local name = stinky:match("([^/]+)")
 | 
						||
				if Heimdall_Data.config.commander.debug then
 | 
						||
					print(string.format("[%s] Ignoring stinky: %s", ModuleName, name))
 | 
						||
				end
 | 
						||
				shared.StinkyTracker.Ignore(name)
 | 
						||
			end
 | 
						||
			return {}
 | 
						||
		end
 | 
						||
 | 
						||
		---@class Command
 | 
						||
		---@field keywordRe string
 | 
						||
		---@field commanderOnly boolean
 | 
						||
		---@field callback fun(...: any): string[]
 | 
						||
 | 
						||
		local commands = {
 | 
						||
			{ keywordRe = "^who$", commanderOnly = false, callback = WhoPartitionedStinkies },
 | 
						||
			{ keywordRe = "^howmany$", commanderOnly = false, callback = CountPartitionedStinkies },
 | 
						||
			{ keywordRe = "^classes$", commanderOnly = false, callback = CountClassPartitionedStinkies },
 | 
						||
			{ keywordRe = "^help$", commanderOnly = false, callback = HelpRu },
 | 
						||
			{ keywordRe = "^helpen$", commanderOnly = false, callback = HelpEn },
 | 
						||
			{ keywordRe = "^joingroup$", commanderOnly = false, callback = JoinGroup },
 | 
						||
			{ keywordRe = "^leavegroup$", commanderOnly = false, callback = LeaveGroup },
 | 
						||
			{ keywordRe = "^follow$", commanderOnly = false, callback = FollowTarget },
 | 
						||
			{ keywordRe = "^macro", commanderOnly = false, callback = MacroTarget },
 | 
						||
			{ keywordRe = "^ignore", commanderOnly = false, callback = IgnoreMacroTarget },
 | 
						||
		}
 | 
						||
 | 
						||
		local commanderChannelFrame = CreateFrame("Frame")
 | 
						||
		commanderChannelFrame:RegisterEvent("CHAT_MSG_CHANNEL")
 | 
						||
		commanderChannelFrame:SetScript("OnEvent", function(self, event, msg, sender, ...)
 | 
						||
			--if Heimdall_Data.config.commander.debug then
 | 
						||
			--	print(string.format("[%s] Event received", ModuleName))
 | 
						||
			--	shared.dumpTable(Heimdall_Data.config.commander)
 | 
						||
			--end
 | 
						||
			if not Heimdall_Data.config.commander.enabled then
 | 
						||
				--if Heimdall_Data.config.commander.debug then
 | 
						||
				--	print(string.format("[%s] Module disabled, ignoring event", ModuleName))
 | 
						||
				--end
 | 
						||
				return
 | 
						||
			end
 | 
						||
			local channelId = select(6, ...)
 | 
						||
			local _, channelname = GetChannelName(channelId)
 | 
						||
			local ok = false
 | 
						||
			for _, channel in pairs(Heimdall_Data.config.commander.channels) do
 | 
						||
				if channel == channelname then
 | 
						||
					ok = true
 | 
						||
					break
 | 
						||
				end
 | 
						||
			end
 | 
						||
			if not ok then
 | 
						||
				if Heimdall_Data.config.commander.debug then
 | 
						||
					print(
 | 
						||
						string.format(
 | 
						||
							"[%s] Channel name '%s' does not match any of the channels '%s'",
 | 
						||
							ModuleName,
 | 
						||
							channelname,
 | 
						||
							table.concat(Heimdall_Data.config.commander.channels, ", ")
 | 
						||
						)
 | 
						||
					)
 | 
						||
				end
 | 
						||
				return
 | 
						||
			end
 | 
						||
 | 
						||
			sender = string.match(sender, "^[^-]+")
 | 
						||
			if Heimdall_Data.config.commander.debug then
 | 
						||
				print(string.format("[%s] Message from: %s", ModuleName, sender))
 | 
						||
				shared.dumpTable(Heimdall_Data.config.commander)
 | 
						||
			end
 | 
						||
 | 
						||
			for _, command in ipairs(commands) do
 | 
						||
				local enabled = Heimdall_Data.config.commander.commands[command.keywordRe] == true or false
 | 
						||
				if Heimdall_Data.config.commander.debug then
 | 
						||
					print(
 | 
						||
						string.format("[%s] Command match: %s = %s", ModuleName, command.keywordRe, tostring(enabled))
 | 
						||
					)
 | 
						||
				end
 | 
						||
				if
 | 
						||
					enabled
 | 
						||
					and (
 | 
						||
						not command.commanderOnly
 | 
						||
						-- if Heimdall_Data.config.commander.debug then print(string.format("[%s] Ignoring command, sender %s not commander %s", ModuleName, sender, Heimdall_Data.config.commander.commander)) end
 | 
						||
 | 
						||
						or (command.commanderOnly and sender == Heimdall_Data.config.commander.commander)
 | 
						||
					)
 | 
						||
				then
 | 
						||
					if msg:match(command.keywordRe) then
 | 
						||
						---@diagnostic disable-next-line: redundant-parameter Currently luals does not support variadic functions as a @field
 | 
						||
						local messages = command.callback({ strsplit(",", msg) })
 | 
						||
						if Heimdall_Data.config.commander.debug then
 | 
						||
							print(string.format("[%s] Messages to send: %s", ModuleName))
 | 
						||
							shared.dumpTable(messages)
 | 
						||
						end
 | 
						||
						for _, message in ipairs(messages) do
 | 
						||
							---@type Message
 | 
						||
							local returnmsg = {
 | 
						||
								channel = "C",
 | 
						||
								data = channelname,
 | 
						||
								message = message,
 | 
						||
							}
 | 
						||
							if Heimdall_Data.config.commander.debug then
 | 
						||
								print(string.format("[%s] Queuing message", ModuleName))
 | 
						||
								shared.dumpTable(msg)
 | 
						||
							end
 | 
						||
							--table.insert(shared.messenger.queue, msg)
 | 
						||
							table.insert(shared.networkMessenger.queue, returnmsg)
 | 
						||
						end
 | 
						||
					end
 | 
						||
				end
 | 
						||
			end
 | 
						||
		end)
 | 
						||
 | 
						||
		print("[Heimdall] Commander module loaded")
 | 
						||
	end,
 | 
						||
}
 |