From 2c0ef2f99b7d15310f4205b5a4064ec4223aeff0 Mon Sep 17 00:00:00 2001 From: breadddevv Date: Sat, 8 Aug 2026 12:12:34 +0100 Subject: [PATCH 1/2] Hopefully fixed afk tracking and removed ROBLOX_WORKSPACE_REDIRECTID as it isn't a required variable. --- Orbit-activity.rbxmx | 70 ++++++++++++++++++-------------------------- README.md | 1 - 2 files changed, 29 insertions(+), 42 deletions(-) diff --git a/Orbit-activity.rbxmx b/Orbit-activity.rbxmx index 3d4107cf..1375281c 100644 --- a/Orbit-activity.rbxmx +++ b/Orbit-activity.rbxmx @@ -13,7 +13,6 @@ local RunService = game:GetService("RunService") local GroupService = game:GetService("GroupService") local HttpQueue = require(script.Components.HttpQueue) -local FastWait = require(script.Components.FastWait) local TovyFolder = Instance.new("Folder", ReplicatedStorage) TovyFolder.Name = "Orbit Assets" @@ -29,23 +28,23 @@ local Configuration = { url = "", auth = "", - privateEnabled = , -- Track private servers? + privateEnabled = , -- Track private servers? studioEnabled = , -- Track Studio sessions? -- Feature flags - bansEnabled = false, -- Let Orbit handle bans? - rankChecking = true, -- Only track members of the group? + bansEnabled = false, -- Let Orbit handle bans? + rankChecking = true, -- Only track members of the group? groupId = , -- Group ID for rank checks - minTrackedRank = , -- Minimum rank to be tracked (overridable via remote config) + minTrackedRank = , -- Minimum rank to be tracked (overridable via remote config) -- Timing - cooldownPeriod = 30, -- Seconds between HTTP retries - minutesTillAFK = 2, -- Idle minutes before AFK flag - scanInterval = 300, -- Seconds between full player scans (5 min) - heartbeatInterval = 60, -- Seconds between lightweight heartbeats - rankRefreshInterval = 600, -- Seconds between per-player rank re-checks (throttles GroupService) - serverHeartbeatEvery = 120, -- Seconds between backend "server alive" pings - remoteEventCooldown = 3, -- Min seconds between accepted client Activity events per player + cooldownPeriod = 30, -- Seconds between HTTP retries + minutesTillAFK = 1, -- Idle minutes before AFK flag + afkPollInterval = 10, -- Seconds between idle-time checks (AFK detection) + scanInterval = 300, -- Seconds between full player scans (5 min) + heartbeatInterval = 60, -- Seconds between lightweight heartbeats + rankRefreshInterval = 600, -- Seconds between per-player rank re-checks (throttles GroupService) + remoteEventCooldown = 3, -- Min seconds between accepted client Activity events per player -- Chat capture maxStoredChatLines = 200, @@ -96,7 +95,6 @@ type PlayerState = { afkStart: number?, isAFK: boolean, afkTimerInstance: NumberValue?, - pendingAFKCheck: boolean, lastRankCheck: number, lastRemoteEventAccepted: number, } @@ -115,7 +113,6 @@ local function stripChat(text: string): string return (text:gsub("^%s+", ""):gsub("%s+$", "")) end - local function setAFK(Player: Player, state: boolean) local st = getState(Player) if not st then return end @@ -420,32 +417,7 @@ local function MovementDetection(Player: Player) local function onActivity(speed: number) if speed > 0 then bumpActivity(Player) - return - end - - local myState = getState(Player) - if not myState or myState.pendingAFKCheck then - return end - - local snapshot = os.clock() - myState.lastActivity = snapshot - myState.pendingAFKCheck = true - - task.spawn(function() - FastWait(60 * Configuration.minutesTillAFK) - - local currentState = getState(Player) - if currentState then - currentState.pendingAFKCheck = false - end - - if isPlayerOnline(Player) and currentState and currentState.lastActivity == snapshot then - setAFK(Player, true) - log("INFO", Player.Name .. " marked AFK (no movement for " - .. Configuration.minutesTillAFK .. " min).") - end - end) end table.insert(connections, Humanoid.Running:Connect(onActivity)) @@ -487,7 +459,7 @@ local function InputChange(Player: Player, isIdle: unknown) bumpActivity(Player) else local idleSeconds = st.lastActivity and (now - st.lastActivity) or math.huge - local threshold = 60 * Configuration.minutesTillAFK -- matches MovementDetection's threshold + local threshold = 60 * Configuration.minutesTillAFK if idleSeconds >= threshold then setAFK(Player, true) @@ -509,7 +481,6 @@ local function InitiatePlayer(Player: Player): boolean afkStart = nil, isAFK = false, afkTimerInstance = nil, - pendingAFKCheck = false, lastRankCheck = os.clock(), lastRemoteEventAccepted = 0, } @@ -612,6 +583,23 @@ local function fetchRemoteConfig() end end +task.spawn(function() + while true do + task.wait(Configuration.afkPollInterval) + local threshold = 60 * Configuration.minutesTillAFK + for userId, st in pairs(PlayerData) do + local Player = Players:GetPlayerByUserId(userId) + if Player and isPlayerOnline(Player) and not st.isAFK then + local idleFor = os.clock() - st.lastActivity + if idleFor >= threshold then + setAFK(Player, true) + log("INFO", Player.Name .. " marked AFK (idle for " .. math.floor(idleFor) .. "s).") + end + end + end + end +end) + task.spawn(function() while true do task.wait(Configuration.heartbeatInterval) diff --git a/README.md b/README.md index 7fb7956f..3db1b5ae 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,6 @@ Prefer to host on your own Vercel account? Deploy in seconds: | `SESSION_SECRET` | A strong secret string — generate with `openssl rand -base64 32` | | `DATABASE_URL` | Your database connection string (e.g. [Supabase](https://supabase.com), [Railway](https://railway.app), [Neon](https://neon.tech)) | | `NEXTAUTH_URL` or `PUBLIC_URL` | Your deployment URL, without a trailing slash (e.g. `https://instance.planetaryapp.cloud`) | -| `ROBLOX_WORKSPACE_REDIRECTID` | Your Roblox Group ID — users with workspace access will be redirected automatically | --- From fc5f55ab648063a5747919e4246a52a90860b538 Mon Sep 17 00:00:00 2001 From: bread Date: Sat, 8 Aug 2026 13:11:11 +0100 Subject: [PATCH 2/2] Limited AFK polling to tracked players. Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- Orbit-activity.rbxmx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Orbit-activity.rbxmx b/Orbit-activity.rbxmx index 1375281c..a3ada57b 100644 --- a/Orbit-activity.rbxmx +++ b/Orbit-activity.rbxmx @@ -589,7 +589,7 @@ task.spawn(function() local threshold = 60 * Configuration.minutesTillAFK for userId, st in pairs(PlayerData) do local Player = Players:GetPlayerByUserId(userId) - if Player and isPlayerOnline(Player) and not st.isAFK then + if Player and isPlayerOnline(Player) and isUserTracked(Player) and not st.isAFK then local idleFor = os.clock() - st.lastActivity if idleFor >= threshold then setAFK(Player, true)