276 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			276 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| local _, shared = ...
 | |
| ---@cast shared HeimdallShared
 | |
| local ModuleName = "Inviter"
 | |
| 
 | |
| ---@class HeimdallInviterConfig
 | |
| ---@field enabled boolean
 | |
| ---@field debug boolean
 | |
| ---@field channels string[]
 | |
| ---@field keyword string
 | |
| ---@field allAssist boolean
 | |
| ---@field agentsAssist boolean
 | |
| ---@field throttle number
 | |
| ---@field kickOffline boolean
 | |
| ---@field cleanupInterval number
 | |
| ---@field afkThreshold number
 | |
| ---@field listeningChannel table<string, boolean>
 | |
| 
 | |
| ---@class Inviter
 | |
| shared.Inviter = {
 | |
| 	Init = function()
 | |
| 		-- Fallback for old config
 | |
| 		if type(Heimdall_Data.config.inviter.listeningChannel) == "string" then
 | |
| 			Heimdall_Data.config.inviter.listeningChannel = {
 | |
| 				[Heimdall_Data.config.inviter.listeningChannel] = true,
 | |
| 			}
 | |
| 		end
 | |
| 		---@type Timer
 | |
| 		local updateTimer = nil
 | |
| 
 | |
| 		local function FixGroup()
 | |
| 			if Heimdall_Data.config.inviter.debug then
 | |
| 				print(string.format("[%s] Checking and fixing group configuration", ModuleName))
 | |
| 			end
 | |
| 
 | |
| 			if not IsInRaid() then
 | |
| 				if Heimdall_Data.config.inviter.debug then
 | |
| 					print(string.format("[%s] Converting party to raid", ModuleName))
 | |
| 				end
 | |
| 				ConvertToRaid()
 | |
| 			end
 | |
| 
 | |
| 			if Heimdall_Data.config.inviter.allAssist then
 | |
| 				if Heimdall_Data.config.inviter.debug then
 | |
| 					print(string.format("[%s] Setting all members to assistant", ModuleName))
 | |
| 				end
 | |
| 				SetEveryoneIsAssistant()
 | |
| 			end
 | |
| 
 | |
| 			if Heimdall_Data.config.inviter.agentsAssist then
 | |
| 				if Heimdall_Data.config.inviter.debug then
 | |
| 					print(string.format("[%s] Processing agents for assistant promotion", ModuleName))
 | |
| 				end
 | |
| 
 | |
| 				shared.AgentTracker.ForEach(function(agent)
 | |
| 					if UnitInParty(agent) and not UnitIsGroupLeader(agent) and not UnitIsRaidOfficer(agent) then
 | |
| 						if Heimdall_Data.config.inviter.debug then
 | |
| 							print(string.format("[%s] Promoting agent to assistant: %s", ModuleName, agent))
 | |
| 						end
 | |
| 						PromoteToAssistant(agent, true)
 | |
| 					elseif Heimdall_Data.config.inviter.debug then
 | |
| 						if not UnitInParty(agent) then
 | |
| 							print(string.format("[%s] Agent not in party: %s", ModuleName, agent))
 | |
| 						elseif UnitIsGroupLeader(agent) then
 | |
| 							print(string.format("[%s] Agent is already leader: %s", ModuleName, agent))
 | |
| 						elseif UnitIsRaidOfficer(agent) then
 | |
| 							print(string.format("[%s] Agent is already assistant: %s", ModuleName, agent))
 | |
| 						end
 | |
| 					end
 | |
| 				end)
 | |
| 			end
 | |
| 
 | |
| 			if Heimdall_Data.config.inviter.debug then
 | |
| 				print(string.format("[%s] Group configuration update complete", ModuleName))
 | |
| 			end
 | |
| 		end
 | |
| 
 | |
| 		---@param name string
 | |
| 		---@return Frame?
 | |
| 		local function FindPlayerRaidFrame(name)
 | |
| 			for group = 1, 8 do
 | |
| 				for player = 1, 5 do
 | |
| 					local button = _G[string.format("ElvUF_RaidGroup%dUnitButton%d", group, player)]
 | |
| 					if Heimdall_Data.config.inviter.debug then
 | |
| 						print(string.format("[%s] button = %s", ModuleName, tostring(button)))
 | |
| 					end
 | |
| 
 | |
| 					local unitName = button and button.unit and UnitName(button.unit)
 | |
| 					if Heimdall_Data.config.inviter.debug then
 | |
| 						print(string.format("[%s] unitName = %s", ModuleName, tostring(unitName)))
 | |
| 					end
 | |
| 					if unitName == name then
 | |
| 						if Heimdall_Data.config.inviter.debug then
 | |
| 							print(string.format("[%s] unitName == name", ModuleName))
 | |
| 						end
 | |
| 						return button
 | |
| 					end
 | |
| 				end
 | |
| 			end
 | |
| 			return nil
 | |
| 		end
 | |
| 
 | |
| 		local framePool = {}
 | |
| 		local playerButtons = {}
 | |
| 		setmetatable(playerButtons, { __mode = "kv" })
 | |
| 		---@param players string[]
 | |
| 		local function OverlayKickButtons(players)
 | |
| 			for _, frame in pairs(framePool) do
 | |
| 				frame:Hide()
 | |
| 			end
 | |
| 			for _, name in pairs(players) do
 | |
| 				local frame = FindPlayerRaidFrame(name)
 | |
| 				if frame then
 | |
| 					playerButtons[name] = frame
 | |
| 					-- All of these are ELVUI specific so they won't be in our meta...
 | |
| 					---@diagnostic disable-next-line: undefined-field
 | |
| 					local button = framePool[frame.unit]
 | |
| 						or CreateFrame(
 | |
| 							"Button",
 | |
| 							---@diagnostic disable-next-line: undefined-field
 | |
| 							string.format("HeimdallKickButton%s", frame.unit, frame, "SecureActionButtonTemplate")
 | |
| 						)
 | |
| 					---@diagnostic disable-next-line: undefined-field
 | |
| 					framePool[frame.unit] = button
 | |
| 
 | |
| 					---@diagnostic disable-next-line: undefined-field
 | |
| 					button:SetSize(frame.UNIT_WIDTH / 2, frame.UNIT_HEIGHT / 2)
 | |
| 					button:SetPoint("CENTER", frame, "CENTER", 0, 0)
 | |
| 					button:SetNormalTexture("Interface\\Buttons\\UI-GroupLoot-KickIcon")
 | |
| 					button:SetHighlightTexture("Interface\\Buttons\\UI-GroupLoot-KickIcon")
 | |
| 					button:SetPushedTexture("Interface\\Buttons\\UI-GroupLoot-KickIcon")
 | |
| 					button:SetDisabledTexture("Interface\\Buttons\\UI-GroupLoot-KickIcon")
 | |
| 					button:SetAlpha(0.5)
 | |
| 					button:Show()
 | |
| 					button:SetScript("OnClick", function()
 | |
| 						UninviteUnit(name)
 | |
| 						button:Hide()
 | |
| 					end)
 | |
| 				else
 | |
| 					if Heimdall_Data.config.inviter.debug then
 | |
| 						print(string.format("[%s] Frame for player %s not found", ModuleName, name))
 | |
| 					end
 | |
| 				end
 | |
| 			end
 | |
| 		end
 | |
| 
 | |
| 		---@type table<string, number>
 | |
| 		local groupMembers = {}
 | |
| 		local function CleanGroups()
 | |
| 			if not Heimdall_Data.config.inviter.kickOffline then return end
 | |
| 			print("Cleaning groups")
 | |
| 			local now = GetTime()
 | |
| 			for i = 1, 40 do
 | |
| 				local unit = "raid" .. i
 | |
| 				if UnitExists(unit) then
 | |
| 					local name = UnitName(unit)
 | |
| 					if name then
 | |
| 						-- When we load (into game) we want to consider everyone "online"
 | |
| 						-- In other words everyone we haven't seen before is "online" the first time we see them
 | |
| 						-- This is to avoid kicking people who might not be offline which we don't know because we just logged in
 | |
| 						if not groupMembers[name] then
 | |
| 							groupMembers[name] = now
 | |
| 						else
 | |
| 							local online = UnitIsConnected(unit)
 | |
| 							if online then groupMembers[name] = now end
 | |
| 						end
 | |
| 					end
 | |
| 				end
 | |
| 			end
 | |
| 			local afkPlayers = {}
 | |
| 			for name, time in pairs(groupMembers) do
 | |
| 				if not UnitInParty(name) then
 | |
| 					print(string.format("%s no longer in party", name))
 | |
| 					groupMembers[name] = nil
 | |
| 				else
 | |
| 					if time < now - Heimdall_Data.config.inviter.afkThreshold then
 | |
| 						print(string.format("Kicking %s for being offline", name))
 | |
| 						afkPlayers[#afkPlayers + 1] = name
 | |
| 						-- Blyat this is protected...
 | |
| 						-- UninviteUnit(name)
 | |
| 					end
 | |
| 				end
 | |
| 			end
 | |
| 			OverlayKickButtons(afkPlayers)
 | |
| 		end
 | |
| 		local function Tick()
 | |
| 			CleanGroups()
 | |
| 			C_Timer.NewTimer(Heimdall_Data.config.inviter.cleanupInterval, Tick, 1)
 | |
| 		end
 | |
| 		Tick()
 | |
| 
 | |
| 		local groupRosterUpdateFrame = CreateFrame("Frame")
 | |
| 		groupRosterUpdateFrame:RegisterEvent("GROUP_ROSTER_UPDATE")
 | |
| 		groupRosterUpdateFrame:SetScript("OnEvent", function(self, event, ...)
 | |
| 			if Heimdall_Data.config.inviter.debug then
 | |
| 				print(string.format("[%s] Event received: %s", ModuleName, event))
 | |
| 			end
 | |
| 
 | |
| 			if not Heimdall_Data.config.inviter.enabled then
 | |
| 				if Heimdall_Data.config.inviter.debug then
 | |
| 					print(string.format("[%s] Module disabled, ignoring event", ModuleName))
 | |
| 				end
 | |
| 				return
 | |
| 			end
 | |
| 
 | |
| 			if Heimdall_Data.config.inviter.debug then
 | |
| 				print(string.format("[%s] Group roster changed - Checking configuration", ModuleName))
 | |
| 			end
 | |
| 			if updateTimer then updateTimer:Cancel() end
 | |
| 			updateTimer = C_Timer.NewTimer(Heimdall_Data.config.inviter.throttle, FixGroup)
 | |
| 		end)
 | |
| 
 | |
| 		local inviterChannelFrame = CreateFrame("Frame")
 | |
| 		inviterChannelFrame:RegisterEvent("CHAT_MSG_CHANNEL")
 | |
| 		inviterChannelFrame:SetScript("OnEvent", function(self, event, msg, sender, ...)
 | |
| 			--if Heimdall_Data.config.inviter.debug then
 | |
| 			--	print(string.format("[%s] Chat message received: %s", ModuleName, msg))
 | |
| 			--	shared.dump(Heimdall_Data.config.inviter)
 | |
| 			--end
 | |
| 			if not Heimdall_Data.config.inviter.enabled then return end
 | |
| 			local channelId = select(6, ...)
 | |
| 			local _, channelname = GetChannelName(channelId)
 | |
| 			if Heimdall_Data.config.inviter.debug then
 | |
| 				print(string.format("[%s] Channel name: %s", ModuleName, channelname))
 | |
| 			end
 | |
| 
 | |
| 			local ok = false
 | |
| 			for _, channel in pairs(Heimdall_Data.config.inviter.channels) do
 | |
| 				if channel == channelname then
 | |
| 					ok = true
 | |
| 					break
 | |
| 				end
 | |
| 			end
 | |
| 
 | |
| 			if not ok then
 | |
| 				if Heimdall_Data.config.inviter.debug then
 | |
| 					print(string.format("[%s] Channel name does not match any of the channels", ModuleName))
 | |
| 				end
 | |
| 				return
 | |
| 			end
 | |
| 			if msg == Heimdall_Data.config.inviter.keyword then
 | |
| 				if Heimdall_Data.config.inviter.debug then
 | |
| 					print(string.format("[%s] Inviting %s", ModuleName, sender))
 | |
| 				end
 | |
| 				InviteUnit(sender)
 | |
| 			else
 | |
| 				if Heimdall_Data.config.inviter.debug then
 | |
| 					print(string.format("[%s] Message does not match keyword", ModuleName))
 | |
| 				end
 | |
| 			end
 | |
| 		end)
 | |
| 
 | |
| 		if Heimdall_Data.config.inviter.debug then
 | |
| 			print(
 | |
| 				string.format(
 | |
| 					"[%s] Module initialized - All assist: %s, Agents assist: %s",
 | |
| 					ModuleName,
 | |
| 					tostring(Heimdall_Data.config.inviter.allAssist),
 | |
| 					tostring(Heimdall_Data.config.inviter.agentsAssist)
 | |
| 				)
 | |
| 			)
 | |
| 		end
 | |
| 
 | |
| 		if Heimdall_Data.config.inviter.debug then
 | |
| 			print(
 | |
| 				string.format(
 | |
| 					"[%s] Module initialized - All assist: %s, Agents assist: %s",
 | |
| 					ModuleName,
 | |
| 					tostring(Heimdall_Data.config.inviter.allAssist),
 | |
| 					tostring(Heimdall_Data.config.inviter.agentsAssist)
 | |
| 				)
 | |
| 			)
 | |
| 		end
 | |
| 		print("[Heimdall] Inviter loaded")
 | |
| 	end,
 | |
| }
 |