mirror of
https://github.com/sky-systems/sky_phone.git
synced 2026-08-28 17:01:18 +00:00
30559048fd
* FIX - preserve LB custom app lifecycle * FIX - reset LB export aliases before startup * FIX - report competing custom app providers * FIX - identify LB app frames as live NUI * FIX - complete LB custom app compatibility * FIX - provide LB PicChat runtime exports * FIX - route LB PicChat through Sky Phone * FIX - return cached LB equipped phone number * FIX - harden PicChat compatibility migration * ENH - complete modular phone provider and Creator APIs * DOC - document the Sky Phone Creator API --------- Co-authored-by: DerEchteAlec <bycraky@gmail.com> Co-authored-by: DerEchteAlec <alec.schitzkat@luwan.io>
152 lines
4.8 KiB
Lua
152 lines
4.8 KiB
Lua
local invoking_resource = "creator_resource"
|
|
local client_events = {}
|
|
local encoded_value
|
|
local notification_requests = {}
|
|
|
|
Config = {
|
|
CustomApps = {
|
|
BundledApps = false,
|
|
Enabled = true,
|
|
ExternalApps = true,
|
|
MaximumMessageBytes = 64,
|
|
TrustedAdapters = {},
|
|
},
|
|
}
|
|
|
|
json = {
|
|
decode = function(encoded)
|
|
if encoded:sub(1, 1) == '"' then
|
|
return encoded:sub(2, -2)
|
|
end
|
|
return encoded_value
|
|
end,
|
|
encode = function(value)
|
|
if type(value) == "function" then
|
|
error("unsupported")
|
|
end
|
|
if type(value) == "string" then
|
|
return '"' .. value .. '"'
|
|
end
|
|
encoded_value = value
|
|
return "{}"
|
|
end,
|
|
}
|
|
|
|
SkyPhoneNotifications = {
|
|
Send = function(target, notification)
|
|
notification_requests[#notification_requests + 1] = {
|
|
notification = notification,
|
|
target = target,
|
|
}
|
|
return { delivered = target.value == 10 and 1 or 0 }
|
|
end,
|
|
}
|
|
|
|
Bridge = {
|
|
Debug = function() end,
|
|
Framework = {
|
|
GetIdentifier = function(source)
|
|
return source == 10 and "license:online" or nil
|
|
end,
|
|
},
|
|
}
|
|
|
|
function AddEventHandler() end
|
|
function GetCurrentResourceName() return "sky_phone" end
|
|
function GetInvokingResource() return invoking_resource end
|
|
function GetResourceState() return "started" end
|
|
function TriggerClientEvent(name, target, ...)
|
|
client_events[#client_events + 1] = {
|
|
arguments = { ... },
|
|
name = name,
|
|
target = target,
|
|
}
|
|
end
|
|
|
|
assert(loadfile("sky_phone/source/shared/custom_apps.lua"))()
|
|
assert(loadfile("sky_phone/source/server/custom_apps.lua"))()
|
|
|
|
local api = assert(SkyPhoneApps.ServerPublicApi)
|
|
local capabilities = api.GetCustomAppCapabilities()
|
|
assert(capabilities.enabled and capabilities.externalApps)
|
|
assert(capabilities.messageDispatch and capabilities.notificationDispatch)
|
|
assert(api.AddCustomAppPolicy({
|
|
id = "creator-app",
|
|
permissions = { "app.open", "notifications" },
|
|
}))
|
|
|
|
assert(api.SendAppMessage(10, "creator-app", {
|
|
action = "refresh",
|
|
revision = 2,
|
|
}))
|
|
assert(#client_events == 1, "valid server app messages must emit exactly one client event")
|
|
assert(client_events[1].name == "sky_phone:custom-app:message")
|
|
assert(client_events[1].target == 10)
|
|
assert(client_events[1].arguments[1] == "creator_resource",
|
|
"the server must bind messages to the invoking owner resource")
|
|
assert(client_events[1].arguments[2] == "creator-app")
|
|
assert(client_events[1].arguments[3].action == "refresh")
|
|
|
|
local notification_success, notification_result = api.SendCustomAppNotification(
|
|
10,
|
|
"creator-app",
|
|
{
|
|
title = "Creator",
|
|
content = "Updated",
|
|
}
|
|
)
|
|
assert(notification_success and notification_result.delivered == 1)
|
|
assert(#notification_requests == 1)
|
|
assert(notification_requests[1].target.kind == "source")
|
|
assert(notification_requests[1].target.value == 10)
|
|
assert(notification_requests[1].notification.appId == "creator-app")
|
|
assert(notification_requests[1].notification.text == "Updated")
|
|
|
|
notification_success, notification_result = api.SendCustomAppNotification(
|
|
20,
|
|
"creator-app",
|
|
{
|
|
title = "Creator",
|
|
text = "Offline",
|
|
}
|
|
)
|
|
assert(not notification_success and notification_result == "device_not_equipped")
|
|
|
|
notification_success, notification_result = api.SendCustomAppNotification(
|
|
10,
|
|
"creator-app",
|
|
{
|
|
appId = "other-app",
|
|
title = "Creator",
|
|
text = "Spoofed",
|
|
}
|
|
)
|
|
assert(not notification_success and notification_result == "invalid_app_id")
|
|
|
|
local success, error_code = api.SendCustomAppMessage("10", "creator-app", {})
|
|
assert(not success and error_code == "invalid_source", "message targets must remain strictly typed")
|
|
|
|
success, error_code = api.SendCustomAppMessage(20, "creator-app", {})
|
|
assert(not success and error_code == "player_unavailable", "offline message targets must fail visibly")
|
|
|
|
success, error_code = api.SendCustomAppMessage(10, "creator-app", string.rep("x", 65))
|
|
assert(not success and error_code == "payload_too_large", "message payload limits must be server enforced")
|
|
|
|
success, error_code = api.SendCustomAppMessage(10, "creator-app", function() end)
|
|
assert(not success and error_code == "invalid_payload", "non-JSON message payloads must be rejected")
|
|
|
|
invoking_resource = "other_resource"
|
|
success, error_code = api.SendCustomAppMessage(10, "creator-app", {})
|
|
assert(not success and error_code == "app_owner_mismatch",
|
|
"a different resource must not message another owner's app")
|
|
assert(#client_events == 1, "rejected messages must not reach a client")
|
|
|
|
notification_success, notification_result = api.SendCustomAppNotification(
|
|
10,
|
|
"creator-app",
|
|
{ title = "Creator", text = "Spoofed" }
|
|
)
|
|
assert(not notification_success and notification_result == "app_owner_mismatch")
|
|
|
|
print("Custom app server messaging tests passed")
|