--[[
?? Panora Demote Plugin - BAE (Basic Admin Essentials) Integration
?? INSTALLATION & CONFIGURATION INSTRUCTIONS
1. Insert this ModuleScript under the "Plugins" folder in your Basic Admin Essentials system.
2. Navigate to https://app.panora.cc and obtain your unique API key. Replace the API_KEY variable below with that key.
3. Set your Roblox Group ID that is linked to your Panora Workspace in the GROUP_ID variable.
4. In the Panora dashboard, under the "Panora API" tab, whitelist your game's Universal Game ID to allow API access.
5. Update the `ranks` table to reflect your group's rank IDs and their exact corresponding names.
6. Set a cooldown period for demotions. We recommend a minimum of 20 seconds to avoid unexpected behavior.
?? WARNING:
Do not modify any backend logic or functionality unless you are experienced with Lua and BAE plugin structures.
Panora support will not assist with issues caused by unauthorized script modifications. You may only safely modify:
- API Key
- Group ID
- Rank definitions
- Cooldown time
??? This plugin allows authorized users to demote a player to the previous rank within your defined hierarchy using the Panora API.
--]]
local HttpService = game:GetService("HttpService")
local Plugin = function(...)
local Data = {...}
local remoteEvent = Data[1][1]
local remoteFunction = Data[1][2]
local returnPermissions = Data[1][3]
local Commands = Data[1][4]
local Prefix = Data[1][5]
local actionPrefix = Data[1][6]
local returnPlayers = Data[1][7]
local cleanData = Data[1][8]
local pluginName = script.Name
local pluginPrefix = Prefix
local pluginLevel = 2
local pluginUsage = "<username>"
local pluginDescription = "Demote a User | Panora"
-- ?? Your Panora API Key - Obtain this from https://app.panora.cc
local API_KEY = "YOUR_PANORA_API_HERE"
-- ??? Your Roblox Group ID linked with Panora Workspace
local GROUP_ID = 000000
-- ?? Rank configuration: Define your rank hierarchy here in the correct order
local ranks = {
{rankId = 1, rankName = "Member"},
{rankId = 2, rankName = "Moderator"},
-- Add more ranks as needed in ascending order
}
-- ?? Cooldown configuration to prevent repeated rapid demotions (recommended: 20 seconds)
local recentDemotions = {}
local COOLDOWN_TIME = 20
-- DO NOT MODIFY BELOW, UNLESS YOU KNOW WHAT YOU'RE DOING!
local function findPreviousRank(currentRoleName)
for i, rankData in ipairs(ranks) do
if rankData.rankName == currentRoleName and ranks[i - 1] then
return ranks[i - 1]
end
end
return nil
end
local function rankUser(rankData)
local url = "https://api.panora.cc/v1/ranker?placeid=" .. game.GameId
local payload = HttpService:JSONEncode(rankData)
local success, response = pcall(function()
return HttpService:RequestAsync({
Url = url,
Method = "POST",
Headers = {
["Authorization"] = "Bearer " .. API_KEY,
["Content-Type"] = "application/json"
},
Body = payload
})
end)
if success and response.Success then
print("? Successfully ranked:", response.Body)
return true
else
warn("? Failed to rank user:", response and response.Body or tostring(response))
return false
end
end
local function pluginFunction(Args)
local player = Args[1]
local target = Args[3]
if not target then
return "?? Please provide a username."
end
local victims = returnPlayers(player, target)
if not victims or #victims == 0 then
return "? Couldn't find player."
end
local targetPlayer = victims[1]
local lastDemoteTime = recentDemotions[targetPlayer.UserId]
if lastDemoteTime and os.time() - lastDemoteTime < COOLDOWN_TIME then
local remaining = COOLDOWN_TIME - (os.time() - lastDemoteTime)
return `{targetPlayer.Name} was recently demoted. Please wait {remaining} seconds before trying again!`
end
local currentRoleName = targetPlayer:GetRoleInGroup(GROUP_ID)
local previousRank = findPreviousRank(currentRoleName)
if not previousRank then
return "??? Already at lowest rank or current role not found in rank list."
end
local rankData = {
rankerName = player.Name,
rankerId = player.UserId,
rankeeName = targetPlayer.Name,
rankeeId = targetPlayer.UserId,
newRankId = previousRank.rankId,
oldRankName = currentRoleName,
command = "demote | BAE Integration",
prefix = Prefix,
webhookUrl = nil
}
local success = rankUser(rankData)
if success then
recentDemotions[targetPlayer.UserId] = os.time()
return `? Successfully demoted {targetPlayer.Name} to {previousRank.rankName}.`
else
return "? Demotion failed. Check logs or API key validity."
end
end
local descToReturn = pluginPrefix .. pluginName .. (pluginUsage ~= "" and (" " .. pluginUsage) or "") .. "\n" .. pluginDescription
return pluginName, pluginFunction, pluginLevel, pluginPrefix, {pluginName, pluginUsage, pluginDescription}
end
return Plugin