mirror of
https://github.com/sky-systems/sky_phone.git
synced 2026-08-29 09:01:33 +00:00
162 lines
4.8 KiB
Lua
162 lines
4.8 KiB
Lua
Bridge.Database.AfterMigration("sky_phone", function()
|
|
local marker_colors = {
|
|
blue = true,
|
|
green = true,
|
|
orange = true,
|
|
purple = true,
|
|
red = true,
|
|
}
|
|
|
|
local function affected_rows(result)
|
|
if type(result) == "number" then
|
|
return result
|
|
end
|
|
|
|
return type(result) == "table" and tonumber(result.affectedRows) or 0
|
|
end
|
|
|
|
local function text_length(value)
|
|
return type(value) == "string" and utf8.len(value) or nil
|
|
end
|
|
|
|
local function marker_dto(row)
|
|
return {
|
|
id = row.id,
|
|
label = row.label,
|
|
color = row.color,
|
|
coords = {
|
|
x = tonumber(row.position_x) or 0.0,
|
|
y = tonumber(row.position_y) or 0.0,
|
|
z = tonumber(row.position_z) or 0.0,
|
|
},
|
|
}
|
|
end
|
|
|
|
local function validate_marker(data)
|
|
if type(data) ~= "table" or type(data.coords) ~= "table" then
|
|
return nil
|
|
end
|
|
|
|
local label = type(data.label) == "string" and data.label:match("^%s*(.-)%s*$") or nil
|
|
local label_length = text_length(label)
|
|
local color = data.color
|
|
local x = tonumber(data.coords.x)
|
|
local y = tonumber(data.coords.y)
|
|
local z = tonumber(data.coords.z)
|
|
if not label_length
|
|
or label_length < 1
|
|
or label_length > Config.MapMarkers.LabelMaxLength
|
|
or not marker_colors[color]
|
|
or not x
|
|
or not y
|
|
or (data.coords.z ~= nil and not z)
|
|
or x ~= x
|
|
or y ~= y
|
|
or (z and z ~= z)
|
|
or math.abs(x) > 10000.0
|
|
or math.abs(y) > 10000.0
|
|
or (z and z < -1000.0)
|
|
or (z and z > 3000.0)
|
|
then
|
|
return nil
|
|
end
|
|
|
|
return {
|
|
label = label,
|
|
color = color,
|
|
x = x,
|
|
y = y,
|
|
z = z or 0.0,
|
|
}
|
|
end
|
|
|
|
Bridge.Callbacks.Register("sky_phone:map:markers", function(source)
|
|
local session, error_response = SkyPhone.RequireSession(source)
|
|
if not session then
|
|
return error_response
|
|
end
|
|
|
|
local rows = Bridge.Database.Query([[
|
|
SELECT `id`, `label`, `color`, `position_x`, `position_y`, `position_z`
|
|
FROM `sky_phone_map_markers`
|
|
WHERE `device_imei` = ?
|
|
ORDER BY `created_at`, `id`
|
|
LIMIT ?
|
|
]], { session.imei, Config.MapMarkers.MaximumMarkers })
|
|
local markers = {}
|
|
for index = 1, #rows do
|
|
markers[index] = marker_dto(rows[index])
|
|
end
|
|
return { success = true, data = markers }
|
|
end)
|
|
|
|
Bridge.Callbacks.Register("sky_phone:map:create-marker", function(source, data)
|
|
if not SkyPhone.AllowOperation(source, "map_marker_write", Config.MapMarkers.ActionsPerMinute, 60) then
|
|
return { success = false, error = "rate_limited" }
|
|
end
|
|
|
|
local session, error_response = SkyPhone.RequireSession(source)
|
|
if not session then
|
|
return error_response
|
|
end
|
|
|
|
local marker = validate_marker(data)
|
|
if not marker then
|
|
return { success = false, error = "invalid_marker" }
|
|
end
|
|
|
|
local count_rows = Bridge.Database.Query([[
|
|
SELECT COUNT(*) AS `count`
|
|
FROM `sky_phone_map_markers`
|
|
WHERE `device_imei` = ?
|
|
]], { session.imei })
|
|
if (tonumber(count_rows[1] and count_rows[1].count) or 0) >= Config.MapMarkers.MaximumMarkers then
|
|
return { success = false, error = "marker_limit" }
|
|
end
|
|
|
|
local ids = Bridge.Database.Query("SELECT UUID() AS `id`", {})
|
|
local id = ids[1] and ids[1].id
|
|
if type(id) ~= "string" then
|
|
error("[sky_phone] Database did not generate a map marker id.")
|
|
end
|
|
|
|
Bridge.Database.Query([[
|
|
INSERT INTO `sky_phone_map_markers`
|
|
(`id`, `device_imei`, `label`, `color`, `position_x`, `position_y`, `position_z`)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
]], { id, session.imei, marker.label, marker.color, marker.x, marker.y, marker.z })
|
|
return {
|
|
success = true,
|
|
data = {
|
|
id = id,
|
|
label = marker.label,
|
|
color = marker.color,
|
|
coords = { x = marker.x, y = marker.y, z = marker.z },
|
|
},
|
|
}
|
|
end)
|
|
|
|
Bridge.Callbacks.Register("sky_phone:map:delete-marker", function(source, data)
|
|
if not SkyPhone.AllowOperation(source, "map_marker_write", Config.MapMarkers.ActionsPerMinute, 60) then
|
|
return { success = false, error = "rate_limited" }
|
|
end
|
|
|
|
local session, error_response = SkyPhone.RequireSession(source)
|
|
if not session then
|
|
return error_response
|
|
end
|
|
if type(data) ~= "table" or type(data.id) ~= "string" or #data.id ~= 36 then
|
|
return { success = false, error = "invalid_marker" }
|
|
end
|
|
|
|
local result = Bridge.Database.Query(
|
|
"DELETE FROM `sky_phone_map_markers` WHERE `id` = ? AND `device_imei` = ?",
|
|
{ data.id, session.imei }
|
|
)
|
|
if affected_rows(result) ~= 1 then
|
|
return { success = false, error = "marker_not_found" }
|
|
end
|
|
return { success = true }
|
|
end)
|
|
end)
|