My script have a problem. Punch card

A punch card system in a Roblox game. When the person equips the Driver Card and let the card touches the Card Reader , the script logs the player’s login and logout time, their Roblox group rank, and sends this information to a Discord webhook. The script also plays a sound when the card is read. Additionally, the script prints a message when the “Driver Card” object is touched.

The issue is, it doesn’t have a error code. Print or the sound is not produced. Most importantly, the data transfer to a discord server channel too. (Webhook)
image
image

local httpService = game:GetService("HttpService")
local groupID = xxxxx
local webhookURL = "https://hooks.hyra.io/api/webhooks/"

local function getTime()
	return os.date("%Y-%m-%d %X")
end

local function sendToWebhook(player, status)
	print("Sending data to webhook")

	local playerRank = tostring(player:GetRoleInGroup(groupID))
	local playerName = player.Name
	local time = getTime()

	local data = {
		["username"] = "Punch Card System",
		["embeds"] = {{
			["title"] = "Punch Card System",
			["color"] = tonumber("0x00FF00", 16),
			["fields"] = {
				{["name"] = "Player", ["value"] = playerName},
				{["name"] = "Rank", ["value"] = playerRank},
				{["name"] = "Status", ["value"] = status},
				{["name"] = "Time", ["value"]=time}
			}
		}}
	}

	local jsonData=httpService:JSONEncode(data)

	local success,err=pcall(function()
		httpService:PostAsync(webhookURL,jsonData,Enum.HttpContentType.ApplicationJson)
	end)

	if not success then
		print("Error sending data to webhook:",err)
	end 
end

local function onCardTouched(mouse)
	print("Driver Card equipped")

	local player=game.Players:GetPlayerFromCharacter(mouse.Parent)
	if player then
		local soundId=1283290053
		local sound=Instance.new("Sound")
		sound.SoundId="rbxassetid://"..soundId
		sound.Parent=player.Character
		sound:Play()

		if mouse.Target.Name=="LogOn" then
			sendToWebhook(player,"Log On")
		elseif mouse.Target.Name=="LogOff" then
			sendToWebhook(player,"Log Off")
		end 
	end 
end 

game.StarterPack.DriverCard.Equipped:Connect(function(mouse)
	print("Equipped event triggered")
	onCardTouched(mouse)
end)

Can you elaborate on what you mean by “touches a Driver Card”? The code seems to trigger when a Driver Card is “equipped”. The Driver Card looks like a tool in the backpack.

Oops typo, I mean was when the person equips the Driver Card and let the card touches the Card Reader. The driver card is in a backpack so people can punch in and punch out.

Ok understanding a bit more. The Driver Card starts in the player’s backpack?

Yup, its a tool. Its only give to the specific rank in the group.

Ok so then when the Driver Card is in their hand, and then they make the card touch the “Logon” part of the card reader, then log them on, and if they make the card touch the “logoff” part of the reader, log them off? If so then I have an idea to make your code work. And can you show the Card Reader Model?

Its supposed to be on a tool only which is Card Reader. But we also can try to stick with that idea too. and maybe if the player disconnected the game it can automatically logoff.

local function onPlayerRemoving(player)
	if logOnTable[player] then
		logOnTable[player] = nil
		sendToWebhook(player, "Log Off")
	end
end

The Card Reader is a tool in the backpack as well? I thought it was something in the Workspace.

No, its supposed to be as a only block which is Card Reader. It was in workspace. not a tool sorry

I recommend using pcalls like this over how you are using them.

local success, response = pcall(httpService.PostAsync, httpService, webhookURL, jsonData, Enum.ContentType.Application.Json)

Then you can do print(response) to see what was returned from the request.

Take a look at this post if you would like to read more about pcalls:

1 Like

Ok so I don’t have your driver card tool, so substituting a sword here. Assuming you mean something like this?

https://youtu.be/odxlIJOKxYI

Yes, its like this and it will beep when it touches.

Alright give me a couple minutes and I’ll send a script when I can get back to my computer.

1 Like

So you would want to put something like this on each part that gets touched to log them on and off.

local debounce = false
script.Parent.Touched:Connect(function(hit)
	if hit.Parent.Name == "Driver Card" and debounce == false then
		debounce = true
		local player = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent.Parent)
		if player then
			sendToWebhook(player,"Log On") -- change to Log Off for the other button
		end
		task.wait(5) -- or however long you want the game to wait before allowing the logon to be touched again
		debounce = false
	end
end)

You can get rid of your whole onCardTouched function and your game.StarterPack.DriverCard.Equipped:Connect function as well.

So do i remain the same script that i put in serverscript sevices? (the one i wrote in forum)

Assuming you have a part that gets touched for the logon and logoff, then yes you can have the script in your serverscript services and this would be your script:

local httpService = game:GetService("HttpService")
local groupID = xxxxx
local webhookURL = "https://hooks.hyra.io/api/webhooks/"

local function getTime()
	return os.date("%Y-%m-%d %X")
end

local function sendToWebhook(player, status)
	print("Sending data to webhook")

	local playerRank = tostring(player:GetRoleInGroup(groupID))
	local playerName = player.Name
	local time = getTime()

	local data = {
		["username"] = "Punch Card System",
		["embeds"] = {{
			["title"] = "Punch Card System",
			["color"] = tonumber("0x00FF00", 16),
			["fields"] = {
				{["name"] = "Player", ["value"] = playerName},
				{["name"] = "Rank", ["value"] = playerRank},
				{["name"] = "Status", ["value"] = status},
				{["name"] = "Time", ["value"]=time}
			}
		}}
	}

	local jsonData=httpService:JSONEncode(data)

	local success,err=pcall(function()
		httpService:PostAsync(webhookURL,jsonData,Enum.HttpContentType.ApplicationJson)
	end)

	if not success then
		print("Error sending data to webhook:",err)
	end 
end

local logonDebounce = false
game.Workspace.YourLogonPartName.Touched:Connect(function(hit) -- obviously replace YourLogonPartName with whatever your part is named and wherever it is
	if hit.Parent.Name == "Driver Card" and logonDebounce == false then
		debounce = true
		local player = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent.Parent)
		if player then
			sendToWebhook(player,"Log On") -- change to Log Off for the other button
		end
		task.wait(5) -- or however long you want the game to wait before allowing the logon to be touched again
		logonDebounce = false
	end
end)

local logOffDebounce = false
game.Workspace.YourLogoffPartName.Touched:Connect(function(hit) -- obviously replace YourLogoffPartName with whatever your part is named and wherever it is
	if hit.Parent.Name == "Driver Card" and logOffDebounce == false then
		debounce = true
		local player = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent.Parent)
		if player then
			sendToWebhook(player,"Log Off") -- change to Log Off for the other button
		end
		task.wait(5) -- or however long you want the game to wait before allowing the logon to be touched again
		logOffDebounce = false
	end
end)

Thank you very much finally its working. Theres a another issue which is Players can either log on multiple times once they touch the part, or log off multiple time when they didnt even logon.

is there anyway for when the player touches the LogOff part with their Driver Card , the script calculates the duration between the logon time and the current time. The duration is formatted as a string in days, hours, minutes and seconds and sent to the webhook along with a “Log Off” message? and it keeps adding the previous amount until the new month, new month will autoreset.

For this, add a :PlayerAdded function so when the player logs on, you can create 2 boolean variables called something like “loggedOn” and “loggedOff”. In the touched functions I gave you, assign the values to true for the corresponding buttons. Then before sending the webhook, check the variable. If they’re already logged on, then dont send the logon, and if they’re already logged of, dont send the logoff. This should also stop them from being able to logoff if they aren’t already logged on and vice versa.

For this, you would need to save their total drive times in a datastore when they logoff. In the :PlayerAdded function also add number values called logonTime and logofffTime. Then whenever they logon, assign tick() to the logonTime. When they log off, assign tick() to logoffTime. Then subtract the two to get the total number of seconds of their current session drive time when they logoff. Your send logoff webhook can then grab their previous total time from the datastore and add it to their current session drive time, and send that to the webhook. Then just update the datastore with their new total drive time. As for formatting, there’s a plenty of other forum posts on how to format seconds into days:hours:minutes:seconds etc. You can search for those and pick one.Once your new month begins, just reset the drivers total drive time back to 0 in the datastore.

Thank you very much man. Aprreciate it.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.