Compare commits

..

1 Commits

Author SHA1 Message Date
pizzaboxer f8eac67dac lmao 2022-12-31 16:14:53 +00:00
54 changed files with 1618 additions and 725 deletions

9
XD.php
View File

@ -1,9 +0,0 @@
<?php require $_SERVER['DOCUMENT_ROOT']."/api/private/core.php";
$pageBuilder = new PageBuilder();
$pageBuilder->buildHeader();
?>
Do not run <code>game:HttpGet("http://polygon.pizzaboxer.xyz/XD")</code> in studio
please no
Plz
<?php $pageBuilder->buildFooter();

View File

@ -63,7 +63,7 @@ $pageBuilder->buildHeader();
<a class="btn btn-outline-primary btn-lg btn-block px-0" href="/admin/site-banners"><i class="fal fa-bullhorn"></i> Site banners</a>
</div>
<div class="col-md-4 py-2 px-1">
<a class="btn btn-outline-primary btn-lg btn-block px-0" href="#" onclick="polygon.buildModal({header: 'coming soon', body: 'Sample Text', buttons: [{class:'btn btn-primary px-4', dismiss:true, text:'OK'}]});"><i class="fal fa-rss-square"></i> Newsfeed</a>
<a class="btn btn-outline-primary btn-lg btn-block px-0" href="/admin/newsfeed"><i class="fal fa-rss-square"></i> Newsfeed</a>
</div>
<div class="col-md-4 py-2 px-1">
<a class="btn btn-outline-primary btn-lg btn-block px-0" href="/admin/staff-audit"><i class="fal fa-book"></i> Audit log</a>

1
ads.txt Normal file
View File

@ -0,0 +1 @@
google.com, pub-3972374207754919, DIRECT, f08c47fec0942fa0

View File

@ -12,8 +12,12 @@ $DeleteQuery = Database::singleton()->run(
[":AssetID" => $AssetID, ":UserID" => SESSION["user"]["id"]]
);
if (!$DeleteQuery->rowCount()) API::respond(200, false, "You do not own this asset");
if (!$DeleteQuery->rowCount())
API::respond(200, false, "You do not own this asset");
Database::singleton()->run("UPDATE assets SET Sales = Sales - 1 WHERE id = :AssetID", [":AssetID" => $AssetID]);
$assetCreatorId = Database::singleton()->run("SELECT creator FROM assets WHERE id = :assetId", [":assetId" => $AssetID])->fetchColumn();
API::respond(200, true, "OK");
if ($assetCreatorId != SESSION["user"]["id"])
Database::singleton()->run("UPDATE assets SET Sales = Sales - 1 WHERE id = :AssetID", [":AssetID" => $AssetID]);
API::respond(200, true, "OK");

View File

@ -0,0 +1,28 @@
<?php require $_SERVER['DOCUMENT_ROOT'].'/api/private/core.php';
use pizzaboxer\ProjectPolygon\Database;
use pizzaboxer\ProjectPolygon\API;
API::initialize(["method" => "GET", "logged_in" => true]);
$items = [];
$friends = Database::singleton()->run(
"SELECT friends.*, users.username, users.id AS userId FROM friends
INNER JOIN users ON users.id = (CASE WHEN requesterId = :uid THEN receiverId ELSE requesterId END)
WHERE :uid IN (requesterId, receiverId) AND friends.status = 1",
[":uid" => SESSION["user"]["id"]]
);
while ($friend = $friends->fetch())
{
$items[] = [
"UserID" => (int)$friend["userId"],
"Username" => $friend["username"],
"TimeRequested" => date('c', $friend["timeSent"])
];
}
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . SESSION["user"]["id"] . '-friends.json"');
echo json_encode($items, JSON_PRETTY_PRINT);

137
api/account/data/groups.php Normal file
View File

@ -0,0 +1,137 @@
<?php require $_SERVER['DOCUMENT_ROOT'].'/api/private/core.php';
use pizzaboxer\ProjectPolygon\Database;
use pizzaboxer\ProjectPolygon\API;
API::initialize(["method" => "GET", "logged_in" => true]);
$items = [];
$groups = Database::singleton()->run(
"SELECT * FROM groups WHERE creator = :uid",
[":uid" => SESSION["user"]["id"]]
);
while ($group = $groups->fetch())
{
// relationships
$relationships = Database::singleton()->run(
"SELECT groups_relationships.*, groups.id AS RelatingGroupID, groups.name AS RelatingGroupName FROM groups_relationships
INNER JOIN groups ON groups.id = (CASE WHEN Declarer = :groupId THEN Recipient ELSE Declarer END)
WHERE :groupId IN (Declarer, Recipient) AND Established IS NOT NULL",
[":groupId" => $group["id"]]
);
$groupRelationships = [];
while ($relationship = $relationships->fetch())
{
$groupRelationships[] = [
"Type" => $relationship["Type"],
"RelatingGroupID" => (int)$relationship["RelatingGroupID"],
"RelatingGroupName" => $relationship["RelatingGroupName"],
"TimeDeclared" => date('c', $relationship["Declared"]),
"TimeEstablished" => date('c', $relationship["Established"]),
"TimeBroken" => $relationship["Broken"] > 0 ? date('c', $relationship["Broken"]) : null,
];
}
// ranks
$ranks = Database::singleton()->run(
"SELECT * FROM groups_ranks WHERE GroupID = :groupId
ORDER BY rank ASC",
[":groupId" => $group["id"]]
);
$groupRanks = [];
while ($rank = $ranks->fetch())
{
$groupRanks[] = [
"Rank" => (int)$rank["Rank"],
"Name" => $rank["Name"],
"Description" => $rank["Description"],
"TimeCreated" => date('c', $rank["Created"]),
"Permissions" => json_decode($rank["Permissions"])
];
}
// members
$members = Database::singleton()->run(
"SELECT groups_members.*, users.username AS UserName FROM groups_members
INNER JOIN users ON users.id = UserID WHERE GroupID = :groupId",
[":groupId" => $group["id"]]
);
$groupMembers = [];
while ($member = $members->fetch())
{
$groupMembers[] = [
"UserID" => (int)$member["UserID"],
"UserName" => $member["UserName"],
"Rank" => (int)$member["Rank"],
"TimeJoined" => date('c', $member["Joined"])
];
}
// wall
$wallPosts = Database::singleton()->run(
"SELECT groups_wall.*, users.username AS PosterName FROM groups_wall
INNER JOIN users ON users.id = PosterID WHERE GroupID = :groupId",
[":groupId" => $group["id"]]
);
$groupWall = [];
while ($wallPost = $wallPosts->fetch())
{
$groupWall[] = [
"UserID" => (int)$wallPost["PosterID"],
"UserName" => $wallPost["PosterName"],
"Content" => $wallPost["Content"],
"TimePosted" => date('c', $wallPost["TimePosted"])
];
}
// audit
$auditLogs = Database::singleton()->run(
"SELECT groups_audit.*, users.username AS UserName FROM groups_audit
INNER JOIN users ON users.id = UserID WHERE GroupID = :groupId",
[":groupId" => $group["id"]]
);
$groupAudit = [];
while ($auditLog = $auditLogs->fetch())
{
$groupAudit[] = [
"UserID" => (int)$auditLog["UserID"],
"UserName" => $auditLog["UserName"],
"Category" => $auditLog["Category"],
"Description" => $auditLog["Description"],
"TimeCreated" => date('c', $auditLog["Time"])
];
}
$items[] = [
"ID" => (int)$group["id"],
"Name" => $group["name"],
"Description" => $group["description"],
"TimeCreated" => date('c', $group["created"]),
"Relationships" => $groupRelationships,
"Ranks" => $groupRanks,
"Members" => $groupMembers,
"Wall" => $groupWall,
"Audit" => $groupAudit
];
}
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . SESSION["user"]["id"] . '-groups.json"');
echo json_encode($items, JSON_PRETTY_PRINT);

View File

@ -0,0 +1,45 @@
<?php require $_SERVER['DOCUMENT_ROOT'].'/api/private/core.php';
use pizzaboxer\ProjectPolygon\Database;
use pizzaboxer\ProjectPolygon\API;
use pizzaboxer\ProjectPolygon\Catalog;
API::initialize(["method" => "GET", "logged_in" => true]);
$items = [];
$assets = Database::singleton()->run(
"SELECT assets.*, users.username,
ownedAssets.wearing, ownedAssets.last_toggle, ownedAssets.timestamp FROM ownedAssets
INNER JOIN assets ON assets.id = assetId
INNER JOIN users ON creator = users.id
WHERE userId = :uid",
[":uid" => SESSION["user"]["id"]]
);
while ($asset = $assets->fetch())
{
$items[] = [
"AssetID" => (int)$asset["id"],
"AssetName" => $asset["name"],
"AssetDescription" => $asset["description"],
"AssetType" => Catalog::GetTypeByNum($asset["type"]),
"AssetTypeID" => (int)$asset["type"],
"AssetSales" => (int)$asset["Sales"],
"AssetPrice" => (bool)$asset["sale"] ? (int)$asset["price"] : null,
"AssetIsForSale" => (bool)$asset["sale"],
"AssetIsCopylocked" => (bool)!$asset["publicDomain"],
"AssetCreatorID" => (int)$asset["creator"],
"AssetCreatorName" => $asset["username"],
"TimeAssetCreated" => date('c', $asset["created"]),
"TimeAssetUpdated" => date('c', $asset["updated"]),
"Wearing" => (bool)$asset["wearing"],
"TimeLastWorn" => $asset["last_toggle"] > 0 ? date('c', $asset["last_toggle"]) : null,
"TimeObtained" => date('c', $asset["timestamp"])
];
}
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . SESSION["user"]["id"] . '-inventory.json"');
echo json_encode($items, JSON_PRETTY_PRINT);

View File

@ -0,0 +1,36 @@
<?php require $_SERVER['DOCUMENT_ROOT'].'/api/private/core.php';
use pizzaboxer\ProjectPolygon\Database;
use pizzaboxer\ProjectPolygon\API;
use pizzaboxer\ProjectPolygon\Catalog;
API::initialize(["method" => "GET", "logged_in" => true]);
$items = [];
$transactions = Database::singleton()->run(
"SELECT transactions.*, users.username, users.id AS userId, assets.name, assets.type FROM transactions
INNER JOIN users ON users.id = (CASE WHEN seller = :UserID THEN purchaser ELSE seller END)
INNER JOIN assets ON assets.id = transactions.assetId
WHERE :UserID IN (seller, purchaser)",
[":UserID" => SESSION["user"]["id"]]
);
while ($transaction = $transactions->fetch())
{
$items[] = [
"TransactionType" => $transaction["seller"] == SESSION["user"]["id"] ? "Sale" : "Purchase",
"TransactionAmount" => (int)$transaction["amount"],
"TransactionUserID" => (int)$transaction["userId"],
"TransactionUsername" => $transaction["username"],
"AssetID" => (int)$transaction["assetId"],
"AssetName" => $transaction["name"],
"AssetType" => Catalog::GetTypeByNum($transaction["type"]),
"AssetTypeID" => (int)$transaction["type"],
"TimeTransacted" => date('c', $transaction["timestamp"])
];
}
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . SESSION["user"]["id"] . '-transactions.json"');
echo json_encode($items, JSON_PRETTY_PRINT);

View File

@ -26,14 +26,20 @@ $FeedResults = Database::singleton()->run(
[":uid" => SESSION["user"]["id"]]
);
/* $NewsResults = Database::singleton()->run(
"SELECT * FROM feed_news WHERE time_deleted IS NULL ORDER BY id DESC LIMIT 1"
);
$FetchNews = $NewsResults->fetch(PDO::FETCH_OBJ); */
$feed = [];
$news = [];
/*$news[] =
/* $news[] =
[
"header" => '<h4 class="font-weight-normal">lol</h4>',
"message" => 'fucked your mom'
];*/
"header" => '<h4 class="font-weight-normal">'.$FetchNews->title.'</h4>',
"message" => Polygon::FilterText($markdown->setEmbedsEnabled(true)->text($FetchNews->body),false)
]; */
/*$news[] =
[

View File

@ -12,12 +12,12 @@ $row = (object)SESSION["user"];
$currentpwd = new Password($_POST['currentpwd']);
$newpwd = new Password($_POST['newpwd']);
if($row->lastpwdchange+1800 > time()) API::respond(429, false, "Please wait ".ceil((($row->lastpwdchange+1800)-time())/60)." minutes before attempting to change your password again");
if(!$currentpwd->verify($row->password)) API::respond(400, false, "Your current password does not match");
if($_POST['currentpwd'] == $_POST['newpwd']) API::respond(400, false, "Your new password cannot be the same as your current one");
if(strlen(preg_replace('/[0-9]/', "", $_POST['newpwd'])) < 6) API::respond(400, false, "Your new password is too weak. Make sure it contains at least six non-numeric characters");
if(strlen(preg_replace('/[^0-9]/', "", $_POST['newpwd'])) < 2) API::respond(400, false, "Your new password is too weak. Make sure it contains at least two numbers");
if($_POST['newpwd'] != $_POST['confnewpwd']) API::respond(400, false, "Confirmation password does not match");
if($row->lastpwdchange+1800 > time()) API::respond(200, false, "Please wait ".ceil((($row->lastpwdchange+1800)-time())/60)." minutes before attempting to change your password again");
if(!$currentpwd->verify($row->password)) API::respond(200, false, "Your current password does not match");
if($_POST['currentpwd'] == $_POST['newpwd']) API::respond(200, false, "Your new password cannot be the same as your current one");
if(strlen(preg_replace('/[0-9]/', "", $_POST['newpwd'])) < 6) API::respond(200, false, "Your new password is too weak. Make sure it contains at least six non-numeric characters");
if(strlen(preg_replace('/[^0-9]/', "", $_POST['newpwd'])) < 2) API::respond(200, false, "Your new password is too weak. Make sure it contains at least two numbers");
if($_POST['newpwd'] != $_POST['confnewpwd']) API::respond(200, false, "Confirmation password does not match");
$newpwd->update($userid);
API::respond(200, true, "OK");
API::respond(200, true, "OK");

25
api/admin/delete-news.php Normal file
View File

@ -0,0 +1,25 @@
<?php require $_SERVER['DOCUMENT_ROOT'].'/api/private/core.php';
use pizzaboxer\ProjectPolygon\Database;
use pizzaboxer\ProjectPolygon\Users;
use pizzaboxer\ProjectPolygon\API;
use pizzaboxer\ProjectPolygon\Polygon;
API::initialize(["method" => "POST", "admin" => Users::STAFF_ADMINISTRATOR, "admin_ratelimit" => true, "secure" => true]);
if(!isset($_POST["id"])){ API::respond(400, false, "Invalid Request"); }
$postID = $_POST["id"];
$query = Database::singleton()->run("SELECT * FROM feed_news WHERE time_deleted IS NOT NULL AND id = :id", [":id" => $postID]);
$postInfo = $query->fetch(PDO::FETCH_OBJ);
if(!$postInfo) { API::respond(400, false, "Bad Request"); }
Database::singleton()->run(
"UPDATE feed_news SET time_deleted = UNIX_TIMESTAMP() WHERE id = :id)",
[":id" => $id]
);
Users::LogStaffAction("[ Feed ] ".SESSION["user"]["username"]." deleted a post titled ".Polygon::FilterText($postInfo->title).". ( user ID ".SESSION["user"]["id"]." ) ( Reason: N/A )");
API::respond(200, true, "Deleted successfully.");

View File

@ -6,13 +6,13 @@ use pizzaboxer\ProjectPolygon\API;
API::initialize(["method" => "POST", "admin" => Users::STAFF_ADMINISTRATOR, "admin_ratelimit" => true, "secure" => true]);
if(SESSION["user"]["id"] != 1){ API::respond(400, false, "Insufficient admin level"); }
if(SESSION["user"]["id"] != 6){ API::respond(400, false, "Insufficient admin level"); }
if(!isset($_POST["username"]) || !isset($_POST["amount"]) || !isset($_POST["reason"])){ API::respond(400, false, "Invalid Request"); }
if(!trim($_POST["username"])){ API::respond(400, false, "You haven't set a username"); }
if(!$_POST["amount"]){ API::respond(400, false, "You haven't set the amount of ".SITE_CONFIG["site"]["currency"]." to give"); }
if(!is_numeric($_POST["amount"])){ API::respond(400, false, "The amount of ".SITE_CONFIG["site"]["currency"]." to give must be numerical"); }
if($_POST["amount"] > 500 || $_POST["amount"] < -500){ API::respond(400, false, "Maximum amount of ".SITE_CONFIG["site"]["currency"]." you can give/take is 500 at a time"); }
if($_POST["amount"] > 20000 || $_POST["amount"] < -500){ API::respond(400, false, "Maximum amount of ".SITE_CONFIG["site"]["currency"]." you can give/take is 500 at a time"); }
if(!trim($_POST["reason"])){ API::respond(400, false, "You must set a reason"); }
@ -27,4 +27,4 @@ Database::singleton()->run(
);
Users::LogStaffAction("[ Currency ] Gave ".$_POST["amount"]." ".SITE_CONFIG["site"]["currency"]." to ".$userInfo->username." ( user ID ".$userInfo->id." ) ( Reason: ".$_POST["reason"]." )");
API::respond(200, true, "Gave ".$_POST["amount"]." ".SITE_CONFIG["site"]["currency"]." to ".$userInfo->username);
API::respond(200, true, "Gave ".$_POST["amount"]." ".SITE_CONFIG["site"]["currency"]." to ".$userInfo->username);

27
api/admin/post-news.php Normal file
View File

@ -0,0 +1,27 @@
<?php require $_SERVER['DOCUMENT_ROOT'].'/api/private/core.php';
use pizzaboxer\ProjectPolygon\Database;
use pizzaboxer\ProjectPolygon\Users;
use pizzaboxer\ProjectPolygon\API;
use pizzaboxer\ProjectPolygon\Polygon;
API::initialize(["method" => "POST", "admin" => Users::STAFF_ADMINISTRATOR, "admin_ratelimit" => true, "secure" => true]);
if(!isset($_POST["title"]) || !isset($_POST["body"])){ API::respond(400, false, "Invalid Request"); }
if(!trim($_POST["title"])){ API::respond(400, false, "You haven't set a title."); }
if(!trim($_POST["body"])){ API::respond(400, false, "You haven't set a body."); }
if(strlen($_POST["title"]) < 3 || strlen($_POST["title"]) > 64){ API::respond(400, false, "The title should be less than 64 characters and greater than 3."); }
if(strlen($_POST["body"]) < 3 || strlen($_POST["body"] > 1024)){ API::respond(400, false, "The body should be less than 1024 characters and greater than 3."); }
$title = $_POST["title"];
$body = $_POST["body"];
Database::singleton()->run(
"INSERT INTO feed_news (title, body, user_id, time_created) VALUES (:title, :body, :user_id, UNIX_TIMESTAMP())",
[":title" => $title, ":body" => $body, ":user_id" => SESSION["user"]["id"]]
);
Users::LogStaffAction("[ Feed ] ".SESSION["user"]["username"]." published a new post titled ".Polygon::FilterText($title).". ( user ID ".SESSION["user"]["id"]." ) ( Reason: N/A )");
API::respond(200, true, "Posted successfully.");

View File

@ -15,13 +15,6 @@ $bannedUntil = strtotime($_POST["until"]." ".date('G:i:s'));
if($bannedUntil < strtotime('tomorrow')){ API::respond(400, false, "Ban time must be at least 1 day long"); }
//markdown
$markdown = new Parsedown();
$markdown->setMarkupEscaped(true);
$markdown->setBreaksEnabled(true);
$markdown->setSafeMode(true);
$markdown->setUrlsLinked(true);
$text =
[
"title" =>
@ -53,7 +46,7 @@ ob_start(); ?>
<p class="card-text mb-0">Reason:</p>
<div class="card">
<div class="card-body p-2">
<?=str_replace('<p>', '<p class="mb-0">', $markdown->text($_POST["moderationNote"], true))?>
<?=str_replace('<p>', '<p class="mb-0">', $markdown->setEmbedsEnabled(true)->text($_POST["moderationNote"]))?>
</div>
</div>
<br>

View File

@ -59,14 +59,17 @@ Database::singleton()->run(
[":aid" => $id, ":uid" => $uid]
);
Database::singleton()->run(
"INSERT INTO transactions (purchaser, seller, assetId, amount, flagged, timestamp)
VALUES (:uid, :sid, :aid, :price, :flagged, UNIX_TIMESTAMP())",
[":uid" => $uid, ":sid" => $item->creator, ":aid" => $id, ":price" => $item->price, ":flagged" => (int)$IsAlt]
);
Database::singleton()->run("UPDATE assets SET Sales = Sales + 1 WHERE id = :AssetID", [":AssetID" => $id]);
if ($item->creator != SESSION["user"]["id"])
{
Database::singleton()->run(
"INSERT INTO transactions (purchaser, seller, assetId, amount, flagged, timestamp)
VALUES (:uid, :sid, :aid, :price, :flagged, UNIX_TIMESTAMP())",
[":uid" => $uid, ":sid" => $item->creator, ":aid" => $id, ":price" => $item->price, ":flagged" => (int)$IsAlt]
);
Database::singleton()->run("UPDATE assets SET Sales = Sales + 1 WHERE id = :AssetID", [":AssetID" => $id]);
}
die(json_encode(
[
"status" => 200,
@ -76,4 +79,4 @@ die(json_encode(
"image" => Thumbnails::GetAsset($item),
"text" => "You have successfully purchased the ".htmlspecialchars($item->name)." ".Catalog::GetTypeByNum($item->type)." from ".$item->username." for ".getPrice($item->price),
"buttons" => [['class' => 'btn btn-primary continue-shopping', 'dismiss' => true, 'text' => 'Continue Shopping']],
]));
]));

View File

@ -85,7 +85,8 @@ while ($Place = $Places->fetch(\PDO::FETCH_OBJ))
[
"PlaceID" => (int) $Place->id,
"Name" => Polygon::FilterText($Place->name),
"Description" => Polygon::FilterText($Place->description),
// "Description" => Polygon::FilterText($Place->description),
"Description" => Polygon::FilterText($markdown->setEmbedsEnabled(true)->line($Place->description), false),
"Visits" => number_format($Place->Visits),
"OnlinePlayers" => $Place->ServerRunning ? number_format($Place->ActivePlayers) : false,
"Location" => "/" . encode_asset_name($Place->name) . "-place?id={$Place->id}",

View File

@ -230,8 +230,34 @@ game:GetService("Players").PlayerAdded:connect(function(player)
player.Chatted:connect(function(message, recipient)
print("[" .. player.Name .. "]: " .. message)
-- 1 : needs semicolon
-- 2 : doesn't need semicolon
local commands = {
["ec"] = 1,
["energycell"] = 1,
["reset"] = 1,
["kys"] = 1,
["xlxi"] = 1,
["egg"] = 2,
["pog"] = 2,
["poggers"] = 2
}
if commands[message:sub(2):lower()] == 1 or commands[message:lower()] == 2 then
if player.Character then
local Head = player.Character:FindFirstChild("Head")
if Head then
local Sound = Instance.new("Sound", Head)
Sound.SoundId = "http://polygon.pizzaboxer.xyz/asset/?id=12679"
Sound:Play()
end
player.Character:BreakJoints()
end
end
end)
--[[ if url and access and placeId and player and player.userId then
game:HttpGet(url .. "/Game/ClientPresence.ashx?action=connect&" .. access .. "&Ticket=" .. player.PolygonTicket.Value)
game:HttpGet(url .. "/Game/PlaceVisit.ashx?Ticket=" .. player.PolygonTicket .. "&" .. access)
@ -309,10 +335,7 @@ ns.ChildAdded:connect(function(replicator)
print("[paclib] " .. player.Name .. " has been authenticated")
if url and access and placeId and player and player.userId then
while true do
wait(1)
if player.Character then break end
end
print("[presence] Submitting " .. player.Name .. "'s client presence...")
game:HttpGet(url .. "/Game/ClientPresence.ashx?action=connect&" .. access .. "&Ticket=" .. PolygonTickets[player.userId])
game:HttpGet(url .. "/Game/PlaceVisit.ashx?Ticket=" .. PolygonTickets[player.userId] .. "&" .. access)
end
@ -335,4 +358,4 @@ InactivityHandler()
------------------------------END START GAME SHARED SCRIPT--------------------------
<?php echo RBXClient::CryptSignScript(ob_get_clean());
<?php echo RBXClient::CryptSignScript(ob_get_clean());

View File

@ -24,12 +24,8 @@ class Parsedown
# ~
function text($text, $embedsEnabled = false)
function text($text)
{
$this->setEmbedsEnabled($embedsEnabled);
if(!$embedsEnabled) $text = preg_replace(["/!\[(.*)\]\((.*)\)/i", "/!\[(.*)\]\((.*) \"(.*)\"\)/i"], ["$2", "[$3]($2)"], $text);
# make sure no definitions are set
$this->DefinitionData = array();
@ -82,6 +78,7 @@ class Parsedown
protected $urlsLinked = true;
/// PROJECT POLYGON ///
function setEmbedsEnabled($embedsEnabled)
{
$this->embedsEnabled = $embedsEnabled;
@ -90,6 +87,7 @@ class Parsedown
}
protected $embedsEnabled = false;
/// PROJECT POLYGON ///
function setSafeMode($safeMode)
{
@ -1067,6 +1065,11 @@ class Parsedown
# ~
#
public function raw($text, $nonNestables=array())
{
return $text;
}
public function line($text, $nonNestables=array())
{
$markup = '';
@ -1083,6 +1086,13 @@ class Parsedown
foreach ($this->InlineTypes[$marker] as $inlineType)
{
/// PROJECT POLYGON ///
if (!$this->embedsEnabled && $inlineType == 'Image')
{
continue;
}
/// PROJECT POLYGON ///
# check to see if the current inline type is nestable in the current context
if ( ! empty($nonNestables) and in_array($inlineType, $nonNestables))
@ -1253,21 +1263,57 @@ class Parsedown
return;
}
$Inline = array(
'extent' => $Link['extent'] + 1,
'element' => array(
'name' => 'img',
'attributes' => array(
'class' => "img-fluid",
'src' => $Link['element']['attributes']['href'],
'alt' => $Link['element']['text'],
/// PROJECT POLYGON ///
if (strcasecmp($Link['element']['text'], 'Twitter') == 0)
{
$Inline = array(
'extent' => $Link['extent'] + 1,
'element' => array(
'name' => 'div',
'text' => '<blockquote class="twitter-tweet"><a href="' . $Link['element']['attributes']['href'] . '"></a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>',
'handler' => 'raw',
),
),
);
);
}
else if (strcasecmp($Link['element']['text'], 'YouTube') == 0)
{
parse_str(parse_url($Link['element']['attributes']['href'])["query"], $params);
$Inline['element']['attributes'] += $Link['element']['attributes'];
if (!isset($params['v']))
return;
unset($Inline['element']['attributes']['href']);
$Inline = array(
'extent' => $Link['extent'] + 1,
'element' => array(
'name' => 'div',
'attributes' => array(
'class' => 'embed-responsive embed-responsive-16by9',
),
'text' => '<iframe class="embed-responsive-item" src="https://www.youtube.com/embed/' . $params['v'] . '" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>',
'handler' => 'raw',
),
);
}
else
{
$Inline = array(
'extent' => $Link['extent'] + 1,
'element' => array(
'name' => 'img',
'attributes' => array(
'class' => "img-fluid",
'src' => $Link['element']['attributes']['href'],
'alt' => $Link['element']['text'],
),
),
);
$Inline['element']['attributes'] += $Link['element']['attributes'];
unset($Inline['element']['attributes']['href']);
}
/// PROJECT POLYGON ///
return $Inline;
}

View File

@ -45,8 +45,11 @@ class API
if ($logged_in)
{
if (!SESSION || SESSION["user"]["twofa"] && !SESSION["2faVerified"]) self::respond(401, false, "You are not logged in");
if (!isset($_SERVER['HTTP_X_POLYGON_CSRF'])) self::respond(401, false, "Unauthorized");
if ($_SERVER['HTTP_X_POLYGON_CSRF'] != SESSION["csrfToken"]) self::respond(401, false, "Unauthorized");
if ($method != "GET")
{
if (!isset($_SERVER['HTTP_X_POLYGON_CSRF'])) self::respond(401, false, "Unauthorized");
if ($_SERVER['HTTP_X_POLYGON_CSRF'] != SESSION["csrfToken"]) self::respond(401, false, "Unauthorized");
}
}
if ($admin !== false)

View File

@ -4,6 +4,7 @@ namespace pizzaboxer\ProjectPolygon;
use pizzaboxer\ProjectPolygon\Database;
use pizzaboxer\ProjectPolygon\Users;
use pizzaboxer\ProjectPolygon\Polygon;
class PageBuilder
{
@ -29,12 +30,13 @@ class PageBuilder
"title" => false,
"Theme" => "light",
"ShowNavbar" => true,
"ShowFooter" => true
"ShowFooter" => true,
"ShowFooterAd" => true
];
private array $appAttributes =
[
"class" => "app container py-4 nav-content"
"class" => "app container nav-content py-4"
];
private array $metaTags =
@ -114,6 +116,11 @@ class PageBuilder
function buildHeader()
{
if (!isset($_COOKIE['farewell']) && $_SERVER['DOCUMENT_URI'] != "/farewell.php" && !Polygon::IsWaybackMachine() && !Polygon::IsEmbed() && !Polygon::IsClientBrowser() && GetUserAgent() != "Roblox/WinInet")
{
header("Location: /farewell?ReturnUrl=" . urlencode($_SERVER['REQUEST_URI']));
}
$this->addMetaTag("og:title", $this->config["title"]);
$this->addResource("polygonScripts", "/js/polygon/core.js", true, true);
$this->addResource("stylesheets", "/css/polygon.css");
@ -183,4 +190,4 @@ class PageBuilder
die();
}
}
}

View File

@ -24,6 +24,11 @@ class Polygon
return strpos(GetUserAgent(), "MSIE 7.0") !== false;
}
static function IsWaybackMachine()
{
return strpos(GetUserAgent(), "archive.org") !== false;
}
static function IsThumbnailServerIP()
{
return GetIPAddress() == SITE_CONFIG["ThumbnailServer"]["Address"];
@ -202,7 +207,7 @@ class Polygon
]);
}
if (self::IsDevSite())
/* if (self::IsDevSite())
{
array_unshift($announcements,
[
@ -210,6 +215,16 @@ class Polygon
"textcolor" => "light",
"bgcolor" => "#F76E19"
]);
} */
if ($_SERVER["HTTP_HOST"] == "pizzaboxer.xyz")
{
array_unshift($announcements,
[
"text" => "Game launching will not work on this domain. Click [here](https://polygon.pizzaboxer.xyz) to go to the correct domain.",
"textcolor" => "light",
"bgcolor" => "#F76E19"
]);
}
}
}
}

View File

@ -216,7 +216,19 @@ class Users
$banInfo = self::GetUserModeration($userId);
if (!$banInfo) return false;
if (!$admin && ($banInfo->banType == 3 || ($banInfo->banType != 1 && $banInfo->timeEnds < time()))) return false;
if (!$admin)
{
if ($banInfo->banType == 2 && $banInfo->timeEnds > time()) // temporary
{
return false;
}
if ($banInfo->banType == 3) // permanent
{
return false;
}
}
Database::singleton()->run(
"UPDATE bans SET isDismissed = 1 WHERE userId = :id AND NOT isDismissed;
@ -252,7 +264,7 @@ class Users
);
}
while($ip = $ips->fetch(\PDO::FETCH_OBJ))
while ($ip = $ips->fetch(\PDO::FETCH_OBJ))
{
if(in_array($ip->loginIp, $usedIPs)) continue;
$usedIPs[] = $ip->loginIp;

View File

@ -62,7 +62,9 @@ $bypassRules =
"/game/serverpresence.php",
"/game/verifyplayer.php",
"/asset/index.php"
"/asset/index.php",
"/farewell.php"
],
"Moderation" =>
@ -73,7 +75,14 @@ $bypassRules =
"/info/selfhosting.php",
"/directory_login/2fa.php",
"/logout.php",
"/rbxclient/game/machineconfiguration.php"
"/rbxclient/game/machineconfiguration.php",
"/my/account.php",
"/api/account/update-settings.php",
"/api/account/update-password.php",
"/api/account/destroy-sessions.php",
"/farewell.php"
],
"HTTPS" =>

View File

@ -34,7 +34,7 @@ success, error = pcall(function() game:Load(baseUrl .. "/Asset/?id=" .. assetId
if not success then
print("[" .. game.JobId .. "] Failed to load map! (" .. error .. ")")
game:HttpPost(baseUrl .. "/api/render/update?ApiKey=" .. thumbnailKey .. "&amp;RenderJobID=" .. game.JobId, '{"Status": 3, "Message": "Failed to load map! (" .. error .. ")"}', true, "text/plain", true)
game:HttpPost(baseUrl .. "/api/render/update?ApiKey=" .. thumbnailKey .. "&amp;RenderJobID=" .. game.JobId, '{"Status": 3, "Message": "Failed to load map! (' .. error .. ')"}', true, "text/plain", true)
else
-- Do this after again loading the place file to ensure that these values aren't changed when the place file is loaded.
game:GetService("HttpService").HttpEnabled = true

View File

@ -1,14 +1,15 @@
</div>
<?php if ($this->config["ShowFooter"]) { ?>
<div class="mt-2" align="center">
<ins class="adsbygoogle" style="display:inline-block;width:728px;height:90px" data-ad-client="ca-pub-3972374207754919" data-ad-slot="7346178371"></ins>
</div>
<footer>
<div class="container text-center py-2">
<hr>
<div class="row mt-4">
<div class="col-xl-6 col-lg-4 text-lg-left">
<?php if (SESSION) { ?>
<p><a href="/info/terms-of-service" class="px-2" style="color:inherit">Terms of Service</a> | <a href="/info/privacy" class="px-2" style="color:inherit">Privacy Policy</a> | <a href="/discord" class="px-2" style="color:inherit">Discord</a></p>
<?php } else { ?>
<p><a href="/info/terms-of-service" class="px-2" style="color:inherit">Terms of Service</a> | <a href="/info/privacy" class="px-2" style="color:inherit">Privacy Policy</a></p>
<?php } ?>
</div>
<div class="col-xl-6 col-lg-8 text-lg-right">
<p><small>© <?= date("Y") ?> Project Polygon. We are in no way associated with Roblox Corporation.</small></p>
@ -48,7 +49,7 @@
<div class="install template d-none">
<div class="modal-body text-center pb-0">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<img src="/img/PolygonChristmas.png" class="img-fluid pl-3 py-3 pr-1" style="max-width: 150px">
<img src="/img/ProjectPolygon.png" class="img-fluid pl-3 py-3 pr-1" style="max-width: 150px">
<h2 class="font-weight-normal">Welcome to <?= SITE_CONFIG["site"]["name"] ?>!</h2>
<h5 class="font-weight-normal">Seems like you don't have <span class="year">2010</span> installed</h5>
<a class="btn btn-success btn-block mx-auto mt-3 install" style="max-width:18rem">Download</a>
@ -143,9 +144,6 @@
<?php foreach ($this->polygonScripts as $url) { ?>
<script type="text/javascript" src="<?= $url ?>"></script>
<?php } ?>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<?=$this->footerAdditions?>
</body>
</html>

View File

@ -13,7 +13,6 @@
<?php } foreach ($this->scripts as $url) { ?>
<script type="text/javascript" src="<?= $url ?>"></script>
<?php } ?>
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3972374207754919" crossorigin="anonymous"></script>
<script>
var polygon = {};

View File

@ -152,6 +152,8 @@ else if ($Response["Status"] == 3)
"UPDATE renderqueue SET renderStatus = :Status, timestampCompleted = UNIX_TIMESTAMP(), additionalInfo = :Message WHERE jobID = :JobID",
[":Status" => $Response["Status"], ":Message" => $Response["Message"], ":JobID" => $_GET["RenderJobID"]]
);
throw new Exception("Failed to render request ID " . $_GET["RenderJobID"] . "! (" . $Response["Message"] . ")");
}
// file_put_contents("tests/{$JobID}.png", base64_decode($Response->click));

View File

@ -6,9 +6,7 @@ use pizzaboxer\ProjectPolygon\Users;
use pizzaboxer\ProjectPolygon\Thumbnails;
use pizzaboxer\ProjectPolygon\PageBuilder;
Users::RequireLogin();
$category = $_GET['Category'] ?? "Users";
$category = $_GET['Category'] ?? (SESSION ? "Users" : "Groups");
$page = $_GET['PageNumber'] ?? 1;
$keyword = $_GET['SearchTextBox'] ?? "";
$keyword_sql = "%";
@ -32,6 +30,8 @@ if($category == "Groups")
}
else
{
Users::RequireLogin();
// WHERE MATCH (username) AGAINST (:keywd IN NATURAL LANGUAGE MODE)
$querycount =
@ -112,7 +112,7 @@ $pageBuilder->buildHeader();
<tbody>
<?php while($row = $results->fetch(\PDO::FETCH_OBJ)) { ?>
<tr>
<td><a href="/groups?gid=<?=$row->id?>"><img src="<?=Thumbnails::GetAssetFromID($row->emblem)?>" title="<?=$row->name?>" alt="<?=$row->name?>" width="63" height="63"></a></td>
<td><a href="/groups?gid=<?=$row->id?>"><img src="<?=Thumbnails::GetAssetFromID($row->emblem)?>" title="<?=Polygon::FilterText($row->name)?>" alt="<?=Polygon::FilterText($row->name)?>" width="63" height="63"></a></td>
<td class="text-break"><a href="/groups?gid=<?=$row->id?>"><?=Polygon::FilterText($row->name)?></a></td>
<td class="text-break"><?=Polygon::FilterText($row->description)?></td>
<td><?=$row->MemberCount?></td>

View File

@ -75,6 +75,32 @@ body
transform: rotate(0deg);
}
@media (min-width: 728px) {
.ad-banner {
display: inline-block;
width: 728px;
height: 90px;
}
}
@media (max-width: 728px) {
.ad-banner {
display: none;
}
}
.ad-skyscraper {
display: inline-block;
width: 160px;
height: 600px;
}
.ad-square {
display: inline-block;
width: 300px;
height: 250px;
}
@media (min-width: 768px)
{
.divider-right

View File

@ -0,0 +1,119 @@
<?php require $_SERVER['DOCUMENT_ROOT'].'/api/private/core.php';
use pizzaboxer\ProjectPolygon\Users;
use pizzaboxer\ProjectPolygon\PageBuilder;
use pizzaboxer\ProjectPolygon\Database;
use pizzaboxer\ProjectPolygon\Polygon;
Users::RequireAdmin(Users::STAFF_ADMINISTRATOR);
$pageBuilder = new PageBuilder(["title" => "Post News"]);
$pageBuilder->buildHeader();
$query = Database::singleton()->run("SELECT * FROM feed_news WHERE time_deleted IS NOT NULL ORDER BY id DESC");
$latest_query = Database::singleton()->run("SELECT * FROM feed_news WHERE time_deleted IS NOT NULL ORDER BY id DESC LIMIT 1");
$recent = $latest_query->fetch(PDO::FETCH_OBJ);
?>
<h2 class="font-weight-normal">Post News</h2>
<div class="row">
<div class="col-lg-6 py-4 divider-right">
<div class="form-group row">
<label for="title" class="col-sm-3 col-form-label">Title</label>
<div class="col-sm-9">
<input type="text" class="form-control" id="title" placeholder="Give a name for your post.">
</div>
</div>
<div class="form-group row">
<label for="body" class="col-sm-3 col-form-label">Body</label>
<div class="col-sm-9">
<textarea class="form-control" id="body" placeholder="Stay on topic, be brief and concise."></textarea>
</div>
</div>
<div class="row">
<button class="btn btn-success btn-block mx-3" data-control="postNews"><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" style="display:none"></span> Post News</button>
</div>
</div>
<div class="col-lg-6 pt-3">
<h2 class="font-weight-normal">Some notes</h2>
<ul class="list-group">
<li class="list-group-item">Stay brief and concise.</li>
<li class="list-group-item">All posts will be shown on site, so be careful about what you post.</li>
<li class="list-group-item">Posts will be logged.</li>
</ul>
</div>
</div>
<hr>
<h2 class="font-weight-normal">All Posts</h2>
<table class="table table-hover table-responsive">
<thead class="thead-light">
<tr>
<th scope="col">Title</th>
<th scope="col">Body</th>
<th scope="col">Author</th>
<th scope="col">Posted On</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr>
<?php while($row = $query->fetch(\PDO::FETCH_OBJ)) { ?>
<tr class="<?=$recent->id === $row->id ? "table-primary" : "table-light"?>">
<td>
<?=Polygon::FilterText($row->title)?>
</td>
<td>
<button class="btn btn-primary" data-title="Body of <?=$row->title?>" data-text="<?=Polygon::FilterText($markdown->setEmbedsEnabled(true)->text($row->body),false)?>" data-control="openModal">View</button>
</td>
<td>
<a href="/user?ID=<?=$row->user_id?>"><?=Users::GetNameFromID($row->user_id)?></a>
</td>
<td>
<?=date("j/n/Y", $row->time_created)?>
</td>
<td>
<button class="btn btn-danger" data-post-id="<?=$row->id?>" data-control="deletePost"><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" style="display:none"> Delete</button>
</td>
</tr>
<?php } ?>
</tr>
</tbody>
</table>
<script>
//admin.js
$('button[data-control$="postNews"]').on('click', this, function()
{
var button = this;
$(button).attr("disabled", "disabled").find("span").show();
$.post('/api/admin/post-news', {"title":$("#title").val(), "body":$("#body").val()}, function(data)
{
if(data.success){ location.reload() }
else{ toastr["error"](data.message); }
$(button).removeAttr("disabled").find("span").hide();
});
});
$('button[data-control$="deletePost"]').on('click', this, function()
{
var button = this;
$(button).attr("disabled", "disabled").find("span").show();
$.post('/api/admin/delete-news', {"id":$(this).attr("data-post-id")}, function(data)
{
if(data.success){ location.reload() }
else{ toastr["error"](data.message); }
$(button).removeAttr("disabled").find("span").hide();
});
});
$('button[data-control$="openModal"]').on('click', this, function()
{
polygon.buildModal({
header: $(this).attr("data-title"),
body: $(this).attr("data-text"),
buttons: [{class: 'btn btn-outline-secondary', dismiss: true, text: 'Close'}]
});
});
</script>
<?php $pageBuilder->buildFooter(); ?>

View File

@ -16,6 +16,7 @@ $FilterCategories =
"Currency" => "[ Currency ]%",
"Banners" => "[ Banners ]%",
"Render" => "[ Render ]%",
"Feed" => "[ Feed ]%"
];
$Filter = $_GET["Filter"] ?? "All";
@ -74,6 +75,7 @@ $pageBuilder->buildHeader();
<option value="Forums"<?=$FilterSQL==$FilterCategories["Forums"]?' selected':''?>>Forums</option>
<option value="Currency"<?=$FilterSQL==$FilterCategories["Currency"]?' selected':''?>>Currency</option>
<option value="Render"<?=$FilterSQL==$FilterCategories["Render"]?' selected':''?>>Render</option>
<option value="Feed"<?=$FilterSQL==$FilterCategories["Feed"]?' selected':''?>>Feed</option>
</select>
</div>
<input class="form-control" name="Query" type="text" placeholder="Search for term" aria-label="Filter">

View File

@ -37,7 +37,7 @@ if($_SERVER['REQUEST_METHOD'] == "POST")
$subject = $_POST["subject"] ?? "";
$body = $_POST["body"] ?? "";
$userid = SESSION["user"]["id"];
if(!$threadInfo)
{
if(!strlen($subject)) $errors["subject"] = "Subject cannot be empty";
@ -59,6 +59,11 @@ if($_SERVER['REQUEST_METHOD'] == "POST")
if(!$errors["subject"] && !$errors["body"] && !$errors["general"])
{
if ($userid == 441 || $userid == 911)
{
redirect("https://www.youtube.com/watch?v=1hfk8kh75icgHwz8JtOx-Ep0bfLM7Sj2");
}
if($threadInfo)
{
Database::singleton()->run(

View File

@ -15,13 +15,6 @@ if(!$threadInfo || $threadInfo->deleted && (!SESSION || !SESSION["user"]["adminl
$authorInfo = Users::GetInfoFromID($threadInfo->author);
//markdown
$markdown = new Parsedown();
$markdown->setMarkupEscaped(true);
$markdown->setBreaksEnabled(true);
$markdown->setSafeMode(true);
$markdown->setUrlsLinked(true);
//reply pagination
$page = $_GET['page'] ?? 1;
@ -49,6 +42,8 @@ $pageBuilder = new PageBuilder(["title" => Polygon::FilterText($threadInfo->subj
$pageBuilder->addMetaTag("og:description", Polygon::FilterText($threadInfo->body, true, false));
$pageBuilder->buildHeader();
?>
<?php if ($threadInfo->deleted) { ?><div class="alert alert-danger px-2 py-1 mb-3" role="alert">This post has been deleted</div><?php } ?>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/forum"><?=SITE_CONFIG["site"]["name"]?> Forum</a></li>
@ -59,8 +54,7 @@ $pageBuilder->buildHeader();
<div class="row mb-2">
<div class="col">
<?php if(SESSION){ ?><a class="btn btn-primary<?=$threadInfo->deleted?' disabled':''?>" href="/forum/addpost?PostID=<?=$threadInfo->id?>"><i class="far fa-comment-alt-plus mr-2"></i> New Reply</a><?php } ?>
<?=$threadInfo->deleted?'<span class="text-danger">[ This is a deleted thread ]</span>':''?>
<?php if(SESSION){ ?><a class="btn btn-primary<?=$threadInfo->deleted?' disabled':''?>" href="/forum/addpost?PostID=<?=$threadInfo->id?>"><i class="fas fa-plus mr-1"></i> New Reply</a><?php } ?>
</div>
<?php if($pagination->Pages > 1) { ?>
<div class="col">
@ -71,6 +65,7 @@ $pageBuilder->buildHeader();
<div class="card">
<div class="card-header bg-primary text-white">
<?php if($threadInfo->pinned) { ?><i class="fas fa-thumbtack text-success mr-1"></i><?php } ?>
<?=Polygon::FilterText($threadInfo->subject)?>
</div>
</div>
@ -92,7 +87,7 @@ $pageBuilder->buildHeader();
</span>
<?php } ?>
<br>
<?=Polygon::FilterText($markdown->text($threadInfo->body, $authorInfo->adminlevel == 2), false)?>
<?=Polygon::FilterText($markdown->setEmbedsEnabled($authorInfo->adminlevel == 2)->text($threadInfo->body), false)?>
</div>
</div>
</div>
@ -115,15 +110,14 @@ $pageBuilder->buildHeader();
</span>
<?php } ?>
<br>
<?=Polygon::FilterText($markdown->text($reply->body, $authorInfo->adminlevel == 2), false)?>
<?=Polygon::FilterText($markdown->setEmbedsEnabled($authorInfo->adminlevel == 2)->text($reply->body), false)?>
</div>
</div>
</div>
<?php } ?>
<div class="row">
<div class="col">
<?php if(SESSION){ ?><a class="btn btn-primary<?=$threadInfo->deleted?' disabled':''?>" href="/forum/addpost?PostID=<?=$threadInfo->id?>"><i class="far fa-comment-alt-plus mr-2"></i> New Reply</a><?php } ?>
<?=$threadInfo->deleted?'<span class="text-danger">[ This is a deleted thread ]</span>':''?>
<?php if(SESSION){ ?><a class="btn btn-primary<?=$threadInfo->deleted?' disabled':''?>" href="/forum/addpost?PostID=<?=$threadInfo->id?>"><i class="fas fa-plus mr-1"></i> New Reply</a><?php } ?>
</div>
<div class="col">
<?=Pagination::insert()?>

View File

@ -94,10 +94,10 @@ if ($_SERVER["REQUEST_METHOD"] == "POST")
{
$Error = "Invalid access level selected";
}
else if ($Access != "Friends" && $Version != "2011")
/* else if ($Access != "Friends" && $Version != "2011")
{
$Error = "2010 and 2012 places must be set to friends-only";
}
} */
else if (!in_array($ChatType, ["Classic", "Bubble", "Both"]))
{
$Error = "Invalid Chat Type selected";
@ -238,10 +238,14 @@ $pageBuilder->buildHeader();
</select>
</div>
<div class="form-group" style="max-width: 26rem;">
<label for="Access">Access: <i class="far fa-question-circle text-muted" title="2010 and 2012 places can only be accessible to friends for the time being" data-toggle="tooltip"></i></label>
<select name="Access" id="Access" class="form-control form-control-sm">
<label for="Access">Access: <!--i class="far fa-question-circle text-muted" title="2010 and 2012 places can only be accessible to friends for the time being" data-toggle="tooltip"></i--></label>
<!--select name="Access" id="Access" class="form-control form-control-sm">
<option value="Everyone" disabled="disabled">Everyone</option>
<option value="Friends" selected="selected">Friends</option>
</select-->
<select name="Access" id="Access" class="form-control form-control-sm">
<option value="Everyone" selected="selected">Everyone</option>
<option value="Friends">Friends</option>
</select>
</div>
<div class="form-group" style="max-width: 26rem;">
@ -332,7 +336,7 @@ $("input[name='PlaceUpload']").change(function(event)
$(".place-template[data-template-id='custom']").find(".card-body").addClass("bg-primary");
});
$("select[name='Version']").change(function()
/* $("select[name='Version']").change(function()
{
if ($(this).val() == "2010" || $(this).val() == "2012")
{
@ -345,7 +349,7 @@ $("select[name='Version']").change(function()
$("label[for='Access'] i").addClass("d-none");
$("select[name='Access'] option[value='Everyone']").removeAttr("disabled");
}
});
}); */
$('.global.modal').on('hidden.bs.modal', function()
{

View File

@ -91,10 +91,10 @@ if ($_SERVER["REQUEST_METHOD"] == "POST")
{
$Error = "Invalid access level selected";
}
else if ($Access != "Friends" && $Version != "2011")
/* else if ($Access != "Friends" && $Version != "2011")
{
$Error = "2010 and 2012 places must be set to friends-only";
}
} */
else if (!in_array($ChatType, ["Classic", "Bubble", "Both"]))
{
$Error = "Invalid Chat Type selected";
@ -235,10 +235,14 @@ $pageBuilder->buildHeader();
</select>
</div>
<div class="form-group" style="max-width: 26rem;">
<label for="Access">Access: <i class="far fa-question-circle text-muted<?=!in_array($PlaceInfo->Version, ["2010", "2012"]) ? " d-none":""?>" title="2010 and 2012 places can only be accessible to friends for the time being" data-toggle="tooltip"></i></label>
<select name="Access" id="Access" class="form-control form-control-sm">
<label for="Access">Access: <!--i class="far fa-question-circle text-muted<?=!in_array($PlaceInfo->Version, ["2010", "2012"]) ? " d-none":""?>" title="2010 and 2012 places can only be accessible to friends for the time being" data-toggle="tooltip"></i--></label>
<!--select name="Access" id="Access" class="form-control form-control-sm">
<option value="Everyone"<?=$PlaceInfo->Access == "Everyone" ? "selected=\"selected\"" : ""?><?=in_array($PlaceInfo->Version, ["2010", "2012"]) ? " disabled=\"disabled\"":""?>>Everyone</option>
<option value="Friends"<?=$PlaceInfo->Access == "Friends" ? "selected=\"selected\"" : ""?>>Friends</option>
</select-->
<select name="Access" id="Access" class="form-control form-control-sm">
<option value="Everyone"<?=$PlaceInfo->Access == "Everyone" ? "selected=\"selected\"" : ""?>>Everyone</option>
<option value="Friends"<?=$PlaceInfo->Access == "Friends" ? "selected=\"selected\"" : ""?>>Friends</option>
</select>
</div>
<div class="form-group" style="max-width: 26rem;">
@ -297,9 +301,9 @@ $pageBuilder->buildHeader();
<?php } ?>
<div class="col-lg-3 col-md-4 col-6 px-2 mb-3">
<div class="place-template card hover h-100" role="button" data-template-id="custom">
<img class="card-img-top img-fluid" title="Create from Place File" alt="Create from Place File" src="<?=Thumbnails::GetStatus("rendering", 768, 432)?>">
<img class="card-img-top img-fluid" title="Update from Place File" alt="Update from Place File" src="<?=Thumbnails::GetStatus("rendering", 768, 432)?>">
<div class="card-body p-2 text-center">
<p class="mb-0 text-truncate" title="Create from Place File">Create from Place File</p>
<p class="mb-0 text-truncate" title="Update from Place File">Update from Place File</p>
</div>
</div>
</div>
@ -354,7 +358,7 @@ $("input[name='PlaceUpload']").change(function(event)
$(".place-template[data-template-id='custom']").find(".card-body").addClass("bg-primary");
});
$("select[name='Version']").change(function()
/* $("select[name='Version']").change(function()
{
if ($(this).val() == "2010" || $(this).val() == "2012")
{
@ -367,7 +371,7 @@ $("select[name='Version']").change(function()
$("label[for='Access'] i").addClass("d-none");
$("select[name='Access'] option[value='Everyone']").removeAttr("disabled");
}
});
}); */
$('.global.modal').on('hidden.bs.modal', function()
{

84
farewell.php Normal file
View File

@ -0,0 +1,84 @@
<?php require $_SERVER['DOCUMENT_ROOT'].'/api/private/core.php';
use pizzaboxer\ProjectPolygon\PageBuilder;
$pageBuilder = new PageBuilder(["title" => "Farewell", "ShowNavbar" => false, "ShowFooter" => false]);
$pageBuilder->buildHeader();
?>
<style>
body
{
background: url(/img/landing/polygonville-edit2.jpg);
background-attachment: fixed;
background-size: cover;
background-position: center;
box-shadow: inset 0 0 5rem rgba(0, 0, 0, .5);
}
.bg-landing
{
background-color: rgba(129, 156, 82, 0.5);
}
.navbar-orange
{
background-color: rgba(145, 145, 145, 0.5);
}
.nav-link, .nav-link:hover
{
color: white;
}
.app, footer
{
color: white
; text-shadow: 0 .05rem .1rem rgba(0, 0, 0, .5);
}
.app .btn, .app .nav-link, .app small.text-danger
{
text-shadow: none;
}
</style>
<div style="max-width:20rem" class="row mx-auto mt-4">
<div class="col-4 pr-0">
<img src="/img/ProjectPolygon.png" class="img-fluid">
</div>
<div class="col-8">
<h1 class="font-weight-normal pt-3">farewell</h1>
</div>
</div>
<div class="card bg-landing text-white mx-auto my-4" style="max-width:38rem">
<div class="card-body" style="background-color: revert">
<p>Yep, that's right. This moment has been nearly two years in the making.</p>
<p>Project Polygon was made with the original intention being to see if I was capable of developing a fully-featured revival by myself, and it's no doubt been the biggest project I have taken on single-handedly.</p>
<p>Having been nearly two years since its inception, and nearly a year since its public launch, I've felt that now it's just the time to move on from this. It has certainly run its course, surviving an extra year more than it was supposed to. Two years is a lot of time, and so it's time for me to move on, and all of you too.</p>
<p>Besides, despite only being two years old, the code behind this really hasn't aged well. It's a mess, and I've even intentionally avoided adding features due to fear of making the code even more of a mess than it already is, thanks to the codebase that much of 14-year-old me wrote. Wonder why we never got stuff like packages? Now you know.</p>
<p>A <b>lot</b> has happened within the past year, and I'm not entirely sure whether to be proud or ashamed of this. Maybe it's both. We've definitely had our ups and downs, and to be honest, I don't know if I regret launching this.</p><p>The website will remain fully accessible for two weeks until August 12, giving all of you the opportunity to archive whatever you need, and maybe even say goodbye. After those two weeks, it'll be like this never existed. I might even make everything open-source. No promises though.</p>
<p class="mb-0">There's a few people I'd like to give thanks to specifically:</p>
<ul>
<li>taskmanager - helping with website development</li>
<li>Carrot, KJF, coke - helping with game client development</li>
<li>All of our staff (cole, doodama, Dylan, jamrio, kinery, KJF, warden)</li>
<li>The people who helped start Project Polygon (yimy, Multako, bucks, mag, chess)</li>
</ul>
<p class="mb-0">To all the people who played this, and even the people who tried to break it: </p>
<h2 class="mb-3">Thank You.</h2>
<p> - pizzaboxer</p>
<button class="btn btn-lg btn-success btn-lg btn-block" onclick="acknowledge()">Acknowledge</button>
</div>
</div>
<script>
function acknowledge()
{
document.cookie = "farewell=1; expires=Fri, 13 August 2022 00:00:00 UTC";
params = new URLSearchParams(window.location.search);
if (params.has("ReturnUrl") && params.get("ReturnUrl").startsWith("/"))
{
window.location = params.get("ReturnUrl");
}
}
</script>
<?php $pageBuilder->buildFooter(); ?>

View File

@ -25,7 +25,7 @@ if(isset($_GET['ID']) || isset($_GET['id']))
$threads = Database::singleton()->run(
"SELECT * FROM forum_threads WHERE subforumid = :id AND NOT deleted AND (subject LIKE :query OR body LIKE :query)
ORDER BY pinned, bumpIndex DESC LIMIT 20 OFFSET $offset",
ORDER BY pinned DESC, bumpIndex DESC LIMIT 20 OFFSET $offset",
[":id" => $subforumInfo->id, ":query" => $searchquery]
);
@ -74,7 +74,7 @@ $pageBuilder->buildHeader();
<?php if($isSubforum) { ?>
<div class="row mb-2">
<div class="col-lg-8 col-md-6">
<?php if(SESSION && SESSION["user"]["adminlevel"] >= $subforumInfo->minadminlevel){ ?><a class="btn btn-primary" href="/forum/addpost?ForumID=<?=$subforumInfo->id?>"><i class="far fa-paper-plane mr-2"></i> Create Post</a><?php } ?>
<?php if(SESSION && SESSION["user"]["adminlevel"] >= $subforumInfo->minadminlevel){ ?><a class="btn btn-primary" href="/forum/addpost?ForumID=<?=$subforumInfo->id?>"><i class="fas fa-plus mr-1"></i> Create Post</a><?php } ?>
</div>
<div class="col-lg-4 col-md-6">
<form class="input-group form-inline float-right">
@ -106,6 +106,7 @@ $pageBuilder->buildHeader();
<td class="p-0">
<a href="/forum/showpost?PostID=<?=$thread->id?>" class="text-decoration-none">
<div style="padding: 0.75rem" class="text-dark">
<?php if($thread->pinned) { ?><i class="fas fa-thumbtack text-success mr-1"></i><?php } ?>
<?=Polygon::FilterText($thread->subject)?>
</div>
</a>
@ -115,14 +116,14 @@ $pageBuilder->buildHeader();
<td class="text-center"><span data-toggle="tooltip" data-placement="right" title="<?=date('j/n/Y g:i A', $thread->bumpIndex)?>"><?=timeSince($thread->bumpIndex)?></span></td>
</tr>
<?php } if(!$pages) { ?>
<tr><td colspan="4" class="text-center"><?=isset($_GET['searchq'])?"Looks like there's no posts here that matched your query":'This subforum does not have any posts yet! <a class="btn btn-sm btn-primary mx-2" href="/forum/addpost?ForumID='.$subforumInfo->id.'"><i class="far fa-paper-plane mr-2"></i> Create Post</a>'?></td></tr>
<tr><td colspan="4" class="text-center"><?=isset($_GET['searchq'])?"Looks like there's no posts here that matched your query":'This subforum does not have any posts yet! <a class="btn btn-sm btn-primary mx-2" href="/forum/addpost?ForumID='.$subforumInfo->id.'"><i class="fas fa-plus mr-1"></i> Create Post</a>'?></td></tr>
<?php } ?>
</tbody>
</table>
</div>
<div class="row mb-2">
<div class="col-sm-6">
<?php if(SESSION && SESSION["user"]["adminlevel"] >= $subforumInfo->minadminlevel){ ?><a class="btn btn-primary" href="/forum/addpost?ForumID=<?=$subforumInfo->id?>"><i class="far fa-paper-plane mr-2"></i> Create Post</a><?php } ?>
<?php if(SESSION && SESSION["user"]["adminlevel"] >= $subforumInfo->minadminlevel){ ?><a class="btn btn-primary" href="/forum/addpost?ForumID=<?=$subforumInfo->id?>"><i class="fas fa-plus mr-1"></i> Create Post</a><?php } ?>
</div>
<div class="col-sm-6">
<?=Pagination::insert()?>

View File

@ -1,16 +1,42 @@
<?php require $_SERVER['DOCUMENT_ROOT'].'/api/private/core.php';
use pizzaboxer\ProjectPolygon\Database;
use pizzaboxer\ProjectPolygon\Users;
use pizzaboxer\ProjectPolygon\Thumbnails;
use pizzaboxer\ProjectPolygon\PageBuilder;
Users::RequireLogin();
$totalGameJoins = Database::singleton()->run(
"SELECT COUNT(*) FROM GameJobSessions WHERE UserID = :UserID",
[":UserID" => SESSION["user"]["id"]]
)->fetchColumn();
$failedGameJoins = Database::singleton()->run(
"SELECT COUNT(*) FROM GameJobSessions WHERE UserID = :UserID AND Verified = 0",
[":UserID" => SESSION["user"]["id"]]
)->fetchColumn();
// the idea here is that we only show the help message if at least 70% of all game joins have failed
if ($totalGameJoins == 0)
$failedGameJoinRate = 1;
else
$failedGameJoinRate = $failedGameJoins / $totalGameJoins;
$showHelpMessage = $failedGameJoinRate > 0.7;
$pageBuilder = new PageBuilder(["title" => "Games"]);
$pageBuilder->addResource("scripts", "/js/protocolcheck.js");
$pageBuilder->addResource("polygonScripts", "/js/polygon/games.js");
$pageBuilder->buildHeader();
?>
<?php if ($showHelpMessage) { ?>
<div class="bg-primary mb-2 px-3 py-2 text-light rounded">
<i class="fas fa-exclamation-circle"></i>
Having difficulty with the game client? <a href="/forum/showpost?PostID=1775" class="text-light">Read this help thread.</a>
</div>
<?php } ?>
<div class="places-container">
<div class="row px-2">
<div class="col-xl-2 col-lg-2 col-md-3 col-sm-4 col-12 px-2 my-1">
@ -26,12 +52,17 @@ $pageBuilder->buildHeader();
</div>
<div class="col-xl-2 col-lg-2 col-md-3 col-sm-4 col-6 px-2 my-1">
<span class="mb-1">Version:</span>
<select class="form-control form-control-sm VersionFilter">
<option>All</option>
<option>2010</option>
<option>2011</option>
<option>2012</option>
</select>
<div class="version-filter-wrapper">
<select class="form-control form-control-sm VersionFilter">
<option>All</option>
<option>2010</option>
<option>2011</option>
<option>2012</option>
</select>
<div class="input-group-append d-none">
<a class="btn btn-sm btn-success version-filter-download" href="#"><i class="far fa-download"></i></a>
</div>
</div>
</div>
<div class="col-xl-6 col-lg-6 col-lg-4 col-md-3 col-12 px-2 my-1">
<span class="mb-1 d-none d-xl-inline d-lg-inline d-md-inline">&nbsp;</span>

View File

@ -250,7 +250,7 @@ $pageBuilder->buildHeader();
<p class="no-items p-3"></p>
</div>
<div class="items"></div>
<div class="pagination form-inline justify-content-center d-none">
<div class="pagination form-inline justify-content-center d-none py-3">
<button type="button" class="btn btn-light mx-2 back"><h5 class="mb-0"><i class="fal fa-caret-left"></i></h5></button>
<span>Page</span>
<input class="form-control form-control-sm text-center mx-1 px-0 page" type="text" data-last-page="1" style="width:40px">

View File

@ -23,7 +23,7 @@ $pageBuilder->addResource("polygonScripts", "/js/3D/PolygonOrbitControls.js");
$pageBuilder->buildHeader();
?>
<h2 class="font-weight-normal">Hello, <?=SESSION["user"]["username"]?>!</h2>
<h2 class="font-weight-normal mb-2">Hello, <?=SESSION["user"]["username"]?>!</h2>
<div class="row">
<div class="col-lg-3 col-md-4 p-0 divider-right">
<div class="p-3 text-center">
@ -57,7 +57,7 @@ $pageBuilder->buildHeader();
</div>
</div>
<div class="col-lg-6 col-md-8 px-3 divider-right">
<div class="polygon-news" style="display:none;">
<div class="polygon-news d-none">
<h3 class="font-weight-normal pb-0">Updates from <?=SITE_CONFIG["site"]["name"]?></h3>
<div class="newsfeed-container">
<div class="text-center mt-2">
@ -67,9 +67,9 @@ $pageBuilder->buildHeader();
</div>
<div class="template d-none">
<div class="divider-top pb-2 pt-3">
<div class="row">
<div class="row">
<div class="col-2 pr-0 text-center">
<img src="<?=Thumbnails::GetStatus("rendering")?>" data-src="$img" class="img-fluid">
<img src="/img/ProjectPolygon.png" class="img-fluid">
</div>
<div class="col-10">
<h4 class="font-weight-normal mb-0">$header</h4>

View File

@ -80,7 +80,7 @@ if($_SERVER['REQUEST_METHOD'] == 'POST' && !$MaximumAccounts)
if (!VerifyReCAPTCHA()) $Errors->ReCAPTCHA = "ReCAPTCHA verification failed, please try again.";
$TicketCheck = Database::singleton()->run(
"SELECT COUNT(*) FROM InviteTickets WHERE Ticket = :Ticket AND UsedBy IS NULL",
"SELECT COUNT(*) FROM InviteTickets WHERE Ticket = :Ticket AND UsedBy IS NULL AND NOT (SELECT banned FROM users WHERE id = InviteTickets.CreatedBy)",
[":Ticket" => $Fields->RegistrationKey]
)->fetchColumn();
if ($TicketCheck == 0) $Errors->RegistrationKey = "That registration ticket is invalid";

274
item.php
View File

@ -18,7 +18,7 @@ $isAdmin = Users::IsAdmin();
if($_SERVER['REQUEST_URI'] != "/".encode_asset_name($item->name)."-item?id=".$item->id) redirect("/".encode_asset_name($item->name)."-item?id=".$item->id);
$pageBuilder = new PageBuilder(["title" => Polygon::FilterText($item->name).", ".vowel(Catalog::GetTypeByNum($item->type))." by ".$item->username]);
$pageBuilder = new PageBuilder(["title" => Polygon::FilterText($item->name).", ".vowel(Catalog::GetTypeByNum($item->type))." by ".$item->username, "ShowFooterAd" => false]);
$pageBuilder->addAppAttribute("data-asset-id", $item->id);
$pageBuilder->addMetaTag("og:description", Polygon::FilterText($item->description));
$pageBuilder->addMetaTag("og:image", Thumbnails::GetAsset($item));
@ -36,156 +36,158 @@ $pageBuilder->addResource("polygonScripts", "/js/3D/PolygonOrbitControls.js");
$pageBuilder->buildHeader();
?>
<div class="container" style="max-width: 58rem">
<?php if($ownsAsset || $isCreator || $isAdmin) { ?>
<div class="dropdown d-flex justify-content-end float-right">
<a class="btn btn-sm btn-light py-0 px-1" href="#" role="button" id="configure-asset" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="fa-stack">
<i class="fas fa-cog"></i>
<i class="fas fa-angle-down"></i>
</span>
</a>
<div class="dropdown-menu dropdown-menu-right bg-light" aria-labelledby="configure-asset">
<?php if($isCreator || Users::IsAdmin([Users::STAFF_CATALOG, Users::STAFF_ADMINISTRATOR])) { ?>
<a class="dropdown-item" href="/my/item?ID=<?=$item->id?>">Configure</a>
<?php } if($ownsAsset) { ?>
<a class="dropdown-item delete-item-prompt" href="#" data-item-id="<?=$item->id?>">Delete from My Stuff</a>
<?php } if(Users::IsAdmin()) { ?>
<a class="dropdown-item asset-<?=$item->approved==1?'decline':'approve'?>" href="#"><?=$item->approved==1?'Disa':'A'?>pprove Asset</a>
<a class="dropdown-item asset-rerender" href="#">Request Re-render</a>
<a class="dropdown-item" href="/admin/transactions?AssetID=<?=$item->id?>">Transaction History</a>
<?php } ?>
</div>
</div>
<?php } ?>
<h1 class="font-weight-normal"><?=Polygon::FilterText($item->name)?></h1>
<h5 class="font-weight-normal"><?=SITE_CONFIG["site"]["name"]?> <?=Catalog::GetTypeByNum($item->type)?></h5>
<div class="row">
<div class="col-lg-4 col-md-6 col-sm-12 pb-3">
<?php if (in_array($item->type, [4, 8, 11, 12, 17, 19]) && $item->approved == 1) { /* meshes, hats, shirts, pants, heads and gears */ ?>
<div class="thumbnail-holder text-right" data-reset-enabled-every-page="" data-3d-thumbs-enabled="" data-url="<?=Thumbnails::GetAsset($item)?>">
<span class="thumbnail-span mx-auto d-block" data-3d-url="/asset-thumbnail-3d/json?assetId=<?=$item->id?>">
<img alt="<?=Polygon::FilterText($item->name)?>" class="img-fluid" src="<?=Thumbnails::GetAsset($item)?>">
<div class="row">
<div class="col" style="max-width: 58rem">
<?php if($ownsAsset || $isCreator || $isAdmin) { ?>
<div class="dropdown d-flex justify-content-end float-right">
<a class="btn btn-sm btn-light py-0 px-1" href="#" role="button" id="configure-asset" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="fa-stack">
<i class="fas fa-cog"></i>
<i class="fas fa-angle-down"></i>
</span>
<button class="enable-three-dee btn btn-sm btn-light">Enable 3D</button>
</div>
<?php } else { ?>
<img src="<?=Thumbnails::GetAsset($item)?>" class="img-fluid mt-3" border="0">
<?php } ?>
</div>
<div class="col-lg-5 col-md-6 col-sm-6">
<div class="row pb-3">
<div class="col-4">
<img src="<?=Thumbnails::GetAvatar($item->creator)?>" class="img-fluid">
</div>
<div class="col-8">
<p class="m-0">Creator: <a href="/user?ID=<?=$item->creator?>"><?=$item->username?></a></p>
<p class="m-0">Created: <?=timeSince($item->created)?></p>
<p class="m-0">Updated: <?=timeSince($item->updated)?></p>
</div>
</div>
<?php if(strlen($item->description)) { ?>
<p><?=nl2br(Polygon::FilterText($item->description))?></p>
<hr>
<?php } if($item->type == 19) { ?>
<small class="text-muted">Gear Attributes:</small><br>
<?php foreach(json_decode($item->gear_attributes) as $attr => $enabled) { if($enabled) { ?>
<div class="gear-attribute"><i class="<?=Catalog::$GearAttributesDisplay[$attr]["icon"]?>"></i> <small><?=Catalog::$GearAttributesDisplay[$attr]["text_item"]?></small></div>
<?php } } } ?>
<?php if($item->type == 3) { ?>
<?php if($item->audioType == "audio/mid") { ?>
<p class="mb-2"><i class="far fa-info-circle text-primary"></i> This audio is a MIDI and cannot be played back in a browser, but will work ingame</p>
<?php } else { ?>
<audio src="/asset/?id=<?=$item->id?>&audiostream=true" controls="controls" style="max-height:30px;width:100%">
your browser smells
</audio>
<?php } } ?>
</div>
<div class="col-lg-3 col-md-12 col-sm-6 pl-0 d-flex justify-content-lg-end justify-content-center" style="align-items:flex-start">
<div class="card text-center bg-cardpanel px-3 py-2 BuyPriceBox">
<?php if($item->sale){ ?>
<p class="mb-1">Price: <span class="text-success"><?=$item->price?'<i class="fal fa-pizza-slice"></i> '.$item->price:'FREE'?></span></p>
</a>
<div class="dropdown-menu dropdown-menu-right bg-light" aria-labelledby="configure-asset">
<?php if($isCreator || Users::IsAdmin([Users::STAFF_CATALOG, Users::STAFF_ADMINISTRATOR])) { ?>
<a class="dropdown-item" href="/my/item?ID=<?=$item->id?>">Configure</a>
<?php } if($ownsAsset) { ?>
<span class="disabled-wrapper" data-toggle="tooltip" data-placement="top" data-original-title="You already own this item">
<button class="btn btn-success disabled px-4" disabled><h5 class="font-weight-normal mb-1"><?=!$item->sale || $item->price ? 'Buy Now':'Take One'?></h5></button>
</span>
<?php } elseif($item->sale) { ?>
<button data-asset-type="<?=Catalog::GetTypeByNum($item->type)?>" class="btn btn-success px-4 purchase-item-prompt" data-item-name="<?=htmlspecialchars($item->name)?>" data-item-id="<?=$item->id?>" data-item-thumbnail="<?=Thumbnails::GetAsset($item)?>" data-expected-price="<?=$item->price?>" data-seller-name="<?=$item->username?>"><h5 class="font-weight-normal mb-1"><?=$item->price?'Buy Now':'Take One'?></h5></button>
<?php } else { ?>
<span class="disabled-wrapper" data-toggle="tooltip" data-placement="top" data-original-title="This item is no longer for sale">
<button class="btn btn-success disabled px-4" disabled><h5 class="font-weight-normal mb-1">Buy Now</h5></button>
</span>
<a class="dropdown-item delete-item-prompt" href="#" data-item-id="<?=$item->id?>">Delete from My Stuff</a>
<?php } if(Users::IsAdmin()) { ?>
<a class="dropdown-item asset-<?=$item->approved==1?'decline':'approve'?>" href="#"><?=$item->approved==1?'Disa':'A'?>pprove Asset</a>
<a class="dropdown-item asset-rerender" href="#">Request Re-render</a>
<a class="dropdown-item" href="/admin/transactions?AssetID=<?=$item->id?>">Transaction History</a>
<?php } ?>
<p class="text-muted mb-0">(<?=$item->Sales?> sold)</p>
</div>
</div>
</div>
<?php if($item->comments) { ?>
<div class="comments-container mt-3">
<h3 class="font-weight-normal">Commentary</h3>
<?php } ?>
<h1 class="font-weight-normal"><?=Polygon::FilterText($item->name)?></h1>
<h5 class="font-weight-normal"><?=SITE_CONFIG["site"]["name"]?> <?=Catalog::GetTypeByNum($item->type)?></h5>
<div class="row">
<div class="col-lg-9">
<?php if(SESSION) { ?>
<div class="row write-comment">
<div class="col-2 pr-0">
<a href="/user?ID=<?=SESSION["user"]["id"]?>"><img src="<?=Thumbnails::GetStatus("rendering")?>" data-src="<?=Thumbnails::GetAvatar(SESSION["user"]["id"])?>" class="img-fluid"></a>
</div>
<div class="col-10">
<div class="card">
<div class="card-header bg-primary text-light py-2">Write a comment!</div>
<div class="card-body py-2">
<textarea class="form-control p-0 border-none" rows="2" style="resize:none"></textarea>
</div>
<div class="text-right">
<span class="text-danger post-error d-none">Please wait 60 seconds before posting another comment</span>
<button class="btn btn-sm btn-primary post-comment"><span class="spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span> Comment</button>
</div>
</div>
</div>
<div class="col-lg-4 col-md-6 col-sm-12 pb-3">
<?php if (in_array($item->type, [4, 8, 11, 12, 17, 19]) && $item->approved == 1) { /* meshes, hats, shirts, pants, heads and gears */ ?>
<div class="thumbnail-holder text-right" data-reset-enabled-every-page="" data-3d-thumbs-enabled="" data-url="<?=Thumbnails::GetAsset($item)?>">
<span class="thumbnail-span mx-auto d-block" data-3d-url="/asset-thumbnail-3d/json?assetId=<?=$item->id?>">
<img alt="<?=Polygon::FilterText($item->name)?>" class="img-fluid" src="<?=Thumbnails::GetAsset($item)?>">
</span>
<button class="enable-three-dee btn btn-sm btn-light">Enable 3D</button>
</div>
<?php } else { ?>
<img src="<?=Thumbnails::GetAsset($item)?>" class="img-fluid mt-3" border="0">
<?php } ?>
<div class="divider-bottom my-3"></div>
<div class="no-items d-none">
<div class="row comment">
<div class="col-2 pr-0 mb-3">
<img src="/img/ProjectPolygon.png" class="img-fluid">
</div>
<div class="col-lg-5 col-md-6 col-sm-6">
<div class="row pb-3">
<div class="col-4">
<img src="<?=Thumbnails::GetAvatar($item->creator)?>" class="img-fluid">
</div>
<div class="col-8">
<p class="m-0">Creator: <a href="/user?ID=<?=$item->creator?>"><?=$item->username?></a></p>
<p class="m-0">Created: <?=timeSince($item->created)?></p>
<p class="m-0">Updated: <?=timeSince($item->updated)?></p>
</div>
</div>
<?php if(strlen($item->description)) { ?>
<p><?=nl2br(Polygon::FilterText($item->description))?></p>
<hr>
<?php } if($item->type == 19) { ?>
<small class="text-muted">Gear Attributes:</small><br>
<?php foreach(json_decode($item->gear_attributes) as $attr => $enabled) { if($enabled) { ?>
<div class="gear-attribute"><i class="<?=Catalog::$GearAttributesDisplay[$attr]["icon"]?>"></i> <small><?=Catalog::$GearAttributesDisplay[$attr]["text_item"]?></small></div>
<?php } } } ?>
<?php if($item->type == 3) { ?>
<?php if($item->audioType == "audio/mid") { ?>
<p class="mb-2"><i class="far fa-info-circle text-primary"></i> This audio is a MIDI and cannot be played back in a browser, but will work ingame</p>
<?php } else { ?>
<audio src="/asset/?id=<?=$item->id?>&audiostream=true" controls="controls" style="max-height:30px;width:100%">
your browser smells
</audio>
<?php } } ?>
</div>
<div class="col-lg-3 col-md-12 col-sm-6 pl-0 d-flex justify-content-lg-end justify-content-center" style="align-items:flex-start">
<div class="card text-center bg-cardpanel px-3 py-2 BuyPriceBox">
<?php if($item->sale){ ?>
<p class="mb-1">Price: <span class="text-success"><?=$item->price?'<i class="fal fa-pizza-slice"></i> '.$item->price:'FREE'?></span></p>
<?php } if($ownsAsset) { ?>
<span class="disabled-wrapper" data-toggle="tooltip" data-placement="top" data-original-title="You already own this item">
<button class="btn btn-success disabled px-4" disabled><h5 class="font-weight-normal mb-1"><?=!$item->sale || $item->price ? 'Buy Now':'Take One'?></h5></button>
</span>
<?php } elseif($item->sale) { ?>
<button data-asset-type="<?=Catalog::GetTypeByNum($item->type)?>" class="btn btn-success px-4 purchase-item-prompt" data-item-name="<?=htmlspecialchars($item->name)?>" data-item-id="<?=$item->id?>" data-item-thumbnail="<?=Thumbnails::GetAsset($item)?>" data-expected-price="<?=$item->price?>" data-seller-name="<?=$item->username?>"><h5 class="font-weight-normal mb-1"><?=$item->price?'Buy Now':'Take One'?></h5></button>
<?php } else { ?>
<span class="disabled-wrapper" data-toggle="tooltip" data-placement="top" data-original-title="This item is no longer for sale">
<button class="btn btn-success disabled px-4" disabled><h5 class="font-weight-normal mb-1">Buy Now</h5></button>
</span>
<?php } ?>
<p class="text-muted mb-0">(<?=$item->Sales?> sold)</p>
</div>
</div>
</div>
<?php if($item->comments) { ?>
<div class="comments-container mt-3">
<h3 class="font-weight-normal">Commentary</h3>
<div class="row mt-4">
<div class="col-lg-9">
<?php if(SESSION) { ?>
<div class="row write-comment">
<div class="col-2 pr-0">
<a href="/user?ID=<?=SESSION["user"]["id"]?>"><img src="<?=Thumbnails::GetStatus("rendering")?>" data-src="<?=Thumbnails::GetAvatar(SESSION["user"]["id"])?>" class="img-fluid"></a>
</div>
<div class="col-10 mb-3">
<div class="col-10">
<div class="card">
<div class="card-header py-2">
Nobody has posted any comments for this item
</div>
<div class="card-header bg-primary text-light py-2">Write a comment!</div>
<div class="card-body py-2">
<p>Come and share your thoughts about it!</p>
<textarea class="form-control p-0 border-none" rows="2" style="resize:none"></textarea>
</div>
<div class="text-right">
<span class="text-danger post-error d-none">Please wait 60 seconds before posting another comment</span>
<button class="btn btn-sm btn-primary post-comment"><span class="spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span> Comment</button>
</div>
</div>
</div>
</div>
</div>
<div class="items"></div>
<div class="pagination form-inline justify-content-center d-none">
<button type="button" class="btn btn-light mx-2 back"><h5 class="mb-0"><i class="fal fa-caret-left"></i></h5></button>
<span>Page</span>
<input class="form-control form-control-sm text-center mx-1 px-0 page" type="text" data-last-page="1" style="width:40px">
<span>of <span class="pages">10</span></span>
<button type="button" class="btn btn-light mx-2 next"><h5 class="mb-0"><i class="fal fa-caret-right"></i></h5></button>
</div>
<div class="text-center">
<div class="loading"><span class="jumbo spinner-border" role="status"></span></div>
<a class="btn btn-light btn-sm show-more d-none">Show More</a>
</div>
<div class="template d-none">
<div class="row comment">
<div class="col-2 pr-0 mb-3">
<a href="/user?ID=$commenter_id"><img data-src="$commenter_avatar" class="img-fluid"></a>
</div>
<div class="col-10 mb-3">
<div class="card">
<div class="card-header py-2">
Posted $time by <a href="/user?ID=$commenter_id">$commenter_name</a>
<?php } ?>
<div class="divider-bottom my-3"></div>
<div class="no-items d-none">
<div class="row comment">
<div class="col-2 pr-0 mb-3">
<img src="/img/ProjectPolygon.png" class="img-fluid">
</div>
<div class="col-10 mb-3">
<div class="card">
<div class="card-header py-2">
Nobody has posted any comments for this item
</div>
<div class="card-body py-2">
<p>Come and share your thoughts about it!</p>
</div>
</div>
<div class="card-body py-2">
<p>$content</p>
</div>
</div>
</div>
<div class="items"></div>
<div class="pagination form-inline justify-content-center d-none">
<button type="button" class="btn btn-light mx-2 back"><h5 class="mb-0"><i class="fal fa-caret-left"></i></h5></button>
<span>Page</span>
<input class="form-control form-control-sm text-center mx-1 px-0 page" type="text" data-last-page="1" style="width:40px">
<span>of <span class="pages">10</span></span>
<button type="button" class="btn btn-light mx-2 next"><h5 class="mb-0"><i class="fal fa-caret-right"></i></h5></button>
</div>
<div class="text-center">
<div class="loading"><span class="jumbo spinner-border" role="status"></span></div>
<a class="btn btn-light btn-sm show-more d-none">Show More</a>
</div>
<div class="template d-none">
<div class="row comment">
<div class="col-2 pr-0 mb-3">
<a href="/user?ID=$commenter_id"><img data-src="$commenter_avatar" class="img-fluid"></a>
</div>
<div class="col-10 mb-3">
<div class="card">
<div class="card-header py-2">
Posted $time by <a href="/user?ID=$commenter_id">$commenter_name</a>
</div>
<div class="card-body py-2">
<p>$content</p>
</div>
</div>
</div>
</div>
@ -193,8 +195,8 @@ $pageBuilder->buildHeader();
</div>
</div>
</div>
<?php } ?>
</div>
<?php } ?>
</div>
<script type="text/javascript">
$(function(){ polygon.appendination.register(polygon.item.comments, 1200); });

View File

@ -1,7 +1,7 @@
polygon.games =
{
Joining: false,
protocols: {2009: "polygon-nine", 2010: "polygon-ten", 2011: "polygon-eleven", 2012: "polygon-twelve"},
protocols: { 2009: "polygon-nine", 2010: "polygon-ten", 2011: "polygon-eleven", 2012: "polygon-twelve" },
install: function(client)
{
@ -209,9 +209,20 @@ polygon.games.Places = polygon.CreateControl(
Control.SetFilter({FilterBy: $(this).val()});
});
$("." + Control.Container + "-container select.VersionFilter").change(function()
{
Control.SetFilter({FilterVersion: $(this).val()});
$("." + Control.Container + "-container select.VersionFilter").change(function() {
wrapper = $("." + Control.Container + "-container div.version-filter-wrapper");
version = $(this).val();
if (version == "All") {
wrapper.removeClass("input-group");
wrapper.find("div.input-group-append").addClass("d-none");
} else {
wrapper.addClass("input-group");
wrapper.find("div.input-group-append").removeClass("d-none");
wrapper.find("a.version-filter-download").attr("href", "https://setup" + version + ".pizzaboxer.xyz/Polygon" + version + ".exe");
}
Control.SetFilter({ FilterVersion: version });
});
$("." + Control.Container + "-container button.SearchButton").click(function()

View File

@ -50,7 +50,7 @@ $pageBuilder->buildHeader();
<p class="card-text">Done at: <?=date('j/n/Y g:i:s A \G\M\T', $moderationInfo->timeStarted)?></p>
<p class="card-text mb-0">Moderator note:</p>
<div class="card card-body px-2 pb-2 pt-1">
<?=str_replace('<p>', '<p class="mb-0">', $markdown->text($moderationInfo->reason, true))?>
<?=str_replace('<p>', '<p class="mb-0">', $markdown->setEmbedsEnabled(true)->text($moderationInfo->reason))?>
</div>
<br>
<p class="card-text"><?=$text["footer"][$moderationInfo->banType]?></p>

View File

@ -153,6 +153,9 @@ $pageBuilder->buildHeader();
<li class="nav-item">
<a class="nav-link" id="sessions-tab" data-toggle="tab" href="#sessions" role="tab" aria-controls="sessions" aria-selected="false">Sessions</a>
</li>
<li class="nav-item">
<a class="nav-link" id="data-tab" data-toggle="tab" href="#data" role="tab" aria-controls="data" aria-selected="false">Data</a>
</li>
</ul>
</div>
<div class="col-lg-10 col-md-9 px-3">
@ -299,6 +302,23 @@ $pageBuilder->buildHeader();
</div>
<button class="btn btn-danger destroy-sessions"><span class="spinner-border spinner-border-sm d-none"></span> Invalidate all other sessions</button>
</div>
<div class="tab-pane" id="data" role="tabpanel" aria-labelledby="data-tab">
<h2>Data</h2>
<p>If there's any data you wish to download and archive, you can do so here.</p>
<p>All forum data and archived Roblox audio assets will be publicly released in the Discord server.</p>
<div class="input-group data-select-wrapper" style="max-width:20rem;">
<select class="form-control form-control-sm data-select">
<option disabled selected>Select what to download...</option>
<option value="friends">Friends</option>
<option value="groups">Owned Groups</option>
<option value="inventory">Inventory</option>
<option value="transactions">Transactions</option>
</select>
<div class="input-group-append">
<a class="btn btn-sm btn-success disabled data-select-download" href="#"><i class="far fa-download"></i> Download</a>
</div>
</div>
</div>
</div>
</div>
</div>
@ -371,5 +391,10 @@ $pageBuilder->buildHeader();
polygon.button.busy(this);
$("form").submit();
});
$(".data-select").change(function() {
data = $(this).val();
$(".data-select-download").attr("href", "/api/account/data/" + data).removeClass("disabled");
});
</script>
<?php $pageBuilder->buildFooter(); ?>

View File

@ -7,20 +7,29 @@ use pizzaboxer\ProjectPolygon\PageBuilder;
Users::RequireLogin();
$Alert = false;
$interval = "1 week";
$LastCreation = SESSION["user"]["LastInviteTicketCheck"] ?: SESSION["user"]["jointime"];
$CreatableTickets = floor((time() - $LastCreation) / 1210000);
$TimeRemaining = GetReadableTime($LastCreation, ["RelativeTime" => "2 weeks"]);
$CreatableTickets = SESSION["user"]["CreatableInviteTickets"]; //floor((time() - $LastCreation) / strtotime($interval, 0));
$TimeRemaining = GetReadableTime($LastCreation, ["RelativeTime" => $interval]);
if ($CreatableTickets)
/* if (SESSION["user"]["CreatableInviteTickets"] != $CreatableTickets)
{
Database::singleton()->run(
"UPDATE users SET CreatableInviteTickets = :CreatableTickets, LastInviteTicketCheck = UNIX_TIMESTAMP() WHERE id = :UserID",
[":UserID" => SESSION["user"]["id"], ":CreatableTickets" => $CreatableTickets]
);
Database::singleton()->run(
"UPDATE users SET CreatableInviteTickets = :CreatableTickets, LastInviteTicketCheck = UNIX_TIMESTAMP() WHERE id = :UserID",
[":UserID" => SESSION["user"]["id"], ":CreatableTickets" => $CreatableTickets]
);
} */
if (($LastCreation + strtotime($interval, 0)) < time())
{
Database::singleton()->run(
"UPDATE users SET CreatableInviteTickets = CreatableInviteTickets + 1, LastInviteTicketCheck = UNIX_TIMESTAMP() WHERE id = :UserID",
[":UserID" => SESSION["user"]["id"]]
);
}
if ($_SERVER["REQUEST_METHOD"] == "POST" && SESSION["user"]["CreatableInviteTickets"] > 0)
if ($_SERVER["REQUEST_METHOD"] == "POST" && $CreatableTickets > 0)
{
$Ticket = sprintf("PolygonTicket(%s)", bin2hex(random_bytes(16)));
@ -29,10 +38,12 @@ if ($_SERVER["REQUEST_METHOD"] == "POST" && SESSION["user"]["CreatableInviteTick
[":Ticket" => $Ticket, ":UserID" => SESSION["user"]["id"]]
);
Database::singleton()->run(
"UPDATE users SET CreatableInviteTickets = CreatableInviteTickets - 1 WHERE id = :UserID",
[":UserID" => SESSION["user"]["id"]]
);
Database::singleton()->run(
"UPDATE users SET CreatableInviteTickets = CreatableInviteTickets - 1 WHERE id = :UserID",
[":UserID" => SESSION["user"]["id"]]
);
$CreatableTickets -= 1;
$Alert = ["Text" => sprintf("Your key has been created! <code>%s</code>", $Ticket), "Color" => "success"];
}
@ -97,8 +108,8 @@ $pageBuilder->buildHeader();
?>
<?php if($Alert !== false) { ?><div class="alert alert-<?=$Alert["Color"]?> px-2 py-1" role="alert"><?=$Alert["Text"]?></div><?php } ?>
<h2 class="font-weight-normal pb-0">My Invitations</h2>
<?php if (SESSION["user"]["CreatableInviteTickets"] > 0) { ?>
<p class="pb-0">You currently have <?=SESSION["user"]["CreatableInviteTickets"]?> ticket creations remaining.</p>
<?php if ($CreatableTickets > 0) { ?>
<p class="pb-0">You currently have <?=$CreatableTickets?> ticket creations remaining.</p>
<?php } else { ?>
<p class="pb-0">You must wait <?=$TimeRemaining?> before you can create a new invite ticket.</p>
<?php } ?>
@ -113,7 +124,7 @@ $pageBuilder->buildHeader();
</li>
</ul>
<div class="mt-3 mr-0 mr-md-3">
<?php if (SESSION["user"]["CreatableInviteTickets"] > 0) { ?>
<?php if ($CreatableTickets > 0) { ?>
<form method="post">
<button type="submit" class="btn btn-sm btn-success btn-block">Create Ticket</button>
</form>

402
nginx.conf Normal file
View File

@ -0,0 +1,402 @@
limit_req_zone $binary_remote_addr zone=catalogapi:10m rate=3r/s;
limit_req_zone $binary_remote_addr zone=characterapi:10m rate=3r/s;
# Automatic HTTPS Redirect
# (cloudflare's encryption mode MUST be set to Full for this to work properly)
server
{
listen 80;
server_name polygoncdn.pizzaboxer.xyz;
return 301 https://$host$request_uri;
}
server
{
listen 80;
listen 443 ssl http2;
server_name chef.pizzaboxer.xyz polygon.pizzaboxer.xyz polygon.local pizzaboxer.xyz www.pizzaboxer.xyz;
#server_name polygon.local;
add_header imagien-if "nickster v was bibster v";
add_header X-UA-Compatible "IE=Edge" always;
ssl_certificate ssl/pizzaboxer.xyz.pem;
ssl_certificate_key ssl/pizzaboxer.xyz.key;
root /var/www/pizzaboxer.xyz/polygon;
error_page 403 =404 /error.php?code=404;
error_page 404 /error.php?code=404;
index index.php index.html index.htm;
########################################
########### Client Rewrites ############
########################################
rewrite (?i)^/Landing.aspx$ /games redirect;
rewrite (?i)^/Asset$ /rbxclient/asset/fetch.php last;
rewrite (?i)^/Asset/$ /rbxclient/asset/fetch.php last;
rewrite (?i)^/Asset/Default.ashx$ /rbxclient/asset/fetch.php last;
rewrite (?i)^/Asset/CharacterFetch.ashx$ /rbxclient/asset/characterfetch.php last;
rewrite (?i)^/Asset/BodyColors.ashx$ /rbxclient/asset/bodycolors.php last;
rewrite (?i)^/Asset/GetScriptState.ashx$ /rbxclient/asset/getscriptstate.html last;
rewrite (?i)^/Experience/(.*)$ /Game/$1;
rewrite (?i)^/Thumbs/Avatar.ashx$ /thumbs/avatar.php last;
rewrite (?i)^/Thumbs/Asset.ashx$ /thumbs/asset.php last;
rewrite (?i)^/Game/PlaceLauncher.ashx$ /api/games/placelauncher.php last;
rewrite (?i)^/Game/Studio.ashx$ /rbxclient/game/studio.php last;
rewrite (?i)^/Game/Edit.ashx$ /rbxclient/game/edit.php last;
rewrite (?i)^/Game/Visit.ashx$ /rbxclient/game/visit.php last;
rewrite (?i)^/Game/Join.ashx$ /rbxclient/game/join.php last;
rewrite (?i)^/Game/GameServer.ashx$ /rbxclient/game/gameserver.php last;
rewrite (?i)^/Game/ClientPresence.ashx$ /rbxclient/game/clientpresence.php last;
rewrite (?i)^/Game/PlaceVisit.ashx$ /rbxclient/game/placevisit.php last;
rewrite (?i)^/Game/PlaceSpecificScript.ashx$ /rbxclient/game/placespecificscript.php last;
rewrite (?i)^/Game/LoadPlaceInfo.ashx$ /rbxclient/game/loadplaceinfo.php last;
rewrite (?i)^/Game/Help.aspx$ /rbxclient/game/help.php last;
rewrite (?i)^/Game/KeepAlivePinger.ashx$ /rbxclient/game/keepalivepinger.php last;
rewrite (?i)^/Game/MachineConfiguration.ashx$ /rbxclient/game/machineconfiguration.php last;
rewrite (?i)^/Game/Knockouts.ashx$ /rbxclient/game/knockouts.php last;
rewrite (?i)^/Game/Wipeouts.ashx$ /rbxclient/game/wipeouts.php last;
rewrite (?i)^/Game/GetAuthTicket$ /rbxclient/game/getauthticket.php last;
rewrite (?i)^/Game/Tools/ThumbnailAsset.ashx$ /thumbs/asset.php last;
rewrite (?i)^/Game/Tools/InsertAsset.ashx$ /rbxclient/game/tools/insertasset.php last;
rewrite (?i)^/Game/Badge/AwardBadge.ashx$ /rbxclient/game/badge/awardbadge.php last;
rewrite (?i)^/Game/Badge/HasBadge.ashx$ /rbxclient/game/badge/hasbadge.php last;
rewrite (?i)^/Game/Badge/IsBadgeDisabled.ashx$ /rbxclient/game/badge/isbadgedisabled.php last;
rewrite (?i)^/Game/GamePass/GamePassHandler.ashx$ /rbxclient/game/gamepass/gamepasshandler.php last;
rewrite (?i)^/Game/LuaWebService/HandleSocialRequest.ashx$ /rbxclient/game/luawebservice/handlesocialrequest.php last;
rewrite (?i)^/Game/(.*)$ /game/$1;
rewrite (?i)^/Friend/CreateFriend$ /rbxclient/friend/createfriend.php last;
rewrite (?i)^/Friend/BreakFriend$ /rbxclient/friend/breakfriend.php last;
rewrite (?i)^/Friend/AreFriends$ /rbxclient/friend/arefriends.php last;
rewrite (?i)^/Analytics/GamePerfMonitor.ashx$ /rbxclient/analytics/gameperfmonitor.php last;
rewrite (?i)^/Analytics/Measurement.ashx$ /rbxclient/analytics/measurement.php last;
rewrite (?i)^/Login/Negotiate.ashx$ /rbxclient/login/negotiate.php last;
rewrite (?i)^/Build/$ /develop redirect;
rewrite (?i)^/Build/Default.aspx$ /develop redirect;
rewrite (?i)^/IDE/Landing.aspx$ /ide/welcome redirect;
rewrite (?i)^/IDE/ClientToolbox.aspx$ /rbxclient/studio/toolbox.php last;
rewrite (?i)^/IDE/Upload.aspx$ /rbxclient/studio/publish-place.php last;
rewrite (?i)^/IDE/Welcome$ /rbxclient/studio/welcome.php last;
rewrite (?i)^/UI/Save.aspx$ /rbxclient/studio/publish-model.php last;
rewrite (?i)^/UploadMedia/PostImage.aspx$ /rbxclient/uploadmedia/screenshot.php last;
rewrite (?i)^/UploadMedia/UploadVideo.aspx$ /rbxclient/uploadmedia/video.php last;
rewrite (?i)^/Error/Dmp.ashx$ /rbxclient/error/dump.php;
########################################
########### Website Rewrites ###########
########################################
rewrite ^/(.*)-item(.*)$ /item$2;
rewrite ^/(.*)-place(.*)$ /placeitem$2;
rewrite ^/forum/$ /forum.php last;
rewrite ^/admin/$ /admin.php last;
rewrite ^/login/(.*)$ /directory_login/$1.php last;
rewrite ^/games/(.*)$ /directory_games/$1.php last;
rewrite ^/forum/(.*)$ /directory_forum/$1.php last;
rewrite ^/admin/(.*)$ /directory_admin/$1.php last;
rewrite /places/create$ /directory_places/create.php last;
rewrite /places/(.*)/update$ /directory_places/update.php?PlaceID=$1 last;
rewrite /asset-thumbnail-3d/json$ /thumbs/asset3d.php last;
rewrite /avatar-thumbnail-3d/json$ /thumbs/avatar3d.php last;
rewrite /thumbnail/resolve-hash/(.*)$ /thumbs/resolvehash.php?filename=$1 last;
location /
{
try_files $uri $uri/ @extensionless-php;
}
location /api/catalog
{
limit_req zone=catalogapi;
try_files $uri $uri/ @extensionless-php;
}
location /api/character
{
limit_req zone=characterapi;
try_files $uri $uri/ @extensionless-php;
}
location ~ /api/private
{
deny all;
return 404;
}
location ~ /\.
{
deny all;
return 404;
}
location @extensionless-php
{
rewrite ^(.*)$ $1.php last;
}
location ~ \.php$
{
include snippets/fastcgi-php.conf;
}
}
server
{
listen 80;
listen 443 ssl http2;
server_name stub;
#server_name polygon.pizzaboxer.xyz;
add_header imagien-if "nickster v was bibster v";
add_header X-UA-Compatible "IE=Edge" always;
ssl_certificate ssl/pizzaboxer.xyz.pem;
ssl_certificate_key ssl/pizzaboxer.xyz.key;
root /var/www/pizzaboxer.xyz/polygonmaintenance;
error_page 403 =404 index.html;
error_page 404 index.html;
index index.html;
}
server
{
listen 80;
listen 443 ssl http2;
server_name polygondev.pizzaboxer.xyz vednogylop.pizzaboxer.xyz dev.polygon.local;
add_header X-UA-Compatible "IE=Edge" always;
ssl_certificate ssl/pizzaboxer.xyz.pem;
ssl_certificate_key ssl/pizzaboxer.xyz.key;
root /var/www/pizzaboxer.xyz/polygondev;
error_page 403 =404 /error.php?code=404;
error_page 404 /error.php?code=404;
index index.php index.html index.htm;
########################################
########### Client Rewrites ############
########################################
rewrite (?i)^/Landing.aspx$ /games redirect;
rewrite (?i)^/Asset$ /rbxclient/asset/fetch.php last;
rewrite (?i)^/Asset/$ /rbxclient/asset/fetch.php last;
rewrite (?i)^/Asset/Default.ashx$ /rbxclient/asset/fetch.php last;
rewrite (?i)^/Asset/CharacterFetch.ashx$ /rbxclient/asset/characterfetch.php last;
rewrite (?i)^/Asset/BodyColors.ashx$ /rbxclient/asset/bodycolors.php last;
rewrite (?i)^/Asset/GetScriptState.ashx$ /rbxclient/asset/getscriptstate.html last;
rewrite (?i)^/Experience/(.*)$ /Game/$1;
rewrite (?i)^/Thumbs/Avatar.ashx$ /thumbs/avatar.php last;
rewrite (?i)^/Thumbs/Asset.ashx$ /thumbs/asset.php last;
rewrite (?i)^/Game/PlaceLauncher.ashx$ /api/games/placelauncher.php last;
rewrite (?i)^/Game/Studio.ashx$ /rbxclient/game/studio.php last;
rewrite (?i)^/Game/Edit.ashx$ /rbxclient/game/edit.php last;
rewrite (?i)^/Game/Visit.ashx$ /rbxclient/game/visit.php last;
rewrite (?i)^/Game/Join.ashx$ /rbxclient/game/join.php last;
rewrite (?i)^/Game/GameServer.ashx$ /rbxclient/game/gameserver.php last;
rewrite (?i)^/Game/ClientPresence.ashx$ /rbxclient/game/clientpresence.php last;
rewrite (?i)^/Game/PlaceVisit.ashx$ /rbxclient/game/placevisit.php last;
rewrite (?i)^/Game/PlaceSpecificScript.ashx$ /rbxclient/game/placespecificscript.php last;
rewrite (?i)^/Game/LoadPlaceInfo.ashx$ /rbxclient/game/loadplaceinfo.php last;
rewrite (?i)^/Game/Help.aspx$ /rbxclient/game/help.php last;
rewrite (?i)^/Game/KeepAlivePinger.ashx$ /rbxclient/game/keepalivepinger.php last;
rewrite (?i)^/Game/MachineConfiguration.ashx$ /rbxclient/game/machineconfiguration.php last;
rewrite (?i)^/Game/Knockouts.ashx$ /rbxclient/game/knockouts.php last;
rewrite (?i)^/Game/Wipeouts.ashx$ /rbxclient/game/wipeouts.php last;
rewrite (?i)^/Game/GetAuthTicket$ /rbxclient/game/getauthticket.php last;
rewrite (?i)^/Game/Tools/ThumbnailAsset.ashx$ /thumbs/asset.php last;
rewrite (?i)^/Game/Tools/InsertAsset.ashx$ /rbxclient/game/tools/insertasset.php last;
rewrite (?i)^/Game/Badge/AwardBadge.ashx$ /rbxclient/game/badge/awardbadge.php last;
rewrite (?i)^/Game/Badge/HasBadge.ashx$ /rbxclient/game/badge/hasbadge.php last;
rewrite (?i)^/Game/Badge/IsBadgeDisabled.ashx$ /rbxclient/game/badge/isbadgedisabled.php last;
rewrite (?i)^/Game/GamePass/GamePassHandler.ashx$ /rbxclient/game/gamepass/gamepasshandler.php last;
rewrite (?i)^/Game/LuaWebService/HandleSocialRequest.ashx$ /rbxclient/game/luawebservice/handlesocialrequest.php last;
rewrite (?i)^/Game/(.*)$ /game/$1;
rewrite (?i)^/Friend/CreateFriend$ /rbxclient/friend/createfriend.php last;
rewrite (?i)^/Friend/BreakFriend$ /rbxclient/friend/breakfriend.php last;
rewrite (?i)^/Friend/AreFriends$ /rbxclient/friend/arefriends.php last;
rewrite (?i)^/Analytics/GamePerfMonitor.ashx$ /rbxclient/analytics/gameperfmonitor.php last;
rewrite (?i)^/Analytics/Measurement.ashx$ /rbxclient/analytics/measurement.php last;
rewrite (?i)^/Login/Negotiate.ashx$ /rbxclient/login/negotiate.php last;
rewrite (?i)^/Build/$ /develop redirect;
rewrite (?i)^/Build/Default.aspx$ /develop redirect;
rewrite (?i)^/IDE/Landing.aspx$ /ide/welcome redirect;
rewrite (?i)^/IDE/ClientToolbox.aspx$ /rbxclient/studio/toolbox.php last;
rewrite (?i)^/IDE/Upload.aspx$ /rbxclient/studio/publish-place.php last;
rewrite (?i)^/IDE/Welcome$ /rbxclient/studio/welcome.php last;
rewrite (?i)^/UI/Save.aspx$ /rbxclient/studio/publish-model.php last;
rewrite (?i)^/UploadMedia/PostImage.aspx$ /rbxclient/uploadmedia/screenshot.php last;
rewrite (?i)^/UploadMedia/UploadVideo.aspx$ /rbxclient/uploadmedia/video.php last;
rewrite (?i)^/Error/Dmp.ashx$ /rbxclient/error/dump.php;
########################################
########### Website Rewrites ###########
########################################
rewrite ^/(.*)-item(.*)$ /item$2;
rewrite ^/(.*)-place(.*)$ /placeitem$2;
rewrite ^/forum/$ /forum.php last;
rewrite ^/admin/$ /admin.php last;
rewrite ^/login/(.*)$ /directory_login/$1.php last;
rewrite ^/games/(.*)$ /directory_games/$1.php last;
rewrite ^/forum/(.*)$ /directory_forum/$1.php last;
rewrite ^/admin/(.*)$ /directory_admin/$1.php last;
rewrite /places/create$ /directory_places/create.php last;
rewrite /places/(.*)/update$ /directory_places/update.php?PlaceID=$1 last;
rewrite /asset-thumbnail-3d/json$ /thumbs/asset3d.php last;
rewrite /avatar-thumbnail-3d/json$ /thumbs/avatar3d.php last;
rewrite /thumbnail/resolve-hash/(.*)$ /thumbs/resolvehash.php?filename=$1 last;
location /
{
try_files $uri $uri/ @extensionless-php;
}
location /api/catalog
{
limit_req zone=catalogapi;
try_files $uri $uri/ @extensionless-php;
}
location /api/character
{
limit_req zone=characterapi;
try_files $uri $uri/ @extensionless-php;
}
location ~ /api/private
{
deny all;
return 404;
}
location ~ /\.
{
deny all;
return 404;
}
location @extensionless-php
{
rewrite ^(.*)$ $1.php last;
}
location ~ \.php$
{
include snippets/fastcgi-php.conf;
}
}
server
{
listen 443 ssl http2;
server_name polygonapi.pizzaboxer.xyz clientsettingsapi.pizzaboxer.xyz;
ssl_certificate ssl/pizzaboxer.xyz.pem;
ssl_certificate_key ssl/pizzaboxer.xyz.key;
root /var/www/pizzaboxer.xyz/polygonapi;
error_page 403 =404 /404.php;
error_page 404 /404.php;
index index.php index.html index.htm;
rewrite (?i)^/currency/balance /api/currency/balance.php last;
rewrite (?i)^/marketplace/productinfo /api/marketplace/productinfo.php last;
rewrite (?i)^/ownership/hasasset /api/ownership/hasasset.php last;
rewrite (?i)^/users/([0-9]+) /api/users/info.php?userId=$1 last;
rewrite (?i)^/users/get-by-username /api/users/info.php last;
location ~ /private
{
deny all;
return 404;
}
location ~ ^/(status|ping)$
{
include snippets/fastcgi-php.conf;
}
location ~ \.php$
{
include snippets/fastcgi-php.conf;
}
}
server
{
listen 443 ssl http2;
server_name polygoncdn.pizzaboxer.xyz;
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Headers "x-polygon-csrf";
ssl_certificate ssl/pizzaboxer.xyz.pem;
ssl_certificate_key ssl/pizzaboxer.xyz.key;
error_page 405 =200 $uri;
root /var/www/pizzaboxer.xyz/polygoncdn;
}
server
{
listen 80;
listen 443 ssl http2;
server_name ~^setup(?<year>.+)\.pizzaboxer\.xyz;
ssl_certificate ssl/pizzaboxer.xyz.pem;
ssl_certificate_key ssl/pizzaboxer.xyz.key;
root /var/www/pizzaboxer.xyz/setup$year;
rewrite /version-(\w+)-(.*)$ /version-$1/$2 last;
}

View File

@ -1,5 +1,6 @@
<?php require $_SERVER['DOCUMENT_ROOT'].'/api/private/core.php';
use pizzaboxer\ProjectPolygon\Database;
use pizzaboxer\ProjectPolygon\Polygon;
use pizzaboxer\ProjectPolygon\Games;
use pizzaboxer\ProjectPolygon\Users;
@ -30,7 +31,7 @@ if($_SERVER['REQUEST_URI'] != "/".encode_asset_name($Asset->name)."-place?id=".$
redirect("/".encode_asset_name($Asset->name)."-place?id=".$Asset->id);
}
$pageBuilder = new PageBuilder(["title" => Polygon::FilterText($Asset->name).", ".vowel(Catalog::GetTypeByNum($Asset->type))." by ".$Asset->username]);
$pageBuilder = new PageBuilder(["title" => Polygon::FilterText($Asset->name).", ".vowel(Catalog::GetTypeByNum($Asset->type))." by ".$Asset->username, "ShowFooterAd" => false]);
$pageBuilder->addAppAttribute("data-asset-id", $Asset->id);
$pageBuilder->addAppAttribute("data-owns-asset", $CanConfigure ? "true" : "false");
$pageBuilder->addMetaTag("og:image", $AssetThumbnail);
@ -45,6 +46,26 @@ if (Polygon::IsEmbed())
$pageBuilder->buildFooter();
die();
}
else
{
$totalGameJoins = Database::singleton()->run(
"SELECT COUNT(*) FROM GameJobSessions WHERE UserID = :UserID",
[":UserID" => SESSION["user"]["id"]]
)->fetchColumn();
$failedGameJoins = Database::singleton()->run(
"SELECT COUNT(*) FROM GameJobSessions WHERE UserID = :UserID AND Verified = 0",
[":UserID" => SESSION["user"]["id"]]
)->fetchColumn();
// the idea here is that we only show the help message if at least 70% of all game joins have failed
if ($totalGameJoins == 0)
$failedGameJoinRate = 1;
else
$failedGameJoinRate = $failedGameJoins / $totalGameJoins;
$showHelpMessage = $failedGameJoinRate > 0.7;
}
$pageBuilder->addResource("scripts", "/js/protocolcheck.js");
$pageBuilder->addResource("polygonScripts", "/js/polygon/games.js");
@ -53,174 +74,183 @@ if($IsStaff) $pageBuilder->addResource("polygonScripts", "/js/polygon/admin/asse
$pageBuilder->buildHeader();
?>
<div class="container" style="max-width: 58rem">
<?php if ($CanConfigure) { ?>
<div class="dropdown d-flex justify-content-end float-right">
<a class="btn btn-sm btn-light py-0 px-1" href="#" role="button" id="configure-asset" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="fa-stack">
<i class="fas fa-cog"></i>
<i class="fas fa-angle-down"></i>
</span>
</a>
<div class="dropdown-menu dropdown-menu-right bg-light" aria-labelledby="configure-asset">
<?php if ($CanConfigure) { ?>
<a class="dropdown-item" href="/places/<?=$Asset->id?>/update">Configure</a>
<a class="dropdown-item" href="/asset/?id=<?=$Asset->id?>">Download Place File</a>
<?php } if ($IsAdmin) { ?>
<a class="dropdown-item asset-<?=$Asset->approved==1?'decline':'approve'?>" href="#"><?=$Asset->approved==1?'Disa':'A'?>pprove Asset</a>
<a class="dropdown-item asset-rerender" href="#">Request Re-render</a>
<?php } ?>
<?php if ($showHelpMessage) { ?>
<div class="bg-primary mb-2 px-3 py-2 text-light rounded">
<i class="fas fa-exclamation-circle"></i>
Having difficulty with the game client? <a href="/forum/showpost?PostID=1775" class="text-light">Read this help thread.</a>
</div>
<?php } ?>
<div class="row">
<div class="col" style="max-width: 58rem">
<?php if ($CanConfigure) { ?>
<div class="dropdown d-flex justify-content-end float-right">
<a class="btn btn-sm btn-light py-0 px-1" href="#" role="button" id="configure-asset" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="fa-stack">
<i class="fas fa-cog"></i>
<i class="fas fa-angle-down"></i>
</span>
</a>
<div class="dropdown-menu dropdown-menu-right bg-light" aria-labelledby="configure-asset">
<?php if ($CanConfigure) { ?>
<a class="dropdown-item" href="/places/<?=$Asset->id?>/update">Configure</a>
<a class="dropdown-item" href="/asset/?id=<?=$Asset->id?>">Download Place File</a>
<?php } if ($IsAdmin) { ?>
<a class="dropdown-item asset-<?=$Asset->approved==1?'decline':'approve'?>" href="#"><?=$Asset->approved==1?'Disa':'A'?>pprove Asset</a>
<a class="dropdown-item asset-rerender" href="#">Request Re-render</a>
<?php } ?>
</div>
</div>
</div>
<?php } ?>
<h2 class="font-weight-normal"><?=Polygon::FilterText($Asset->name)?></h2>
<div class="row">
<div class="col-sm-8">
<img src="<?=$AssetThumbnail?>" class="img-fluid">
<?php if (strlen($Asset->description)) { ?>
<p class="mb-0 mt-1"><?=nl2br(Polygon::FilterText($Asset->description))?></p>
<?php } ?>
</div>
<div class="col-sm-4">
<div class="row mx-0 mb-3 pb-2 divider-bottom">
<div class="pl-3">
<img src="<?=Thumbnails::GetAvatar($Asset->creator)?>" width="80" height="80">
<?php } ?>
<h2 class="font-weight-normal"><?=Polygon::FilterText($Asset->name)?></h2>
<div class="row">
<div class="col-sm-8">
<img src="<?=$AssetThumbnail?>" class="img-fluid">
<?php if (strlen($Asset->description)) { ?>
<p class="mb-0 mt-1"><?=Polygon::FilterText($markdown->setEmbedsEnabled(true)->text($Asset->description), false)?></p>
<?php } ?>
</div>
<div class="col-sm-4">
<div class="row mx-0 mb-3 pb-2 divider-bottom">
<div class="pl-3">
<img src="<?=Thumbnails::GetAvatar($Asset->creator)?>" width="80" height="80">
</div>
<div class="pl-2">
<h5 class="font-weight-normal mb-0">Builder:</h5>
<h5 class="font-weight-normal mb-0"><a href="/user?ID=<?=$Asset->creator?>"><?=$Asset->username?></a></h5>
<p class="mb-0">Joined: <?=date("m/d/Y", $Asset->jointime)?></p>
</div>
</div>
<div class="pl-2">
<h5 class="font-weight-normal mb-0">Builder:</h5>
<h5 class="font-weight-normal mb-0"><a href="/user?ID=<?=$Asset->creator?>"><?=$Asset->username?></a></h5>
<p class="mb-0">Joined: <?=date("m/d/Y", $Asset->jointime)?></p>
<?php if (Games::CanPlayGame($Asset) || $IsStaff) { ?>
<button class="btn btn-success btn-block my-2 pt-1 pb-0 mx-auto VisitButton VisitButtonPlay" placeid="<?=$Asset->id?>" style="max-width: 13rem"><h5 class="font-weight-normal pb-0">Play</h5></button>
<?php if ($Asset->publicDomain || $IsCreator || $IsStaff) { ?>
<button class="btn btn-success btn-block my-2 pt-1 pb-0 mx-auto VisitButton VisitButtonSolo" placeid="<?=$Asset->id?>" placeversion="<?=$Asset->Version?>" style="max-width: 13rem" title="Visit this game Solo" data-toggle="tooltip" data-placement="bottom"><h5 class="font-weight-normal pb-0">Visit</h5></button>
<button class="btn btn-success btn-block my-2 pt-1 pb-0 mx-auto VisitButton VisitButtonEdit" placeid="<?=$Asset->id?>" placeversion="<?=$Asset->Version?>" style="max-width: 13rem" title="Open in Studio Mode" data-toggle="tooltip" data-placement="bottom"><h5 class="font-weight-normal pb-0">Edit</h5></button>
<?php } ?>
<?php } else { ?>
<div class="text-center">
<p>Sorry, this place is currently only open to the creator's friends.</p>
</div>
<?php } ?>
<div class="details mt-3" style="line-height: normal">
<p class="mb-0"><small><b>Created:</b> <?=timeSince($Asset->created)?></small></p>
<p class="mb-0"><small><b>Updated:</b> <?=timeSince($Asset->updated)?></small></p>
<p class="mb-0"><small><b>Visited:</b> <?=number_format($Asset->Visits)?></small></p>
<p class="mb-0"><small><b>Version:</b> <?=$Asset->Version?></small></p>
<p class="mb-2"><small><b>Max Players:</b> <?=number_format($Asset->MaxPlayers)?></small></p>
<p class="mb-0"><small><b>Allowed Gear Types:</b></small></p>
<?php if (!in_array(true, $Gears)) { ?>
<i class="far fa-times-circle text-primary" data-toggle="tooltip" data-placement="bottom" title="No Gear Allowed"></i>
<?php } else { foreach($Gears as $Attribute => $Enabled) { if (!$Enabled) continue; ?>
<i class="<?=Catalog::$GearAttributesDisplay[$Attribute]["icon"]?> text-primary" data-toggle="tooltip" data-placement="bottom" title="<?=Catalog::$GearAttributesDisplay[$Attribute]["text_sel"]?>"></i>
<?php } } ?>
</div>
</div>
<?php if (Games::CanPlayGame($Asset) || $IsStaff) { ?>
<button class="btn btn-success btn-block my-2 pt-1 pb-0 mx-auto VisitButton VisitButtonPlay" placeid="<?=$Asset->id?>" style="max-width: 13rem"><h5 class="font-weight-normal pb-0">Play</h5></button>
<?php if ($Asset->publicDomain || $IsCreator || $IsStaff) { ?>
<button class="btn btn-success btn-block my-2 pt-1 pb-0 mx-auto VisitButton VisitButtonSolo" placeid="<?=$Asset->id?>" placeversion="<?=$Asset->Version?>" style="max-width: 13rem" title="Visit this game Solo" data-toggle="tooltip" data-placement="bottom"><h5 class="font-weight-normal pb-0">Visit</h5></button>
<button class="btn btn-success btn-block my-2 pt-1 pb-0 mx-auto VisitButton VisitButtonEdit" placeid="<?=$Asset->id?>" placeversion="<?=$Asset->Version?>" style="max-width: 13rem" title="Open in Studio Mode" data-toggle="tooltip" data-placement="bottom"><h5 class="font-weight-normal pb-0">Edit</h5></button>
<?php } ?>
<?php } else { ?>
<div class="text-center">
<p>Sorry, this place is currently only open to the creator's friends.</p>
</div>
<?php } ?>
<div class="details mt-3" style="line-height: normal">
<p class="mb-0"><small><b>Created:</b> <?=timeSince($Asset->created)?></small></p>
<p class="mb-0"><small><b>Updated:</b> <?=timeSince($Asset->updated)?></small></p>
<p class="mb-0"><small><b>Visited:</b> <?=number_format($Asset->Visits)?></small></p>
<p class="mb-0"><small><b>Version:</b> <?=$Asset->Version?></small></p>
<p class="mb-2"><small><b>Max Players:</b> <?=number_format($Asset->MaxPlayers)?></small></p>
<p class="mb-0"><small><b>Allowed Gear Types:</b></small></p>
<?php if (!in_array(true, $Gears)) { ?>
<i class="far fa-times-circle text-primary" data-toggle="tooltip" data-placement="bottom" title="No Gear Allowed"></i>
<?php } else { foreach($Gears as $Attribute => $Enabled) { if (!$Enabled) continue; ?>
<i class="<?=Catalog::$GearAttributesDisplay[$Attribute]["icon"]?> text-primary" data-toggle="tooltip" data-placement="bottom" title="<?=Catalog::$GearAttributesDisplay[$Attribute]["text_sel"]?>"></i>
<?php } } ?>
</div>
</div>
</div>
<ul class="nav nav-tabs mt-4 pl-2" id="placeTabs" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="games-tab" data-toggle="tab" href="#games" role="tab" aria-controls="games" aria-selected="true">Games</a>
</li>
<?php if($Asset->comments) { ?>
<li class="nav-item">
<a class="nav-link" id="commentary-tab" data-toggle="tab" href="#commentary" role="tab" aria-controls="commentary" aria-selected="true">Commentary</a>
</li>
<?php } ?>
</ul>
<div class="tab-content py-3" id="placeTabsContent">
<div class="tab-pane active running-games-container" id="games" role="tabpanel">
<div class="items"></div>
<div class="pagination form-inline justify-content-center d-none">
<button type="button" class="btn btn-light mx-2 back"><h5 class="mb-0"><i class="fal fa-caret-left"></i></h5></button>
<span>Page</span>
<input class="form-control form-control-sm text-center mx-1 px-0 page" type="text" data-last-page="1" style="width:40px">
<span>of <span class="pages">10</span></span>
<button type="button" class="btn btn-light mx-2 next"><h5 class="mb-0"><i class="fal fa-caret-right"></i></h5></button>
<ul class="nav nav-tabs mt-4 pl-2" id="placeTabs" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="games-tab" data-toggle="tab" href="#games" role="tab" aria-controls="games" aria-selected="true">Games</a>
</li>
<?php if($Asset->comments) { ?>
<li class="nav-item">
<a class="nav-link" id="commentary-tab" data-toggle="tab" href="#commentary" role="tab" aria-controls="commentary" aria-selected="true">Commentary</a>
</li>
<?php } ?>
</ul>
<div class="tab-content py-3" id="placeTabsContent">
<div class="tab-pane active running-games-container" id="games" role="tabpanel">
<div class="items"></div>
<div class="pagination form-inline justify-content-center d-none">
<button type="button" class="btn btn-light mx-2 back"><h5 class="mb-0"><i class="fal fa-caret-left"></i></h5></button>
<span>Page</span>
<input class="form-control form-control-sm text-center mx-1 px-0 page" type="text" data-last-page="1" style="width:40px">
<span>of <span class="pages">10</span></span>
<button type="button" class="btn btn-light mx-2 next"><h5 class="mb-0"><i class="fal fa-caret-right"></i></h5></button>
</div>
<div class="text-center">
<div class="loading"><span class="jumbo spinner-border" role="status"></span></div>
<p class="no-items"></p>
<button class="btn btn-sm btn-light refresh d-none">Refresh</button>
</div>
<div class="template d-none">
<div class="row">
<div class="col-3">
<p>$PlayerCount of $MaximumPlayers players max</p>
<button class="btn btn-sm btn-light VisitButton VisitButtonPlay" jobid="$JobID">Join</button>
<button class="btn btn-sm btn-light ShutdownGame" jobid="$JobID">Shutdown</button>
</div>
<div class="col-9">
<div class="row mx-0 IngamePlayers"></div>
</div>
</div>
</div>
</div>
<div class="text-center">
<div class="loading"><span class="jumbo spinner-border" role="status"></span></div>
<p class="no-items"></p>
<button class="btn btn-sm btn-light refresh d-none">Refresh</button>
</div>
<div class="template d-none">
<?php if($Asset->comments) { ?>
<div class="tab-pane comments-container" id="commentary" role="tabpanel">
<div class="row">
<div class="col-3">
<p>$PlayerCount of $MaximumPlayers players max</p>
<button class="btn btn-sm btn-light VisitButton VisitButtonPlay" jobid="$JobID">Join</button>
<button class="btn btn-sm btn-light ShutdownGame" jobid="$JobID">Shutdown</button>
</div>
<div class="col-9">
<div class="row mx-0 IngamePlayers"></div>
</div>
</div>
</div>
</div>
<?php if($Asset->comments) { ?>
<div class="tab-pane comments-container" id="commentary" role="tabpanel">
<div class="row">
<div class="col-lg-9">
<?php if(SESSION) { ?>
<div class="row write-comment">
<div class="col-2 pr-0">
<a href="/user?ID=<?=SESSION["user"]["id"]?>"><img src="<?=Thumbnails::GetStatus("rendering")?>" data-src="<?=Thumbnails::GetAvatar(SESSION["user"]["id"])?>" class="img-fluid"></a>
</div>
<div class="col-10">
<div class="card">
<div class="card-header bg-primary text-light py-2">Write a comment!</div>
<div class="card-body py-2">
<textarea class="form-control p-0 border-none" rows="2" style="resize:none"></textarea>
</div>
<div class="text-right">
<span class="text-danger post-error d-none">Please wait 60 seconds before posting another comment</span>
<button class="btn btn-sm btn-primary post-comment"><span class="spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span> Comment</button>
</div>
<div class="col-lg-9">
<?php if(SESSION) { ?>
<div class="row write-comment">
<div class="col-2 pr-0">
<a href="/user?ID=<?=SESSION["user"]["id"]?>"><img src="<?=Thumbnails::GetStatus("rendering")?>" data-src="<?=Thumbnails::GetAvatar(SESSION["user"]["id"])?>" class="img-fluid"></a>
</div>
</div>
</div>
<?php } ?>
<div class="divider-bottom my-3"></div>
<div class="no-items d-none">
<div class="row comment">
<div class="col-2 pr-0 mb-3">
<img src="/img/ProjectPolygon.png" class="img-fluid">
</div>
<div class="col-10 mb-3">
<div class="col-10">
<div class="card">
<div class="card-header py-2">
Nobody has posted any comments for this item
</div>
<div class="card-header bg-primary text-light py-2">Write a comment!</div>
<div class="card-body py-2">
<p>Come and share your thoughts about it!</p>
<textarea class="form-control p-0 border-none" rows="2" style="resize:none"></textarea>
</div>
<div class="text-right">
<span class="text-danger post-error d-none">Please wait 60 seconds before posting another comment</span>
<button class="btn btn-sm btn-primary post-comment"><span class="spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span> Comment</button>
</div>
</div>
</div>
</div>
</div>
<div class="items"></div>
<div class="pagination form-inline justify-content-center d-none">
<button type="button" class="btn btn-light mx-2 back"><h5 class="mb-0"><i class="fal fa-caret-left"></i></h5></button>
<span>Page</span>
<input class="form-control form-control-sm text-center mx-1 px-0 page" type="text" data-last-page="1" style="width:40px">
<span>of <span class="pages">10</span></span>
<button type="button" class="btn btn-light mx-2 next"><h5 class="mb-0"><i class="fal fa-caret-right"></i></h5></button>
</div>
<div class="text-center">
<div class="loading"><span class="jumbo spinner-border" role="status"></span></div>
<a class="btn btn-light btn-sm show-more d-none">Show More</a>
</div>
<div class="template d-none">
<div class="row comment">
<div class="col-2 pr-0 mb-3">
<a href="/user?ID=$commenter_id"><img data-src="$commenter_avatar" class="img-fluid"></a>
</div>
<div class="col-10 mb-3">
<div class="card">
<div class="card-header py-2">
Posted $time by <a href="/user?ID=$commenter_id">$commenter_name</a>
<?php } ?>
<div class="divider-bottom my-3"></div>
<div class="no-items d-none">
<div class="row comment">
<div class="col-2 pr-0 mb-3">
<img src="/img/ProjectPolygon.png" class="img-fluid">
</div>
<div class="col-10 mb-3">
<div class="card">
<div class="card-header py-2">
Nobody has posted any comments for this item
</div>
<div class="card-body py-2">
<p>Come and share your thoughts about it!</p>
</div>
</div>
<div class="card-body py-2">
<p>$content</p>
</div>
</div>
</div>
<div class="items"></div>
<div class="pagination form-inline justify-content-center d-none">
<button type="button" class="btn btn-light mx-2 back"><h5 class="mb-0"><i class="fal fa-caret-left"></i></h5></button>
<span>Page</span>
<input class="form-control form-control-sm text-center mx-1 px-0 page" type="text" data-last-page="1" style="width:40px">
<span>of <span class="pages">10</span></span>
<button type="button" class="btn btn-light mx-2 next"><h5 class="mb-0"><i class="fal fa-caret-right"></i></h5></button>
</div>
<div class="text-center">
<div class="loading"><span class="jumbo spinner-border" role="status"></span></div>
<a class="btn btn-light btn-sm show-more d-none">Show More</a>
</div>
<div class="template d-none">
<div class="row comment">
<div class="col-2 pr-0 mb-3">
<a href="/user?ID=$commenter_id"><img data-src="$commenter_avatar" class="img-fluid"></a>
</div>
<div class="col-10 mb-3">
<div class="card">
<div class="card-header py-2">
Posted $time by <a href="/user?ID=$commenter_id">$commenter_name</a>
</div>
<div class="card-body py-2">
<p>$content</p>
</div>
</div>
</div>
</div>
@ -228,8 +258,8 @@ $pageBuilder->buildHeader();
</div>
</div>
</div>
<?php } ?>
</div>
<?php } ?>
</div>
</div>
<?php $pageBuilder->buildFooter(); ?>

View File

@ -179,7 +179,7 @@ else
{
if ($Asset->approved == 2) die(http_response_code(403));
}
else if (SESSION && SESSION["user"]["id"] != 1)
else
{
if ($Asset->approved != 1) die(http_response_code(403));
if ($Asset->Access == "Friends" && !Games::CanPlayGame($Asset)) die(http_response_code(403));
@ -241,4 +241,4 @@ else
if(!$RobloxAsset && $Asset->type == 5) $AssetData = RBXClient::CryptSignScript($AssetData, $Asset->id);
header('Content-Length: '.strlen($AssetData));
die($AssetData);
die($AssetData);

View File

@ -35,7 +35,7 @@ else if ($FriendConnection->status == 0) // friend request pending
{
Database::singleton()->run("UPDATE friends SET status = 1 WHERE id = :FriendID", [":FriendID" => $FriendConnection->id]);
}
else if ($FriendConnection->Status == 1) // friend connection already exists
else if ($FriendConnection->status == 1) // friend connection already exists
{
throw new Exception("friend connection already exists between firstUserId {$RequesterID} and secondUserId {$ReceiverID}");
}

View File

@ -41,7 +41,7 @@ else if (SESSION)
$LocationType = $_GET["LocationType"] ?? "Visit";
$PlaceInfo = Catalog::GetAssetInfo($PlaceID);
if (!$PlaceInfo) die("OK");
if (!$PlaceInfo || !$PlaceInfo->Version) die("");
// check if they have ownership of the place
if ($LocationType == "Studio" && !$PlaceInfo->publicDomain && $PlaceInfo->creator != SESSION["user"]["id"])

File diff suppressed because one or more lines are too long

View File

@ -77,7 +77,8 @@ if ($_SERVER['REQUEST_METHOD'] == "POST")
"ServerRunning" => 0,
"ActivePlayers" => 0,
"MaxPlayers" => 10,
"Access" => "Friends",
// "Access" => "Friends",
"Access" => "Everyone",
"Visits" => 0,
"Version" => 2010,
"ChatType" => "Classic",

View File

@ -5,6 +5,7 @@ use pizzaboxer\ProjectPolygon\Thumbnails;
$ResX = $_GET['x'] ?? $_GET['wd'] ?? $_GET["width"] ?? 420;
$ResY = $_GET['y'] ?? $_GET['ht'] ?? $_GET["height"] ?? 420;
$ForceRoblox = isset($_GET["roblox"]) && $_GET["roblox"] == "true";
$AssetID = $_GET['id'] ?? $_GET['assetId'] ?? $_GET['aid'] ?? 0;
$AssetVersionID = $_GET['assetversionid'] ?? $_GET['assetVersionId'] ?? 0;
@ -14,7 +15,7 @@ $AssetInfo = Database::singleton()->run(
[":AssetID" => $AssetID]
)->fetch(\PDO::FETCH_OBJ);
if (!$AssetInfo)
if (!$AssetInfo || $ForceRoblox)
{
if (($AssetID && is_numeric($AssetID)) || ($AssetVersionID && is_numeric($AssetVersionID)))
{
@ -50,6 +51,7 @@ if (!$AssetInfo)
$parametersHttp = http_build_query($parameters);
// alternate URL: https://assetgame.roblox.com/asset/request-thumbnail-fix?
$serviceRequest = file_get_contents("https://assetgame.roblox.com/Thumbs/Asset.asmx/RequestThumbnail_v2?{$parametersHttp}", false, $context);
if ($http_response_header[0] == "HTTP/1.1 200 OK")