277 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			277 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
local _, shared = ...
 | 
						|
---@cast shared HeimdallShared
 | 
						|
 | 
						|
---@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>
 | 
						|
 | 
						|
local ModuleName = "Inviter"
 | 
						|
 | 
						|
---@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.dumpTable(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,
 | 
						|
}
 |