mirror of
https://github.com/sky-systems/sky_phone.git
synced 2026-08-29 01:01:31 +00:00
ADD - implement CrewLink location groups
This commit is contained in:
@@ -365,6 +365,29 @@ Config.MapMarkers = {
|
||||
ActionsPerMinute = 60,
|
||||
}
|
||||
|
||||
Config.CrewLink = {
|
||||
UsernameMinLength = 3,
|
||||
UsernameMaxLength = 20,
|
||||
GroupNameMinLength = 3,
|
||||
GroupNameMaxLength = 32,
|
||||
MaximumGroupsPerProfile = 5,
|
||||
MaximumMembersPerGroup = 16,
|
||||
InviteCodeLength = 8,
|
||||
InviteLifetimeSeconds = 30,
|
||||
NearbyInviteDistance = 5.0,
|
||||
NearbyScanLimit = 12,
|
||||
PingLabelMaxLength = 48,
|
||||
PingLifetimeSeconds = 300,
|
||||
MaximumActivePings = 12,
|
||||
ActionsPerMinute = 30,
|
||||
LiveRequestsPerMinute = 120,
|
||||
OverheadRefreshMilliseconds = 3000,
|
||||
OverheadDistance = 50.0,
|
||||
ExternalPingResources = {
|
||||
-- ["example_resource"] = true,
|
||||
},
|
||||
}
|
||||
|
||||
Config.Calendar = {
|
||||
TitleMaxLength = 120,
|
||||
NoteMaxLength = 2000,
|
||||
|
||||
@@ -80,6 +80,43 @@ Locales["en"] = {
|
||||
},
|
||||
},
|
||||
Apps = {
|
||||
crewlink = {
|
||||
name = "CrewLink", connecting = "Connecting your crew...", privateNetwork = "Private location network",
|
||||
signInTitle = "Connect your iFruit Account", signInBody = "CrewLink uses your private iFruit identity to keep groups and roles available across your phones.", openSettings = "Open iFruit Settings",
|
||||
welcomeEyebrow = "Your crew. One signal.", welcomeTitle = "Find your people", welcomeBody = "Choose a private CrewLink username. Only confirmed group members can see your presence and shared location.",
|
||||
username = "CrewLink username", usernamePlaceholder = "e.g. Skyline", createProfile = "Create CrewLink Profile", profileCreated = "Your CrewLink profile is ready.", privacyNote = "Private by design. No public player search.",
|
||||
noGroupEyebrow = "No active crew", noGroupTitle = "Build your private network", noGroupBody = "Create a crew or join friends with a private invitation code.",
|
||||
createGroup = "Create Group", createGroupBody = "Give your crew a recognizable name and signal colour.", joinGroup = "Join Group", joinWithCode = "Join with Code", joinWithCodeBody = "Enter the private eight-character code shared by a coordinator.",
|
||||
groupName = "Group name", groupNamePlaceholder = "e.g. Night Shift", groupColour = "Signal colour", createCrew = "Create Crew", joinCrew = "Join Crew", inviteCode = "Invitation code", inviteCodePlaceholder = "AB12CD34",
|
||||
groupCreated = "Crew created.", joinedGroup = "You joined the crew.", activeGroupChanged = "Active crew changed.", pendingInvitations = "Invitations", invitedBy = "Invited by @{username}", inviteAccepted = "Invitation accepted.", inviteDeclined = "Invitation declined.",
|
||||
navigation = "CrewLink navigation", map = "Map", crew = "Crew", pings = "Pings", profile = "Profile", onlineNow = "online now", zoomIn = "Zoom in", zoomOut = "Zoom out", myLocation = "Center my location",
|
||||
member = "Member", members = "Members", openCrew = "View team", newPing = "New Ping", shareLocation = "Mark a place", locationUnavailable = "Your live location is currently hidden.", activeCrew = "Active private crew", groupSummarySingle = "{online} of {total} member online", groupSummary = "{online} of {total} members online", private = "Private",
|
||||
nearby = "Nearby", copyCode = "Copy code", manage = "Manage", refresh = "Refresh", codeCopied = "Invitation code copied.", codeRotated = "A new invitation code is active.",
|
||||
peopleNearby = "People Nearby", peopleNearbyBody = "Only CrewLink users within {distance} meters appear here.", metersAway = "{distance} m away", invite = "Invite", inviteSent = "Invitation sent to @{username}.", nobodyNearby = "Nobody in range", nobodyNearbyBody = "Move closer to another CrewLink user and scan again.", scanAgain = "Scan Again",
|
||||
liveCoordination = "Live coordination", noPings = "No active pings", noPingsBody = "Share a meeting point, warning, or target with your crew.", expiresMinutes = "{count} min left", expiresSeconds = "{count} sec left", sharedBy = "Shared by @{username}", setRoute = "Set Route", routeSet = "GPS route set.", pingCreated = "Ping shared with your crew.", pingRemoved = "Ping removed.",
|
||||
newPingBody = "Share your current position or place the ping at the center of the map.", pingLabel = "Ping label", pingLabelPlaceholder = "e.g. Meet at the garage", placeOnMap = "Use map center", placeOnMapBody = "Otherwise your current position is used.", sharePing = "Share Ping",
|
||||
pingTypes = { meeting = "Meet", danger = "Danger", help = "Help", target = "Target", info = "Info" },
|
||||
status = { live = "Live", hidden = "Location hidden", offline = "Offline" },
|
||||
roles = { owner = "Owner", coordinator = "Coordinator", moderator = "Moderator", member = "Member", guest = "Guest" },
|
||||
roleDescriptions = { coordinator = "Manage invitations, settings, roles, and pings.", moderator = "Invite nearby users and moderate group pings.", member = "Share presence and create pings when enabled.", guest = "View the active crew without coordination permissions." },
|
||||
manageCrew = "Manage Crew", manageCrewBody = "Update identity, permissions, and invitations.", memberPings = "Member pings", memberPingsBody = "Allow members and guests to create pings.", allowOverhead = "Overhead labels", allowOverheadBody = "Permit nearby opt-in member labels in the world.", groupSaved = "Crew settings saved.",
|
||||
assignRole = "Assign Role", roleUpdated = "Member role updated.", transferOwnership = "Transfer Ownership", removeMember = "Remove from Crew", yourCrewLinkId = "Your CrewLink ID", privacyVisibility = "Privacy & Visibility", shareOnMap = "Share on group map", shareOnMapBody = "Active members can see your live position.", overheadLabels = "Nearby overhead label", overheadLabelsBody = "Show your CrewLink name to nearby opted-in members.",
|
||||
yourGroups = "Your Groups", createAnotherGroup = "Create another group", account = "CrewLink Account", externalApi = "Connected resources", externalApiBody = "Approved scripts may add temporary group pings.", editUsername = "Edit Username", editUsernameBody = "Your username is unique across CrewLink.", profileSaved = "CrewLink profile saved.", deleteGroup = "Delete Group", leaveGroup = "Leave Group", confirmAction = "Confirm",
|
||||
confirm = {
|
||||
["delete-group"] = { title = "Delete this crew?", body = "The group, memberships, invitations, and active pings will be permanently removed." },
|
||||
["leave-group"] = { title = "Leave this crew?", body = "You will lose access to its members, map, and pings." },
|
||||
["remove-member"] = { title = "Remove this member?", body = "They will immediately lose access to this crew." },
|
||||
["transfer-owner"] = { title = "Transfer ownership?", body = "The selected member becomes owner and you become coordinator." },
|
||||
},
|
||||
["delete-groupDone"] = "Crew deleted.", ["leave-groupDone"] = "You left the crew.", ["remove-memberDone"] = "Member removed.", ["transfer-ownerDone"] = "Ownership transferred.",
|
||||
notifications = { invite = "{actor} invited you to {group}.", member_joined = "{actor} joined {group}.", ping = "{actor} shared '{ping}' with {group}.", role = "Your CrewLink role changed in {group}.", removed = "You were removed from {group}.", default = "Your CrewLink group has an update." },
|
||||
errors = {
|
||||
not_authenticated = "Sign in to your iFruit Account first.", profile_required = "Create your CrewLink profile first.", invalid_username = "Use 3-20 letters, numbers, dots, or underscores.", invalid_profile = "Check your profile details.", username_taken = "That CrewLink username is already taken.",
|
||||
invalid_group = "Choose a valid group name and signal colour.", group_limit = "You have reached your group limit.", member_limit = "This group has reached its member limit.", group_not_found = "This group is no longer available.", invalid_code = "That invitation code is invalid.", already_member = "You are already a member of this group.", forbidden = "Your current role cannot perform this action.",
|
||||
player_not_nearby = "That player is no longer nearby.", player_unavailable = "That player cannot receive a CrewLink invitation.", invalid_invitation = "This invitation is invalid.", invitation_expired = "This invitation has expired.", invalid_role = "That role cannot be assigned.", owner_must_transfer = "Transfer ownership before leaving this group.",
|
||||
invalid_ping = "Choose a valid ping type, label, and position.", ping_limit = "This crew already has too many active pings.", ping_not_found = "That ping is no longer active.", rate_limited = "Too many CrewLink actions. Try again shortly.", request_failed = "CrewLink is temporarily unavailable.",
|
||||
},
|
||||
},
|
||||
flare = {
|
||||
name = "Flare", signInTitle = "Sign in to Flare", signInBody = "Flare profiles and matches are linked to your private iFruit account.",
|
||||
createProfile = "Create your profile", welcome = "Find your spark", welcomeBody = "Build a profile and meet people across Los Santos.",
|
||||
|
||||
@@ -31,6 +31,7 @@ client_scripts {
|
||||
'source/client/garage.lua',
|
||||
'source/client/skyride.lua',
|
||||
'source/client/housing.lua',
|
||||
'source/client/crewlink.lua',
|
||||
'source/bridge/client/radio.lua',
|
||||
'source/client/main.lua',
|
||||
'source/client/radio.lua',
|
||||
@@ -71,6 +72,7 @@ server_scripts {
|
||||
'source/server/picstagram.lua',
|
||||
'source/server/feather.lua',
|
||||
'source/server/map.lua',
|
||||
'source/server/crewlink.lua',
|
||||
'source/server/skyride.lua',
|
||||
'source/server/calendar.lua',
|
||||
'source/server/music.lua',
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
local overhead_members = {}
|
||||
|
||||
local function draw_overhead_label(coords, username, role)
|
||||
SetDrawOrigin(coords.x, coords.y, coords.z + 1.05, 0)
|
||||
SetTextScale(0.0, 0.29)
|
||||
SetTextFont(4)
|
||||
SetTextProportional(true)
|
||||
SetTextColour(235, 245, 255, 235)
|
||||
SetTextCentre(true)
|
||||
SetTextOutline()
|
||||
BeginTextCommandDisplayText("STRING")
|
||||
AddTextComponentSubstringPlayerName(("~b~%s~s~ %s"):format(username, role))
|
||||
EndTextCommandDisplayText(0.0, 0.0)
|
||||
ClearDrawOrigin()
|
||||
end
|
||||
|
||||
CreateThread(function()
|
||||
while true do
|
||||
local result = Bridge.Callbacks.Trigger("sky_phone:crewlink:overhead", {})
|
||||
overhead_members = result and result.success and result.data and result.data.members or {}
|
||||
Wait(Config.CrewLink.OverheadRefreshMilliseconds)
|
||||
end
|
||||
end)
|
||||
|
||||
CreateThread(function()
|
||||
while true do
|
||||
local sleep = 1000
|
||||
if #overhead_members > 0 then
|
||||
sleep = 0
|
||||
local player_coords = GetEntityCoords(PlayerPedId())
|
||||
for _, member in ipairs(overhead_members) do
|
||||
local player = GetPlayerFromServerId(member.source)
|
||||
if player ~= -1 then
|
||||
local ped = GetPlayerPed(player)
|
||||
local coords = GetEntityCoords(ped)
|
||||
if #(player_coords - coords) <= Config.CrewLink.OverheadDistance then
|
||||
draw_overhead_label(coords, member.username, member.roleLabel)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Wait(sleep)
|
||||
end
|
||||
end)
|
||||
@@ -147,6 +147,25 @@ local server_callbacks = {
|
||||
"map:markers",
|
||||
"map:create-marker",
|
||||
"map:delete-marker",
|
||||
"crewlink:bootstrap",
|
||||
"crewlink:create-profile",
|
||||
"crewlink:update-profile",
|
||||
"crewlink:create-group",
|
||||
"crewlink:update-group",
|
||||
"crewlink:delete-group",
|
||||
"crewlink:set-active",
|
||||
"crewlink:join-code",
|
||||
"crewlink:rotate-code",
|
||||
"crewlink:nearby",
|
||||
"crewlink:invite-nearby",
|
||||
"crewlink:respond-invite",
|
||||
"crewlink:update-member",
|
||||
"crewlink:transfer-owner",
|
||||
"crewlink:remove-member",
|
||||
"crewlink:leave",
|
||||
"crewlink:create-ping",
|
||||
"crewlink:remove-ping",
|
||||
"crewlink:live",
|
||||
"sim:insert",
|
||||
"sim:eject",
|
||||
"contacts:list",
|
||||
@@ -617,6 +636,22 @@ RegisterNetEvent("sky_phone:billing:new", function(data)
|
||||
SendNUIMessage({ type = "billing:new", data = data })
|
||||
end)
|
||||
|
||||
RegisterNetEvent("sky_phone:crewlink:changed", function(data)
|
||||
SendNUIMessage({ type = "crewlink:changed", data = data })
|
||||
end)
|
||||
|
||||
RegisterNetEvent("sky_phone:crewlink:notification", function(data)
|
||||
local crewlink_locale = get_locale().Nui.Apps.crewlink
|
||||
local notification_text = crewlink_locale.notifications[data.kind]
|
||||
or crewlink_locale.notifications.default
|
||||
data.title = crewlink_locale.name
|
||||
data.text = notification_text
|
||||
:gsub("{actor}", tostring(data.actor or ""))
|
||||
:gsub("{group}", tostring(data.groupName or ""))
|
||||
:gsub("{ping}", tostring(data.pingLabel or ""))
|
||||
SendNUIMessage({ type = "crewlink:notification", data = data })
|
||||
end)
|
||||
|
||||
RegisterNetEvent("sky_phone:messages:changed", function(data)
|
||||
SendNUIMessage({ type = "messages:changed", data = data })
|
||||
end)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1947,6 +1947,128 @@ local schema = {
|
||||
},
|
||||
tableOptions = "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||||
},
|
||||
{
|
||||
name = "sky_phone_crewlink_profiles",
|
||||
columns = {
|
||||
{ name = "id", type = "CHAR(36) NOT NULL", characterSet = "ascii", collation = "ascii_bin" },
|
||||
{ name = "account_id", type = "BIGINT UNSIGNED NOT NULL" },
|
||||
{ name = "username", type = "VARCHAR(20) NOT NULL", characterSet = "ascii", collation = "ascii_general_ci" },
|
||||
{ name = "active_group_id", type = "CHAR(36) NULL", characterSet = "ascii", collation = "ascii_bin" },
|
||||
{ name = "map_visible", type = "TINYINT(1) NOT NULL DEFAULT 1" },
|
||||
{ name = "overhead_visible", type = "TINYINT(1) NOT NULL DEFAULT 0" },
|
||||
{ name = "created_at", type = "DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP" },
|
||||
{ name = "updated_at", type = "DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" },
|
||||
},
|
||||
primaryKey = "id",
|
||||
uniqueKeys = {
|
||||
{ name = "uniq_sky_phone_crewlink_account", columns = "(`account_id`)" },
|
||||
{ name = "uniq_sky_phone_crewlink_username", columns = "(`username`)" },
|
||||
},
|
||||
indexes = {
|
||||
{ name = "idx_sky_phone_crewlink_active", columns = "(`active_group_id`)" },
|
||||
},
|
||||
foreignKeys = {
|
||||
{ column = "account_id", references = "`sky_phone_accounts` (`id`) ON DELETE CASCADE" },
|
||||
},
|
||||
tableOptions = "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||||
},
|
||||
{
|
||||
name = "sky_phone_crewlink_groups",
|
||||
columns = {
|
||||
{ name = "id", type = "CHAR(36) NOT NULL", characterSet = "ascii", collation = "ascii_bin" },
|
||||
{ name = "name", type = "VARCHAR(32) NOT NULL" },
|
||||
{ name = "colour", type = "ENUM('cyan','blue','violet','orange','green','rose') NOT NULL DEFAULT 'cyan'" },
|
||||
{ name = "owner_profile_id", type = "CHAR(36) NOT NULL", characterSet = "ascii", collation = "ascii_bin" },
|
||||
{ name = "invite_code", type = "VARCHAR(12) NOT NULL", characterSet = "ascii", collation = "ascii_bin" },
|
||||
{ name = "allow_member_pings", type = "TINYINT(1) NOT NULL DEFAULT 1" },
|
||||
{ name = "overhead_allowed", type = "TINYINT(1) NOT NULL DEFAULT 1" },
|
||||
{ name = "created_at", type = "DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP" },
|
||||
{ name = "updated_at", type = "DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" },
|
||||
},
|
||||
primaryKey = "id",
|
||||
uniqueKeys = {
|
||||
{ name = "uniq_sky_phone_crewlink_invite_code", columns = "(`invite_code`)" },
|
||||
},
|
||||
indexes = {
|
||||
{ name = "idx_sky_phone_crewlink_owner", columns = "(`owner_profile_id`)" },
|
||||
},
|
||||
foreignKeys = {
|
||||
{ column = "owner_profile_id", references = "`sky_phone_crewlink_profiles` (`id`) ON DELETE CASCADE" },
|
||||
},
|
||||
tableOptions = "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||||
},
|
||||
{
|
||||
name = "sky_phone_crewlink_memberships",
|
||||
columns = {
|
||||
{ name = "id", type = "BIGINT UNSIGNED NOT NULL AUTO_INCREMENT" },
|
||||
{ name = "group_id", type = "CHAR(36) NOT NULL", characterSet = "ascii", collation = "ascii_bin" },
|
||||
{ name = "profile_id", type = "CHAR(36) NOT NULL", characterSet = "ascii", collation = "ascii_bin" },
|
||||
{ name = "role", type = "ENUM('owner','coordinator','moderator','member','guest') NOT NULL DEFAULT 'member'" },
|
||||
{ name = "joined_at", type = "DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP" },
|
||||
},
|
||||
primaryKey = "id",
|
||||
uniqueKeys = {
|
||||
{ name = "uniq_sky_phone_crewlink_membership", columns = "(`group_id`, `profile_id`)" },
|
||||
},
|
||||
indexes = {
|
||||
{ name = "idx_sky_phone_crewlink_profile_groups", columns = "(`profile_id`, `joined_at`)" },
|
||||
},
|
||||
foreignKeys = {
|
||||
{ column = "group_id", references = "`sky_phone_crewlink_groups` (`id`) ON DELETE CASCADE" },
|
||||
{ column = "profile_id", references = "`sky_phone_crewlink_profiles` (`id`) ON DELETE CASCADE" },
|
||||
},
|
||||
tableOptions = "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||||
},
|
||||
{
|
||||
name = "sky_phone_crewlink_invitations",
|
||||
columns = {
|
||||
{ name = "id", type = "CHAR(36) NOT NULL", characterSet = "ascii", collation = "ascii_bin" },
|
||||
{ name = "group_id", type = "CHAR(36) NOT NULL", characterSet = "ascii", collation = "ascii_bin" },
|
||||
{ name = "inviter_profile_id", type = "CHAR(36) NOT NULL", characterSet = "ascii", collation = "ascii_bin" },
|
||||
{ name = "invitee_profile_id", type = "CHAR(36) NOT NULL", characterSet = "ascii", collation = "ascii_bin" },
|
||||
{ name = "status", type = "ENUM('pending','accepted','declined','expired') NOT NULL DEFAULT 'pending'" },
|
||||
{ name = "expires_at", type = "DATETIME NOT NULL" },
|
||||
{ name = "created_at", type = "DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP" },
|
||||
},
|
||||
primaryKey = "id",
|
||||
uniqueKeys = {
|
||||
{ name = "uniq_sky_phone_crewlink_pending_invite", columns = "(`group_id`, `invitee_profile_id`)" },
|
||||
},
|
||||
indexes = {
|
||||
{ name = "idx_sky_phone_crewlink_invitee", columns = "(`invitee_profile_id`, `status`, `expires_at`)" },
|
||||
},
|
||||
foreignKeys = {
|
||||
{ column = "group_id", references = "`sky_phone_crewlink_groups` (`id`) ON DELETE CASCADE" },
|
||||
{ column = "inviter_profile_id", references = "`sky_phone_crewlink_profiles` (`id`) ON DELETE CASCADE" },
|
||||
{ column = "invitee_profile_id", references = "`sky_phone_crewlink_profiles` (`id`) ON DELETE CASCADE" },
|
||||
},
|
||||
tableOptions = "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||||
},
|
||||
{
|
||||
name = "sky_phone_crewlink_pings",
|
||||
columns = {
|
||||
{ name = "id", type = "CHAR(36) NOT NULL", characterSet = "ascii", collation = "ascii_bin" },
|
||||
{ name = "group_id", type = "CHAR(36) NOT NULL", characterSet = "ascii", collation = "ascii_bin" },
|
||||
{ name = "creator_profile_id", type = "CHAR(36) NULL", characterSet = "ascii", collation = "ascii_bin" },
|
||||
{ name = "source_resource", type = "VARCHAR(64) NULL", characterSet = "ascii", collation = "ascii_general_ci" },
|
||||
{ name = "type", type = "ENUM('meeting','danger','help','target','info') NOT NULL" },
|
||||
{ name = "label", type = "VARCHAR(48) NOT NULL" },
|
||||
{ name = "position_x", type = "DECIMAL(10,3) NOT NULL" },
|
||||
{ name = "position_y", type = "DECIMAL(10,3) NOT NULL" },
|
||||
{ name = "position_z", type = "DECIMAL(10,3) NOT NULL" },
|
||||
{ name = "expires_at", type = "DATETIME NOT NULL" },
|
||||
{ name = "created_at", type = "DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP" },
|
||||
},
|
||||
primaryKey = "id",
|
||||
indexes = {
|
||||
{ name = "idx_sky_phone_crewlink_pings", columns = "(`group_id`, `expires_at`)" },
|
||||
},
|
||||
foreignKeys = {
|
||||
{ column = "group_id", references = "`sky_phone_crewlink_groups` (`id`) ON DELETE CASCADE" },
|
||||
{ column = "creator_profile_id", references = "`sky_phone_crewlink_profiles` (`id`) ON DELETE SET NULL" },
|
||||
},
|
||||
tableOptions = "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||||
},
|
||||
}
|
||||
|
||||
Bridge.Database.Migrate("sky_phone", schema)
|
||||
|
||||
@@ -850,3 +850,82 @@ CREATE TABLE IF NOT EXISTS `sky_phone_feather_reports` (
|
||||
FOREIGN KEY (`reporter_id`) REFERENCES `sky_phone_feather_profiles` (`id`) ON DELETE CASCADE,
|
||||
FOREIGN KEY (`post_id`) REFERENCES `sky_phone_feather_posts` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `sky_phone_crewlink_profiles` (
|
||||
`id` CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
||||
`account_id` BIGINT UNSIGNED NOT NULL,
|
||||
`username` VARCHAR(20) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,
|
||||
`active_group_id` CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NULL,
|
||||
`map_visible` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`overhead_visible` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uniq_sky_phone_crewlink_account` (`account_id`),
|
||||
UNIQUE KEY `uniq_sky_phone_crewlink_username` (`username`),
|
||||
KEY `idx_sky_phone_crewlink_active` (`active_group_id`),
|
||||
FOREIGN KEY (`account_id`) REFERENCES `sky_phone_accounts` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `sky_phone_crewlink_groups` (
|
||||
`id` CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
||||
`name` VARCHAR(32) NOT NULL,
|
||||
`colour` ENUM('cyan','blue','violet','orange','green','rose') NOT NULL DEFAULT 'cyan',
|
||||
`owner_profile_id` CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
||||
`invite_code` VARCHAR(12) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
||||
`allow_member_pings` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`overhead_allowed` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uniq_sky_phone_crewlink_invite_code` (`invite_code`),
|
||||
KEY `idx_sky_phone_crewlink_owner` (`owner_profile_id`),
|
||||
FOREIGN KEY (`owner_profile_id`) REFERENCES `sky_phone_crewlink_profiles` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `sky_phone_crewlink_memberships` (
|
||||
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`group_id` CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
||||
`profile_id` CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
||||
`role` ENUM('owner','coordinator','moderator','member','guest') NOT NULL DEFAULT 'member',
|
||||
`joined_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uniq_sky_phone_crewlink_membership` (`group_id`,`profile_id`),
|
||||
KEY `idx_sky_phone_crewlink_profile_groups` (`profile_id`,`joined_at`),
|
||||
FOREIGN KEY (`group_id`) REFERENCES `sky_phone_crewlink_groups` (`id`) ON DELETE CASCADE,
|
||||
FOREIGN KEY (`profile_id`) REFERENCES `sky_phone_crewlink_profiles` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `sky_phone_crewlink_invitations` (
|
||||
`id` CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
||||
`group_id` CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
||||
`inviter_profile_id` CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
||||
`invitee_profile_id` CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
||||
`status` ENUM('pending','accepted','declined','expired') NOT NULL DEFAULT 'pending',
|
||||
`expires_at` DATETIME NOT NULL,
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uniq_sky_phone_crewlink_pending_invite` (`group_id`,`invitee_profile_id`),
|
||||
KEY `idx_sky_phone_crewlink_invitee` (`invitee_profile_id`,`status`,`expires_at`),
|
||||
FOREIGN KEY (`group_id`) REFERENCES `sky_phone_crewlink_groups` (`id`) ON DELETE CASCADE,
|
||||
FOREIGN KEY (`inviter_profile_id`) REFERENCES `sky_phone_crewlink_profiles` (`id`) ON DELETE CASCADE,
|
||||
FOREIGN KEY (`invitee_profile_id`) REFERENCES `sky_phone_crewlink_profiles` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `sky_phone_crewlink_pings` (
|
||||
`id` CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
||||
`group_id` CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
||||
`creator_profile_id` CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NULL,
|
||||
`source_resource` VARCHAR(64) CHARACTER SET ascii COLLATE ascii_general_ci NULL,
|
||||
`type` ENUM('meeting','danger','help','target','info') NOT NULL,
|
||||
`label` VARCHAR(48) NOT NULL,
|
||||
`position_x` DECIMAL(10,3) NOT NULL,
|
||||
`position_y` DECIMAL(10,3) NOT NULL,
|
||||
`position_z` DECIMAL(10,3) NOT NULL,
|
||||
`expires_at` DATETIME NOT NULL,
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_sky_phone_crewlink_pings` (`group_id`,`expires_at`),
|
||||
FOREIGN KEY (`group_id`) REFERENCES `sky_phone_crewlink_groups` (`id`) ON DELETE CASCADE,
|
||||
FOREIGN KEY (`creator_profile_id`) REFERENCES `sky_phone_crewlink_profiles` (`id`) ON DELETE SET NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
Reference in New Issue
Block a user