For loop (ipairs()) skipping over non-nil value

(Background) Trying to send a multiline webhook containing server logs (normally sent every 60 seconds) by looping over an array of unsent logs and adding each one with a “\n” before it, then adding the actual log.

local StartTick = tick()
local Logs = {}
local UnsentLogs = {}

-- ConvertTime function is here (it works fine)

function module.CreateLog(user, action) -- Both arguments are strings
	print("Creating log")
	local LastTick = tick()
	local log = user.." | "..action.." | "..ConvertTime(LastTick - StartTick) -- Converts to something like: 00:00:07
	print(log) -- Prints something like: "Copycat4858 | action | 00:00:07"
	table.insert(Logs, #Logs+1, log)
	table.insert(UnsentLogs, #UnsentLogs+1, log)
	NotificationRemote:FireAllClients(user, action)
end

spawn(function()
	repeat
		wait(10) -- This is normally 60, but is 10 for testing purposes
		if #UnsentLogs >= 1 then
			local tbl = {"Logs", ""}
			print(#UnsentLogs) -- I have 2 buttons I press before wait(10) expires, creating 2 logs, printing "2"
			for i,v in ipairs(UnsentLogs) do
                print("loop") -- Only prints once per cycle of the repeat until, rather than twice
				tbl[2] = tbl[2].."\n"..v
				table.remove(UnsentLogs, i)
				print(#UnsentLogs) -- Prints 1 at first
				print("Added log to webhook") -- Only prints once per cycle of the repeat until, rather than twice
			end
			print(tbl[1], tbl[2])
			HTTPManager.SendWebhook(tbl, Settings.LogWebhook) -- Sends correctly, just only with one log
			print("Sent logs webhook") -- Prints
		end
	until nil
end)

It eventually sends both, but they get sent individually, rather than all in one. Any clue why the loop is only running once per cycle of the repeat until?

try setting it to false instead of nil maybe?

local UnsentLogs = {}

function module.CreateLog(user, testlog) -- Both arguments are strings
	local log = testlog
	print("Created log: "..log)
	table.insert(UnsentLogs, #UnsentLogs+1, log)
end

spawn(function()
	repeat
		wait(10)
		if #UnsentLogs >= 1 then
			local tbl = {"Logs", ""}
			repeat
				for i,v in ipairs(UnsentLogs) do
					tbl[2] = tbl[2].."\n"..v
					table.remove(UnsentLogs, i)
				end
			until #UnsentLogs < 1
			
			--[[
			local data = {
				['username'] = "webhookname:",
				['content'] = tbl[2]
			}
			game:GetService('HttpService'):PostAsync("webhook url", game:GetService('HttpService'):JSONEncode(data))
			--]]
			print("Sent log webhook with: "..tbl[2])
		end
	until nil
end)

I deleted all the unnecessary parts for my testing, so just take the pieces you need from this to make your script work. This works fine but you’re gonna have to adapt the: log creation, webhook portion, and the tbl[2] parts to match the functions you have set up already.

(If you want an explanation, the main fix is just using the ‘repeat until #UnsentLogs < 1’ to create the string concatenation without issue.)

1 Like

:+1: I’ll look into string concatenation further in the future (your solution worked).

1 Like