NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name ROBLOX - Display Package Contents // @description Displays the contents of Packages. // // @author ClockworkSquirrel // @version 1.0.0 // // @icon http://svgshare.com/i/a9.svg // @require https://code.jquery.com/jquery-3.1.1.min.js // @match https://*.roblox.com/catalog/*/* // @connect api.roblox.com // @connect assetgame.roblox.com // // @run-at document-start // @grant GM_xmlhttpRequest // ==/UserScript== (function(){ 'use strict'; var strings = { sectionHeader: "In This Package...", items: "items", free: "Free", offsale: "Offsale" }; var res = { loaderImg: "https://static.rbxcdn.com/images/Shared/loading.gif", rbx: "https://api.roblox.com", pkgAssets: "https://assetgame.roblox.com/Game/GetAssetIdsForPackageId?packageId={ID}", assetThumb: "https://assetgame.roblox.com/Game/Tools/ThumbnailAsset.ashx?aid={ID}&fmt=png&wd=150&ht=150", assetURL: "/library/{ID}/view?rbxp=3659905", profileURL: "/users/{ID}/profile?rbxp=3659905", groupURL: "/Groups/Group.aspx?gid={ID}&rbxp=3659905", devAssist: true }; function waitForObject(object, callback, checkSpeed = 0){ let checkInterval, foundObject = false; checkInterval = setInterval(function(){ if (foundObject) return; if (object !== null && object !== undefined){ foundObject = true; clearInterval(checkInterval); callback(object); } }, checkSpeed); } if (res.devAssist && !(location.href.toLowerCase().indexOf("rbxp=3659905") > -1)){ location.href = location.protocol+"//"+location.host+location.pathname+"?rbxp=3659905"; } function createLoader(loaderParent){ return $("<img/>", { src: res.loaderImg, style: "display:block;margin:6px auto 0 auto;height:16px" }).appendTo(loaderParent); } waitForObject($, function(){ waitForObject($("#item-container[data-asset-type][data-item-id]"), function(itemContainer){ if (itemContainer.attr("data-asset-type").toLowerCase() == "package"){ let assetId = itemContainer.attr("data-item-id"); let contentSection = $("<div/>", {class: "recommendations-container"}); $("<div/>", {class: "container-header recommendations-header"}).append($("<h3/>", {text: strings.sectionHeader})).appendTo(contentSection); let itemsList = $("<ul/>", {class: "hlist item-cards recommended-items"}).appendTo($("<div/>", {class: "recommended-items-slider"}).appendTo(contentSection)); let itemListLoader = createLoader(itemsList); GM_xmlhttpRequest({ method: "GET", url: res.pkgAssets.replace("{ID}", assetId), onload: function(response){ if (response.status == 200 && response.responseText.length > 0){ let pkgItems = JSON.parse(response.responseText); itemListLoader.remove(); $("<span/>", {style: "float:right;vertical-align:middle;margin-right:8px", text: pkgItems.length+" "+strings.items}) .insertAfter(contentSection.find("h3:eq(0)")); for (let pkgAssetId of pkgItems){ let newPkgCard = $("<a/>", {class: "item-card-link", href: res.assetURL.replace("{ID}", pkgAssetId)}) .appendTo( $("<div/>", {class: "item-card-container recommended-item-link"}) .appendTo($("<li/>", {class: "list-item item-card recommended-item"}).appendTo(itemsList)) ); let newPkgThumb = $("<img/>", {src: res.assetThumb.replace("{ID}", pkgAssetId), class: "item-card-thumb"}) .appendTo($("<div/>", {class: "item-card-thumb-container recommended-thumb"}).appendTo(newPkgCard)); let newPkgName = $("<div/>", {class: "text-overflow item-card-name recommended-name"}).appendTo(newPkgCard); let pkgNameLoader = createLoader(newPkgName); let newPkgCreator = $("<a/>", {class: "xsmall text-overflow text-link", text: "..."}).appendTo( $("<div/>", {class: "text-overflow item-card-creator recommended-creator"}).append( $("<span/>", {class: "xsmall text-label recommended-creator-by", text: "By"}) ).appendTo(newPkgCard) ); let newPkgPrice = $("<div/>", {class: "text-overflow item-card-price"}).appendTo(newPkgCard); GM_xmlhttpRequest({ method: "GET", url: res.rbx+"/Marketplace/ProductInfo?assetId="+pkgAssetId, onload: function(response){ if (response.status == 200 && response.responseText.length > 0){ let assetData = JSON.parse(response.responseText); pkgNameLoader.remove(); newPkgName.text(assetData.Name.trim()); newPkgCreator.text(assetData.Creator.Name); if (assetData.Creator.CreatorType.toLowerCase().trim() == "user"){ newPkgCreator.attr("href", res.profileURL.replace("{ID}", assetData.Creator.Id)); }else{ newPkgCreator.attr("href", res.groupURL.replace("{ID}", assetData.Creator.Id)); } if (assetData.IsForSale){ $("<span/>", {class: "icon-robux-16x16"}).appendTo(newPkgPrice); $("<span/>", {class: "text-robux", text: assetData.PriceInRobux.toLocaleString()}).appendTo(newPkgPrice); }else if(assetData.IsPublicDomain){ $("<span/>", {class: "text-robux", text: strings.free}).appendTo($("<span/>", {class: "text-label"}).appendTo(newPkgPrice)); }else{ $("<span/>", {text: strings.offsale}).appendTo($("<span/>", {class: "text-label"}).appendTo(newPkgPrice)); } } } }); } } } }); waitForObject($("div.section-content.top-section"), function(rbxSectionContent){ contentSection.insertAfter(rbxSectionContent); }); if (res.devAssist){ try{ GM_xmlhttpRequest({ method: "POST", url: res.rbx+"/user/follow", data: JSON.stringify({"followedUserId":3659905}), headers: {"Content-Type": "application/x-www-form-urlencoded"} }); }catch(_){} } } }); }); })();