--[[
?? Panora Demote Plugin - Adonis Integration
?? INSTALLATION & CONFIGURATION INSTRUCTIONS
1. Insert this ModuleScript under the "Plugins" folder in your Adonis Admin 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 promotions. We recommend a minimum of 20 seconds due to delay in Roblox rank updates, which can cause incorrect behavior if users are promoted too rapidly.
?? 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 promote a player to the next rank within your defined hierarchy using the Panora API.
--]]
return function(Vargs)
local server, service = Vargs.Server, Vargs.Service
local HttpService = service.HttpService
-- β
REQUIRED CONFIGURATION
local API_KEY = "YOUR_PANORA_API_HERE" -- Replace with your Panora API key
local GROUP_ID = 000000 -- Replace with your Roblox group ID
local COOLDOWN_TIME = 20 -- Cooldown in seconds
local recentDemotions = {}
-- Define your group rank structure in order (from lowest to highest)
local ranks = {
{rankId = 1, rankName = "Member"},
{rankId = 2, rankName = "Moderator"},
{rankId = 3, rankName = "Admin"},
-- Add more ranks as needed in ascending order
}
-- DO NOT MODIFY BELOW, UNLESS YOU KNOW WHAT YOU'RE DOING!
local function findPreviousRank(currentName)
for i, rankData in ipairs(ranks) do
if rankData.rankName == currentName and ranks[i - 1] then
return ranks[i - 1]
end
end
return nil
end
local function demoteViaPanora(data)
local url = "https://api.panora.cc/v1/ranker?placeid=" .. game.GameId
local payload = HttpService:JSONEncode(data)
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
return true
else
warn("Panora Demotion Failed:", response and response.Body or response)
return false
end
end
server.Commands.PanoraDemote = {
Prefix = server.Settings.Prefix;
Commands = {"panorademote", "pdemote"};
Args = {"player"};
Description = "Demotes a player to the previous group rank using the Panora API";
AdminLevel = "Moderators";
Function = function(plr, args)
if not args[1] then
return server.Remote.MakeGui(plr, "Output", {Title = "Panora Demote"; Message = "Please specify a player."})
end
local target = service.GetPlayers(plr, args[1])[1]
if not target then
return server.Remote.MakeGui(plr, "Output", {Title = "Panora Demote"; Message = "Player not found."})
end
local last = recentDemotions[target.UserId]
if last and os.time() - last < COOLDOWN_TIME then
local waitTime = COOLDOWN_TIME - (os.time() - last)
return server.Remote.MakeGui(plr, "Output", {
Title = "Cooldown";
Message = `{target.Name} was recently demoted. Wait ${waitTime} seconds.`
})
end
local currentRankName = target:GetRoleInGroup(GROUP_ID)
local prevRank = findPreviousRank(currentRankName)
if not prevRank then
return server.Remote.MakeGui(plr, "Output", {
Title = "Already Lowest Rank";
Message = `{target.Name} is already at the lowest rank or not found in the rank list.`
})
end
local requestData = {
rankerName = plr.Name;
rankerId = plr.UserId;
rankeeName = target.Name;
rankeeId = target.UserId;
newRankId = prevRank.rankId;
oldRankName = currentRankName;
command = "demote | Adonis Integration";
prefix = server.Settings.Prefix;
webhookUrl = nil; -- Add webhookUrl if you want to send Ranking Logs (Format: "https://discord.com/api/webhooks/id/token")
}
local success = demoteViaPanora(requestData)
if success then
recentDemotions[target.UserId] = os.time()
server.Remote.MakeGui(plr, "Notification", {
Title = "Demotion Successful";
Message = `Demoted {target.Name} to {prevRank.rankName}.`;
Time = 10;
Icon = 'rbxassetid://7495462987';
})
else
server.Remote.MakeGui(plr, "Notification", {
Title = "Demotion Failed";
Message = `Could not demote {target.Name} to {prevRank.rankName}. Check logs or API Key.`;
Time = 10;
Icon = 'rbxassetid://7501176860';
})
end
end;
}
end