- Avatar Sandbox rewrite
- Updated owned item tags code
- Inventory Collectibles Category
- Great Divide Features ("Potentially Unbalanced" indicator in server list and User Statistics tab on profiles)
- Refreshed Settings Page design
- Fixed library item type detection
- Breadcrumbs on the view page for models, audios, decals, and meshes now link to the Library instead of the Store.
- If the document loads prior to the DOMContentLoaded event being registered in the sitewide.js file, then it'll still run everything as normal instead of just not running
- Updated README.md
I was bored so:
- You can now make a profile act like a birthday profile by appending ?birthday=true to the URL
456 lines
No EOL
12 KiB
JavaScript
Executable file
456 lines
No EOL
12 KiB
JavaScript
Executable file
const Manifest = chrome.runtime.getManifest();
|
|
const SettingsURL = chrome.runtime.getURL('settings.html');
|
|
|
|
const DefaultSettings = {
|
|
PinnedGamesOn: true,
|
|
ForumMentsOn: true,
|
|
BestFriendsOn: false,
|
|
ImprovedFrListsOn: false,
|
|
IRLPriceWithCurrency: {
|
|
Enabled: true,
|
|
Currency: 0,
|
|
Package: 0
|
|
},
|
|
IRLPriceWithCurrencyOn: true,
|
|
IRLPriceWithCurrencyCurrency: 0,
|
|
IRLPriceWithCurrencyPackage: 0,
|
|
HideNotifBadgesOn: false,
|
|
StoreOwnTagOn: true,
|
|
ThemeCreatorOn: false,
|
|
ThemeCreator: {
|
|
Enabled: false,
|
|
BGColor: null,
|
|
BGImage: null,
|
|
BGImageSize: 'fit',
|
|
PrimaryTextColor: null,
|
|
SecondaryTextColor: null,
|
|
LinkTextColor: null,
|
|
WebsiteLogo: null
|
|
},
|
|
ModifyNavOn: false,
|
|
ModifyNav: [
|
|
{
|
|
Label: 'Places',
|
|
Link: 'https://polytoria.com/places'
|
|
},
|
|
{
|
|
Label: 'Store',
|
|
Link: 'https://polytoria.com/store'
|
|
},
|
|
{
|
|
Label: 'Guilds',
|
|
Link: 'https://polytoria.com/guilds'
|
|
},
|
|
{
|
|
Label: 'People',
|
|
Link: 'https://polytoria.com/users'
|
|
},
|
|
{
|
|
Label: 'Forum',
|
|
Link: 'https://polytoria.com/forum'
|
|
}
|
|
],
|
|
MoreSearchFiltersOn: true,
|
|
ApplyMembershipTheme: {
|
|
Enabled: false,
|
|
Theme: 0
|
|
},
|
|
ApplyMembershipThemeOn: false,
|
|
ApplyMembershipThemeTheme: 0,
|
|
MultiCancelOutTradesOn: true,
|
|
ItemWishlistOn: true,
|
|
HideUpgradeBtnOn: false,
|
|
TryOnItemsOn: true,
|
|
OutfitCostOn: true,
|
|
ShowPlaceRevenueOn: true,
|
|
ReplaceItemSalesOn: false,
|
|
HoardersListOn: true,
|
|
HoardersList: {
|
|
Enabled: true,
|
|
AvatarsEnabled: false,
|
|
MinCopies: 2
|
|
},
|
|
LibraryDownloadsOn: true,
|
|
EventItemsCatOn: true,
|
|
HomeFriendCountOn: true,
|
|
HideUserAds: {
|
|
Enabled: false,
|
|
Banners: true,
|
|
Rectangles: true
|
|
},
|
|
UploadMultipleDecals: true,
|
|
GD_ServerBalanceOn: true,
|
|
AvatarDimensionToggleOn: true,
|
|
TheGreatDivide: {
|
|
Enabled: true,
|
|
UnbalancedIndicatorOn: true,
|
|
MVPUserIndicatorOn: true,
|
|
UserStatsOn: true,
|
|
LeaderboardsOn: true
|
|
},
|
|
CollectibleInventoryCatOn: true
|
|
}
|
|
|
|
// ON EXTENSION INSTALL / RELOAD
|
|
chrome.runtime.onInstalled.addListener(() => {
|
|
chrome.storage.sync.get(['PolyPlus_Settings'], function(result){
|
|
const MergedSettings = MergeObjects((result.PolyPlus_Settings || DefaultSettings), DefaultSettings)
|
|
chrome.storage.sync.set({'PolyPlus_Settings': MergedSettings}, function(){
|
|
console.log('Successfully merged settings')
|
|
})
|
|
})
|
|
});
|
|
|
|
chrome.runtime.onMessage.addListener(async function (request, sender, sendResponse) {
|
|
if (request.action === 'reload') {
|
|
chrome.runtime.reload();
|
|
} else if (request.action === 'greatdivide_stats') {
|
|
const Statistics = (await (await fetch('https://stats.silly.mom/player_stats?username=' + request.username)).json()).results
|
|
|
|
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs){
|
|
chrome.scripting
|
|
.executeScript({
|
|
target: {tabId: tabs[0].id},
|
|
func: LoadStats,
|
|
args: [Statistics]
|
|
})
|
|
})
|
|
|
|
const LoadStats = function(stats){
|
|
if (stats !== null) {
|
|
stats = stats[0]
|
|
document.getElementById('p+greatdivide_stats').innerHTML = `
|
|
<div class="mb-1">
|
|
<b>
|
|
<i class="fa-duotone fa-swords text-center d-inline-block" style="width:1.2em"></i>
|
|
Kills
|
|
</b>
|
|
<span class="float-end">
|
|
${stats.Kills.toLocaleString()} (${stats.UniqueKills.toLocaleString()} unique)
|
|
</span>
|
|
</div>
|
|
<div class="mb-1">
|
|
<b>
|
|
<i class="fa-duotone fa-skull text-center d-inline-block" style="width:1.2em"></i>
|
|
Deaths
|
|
</b>
|
|
<span class="float-end">
|
|
${stats.Deaths.toLocaleString()}
|
|
</span>
|
|
</div>
|
|
<div class="mb-1">
|
|
<b>
|
|
<i class="fa-solid fa-percent text-center d-inline-block" style="width:1.2em"></i>
|
|
Kill Death Ratio
|
|
</b>
|
|
<span class="float-end">
|
|
${(stats.Kills / stats.Deaths).toFixed(4)}
|
|
</span>
|
|
</div>
|
|
<div class="mb-1">
|
|
<b>
|
|
<i class="fa-duotone fa-hundred-points text-center d-inline-block" style="width:1.2em"></i>
|
|
Points Scored
|
|
</b>
|
|
<span class="float-end">
|
|
${stats.PointsScored.toLocaleString()}
|
|
</span>
|
|
</div>
|
|
<div class="mb-1">
|
|
<b>
|
|
<i class="fa-solid fa-money-bill-wave text-center d-inline-block" style="width:1.2em"></i>
|
|
Cash Earned
|
|
</b>
|
|
<span class="float-end">
|
|
${stats.CashEarned.toLocaleString()}
|
|
</span>
|
|
</div>
|
|
<div class="mb-1">
|
|
<b>
|
|
<i class="fa-duotone fa-flag text-center d-inline-block" style="width:1.2em"></i>
|
|
Flags Captured
|
|
</b>
|
|
<span class="float-end">
|
|
${stats.FlagsCaptured} (${stats.FlagsReturned} returned)
|
|
</span>
|
|
</div>
|
|
<div class="mb-3">
|
|
<b>
|
|
<i class="fa-solid fa-box-open text-center d-inline-block" style="width:1.2em"></i>
|
|
Airdrops Collected
|
|
</b>
|
|
<span class="float-end">
|
|
${stats.AirdropsCollected}
|
|
</span>
|
|
</div>
|
|
`
|
|
} else {
|
|
document.getElementById('p+greatdivide_stats').innerHTML = "<div class=\"mb-3\">This user hasn't participated in The Great Divide.</div>"
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// WHEN CLICKING ON EXTENSION ICON OPEN THE SETTINGS PAGE
|
|
chrome.action.onClicked.addListener((tab) => {
|
|
chrome.tabs.create({active: true, url: SettingsURL});
|
|
});
|
|
|
|
// REGISTER AN ALARM FOR DAILY UPDATE CHECK
|
|
chrome.alarms.create('PolyPlus-UpdateCheck', {
|
|
when: Date.now() + GetNext12PM()
|
|
});
|
|
|
|
function GetNext12PM() {
|
|
const Now = new Date();
|
|
const Next = new Date();
|
|
Next.setHours(12, 0, 0, 0);
|
|
if (Now.getHours() >= 12) {
|
|
Next.setDate(Next.getDate() + 1);
|
|
}
|
|
return Next - Now;
|
|
}
|
|
|
|
// HANDLE ALARMS FIRING
|
|
/*
|
|
chrome.alarms.onAlarm.addListener(function (alarm) {
|
|
if (alarm.name === 'PolyPlus-UpdateCheck') {
|
|
RunUpdateNotifier();
|
|
}
|
|
});
|
|
*/
|
|
function RunUpdateNotifier() {
|
|
chrome.storage.local.get(['PolyPlus_LiveVersion', 'PolyPlus_OutOfDate', 'PolyPlus_SkipUpdate'], function (result) {
|
|
const OutOfDate = result.PolyPlus_OutOfDate || false;
|
|
const SkipUpdate = result.PolyPlus_SkipUpdate || null;
|
|
const LiveVersion = result.PolyPlus_LiveVersion || Manifest.version;
|
|
if (OutOfDate !== true && SkipUpdate !== LiveVersion) {
|
|
fetch('https://polyplus.vercel.app/data/version.json')
|
|
.then((response) => {
|
|
if (!response.ok) {
|
|
throw new Error('Network not ok');
|
|
}
|
|
return response.json();
|
|
})
|
|
.then((data) => {
|
|
chrome.storage.local.set({PolyPlus_LiveVersion: data.version}, function () {
|
|
console.log('Cached live version');
|
|
});
|
|
if (data.version > Manifest.version) {
|
|
chrome.storage.local.set({PolyPlus_OutOfDate: true, PolyPlus_ReleaseNotes: data.releaseNotes}, function () {
|
|
console.log('Cached update notifier result');
|
|
});
|
|
chrome.notifications.create(
|
|
'',
|
|
{
|
|
type: 'basic',
|
|
iconUrl: chrome.runtime.getURL('icon.png'),
|
|
title: 'New Update Available',
|
|
message: 'A new update is available for Poly+! (v' + data.version + ')'
|
|
},
|
|
function (notificationID) {
|
|
chrome.notifications.onClicked.addListener(function (id) {
|
|
if (id === notificationID) {
|
|
chrome.tabs.create({url: 'https://github.com/IndexingGitHub/PolyPlus/releases', active: true});
|
|
chrome.notifications.clear(notificationID);
|
|
}
|
|
});
|
|
}
|
|
);
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
console.log(error);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
chrome.contextMenus.removeAll(function () {
|
|
chrome.contextMenus.create({
|
|
title: 'Run Update Notifier',
|
|
id: 'PolyPlus-RunUpdateNotifier',
|
|
contexts: ['all'],
|
|
documentUrlPatterns: [
|
|
'https://polytoria.com/my/settings/polyplus*'
|
|
]
|
|
});
|
|
|
|
// COPY ASSET ID CONTEXT MENU ITEM REGISTRATION
|
|
/*
|
|
const AssetTypes = ["Place", "User", "Item", "Guild"]
|
|
AssetTypes.forEach(type => {
|
|
chrome.contextMenus.create({
|
|
title: 'Copy ' + type + ' ID',
|
|
id: 'PolyPlus-Copy' + type + 'ID',
|
|
contexts: ['link'],
|
|
documentUrlPatterns: ['https://polytoria.com/*', SettingsURL],
|
|
targetUrlPatterns: [
|
|
'https://polytoria.com/places/**'
|
|
]
|
|
});
|
|
})
|
|
*/
|
|
chrome.contextMenus.create({
|
|
title: 'Copy Place ID',
|
|
id: 'PolyPlus-CopyPlaceID',
|
|
contexts: ['link'],
|
|
documentUrlPatterns: ['https://polytoria.com/*', SettingsURL],
|
|
targetUrlPatterns: [
|
|
'https://polytoria.com/places/**'
|
|
]
|
|
});
|
|
chrome.contextMenus.create({
|
|
title: 'Copy User ID',
|
|
id: 'PolyPlus-CopyUserID',
|
|
contexts: ['link'],
|
|
documentUrlPatterns: ['https://polytoria.com/*', SettingsURL],
|
|
targetUrlPatterns: [
|
|
'https://polytoria.com/users/**',
|
|
'https://polytoria.com/u/**'
|
|
]
|
|
});
|
|
chrome.contextMenus.create({
|
|
title: 'Copy Item ID',
|
|
id: 'PolyPlus-CopyItemID',
|
|
contexts: ['link'],
|
|
documentUrlPatterns: ['https://polytoria.com/*', SettingsURL],
|
|
targetUrlPatterns: [
|
|
'https://polytoria.com/store/**'
|
|
]
|
|
});
|
|
chrome.contextMenus.create({
|
|
title: 'Copy Guild ID',
|
|
id: 'PolyPlus-CopyGuildID',
|
|
contexts: ['link'],
|
|
documentUrlPatterns: ['https://polytoria.com/*', SettingsURL],
|
|
targetUrlPatterns: [
|
|
'https://polytoria.com/guilds/**'
|
|
]
|
|
});
|
|
|
|
// COPY AVATAR HASH CONTEXT MENU ITEM REGISTRATION
|
|
chrome.contextMenus.create({
|
|
title: 'Copy Avatar Hash',
|
|
id: 'PolyPlus-CopyAvatarHash',
|
|
contexts: ['image'],
|
|
documentUrlPatterns: ['https://polytoria.com/*', SettingsURL],
|
|
targetUrlPatterns: [
|
|
'https://c0.ptacdn.com/thumbnails/avatars/**'
|
|
]
|
|
});
|
|
});
|
|
|
|
// HANDLE CONTEXT MENU ITEMS
|
|
chrome.contextMenus.onClicked.addListener(async function (info, tab) {
|
|
if (["CopyPlaceID", "CopyUserID", "CopyItemID", "CopyGuildID"].indexOf(info.menuItemId.split('-')[1]) !== -1) {
|
|
console.log(info.linkUrl.split('/')[3]);
|
|
let ID = info.linkUrl.split('/')[4];
|
|
if (info.linkUrl.split('/')[3] === 'u') {
|
|
ID = (await (await fetch('https://api.polytoria.com/v1/users/find?username=' + info.linkUrl.split('/')[4])).json()).id;
|
|
}
|
|
console.log(ID);
|
|
chrome.scripting
|
|
.executeScript({
|
|
target: {tabId: tab.id},
|
|
func: CopyAssetID,
|
|
args: [ID]
|
|
})
|
|
.then(() => console.log('Copied ID!'));
|
|
}
|
|
|
|
if (info.menuItemId === 'PolyPlus-CopyAvatarHash') {
|
|
let Hash = new URL(info.srcUrl).pathname.split('/')[3].replace('-icon', '').replace('.png', '');
|
|
chrome.scripting
|
|
.executeScript({
|
|
target: {tabId: tab.id},
|
|
func: CopyAvatarHash,
|
|
args: [Hash]
|
|
})
|
|
.then(() => console.log('Copied ID!'));
|
|
}
|
|
|
|
if (info.menuItemId === 'PolyPlus-RunUpdateNotifier') {
|
|
RunUpdateNotifier();
|
|
}
|
|
});
|
|
|
|
/*
|
|
GREEN LOGO WHEN EXTENSION APPLIES TO CURRENT TAB PAGE, RED WHEN IT DOESN'T
|
|
COMING SOON
|
|
|
|
chrome.tabs.onActivated.addListener(function (info){
|
|
chrome.tabs.get(info.tabId, function(tab){
|
|
const Any = CheckIfScriptApplies(tab.url)
|
|
console.log(Any)
|
|
});
|
|
});
|
|
|
|
function CheckIfScriptApplies(url) {
|
|
const matches = Manifest.content_scripts.map(script => {
|
|
script.matches.forEach(match => {
|
|
console.log(url, match, url.startsWith(match))
|
|
if (url.startsWith(match)) {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
})
|
|
})
|
|
|
|
return matches
|
|
}
|
|
|
|
function matchesUrl(patterns, url) {
|
|
return patterns.some(pattern => {
|
|
return new RegExp(pattern).test(url);
|
|
});
|
|
}
|
|
*/
|
|
|
|
function CopyAssetID(id) {
|
|
navigator.clipboard
|
|
.writeText(id)
|
|
.catch((err) => {
|
|
alert('Failure to copy ID.', err);
|
|
});
|
|
}
|
|
|
|
function CopyAvatarHash(hash) {
|
|
navigator.clipboard
|
|
.writeText(hash)
|
|
.then(() => {
|
|
alert('Successfully copied avatar hash!');
|
|
})
|
|
.catch(() => {
|
|
alert('Failure to copy avatar hash.');
|
|
});
|
|
}
|
|
|
|
function OpenSweetAlert2Modal(icon, title, text) {
|
|
console.log(window, window.Swal, window.bootstrap)
|
|
window.Swal.fire({
|
|
icon: icon,
|
|
title: title,
|
|
text: text
|
|
})
|
|
}
|
|
|
|
// MergeObjects function was written by ChatGPT cause I was lazy and it was awhile ago
|
|
function MergeObjects(obj1, obj2) {
|
|
var mergedObj = {};
|
|
|
|
// Copy the values from obj1 to the mergedObj
|
|
for (var key in obj1) {
|
|
mergedObj[key] = obj1[key];
|
|
}
|
|
|
|
// Merge the values from obj2 into the mergedObj, favoring obj2 for non-existing keys in obj1
|
|
for (var key in obj2) {
|
|
if (!obj1.hasOwnProperty(key)) {
|
|
mergedObj[key] = obj2[key];
|
|
}
|
|
}
|
|
|
|
return mergedObj;
|
|
} |