local Players = game:GetService("Players") local ReplicatedStorage = game:GetService("ReplicatedStorage") local localPlayer = Players.LocalPlayer -- Console logging local function ts() return os.date("!%Y-%m-%d %H:%M:%S") end local function dbg(msg) print(string.format("[ChatLogger][%s] %s", ts(), msg)) end dbg("Initializing client chat logger...") -- Detect executor file APIs (support common aliases) local g = getfenv and getfenv() or _G local _write = rawget(g, "writefile") or rawget(g, "write_file") local _append = rawget(g, "appendfile") or rawget(g, "append_file") local _isfile = rawget(g, "isfile") or rawget(g, "is_file") local _makefolder = rawget(g, "makefolder") or rawget(g, "make_folder") local _isfolder = rawget(g, "isfolder") or rawget(g, "is_folder") local _delfile = rawget(g, "delfile") or rawget(g, "deletefile") local hasWrite = (typeof(_write) == "function") local hasAppend = (typeof(_append) == "function") local hasIsFile = (typeof(_isfile) == "function") local hasMakeFolder = (typeof(_makefolder) == "function") local hasIsFolder = (typeof(_isfolder) == "function") local hasDelFile = (typeof(_delfile) == "function") local saveFolder = "chatlogs" local function ensureFolder() if hasIsFolder and hasMakeFolder then local ok, exists = pcall(function() return _isfolder(saveFolder) end) if not ok or not exists then pcall(function() _makefolder(saveFolder) end) end end end local function defaultFilename() local name = os.date("!%Y-%m-%d_%H-%M-%S") .. ".txt" if hasIsFolder then local ok, exists = pcall(function() return _isfolder(saveFolder) end) if ok and exists then return string.format("%s/%s", saveFolder, name) end end -- fallback: save in root if folder API not available return "chatlog_" .. name end dbg(string.format("File API detected: write=%s append=%s isfile=%s makefolder=%s isfolder=%s", tostring(hasWrite), tostring(hasAppend), tostring(hasIsFile), tostring(hasMakeFolder), tostring(hasIsFolder))) -- GUI theme local COLOR_BG = Color3.fromRGB(18, 18, 20) local COLOR_PANEL = COLOR_BG local COLOR_ACCENT = Color3.fromRGB(0, 170, 255) local COLOR_TEXT = Color3.fromRGB(235, 235, 240) local COLOR_MUTED = Color3.fromRGB(160, 160, 170) local COLOR_HIGHLIGHT = Color3.fromRGB(80, 180, 255) -- Build GUI local screenGui = Instance.new("ScreenGui") screenGui.Name = "ChatLoggerGUI" screenGui.ResetOnSpawn = false screenGui.IgnoreGuiInset = false screenGui.Parent = localPlayer:WaitForChild("PlayerGui") -- Clipboard helpers (support multiple executor APIs) local function hasClipboardAPI() local g = getfenv and getfenv() or _G if typeof(rawget(g, "setclipboard")) == "function" then return true end if typeof(rawget(g, "set_clipboard")) == "function" then return true end if typeof(rawget(g, "toclipboard")) == "function" then return true end if typeof(rawget(g, "setrbxclipboard")) == "function" then return true end local synTbl = rawget(g, "syn") if typeof(synTbl) == "table" then if typeof(rawget(synTbl, "write_clipboard")) == "function" then return true end if typeof(rawget(synTbl, "setclipboard")) == "function" then return true end end local clipTbl = rawget(g, "Clipboard") if typeof(clipTbl) == "table" then if typeof(rawget(clipTbl, "set")) == "function" then return true end if typeof(rawget(clipTbl, "Set")) == "function" then return true end if typeof(rawget(clipTbl, "copy")) == "function" then return true end if typeof(rawget(clipTbl, "settext")) == "function" then return true end if typeof(rawget(clipTbl, "SetText")) == "function" then return true end end return false end local function trySetClipboard(text) local s = tostring(text or "") -- Direct globals first (common in executors) if typeof(setclipboard) == "function" and pcall(function() setclipboard(s) end) then return true end if typeof(set_clipboard) == "function" and pcall(function() set_clipboard(s) end) then return true end if typeof(toclipboard) == "function" and pcall(function() toclipboard(s) end) then return true end if typeof(setrbxclipboard) == "function" and pcall(function() setrbxclipboard(s) end) then return true end -- getgenv support local genv = typeof(getgenv) == "function" and getgenv() or nil if genv then if typeof(rawget(genv, "setclipboard")) == "function" and pcall(function() rawget(genv, "setclipboard")(s) end) then return true end if typeof(rawget(genv, "set_clipboard")) == "function" and pcall(function() rawget(genv, "set_clipboard")(s) end) then return true end if typeof(rawget(genv, "toclipboard")) == "function" and pcall(function() rawget(genv, "toclipboard")(s) end) then return true end if typeof(rawget(genv, "setrbxclipboard")) == "function" and pcall(function() rawget(genv, "setrbxclipboard")(s) end) then return true end end -- Environment/rawget fallbacks local g = getfenv and getfenv() or _G local candidates = {} table.insert(candidates, rawget(g, "setclipboard")) table.insert(candidates, rawget(g, "set_clipboard")) table.insert(candidates, rawget(g, "toclipboard")) table.insert(candidates, rawget(g, "setrbxclipboard")) local synTbl = rawget(g, "syn") if typeof(synTbl) == "table" then local synWrite = rawget(synTbl, "write_clipboard") or rawget(synTbl, "setclipboard") if typeof(synWrite) == "function" then table.insert(candidates, function(t) synWrite(tostring(t or "")) end) end end local clipTbl = rawget(g, "Clipboard") if typeof(clipTbl) == "table" then local methods = { rawget(clipTbl, "set"), rawget(clipTbl, "Set"), rawget(clipTbl, "copy"), rawget(clipTbl, "settext"), rawget(clipTbl, "SetText") } for _, mf in ipairs(methods) do if typeof(mf) == "function" then table.insert(candidates, function(t) local s = tostring(t or "") local ok = pcall(function() mf(clipTbl, s) end) if not ok then mf(s) end end) end end end for _, f in ipairs(candidates) do if typeof(f) == "function" then local ok = pcall(function() f(s) end) if ok then return true end end end return false end local function copyText(text) if trySetClipboard(text) then dbg("Copied to clipboard") toast("copied to clipboard") return true else toast("Clipboard unavailable in this executor") dbg("Clipboard API not available or copy failed") return false end end local main = Instance.new("Frame") main.Name = "Main" main.BackgroundColor3 = COLOR_BG main.BorderSizePixel = 0 main.AnchorPoint = Vector2.new(1, 1) main.Position = UDim2.new(1, -20, 1, -20) main.Size = UDim2.new(0, 600, 0, 380) main.Parent = screenGui local corner = Instance.new("UICorner") corner.CornerRadius = UDim.new(0, 10) corner.Parent = main local stroke = Instance.new("UIStroke") stroke.Thickness = 1 stroke.Color = Color3.fromRGB(55, 55, 70) stroke.ApplyStrokeMode = Enum.ApplyStrokeMode.Border stroke.Parent = main stroke.Transparency = 1 -- removed unused shadow local content = Instance.new("Frame") content.BackgroundTransparency = 1 content.Size = UDim2.new(1, 0, 1, 0) content.Parent = main local layout = Instance.new("UIListLayout") layout.FillDirection = Enum.FillDirection.Vertical layout.SortOrder = Enum.SortOrder.LayoutOrder layout.Parent = content local header = Instance.new("Frame") header.BackgroundColor3 = COLOR_PANEL header.Size = UDim2.new(1, 0, 0, 44) header.BorderSizePixel = 0 header.LayoutOrder = 1 header.Parent = content local headerCorner = Instance.new("UICorner") headerCorner.CornerRadius = UDim.new(0, 10) headerCorner.Parent = header local title = Instance.new("TextLabel") title.BackgroundTransparency = 1 title.Font = Enum.Font.GothamBold title.Text = "dckrzw's logger" title.TextColor3 = COLOR_TEXT title.TextSize = 18 title.TextXAlignment = Enum.TextXAlignment.Left title.Position = UDim2.new(0, 16, 0, 0) title.Size = UDim2.new(1, -32, 1, 0) title.Parent = header -- header right controls local headerControls = Instance.new("Frame") headerControls.BackgroundTransparency = 1 headerControls.AnchorPoint = Vector2.new(1, 0) headerControls.Position = UDim2.new(1, -10, 0, 6) headerControls.Size = UDim2.new(0, 120, 1, -12) headerControls.Parent = header local headerLayout = Instance.new("UIListLayout") headerLayout.FillDirection = Enum.FillDirection.Horizontal headerLayout.HorizontalAlignment = Enum.HorizontalAlignment.Right headerLayout.VerticalAlignment = Enum.VerticalAlignment.Center headerLayout.Padding = UDim.new(0, 6) headerLayout.Parent = headerControls local function makeIconButton(text) local b = Instance.new("TextButton") b.AutoButtonColor = false b.BackgroundColor3 = COLOR_BG b.TextColor3 = COLOR_TEXT b.Font = Enum.Font.Gotham b.TextSize = 14 b.Text = text b.Size = UDim2.new(0, 32, 1, 0) b.BorderSizePixel = 0 local c = Instance.new("UICorner"); c.CornerRadius = UDim.new(0, 8); c.Parent = b local s = Instance.new("UIStroke"); s.Thickness = 1; s.Color = Color3.fromRGB(55,55,65); s.Parent = b local ts = game:GetService("TweenService") local normal = {BackgroundColor3 = COLOR_BG} local hover = {BackgroundColor3 = COLOR_PANEL} b.MouseEnter:Connect(function() ts:Create(b, TweenInfo.new(0.12, Enum.EasingStyle.Sine, Enum.EasingDirection.Out), hover):Play() end) b.MouseLeave:Connect(function() ts:Create(b, TweenInfo.new(0.12, Enum.EasingStyle.Sine, Enum.EasingDirection.Out), normal):Play() end) return b end local btnMin = makeIconButton("–") btnMin.Parent = headerControls local btnInfo = makeIconButton("i") btnInfo.Parent = headerControls local btnClose = makeIconButton("×") btnClose.Parent = headerControls local controls = Instance.new("Frame") controls.BackgroundTransparency = 1 controls.Size = UDim2.new(1, 0, 0, 48) controls.Position = UDim2.new(0, 0, 0, 0) controls.LayoutOrder = 2 controls.Parent = content local controlsLayout = Instance.new("UIListLayout") controlsLayout.FillDirection = Enum.FillDirection.Horizontal controlsLayout.HorizontalAlignment = Enum.HorizontalAlignment.Left controlsLayout.VerticalAlignment = Enum.VerticalAlignment.Center controlsLayout.Padding = UDim.new(0, 8) controlsLayout.Parent = controls local controlsPadding = Instance.new("UIPadding") controlsPadding.PaddingLeft = UDim.new(0, 8) controlsPadding.PaddingRight = UDim.new(0, 8) controlsPadding.PaddingTop = UDim.new(0, 6) controlsPadding.PaddingBottom = UDim.new(0, 6) controlsPadding.Parent = controls local function makeButton(text) local button = Instance.new("TextButton") button.AutoButtonColor = false button.BackgroundColor3 = COLOR_BG button.TextColor3 = COLOR_TEXT button.Font = Enum.Font.Gotham button.TextSize = 13 button.Text = text button.Size = UDim2.new(0, 124, 1, 0) button.BorderSizePixel = 0 local bcorner = Instance.new("UICorner") bcorner.CornerRadius = UDim.new(0, 8) bcorner.Parent = button local bstroke = Instance.new("UIStroke") bstroke.Thickness = 1 bstroke.Color = Color3.fromRGB(65, 65, 80) bstroke.ApplyStrokeMode = Enum.ApplyStrokeMode.Border bstroke.Parent = button local tweenService = game:GetService("TweenService") local normal = {BackgroundColor3 = COLOR_BG} local hover = {BackgroundColor3 = COLOR_PANEL} button.MouseEnter:Connect(function() tweenService:Create(button, TweenInfo.new(0.15, Enum.EasingStyle.Sine, Enum.EasingDirection.Out), hover):Play() end) button.MouseLeave:Connect(function() tweenService:Create(button, TweenInfo.new(0.15, Enum.EasingStyle.Sine, Enum.EasingDirection.Out), normal):Play() end) return button end local btnCopy = makeButton("Copy All") btnCopy.Parent = controls local btnClear = makeButton("Clear") btnClear.Parent = controls btnCopy.Size = UDim2.new(0.5, -4, 1, 0) btnClear.Size = UDim2.new(0.5, -4, 1, 0) local logHolder = Instance.new("Frame") logHolder.BackgroundTransparency = 1 logHolder.Size = UDim2.new(1, -16, 1, -44 - 48 - 16) logHolder.Position = UDim2.new(0, 8, 0, 0) logHolder.LayoutOrder = 3 logHolder.Parent = content local scroller = Instance.new("ScrollingFrame") scroller.BackgroundColor3 = COLOR_PANEL scroller.BorderSizePixel = 0 scroller.Size = UDim2.new(1, 0, 1, 0) scroller.CanvasSize = UDim2.new(0, 0, 0, 0) scroller.ScrollBarThickness = 6 scroller.ScrollBarImageColor3 = COLOR_HIGHLIGHT scroller.Parent = logHolder local scCorner = Instance.new("UICorner") scCorner.CornerRadius = UDim.new(0, 8) scCorner.Parent = scroller local list = Instance.new("UIListLayout") list.FillDirection = Enum.FillDirection.Vertical list.Padding = UDim.new(0, 4) list.SortOrder = Enum.SortOrder.LayoutOrder list.Parent = scroller local padding = Instance.new("UIPadding") padding.PaddingTop = UDim.new(0, 8) padding.PaddingBottom = UDim.new(0, 8) padding.PaddingLeft = UDim.new(0, 8) padding.PaddingRight = UDim.new(0, 8) padding.Parent = scroller local function toLine(entry) local timestamp = os.date("!%Y-%m-%d %H:%M:%S", entry.t or os.time()) local author = entry.author or "Unknown" local userId = tostring(entry.userId or 0) local text = entry.text or "" return string.format("[%s] %s (%s): %s", timestamp, author, userId, text) end local buffer = {} local function addLogLine(text) local label = Instance.new("TextLabel") label.BackgroundTransparency = 1 label.Font = Enum.Font.Gotham label.TextXAlignment = Enum.TextXAlignment.Left label.TextYAlignment = Enum.TextYAlignment.Top label.TextWrapped = true label.TextSize = 15 label.TextColor3 = COLOR_MUTED label.Size = UDim2.new(1, -8, 0, 0) label.AutomaticSize = Enum.AutomaticSize.Y label.Text = text label.Parent = scroller scroller.CanvasSize = UDim2.new(0, 0, 0, list.AbsoluteContentSize.Y + 16) scroller.CanvasPosition = Vector2.new(0, math.max(0, scroller.CanvasSize.Y.Offset - scroller.AbsoluteWindowSize.Y)) end list:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(function() scroller.CanvasSize = UDim2.new(0, 0, 0, list.AbsoluteContentSize.Y + 16) end) local function getAllText() return table.concat(buffer, "\n") end -- removed unused openCopyModal -- Save dialog modal: choose path and edit text before saving local function openSaveModal() local modal = Instance.new("Frame") modal.BackgroundColor3 = COLOR_BG modal.Size = UDim2.new(1, 0, 1, 0) modal.BackgroundTransparency = 0.1 modal.Parent = screenGui local mCorner = Instance.new("UICorner") mCorner.CornerRadius = UDim.new(0, 10) mCorner.Parent = modal local inner = Instance.new("Frame") inner.BackgroundColor3 = COLOR_PANEL inner.Size = UDim2.new(0, 620, 0, 420) inner.AnchorPoint = Vector2.new(0.5, 0.5) inner.Position = UDim2.new(0.5, 0, 0.5, 0) inner.Parent = modal local iCorner = Instance.new("UICorner") iCorner.CornerRadius = UDim.new(0, 10) iCorner.Parent = inner local pathLabel = Instance.new("TextLabel") pathLabel.BackgroundTransparency = 1 pathLabel.TextColor3 = COLOR_TEXT pathLabel.Font = Enum.Font.Gotham pathLabel.TextSize = 13 pathLabel.TextXAlignment = Enum.TextXAlignment.Left pathLabel.Position = UDim2.new(0, 10, 0, 10) pathLabel.Size = UDim2.new(0, 80, 0, 24) pathLabel.Text = "Path:" pathLabel.Parent = inner local pathBox = Instance.new("TextBox") pathBox.ClearTextOnFocus = false pathBox.TextEditable = true pathBox.BackgroundColor3 = COLOR_BG pathBox.TextColor3 = COLOR_TEXT pathBox.Font = Enum.Font.Code pathBox.TextSize = 14 pathBox.TextXAlignment = Enum.TextXAlignment.Left pathBox.TextYAlignment = Enum.TextYAlignment.Center pathBox.Size = UDim2.new(1, -100, 0, 28) pathBox.Position = UDim2.new(0, 90, 0, 10) pathBox.Text = currentSavePath or defaultFilename() pathBox.Parent = inner local contentBox = Instance.new("TextBox") contentBox.ClearTextOnFocus = false contentBox.MultiLine = true contentBox.TextEditable = true contentBox.BackgroundColor3 = COLOR_BG contentBox.TextColor3 = COLOR_TEXT contentBox.Font = Enum.Font.Code contentBox.TextSize = 14 contentBox.TextXAlignment = Enum.TextXAlignment.Left contentBox.TextYAlignment = Enum.TextYAlignment.Top contentBox.Size = UDim2.new(1, -20, 1, -100) contentBox.Position = UDim2.new(0, 10, 0, 48) contentBox.Text = getAllText() contentBox.Parent = inner local saveBtn = makeButton("Save") saveBtn.Size = UDim2.new(0, 110, 0, 36) saveBtn.Position = UDim2.new(1, -240, 1, -46) saveBtn.Parent = inner local cancelBtn = makeButton("Cancel") cancelBtn.Size = UDim2.new(0, 110, 0, 36) cancelBtn.Position = UDim2.new(1, -120, 1, -46) cancelBtn.Parent = inner cancelBtn.MouseButton1Click:Connect(function() modal:Destroy() end) saveBtn.MouseButton1Click:Connect(function() local path = tostring(pathBox.Text or "") if path == "" then toast("Please enter a file path") return end currentSavePath = path local content = tostring(contentBox.Text or "") local ok, err if hasWrite then ok, err = pcall(function() _write(currentSavePath, content) end) elseif hasAppend then -- simulate overwrite using delete then append if possible if hasIsFile then pcall(function() if _isfile(currentSavePath) and hasDelFile then _delfile(currentSavePath) end end) end ok, err = pcall(function() _append(currentSavePath, content) end) else -- fallback: copy to clipboard if typeof(setclipboard) == "function" then pcall(function() setclipboard(content) end) toast("Copied to clipboard (no file API)") modal:Destroy() return elseif typeof(set_clipboard) == "function" then pcall(function() set_clipboard(content) end) toast("Copied to clipboard (no file API)") modal:Destroy() return else toast("Save unavailable in this executor") return end end if ok then toast("Saved: " .. currentSavePath) modal:Destroy() else toast("Save failed") dbg("Save failed: " .. tostring(err)) end end) end -- Info modal: shows Discord contact and copy button local function openInfoModal() local inner = Instance.new("Frame") inner.BackgroundColor3 = COLOR_PANEL inner.Size = UDim2.new(0, 420, 0, 160) inner.AnchorPoint = Vector2.new(0.5, 0.5) inner.Position = UDim2.new(0.5, 0, 0.5, 0) inner.Parent = screenGui inner.ZIndex = 50 local iCorner = Instance.new("UICorner") iCorner.CornerRadius = UDim.new(0, 10) iCorner.Parent = inner local title = Instance.new("TextLabel") title.BackgroundTransparency = 1 title.Font = Enum.Font.GothamBold title.Text = "Contact" title.TextColor3 = COLOR_TEXT title.TextSize = 18 title.TextXAlignment = Enum.TextXAlignment.Left title.Position = UDim2.new(0, 14, 0, 12) title.Size = UDim2.new(1, -28, 0, 24) title.Parent = inner title.ZIndex = 51 local desc = Instance.new("TextLabel") desc.BackgroundTransparency = 1 desc.Font = Enum.Font.Gotham desc.Text = "Discord: dckrzw" desc.TextColor3 = COLOR_TEXT desc.TextSize = 16 desc.TextXAlignment = Enum.TextXAlignment.Left desc.Position = UDim2.new(0, 14, 0, 48) desc.Size = UDim2.new(1, -28, 0, 24) desc.Parent = inner desc.ZIndex = 51 local copyBtn = makeButton("Copy") copyBtn.Size = UDim2.new(0, 110, 0, 36) copyBtn.Position = UDim2.new(1, -240, 1, -46) copyBtn.Parent = inner copyBtn.ZIndex = 51 local closeBtn = makeButton("Close") closeBtn.Size = UDim2.new(0, 110, 0, 36) closeBtn.Position = UDim2.new(1, -120, 1, -46) closeBtn.Parent = inner closeBtn.ZIndex = 51 closeBtn.MouseButton1Click:Connect(function() inner:Destroy() end) copyBtn.MouseButton1Click:Connect(function() copyText("dckrzw") end) end -- Lightweight toast feedback local function toast(msg) local tweenService = game:GetService("TweenService") local t = Instance.new("TextLabel") t.BackgroundTransparency = 0.2 t.BackgroundColor3 = COLOR_PANEL t.TextColor3 = COLOR_TEXT t.BorderSizePixel = 0 t.Font = Enum.Font.Gotham t.TextSize = 14 t.Text = msg t.AnchorPoint = Vector2.new(0.5, 1) t.Position = UDim2.new(0.5, 0, 1, -8) t.Size = UDim2.new(0, 220, 0, 32) t.Parent = screenGui local c = Instance.new("UICorner"); c.CornerRadius = UDim.new(0, 8); c.Parent = t local s = Instance.new("UIStroke"); s.Thickness = 1; s.Color = Color3.fromRGB(65,65,80); s.Parent = t tweenService:Create(t, TweenInfo.new(0.15, Enum.EasingStyle.Sine, Enum.EasingDirection.Out), {BackgroundTransparency = 0.05}):Play() task.delay(1.2, function() tweenService:Create(t, TweenInfo.new(0.25, Enum.EasingStyle.Sine, Enum.EasingDirection.In), {TextTransparency = 1, BackgroundTransparency = 1}):Play() wait(0.26) t:Destroy() end) end -- Clipboard copy using executor API if available local function copyAll() local text = getAllText() copyText(text) end btnCopy.MouseButton1Click:Connect(copyAll) local currentSavePath = nil btnClear.MouseButton1Click:Connect(function() buffer = {} for _, child in ipairs(scroller:GetChildren()) do if child:IsA("TextLabel") then child:Destroy() end end scroller.CanvasSize = UDim2.new(0, 0, 0, 0) dbg("Cleared on-screen buffer") end) -- Minimize/close local minimized = false btnMin.MouseButton1Click:Connect(function() minimized = not minimized scroller.Visible = not minimized controls.Visible = not minimized logHolder.Visible = not minimized layout.VerticalAlignment = minimized and Enum.VerticalAlignment.Center or Enum.VerticalAlignment.Top main.Size = minimized and UDim2.new(0, 280, 0, 60) or UDim2.new(0, 600, 0, 380) end) btnClose.MouseButton1Click:Connect(function() screenGui:Destroy() end) btnInfo.MouseButton1Click:Connect(function() openInfoModal() end) -- Drag support do local UIS = game:GetService("UserInputService") local dragging = false local dragStart, startPos header.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 then dragging = true dragStart = input.Position startPos = main.Position input.Changed:Connect(function() if input.UserInputState == Enum.UserInputState.End then dragging = false end end) end end) UIS.InputChanged:Connect(function(input) if dragging and input.UserInputType == Enum.UserInputType.MouseMovement then local delta = input.Position - dragStart main.Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y) end end) end -- Chat hooks (client) local function sanitizeText(raw) if not raw then return "" end -- Remove rich text tags like ... and any <...> local cleaned = tostring(raw):gsub("<.->", "") -- Collapse excessive whitespace cleaned = cleaned:gsub("%s+", " "):gsub("^%s+", ""):gsub("%s+$", "") return cleaned end local function pushEntry(author, userId, channel, text) local entry = { t = os.time(), author = author or "Unknown", userId = userId or 0, channel = channel, text = sanitizeText(text), } local line = toLine(entry) buffer[#buffer + 1] = line addLogLine(line) end local hooked = false -- Preferred: TextChatService local tcs = game:GetService("TextChatService") if tcs and tcs.MessageReceived then pcall(function() tcs.MessageReceived:Connect(function(message) local text = message.Text or "" local authorName = "SYSTEM" local userId = 0 if message.TextSource then authorName = message.TextSource.Name or "Unknown" userId = message.TextSource.UserId or 0 end pushEntry(authorName, userId, nil, text) end) hooked = true dbg("Hooked TextChatService.MessageReceived") end) end -- Legacy fallback: DefaultChatSystemChatEvents if not hooked then local success, event = pcall(function() return ReplicatedStorage:WaitForChild("DefaultChatSystemChatEvents", 2) end) if success and event then local msgEvent = event:FindFirstChild("OnMessageDoneFiltering") if msgEvent and msgEvent:IsA("RemoteEvent") then msgEvent.OnClientEvent:Connect(function(data) local msg = "" if typeof(data) == "table" then msg = data.Message or "" end pushEntry((data and data.FromSpeaker) or "Unknown", 0, nil, msg) end) hooked = true dbg("Hooked DefaultChatSystemChatEvents.OnMessageDoneFiltering") end end end if not hooked then dbg("No chat system hook available on client") end addLogLine("dckrzw's logger ready. New messages will appear here.") dbg("GUI built and active")