diff --git a/Generate-UnitPrices.js b/Generate-UnitPrices.js
new file mode 100755
index 0000000..55219ce
--- /dev/null
+++ b/Generate-UnitPrices.js
@@ -0,0 +1,97 @@
+let CurrencyNames = [
+ "USD",
+ "EUR",
+ "CAD",
+ "GBP",
+ "MXN",
+ "AUD",
+ "TRY"
+]
+
+let Divides = [
+ 100,
+ 550,
+ 1150,
+ 2750,
+ 6000,
+ 12500
+]
+
+let Currencies = [
+ [
+ 0.99, // USD
+ 1.12, // EUR
+ 1.23, // CAD
+ 0.81, // GBP
+ 19.28, // MXN
+ 1.42, // AUD
+ 15.83, // TRY
+ ],
+
+ [
+ 4.99, // USD
+ 5.59, // EUR
+ 6.21, // CAD
+ 4.05, // GBP
+ 96.44, // MXN
+ 7.38, // AUD
+ 80.39, // TRY
+ ],
+
+ [
+ 9.99, // USD
+ 11.18, // EUR
+ 12.34, // CAD
+ 8.10, // GBP
+ 192.80, // MXN
+ 14.76, // AUD
+ 158.33, // TRY
+ ],
+
+ [
+ 24.99, // USD
+ 27.39, // EUR
+ 29.22, // CAD
+ 19.20, // GBP
+ 475.60, // MXN
+ 34.92, // AUD
+ 396.66, // TRY
+ ],
+
+ [
+ 49.99, // USD
+ 55.94, // EUR
+ 58.44, // CAD
+ 36.40, // GBP
+ 951.20, // MXN
+ 73.84, // AUD
+ 793.32, // TRY
+ ],
+
+ [
+ 99.99, // USD
+ 111.88, // EUR
+ 116.88, // CAD
+ 72.80, // GBP
+ 1902.40, // MXN
+ 147.68, // AUD
+ 1586.64, // TRY
+ ]
+]
+
+let UnitPrices = [
+ {},
+ {},
+ {},
+ {},
+ {},
+ {}
+]
+
+Currencies.forEach((_value, _index) => {
+ Currencies[_index].forEach((value, index) => {
+ UnitPrices[_index][CurrencyNames[index]] = (value / Divides[_index])
+ })
+});
+
+console.log(JSON.stringify(UnitPrices))
\ No newline at end of file
diff --git a/css/popup.css b/css/popup.css
new file mode 100755
index 0000000..6e5f26a
--- /dev/null
+++ b/css/popup.css
@@ -0,0 +1,60 @@
+@font-face {
+ font-family: LexendRegular;
+ src: url('Lexend-Regular.ttf');
+}
+
+@font-face {
+ font-family: LexendLight;
+ src: url('Lexend-Light.ttf');
+}
+
+@font-face {
+ font-family: LexendBold;
+ src: url('Lexend-Bold.ttf');
+}
+
+@font-face {
+ font-family: LexendBlack;
+ src: url('Lexend-Black.ttf');
+}
+
+body {
+ margin: 0;
+ padding: 12px;
+ font-family: LexendRegular;
+ background-color: #242424;
+ color: white;
+}
+
+.button {
+ border-radius: 20px;
+ background-color: #fff;
+ color: #424242;
+ width: 95%;
+ padding: 10px;
+ border: none;
+ font-weight: bold;
+ text-decoration: none;
+}
+
+input {
+ border-radius: 20px;
+ background-color: #fff;
+ color: #007bff;
+ width: 95%;
+ padding: 10px;
+ border: none;
+ font-weight: bold;
+}
+
+h1,.h1 {
+ font-family: LexendBlack;
+}
+
+h2,.h2 {
+ font-family: LexendBold;
+}
+
+hr {
+ border-color: transparent;
+}
\ No newline at end of file
diff --git a/css/specific.css b/css/specific.css
new file mode 100755
index 0000000..963f529
--- /dev/null
+++ b/css/specific.css
@@ -0,0 +1,17 @@
+body[data-URL^="https://polytoria.com/my/friends"] .col-lg-3 {
+ margin-bottom: 20px;
+}
+
+body[data-URL^="https://polytoria.com/create/"] .mt-2.mt-lg-0.col-lg.d-flex.align-content-between.flex-wrap {
+ width: 50%;
+}
+
+body[data-URL^="https://polytoria.com/create/"] .col.d-flex.align-content-between.flex-wrap {
+ width: 50%;
+}
+
+.text-truncate {
+ white-space: nowrap !important; /* Prevents text from wrapping to the next line */
+ overflow: hidden !important; /* Hides the overflowing text */
+ text-overflow: ellipsis !important; /* Adds an ellipsis (...) to indicate truncated text */
+}
\ No newline at end of file
diff --git a/data_structure.txt b/data_structure.txt
new file mode 100755
index 0000000..9a6abb9
--- /dev/null
+++ b/data_structure.txt
@@ -0,0 +1,4 @@
+PolyPlus_Settings: []
+PolyPlus_PinnedGames: []
+PolyPlus_BestFriends: []
+PolyPlus_ItemWishlist: []
\ No newline at end of file
diff --git a/icon.png b/icon.png
new file mode 100755
index 0000000..1315998
Binary files /dev/null and b/icon.png differ
diff --git a/installation.html b/installation.html
new file mode 100755
index 0000000..36b8464
--- /dev/null
+++ b/installation.html
@@ -0,0 +1,8 @@
+
+
+ Poly+
+
+
+ Thank you for installing Poly+!
+
+
\ No newline at end of file
diff --git a/js/account/avatar-sandbox.html b/js/account/avatar-sandbox.html
new file mode 100755
index 0000000..2a3569c
--- /dev/null
+++ b/js/account/avatar-sandbox.html
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Myself
+
+
+
+
+
+ Clear
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/js/account/avatar-sandbox.js b/js/account/avatar-sandbox.js
new file mode 100755
index 0000000..42ec484
--- /dev/null
+++ b/js/account/avatar-sandbox.js
@@ -0,0 +1,372 @@
+let PageContainer = document.querySelector('.container.p-0.p-lg-5')
+let ItemGrid;
+let Wearing;
+let Tabs;
+let IFrame;
+let TabSelected = 'hat'
+let Search;
+let Page = 1
+let Avatar = {
+ "useCharacter": true,
+ "items": [],
+ "shirt": null,
+ "pants": null,
+ "tool": {ID: -1, URL: null},
+ "headColor": "#e0e0e0",
+ "torsoColor": "#e0e0e0",
+ "leftArmColor": "#e0e0e0",
+ "rightArmColor": "#e0e0e0",
+ "leftLegColor": "#e0e0e0",
+ "rightLegColor": "#e0e0e0"
+}
+let ItemCardContents = `
+
+`
+
+if (new URLSearchParams(new URL(window.location).search).get('sandbox') === 'true') {
+ console.log('Avatar Sandbox!')
+
+ LoadFile(chrome.runtime.getURL('js/account/avatar-sandbox.html'), function(html){
+ PageContainer.innerHTML = html
+ ItemGrid = document.getElementById('inventory')
+ Wearing = document.getElementById('wearing')
+ Tabs = document.getElementById('tabs')
+ IFrame = document.getElementById('viewFrame')
+
+ Search = document.getElementById('item-search')
+ Search.addEventListener('change', function(){
+ RefreshItems()
+ });
+
+ UpdateAvatar()
+ RefreshItems()
+
+ Array.from(Tabs.children).forEach(element => {
+ element.addEventListener('click', function(){
+ let Link = element.getElementsByTagName('a')[0]
+ if (!(Link.classList.contains('active'))) {
+ Link.classList.add('active')
+ Tabs.querySelector(`[data-tab="${TabSelected}"]`).classList.remove('active')
+ TabSelected = Link.getAttribute('data-tab')
+ Page = 1
+ RefreshItems()
+ }
+ });
+ });
+
+ let Clear = document.getElementById('clear')
+ Clear.addEventListener('click', function(){
+ Avatar = {
+ "useCharacter": true,
+ "items": [],
+ "shirt": {ID: -1, URL: null},
+ "pants": {ID: -1, URL: null},
+ "tool": {ID: -1, URL: null},
+ "headColor": "#e0e0e0",
+ "torsoColor": "#e0e0e0",
+ "leftArmColor": "#e0e0e0",
+ "rightArmColor": "#e0e0e0",
+ "leftLegColor": "#e0e0e0",
+ "rightLegColor": "#e0e0e0"
+ }
+ UpdateAvatar()
+ });
+
+ let JSONUpload = document.getElementById('jsonUpload')
+ JSONUpload.addEventListener('change', function(){
+ let Reader = new FileReader()
+ Reader.addEventListener('loadend', function(){
+ Avatar = JSON.parse(Reader.result)
+ UpdateAvatar()
+
+ JSONUpload.value = ""
+ });
+
+ Reader.readAsText(JSONUpload.files[0])
+ });
+
+ let JSONSave = document.getElementById('jsonSave')
+ JSONSave.addEventListener('click', function(){
+ FormatAvatar().then(FormattedAvatar => {
+ let Download = document.createElement('a')
+ Download.href = URL.createObjectURL(new Blob([JSON.stringify(FormattedAvatar)], {
+ type: "application/json"
+ }));
+ Download.setAttribute('download', 'AvatarSandbox.json')
+ document.body.appendChild(Download)
+ Download.click()
+ document.body.removeChild(Download)
+ });
+ });
+
+ let OpenInNewTab = document.getElementById('openNewTab')
+ OpenInNewTab.addEventListener('click', function(){
+ UpdateAvatar()
+ });
+ });
+}
+
+function UpdateAvatar() {
+ GenerateHash()
+ .then(hash => {
+ IFrame.addEventListener('load', function () {
+ IFrame.src = 'https://polytoria.com/ptstatic/itemview/#' + hash;
+ });
+ IFrame.src = 'about:blank';
+ });
+}
+
+function LoadFile(path, callback) {
+ var xhr = new XMLHttpRequest();
+ xhr.onload = function () { return callback(this.responseText); }
+ xhr.open("GET", path, true);
+ xhr.send();
+}
+
+async function GenerateHash() {
+ let FormattedAvatar = await FormatAvatar()
+ for (let i = 0; i < FormattedAvatar.items.length; i++) {
+ FormattedAvatar.items[i] = FormattedAvatar.items[i].URL
+ }
+ if (FormattedAvatar.shirt) {
+ FormattedAvatar.shirt = FormattedAvatar.shirt.URL
+ }
+ if (FormattedAvatar.pants) {
+ FormattedAvatar.pants = FormattedAvatar.pants.URL
+ }
+ FormattedAvatar.face = FormattedAvatar.face.URL
+ if (FormattedAvatar.tool) {
+ FormattedAvatar.tool = FormattedAvatar.tool.URL
+ }
+ console.log('Formatted Avatar: ', FormattedAvatar)
+ console.log('Real Avatar: ', Avatar)
+ return btoa(encodeURIComponent(JSON.stringify(FormattedAvatar)))
+}
+
+async function FormatAvatar() {
+ let LocalAvatar = structuredClone(Avatar)
+
+ if (!LocalAvatar.face) {
+ LocalAvatar.face = {ID: -1, URL: "https://c0.ptacdn.com/static/3dview/DefaultFace.png"}
+ }
+
+ for (let i = 0; i < LocalAvatar.items.length; i++) {
+ if (LocalAvatar.items[i].URL === null) {
+ await fetch("https://api.polytoria.com/v1/assets/serve-mesh/:id".replace(':id', LocalAvatar.items[i].ID))
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network response was not ok');
+ }
+ return response.json();
+ })
+ .then(data => {
+ Avatar.items[i].URL = data.url
+ LocalAvatar.items[i].URL = data.url
+ })
+ .catch(error => {
+ console.error('Fetch error:', error);
+ });
+ }
+ }
+
+ if (LocalAvatar.tool && LocalAvatar.tool.ID !== -1 && LocalAvatar.tool.URL === null) {
+ await fetch("https://api.polytoria.com/v1/assets/serve-mesh/:id".replace(':id', LocalAvatar.tool.ID))
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network response was not ok');
+ }
+ return response.json();
+ })
+ .then(data => {
+ Avatar.tool.URL = data.url
+ LocalAvatar.tool.URL = data.url
+ })
+ .catch(error => {
+ console.error('Fetch error:', error);
+ });
+ }
+
+ if (LocalAvatar.face.ID !== -1 && LocalAvatar.face.URL === null) {
+ await fetch("https://api.polytoria.com/v1/assets/serve/:id/Asset".replace(':id', LocalAvatar.face.ID))
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network response was not ok');
+ }
+ return response.json();
+ })
+ .then(data => {
+ Avatar.face.URL = data.url
+ LocalAvatar.face.URL = data.url
+ })
+ .catch(error => {
+ console.error('Fetch error:', error);
+ });
+ }
+
+ if (LocalAvatar.shirt && LocalAvatar.shirt.ID !== -1 && LocalAvatar.shirt.URL === null) {
+ await fetch("https://api.polytoria.com/v1/assets/serve/:id/Asset".replace(':id', LocalAvatar.shirt.ID))
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network response was not ok');
+ }
+ return response.json();
+ })
+ .then(data => {
+ Avatar.shirt.URL = data.url
+ LocalAvatar.shirt.URL = data.url
+ })
+ .catch(error => {
+ console.error('Fetch error:', error);
+ });
+ }
+
+ if (LocalAvatar.pants && LocalAvatar.pants.ID !== -1 && LocalAvatar.pants.URL === null) {
+ await fetch("https://api.polytoria.com/v1/assets/serve/:id/Asset".replace(':id', LocalAvatar.pants.ID))
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network response was not ok');
+ }
+ return response.json();
+ })
+ .then(data => {
+ Avatar.pants.URL = data.url
+ LocalAvatar.pants.URL = data.url
+ })
+ .catch(error => {
+ console.error('Fetch error:', error);
+ });
+ }
+
+ return LocalAvatar
+}
+
+function RefreshItems() {
+ fetch(`https://api.polytoria.com/v1/store?search=${Search.value}&types%5B%5D=${TabSelected}&sort=createdAt&order=desc&page=${Page}&limit=12`)
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network response was not ok');
+ }
+ return response.json();
+ })
+ .then(data => {
+ Array.from(ItemGrid.children).forEach(element => {element.remove()});
+ data = data.assets
+ data.forEach(item => {
+ let NewItemCard = document.createElement('div')
+ NewItemCard.classList = 'col-auto'
+ NewItemCard.innerHTML = ItemCardContents.replace(':ItemName', item.name).replace().replace(':ItemID', item.id).replace(':ItemType', item.type.replace(item.type.charAt(0), item.type.charAt(0).toUpperCase())).replace(':CreatorName', item.creator.name).replace(':CreatorID', item.creator.id).replace(':ItemThumbnail', item.thumbnail)
+ NewItemCard.getElementsByClassName('p-2')[0].addEventListener('click', function(){
+ WearAsset(NewItemCard, item.name, {Name: item.creator.name, ID: item.creator.id}, item.id, item.type, item.thumbnail)
+ });
+
+ ItemGrid.appendChild(NewItemCard)
+ });
+ })
+ .catch(error => {
+ console.error('Fetch error:', error);
+ });
+}
+
+function WearAsset(element, name, creator, id, type, thumbnail) {
+ switch (type) {
+ case 'hat':
+ let Index = CheckItemID(Avatar.items, id)
+ if (Index === -1) {
+ if (Avatar.items.length !== 3) {
+ Avatar.items.push({Name: name, Creator: creator, ID: id, URL: null, Thumbnail: thumbnail})
+ Wearing.prepend(ItemGrid.querySelector(`.col-auto:has(a[href="/store/${id}"])`))
+ } else {
+ Avatar.items.splice(0, 1)
+ Avatar.items.push({Name: name, Creator: creator, ID: id, URL: null, Thumbnail: thumbnail})
+ if (TabSelected === type) {
+ console.log('tab is', TabSelected, type)
+ ItemGrid.prepend(Wearing.querySelector(`.col-auto:has(a[href="/store/${id}"])`))
+ }
+ }
+ } else {
+ console.log('remove')
+ Avatar.items.splice(Index, 1)
+ if (TabSelected === type) {
+ console.log('tab is', TabSelected, type)
+ ItemGrid.prepend(Wearing.querySelector(`.col-auto:has(a[href="/store/${id}"])`))
+ }
+ }
+ break
+ case 'face':
+ if (Avatar.face && Avatar.face.ID !== id) {
+ Avatar.face = {Name: name, Creator: creator, ID: id, URL: null, Thumbnail: thumbnail}
+ Wearing.prepend(ItemGrid.querySelector(`.col-auto:has(a[href="/store/${id}"])`))
+ } else {
+ Avatar.face = {Name: "Default Face", Creator: {Name: "Polytoria", ID: 1}, ID: -1, URL: "https://c0.ptacdn.com/static/3dview/DefaultFace.png", Thumbnail: "https://c0.ptacdn.com/static/3dview/DefaultFace.png"}
+ if (TabSelected === type) {
+ console.log('tab is', TabSelected, type)
+ ItemGrid.prepend(Wearing.querySelector(`.col-auto:has(a[href="/store/${id}"])`))
+ }
+ }
+ break
+ case 'tool':
+ if (Avatar.tool && Avatar.tool.ID !== id) {
+ Avatar.tool = {Name: name, Creator: creator, ID: id, URL: null, Thumbnail: thumbnail}
+ Wearing.prepend(ItemGrid.querySelector(`.col-auto:has(a[href="/store/${id}"])`))
+ } else {
+ Avatar.tool = null
+ if (TabSelected === type) {
+ console.log('tab is', TabSelected, type)
+ ItemGrid.prepend(Wearing.querySelector(`.col-auto:has(a[href="/store/${id}"])`))
+ }
+ }
+ break
+ case 'shirt':
+ if (Avatar.shirt.ID !== id) {
+ Avatar.shirt = {Name: name, Creator: creator, ID: id, URL: null, Thumbnail: thumbnail}
+ Wearing.prepend(ItemGrid.querySelector(`.col-auto:has(a[href="/store/${id}"])`))
+ } else {
+ Avatar.shirt = null
+ if (TabSelected === type) {
+ console.log('tab is', TabSelected, type)
+ ItemGrid.prepend(Wearing.querySelector(`.col-auto:has(a[href="/store/${id}"])`))
+ }
+ }
+ break
+ case 'pants':
+ if (Avatar.pants.ID !== id) {
+ Avatar.pants = {Name: name, Creator: creator, ID: id, URL: null, Thumbnail: thumbnail}
+ Wearing.prepend(ItemGrid.querySelector(`.col-auto:has(a[href="/store/${id}"])`))
+ } else {
+ Avatar.pants = null
+ if (TabSelected === type) {
+ console.log('tab is', TabSelected, type)
+ ItemGrid.prepend(Wearing.querySelector(`.col-auto:has(a[href="/store/${id}"])`))
+ }
+ }
+ break
+ }
+
+ UpdateAvatar()
+}
+
+function CheckItemID(object, id) {
+ for (let i = 0; i < object.length; i++) {
+ if (object[i] === id || object[i].ID === id) {
+ console.log('Index: ' + i)
+ return i
+ }
+ }
+ return -1
+}
\ No newline at end of file
diff --git a/js/account/avatar-sandbox2.js b/js/account/avatar-sandbox2.js
new file mode 100755
index 0000000..ebad5e6
--- /dev/null
+++ b/js/account/avatar-sandbox2.js
@@ -0,0 +1,456 @@
+setTimeout(function () {}, 100)
+const UserID = JSON.parse(window.localStorage.getItem('account_info')).ID
+
+let PageContainer = document.querySelector('.container.p-0.p-lg-5')
+let ItemGrid;
+let Wearing;
+let Tabs;
+let IFrame;
+let TabSelected = 'hat'
+let Search;
+let Page = 1
+let Avatar = {
+ "useCharacter": true,
+ "items": [
+ 24122
+ ],
+ "shirt": 24118,
+ "pants": 24123,
+ "headColor": "#e0e0e0",
+ "torsoColor": "#e0e0e0",
+ "leftArmColor": "#e0e0e0",
+ "rightArmColor": "#e0e0e0",
+ "leftLegColor": "#e0e0e0",
+ "rightLegColor": "#e0e0e0"
+}
+let ItemCardContents = `
+
+`
+
+if (new URLSearchParams(new URL(window.location).search).get('sandbox') === 'true') {
+ console.log('Avatar Sandbox!')
+
+ LoadFile(chrome.runtime.getURL('js/account/avatar-sandbox.html'), function(html){
+ PageContainer.innerHTML = html
+ ItemGrid = document.getElementById('inventory')
+ Wearing = document.getElementById('wearing')
+ Tabs = document.getElementById('tabs')
+ IFrame = document.getElementById('viewFrame')
+
+ Search = document.getElementById('item-search')
+ Search.addEventListener('onchange', function(){
+ RefreshItems()
+ });
+
+ UpdateAvatar()
+ RefreshItems()
+ LoadWearing()
+
+ Array.from(Tabs.children).forEach(element => {
+ element.addEventListener('click', function(){
+ let Link = element.getElementsByTagName('a')[0]
+ if (!(Link.classList.contains('active'))) {
+ Link.classList.add('active')
+ Tabs.querySelector(`[data-tab="${TabSelected}"]`).classList.remove('active')
+ TabSelected = Link.getAttribute('data-tab')
+ Page = 1
+ RefreshItems()
+ }
+ });
+ });
+
+ let Clear = document.getElementById('clear')
+ Clear.addEventListener('click', function(){
+ Avatar = {
+ "useCharacter": true,
+ "items": [
+ 24122
+ ],
+ "shirt": 24118,
+ "pants": 24123,
+ "headColor": "#e0e0e0",
+ "torsoColor": "#e0e0e0",
+ "leftArmColor": "#e0e0e0",
+ "rightArmColor": "#e0e0e0",
+ "leftLegColor": "#e0e0e0",
+ "rightLegColor": "#e0e0e0"
+ }
+ UpdateAvatar()
+ });
+
+ let Myself = document.getElementById('myself')
+ Myself.addEventListener('click', function(){
+ LoadMyself()
+ });
+
+ let JSONUpload = document.getElementById('jsonUpload')
+ JSONUpload.addEventListener('change', function(){
+ let Reader = new FileReader()
+ Reader.addEventListener('loadend', function(){
+ Avatar = JSON.parse(Reader.result)
+ UpdateAvatar()
+
+ JSONUpload.value = ""
+ });
+
+ Reader.readAsText(JSONUpload.files[0])
+ });
+
+ let JSONSave = document.getElementById('jsonSave')
+ JSONSave.addEventListener('click', function(){
+ let Download = document.createElement('a')
+ Download.href = URL.createObjectURL(new Blob([JSON.stringify(Avatar)], {
+ type: "application/json"
+ }));
+ Download.setAttribute('download', 'AvatarSandbox.json')
+ document.body.appendChild(Download)
+ Download.click()
+ document.body.removeChild(Download)
+ });
+
+ let OpenInNewTab = document.getElementById('openNewTab')
+ OpenInNewTab.addEventListener('click', function(){
+ UpdateAvatar()
+ });
+ });
+}
+
+function UpdateAvatar() {
+ GenerateHash()
+ .then(hash => {
+ IFrame.addEventListener('load', function () {
+ IFrame.src = 'https://polytoria.com/ptstatic/itemview/#' + hash;
+ });
+ IFrame.src = 'about:blank';
+ });
+}
+
+function LoadFile(path, callback) {
+ var xhr = new XMLHttpRequest();
+ xhr.onload = function () { return callback(this.responseText); }
+ xhr.open("GET", path, true);
+ xhr.send();
+}
+
+async function GenerateHash(data) {
+ if (!data) {
+ console.log('Data not provided')
+ let FormattedAvatar = await FormatAvatar()
+ return btoa(encodeURIComponent(JSON.stringify(FormattedAvatar)))
+ } else {
+ console.log('Data provided')
+ return btoa(encodeURIComponent(JSON.stringify(data)))
+ }
+}
+
+function RefreshItems() {
+ fetch(`https://api.polytoria.com/v1/store?search=${Search.value}&types%5B%5D=${TabSelected}&sort=createdAt&order=desc&page=${Page}&limit=12`)
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network response was not ok');
+ }
+ return response.json();
+ })
+ .then(data => {
+ Array.from(ItemGrid.children).forEach(element => {element.remove()});
+ data = data.assets
+ data.forEach(item => {
+ let NewItemCard = document.createElement('div')
+ NewItemCard.classList = 'col-auto'
+ NewItemCard.innerHTML = ItemCardContents
+ .replace(':ItemName', item.name)
+ .replace(':ItemID', item.id)
+ .replace(':ItemType', item.type)
+ .replace(item.type.charAt(0), item.type.charAt(0).toUpperCase())
+ .replace(':CreatorName', item.creator.name)
+ .replace(':CreatorID', item.creator.id)
+ .replace(':ItemThumbnail', item.thumbnail)
+ NewItemCard.getElementsByClassName('p-2')[0].addEventListener('click', function(){
+ WearAsset(NewItemCard, item)
+ });
+
+ ItemGrid.appendChild(NewItemCard)
+ });
+ })
+ .catch(error => {
+ console.error('Fetch error:', error);
+ });
+}
+
+async function FormatAvatar() {
+ const FormattedAvatar = structuredClone(Avatar)
+
+ // Hats, Tools: https://api.polytoria.com/v1/assets/serve-mesh/:id
+ // or: https://api.polytoria.com/v1/assets/serve/:id/Asset
+
+ Avatar.items.forEach(async (item, index) => {
+ if (typeof(item) === 'number') {
+ console.log(item)
+ await FetchMesh(item)
+ .then(URL => {
+ console.log('URL: ' + URL)
+ FormattedAvatar.items[index] = URL
+ })
+ .catch(error => {
+ throw new Error(error)
+ });
+ console.log('after url')
+ //Avatar.items[index] = URL
+ }
+ });
+
+ if (typeof(FormattedAvatar.tool) === 'number') {console.log(FormattedAvatar.tool); FormattedAvatar.tool = await FetchMesh(FormattedAvatar.tool)}
+
+ if (FormattedAvatar.face && typeof(FormattedAvatar.face) === 'number') {
+ FormattedAvatar.face = await FetchAsset(FormattedAvatar.face)
+ } else {
+ FormattedAvatar.face = "https://c0.ptacdn.com/static/3dview/DefaultFace.png"
+ }
+
+ if (typeof(FormattedAvatar.shirt) === 'number') {FormattedAvatar.shirt = await FetchAsset(FormattedAvatar.shirt)}
+ if (typeof(FormattedAvatar.pants) === 'number') {FormattedAvatar.pants = await FetchAsset(FormattedAvatar.pants)}
+
+ console.log('Real Avatar: ', Avatar, 'Formatted: ', FormattedAvatar)
+ return FormattedAvatar
+}
+
+function LoadMyself() {
+ fetch('https://api.polytoria.com/v1/users/:id/avatar'.replace(':id', UserID))
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network not ok')
+ }
+ return response.json()
+ })
+ .then(data => {
+ Avatar.items = []
+
+ data.assets.forEach(item => {
+ switch(item.type) {
+ case 'hat':
+ Avatar.items.push(item.id)
+ break
+ default:
+ Avatar[item.type] = item.id
+ break
+ }
+ });
+
+ Avatar.headColor = '#' + data.colors.head || '#cdcdcd'
+ Avatar.torsoColor = '#' + data.colors.torso || '#cdcdcd'
+ Avatar.leftArmColor = '#' + data.colors.leftArm || '#cdcdcd'
+ Avatar.rightArmColor = '#' + data.colors.rightArm || '#cdcdcd'
+ Avatar.leftLegColor = '#' + data.colors.leftLeg || '#cdcdcd'
+ Avatar.rightLegColor = '#' + data.colors.rightLeg || '#cdcdcd'
+
+ UpdateAvatar()
+ })
+ .catch(error => {
+ console.log(error)
+ });
+}
+
+function WearAsset(element, info) {
+ if (Avatar.items.indexOf(info.id) === -1 && Avatar[info.type] !== info.id) {
+ console.log('Equip')
+ switch(info.type) {
+ case 'hat':
+ Avatar.items.push(info.id)
+ break
+ default:
+ Avatar[info.type] = info.id
+ break
+ }
+ } else {
+ console.log('unequip')
+ switch(info.type) {
+ case 'hat':
+ Avatar.items.splice(Avatar.items.indexOf(info.id), 1)
+ break
+ case 'face':
+ Avatar.face = "https://c0.ptacdn.com/static/3dview/DefaultFace.png"
+ break
+ default:
+ Avatar[info.type] = undefined
+ break
+ }
+ }
+
+ LoadWearing()
+ UpdateAvatar()
+}
+
+async function FetchMesh(id) {
+ if (id === null) {return null}
+ console.log('https://api.polytoria.com/v1/assets/serve-mesh/:id'.replace(':id', id))
+ return fetch('https://api.polytoria.com/v1/assets/serve-mesh/:id'.replace(':id', id))
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network not ok')
+ }
+ return response.json()
+ })
+ .then(data => {
+ console.log(data, 'finished', data.url)
+ return data.url
+ })
+ .catch(error => {
+ console.log('Fetch error: ' + error)
+ });
+}
+
+async function FetchAsset(id) {
+ if (id === null) {return null}
+ return fetch('https://api.polytoria.com/v1/assets/serve/:id/Asset'.replace(':id', id))
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network not ok')
+ }
+ return response.json()
+ })
+ .then(data => {
+ return data.url
+ })
+ .catch(error => {
+ console.log('Fetch error: ' + error)
+ });
+}
+
+function LoadWearing() {
+ const WearingItems = [
+ ...Avatar.items,
+ Avatar.shirt,
+ Avatar.pants,
+ Avatar.face
+ ].filter(item => item !== null && item !== undefined);
+
+ Array.from(Wearing.children).forEach(element => {
+ const ItemID = element.getElementsByTagName('a')[0].href.split('/')[2]
+ if (!WearingItems.includes(ItemID)) {
+ element.remove();
+ }
+ });
+
+ WearingItems.forEach(item => {
+
+ const ExistingElement = Wearing.querySelector(`[data-itemid="${item}"]`);
+ if (!ExistingElement) {
+ fetch(`https://api.polytoria.com/v1/store/${item}`)
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network not ok');
+ }
+ return response.json();
+ })
+ .then(item => {
+ if (Wearing.innerHTML === 'No items to show.') {
+ Wearing.innerHTML = ''
+ }
+ let NewItemCard = document.createElement('div');
+ NewItemCard.classList = 'col-auto';
+ NewItemCard.innerHTML = ItemCardContents
+ .replace(':ItemName', item.name)
+ .replace(':ItemID', item.id)
+ .replace(':ItemType', item.type.charAt(0).toUpperCase() + item.type.substring(1))
+ .replace(':CreatorName', item.creator.name)
+ .replace(':CreatorID', item.creator.id)
+ .replace(':ItemThumbnail', item.thumbnail);
+ Wearing.appendChild(NewItemCard);
+ NewItemCard.getElementsByClassName('p-2')[0].addEventListener('click', function () {
+ WearAsset(NewItemCard, item);
+ });
+ })
+ .catch(error => {
+ console.log('Fetch error: ' + error);
+ });
+ }
+ });
+
+ if (Array.from(Wearing.children).length === 0) {
+ Wearing.innerHTML = 'No items to show.'
+ }
+}
+
+
+/*
+function LoadWearing() {
+ const WearingItems = [
+ ...Avatar.items,
+ Avatar.shirt,
+ Avatar.pants,
+ Avatar.face
+ ].filter(item => item !== null)
+
+ Array.from(Wearing.children).forEach(element => {
+ console.log('AAAAAAAAAAAA', element)
+ })
+}
+*/
+
+/*
+function LoadWearing() {
+ const AllItems = structuredClone(Avatar.items)
+ AllItems.push(Avatar.shirt)
+ AllItems.push(Avatar.pants)
+ AllItems.push(Avatar.face)
+ AllItems.forEach(item => {
+ if (item !== null) {
+ let Element = document.querySelector(`a[href="/store/${item}"]`)
+ if (Element !== null) {
+ console.log('exists - load wearing')
+ Element = Element.parentElement.parentElement
+ Wearing.appendChild(Element)
+ } else if (Element === null) {
+ console.log('doesn\' exist - load wearing')
+ fetch('https://api.polytoria.com/v1/store/:id'.replace(':id', item))
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network not ok')
+ }
+ return response.json()
+ })
+ .then(item => {
+ let NewItemCard = document.createElement('div')
+ NewItemCard.classList = 'col-auto'
+ NewItemCard.innerHTML = ItemCardContents
+ .replace(':ItemName', item.name)
+ .replace(':ItemID', item.id)
+ .replace(':ItemType', item.type.charAt(0).toUpperCase() + item.type.substring(1))
+ .replace(':CreatorName', item.creator.name)
+ .replace(':CreatorID', item.creator.id)
+ .replace(':ItemThumbnail', item.thumbnail)
+ Wearing.appendChild(NewItemCard)
+ NewItemCard.getElementsByClassName('p-2')[0].addEventListener('click', function(){
+ WearAsset(NewItemCard, item)
+ });
+ })
+ .catch(error => {
+ console.log('Fetch error: ' + error)
+ });
+ } else if (item.type === TabSelected) {
+ console.log('item type is selected tab - load wearing')
+ ItemGrid.appendChild(Element)
+ } else {
+ console.log('remove item - load wearing')
+ Element.remove()
+ }
+ }
+ });
+}
+*/
\ No newline at end of file
diff --git a/js/account/create.js b/js/account/create.js
new file mode 100755
index 0000000..bcd28ab
--- /dev/null
+++ b/js/account/create.js
@@ -0,0 +1,7 @@
+let NavColumn = document.getElementsByClassName('col-lg-2')[0]
+let LaunchCreatorBtn = document.createElement('button')
+LaunchCreatorBtn.classList = 'btn btn-success w-100'
+LaunchCreatorBtn.innerText = 'Launch Creator'
+LaunchCreatorBtn.setAttribute('data-id', '1')
+LaunchCreatorBtn.setAttribute('onclick', 'editPlace(this)')
+NavColumn.appendChild(LaunchCreatorBtn)
\ No newline at end of file
diff --git a/js/account/friends.js b/js/account/friends.js
new file mode 100755
index 0000000..fec1777
--- /dev/null
+++ b/js/account/friends.js
@@ -0,0 +1,212 @@
+var SelectedFriends = []
+
+setTimeout(function () {
+ chrome.storage.sync.get(['PolyPlus_Settings'], function(result){
+ Settings = result.PolyPlus_Settings;
+ if (Settings.ImprovedFrListsOn === true) {
+ var Tab = "requests"
+
+ var FriendsContainer = document.getElementById('friends-container')
+ var Container = document.createElement('div')
+ Container.classList = 'row mb-3'
+ Container.innerHTML = `
+ Accept all Friend Request(s)
+ Decline all Friend Request(s)
+ `
+ FriendsContainer.parentElement.insertBefore(Container, FriendsContainer)
+ var AccAllFrBtn = document.getElementById('AccAllFrBtn')
+ var DelAllFrBtn = document.getElementById('DelAllFrBtn')
+ var AccBtns = document.querySelectorAll('[onclick="acceptFriendRequest(this)"]')
+ var DelBtns = document.querySelectorAll('[onclick="declineFriendRequest(this)"]')
+ if (!(AccBtns.length === 0)) {
+ AccAllFrBtn.addEventListener('click', function(){
+ AccBtns.forEach(element => {
+ setTimeout(function () {}, 145)
+ fetch('https://polytoria.com/api/friends/send', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-CSRF-Token': document.querySelector('input[name="_csrf"]').value
+ },
+ body: JSON.stringify({ userID: parseInt(element.getAttribute('data-user-id')) }),
+ })
+ .catch(error => {
+ // Handle any errors
+ console.error('Error:', error);
+ Success = false
+ });
+
+ /*
+ let NewAcceptBtn = document.createElement('a')
+ NewAcceptBtn.style.display = 'none'
+ sNewAcceptBtn.classList = 'btn btn-success'
+ NewAcceptBtn.setAttribute('data-user-id', element.getAttribute('data-user-id'))
+ NewAcceptBtn.setAttribute('onclick', 'acceptFriendRequest(this)')
+ FriendsContainer.appendChild(NewAcceptBtn)
+ NewAcceptBtn.click();
+ */
+ })
+ });
+ } else {
+ AccAllFrBtn.setAttribute('disabled', 'true')
+ }
+ if (!(DelBtns.length === 0)) {
+ DelAllFrBtn.addEventListener('click', function(){
+ DelBtns.forEach(element => {
+ setTimeout(function () {}, 110)
+ fetch('https://polytoria.com/api/friends/remove', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-CSRF-Token': document.querySelector('input[name="_csrf"]').value
+ },
+ body: JSON.stringify({ userID: parseInt(element.getAttribute('data-user-id')) }),
+ })
+ .catch(error => {
+ // Handle any errors
+ console.error('Error:', error, document.querySelector('input[name="_csrf"]').value);
+ Success = false
+ });
+
+ /*
+ let NewDeclineBtn = document.createElement('a')
+ NewDeclineBtn.style.display = 'none'
+ NewDeclineBtn.classList = 'btn btn-danger'
+ NewDeclineBtn.setAttribute('data-user-id', element.getAttribute('data-user-id'))
+ NewDeclineBtn.setAttribute('onclick', 'declineFriendRequest(this)')
+ FriendsContainer.appendChild(NewDeclineBtn)
+ NewDeclineBtn.click();
+ */
+ })
+ });
+ } else {
+ DelAllFrBtn.setAttribute('disabled', 'true')
+ }
+ let Text = document.createElement('p')
+ Text.classList = 'mx-auto'
+ Text.style.textAlign = 'center'
+ Text.style.fontSize = '1.3rem'
+ Text.style.display = 'none'
+ Text.innerHTML = `
+ 0 friends selected!
+
+ View Selection
+ Clear Selection
+ Remove Selected Friends
+ `
+ FriendsContainer.parentElement.insertBefore(Text, FriendsContainer)
+ let Text_Span = Text.querySelector('span');
+ let Text_View = document.getElementById('viewSelectionBtn');
+ let Text_Clear = document.getElementById('clearSelectionBtn');
+ let Text_Remove = document.getElementById('removeSelectionBtn');
+ document.querySelector('[data-friends-tab="requests"]').addEventListener('click', function(){
+ Tab = "requests"
+ Container.style.display = '';
+ Text.style.display = 'none';
+ document.querySelectorAll('input[type="check"]').forEach(element => {element.remove();});
+ });
+ document.querySelector('[data-friends-tab="friends"]').addEventListener('click', function(){
+ Tab = "friends"
+ Container.style.display = 'none';
+ Text.style.display = '';
+ });
+ var ConfirmRemove = 0
+ Text_View.addEventListener('click', function(){});
+ Text_Clear.addEventListener('click', function(){
+ SelectedFriends = []
+ UpdateCheckboxes();
+ Text_Span.innerText = SelectedFriends.length
+ });
+ Text_Remove.addEventListener('click', function(){
+ ConfirmRemove = ConfirmRemove + 1
+ switch(ConfirmRemove) {
+ case 0:
+ Text_Remove.innerText = 'Remove Selected Friends'
+ break
+ case 1:
+ Text_Remove.innerText = 'Are you sure?'
+ break
+ case 2:
+ for (let i = 0; i < SelectedFriends.length; i++) {
+ setTimeout(function () {}, 110)
+ let NewDeclineBtn = document.createElement('a')
+ NewDeclineBtn.style.display = 'none'
+ NewDeclineBtn.classList = 'btn btn-danger'
+ NewDeclineBtn.setAttribute('data-user-id', SelectedFriends[i])
+ NewDeclineBtn.setAttribute('onclick', 'declineFriendRequest(this)')
+ FriendsContainer.appendChild(NewDeclineBtn)
+ NewDeclineBtn.click();
+ }
+ SelectedFriends = []
+ UpdateCheckboxes();
+ Text_Remove.innerText = 'Remove Selected Friends'
+ ConfirmRemove = 0
+ break
+ }
+ });
+
+ const observer = new MutationObserver(function (){
+ if (FriendsContainer.children.length > 0 && Tab === "friends") {
+ LoadCheckBoxes();
+ }
+ });
+ observer.observe(FriendsContainer, {childList: true, subtree: false});
+
+ function LoadCheckBoxes() {
+ Array.from(FriendsContainer.children).forEach(element => {
+ let DeclineBtn = element.querySelector('a.btn.btn-danger')
+ let UserID = DeclineBtn.getAttribute('data-user-id')
+ let Column = document.createElement('div')
+ let EditColumn = element.querySelector('.col-9')
+ Column.classList = 'col-auto'
+ var NewCheckBox = document.createElement('button')
+ NewCheckBox.classList = 'polyplus-multiremovefr-checkbox'
+ NewCheckBox.setAttribute('style', 'padding: 20px; background-color: #191919; border: 1px solid #393939; border-radius: 1rem;')
+ var Index = SelectedFriends.indexOf(UserID)
+ if (Index !== -1) {
+ DeclineBtn.classList.add('disabled')
+ NewCheckBox.style.borderColor = 'lime'
+ }
+ EditColumn.classList.remove('col-9')
+ EditColumn.classList.add('col')
+ Column.appendChild(NewCheckBox)
+ EditColumn.parentElement.appendChild(Column)
+ NewCheckBox.addEventListener('click', function(){
+ var Index = SelectedFriends.indexOf(UserID)
+ if (Index === -1) {
+ DeclineBtn.classList.add('disabled')
+ SelectedFriends.push(UserID)
+ NewCheckBox.style.borderColor = 'lime'
+ } else {
+ SelectedFriends.splice(Index, 1)
+ NewCheckBox.style.borderColor = '#393939'
+ DeclineBtn.classList.remove('disabled')
+ }
+ Text_Span.innerText = SelectedFriends.length
+ UpdateCheckboxes();
+ });
+ });
+ }
+
+ function UpdateCheckboxes(){
+ document.querySelectorAll('.polyplus-multiremovefr-checkbox').forEach(element => {
+ let Parent = element.parentElement.parentElement.parentElement.parentElement.parentElement
+ let DeclineBtn = Parent.querySelector('a.btn.btn-danger')
+ if (element.getAttribute('disabled')) {
+ element.removeAttribute('disabled')
+ }
+ if (SelectedFriends.IndexOf(DeclineBtn.getAttribute('data-user-id')) === -1) {
+ element.style.borderColor = '#393939'
+ DeclineBtn.classList.remove('disabled')
+ if (SelectedFriends.length >= 25) {
+ element.setAttribute('disabled', true)
+ }
+ } else {
+ DeclineBtn.classList.add('disabled')
+ element.style.borderColor = 'lime'
+ }
+ })
+ }
+ }
+ });
+}, 100);
\ No newline at end of file
diff --git a/js/account/home.js b/js/account/home.js
new file mode 100755
index 0000000..ea9f6c1
--- /dev/null
+++ b/js/account/home.js
@@ -0,0 +1,143 @@
+var Settings;
+var PinnedGames;
+var BestFriends;
+
+let ContainerElement = `
+
`;
+let GameContainerElement = `
+
+
+
+
+
+
+`;
+let TitleElement = `
+
+
Jump right back into your favorite games
+ Pinned Games
+`;
+var FriendContainer = document.querySelector('.card:has(.friendsPopup) .card-body')
+
+let NewContainer = document.createElement('div');
+NewContainer.style.display = 'none'
+NewContainer.classList = 'card card-dash mcard';
+NewContainer.style.animationDelay = '0.18s';
+NewContainer.innerHTML = ContainerElement;
+
+let NewTitle = document.createElement('div');
+NewTitle.style.display = 'none'
+NewTitle.classList = 'row reqFadeAnim px-2 px-lg-0';
+NewTitle.innerHTML = TitleElement;
+
+let BestFriendsContainer = document.createElement('div')
+BestFriendsContainer.classList = 'd-flex'
+BestFriendsContainer.style = 'display: none; border-bottom: 1px solid #000; padding-bottom: 10px; margin-bottom: 10px; width: 100%;'
+/*
+BestFriendsContainer.style.display = 'none'
+BestFriendsContainer.style.borderBottom = '1px solid #000'
+BestFriendsContainer.style.paddingBottom = '10px'
+BestFriendsContainer.style.marginBottom = '10px'
+BestFriendsContainer.style.width = '100%'
+*/
+
+let Spacer = document.createElement('div')
+Spacer.innerHTML = ' '
+Spacer.style.width = '50px'
+Spacer.prepend(BestFriendsContainer)
+FriendContainer.prepend(BestFriendsContainer)
+
+UpdateLocalData();
+
+function UpdateLocalData() {
+ chrome.storage.sync.get(['PolyPlus_Settings'], function(result) {
+ Settings = result.PolyPlus_Settings
+ });
+
+ chrome.storage.sync.get(['PolyPlus_PinnedGames'], function(result) {
+ PinnedGames = result.PolyPlus_PinnedGames || [];
+ chrome.storage.sync.get(['PolyPlus_BestFriends'], function(result) {
+ BestFriends = result.PolyPlus_BestFriends || [];
+ if (Settings.PinnedGamesOn === true) {
+ LoadPinnedGames();
+ } else {
+ NewContainer.style.display = 'none'
+ NewTitle.style.display = 'none'
+ }
+ if (Settings.BestFriendsOn === true) {
+ LoadBestFriends();
+ } else {
+ BestFriendsContainer.style.display = 'none'
+ Spacer.style.display = 'none'
+ }
+ });
+ });
+}
+
+function LoadPinnedGames() {
+ var Existing = NewContainer.children[0].children
+ Array.from(Existing).forEach(element => {
+ element.remove();
+ });
+
+ if (PinnedGames.length === 0) {
+ NewContainer.style.display = 'none'
+ NewTitle.style.display = 'none'
+ } else {
+ NewContainer.style.display = ''
+ NewTitle.style.display = ''
+ }
+
+ PinnedGames.forEach(element => {
+ fetch('https://api.polytoria.com/v1/places/:id'.replace(':id', element))
+ .then(response => response.json())
+ .then(data => {
+ let GameName = data.name;
+ let GameThumbnail = data.thumbnail;
+
+ var NewGameContainer = document.createElement('a');
+ NewGameContainer.innerHTML = GameContainerElement.replace(':GameName',GameName).replace(':Thumbnail',GameThumbnail);
+ NewGameContainer.setAttribute('href', '/places/:id'.replace(':id',element));
+
+ if (new Date().getDate() >= new Date(data.updatedAt).getDate()) {
+ console.log('Game has updated')
+ }
+
+ NewContainer.children[0].appendChild(NewGameContainer);
+ })
+ .catch(error => {
+ console.error('Error:', error);
+ });
+ });
+}
+
+function LoadBestFriends() {
+ Array.from(document.querySelectorAll('[bestFriend]')).forEach(element => {
+ element.removeAttribute('bestFriend')
+ element.getElementsByClassName('friend-name')[0].style.color = 'initial';
+ FriendContainer.appendChild(element)
+ });
+
+ if (BestFriends.length === 0) {
+ BestFriendsContainer.style.display = 'none'
+ } else {
+ BestFriendsContainer.style.display = ''
+ }
+
+ BestFriends.forEach(element => {
+ let ExistingFriend = document.getElementById('friend-' + element)
+ if (ExistingFriend) {
+ ExistingFriend.setAttribute('bestFriend', 'true')
+ ExistingFriend.getElementsByClassName('friend-name')[0].style.color = 'yellow';
+ BestFriendsContainer.prepend(ExistingFriend)
+ }
+ });
+}
+
+var SecondaryColumn = document.getElementsByClassName('col-lg-8')[0]
+SecondaryColumn.insertBefore(NewContainer, SecondaryColumn.children[0]);
+SecondaryColumn.insertBefore(NewTitle, SecondaryColumn.children[0]);
\ No newline at end of file
diff --git a/js/account/inventory.js b/js/account/inventory.js
new file mode 100755
index 0000000..a57615b
--- /dev/null
+++ b/js/account/inventory.js
@@ -0,0 +1,186 @@
+if (window.location.pathname.split('/')[3] === "inventory") {
+ let UserID = window.location.pathname.split('/')[2]
+ if (UserID === JSON.parse(window.localStorage.getItem('account_info')).ID) {
+ let Nav = document.getElementsByClassName('nav-pills')[0]
+ let WishlistNav = document.createElement('li')
+ WishlistNav.classList.add('nav-item')
+ WishlistNav.innerHTML = `
+
+
+ Item Wishlist
+
+ `
+ Nav.appendChild(WishlistNav)
+
+ if (window.location.pathname.split('/')[4] === "wishlist") {
+ let ItemGrid = document.getElementsByClassName('itemgrid')[0]
+ let ItemCardContents = `
+
+
+ :LimitedTag
+
+
+
+
+
+ :ItemName
+
+
+
+ by :CreatorName
+
+ X
+ `
+
+ Array.from(ItemGrid.children).forEach(element => {
+ element.remove();
+ });
+ Array.from(Nav.children).forEach(element => {
+ element = element.children[0]
+ if (!(element === WishlistNav)) {
+ if (element.classList.contains('active')) {
+ element.classList.remove('active')
+ }
+ }
+ });
+ WishlistNav.children[0].classList.add('active')
+ let Search = document.createElement('div')
+ Search.classList = 'row'
+ Search.innerHTML = `
+
+
+ Any
+ Hat
+ Faces
+ Tools
+ Shirt
+ Pants
+
+
+
+
+
+
+
+
+
+ Is Limited?
+ Items that are limited
+
+
+
+
+
+
+
+ Is Available?
+ Items that are equal to or less than the budget (excluding limiteds)
+
+
+
+ `
+ ItemGrid.parentElement.prepend(document.createElement('br'), ItemGrid.parentElement.children[0])
+ ItemGrid.parentElement.prepend(Search, ItemGrid.parentElement.children[0])
+
+ let Type = document.getElementById('polyplus-itemwish-type')
+ let SearchBar = document.getElementById('polyplus-itemwish-searchbar')
+ let IsLimited = document.getElementById('polyplus-itemwish-isLimited')
+ let IsAvailable = document.getElementById('polyplus-itemwish-isAvailable')
+
+ Type.addEventListener('change', function(){
+ Update(Type.options[Type.selectedIndex].value, SearchBar.value, IsLimited.checked, IsAvailable.checked)
+ });
+
+ SearchBar.addEventListener('change', function(){
+ Update(Type.options[Type.selectedIndex].value, SearchBar.value, IsLimited.checked, IsAvailable.checked)
+ });
+
+ IsLimited.addEventListener('change', function(){
+ Update(Type.options[Type.selectedIndex].value, SearchBar.value, IsLimited.checked, IsAvailable.checked)
+ });
+
+ IsAvailable.addEventListener('change', function(){
+ Update(Type.options[Type.selectedIndex].value, SearchBar.value, IsLimited.checked, IsAvailable.checked)
+ });
+
+ chrome.storage.sync.get(['PolyPlus_ItemWishlist'], function(result){
+ let Wishlist = result.PolyPlus_ItemWishlist || [];
+ console.log('wishlist: ', Wishlist)
+ Wishlist.forEach(element => {
+ let NewItemCard = document.createElement('div')
+ NewItemCard.classList = 'px-0'
+ fetch('https://api.polytoria.com/v1/store/:id'.replace(':id', element))
+ .then(response => response.json())
+ .then(data => {
+ NewItemCard.innerHTML = ItemCardContents.replace(':ItemID', data.id).replace(':ItemThumbnail', data.thumbnail).replace(':ItemName', data.name).replace(':CreatorID', data.creator.id).replace(':CreatorName', data.creator.name)
+ if (data.isLimited === true) {
+ NewItemCard.innerHTML = NewItemCard.innerHTML.replace(':LimitedTag', 'Limited
')
+ } else {
+ NewItemCard.innerHTML = NewItemCard.innerHTML.replace(':LimitedTag', '')
+ }
+ NewItemCard.setAttribute('data-id', data.id)
+ NewItemCard.setAttribute('data-name', data.name)
+ NewItemCard.setAttribute('data-type', data.type)
+ NewItemCard.setAttribute('data-creator', data.creator.name)
+ NewItemCard.setAttribute('data-limited', data.isLimited)
+ if (data.isLimited === false) {
+ NewItemCard.setAttribute('data-price', data.price)
+ }
+
+ ItemGrid.appendChild(NewItemCard)
+
+ NewItemCard.getElementsByClassName('polyplus-itemwish-removebtn')[0].addEventListener('click', function(){
+ let Index = Wishlist.indexOf(parseInt(NewItemCard.getAttribute('data-id')))
+ if (Index === -1) {
+ NewItemCard.remove();
+ return
+ } else {
+ Wishlist.splice(Index, 1)
+ console.log(Wishlist)
+ NewItemCard.remove();
+ }
+ chrome.storage.sync.set({'PolyPlus_ItemWishlist': Wishlist, arrayOrder: true}, function() {
+ console.log('ItemWishlist successfully saved: ' + ItemWishlist)
+ });
+ });
+ })
+ .catch(error => {
+ console.error('Error:', error);
+ });
+ });
+ });
+ }
+ }
+}
+
+function Update(type, query, isLimited, isAvailable) {
+ let ItemGrid = document.getElementsByClassName('itemgrid')[0]
+ let BrickBalance = parseInt(JSON.parse(window.localStorage.getItem('account_info')).Bricks)
+ query = query.toLowerCase();
+ let Results = Array.from(ItemGrid.children)
+ for (let i = 0; i < Results.length; i++) {
+ let Show = true
+
+ console.log('type: ', type)
+ if (!(type === 'any')) {
+ console.log('isn\'t any')
+ if (!(Results[i].getAttribute('data-type') === type)) {Show = false}
+ }
+
+ if (!(Results[i].getAttribute('data-name').toLowerCase().startsWith(query))) {Show = false}
+
+ if (isLimited === true) {
+ if (!(Results[i].getAttribute('data-limited') === 'true')) {Show = false}
+ }
+
+ if (isAvailable === true) {
+ if (!(parseInt(Results[i].getAttribute('data-price')) <= BrickBalance)) {Show = false}
+ }
+
+ if (Show === true) {
+ Results[i].style.display = 'block'
+ } else {
+ Results[i].style.display = 'none'
+ }
+ }
+}
\ No newline at end of file
diff --git a/js/account/settings-privacy.js b/js/account/settings-privacy.js
new file mode 100755
index 0000000..5d5a54b
--- /dev/null
+++ b/js/account/settings-privacy.js
@@ -0,0 +1,32 @@
+setTimeout(function () {}, 100)
+
+chrome.storage.sync.get(['PolyPlus_Settings'], function(result){
+ if (result.PolyPlus_Settings.MoreSearchFiltersOn === true) {
+ let BlockedUsersCard = document.getElementsByClassName('card-body')[1]
+ let InputGroup = document.createElement('div')
+ InputGroup.classList = 'input-group mb-2'
+ InputGroup.innerHTML = `
+
+
+ `
+ BlockedUsersCard.insertBefore(InputGroup, BlockedUsersCard.children[0])
+ let SearchBar = document.getElementById('blocked-users-search')
+ let ConfirmBtn = document.getElementById('blocked-users-confirm')
+
+ ConfirmBtn.addEventListener('click', function(){
+ SearchBlockedUsers(SearchBar.value);
+ });
+
+ function SearchBlockedUsers(query) {
+ query = query.toLowerCase();
+ for (let i = 1; i < BlockedUsersCard.children.length; i++) {
+ let Username = BlockedUsersCard.children[i].getElementsByTagName('h5')[0].innerText.toLowerCase();
+ if (Username.includes(query)) {
+ BlockedUsersCard.children[i].style.display = 'block'
+ } else {
+ BlockedUsersCard.children[i].style.display = 'none'
+ }
+ }
+ }
+ }
+});
\ No newline at end of file
diff --git a/js/account/trades-outbound.js b/js/account/trades-outbound.js
new file mode 100755
index 0000000..270301c
--- /dev/null
+++ b/js/account/trades-outbound.js
@@ -0,0 +1,110 @@
+setTimeout(function() {}, 100)
+var SelectedTrades = []
+
+let Parent = document.getElementsByClassName('card mcard p-5 text-center text-muted')[0].parentElement
+let Text = document.createElement('p')
+Text.classList = 'mx-auto'
+Text.style.textAlign = 'center'
+Text.style.fontSize = '1.3rem'
+Text.innerHTML = `
+0 trades selected!
+
+View Selection
+Clear Selection
+Cancel Selected Trades
+`
+Parent.insertBefore(Text, Parent.children[0])
+let Text_Span = Text.querySelector('span');
+let Text_View = document.getElementById('viewSelectionBtn');
+let Text_Clear = document.getElementById('clearSelectionBtn');
+let Text_Cancel = document.getElementById('cancelSelectionBtn');
+
+var ConfirmCancel = 0
+Text_View.addEventListener('click', function(){});
+Text_Clear.addEventListener('click', function(){
+ SelectedTrades = []
+ UpdateCheckboxes();
+ Text_Span.innerText = SelectedTrades.length
+});
+Text_Cancel.addEventListener('click', function(){
+ ConfirmCancel = ConfirmCancel + 1
+ switch(ConfirmCancel) {
+ case 0:
+ Text_Cancel.innerText = 'Cancel Selected Trades'
+ break
+ case 1:
+ Text_Cancel.innerText = 'Are you sure?'
+ break
+ case 2:
+ let Success = true
+ for (let i = 0; i < SelectedTrades.length; i++) {
+ setTimeout(function () {}, 110)
+ console.log(SelectedTrades[i])
+ fetch('https://polytoria.com/api/trade/decline', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-CSRF-Token': document.querySelector('input[name="_csrf"]').value
+ },
+ body: JSON.stringify({ id: SelectedTrades[i] }),
+ })
+ .catch(error => {
+ // Handle any errors
+ console.error('Error:', error);
+ Success = false
+ });
+ }
+ SelectedTrades = []
+ UpdateCheckboxes();
+ Text_Cancel.innerText = 'Cancel Selected Trades'
+ ConfirmCancel = 0
+ break
+ }
+});
+
+LoadCheckBoxes();
+
+function LoadCheckBoxes() {
+ Array.from(document.getElementsByClassName('card-inbox')).forEach(element => {
+ let ViewBtn = element.querySelector('a.btn.btn-primary')
+ let TradeID = parseInt(ViewBtn.getAttribute('href').split('/')[3])
+ var NewCheckBox = document.createElement('button')
+ NewCheckBox.classList = 'polyplus-multicanceltr-checkbox'
+ NewCheckBox.setAttribute('style', 'padding: 20px; background-color: #191919; border: 1px solid #393939; border-radius: 1rem; margin-left: 10px;')
+ var Index = SelectedTrades.indexOf(TradeID)
+ if (Index !== -1) {
+ NewCheckBox.style.borderColor = 'lime'
+ }
+ ViewBtn.parentElement.appendChild(NewCheckBox)
+ NewCheckBox.addEventListener('click', function(){
+ var Index = SelectedTrades.indexOf(TradeID)
+ if (Index === -1) {
+ SelectedTrades.push(TradeID)
+ NewCheckBox.style.borderColor = 'lime'
+ } else {
+ SelectedTrades.splice(Index, 1)
+ NewCheckBox.style.borderColor = '#393939'
+ }
+ Text_Span.innerText = SelectedTrades.length
+ UpdateCheckboxes();
+ });
+ });
+}
+
+function UpdateCheckboxes(){
+ document.querySelectorAll('.polyplus-multicanceltr-checkbox').forEach(element => {
+ let Parent = element.parentElement
+ let ViewBtn = Parent.querySelector('a.btn.btn-primary')
+ if (element.getAttribute('disabled')) {
+ element.removeAttribute('disabled')
+ }
+ if (SelectedTrades.IndexOf(ViewBtn.getAttribute('data-user-id')) === -1) {
+ element.style.borderColor = '#393939'
+ } else {
+ element.style.borderColor = 'lime'
+ if (SelectedTrades.length >= 10) {
+ element.setAttribute('disabled', true)
+ }
+ }
+ })
+}
\ No newline at end of file
diff --git a/js/account/transactions.js b/js/account/transactions.js
new file mode 100755
index 0000000..62a34de
--- /dev/null
+++ b/js/account/transactions.js
@@ -0,0 +1,101 @@
+setTimeout(function () {}, 100)
+
+let Currencies;
+
+LoadFile(chrome.runtime.getURL('js/resources/currencies.json'), function(text){
+ Currencies = JSON.parse(text)
+ console.log(new Date(Currencies.Date).toLocaleDateString("en-US", {day:"numeric",month:"long",year:"numeric"}), Currencies)
+})
+
+let Nav = document.querySelector('.nav-pills')
+let DIV = document.createElement('div')
+DIV.innerHTML = `
+
+
+
+ United States Dollar (USD)
+ Euro (EUR)
+ Canadian Dollar (CAD)
+ Great British Pound (GBP)
+ Mexican Peso (MXN)
+ Australian Dollar (AUD)
+ Turkish Lira (TRY)
+
+
+ $0.99 USD
+ $4.99 USD
+ a
+ b
+ c
+ d
+
+`
+Nav.appendChild(document.createElement('hr'))
+Nav.appendChild(DIV)
+
+let Input = document.getElementById('polyplus-brickconverter-input')
+let Output = document.getElementById('polyplus-brickconverter-output')
+let Type = document.getElementById('polyplus-brickconverter-type')
+chrome.storage.sync.get(['PolyPlus_Settings'], function(result){
+ Type.selectedIndex = result.PolyPlus_Settings.IRLPriceWithCurrencyCurrency || 0
+});
+let Package = document.getElementById('polyplus-brickconverter-package')
+
+Input.addEventListener('change', function(){
+ Update()
+});
+
+Type.addEventListener('change', function(){
+ Update()
+});
+
+Package.addEventListener('change', function(){
+ Update()
+});
+
+function Update(){
+ let DISPLAY = Type.options[Type.selectedIndex].value
+ let IRL = (parseInt(Input.value.replace(/,/g, '')) * Currencies.Data[Package.selectedIndex][DISPLAY]).toFixed(2)
+ /*
+ var IRL;
+ var DISPLAY;
+ switch (Type.selectedIndex) {
+ case 0:
+ IRL = (parseInt(Input.value.replace(/,/g, '')) * 0.0099).toFixed(2)
+ DISPLAY = 'USD'
+ break
+ case 1:
+ IRL = (parseInt(Input.value.replace(/,/g, '')) * 0.009).toFixed(2)
+ DISPLAY = 'EUR'
+ break
+ case 2:
+ IRL = (parseInt(Input.value.replace(/,/g, '')) * 0.0131).toFixed(2)
+ DISPLAY = 'CAD'
+ break
+ case 3:
+ IRL = (parseInt(Input.value.replace(/,/g, '')) * 0.0077).toFixed(2)
+ DISPLAY = 'GBP'
+ break
+ case 4:
+ IRL = (parseInt(Input.value.replace(/,/g, '')) * 0.1691).toFixed(2)
+ DISPLAY = 'MXN'
+ break
+ case 5:
+ IRL = (parseInt(Input.value.replace(/,/g, '')) * 0.0144).toFixed(2)
+ DISPLAY = 'AUD'
+ break
+ case 6:
+ IRL = (parseInt(Input.value.replace(/,/g, '')) * 0.2338).toFixed(2)
+ DISPLAY = 'TRY'
+ break
+ }
+ */
+ Output.value = "$" + IRL + " " + DISPLAY
+}
+
+function LoadFile(path, callback) {
+ var xhr = new XMLHttpRequest();
+ xhr.onload = function () { return callback(this.responseText); }
+ xhr.open("GET", path, true);
+ xhr.send();
+}
\ No newline at end of file
diff --git a/js/background.js b/js/background.js
new file mode 100755
index 0000000..3c3b1ba
--- /dev/null
+++ b/js/background.js
@@ -0,0 +1,105 @@
+chrome.contextMenus.create({
+ title: 'Copy Asset ID',
+ id: 'PolyPlus-CopyID',
+ contexts: ['link'],
+ documentUrlPatterns: ['https://polytoria.com/*'],
+ targetUrlPatterns: [
+ "https://polytoria.com/places/**",
+ "https://polytoria.com/users/**",
+ "https://polytoria.com/store/**"
+ ]
+});
+
+chrome.contextMenus.create({
+ title: 'Copy Avatar Hash',
+ id: 'PolyPlus-CopyAvatarHash',
+ contexts: ['image'],
+ documentUrlPatterns: ['https://polytoria.com/*'],
+ targetUrlPatterns: [
+ "https://c0.ptacdn.com/thumbnails/avatars/**",
+ "https://c0.ptacdn.com/thumbnails/avatars/**"
+ ]
+});
+
+chrome.contextMenus.onClicked.addListener(function (info, tab){
+ if (info.menuItemId === 'PolyPlus-CopyID') {
+ let ID = parseInt(info.linkUrl.split('/')[4])
+ 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!"));
+ }
+});
+
+/*
+chrome.webNavigation.onCompleted.addListener(function (details){
+ console.log('TAB CREATED')
+
+ chrome.scripting
+ .executeScript({
+ target: {tabId: details.tabId},
+ func: HandleJoinPlace,
+ args: [details.url]
+ })
+}, {
+ url: [{ urlMatches: "https://polytoria.com/join-place/*" }]
+});
+*/
+
+function CopyAssetID(id) {
+ navigator.clipboard
+ .writeText(id)
+ .then(() => {
+ alert('Successfully copied ID!')
+ })
+ .catch(() => {
+ alert('Failure to copy ID.')
+ });
+}
+
+function CopyAvatarHash(hash) {
+ navigator.clipboard
+ .writeText(hash)
+ .then(() => {
+ alert('Successfully copied avatar hash!')
+ })
+ .catch(() => {
+ alert('Failure to copy avatar hash.')
+ });
+}
+
+function HandleJoinPlace(url) {
+ console.log('HANDLING JOINING PLACE')
+ const PlaceID = new URL(url).pathname.split('/')[2]
+ fetch('https://polytoria.com/api/places/join',{
+ method: 'POST',
+ body: {
+ placeID:PlaceID
+ }
+ })
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network not ok')
+ }
+ return response.json()
+ })
+ .then(data => {
+ if (data.success !== true) {throw new Error(data.message)}
+ window.location.href = 'polytoria://client/' + data.token
+ })
+ .catch(error => {console.log(error)})
+}
\ No newline at end of file
diff --git a/js/everywhere.js b/js/everywhere.js
new file mode 100755
index 0000000..832197a
--- /dev/null
+++ b/js/everywhere.js
@@ -0,0 +1,274 @@
+var Settings;
+const ExpectedSettings = {
+ PinnedGamesOn: false,
+ ForumMentsOn: false,
+ BestFriendsOn: false,
+ ImprovedFrListsOn: false,
+ IRLPriceWithCurrencyOn: true,
+ IRLPriceWithCurrencyCurrency: 0,
+ IRLPriceWithCurrencyPackage: 0,
+ HideNotifBadgesOn: true,
+ SimplifiedProfileURLsOn: true,
+ StoreOwnTagOn: true,
+ ThemeCreatorOn: false,
+ ThemeCreator: {
+ BGColor: null,
+ BGImage: null,
+ BGImageSize: 'fit',
+ PrimaryTextColor: null,
+ SecondaryTextColor: null,
+ LinkTextColor: null,
+ WebsiteLogo: null
+ },
+ ModifyNavOn: false,
+ ModifyNav: [
+ {
+ Label: "Play",
+ 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,
+ ApplyMembershipThemeOn: false,
+ ApplyMembershipThemeTheme: 0,
+ ForumMarkOn: true,
+ MultiCancelOutTradesOn: true,
+ ItemWishlistOn: true,
+ HideUpgradeBtnOn: false
+}
+let Theme = null;
+
+chrome.storage.sync.get(["PolyPlus_Settings"], function(result) {
+ // Merge settings and expected settings to make sure all keys exist
+ let RawSettings = result.PolyPlus_Settings
+ Settings = MergeObjects(RawSettings || ExpectedSettings, ExpectedSettings);
+ //chrome.storage.sync.set({ 'PolyPlus_Settings': Settings, arrayOrder: true }, function() {});
+
+ // If theme exists, create a style element to represent it
+ if (Settings.ThemeCreatorOn && Settings.ThemeCreatorOn === true) {
+ Theme = document.createElement('style')
+ switch (Settings.ThemeCreator.BGImageSize) {
+ case 0:
+ Settings.ThemeCreator.BGImageSize = 'fit'
+ break
+ case 1:
+ Settings.ThemeCreator.BGImageSize = 'cover'
+ break
+ case 2:
+ Settings.ThemeCreator.BGImageSize = 'contain'
+ break
+ }
+ Theme.innerHTML = `
+ :root {
+ --polyplus-navbgcolor: ${Settings.ThemeCreator.NavBGColor};
+ --polyplus-navbordercolor: ${Settings.ThemeCreator.NavBorderColor};
+ --polyplus-navitemcolor: ${Settings.ThemeCreator.NavItemColor};
+ --polyplus-sidebarbgcolor: ${Settings.ThemeCreator.SideBGColor};
+ --polyplus-sidebarbordercolor: ${Settings.ThemeCreator.SideBorderColor};
+ --polyplus-sidebaritembgcolor: ${Settings.ThemeCreator.SideItemBGColor};
+ --polyplus-sidebaritembordercolor: ${Settings.ThemeCreator.SideItemBorderColor};
+ --polyplus-sidebaritemcolor: ${Settings.ThemeCreator.SideItemColor};
+ --polyplus-sidebaritemlabelcolor: ${Settings.ThemeCreator.SideItemLabelColor};
+ --polyplus-bgcolor: ${Settings.ThemeCreator.BGColor};
+ --polyplus-bgimage: url(${Settings.ThemeCreator.BGImage});
+ --polyplus-bgimagesize: ${Settings.ThemeCreator.BGImageSize};
+ --polyplus-primarytextcolor: ${Settings.ThemeCreator.PrimaryTextColor};
+ --polyplus-secondarytextcolor: ${Settings.ThemeCreator.SecondaryTextColor};
+ --polyplus-linktextcolor: ${Settings.ThemeCreator.LinkTextColor};
+ --polyplus-linkhoveredtextcolor: ${Settings.ThemeCreator.LinkHoveredTextColor};
+ --polyplus-linkfocusedtextcolor: ${Settings.ThemeCreator.LinkFocusedTextColor};
+ --polyplus-linkvisitedtextcolor: ${Settings.ThemeCreator.LinkVisitedTextColor};
+ --polyplus-cardheadbgcolor: ${Settings.ThemeCreator.CardHeadBGColor};
+ --polyplus-cardbodybgcolor: ${Settings.ThemeCreator.CardBodyBGColor};
+ --polyplus-cardbordercolor: ${Settings.ThemeCreator.CardBorderColor};
+ }
+
+ nav {
+ background-color: var(--polyplus-navbgcolor) !important;
+ border-bottom: 1px solid var(--polyplus-navbordercolor) !important;
+ }
+
+ .nav-sidebar {
+ background-color: var(--polyplus-sidebarbgcolor) !important;
+ border-right: 1px solid var(--polyplus-sidebarbordercolor) !important;
+ }
+
+ #app {
+ background-color: var(--polyplus-bgcolor) !important;
+ background-image: var(--polyplus-bgimage) !important;
+ background-size var(--polyplus-bgimagesize)
+ color: var(--polyplus-primarytextcolor) !important;
+ }
+
+ .text-muted {
+ color: var(--polyplus-secondarytextcolor) !important;
+ }
+
+ a {
+ color: var(--polyplus-linktextcolor) !important;
+ }
+
+ a:hover {
+ color: var(--polyplus-linkhoveredtextcolor) !important;
+ }
+
+ a:focus {
+ color: var(--polyplus-linkfocusedtextcolor) !important;
+ }
+
+ /*
+ a:visited {
+ color: var(--polyplus-linkvisitedtextcolor) !important;
+ }
+ */
+
+ .card-header {
+ background-color: var(--polyplus-cardheadbgcolor) !important;
+ }
+
+ .card {
+ background-color: var(--polyplus-cardbodybgcolor) !important;
+ border-color: var(--polyplus-cardbordercolor) !important;
+ }
+
+ nav a.nav-link {
+ color: var(--polyplus-navitemcolor) !important;
+ }
+
+ .nav-sidebar .nav-sidebar-button {
+ background-color: var(--polyplus-sidebaritembgcolor) !important;
+ border-color: var(--polyplus-sidebaritembordercolor) !important;
+ color: var(--polyplus-sidebaritemcolor) !important;
+ }
+
+ .nav-sidebar-text {
+ color: var(--polyplus-sidebaritemlabelcolor) !important;
+ }
+ `
+ }
+});
+
+document.addEventListener('DOMContentLoaded', function() {
+ if (document.getElementsByClassName('card-header')[0] && document.getElementsByClassName('card-header')[0].innerText === ' Page not found') {
+ return
+ }
+
+ // Check if Theme Exists, if so Load It
+ if (Settings.ThemeCreatorOn && Settings.ThemeCreatorOn === true) {
+ if (!(Settings.ThemeCreator.WebsiteLogo === null)) {
+ document.querySelector('.nav-sidebar img').setAttribute('src', Settings.ThemeCreator.WebsiteLogo)
+ }
+ }
+ if (Settings.ThemeCreatorOn && Settings.ThemeCreatorOn === true && Theme != null) {
+ document.body.prepend(Theme)
+ }
+
+ // Define Data
+ const UserData = {
+ Username: document.querySelector('a.text-reset.text-decoration-none[href^="/users"]').innerText.replace(/\s+/g,''),
+ ID: document.querySelector('.text-reset.text-decoration-none[href^="/users/"]').getAttribute('href').split('/')[2],
+ Bricks: document.querySelector('.brickBalanceCont').innerText.replace(/\s+/g,'')
+ }
+
+ window.localStorage.setItem('account_info', JSON.stringify(UserData))
+ document.body.setAttribute('data-URL', window.location.href)
+
+ // Add PolyPlus Settings link to Sidebar
+ const Parent = document.querySelector('ul.nav.nav-flush')
+ const Clone = Parent.querySelectorAll('li.nav-item')[0].cloneNode(true)
+ Clone.getElementsByTagName('a')[0].href = '/my/settings/polyplus'
+ Clone.getElementsByTagName('span')[0].innerText = "Poly+"
+ const Icon = Clone.querySelector('i')
+ Icon.classList = 'fa-regular fa-sparkles'
+
+ if (Settings.ModifyNavOn && Settings.ModifyNavOn === true) {
+ let NavbarItems = document.querySelectorAll('#main-content nav.navbar .nav-link')
+ let Needed = [NavbarItems[11],NavbarItems[12],NavbarItems[13],NavbarItems[14],NavbarItems[15]]
+ for (let i = 0; i < Settings.ModifyNav.length; i++) {
+ if (Settings.ModifyNav[i].Label != null) {
+ Needed[i].children[1].innerText = Settings.ModifyNav[i].Label
+ Needed[i].href = Settings.ModifyNav[i].Link
+ }
+ }
+ }
+
+ if (Settings.HideUpgradeBtnOn && Settings.HideUpgradeBtnOn === true) {
+ document.querySelector('.nav-sidebar a[href="/upgrade"].nav-link.py-1.nav-sidebar-link').remove()
+ }
+
+ if (Settings.IRLPriceWithCurrencyOn && Settings.IRLPriceWithCurrencyOn === true) {
+ var IRL;
+ var DISPLAY;
+ switch (Settings.IRLPriceWithCurrencyCurrency) {
+ case 0:
+ IRL = (UserData.Bricks.replace(/,/g, '') * 0.0099).toFixed(2)
+ DISPLAY = 'USD'
+ break
+ case 1:
+ IRL = (UserData.Bricks.replace(/,/g, '') * 0.009).toFixed(2)
+ DISPLAY = 'EUR'
+ break
+ case 2:
+ IRL = (UserData.Bricks.replace(/,/g, '') * 0.0131).toFixed(2)
+ DISPLAY = 'CAD'
+ break
+ case 3:
+ IRL = (UserData.Bricks.replace(/,/g, '') * 0.0077).toFixed(2)
+ DISPLAY = 'GBP'
+ break
+ case 4:
+ IRL = (UserData.Bricks.replace(/,/g, '') * 0.1691).toFixed(2)
+ DISPLAY = 'MXN'
+ break
+ case 5:
+ IRL = (UserData.Bricks.replace(/,/g, '') * 0.0144).toFixed(2)
+ DISPLAY = 'AUD'
+ break
+ case 6:
+ IRL = (UserData.Bricks.replace(/,/g, '') * 0.2338).toFixed(2)
+ DISPLAY = 'TRY'
+ break
+ }
+ let BrickBalanceCount = [document.querySelector('.text-success .brickBalanceCount'), document.querySelector('.text-success .brickBalanceCont')]
+ BrickBalanceCount.forEach(element => {
+ element.innerText = element.innerText + ` ($${IRL} ${DISPLAY})`
+ });
+ }
+
+ if (Settings.HideNotifBadgesOn && Settings.HideNotifBadgesOn === true) {
+ document.querySelectorAll('.notif-nav.notif-sidebar').forEach(element => {element.remove();});
+ }
+});
+
+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;
+}
\ No newline at end of file
diff --git a/js/forum/forum-search.js b/js/forum/forum-search.js
new file mode 100755
index 0000000..44613d0
--- /dev/null
+++ b/js/forum/forum-search.js
@@ -0,0 +1,53 @@
+setTimeout(function () {}, 100)
+var Settings;
+chrome.storage.sync.get(['PolyPlus_Settings'], function(result){
+ Settings = result.PolyPlus_Settings;
+
+ if (!(Settings.MoreSearchFiltersOn === true)) {
+ return
+ }
+
+ let Form = document.querySelector('form[action="/forum/search"]')
+ let SearchBtn = document.querySelector('button[type="submit"]')
+ let CreatedByFilter = document.createElement('div')
+ CreatedByFilter.classList = 'input-group mt-2'
+ CreatedByFilter.innerHTML = `
+
+
+ Created by
+
+ `
+ console.log(SearchBtn)
+ Form.insertBefore(CreatedByFilter, SearchBtn.parentElement)
+ let CreatedByFilter_Checkbox = CreatedByFilter.querySelector('input[type="checkbox"]')
+ let CreatedByFilter_Input = CreatedByFilter.querySelector('input[type="text"]')
+ let CreatedByValue = GetURLParameter("createdBy")
+ console.log(CreatedByValue)
+ if (CreatedByValue) {
+ CreatedByFilter_Checkbox.setAttribute('checked', true)
+ CreatedByFilter_Input.setAttribute('value', CreatedByValue)
+ CreatedByFilter_Input.removeAttribute('disabled')
+ document.querySelectorAll('.forum-entry').forEach(element => {
+ console.log(element.querySelectorAll('a[href^="/users/"]')[1].innerText)
+ if (!(element.querySelectorAll('a[href^="/users/"]')[1].innerText === CreatedByValue)) {
+ element.remove();
+ }
+ });
+ }
+ /*
+ CreatedByFilter_Checkbox.addEventListener('click', function(){
+ let Status = CreatedByFilter_Checkbox.getAttribute('checked')
+ if (Status === true) {
+ CreatedByFilter_Input.removeAttribute('disabled')
+ } else {
+ CreatedByFilter_Input.setAttribute('disabled', true)
+ }
+ });
+ */
+});
+
+function GetURLParameter(param) {
+ const queryString = window.location.search;
+ const urlParams = new URLSearchParams(queryString);
+ return urlParams.get(param);
+}
\ No newline at end of file
diff --git a/js/forum/forum-view.js b/js/forum/forum-view.js
new file mode 100755
index 0000000..f999098
--- /dev/null
+++ b/js/forum/forum-view.js
@@ -0,0 +1,173 @@
+var idCache = []
+let url = "https://polytoria.com/users/:id"
+
+console.log('loaded!')
+
+function LowAttentionSpanMode() {
+ let PostContent = document.querySelector('.mcard p:nth-child(3)').textContent
+ let Captions = CombineArray(PostContent.split(' ')).map((x, i) => `${x} `).join('')
+ let NumberOfCaptions = (PostContent.split(' ').length) - 1
+ Swal.fire({
+ title: "No Attention Span Mode",
+ html: `
+
+ ${Captions}
+ `
+ });
+ let CaptionsElement = document.getElementById('polyplus-captions')
+
+ let Index = 0
+ //LoopIteration()
+
+ function LoopIteration() {
+ Array.from(CaptionsElement.children).forEach(element => {
+ element.style.display = 'none'
+ });
+ if (CaptionsElement.children[Index] === undefined) {
+ Swal.close()
+ return
+ }
+ CaptionsElement.children[Index].style.display = 'block'
+ setTimeout(function () {
+ console.log(Index, 'Next Caption')
+ Index++
+ LoopIteration()
+ }, 1100)
+ }
+
+ function CombineArray(arr) {
+ let CombinedArray = [];
+ let CurrentCombinedItem = "";
+
+ for (let i = 0; i < arr.length; i++) {
+ if ((CurrentCombinedItem + " " + arr[i]).length <= 6) {
+ if (CurrentCombinedItem !== "") {
+ CurrentCombinedItem += " ";
+ }
+ CurrentCombinedItem += arr[i];
+ } else {
+ CombinedArray.push(CurrentCombinedItem);
+ CurrentCombinedItem = arr[i];
+ }
+ }
+
+ if (CurrentCombinedItem !== "") {
+ CombinedArray.push(CurrentCombinedItem);
+ }
+
+ return CombinedArray;
+ }
+}
+
+setTimeout(LowAttentionSpanMode, 525)
+
+chrome.storage.sync.get(['PolyPlus_Settings'], function(result) {
+ let text = document.querySelectorAll('p.mb-0 + p')
+
+ if (result.PolyPlus_Settings.ForumMarkOn === true) {
+ text.forEach(element => {
+ element.innerHTML = MarkdownText(element.innerText)
+ });
+ }
+
+ if (result.PolyPlus_Settings.ForumMentsOn === true) {
+ text.forEach(element => {
+ let output = element.innerText.replace(/@([\w.]+)/g, '@$1 ');
+ output = output.replace(/\n/g, ' ');
+ element.innerHTML = output
+
+ let links = element.querySelectorAll('a.polyplus-mention');
+ if (!(links.length > 3)) {
+ HandleLinks(links, null)
+ setTimeout(function () {}, 125)
+ }
+ });
+ }
+});
+
+function HandleLinks(links, link, index = 0) {
+ if (index >= links.length) {
+ return
+ }
+
+ link = links[index]
+ let username = link.textContent.replace(/@/g, '')
+ var inCache = CheckIDCache(username)
+ console.log(idCache, inCache)
+ if (inCache.success === false) {
+ fetch('https://api.polytoria.com/v1/users/find?username=:user'.replace(':user', username))
+ .then(response => {
+ if (!response.ok) {
+ throw new Error(`An error occurred: ${response.status}`);
+ }
+ return response.json();
+ })
+ .then(data => {
+ link.setAttribute('href', url.replace(':id', data.id));
+ idCache.push({ "username": username, "id": data.id });
+ console.log(idCache);
+ HandleLinks(links, null, index + 1)
+ })
+ .catch(error => {
+ console.error(error);
+ link.removeAttribute('href');
+ HandleLinks(links, null, index + 1)
+ });
+ } else {
+ console.log('cached')
+ link.setAttribute('href', url.replace(':id', inCache.id))
+ HandleLinks(links, null, index + 1)
+ }
+}
+
+function CheckIDCache(cache, username) {
+ idCache.forEach(element => {
+ if (element.username === username) {
+ return {"success": true, "id": element.id}
+ }
+ });
+ /*
+ for (let i = 0; i < cache.length; i++) {
+ const element = cache[i];
+ console.log((element.username === username))
+ if (element.username === username) {
+ return {"success": true, "id": element.id};
+ }
+ }
+ */
+ return {"success": false, "id": null};
+}
+
+function MarkdownText(text) {
+ // Split the text into an array of lines
+ const lines = text.split('\n');
+
+ // Process each line
+ const formattedLines = lines.map(line => {
+ if (line.startsWith('###')) {
+ // Third-level heading: remove the '###' and wrap in tag
+ const headingText = line.substring(3).trim();
+ return `${headingText} `;
+ } else if (line.startsWith('##')) {
+ // Secondary heading: remove the '##' and wrap in tag
+ const headingText = line.substring(2).trim();
+ return `${headingText} `;
+ } else if (line.startsWith('#')) {
+ // Big heading: remove the '#' and wrap in tag
+ const headingText = line.substring(1).trim();
+ return `${headingText} `;
+ } else {
+ // Apply formatting to the line
+ let formattedLine = line.replace(/\*\*(.*?)\*\*/g, '$1 '); // Bold
+ formattedLine = formattedLine.replace(/__(.*?)__/g, '$1 '); // Underline
+ formattedLine = formattedLine.replace(/\*(.*?)\*/g, '$1 '); // Italics
+ formattedLine = formattedLine.replace(/~~(.*?)~~/g, '$1 '); // Strikethrough
+ return formattedLine;
+ }
+ });
+
+ // Join the formatted lines back into a single string
+ const formattedText = formattedLines.join('\n\n');
+
+ return formattedText;
+ }
\ No newline at end of file
diff --git a/js/forum/forum-view2.js b/js/forum/forum-view2.js
new file mode 100755
index 0000000..41b62ac
--- /dev/null
+++ b/js/forum/forum-view2.js
@@ -0,0 +1,63 @@
+chrome.storage.sync.get(['PolyPlus'], function (result) {
+ if (result.PolyPlus.Settings.ForumMentsOn === false) {
+ return;
+ }
+
+ const idCache = [];
+ const url = "https://polytoria.com/users/:id";
+ const text = document.querySelectorAll('p.mb-0');
+
+ async function CheckIDCache(cache, username) {
+ for (let i = 0; i < cache.length; i++) {
+ const element = cache[i];
+ console.log('type', typeof element);
+ console.log('expected type', typeof username);
+
+ const cachedUsername = Object.keys(element)[0];
+ if (cachedUsername.toString() === username) {
+ return [true, element];
+ }
+ }
+ return [false, null];
+ }
+
+ async function processLinks(links) {
+ for (const link of links) {
+ const username = link.textContent.replace(/@/g, '');
+ const inCache = await CheckIDCache(idCache, username);
+ console.log('1', inCache[0]);
+ console.log('2', inCache[1]);
+
+ if (inCache[0] === false) {
+ console.log('not cached');
+ try {
+ const response = await fetch(`https://api.polytoria.com/v1/users/find?username=${username}`);
+ if (!response.ok) {
+ throw new Error(`An error occurred: ${response.status}`);
+ }
+ const data = await response.json();
+ link.setAttribute('href', url.replace(':id', data.id));
+ idCache.push({ [username]: data.id });
+ console.log(idCache);
+ } catch (error) {
+ console.error(error);
+ link.removeAttribute('href');
+ }
+ } else {
+ console.log('cached');
+ link.setAttribute('href', url.replace(':id', inCache[1][username]));
+ }
+ }
+ }
+
+ text.forEach(element => {
+ let output = element.innerText.replace(/@([\w.]+)/g, '@$1 ');
+ output = output.replace(/\n/g, ' ');
+ element.innerHTML = output;
+
+ const links = element.querySelectorAll('a');
+ if (!(links.length > 3)) {
+ processLinks(links);
+ }
+ });
+});
diff --git a/js/forum/new-forum-view.js b/js/forum/new-forum-view.js
new file mode 100644
index 0000000..12a8866
--- /dev/null
+++ b/js/forum/new-forum-view.js
@@ -0,0 +1,22 @@
+var Settings = []
+chrome.storage.sync.get(['PolyPlus_Settings'], function(result) {
+ Settings = result.PolyPlus_Settings || []
+
+ if (Settings.ForumMentsOn === true || 1 === 1) {
+ HandleForumMentions()
+ }
+});
+
+function HandleForumMentions() {
+ const ForumText = document.querySelectorAll('p:not(.text-muted):not(.mb-0)')
+ const IDCache = {}
+
+ for (let text of ForumText) {
+ if (/@([\w.]+)/g.test(text.innerText) === true) {
+ const FormattedText = text.innerText.replace(/@([\w.]+)/g, '@$1 ')
+ console.log(FormattedText)
+
+ fetch('https://api.polytoria.com/v1/users/find?username=')
+ }
+ }
+}
\ No newline at end of file
diff --git a/js/membership-themes.js b/js/membership-themes.js
new file mode 100755
index 0000000..06388bd
--- /dev/null
+++ b/js/membership-themes.js
@@ -0,0 +1,43 @@
+chrome.storage.sync.get(['PolyPlus_Settings'], function(result){
+ Settings = result.PolyPlus_Settings;
+
+ if (Settings.ApplyMembershipThemeOn === false) {return}
+ MembershipTheme = Settings.ApplyMembershipThemeTheme === 0 ? 'plus': 'plusdx'
+
+ document.addEventListener('DOMContentLoaded', function(){
+ if (document.getElementsByClassName('card-header')[0] && document.getElementsByClassName('card-header')[0].innerText === ' Page not found') {
+ return
+ }
+
+ if (document.getElementsByTagName('NAV')[0].classList.contains('navbar-plus') === true || document.getElementsByTagName('NAV')[0].classList.contains('navbar-plusdx') === true) {
+ return
+ }
+
+ const Navbar = document.querySelector('.navbar.navbar-expand-lg.navbar-light.bg-navbar.nav-topbar');
+ const Sidebar = document.querySelector('.d-flex.flex-column.flex-shrink-0.bg-sidebar.nav-sidebar');
+
+ Navbar.classList.add('navbar-' + MembershipTheme);
+ Sidebar.classList.add('sidebar-' + MembershipTheme);
+
+ if (MembershipTheme === 'plusdx') {
+ let SidebarLogo = document.querySelector('.nav-sidebar img');
+ SidebarLogo.setAttribute('src', 'https://c0.ptacdn.com/static/images/branding/icon-plusdx.bd9daa92.svg')
+ let SidebarLogoLabel = document.createElement('div')
+ SidebarLogoLabel.classList = 'nplusdx-banner'
+ SidebarLogoLabel.innerHTML = `
+
+ `
+ SidebarLogo.parentElement.appendChild(SidebarLogoLabel)
+
+ if (window.location.pathname === "/home") {
+ let HomeUsernameText = document.getElementsByClassName('home-title2')[0]
+ HomeUsernameText.children[0].classList.add('text-plusdx')
+ let Label = document.createElement('div')
+ Label.classList = 'hplusdx-banner rounded-2'
+ Label.setAttribute('style', 'margin-top: -8px; animation-delay: 0.09s;')
+ Label.innerText = 'Deluxe'
+ HomeUsernameText.appendChild(Label)
+ }
+ }
+ });
+});
\ No newline at end of file
diff --git a/js/op-comments.js b/js/op-comments.js
new file mode 100755
index 0000000..91a148c
--- /dev/null
+++ b/js/op-comments.js
@@ -0,0 +1,53 @@
+let Comments = document.getElementById('comments')
+const Type = window.location.pathname.split('/')[1]
+
+let CreatorID;
+switch (Type) {
+ case 'store':
+ if (document.querySelector('h5 .text-reset[href^="/users/"]')) {
+ CreatorID = document.querySelector('h5 .text-reset[href^="/users/"]').getAttribute('href').split('/')[2]
+ } else {CreatorID = 1}
+ break
+ case 'places':
+ CreatorID = document.querySelector('.mcard .col .text-muted [href^="/users/"]').getAttribute('href').split('/')[2]
+ break
+ case 'feed':
+ CreatorID = document.querySelector('p a[href^="/users/"].text-reset').getAttribute('href').split('/')[2]
+ break
+ case 'guilds':
+ CreatorID = document.querySelector('[class^="userlink-"][href^="/users/"]').getAttribute('href').split('/')[2]
+ Comments = document.getElementById('wall-posts')
+ break
+}
+Array.from(Comments.children).forEach(element => {
+ LoadCreatorTag(element)
+});
+
+const Observer = new MutationObserver(function (list){
+ for (let record of list) {
+ for (let element of record.addedNodes) {
+ LoadCreatorTag(element)
+ }
+ }
+});
+Observer.observe(Comments, {attributes: false, childList: true, subtree: false})
+
+function LoadCreatorTag(element) {
+ let NameElement;
+ if (!(Type === 'guilds')) {
+ NameElement = element.querySelector('.text-reset[href^="/users/"]')
+ } else {
+ NameElement = element.querySelector('[class^="userlink-"][href^="/users/"]')
+ }
+ let UserID = NameElement.getAttribute('href').split('/')[2]
+ if (UserID === CreatorID) {
+ let Tag = document.createElement('span')
+ Tag.classList = 'badge bg-primary'
+ Tag.style.marginLeft = '5px'
+ Tag.style.verticalAlign = 'text-top'
+ Tag.innerText = 'CREATOR'
+ NameElement.appendChild(Tag)
+ //console.log(window.bootstrap)
+ //new window.bootstrap.Tooltip(Tag, {toggle:"tooltip",title:"This user is the creator of this asset!"})
+ }
+}
\ No newline at end of file
diff --git a/js/places/place-edit.js b/js/places/place-edit.js
new file mode 100755
index 0000000..38ec870
--- /dev/null
+++ b/js/places/place-edit.js
@@ -0,0 +1,50 @@
+!(async () => {
+ const ID = window.location.pathname.split('/')[3]
+ const Response = await fetch('https://api.polytoria.com/v1/places/'+ID)
+ let Status = await Response.json()
+ Status = Status.isActive
+ console.log(Status)
+
+ const Form = document.querySelector('form[action="/create/place/update"]')
+ const DIV = document.createElement('div')
+ DIV.classList = 'form-group mt-4'
+ DIV.innerHTML = `
+
+ Toggle Activity
+ Make your place active or inactive (currently ${(Status === true) ? 'active' : 'inactive'}).
+
+
+ `
+
+ Form.insertBefore(DIV, Form.children[Form.children.length-1])
+
+ const ActivityBtn = document.createElement('button')
+ ActivityBtn.type = 'button'
+ ActivityBtn.classList = 'btn ' + (Status === true ? 'btn-danger' : 'btn-success')
+ ActivityBtn.innerText = Status === true ? 'Deactivate' : 'Activate'
+ DIV.appendChild(ActivityBtn)
+
+ ActivityBtn.addEventListener('click', function() {
+ fetch(`https://polytoria.com/api/places/${ID}/toggle-active`, {
+ method: "POST",
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-CSRF-Token': document.querySelector('input[name="_csrf"]').value
+ }
+ })
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network not ok ' + response.status)
+ }
+ return response.json()
+ })
+ .then(data => {
+ Status = data.isActive
+ ActivityBtn.innerText = Status === true ? 'Deactivate' : 'Activate'
+ ActivityBtn.classList = 'btn ' + (Status === true ? 'btn-danger' : 'btn-success')
+ })
+ .catch(error => {
+ console.log(error)
+ });
+ });
+})()
\ No newline at end of file
diff --git a/js/places/place-join.js b/js/places/place-join.js
new file mode 100644
index 0000000..ae438bc
--- /dev/null
+++ b/js/places/place-join.js
@@ -0,0 +1,40 @@
+!(() => {
+ const PlaceID = parseInt(window.location.pathname.split('/')[2])
+
+ console.log('PLACE ID: ' + PlaceID)
+
+ fetch('https://polytoria.com/home')
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network not ok')
+ }
+ return response.text()
+ })
+ .then(data => {
+ const Parser = new DOMParser()
+ const Doc = Parser.parseFromString(data, 'text/html')
+
+ fetch('https://polytoria.com/api/places/join',{
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-Csrf-Token': Doc.querySelector('[name="_csrf"]').value
+ },
+ body: JSON.stringify({
+ 'placeID': PlaceID
+ })
+ })
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network not ok')
+ }
+ return response.json()
+ })
+ .then(data => {
+ if (data.success !== true) {throw new Error(data.message)}
+ window.location.href = 'polytoria://client/' + data.token
+ window.location.href = 'https://polytoria.com/places/' + PlaceID
+ })
+ .catch(error => {console.log(error)})
+ })
+})();
\ No newline at end of file
diff --git a/js/places/place-view.js b/js/places/place-view.js
new file mode 100755
index 0000000..e8e073d
--- /dev/null
+++ b/js/places/place-view.js
@@ -0,0 +1,239 @@
+let URLSplit = window.location.pathname.split('/');
+let GameID = URLSplit[2];
+
+var Settings;
+let PinnedGames;
+
+!(() => {
+ if (GameID === undefined) {return}
+
+ /*
+ const DataContainer = document.getElementById('likes-data-container')
+ const RatingsData = {
+ Likes: parseInt(DataContainer.getAttribute('data-like-count')),
+ Dislikes: parseInt(DataContainer.getAttribute('data-dislike-count')),
+ Percentage: null
+ }
+ RatingsData.Percentage = Math.floor((RatingsData.Likes / (RatingsData.Likes + RatingsData.Dislikes)) * 100)
+ const RatingsContainer = document.getElementById('thumbup-btn').parentElement.parentElement
+
+ const PercentageLabel = document.createElement('small')
+ PercentageLabel.classList = 'text-muted'
+ PercentageLabel.style.fontSize = '0.8rem'
+ PercentageLabel.style.marginLeft = '10px'
+ PercentageLabel.style.marginRight = '10px'
+ PercentageLabel.innerText = RatingsData.Percentage + '%'
+
+ RatingsContainer.children[0].appendChild(PercentageLabel)
+ */
+
+ chrome.storage.sync.get(['PolyPlus_Settings'], function(result) {
+ Settings = result.PolyPlus_Settings;
+
+ if (Settings.PinnedGamesOn === true) {
+ HandlePinnedGames()
+ }
+
+ // Disabled settings
+ if (Settings.InlineEditingOn === true || 1 === 2) {
+ HandleInlineEditing()
+ }
+
+ if (Settings.GameProfilesOn === true && 1 === 2) {
+ HandleGameProfiles()
+ }
+ });
+
+ chrome.storage.onChanged.addListener(function(changes, namespace) {
+ if ('PolyPlus_PinnedGames' in changes) {
+ chrome.storage.sync.get(['PolyPlus_PinnedGames'], function(result) {
+ PinnedGames = result.PolyPlus_PinnedGames || [];
+
+ if (PinnedGames.includes(parseInt(GameID))) {
+ PinBtn.innerHTML = ' Un-pin'
+ } else {
+ if (PinnedGames.length !== 5) {
+ PinBtn.removeAttribute('disabled')
+ PinBtn.innerHTML = ' Pin'
+ } else {
+ PinBtn.setAttribute('disabled', true)
+ PinBtn.innerHTML = ' Pin (max 5/5)'
+ }
+ }
+ });
+ }
+ });
+})()
+
+async function HandlePinnedGames() {
+ chrome.storage.sync.get(['PolyPlus_PinnedGames'], function(result){
+ PinnedGames = result.PolyPlus_PinnedGames || [];
+ const PinBtn = document.createElement('button');
+ PinBtn.classList = 'btn btn-warning btn-sm';
+ PinBtn.style = 'position: absolute; right: 0; margin-right: 7px;'
+
+ if (PinnedGames.includes(parseInt(GameID))) {
+ PinBtn.innerHTML = ' Un-pin';
+ } else {
+ PinBtn.innerHTML = ' Pin';
+ }
+
+ PinBtn.addEventListener('click', function() {
+ PinBtn.setAttribute('disabled', 'true')
+
+ chrome.storage.sync.get(['PolyPlus_PinnedGames'], function(result) {
+ PinnedGames = result.PolyPlus_PinnedGames || [];
+ const Index = PinnedGames.indexOf(parseInt(GameID));
+ if (Index !== -1) {
+ PinnedGames.splice(Index, 1);
+ PinBtn.innerHTML = ' Pin'
+ } else {
+ PinnedGames.push(parseInt(GameID));
+ PinBtn.innerHTML = ' Un-pin'
+ }
+
+ chrome.storage.sync.set({ 'PolyPlus_PinnedGames': PinnedGames, arrayOrder: true }, function() {
+ setTimeout(function() {
+ PinBtn.removeAttribute('disabled')
+ }, 1250)
+ });
+ });
+ });
+
+ document.querySelectorAll('.card-header')[2].appendChild(PinBtn);
+ });
+}
+
+async function HandleInlineEditing() {
+ // Fix description editing
+ // Make it possible to edit description even if the game doesn't initially have a description
+ // Add the ability to edit the game's genre
+ // Improve editing visuals overall
+
+ let Editing = false
+
+ const PlaceTitle = document.querySelector('.card-header h1[style="font-weight:800;font-size:1.6em"]')
+ const PlaceTitleSpan = document.createElement('span')
+ PlaceTitleSpan.innerText = PlaceTitle.innerText
+ PlaceTitle.innerHTML = ''
+ PlaceTitle.appendChild(PlaceTitleSpan)
+
+ const PlaceDesc = document.querySelector('.card.m-card.mb-2 card-body.p-3.small')
+ const PlaceGenre = document.getElementsByClassName('list-unstyled m-0 col')[0].children[3]
+
+ const Genres = [
+ "other",
+ "adventure",
+ "building",
+ "competitive",
+ "creative",
+ "fighting",
+ "funny",
+ "hangout",
+ "medieval",
+ "parkour",
+ "puzzle",
+ "racing",
+ "roleplay",
+ "sandbox",
+ "showcase",
+ "simulator",
+ "sports",
+ "strategy",
+ "survival",
+ "techdemo",
+ "trading",
+ "tycoon",
+ "western"
+ ]
+
+ const EditBtn = document.createElement('button');
+ EditBtn.classList = 'btn btn-primary btn-sm';
+ EditBtn.style = 'position: absolute; right: 0; margin-right: 7px;'
+ EditBtn.innerHTML = ' Edit '
+ document.querySelectorAll('.card-header')[3].appendChild(EditBtn);
+ /*
+ const EditBtn = document.createElement('button')
+ EditBtn.classList = 'text-muted'
+ EditBtn.innerHTML = `
+
+ `
+ EditBtn.setAttribute('style', 'background: transparent; border: none; font-size: 1rem; vertical-align: middle;')
+ PlaceTitle.appendChild(EditBtn)
+ */
+
+ EditBtn.addEventListener('click', function(){
+ Editing = (Editing === true) ? false : true
+
+ EditBtn.children[0].classList.toggle('fa-hammer')
+ EditBtn.children[0].classList.toggle('fa-check-double')
+ EditBtn.children[0].classList.toggle('fa-fade')
+
+ PlaceTitleSpan.setAttribute('contenteditable', Editing.toString())
+ if (PlaceDesc !== null) {
+ console.log('Description exists')
+ PlaceDesc.setAttribute('contenteditable', Editing.toString())
+ }
+ if (Editing === false) {
+ const Send = new FormData()
+ Send.append("_csrf", document.querySelector('input[name="_csrf"]').value)
+ Send.append("id", GameID)
+ Send.append("name", PlaceTitle.innerText || '')
+
+ fetch('/create/place/update', {method:"POST",body:Send})
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network not ok')
+ }
+ return response.text()
+ })
+ .then(data => {
+ console.log('Successfully edited game')
+ })
+ .catch(error => {
+ console.log('Error while editing game')
+ });
+ }
+ });
+}
+
+const Data = JSON.parse('{"gameTitle": "Hyper[Fart]","bg": "#000","accent": "#007bff","secondary": "#","cardBg": "#313131","font": "","text": "#fff"}')
+
+async function HandleGameProfiles(Data) {
+ document.querySelector('h1.my-0')
+ .setAttribute('game-key', 'true');
+ document.querySelector('div[style="min-height: 60vh;"]')
+ .id = 'gameprofile';
+
+ const Style = document.createElement('style')
+
+ Style.innerHTML = `
+ div#app {
+ background: ${Data.bg} !important;
+ }
+
+ #gameprofile {
+ /*font-family: ${Data.font} !important;*/
+ color: ${Data.text} !important;
+ }
+
+ #gameprofile .card {
+ --bs-card-bg: ${Data.cardBg};
+ }
+
+ /*
+ #gameprofile .card.mcard[game-key] .card-header {
+ background: transparent;
+ border: none;
+ }
+ */
+
+ #gameprofile .card.mcard [game-key] {
+ background: linear-gradient(to bottom, ${Data.accent}, ${Data.secondary});
+ background-clip: text;
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ }
+ `
+ document.body.appendChild(Style)
+}
\ No newline at end of file
diff --git a/js/polyplus-settings.js b/js/polyplus-settings.js
new file mode 100755
index 0000000..d12c1e1
--- /dev/null
+++ b/js/polyplus-settings.js
@@ -0,0 +1,894 @@
+const InExtensionSettings = (window.location.pathname.split('/')[3] === "polyplus")
+console.log(window.location.pathname.split('/')[3], InExtensionSettings)
+
+if (InExtensionSettings === true) {
+ window.location.href = chrome.runtime.getURL('settings.html')
+}
+
+document.addEventListener('DOMContentLoaded', function(){
+ const Nav = document.getElementsByClassName('nav nav-pills')[0]
+
+ if (InExtensionSettings === true) {
+ Array.from(Nav.children).forEach(item => {
+ if (item.classList.contains('active')) {
+ item.classList.remove('active')
+ }
+ })
+ }
+
+ const PolyPlusItem = document.createElement('a')
+ PolyPlusItem.classList = 'nav-link'
+ PolyPlusItem.href = chrome.runtime.getURL('settings.html')
+ PolyPlusItem.innerHTML = `
+ Poly+
+ `
+
+ Nav.insertBefore(PolyPlusItem, Nav.getElementsByTagName('hr')[0])
+
+ return
+ if (window.location.pathname.split('/')[3] === "polyplus") {
+ console.log('is settings')
+ PolyPlusItem.classList.add('active')
+ document.getElementsByClassName('col-lg-10')[0].innerHTML = `
+
+
+
+
+
Are you sure you'd like to reset all settings to their respective defaults? (this action is irreversible)
+
Yes
+
No
+
+
+
+
+
+
Unleash your creativity and customize the Polytoria website to your liking! (this feature is still in development)
+
+
+
+
Save Theme to JSON
+
+
+
Load Theme from JSON
+
+
Load
+
+
+
+
+
+
+
+
+
+
+
Primary Text Color
+
+
+
Secondary Text Color
+
+
+
+
+
+
+
+
+
+
+
+ Website Logo (URL)
+
+
+
+
+
Save
+
Cancel
+
+
+
+
+
+
Customize the navbar to your liking!
+
+
+
+
+
+
+
+
Save
+
Cancel
+
+
+
+
+
+ Pinned Games (enabled )
+ Toggle
+
+
+ Pin your favorite games to the top of the homepage!
+
+
+
+ Forum Mentions (disabled )
+ Toggle
+
+
+ Get a quick link to the popular person everyone is talking about's profile!
+
+
+
+ Best Friends (enabled )
+ Toggle
+
+
+ Prioritize the bestest of friends on applicable friend lists!
+
+
+
+ Improved Friend Lists (enabled )
+ Toggle
+
+
+
+ Accept or decline all friend requests with the click of a button or multi-remove existing friends!
+
+ * You can only remove up to 25 friends at once.
+
+
+
+
+ Show IRL price with Brick Count (enabled )
+ Toggle
+
+
+
+ See the real life currency value along with Bricks across the site!
+
+ * Currencies were calculated on [DATE].
+
+ * Currencies other than USD are purely approximations.
+
+
+ United States Dollar (USD)
+ Euro (EUR)
+ Canadian Dollar (CAD)
+ Great British Pound (GBP)
+ Mexican Peso (MXN)
+ Australian Dollar (AUD)
+ Turkish Lira (TRY)
+
+
+
+ $0.99 USD
+ $4.99 USD
+ $9.99 USD
+ $24.99 USD
+ $49.99 USD
+ $99.99 USD
+
+
+
+
+ Hide Notification Badges (disabled )
+ Toggle
+
+
+ Hide the annoying red circles on the sidebar!
+
+
+
+ Simplified Profile URLs (enabled )
+ Toggle
+
+
+ Makes all profile URLs simpler by allowing for you to go to "https://polytoria.com/profile/UsernameGoesHere" to redirect to the real profile URL!
+
+
+
+ Show "OWNED" Tag on Store Main Page (enabled )
+ Toggle
+
+
+ Quickly see if you own the item at a glance with a little tag in the top left corner of item cards on the main store page!
+
+
+
+ Theme Creator (disabled )
+ Toggle
+ Options
+
+
+ Unleash your creativity and customize the Polytoria website to your liking! (this feature is still in development)
+
+
+
+ More Search Filters (enabled )
+ Toggle
+
+
+ Easily find what you're looking for with more search filters side-wide! (this does not affect the main site search on the navbar)
+
+
+
+ Apply Membership Theme for Free (disabled )
+ Toggle
+
+
+ Ever want the fancy membership themes for completely free ? Well now you can get apply them site-wide!
+
+ Plus
+ Plus Deluxe
+
+
+
+
+ Forum Markdown (disabled )
+ Toggle
+
+
+
+ Format forum posts to make them look epic!
+
+
+
+
+ Multi-Cancel Outbound Trades (enabled )
+ Toggle
+
+
+
+ Quickly cancel several out-bound trades (trades that you have sent) all at once
+
+ * You can only cancel up to 10 trades at once.
+
+
+
+
+ Modify Navbar (disabled )
+ Toggle
+ Options
+
+
+
+ Customize the navbar to your liking!
+
+
+
+
+ Item Wishlist (enabled )
+ Toggle
+
+
+
+ Wishlist that item that you REALLY want!
+
+
+
+
+ Hide Upgrade Button (disabled )
+ Toggle
+
+
+ Hide the ugly blue "Upgrade" button on the sidebar!
+
+
+
Save
+
Reset to Default Settings
+
made by Index
+
+ `;
+
+ const SaveBtn = document.getElementById('Save')
+ const Elements = [
+ document.getElementById("PinnedGames"),
+ document.getElementById("ForumMentions"),
+ document.getElementById("BestFriends"),
+ document.getElementById("ImprovedFriendLists"),
+ document.getElementById("IRLPriceWithCurrency"),
+ document.getElementById("HideNotifBadges"),
+ document.getElementById("SimplifiedProfileURLs"),
+ document.getElementById("StoreOwnTag"),
+ document.getElementById("ThemeCreator"),
+ document.getElementById("MoreSearchFilters"),
+ document.getElementById("ApplyMembershipTheme"),
+ document.getElementById("MultiCancelOutTrades"),
+ document.getElementById("ModifyNav"),
+ document.getElementById("ItemWishlist"),
+ document.getElementById("HideUpgradeBtn")
+ ];
+ const ExpectedSettings = {
+ PinnedGamesOn: true,
+ ForumMentsOn: false,
+ BestFriendsOn: true,
+ ImprovedFrListsOn: true,
+ IRLPriceWithCurrencyOn: true,
+ IRLPriceWithCurrencyCurrency: 0,
+ IRLPriceWithCurrencyPackage: 0,
+ HideNotifBadgesOn: false,
+ SimplifiedProfileURLsOn: true,
+ StoreOwnTagOn: true,
+ ThemeCreatorOn: false,
+ ThemeCreator: {
+ BGColor: null,
+ BGImage: null,
+ BGImageSize: 'fit',
+ PrimaryTextColor: null,
+ SecondaryTextColor: null,
+ LinkTextColor: null,
+ WebsiteLogo: null
+ },
+ ModifyNavOn: false,
+ ModifyNav: [
+ {
+ Label: "Play",
+ 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,
+ ApplyMembershipThemeOn: false,
+ ApplyMembershipThemeTheme: 0,
+ MultiCancelOutTradesOn: true,
+ ItemWishlistOn: true,
+ HideUpgradeBtnOn: false
+ }
+
+ /*
+ const ResetDefaultsModal = document.getElementById('ResetDefaults-Modal')
+ const ThemeCreatorModal = {
+ Modal: document.getElementById('ThemeCreator-Modal'),
+ Save: document.getElementById('ThemeCreator-Modal-Save'),
+ BGColor: document.getElementById('ThemeCreator-Modal-BGColor'),
+ BGImage: document.getElementById('ThemeCreator-Modal-BGImage'),
+ BGImageSize: document.getElementById('ThemeCreator-Modal-BGImageSize'),
+ PrimaryTextColor: document.getElementById('ThemeCreator-Modal-PrimaryTextColor'),
+ SecondaryTextColor: document.getElementById('ThemeCreator-Modal-SecondaryTextColor'),
+ LinkTextColor: document.getElementById('ThemeCreator-Modal-LinkTextColor'),
+ WebsiteLogo: document.getElementById('ThemeCreator-Modal-WebsiteLogo')
+ }
+ var ModifyNavModal = {
+ Modal: document.getElementById('ModifyNav-Modal'),
+ Save: document.getElementById('ModifyNav-Modal-Save'),
+ "1Label": document.getElementById('ModifyNav-Modal-1Label'),
+ "1Link": document.getElementById('ModifyNav-Modal-1Link'),
+ "2Label": document.getElementById('ModifyNav-Modal-2Label'),
+ "2Link": document.getElementById('ModifyNav-Modal-2Link'),
+ "3Label": document.getElementById('ModifyNav-Modal-3Label'),
+ "3Link": document.getElementById('ModifyNav-Modal-3Link'),
+ "4Label": document.getElementById('ModifyNav-Modal-4Label'),
+ "4Link": document.getElementById('ModifyNav-Modal-4Link'),
+ "5Label": document.getElementById('ModifyNav-Modal-5Label'),
+ "5Link": document.getElementById('ModifyNav-Modal-5Link'),
+ }
+ */
+ SaveBtn.addEventListener("click", function() {Save()});
+ Elements.forEach(element => {
+ let Button = element.getElementsByTagName('button')[0]
+ let Options = element.getElementsByTagName('button')[1]
+ let Select = element.getElementsByTagName('select') || []
+
+ if (Button) {
+ Button.addEventListener('click', function() {
+ console.log('button clicked!!!!')
+ ToggleSetting(Button.getAttribute('data-setting'), element)
+ });
+ }
+
+ if (Options) {
+ Options.addEventListener('click', function() {
+ let Modal = document.getElementById(Options.getAttribute('data-modal') + '-Modal')
+ let ModalButtons = Modal.getElementsByTagName('button')
+ let ModalInputs = Modal.getElementsByTagName('input')
+ let ModalSelect = Modal.getElementsByTagName('select')
+
+ Array.from(ModalButtons).forEach(btn => {
+ if (!(btn.getAttribute('data-ignore') === 'true')) {
+ btn.addEventListener('click', function(){
+ let Setting = btn.getAttribute('data-setting')
+ if (Setting === '[save]') {
+ Array.from(ModalInputs).forEach(input => {
+ if (!(input.getAttribute('data-ignore') === 'true')) {
+ if (!(input.getAttribute('data-parent'))) {
+ Settings[Modal.getAttribute('data-setting')][input.getAttribute('data-setting')] = input.value || null
+ } else {
+ let Parent = input.getAttribute('data-parent')
+ if (!isNaN(parseInt(Parent))) {Parent = parseInt(Parent)}
+ Settings[Modal.getAttribute('data-setting')][Parent][input.getAttribute('data-setting')] = input.value || null
+ }
+ }
+ });
+ Array.from(ModalSelect).forEach(select => {
+ if (!(select.getAttribute('data-ignore') === 'true')) {
+ if (!(select.getAttribute('data-parent'))) {
+ Settings[Modal.getAttribute('data-setting')][select.getAttribute('data-setting')] = select.selectedIndex
+ } else {
+ let Parent = input.getAttribute('data-parent')
+ if (!isNaN(parseInt(Parent))) {Parent = parseInt(Parent)}
+ Settings[Modal.getAttribute('data-setting')][Parent][select.getAttribute('data-setting')] = select.selectedIndex
+ }
+ }
+ });
+ Save();
+ setTimeout(function () {
+ LoadCurrent();
+ Modal.close();
+ }, 400)
+ } else if (Setting === '[cancel]') {
+ Modal.close();
+ } else {
+ if (!(btn.getAttribute('data-parent'))) {
+ ToggleSetting(Modal.getAttribute('data-setting')[btn.getAttribute('data-setting')], null)
+ } else {
+ let Parent = input.getAttribute('data-parent')
+ if (!isNaN(parseInt(Parent))) {Parent = parseInt(Parent)}
+ ToggleSetting(Modal.getAttribute('data-setting')[Parent][btn.getAttribute('data-setting')], null)
+ }
+ }
+ });
+ }
+ });
+
+ Array.from(ModalInputs).forEach(input => {
+ if (!(input.getAttribute('data-ignore') === 'true')) {
+ if (!(input.getAttribute('data-parent'))) {
+ if (Settings[Modal.getAttribute('data-setting')][input.getAttribute('data-setting')] !== "undefined") {
+ input.value = Settings[Modal.getAttribute('data-setting')][input.getAttribute('data-setting')]
+ }
+ } else {
+ let Parent = input.getAttribute('data-parent')
+ if (Settings[Modal.getAttribute('data-setting')][Parent][input.getAttribute('data-setting')] !== "undefined") {
+ if (!isNaN(parseInt(Parent))) {Parent = parseInt(Parent)}
+ input.value = Settings[Modal.getAttribute('data-setting')][Parent][input.getAttribute('data-setting')]
+ }
+ }
+ }
+ });
+
+ Array.from(ModalSelect).forEach(select => {
+ if (!(select.getAttribute('data-ignore') === 'true')) {
+ if (!(select.getAttribute('data-parent'))) {
+ if (Settings[Modal.getAttribute('data-setting')][select.getAttribute('data-setting')] !== "undefined") {
+ select.selectedIndex = Settings[Modal.getAttribute('data-setting')][select.getAttribute('data-setting')]
+ }
+ } else {
+ let Parent = input.getAttribute('data-parent')
+ if (Settings[Modal.getAttribute('data-setting')][Parent][select.getAttribute('data-setting')] !== "undefined") {
+ if (!isNaN(parseInt(Parent))) {Parent = parseInt(Parent)}
+ select.selectedIndex = Settings[Modal.getAttribute('data-setting')][Parent][select.getAttribute('data-setting')]
+ }
+ }
+ }
+ });
+
+ Modal.showModal()
+ });
+ }
+
+ if (Select.length > 0) {
+ Array.from(Select).forEach(element => {
+ element.addEventListener('change', function() {
+ SetSetting(element.getAttribute('data-setting'), element, element.selectedIndex)
+ });
+ });
+ }
+ });
+ document.getElementById('ResetDefaults').addEventListener('click', function() {
+ ResetDefaultsModal.showModal();
+ });
+ document.getElementById('ResetDefaults-Modal-Yes').addEventListener('click', function() {
+ Settings = ExpectedSettings
+ Save()
+ setTimeout(function () {
+ LoadCurrent();
+ ResetDefaultsModal.close();
+ }, 400)
+ });
+ document.getElementById('ResetDefaults-Modal-No').addEventListener('click', function() {
+ ResetDefaultsModal.close();
+ });
+
+ function LoadCurrent() {
+ chrome.storage.sync.get(["PolyPlus_Settings"], function(result) {
+ Settings = MergeObjects(result.PolyPlus_Settings || ExpectedSettings, ExpectedSettings)
+
+ console.log(Settings)
+
+ Elements.forEach(element => {
+ let Status = element.getElementsByClassName('status')[0]
+ console.log(element, FormatBool(Settings[element.getElementsByTagName('button')[0].getAttribute('data-setting')]))
+ Status.innerText = FormatBool(Settings[element.getElementsByTagName('button')[0].getAttribute('data-setting')])
+ let SelectInput = element.getElementsByTagName('select')[0]
+ if (SelectInput) {
+ SelectInput.selectedIndex = Settings[SelectInput.getAttribute('data-setting')]
+ }
+ });
+ });
+ }
+ LoadCurrent();
+
+ function ToggleSetting(Name, Element) {
+ if (Settings[Name] === true) {
+ Settings[Name] = false;
+ } else {
+ Settings[Name] = true;
+ }
+
+ if (Element != null) {
+ Element.getElementsByClassName('status')[0].innerText = FormatBool(Settings[Name])
+ }
+ if (SaveBtn.getAttribute('disabled')) {
+ SaveBtn.removeAttribute('disabled')
+ }
+ }
+
+ function SetSetting(Name, Element, Value) {
+ console.log(Settings)
+ Settings[Name] = Value
+
+ if (SaveBtn.getAttribute('disabled')) {
+ SaveBtn.removeAttribute('disabled')
+ }
+ }
+
+ function Save() {
+ SaveBtn.setAttribute('disabled', 'true')
+ window.localStorage.setItem('PolyPlusSettings', JSON.stringify(Settings))
+ chrome.storage.sync.set({ 'PolyPlus_Settings': Settings, arrayOrder: true }, function() {
+ console.log('Saved successfully!');
+ });
+
+ console.log(Settings);
+ }
+
+ let LoadThemeFromJSONBtn = document.getElementById('LoadThemeFromJSONBtn')
+ let SaveThemeToJSONInput = document.getElementById('SaveThemeToJSONInput')
+ let CopyThemeJSONBtn = document.getElementById('CopyThemeJSONBtn')
+ LoadThemeFromJSONBtn.addEventListener('click', function(){
+ LoadThemeJSON(LoadThemeFromJSONBtn.previousElementSibling.value)
+ });
+ document.getElementById('ThemeCreator').getElementsByTagName('button')[1].addEventListener('click', function(){
+ SaveThemeToJSONInput.value = JSON.stringify(Settings.ThemeCreator)
+ });
+ CopyThemeJSONBtn.addEventListener('click', function(){
+ if (SaveThemeToJSONInput.value.length > 0) {
+ navigator.clipboard.writeText(SaveThemeToJSONInput.value)
+ }
+ });
+
+ let CurrencyDate = LoadFile(chrome.runtime.getURL('js/resources/currencies.json'), function(text){
+ CurrencyDate = new Date(JSON.parse(text).Date).toLocaleDateString("en-US", {day:"numeric",month:"long",year:"numeric"})
+
+ document.getElementById('IRLPriceWithCurrencyCurrency').previousElementSibling.children[1].innerText = document.getElementById('IRLPriceWithCurrencyCurrency').previousElementSibling.children[1].innerText.replace('[DATE]', CurrencyDate)
+ })
+
+ function LoadThemeJSON(string) {
+ try {
+ let JSONTable = JSON.parse(string)
+ if (JSONTable.length === ExpectedSettings.ThemeCreator.length) {
+ if (confirm('Are you sure you\'d like to replace this theme with the theme specified in the JSON?') === true) {
+ LoadThemeFromJSONBtn.previousElementSibling.value = ''
+ document.getElementById('ThemeCreator-Modal').close()
+ Settings.ThemeCreator = MergeObjects(JSONTable, ExpectedSettings.ThemeCreator)
+ Save();
+ console.log(JSONTable.length, JSONTable, 'applied')
+ document.getElementById('ThemeCreator').getElementsByTagName('button')[1].click();
+ }
+ } else {
+ alert('JSON is not a theme!')
+ //LoadThemeFromJSONBtn.innerText = 'JSON is too short or too long!'
+ //setTimeout(function () {LoadThemeFromJSONBtn.innerText = 'Load'}, 1250)
+ }
+ } catch (error) {
+ alert('JSON is invalid!')
+ //LoadThemeFromJSONBtn.innerText = 'JSON is invalid!'
+ //setTimeout(function () {LoadThemeFromJSONBtn.innerText = 'Load'}, 1250)
+ }
+ }
+
+ /*
+ 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];
+ } else if (obj1[key] !== obj2[key]) {
+ mergedObj[key] = obj2[key];
+ }
+ }
+
+ // Remove keys from mergedObj if they are not present in obj2
+ for (var key in mergedObj) {
+ if (!obj2.hasOwnProperty(key)) {
+ delete mergedObj[key];
+ }
+ }
+
+ return mergedObj;
+ }
+ */
+
+ 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;
+ }
+
+ function FormatBool(bool){
+ if (bool === true) {
+ return 'enabled'
+ } else {
+ return 'disabled'
+ }
+ }
+
+ function LoadFile(path, callback) {
+ var xhr = new XMLHttpRequest();
+ xhr.onload = function () { return callback(this.responseText); }
+ xhr.open("GET", path, true);
+ xhr.send();
+ }
+ }
+});
\ No newline at end of file
diff --git a/js/profile/profile.js b/js/profile/profile.js
new file mode 100755
index 0000000..9dfacf1
--- /dev/null
+++ b/js/profile/profile.js
@@ -0,0 +1,272 @@
+setTimeout(function() {}, 100);
+let URLSplit = window.location.pathname.split('/');
+let UserID = URLSplit[2];
+var Settings;
+var BestFriends;
+var FavoriteBtn;
+if (UserID) {
+ chrome.storage.sync.get(['PolyPlus_Settings'], function(result) {
+ Settings = result.PolyPlus_Settings;
+
+ if (Settings.IRLPriceWithCurrencyOn === true) {
+ HandleIRLPrice()
+ }
+
+ if (Settings.BestFriendsOn === true) {
+ HandleBestFriends()
+ }
+
+ if (1 === 1) {
+ HandleOufitCost()
+ }
+ });
+
+ // Update the local pinned games whenever the 'PinnedGames' array is updated
+ chrome.storage.onChanged.addListener(function(changes, namespace) {
+ if ('PolyPlus_BestFriends' in changes) {
+ chrome.storage.sync.get(['PolyPlus_BestFriends'], function(result) {
+ BestFriends = result.PolyPlus_BestFriends || [];
+
+ if (!(BestFriends.length === 7)) {
+ if (Array.isArray(BestFriends) && BestFriends.includes(parseInt(UserID))) {
+ FavoriteBtn.innerText = 'Remove Best Friend Status'
+ } else {
+ FavoriteBtn.innerText = 'Best Friend'
+ }
+ } else {
+ FavoriteBtn.innerText = 'Remove Best Friend Status (max 7/7)'
+ }
+ });
+ }
+ });
+
+ const UserID = window.location.pathname.split('/')[2]
+ const DefaultAvatar = {
+ "useCharacter": true,
+ "items": [],
+ "shirt": null,
+ "pants": null,
+ "tool": null,
+ "headColor": "#111111",
+ "torsoColor": "#111111",
+ "leftArmColor": "#111111",
+ "rightArmColor": "#111111",
+ "leftLegColor": "#111111",
+ "rightLegColor": "#111111",
+ "face": "https://c0.ptacdn.com/static/3dview/DefaultFace.png"
+ }
+ const Avatar = structuredClone(DefaultAvatar)
+
+ const Original = document.querySelector('.container .dropdown-item:nth-child(2)')
+ const Clone = Original.cloneNode(true)
+ Clone.classList.remove('text-danger')
+ Clone.classList.add('text-primary')
+ Clone.href = '#'
+ Clone.innerHTML = `
+
+ Copy 3D Avatar URL
+ `
+ Clone.addEventListener('click', function(){
+ fetch('https://api.polytoria.com/v1/users/:id/avatar'.replace(':id', UserID))
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network not ok')
+ }
+ return response.json()
+ })
+ .then(data => {
+ data.assets.forEach(item => {
+ switch(item.type) {
+ case 'hat':
+ Avatar.items.push(item.path)
+ break
+ case 'tool':
+ Avatar.tool = item.path
+ break
+ case 'face':
+ Avatar.face = item.path
+ break
+ case 'shirt':
+ Avatar.shirt = item.path
+ break
+ case 'pants':
+ Avatar.pants = item.path
+ break
+ }
+ });
+
+ Avatar.headColor = '#' + data.colors.head || '#cdcdcd'
+ Avatar.torsoColor = '#' + data.colors.torso || '#cdcdcd'
+ Avatar.leftArmColor = '#' + data.colors.leftArm || '#cdcdcd'
+ Avatar.rightArmColor = '#' + data.colors.rightArm || '#cdcdcd'
+ Avatar.leftLegColor = '#' + data.colors.leftLeg || '#cdcdcd'
+ Avatar.rightLegColor = '#' + data.colors.rightLeg || '#cdcdcd'
+
+ const URL = 'https://polytoria.com/ptstatic/itemview/#' + btoa(encodeURIComponent(JSON.stringify(Avatar)))
+ console.log('URL: ', URL)
+ navigator.clipboard.writeText(URL)
+ const SwalCopied = document.createElement('script')
+ SwalCopied.innerHTML = `
+ window.Swal.fire({title: "Copied", icon: "success", html: "The 3D avatar URL has been copied to clipboard!Preview it here! "})
+ `
+ document.body.prepend(SwalCopied)
+ SwalCopied.remove()
+ })
+ .catch(error => {
+ console.log(error)
+ });
+ });
+
+ Original.parentElement.appendChild(Clone)
+}
+
+function HandleIRLPrice() {
+ const NetWorthElement = document.getElementsByClassName('float-end text-success')[0];
+ const NetWorth = parseInt(NetWorthElement.innerText.replace(/,/g, ''));
+ let IRL;
+ let DISPLAY;
+ switch (Settings.IRLPriceWithCurrencyCurrency) {
+ case 0:
+ IRL = (NetWorth * 0.0099).toFixed(2)
+ DISPLAY = 'USD'
+ break
+ case 1:
+ IRL = (NetWorth * 0.009).toFixed(2)
+ DISPLAY = 'EUR'
+ break
+ case 2:
+ IRL = (NetWorth * 0.0131).toFixed(2)
+ DISPLAY = 'CAD'
+ break
+ case 3:
+ IRL = (NetWorth * 0.0077).toFixed(2)
+ DISPLAY = 'GBP'
+ break
+ case 4:
+ IRL = (NetWorth * 0.1691).toFixed(2)
+ DISPLAY = 'MXN'
+ break
+ case 5:
+ IRL = (NetWorth * 0.0144).toFixed(2)
+ DISPLAY = 'AUD'
+ break
+ case 6:
+ IRL = (NetWorth * 0.2338).toFixed(2)
+ DISPLAY = 'TRY'
+ break
+ }
+ NetWorthElement.innerText = NetWorthElement.innerText + " ($" + IRL + " " + DISPLAY + ")"
+}
+
+function HandleBestFriends() {
+ chrome.storage.sync.get(['PolyPlus_BestFriends'], function(result){
+ BestFriends = result.PolyPlus_BestFriends || [];
+
+ console.log('Best friends is enabled!')
+ FavoriteBtn = document.createElement('button');
+ FavoriteBtn.classList = 'btn btn-warning btn-sm ml-2';
+ if (!(BestFriends.length === 7)) {
+ if (Array.isArray(BestFriends) && BestFriends.includes(parseInt(UserID))) {
+ FavoriteBtn.innerText = 'Remove Best Friend Status';
+ } else {
+ FavoriteBtn.innerText = 'Best Friend';
+ }
+ } else {
+ FavoriteBtn.innerText = 'Remove Best Friend Status (max 7/7)'
+ }
+ if (UserID !== JSON.parse(window.localStorage.getItem('account_info')).ID && document.getElementById('add-friend-button').classList.contains('btn-success') === false) {
+ FavoriteBtn.addEventListener('click', function() {
+ Fav(UserID, FavoriteBtn);
+ });
+ } else {
+ FavoriteBtn.style.display = 'none'
+ }
+ document.querySelectorAll('.section-title.px-3.px-lg-0.mt-3')[0].appendChild(FavoriteBtn);
+
+ function Fav(UserID, btn) {
+ if (UserID === JSON.parse(window.localStorage.getItem('account_info')).ID) {
+ return
+ }
+ btn.setAttribute('disabled', 'true')
+ chrome.storage.sync.get(['PolyPlus_BestFriends'], function(result) {
+ const BestFriends = result.PolyPlus_BestFriends || [];
+ const index = BestFriends.indexOf(parseInt(UserID));
+ if (index !== -1) {
+ // Number exists, remove it
+ BestFriends.splice(index, 1);
+ btn.innerText = "Best Friend"
+ console.log('Number', parseInt(UserID), 'removed from BestFriends');
+ } else {
+ // Number doesn't exist, add it
+ BestFriends.push(parseInt(UserID));
+ btn.innerText = "Remove Best Friend Status"
+ console.log('Number', parseInt(UserID), 'added to BestFriends');
+ }
+
+ chrome.storage.sync.set({ 'PolyPlus_BestFriends': BestFriends, arrayOrder: true }, function() {
+ console.log('BestFriends saved successfully!');
+ setTimeout(function() {
+ btn.removeAttribute('disabled')
+ }, 1500)
+ });
+ });
+ }
+
+ function ClearFavs(){
+ chrome.storage.sync.set({ 'PolyPlus': {"PinnedGames": pinnedGames, "BestFriends": []}, arrayOrder: true }, function() {
+ console.log('BestFriends saved successfully!');
+ setTimeout(function() {
+ btn.removeAttribute('disabled')
+ }, 1500)
+ });
+ }
+
+ function ClearFavsOld(){
+ chrome.storage.sync.set({ 'PolyPlus': {"PinnedGames": pinnedGames, "BestFriends": []}, arrayOrder: true }, function() {
+ console.log('BestFriends saved successfully!');
+ setTimeout(function() {
+ btn.removeAttribute('disabled')
+ }, 1500)
+ });
+ }
+ });
+}
+
+async function HandleOufitCost() {
+ const AvatarRow = document.getElementsByClassName('d-flex flex-row flex-nowrap overflow-x-scroll px-3 px-lg-0 mb-2 mb-lg-0')[0]
+
+ let TotalCost = 0
+ let Limiteds = 0
+ let Exclusives = 0
+ for (let item of AvatarRow.children) {
+ const ItemID = item.getElementsByTagName('a')[0].href.split('/')[4]
+ await fetch('https://api.polytoria.com/v1/store/'+ItemID)
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network not ok')
+ }
+ return response.json()
+ })
+ .then(data => {
+ let Price = data.price
+ if (data.isLimited === true) {
+ Limiteds += 1
+ Price = data.averagePrice
+ } else if (data.sales === 0) {
+ Exclusives += 1
+ Price = 0
+ }
+
+ TotalCost += Price
+ })
+ .catch(error => {console.log(error)});
+ }
+
+ const TotalCostText = document.createElement('small')
+ TotalCostText.classList = 'text-muted'
+ TotalCostText.style.padding = '20px'
+ TotalCostText.innerHTML = `${ (Limiteds > 0 || Exclusives > 0) ? '~' : '' } ${TotalCost.toLocaleString()}${ (Limiteds > 0) ? ` (has ${Limiteds} limiteds)` : '' }${ (Exclusives > 0) ? ` (has ${Exclusives} exclusives)` : '' }`
+ AvatarRow.parentElement.parentElement.prepend(TotalCostText)
+ AvatarRow.parentElement.style.marginTop = '10px'
+ console.log(TotalCostText)
+}
\ No newline at end of file
diff --git a/js/profile/simplified-profile.js b/js/profile/simplified-profile.js
new file mode 100755
index 0000000..0fc46ff
--- /dev/null
+++ b/js/profile/simplified-profile.js
@@ -0,0 +1,20 @@
+let Username = window.location.href.split('/')[4]
+
+chrome.storage.sync.get(['PolyPlus_Settings'], function(result) {
+ Settings = result.PolyPlus_Settings;
+
+ if (Settings.SimplifiedProfileURLsOn === true) {
+ fetch("https://api.polytoria.com/v1/users/find?username=" + Username)
+ .then(response => response.json())
+ .then(data => {
+ window.location.href = "https://polytoria.com/users/" + data.id
+ })
+ .catch(error => {
+ console.log("An error occurred:", error);
+ });
+ }
+
+ if (!(parseInt(userID))) {
+ return
+ }
+});
\ No newline at end of file
diff --git a/js/resources/currencies.json b/js/resources/currencies.json
new file mode 100755
index 0000000..1633d0b
--- /dev/null
+++ b/js/resources/currencies.json
@@ -0,0 +1,59 @@
+{
+ "Date": "2023-7-17",
+ "Data": [
+ {
+ "USD": 0.009899999999999999,
+ "EUR": 0.011200000000000002,
+ "CAD": 0.0123,
+ "GBP": 0.008100000000000001,
+ "MXN": 0.1928,
+ "AUD": 0.014199999999999999,
+ "TRY": 0.1583
+ },
+ {
+ "USD": 0.009072727272727274,
+ "EUR": 0.010163636363636363,
+ "CAD": 0.011290909090909091,
+ "GBP": 0.007363636363636363,
+ "MXN": 0.17534545454545455,
+ "AUD": 0.013418181818181819,
+ "TRY": 0.14616363636363636
+ },
+ {
+ "USD": 0.00868695652173913,
+ "EUR": 0.009721739130434783,
+ "CAD": 0.010730434782608695,
+ "GBP": 0.007043478260869565,
+ "MXN": 0.1676521739130435,
+ "AUD": 0.012834782608695652,
+ "TRY": 0.13767826086956522
+ },
+ {
+ "USD": 0.009087272727272727,
+ "EUR": 0.00996,
+ "CAD": 0.010625454545454546,
+ "GBP": 0.006981818181818182,
+ "MXN": 0.17294545454545454,
+ "AUD": 0.012698181818181819,
+ "TRY": 0.14424
+ },
+ {
+ "USD": 0.008331666666666668,
+ "EUR": 0.009323333333333333,
+ "CAD": 0.00974,
+ "GBP": 0.006066666666666666,
+ "MXN": 0.15853333333333333,
+ "AUD": 0.012306666666666667,
+ "TRY": 0.13222
+ },
+ {
+ "USD": 0.0079992,
+ "EUR": 0.008950399999999999,
+ "CAD": 0.0093504,
+ "GBP": 0.005824,
+ "MXN": 0.152192,
+ "AUD": 0.011814400000000001,
+ "TRY": 0.12693120000000002
+ }
+ ]
+}
\ No newline at end of file
diff --git a/js/rewrites/everywhere2.js b/js/rewrites/everywhere2.js
new file mode 100755
index 0000000..e101b17
--- /dev/null
+++ b/js/rewrites/everywhere2.js
@@ -0,0 +1,374 @@
+const start = performance.now()
+var Settings;
+var ExpectedSettings = {
+ PinnedGamesOn: false,
+ ForumMentsOn: false,
+ BestFriendsOn: false,
+ ImprovedFrListsOn: false,
+ IRLPriceWithCurrencyOn: true,
+ IRLPriceWithCurrencyCurrency: 0,
+ IRLPriceWithCurrencyPackage: 0,
+ HideNotifBadgesOn: true,
+ SimplifiedProfileURLsOn: true,
+ StoreOwnTagOn: true,
+ ThemeCreatorOn: false,
+ ThemeCreator: {
+ BGColor: null,
+ BGImage: null,
+ BGImageSize: 'fit',
+ PrimaryTextColor: null,
+ SecondaryTextColor: null,
+ LinkTextColor: null,
+ WebsiteLogo: null
+ },
+ ModifyNavOn: false,
+ ModifyNav: [
+ {
+ Label: "Play",
+ 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,
+ ApplyMembershipThemeOn: false,
+ ApplyMembershipThemeTheme: 0,
+ ForumMarkOn: true,
+ MultiCancelOutTradesOn: true,
+ ItemWishlistOn: true,
+ HideUpgradeBtnOn: false
+}
+var Theme = null;
+
+// Merge settings and expected settings to make sure all keys exist
+let RawSettings = JSON.parse(window.localStorage.getItem('PolyPlusSettings')) || ExpectedSettings
+Settings = MergeObjects(RawSettings || ExpectedSettings, ExpectedSettings);
+chrome.storage.sync.get(["PolyPlus_Settings"], function(result) {
+ window.localStorage.setItem('PolyPlusSettings', JSON.stringify(result))
+});
+
+Theme = document.createElement('style')
+switch (Settings.ThemeCreator.BGImageSize) {
+case 0:
+ Settings.ThemeCreator.BGImageSize = 'fit'
+ break
+case 1:
+ Settings.ThemeCreator.BGImageSize = 'cover'
+ break
+case 2:
+ Settings.ThemeCreator.BGImageSize = 'contain'
+ break
+}
+Theme.innerHTML = `
+:root {
+ --polyplus-navbgcolor: ${Settings.ThemeCreator.NavBGColor};
+ --polyplus-navbordercolor: ${Settings.ThemeCreator.NavBorderColor};
+ --polyplus-navitemcolor: ${Settings.ThemeCreator.NavItemColor};
+ --polyplus-sidebarbgcolor: ${Settings.ThemeCreator.SideBGColor};
+ --polyplus-sidebarbordercolor: ${Settings.ThemeCreator.SideBorderColor};
+ --polyplus-sidebaritembgcolor: ${Settings.ThemeCreator.SideItemBGColor};
+ --polyplus-sidebaritembordercolor: ${Settings.ThemeCreator.SideItemBorderColor};
+ --polyplus-sidebaritemcolor: ${Settings.ThemeCreator.SideItemColor};
+ --polyplus-sidebaritemlabelcolor: ${Settings.ThemeCreator.SideItemLabelColor};
+ --polyplus-bgcolor: ${Settings.ThemeCreator.BGColor};
+ --polyplus-bgimage: url(${Settings.ThemeCreator.BGImage});
+ --polyplus-bgimagesize: ${Settings.ThemeCreator.BGImageSize};
+ --polyplus-primarytextcolor: ${Settings.ThemeCreator.PrimaryTextColor};
+ --polyplus-secondarytextcolor: ${Settings.ThemeCreator.SecondaryTextColor};
+ --polyplus-linktextcolor: ${Settings.ThemeCreator.LinkTextColor};
+ --polyplus-linkhoveredtextcolor: ${Settings.ThemeCreator.LinkHoveredTextColor};
+ --polyplus-linkfocusedtextcolor: ${Settings.ThemeCreator.LinkFocusedTextColor};
+ --polyplus-linkvisitedtextcolor: ${Settings.ThemeCreator.LinkVisitedTextColor};
+ --polyplus-cardheadbgcolor: ${Settings.ThemeCreator.CardHeadBGColor};
+ --polyplus-cardbodybgcolor: ${Settings.ThemeCreator.CardBodyBGColor};
+ --polyplus-cardbordercolor: ${Settings.ThemeCreator.CardBorderColor};
+}
+
+nav {
+ background-color: var(--polyplus-navbgcolor) !important;
+ border-bottom: 1px solid var(--polyplus-navbordercolor) !important;
+}
+
+.nav-sidebar {
+ background-color: var(--polyplus-sidebarbgcolor) !important;
+ border-right: 1px solid var(--polyplus-sidebarbordercolor) !important;
+}
+
+#app {
+ background-color: var(--polyplus-bgcolor) !important;
+ background-image: var(--polyplus-bgimage) !important;
+ background-size var(--polyplus-bgimagesize)
+ color: var(--polyplus-primarytextcolor) !important;
+}
+
+.text-muted {
+ color: var(--polyplus-secondarytextcolor) !important;
+}
+
+a {
+ color: var(--polyplus-linktextcolor) !important;
+}
+
+a:hover {
+ color: var(--polyplus-linkhoveredtextcolor) !important;
+}
+
+a:focus {
+ color: var(--polyplus-linkfocusedtextcolor) !important;
+}
+
+/*
+a:visited {
+ color: var(--polyplus-linkvisitedtextcolor) !important;
+}
+*/
+
+.card-header {
+ background-color: var(--polyplus-cardheadbgcolor) !important;
+}
+
+.card {
+ background-color: var(--polyplus-cardbodybgcolor) !important;
+ border-color: var(--polyplus-cardbordercolor) !important;
+}
+
+nav a.nav-link {
+ color: var(--polyplus-navitemcolor) !important;
+}
+
+.nav-sidebar .nav-sidebar-button {
+ background-color: var(--polyplus-sidebaritembgcolor) !important;
+ border-color: var(--polyplus-sidebaritembordercolor) !important;
+ color: var(--polyplus-sidebaritemcolor) !important;
+}
+
+.nav-sidebar-text {
+ color: var(--polyplus-sidebaritemlabelcolor) !important;
+}
+`
+
+
+document.addEventListener('DOMContentLoaded', function(){
+ // Check if Theme Exists, if so Load It
+ if (Settings.ThemeCreatorOn && Settings.ThemeCreatorOn === true) {
+ if (!(Settings.ThemeCreator.WebsiteLogo === null)) {
+ document.querySelector('.nav-sidebar img').setAttribute('src', Settings.ThemeCreator.WebsiteLogo)
+ }
+ }
+ let end;
+ if (Settings.ThemeCreatorOn && Settings.ThemeCreatorOn === true && Theme != null) {
+ end = performance.now()
+ document.body.prepend(Theme)
+ }
+ console.log(end - start)
+
+ // Define Data
+ var Username = document.querySelector('a.text-reset.text-decoration-none[href^="/users"]').innerText.replace(/\s+/g,'');
+ var UserID = document.querySelector('.text-reset.text-decoration-none[href^="/users/"]').getAttribute('href').split('/')[2]
+ var Bricks = document.querySelector('.brickBalanceCont').innerText.replace(/\s+/g,'');
+
+ document.body.setAttribute('data-username', Username)
+ document.body.setAttribute('data-id', UserID)
+ document.body.setAttribute('data-bricks', Bricks)
+ document.body.setAttribute('data-URL', window.location.href)
+
+ // Add PolyPlus Settings link to Sidebar
+ var parent = document.querySelector('ul.nav.nav-flush')
+ var clone = parent.querySelectorAll('li.nav-item')[0].cloneNode(true)
+ clone.querySelector('a').setAttribute('href', '/my/settings/polyplus')
+ clone.querySelector('span').innerText = "Poly+"
+ var icon = clone.querySelector('i')
+ var newIcon = document.createElement('i')
+ newIcon.classList = 'fa-regular fa-sparkles'
+ icon.parentElement.appendChild(newIcon)
+ icon.remove()
+ parent.appendChild(clone)
+
+ if (Settings.ModifyNavOn && Settings.ModifyNavOn === true) {
+ let NavbarItems = document.querySelectorAll('#main-content nav.navbar .nav-link')
+ let Needed = [NavbarItems[11],NavbarItems[12],NavbarItems[13],NavbarItems[14],NavbarItems[15]]
+ for (let i = 0; i < Settings.ModifyNav.length; i++) {
+ if (Settings.ModifyNav[i].Label != null) {
+ Needed[i].children[1].innerText = Settings.ModifyNav[i].Label
+ Needed[i].setAttribute('href', Settings.ModifyNav[i].Link)
+ }
+ }
+ }
+
+ if (Settings.HideUpgradeBtnOn && Settings.HideUpgradeBtnOn === true) {
+ document.querySelector('.nav-sidebar a[href="/upgrade"].nav-link.py-1.nav-sidebar-link').remove()
+ }
+
+ if (Settings.IRLPriceWithCurrencyOn && Settings.IRLPriceWithCurrencyOn === true) {
+ var IRL;
+ var DISPLAY;
+ switch (Settings.IRLPriceWithCurrencyCurrency) {
+ case 0:
+ IRL = (Bricks.replace(/,/g, '') * 0.0099).toFixed(2)
+ DISPLAY = 'USD'
+ break
+ case 1:
+ IRL = (Bricks.replace(/,/g, '') * 0.009).toFixed(2)
+ DISPLAY = 'EUR'
+ break
+ case 2:
+ IRL = (Bricks.replace(/,/g, '') * 0.0131).toFixed(2)
+ DISPLAY = 'CAD'
+ break
+ case 3:
+ IRL = (Bricks.replace(/,/g, '') * 0.0077).toFixed(2)
+ DISPLAY = 'GBP'
+ break
+ case 4:
+ IRL = (Bricks.replace(/,/g, '') * 0.1691).toFixed(2)
+ DISPLAY = 'MXN'
+ break
+ case 5:
+ IRL = (Bricks.replace(/,/g, '') * 0.0144).toFixed(2)
+ DISPLAY = 'AUD'
+ break
+ case 6:
+ IRL = (Bricks.replace(/,/g, '') * 0.2338).toFixed(2)
+ DISPLAY = 'TRY'
+ break
+ }
+ let BrickBalanceCount = document.querySelectorAll('.brickBalanceCount,.brickBalanceCont')
+ BrickBalanceCount.forEach(element => {
+ element.innerText = element.innerText + " ($" + IRL + " " + DISPLAY + ")"
+ });
+ }
+
+ if (Settings.HideNotifBadgesOn && Settings.HideNotifBadgesOn === true) {
+ document.querySelectorAll('.notif-nav.notif-sidebar').forEach(element => {element.remove();});
+ }
+});
+
+/*
+document.addEventListener('DOMContentLoaded', function() {
+ if (document.getElementsByClassName('card-header')[0] && document.getElementsByClassName('card-header')[0].innerText === ' Page not found') {
+ return
+ }
+
+ // Check if Theme Exists, if so Load It
+ if (Settings.ThemeCreatorOn && Settings.ThemeCreatorOn === true) {
+ if (!(Settings.ThemeCreator.WebsiteLogo === null)) {
+ document.querySelector('.nav-sidebar img').setAttribute('src', Settings.ThemeCreator.WebsiteLogo)
+ }
+ }
+ if (Settings.ThemeCreatorOn && Settings.ThemeCreatorOn === true && Theme != null) {
+ document.body.prepend(Theme)
+ }
+
+ // Define Data
+ var Username = document.querySelector('a.text-reset.text-decoration-none[href^="/users"]').innerText.replace(/\s+/g,'');
+ var UserID = document.querySelector('.text-reset.text-decoration-none[href^="/users/"]').getAttribute('href').split('/')[2]
+ var Bricks = document.querySelector('.brickBalanceCont').innerText.replace(/\s+/g,'');
+
+ document.body.setAttribute('data-username', Username)
+ document.body.setAttribute('data-id', UserID)
+ document.body.setAttribute('data-bricks', Bricks)
+ document.body.setAttribute('data-URL', window.location.href)
+
+ // Add PolyPlus Settings link to Sidebar
+ var parent = document.querySelector('ul.nav.nav-flush')
+ var clone = parent.querySelectorAll('li.nav-item')[0].cloneNode(true)
+ clone.querySelector('a').setAttribute('href', '/my/polyplus')
+ clone.querySelector('span').innerText = "Poly+"
+ var icon = clone.querySelector('i')
+ var newIcon = document.createElement('i')
+ newIcon.classList = 'fa-regular fa-sparkles'
+ icon.parentElement.appendChild(newIcon)
+ icon.remove()
+ parent.appendChild(clone)
+
+ if (Settings.ModifyNavOn && Settings.ModifyNavOn === true) {
+ let NavbarItems = document.querySelectorAll('#main-content nav.navbar .nav-link')
+ let Needed = [NavbarItems[11],NavbarItems[12],NavbarItems[13],NavbarItems[14],NavbarItems[15]]
+ for (let i = 0; i < Settings.ModifyNav.length; i++) {
+ if (Settings.ModifyNav[i].Label != null) {
+ Needed[i].children[1].innerText = Settings.ModifyNav[i].Label
+ Needed[i].setAttribute('href', Settings.ModifyNav[i].Link)
+ }
+ }
+ }
+
+ if (Settings.HideUpgradeBtnOn && Settings.HideUpgradeBtnOn === true) {
+ document.querySelector('.nav-sidebar a[href="/upgrade"].nav-link.py-1.nav-sidebar-link').remove()
+ }
+
+ if (Settings.IRLPriceWithCurrencyOn && Settings.IRLPriceWithCurrencyOn === true) {
+ var IRL;
+ var DISPLAY;
+ switch (Settings.IRLPriceWithCurrencyCurrency) {
+ case 0:
+ IRL = (Bricks.replace(/,/g, '') * 0.0099).toFixed(2)
+ DISPLAY = 'USD'
+ break
+ case 1:
+ IRL = (Bricks.replace(/,/g, '') * 0.009).toFixed(2)
+ DISPLAY = 'EUR'
+ break
+ case 2:
+ IRL = (Bricks.replace(/,/g, '') * 0.0131).toFixed(2)
+ DISPLAY = 'CAD'
+ break
+ case 3:
+ IRL = (Bricks.replace(/,/g, '') * 0.0077).toFixed(2)
+ DISPLAY = 'GBP'
+ break
+ case 4:
+ IRL = (Bricks.replace(/,/g, '') * 0.1691).toFixed(2)
+ DISPLAY = 'MXN'
+ break
+ case 5:
+ IRL = (Bricks.replace(/,/g, '') * 0.0144).toFixed(2)
+ DISPLAY = 'AUD'
+ break
+ case 6:
+ IRL = (Bricks.replace(/,/g, '') * 0.2338).toFixed(2)
+ DISPLAY = 'TRY'
+ break
+ }
+ let BrickBalanceCount = document.querySelectorAll('.brickBalanceCount,.brickBalanceCont')
+ BrickBalanceCount.forEach(element => {
+ element.innerText = element.innerText + " ($" + IRL + " " + DISPLAY + ")"
+ });
+ }
+
+ if (Settings.HideNotifBadgesOn && Settings.HideNotifBadgesOn === true) {
+ document.querySelectorAll('.notif-nav.notif-sidebar').forEach(element => {element.remove();});
+ }
+});
+*/
+
+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;
+}
\ No newline at end of file
diff --git a/js/rewrites/polyplus-settings.js b/js/rewrites/polyplus-settings.js
new file mode 100755
index 0000000..f0057d2
--- /dev/null
+++ b/js/rewrites/polyplus-settings.js
@@ -0,0 +1,883 @@
+document.body.innerHTML = `
+
+
+
+
+
Are you sure you'd like to reset all settings to their respective defaults? (this action is irreversible)
+
Yes
+
No
+
+
+
+
+
+
Unleash your creativity and customize the Polytoria website to your liking! (this feature is still in development)
+
+
+
+
Save Theme to JSON
+
+
+
Load Theme from JSON
+
+
Load
+
+
+
+
+
+
+
+
+
+
+
Primary Text Color
+
+
+
Secondary Text Color
+
+
+
+
+
+
+
+
+
+
+
+ Website Logo (URL)
+
+
+
+
+
Save
+
Cancel
+
+
+
+
+
+
Customize the navbar to your liking!
+
+
+
+
+
+
+
+
Save
+
Cancel
+
+
+
+
<- go back
+
Poly+ Settings
+
[CategoryName]
+
+
+ Pinned Games (enabled )
+ Toggle
+
+
+ Pin your favorite games to the top of the homepage!
+
+
+
+ Forum Mentions (disabled )
+ Toggle
+
+
+ Get a quick link to the popular person everyone is talking about's profile!
+
+
+
+ Best Friends (enabled )
+ Toggle
+
+
+ Prioritize the bestest of friends on applicable friend lists!
+
+
+
+ Improved Friend Lists (enabled )
+ Toggle
+
+
+
+ Accept or decline all friend requests with the click of a button or multi-remove existing friends!
+
+ * You can only remove up to 25 friends at once.
+
+
+
+
+ Show IRL price with Brick Count (enabled )
+ Toggle
+
+
+
+ See the real life currency value along with Bricks across the site!
+
+ * Currencies were calculated on [DATE].
+
+ * Currencies other than USD are purely approximations.
+
+
+ United States Dollar (USD)
+ Euro (EUR)
+ Canadian Dollar (CAD)
+ Great British Pound (GBP)
+ Mexican Peso (MXN)
+ Australian Dollar (AUD)
+ Turkish Lira (TRY)
+
+
+
+ $0.99 USD
+ $4.99 USD
+ $9.99 USD
+ $24.99 USD
+ $49.99 USD
+ $99.99 USD
+
+
+
+
+ Hide Notification Badges (disabled )
+ Toggle
+
+
+ Hide the annoying red circles on the sidebar!
+
+
+
+ Simplified Profile URLs (enabled )
+ Toggle
+
+
+ Makes all profile URLs simpler by allowing for you to go to "https://polytoria.com/profile/UsernameGoesHere" to redirect to the real profile URL!
+
+
+
+ Show "OWNED" Tag on Store Main Page (enabled )
+ Toggle
+
+
+ Quickly see if you own the item at a glance with a little tag in the top left corner of item cards on the main store page!
+
+
+
+ Theme Creator (disabled )
+ Toggle
+ Options
+
+
+ Unleash your creativity and customize the Polytoria website to your liking! (this feature is still in development)
+
+
+
+ More Search Filters (enabled )
+ Toggle
+
+
+ Easily find what you're looking for with more search filters side-wide! (this does not affect the main site search on the navbar)
+
+
+
+ Apply Membership Theme for Free (disabled )
+ Toggle
+
+
+ Ever want the fancy membership themes for completely free ? Well now you can get apply them site-wide!
+
+ Plus
+ Plus Deluxe
+
+
+
+
+ Forum Markdown (disabled )
+ Toggle
+
+
+
+ Format forum posts to make them look epic!
+
+
+
+
+ Multi-Cancel Outbound Trades (enabled )
+ Toggle
+
+
+
+ Quickly cancel several out-bound trades (trades that you have sent) all at once
+
+ * You can only cancel up to 10 trades at once.
+
+
+
+
+ Modify Navbar (disabled )
+ Toggle
+ Options
+
+
+
+ Customize the navbar to your liking!
+
+
+
+
+ Item Wishlist (enabled )
+ Toggle
+
+
+
+ Wishlist that item that you REALLY want!
+
+
+
+
+ Hide Upgrade Button (disabled )
+ Toggle
+
+
+ Hide the ugly blue "Upgrade" button on the sidebar!
+
+
+
Save
+
Reset to Default Settings
+
made by Index
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+var Settings;
+var SaveBtn = document.getElementById('Save')
+var Elements = [
+ document.getElementById("PinnedGames"),
+ document.getElementById("ForumMentions"),
+ document.getElementById("BestFriends"),
+ document.getElementById("ImprovedFriendLists"),
+ document.getElementById("IRLPriceWithCurrency"),
+ document.getElementById("HideNotifBadges"),
+ document.getElementById("SimplifiedProfileURLs"),
+ document.getElementById("StoreOwnTag"),
+ document.getElementById("ThemeCreator"),
+ document.getElementById("MoreSearchFilters"),
+ document.getElementById("ApplyMembershipTheme"),
+ document.getElementById("MultiCancelOutTrades"),
+ document.getElementById("ModifyNav"),
+ document.getElementById("ItemWishlist"),
+ document.getElementById("HideUpgradeBtn")
+];
+var ExpectedSettings = {
+ PinnedGamesOn: true,
+ ForumMentsOn: false,
+ BestFriendsOn: true,
+ ImprovedFrListsOn: true,
+ IRLPriceWithCurrencyOn: true,
+ IRLPriceWithCurrencyCurrency: 0,
+ IRLPriceWithCurrencyPackage: 0,
+ HideNotifBadgesOn: false,
+ SimplifiedProfileURLsOn: true,
+ StoreOwnTagOn: true,
+ ThemeCreatorOn: false,
+ ThemeCreator: {
+ BGColor: null,
+ BGImage: null,
+ BGImageSize: 'fit',
+ PrimaryTextColor: null,
+ SecondaryTextColor: null,
+ LinkTextColor: null,
+ WebsiteLogo: null
+ },
+ ModifyNavOn: false,
+ ModifyNav: [
+ {
+ Label: "Play",
+ 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,
+ ApplyMembershipThemeOn: false,
+ ApplyMembershipThemeTheme: 0,
+ MultiCancelOutTradesOn: true,
+ ItemWishlistOn: true,
+ HideUpgradeBtnOn: false
+}
+
+var ResetDefaultsModal = document.getElementById('ResetDefaults-Modal')
+var ThemeCreatorModal = {
+ Modal: document.getElementById('ThemeCreator-Modal'),
+ Save: document.getElementById('ThemeCreator-Modal-Save'),
+ BGColor: document.getElementById('ThemeCreator-Modal-BGColor'),
+ BGImage: document.getElementById('ThemeCreator-Modal-BGImage'),
+ BGImageSize: document.getElementById('ThemeCreator-Modal-BGImageSize'),
+ PrimaryTextColor: document.getElementById('ThemeCreator-Modal-PrimaryTextColor'),
+ SecondaryTextColor: document.getElementById('ThemeCreator-Modal-SecondaryTextColor'),
+ LinkTextColor: document.getElementById('ThemeCreator-Modal-LinkTextColor'),
+ WebsiteLogo: document.getElementById('ThemeCreator-Modal-WebsiteLogo')
+}
+var ModifyNavModal = {
+ Modal: document.getElementById('ModifyNav-Modal'),
+ Save: document.getElementById('ModifyNav-Modal-Save'),
+ "1Label": document.getElementById('ModifyNav-Modal-1Label'),
+ "1Link": document.getElementById('ModifyNav-Modal-1Link'),
+ "2Label": document.getElementById('ModifyNav-Modal-2Label'),
+ "2Link": document.getElementById('ModifyNav-Modal-2Link'),
+ "3Label": document.getElementById('ModifyNav-Modal-3Label'),
+ "3Link": document.getElementById('ModifyNav-Modal-3Link'),
+ "4Label": document.getElementById('ModifyNav-Modal-4Label'),
+ "4Link": document.getElementById('ModifyNav-Modal-4Link'),
+ "5Label": document.getElementById('ModifyNav-Modal-5Label'),
+ "5Link": document.getElementById('ModifyNav-Modal-5Link'),
+}
+SaveBtn.addEventListener("click", function() {
+ Save();
+});
+Elements.forEach(element => {
+ let Button = element.getElementsByTagName('button')[0]
+ let Options = element.getElementsByTagName('button')[1]
+ let Select = element.getElementsByTagName('select') || []
+
+ if (Button) {
+ Button.addEventListener('click', function() {
+ console.log('button clicked!!!!')
+ ToggleSetting(Button.getAttribute('data-setting'), element)
+ });
+ }
+
+ if (Options) {
+ Options.addEventListener('click', function() {
+ let Modal = document.getElementById(Options.getAttribute('data-modal') + '-Modal')
+ let ModalButtons = Modal.getElementsByTagName('button')
+ let ModalInputs = Modal.getElementsByTagName('input')
+ let ModalSelect = Modal.getElementsByTagName('select')
+
+ Array.from(ModalButtons).forEach(btn => {
+ if (!(btn.getAttribute('data-ignore') === 'true')) {
+ btn.addEventListener('click', function(){
+ let Setting = btn.getAttribute('data-setting')
+ if (Setting === '[save]') {
+ Array.from(ModalInputs).forEach(input => {
+ if (!(input.getAttribute('data-ignore') === 'true')) {
+ if (!(input.getAttribute('data-parent'))) {
+ Settings[Modal.getAttribute('data-setting')][input.getAttribute('data-setting')] = input.value || null
+ } else {
+ let Parent = input.getAttribute('data-parent')
+ if (!isNaN(parseInt(Parent))) {Parent = parseInt(Parent)}
+ Settings[Modal.getAttribute('data-setting')][Parent][input.getAttribute('data-setting')] = input.value || null
+ }
+ }
+ });
+ Array.from(ModalSelect).forEach(select => {
+ if (!(select.getAttribute('data-ignore') === 'true')) {
+ if (!(select.getAttribute('data-parent'))) {
+ Settings[Modal.getAttribute('data-setting')][select.getAttribute('data-setting')] = select.selectedIndex
+ } else {
+ let Parent = input.getAttribute('data-parent')
+ if (!isNaN(parseInt(Parent))) {Parent = parseInt(Parent)}
+ Settings[Modal.getAttribute('data-setting')][Parent][select.getAttribute('data-setting')] = select.selectedIndex
+ }
+ }
+ });
+ Save();
+ setTimeout(function () {
+ LoadCurrent();
+ Modal.close();
+ }, 400)
+ } else if (Setting === '[cancel]') {
+ Modal.close();
+ } else if (Setting === '[callback]') {
+ let Function = btn.getAttribute('data-onclick')
+ if (window[Function] && typeof(window[Function]) === 'function') {
+ console.log('is')
+ window[Function]()
+ }
+ } else {
+ if (!(btn.getAttribute('data-parent'))) {
+ ToggleSetting(Modal.getAttribute('data-setting')[btn.getAttribute('data-setting')], null)
+ } else {
+ let Parent = input.getAttribute('data-parent')
+ if (!isNaN(parseInt(Parent))) {Parent = parseInt(Parent)}
+ ToggleSetting(Modal.getAttribute('data-setting')[Parent][btn.getAttribute('data-setting')], null)
+ }
+ }
+ });
+ }
+ });
+
+ Array.from(ModalInputs).forEach(input => {
+ if (!(input.getAttribute('data-ignore') === 'true')) {
+ if (!(input.getAttribute('data-parent'))) {
+ if (Settings[Modal.getAttribute('data-setting')][input.getAttribute('data-setting')] !== "undefined") {
+ input.value = Settings[Modal.getAttribute('data-setting')][input.getAttribute('data-setting')]
+ }
+ } else {
+ let Parent = input.getAttribute('data-parent')
+ if (Settings[Modal.getAttribute('data-setting')][Parent][input.getAttribute('data-setting')] !== "undefined") {
+ if (!isNaN(parseInt(Parent))) {Parent = parseInt(Parent)}
+ input.value = Settings[Modal.getAttribute('data-setting')][Parent][input.getAttribute('data-setting')]
+ }
+ }
+ }
+ });
+
+ Array.from(ModalSelect).forEach(select => {
+ if (!(select.getAttribute('data-ignore') === 'true')) {
+ if (!(select.getAttribute('data-parent'))) {
+ if (Settings[Modal.getAttribute('data-setting')][select.getAttribute('data-setting')] !== "undefined") {
+ select.selectedIndex = Settings[Modal.getAttribute('data-setting')][select.getAttribute('data-setting')]
+ }
+ } else {
+ let Parent = input.getAttribute('data-parent')
+ if (Settings[Modal.getAttribute('data-setting')][Parent][select.getAttribute('data-setting')] !== "undefined") {
+ if (!isNaN(parseInt(Parent))) {Parent = parseInt(Parent)}
+ select.selectedIndex = Settings[Modal.getAttribute('data-setting')][Parent][select.getAttribute('data-setting')]
+ }
+ }
+ }
+ });
+
+ Modal.showModal()
+ });
+ }
+
+ if (Select.length > 0) {
+ Array.from(Select).forEach(element => {
+ element.addEventListener('change', function() {
+ SetSetting(element.getAttribute('data-setting'), element, element.selectedIndex)
+ });
+ });
+ }
+});
+document.getElementById('ResetDefaults').addEventListener('click', function() {
+ ResetDefaultsModal.showModal();
+});
+document.getElementById('ResetDefaults-Modal-Yes').addEventListener('click', function() {
+ Settings = ExpectedSettings
+ Save()
+ setTimeout(function () {
+ LoadCurrent();
+ ResetDefaultsModal.close();
+ }, 400)
+});
+document.getElementById('ResetDefaults-Modal-No').addEventListener('click', function() {
+ ResetDefaultsModal.close();
+});
+
+function LoadCurrent() {
+ chrome.storage.sync.get(["PolyPlus_Settings"], function(result) {
+ Settings = MergeObjects(result.PolyPlus_Settings || ExpectedSettings, ExpectedSettings)
+
+ console.log(Settings)
+
+ Elements.forEach(element => {
+ let Status = element.getElementsByClassName('status')[0]
+ console.log(element, FormatBool(Settings[element.getElementsByTagName('button')[0].getAttribute('data-setting')]))
+ Status.innerText = FormatBool(Settings[element.getElementsByTagName('button')[0].getAttribute('data-setting')])
+ let SelectInput = element.getElementsByTagName('select')[0]
+ if (SelectInput) {
+ SelectInput.selectedIndex = Settings[SelectInput.getAttribute('data-setting')]
+ }
+ });
+ });
+}
+LoadCurrent();
+
+function ToggleSetting(Name, Element) {
+ if (Settings[Name] === true) {
+ Settings[Name] = false;
+ } else {
+ Settings[Name] = true;
+ }
+
+ if (Element != null) {
+ Element.getElementsByClassName('status')[0].innerText = FormatBool(Settings[Name])
+ }
+ if (SaveBtn.getAttribute('disabled')) {
+ SaveBtn.removeAttribute('disabled')
+ }
+}
+
+function SetSetting(Name, Element, Value) {
+ console.log(Settings)
+ Settings[Name] = Value
+
+ if (SaveBtn.getAttribute('disabled')) {
+ SaveBtn.removeAttribute('disabled')
+ }
+}
+
+function Save() {
+ SaveBtn.setAttribute('disabled', 'true')
+ chrome.storage.sync.set({ 'PolyPlus_Settings': Settings, arrayOrder: true }, function() {
+ console.log('Saved successfully!');
+ });
+
+ console.log(Settings);
+}
+
+let LoadThemeFromJSONBtn = document.getElementById('LoadThemeFromJSONBtn')
+let SaveThemeToJSONInput = document.getElementById('SaveThemeToJSONInput')
+let CopyThemeJSONBtn = document.getElementById('CopyThemeJSONBtn')
+LoadThemeFromJSONBtn.addEventListener('click', function(){
+ LoadThemeJSON(LoadThemeFromJSONBtn.previousElementSibling.value)
+});
+document.getElementById('ThemeCreator').getElementsByTagName('button')[1].addEventListener('click', function(){
+ SaveThemeToJSONInput.value = JSON.stringify(Settings.ThemeCreator)
+});
+CopyThemeJSONBtn.addEventListener('click', function(){
+ if (SaveThemeToJSONInput.value.length > 0) {
+ navigator.clipboard.writeText(SaveThemeToJSONInput.value)
+ }
+});
+
+let CurrencyDate =
+LoadFile(chrome.runtime.getURL('js/resources/currencies.json'), function(text){
+ CurrencyDate = new Date(JSON.parse(text).Date).toLocaleDateString("en-US", {day:"numeric",month:"long",year:"numeric"})
+
+ document.getElementById('IRLPriceWithCurrencyCurrency').previousElementSibling.children[1].innerText = document.getElementById('IRLPriceWithCurrencyCurrency').previousElementSibling.children[1].innerText.replace('[DATE]', CurrencyDate)
+})
+
+function LoadThemeJSON(string) {
+ try {
+ let JSONTable = JSON.parse(string)
+ if (JSONTable.length === ExpectedSettings.ThemeCreator.length) {
+ if (confirm('Are you sure you\'d like to replace this theme with the theme specified in the JSON?') === true) {
+ LoadThemeFromJSONBtn.previousElementSibling.value = ''
+ document.getElementById('ThemeCreator-Modal').close()
+ Settings.ThemeCreator = MergeObjects(JSONTable, ExpectedSettings.ThemeCreator)
+ Save();
+ console.log(JSONTable.length, JSONTable, 'applied')
+ document.getElementById('ThemeCreator').getElementsByTagName('button')[1].click();
+ }
+ } else {
+ alert('JSON is not a theme!')
+ //LoadThemeFromJSONBtn.innerText = 'JSON is too short or too long!'
+ //setTimeout(function () {LoadThemeFromJSONBtn.innerText = 'Load'}, 1250)
+ }
+ } catch (error) {
+ alert('JSON is invalid!')
+ //LoadThemeFromJSONBtn.innerText = 'JSON is invalid!'
+ //setTimeout(function () {LoadThemeFromJSONBtn.innerText = 'Load'}, 1250)
+ }
+}
+
+/*
+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];
+ } else if (obj1[key] !== obj2[key]) {
+ mergedObj[key] = obj2[key];
+ }
+ }
+
+ // Remove keys from mergedObj if they are not present in obj2
+ for (var key in mergedObj) {
+ if (!obj2.hasOwnProperty(key)) {
+ delete mergedObj[key];
+ }
+ }
+
+ return mergedObj;
+}
+*/
+
+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;
+}
+
+function FormatBool(bool){
+ if (bool === true) {
+ return 'enabled'
+ } else {
+ return 'disabled'
+ }
+}
+
+function LoadFile(path, callback) {
+ var xhr = new XMLHttpRequest();
+ xhr.onload = function () { return callback(this.responseText); }
+ xhr.open("GET", path, true);
+ xhr.send();
+}
\ No newline at end of file
diff --git a/js/store/item-view.js b/js/store/item-view.js
new file mode 100755
index 0000000..1da702f
--- /dev/null
+++ b/js/store/item-view.js
@@ -0,0 +1,139 @@
+var ItemID = window.location.pathname.split('/')[2]
+var ItemWishlist;
+var WishlistBtn;
+
+setTimeout(function () {
+ if (!(window.location.href.split('/')[4])) {return}
+ chrome.storage.sync.get(['PolyPlus_Settings'], function(result){
+ var Settings = result.PolyPlus_Settings;
+ let PurchaseBtn = document.querySelector('.btn.btn-outline-success')
+ if (Settings.IRLPriceWithCurrencyOn === true){
+ if (!(PurchaseBtn.getAttribute('disabled'))) {
+ let Price = PurchaseBtn.getAttribute('data-price').replace(/,/g, '')
+ let Span = document.createElement('span')
+ Span.classList = 'text-muted polyplus-own-tag'
+ Span.style.fontSize = '0.7rem'
+ Span.style.fontWeight = 'normal'
+ let IRL;
+ let DISPLAY;
+ switch (Settings.IRLPriceWithCurrencyCurrency) {
+ case 0:
+ IRL = (Price * 0.0099).toFixed(2)
+ DISPLAY = 'USD'
+ break
+ case 1:
+ IRL = (Price * 0.009).toFixed(2)
+ DISPLAY = 'EUR'
+ break
+ case 2:
+ IRL = (Price * 0.0131).toFixed(2)
+ DISPLAY = 'CAD'
+ break
+ case 3:
+ IRL = (Price * 0.0077).toFixed(2)
+ DISPLAY = 'GBP'
+ break
+ case 4:
+ IRL = (Price * 0.1691).toFixed(2)
+ DISPLAY = 'MXN'
+ break
+ case 5:
+ IRL = (Price * 0.0144).toFixed(2)
+ DISPLAY = 'AUD'
+ break
+ case 6:
+ IRL = (Price * 0.2338).toFixed(2)
+ DISPLAY = 'TRY'
+ break
+ }
+ Span.innerText = "($" + IRL + " " + DISPLAY + ")"
+ PurchaseBtn.appendChild(Span)
+ }
+ }
+
+ if (Settings.ItemWishlistOn === true && !(PurchaseBtn.getAttribute('disabled'))) {
+ let DescriptionText = document.querySelector('.card-text')
+ WishlistBtn = document.createElement('button')
+ chrome.storage.sync.get(['PolyPlus_ItemWishlist'], function(result){
+ ItemWishlist = result.PolyPlus_ItemWishlist || [];
+
+ if (Array.isArray(ItemWishlist) && ItemWishlist.includes(parseInt(ItemID))) {
+ WishlistBtn.classList = 'btn btn-danger btn-sm'
+ WishlistBtn.innerHTML = `
+ Un-Wishlist Item
+ `
+ } else {
+ WishlistBtn.classList = 'btn btn-primary btn-sm'
+ WishlistBtn.innerHTML = `
+ Wishlist Item
+ `
+ }
+
+ WishlistBtn.addEventListener('click', function(){
+ Wishlist()
+ });
+
+ DescriptionText.appendChild(document.createElement('br'))
+ DescriptionText.appendChild(WishlistBtn)
+
+ function Wishlist() {
+ WishlistBtn.setAttribute('disabled', true)
+ chrome.storage.sync.get(['PolyPlus_ItemWishlist'], function(result){
+ ItemWishlist = result.PolyPlus_ItemWishlist || [];
+
+ let i = ItemWishlist.indexOf(parseInt(ItemID))
+ console.log(i)
+ if (i !== -1) {
+ ItemWishlist.splice(i, 1)
+ WishlistBtn.classList = 'btn btn-primary btn-sm'
+ WishlistBtn.innerHTML = `
+ Wishlist Item
+ `
+ } else {
+ ItemWishlist.push(parseInt(ItemID))
+ WishlistBtn.classList = 'btn btn-danger btn-sm'
+ WishlistBtn.innerHTML = `
+ Un-Wishlist Item
+ `
+ }
+
+ chrome.storage.sync.set({'PolyPlus_ItemWishlist': ItemWishlist, arrayOrder: true}, function() {
+ setTimeout(function() {
+ WishlistBtn.removeAttribute('disabled')
+ }, 1250)
+ });
+ });
+ }
+ });
+ }
+ })
+}, 100)
+
+chrome.storage.onChanged.addListener(function(changes, namespace) {
+ if ('PolyPlus_ItemWishlist' in changes) {
+ chrome.storage.sync.get(['PolyPlus_ItemWishlist'], function(result) {
+ ItemWishlist = result.PolyPlus_ItemWishlist || [];
+
+ if (Array.isArray(ItemWishlist) && ItemWishlist.includes(parseInt(ItemID))) {
+ WishlistBtn.classList = 'btn btn-danger btn-sm'
+ WishlistBtn.innerHTML = `
+ Un-Wishlist Item
+ `
+ } else {
+ if (!(ItemWishlist.length === 25)) {
+ WishlistBtn.removeAttribute('disabled')
+ WishlistBtn.classList = 'btn btn-primary btn-sm'
+ WishlistBtn.innerHTML = `
+ Wishlist Item
+ `
+ } else {
+ WishlistBtn.setAttribute('disabled', true)
+ WishlistBtn.classList = 'btn btn-primary btn-sm'
+ WishlistBtn.innerHTML = `
+ Wishlist Item
+ `
+ }
+ }
+ });
+ }
+});
\ No newline at end of file
diff --git a/js/store/store.js b/js/store/store.js
new file mode 100755
index 0000000..7dfb80a
--- /dev/null
+++ b/js/store/store.js
@@ -0,0 +1,123 @@
+setTimeout(function () {}, 100)
+var Settings = {IRLPriceWithCurrencyOn: true, IRLPriceWithCurrencyCurrency: 0, StoreOwnTagOn: true};
+var UserID = JSON.parse(window.localStorage.getItem('account_info')).ID
+var ItemGrid = document.getElementById('assets')
+var Inventory = [];
+chrome.storage.sync.get(['PolyPlus_Settings'], function(result){
+ Settings = result.PolyPlus_Settings;
+});
+
+function Update() {
+ if (Settings.IRLPriceWithCurrencyOn === true) {
+ Array.from(ItemGrid.children).forEach(element => {LoadIRLPrices(element)});
+ }
+}
+
+const observer = new MutationObserver(async function (list){
+ for (const record of list) {
+ console.log('record')
+ for (const element of record.addedNodes) {
+ console.log('element', element.tagName, element.classList)
+ if (element.tagName === "DIV" && element.classList.value === 'mb-3 itemCardCont') {
+ if (Settings.IRLPriceWithCurrencyOn === true) {LoadIRLPrices(element)}
+ if (Settings.StoreOwnTagOn === true) {
+ if (Inventory.length === 0) {
+ await fetch("https://api.polytoria.com/v1/users/:id/inventory".replace(':id', UserID))
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network not ok')
+ }
+ return response.json()
+ })
+ .then(data => {
+ Inventory = data.data;
+ LoadOwnedTags(element)
+ return
+ })
+ .catch(error => {
+ console.log(error)
+ });
+ } else {
+ LoadOwnedTags(element)
+ }
+ }
+ }
+ }
+ observer.observe(ItemGrid, {attributes: false,childList: true,subtree: false});
+ }
+});
+
+observer.observe(ItemGrid, {attributes: false,childList: true,subtree: false});
+
+function LoadIRLPrices(element) {
+ if (element.tagName != "DIV") {return}
+ if (element.querySelector('small.text-primary')) {return}
+ let Parent = element.getElementsByTagName('small')[1]
+ if (Parent.innerText === "") {
+ return
+ }
+ let Span = document.createElement('span')
+ Span.classList = 'text-muted polyplus-price-tag'
+ Span.style.fontSize = '0.7rem'
+ let Price = parseInt(Parent.innerText.replace(/,/g, ''))
+ var IRL;
+ var DISPLAY;
+ switch (Settings.IRLPriceWithCurrencyCurrency) {
+ case 0:
+ IRL = (Price * 0.0099).toFixed(2)
+ DISPLAY = 'USD'
+ break
+ case 1:
+ IRL = (Price * 0.009).toFixed(2)
+ DISPLAY = 'EUR'
+ break
+ case 2:
+ IRL = (Price * 0.0131).toFixed(2)
+ DISPLAY = 'CAD'
+ break
+ case 3:
+ IRL = (Price * 0.0077).toFixed(2)
+ DISPLAY = 'GBP'
+ break
+ case 4:
+ IRL = (Price * 0.1691).toFixed(2)
+ DISPLAY = 'MXN'
+ break
+ case 5:
+ IRL = (Price * 0.0144).toFixed(2)
+ DISPLAY = 'AUD'
+ break
+ case 6:
+ IRL = (Price * 0.2338).toFixed(2)
+ DISPLAY = 'TRY'
+ break
+ }
+ Span.innerText = "($" + IRL + " " + DISPLAY + ")"
+ Parent.appendChild(Span)
+}
+
+function LoadOwnedTags(element) {
+ let Item = CheckInventory(parseInt(element.querySelector('[href^="/store/"]').getAttribute('href').split('/')[2]))
+ console.log(Item, Item.id)
+ if (Item.id) {
+ var Tag = document.createElement('span')
+ Tag.classList = 'badge bg-primary polyplus-own-tag'
+ Tag.setAttribute('style', 'position: absolute;font-size: 0.7rem;top: 0px;left: 0px;padding: 5.5px;border-top-left-radius: var(--bs-border-radius-lg)!important;border-top-right-radius: 0px;border-bottom-left-radius: 0px;font-size: 0.65rem;')
+ if (Item.asset.isLimited === false) {
+ Tag.innerText = "owned"
+ } else {
+ Tag.innerHTML = 'owned#' + Item.serial
+ }
+ element.querySelector('img').parentElement.appendChild(Tag)
+ }
+}
+
+function CheckInventory(id) {
+ let Item = {}
+ Inventory.forEach(element => {
+ if (element.asset.id === id) {
+ Item = element
+ }
+ })
+ return Item
+}
\ No newline at end of file
diff --git a/js/store/try-on.js b/js/store/try-on.js
new file mode 100755
index 0000000..2f6a8c5
--- /dev/null
+++ b/js/store/try-on.js
@@ -0,0 +1,148 @@
+let Avatar = {
+ "useCharacter": true,
+ "items": [],
+ "shirt": "https://c0.ptacdn.com/assets/uWrrnFGwgNN5W171vqYTWY7E639rKiXK.png",
+ "pants": "https://c0.ptacdn.com/assets/HD6TFdXD8CaflRNmd84VCNyNsmTB0SH3.png",
+ "headColor": "#e0e0e0",
+ "torsoColor": "#e0e0e0",
+ "leftArmColor": "#e0e0e0",
+ "rightArmColor": "#e0e0e0",
+ "leftLegColor": "#e0e0e0",
+ "rightLegColor": "#e0e0e0"
+}
+
+const Style = document.createElement('style')
+Style.innerHTML = `
+html:has(.polyplus-modal[open]), body:has(.polyplus-modal[open]) {
+ overflow: hidden;
+}
+
+.polyplus-modal::backdrop {
+ background: rgba(0, 0, 0, 0.73);
+}
+`
+document.body.prepend(Style)
+
+const ItemType = document.getElementsByClassName('px-4 px-lg-0 text-muted text-uppercase mb-3')[0].innerText.toLowerCase().split(' ')[1]
+const ItemThumbnail = document.getElementsByClassName('store-thumbnail')[0]
+const IFrame = document.getElementsByClassName('store-thumbnail-3d')[0]
+const TryIFrame = document.createElement('iframe')
+TryIFrame.setAttribute('style', 'width: 100%; height: auto; aspect-ratio: 1; border-radius: 20px;')
+
+const TryOnBtn = document.createElement('button')
+TryOnBtn.classList = 'btn btn-outline-warning'
+TryOnBtn.setAttribute('style', 'position: absolute; bottom: 15px;')
+TryOnBtn.innerHTML = ' '
+TryOnBtn.addEventListener('click', function (){
+ TryOnModal.showModal()
+});
+if (typeof(document.getElementsByClassName('3dviewtoggler')[0]) === 'object') {
+ TryOnBtn.style.right = '60px'
+} else {
+ TryOnBtn.style.right = '10px'
+}
+
+let TryOnModal = document.createElement('dialog')
+TryOnModal.classList = 'polyplus-modal'
+TryOnModal.setAttribute('style', 'width: 450px; border: 1px solid #484848; background-color: #181818; border-radius: 20px; overflow: hidden;')
+TryOnModal.innerHTML = `
+
+
Preview
+ Try on this item!
+
+
+ Close
+
+`
+
+document.body.prepend(TryOnModal)
+ItemThumbnail.parentElement.appendChild(TryOnBtn)
+TryOnModal.children[1].prepend(TryIFrame)
+
+fetch("https://api.polytoria.com/v1/users/:id/avatar".replace(':id', JSON.parse(window.localStorage.getItem('account_info')).ID))
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network response was not ok');
+ }
+ return response.json();
+ })
+ .then(data => {
+ data.assets.forEach(item => {
+ switch (item.type) {
+ case 'hat':
+ Avatar.items[Avatar.items.length] = item.path || ''
+ break
+ case 'face':
+ Avatar.face = item.path || ''
+ break
+ case 'tool':
+ Avatar.tool = item.path || ''
+ break
+ case 'shirt':
+ Avatar.shirt = item.path || ''
+ break
+ case 'pants':
+ Avatar.pants = item.path || ''
+ break
+ }
+ });
+
+ Avatar.headColor = "#" + data.colors.head
+ Avatar.torsoColor = "#" + data.colors.torso
+ Avatar.leftArmColor = "#" + data.colors.leftArm
+ Avatar.rightArmColor = "#" + data.colors.rightArm
+ Avatar.leftLegColor = "#" + data.colors.leftLeg
+ Avatar.rightLegColor = "#" + data.colors.rightLeg
+
+ if (ItemType === 'hat' || ItemType === 'tool') {
+ fetch("https://api.polytoria.com/v1/assets/serve-mesh/:id".replace(':id', window.location.pathname.split('/')[2]))
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network response was not ok');
+ }
+ return response.json();
+ })
+ .then(data => {
+ if (ItemType === 'hat') {
+ Avatar.items[Avatar.items.length] = data.url
+ } else if (ItemType === 'tool') {
+ Avatar.tool = data.url
+ }
+
+ console.log(Avatar)
+ TryIFrame.src = 'https://polytoria.com/ptstatic/itemview/#' + btoa(encodeURIComponent(JSON.stringify(Avatar)))
+ })
+ .catch(error => {
+ console.error('Fetch error:', error);
+ });
+ } else {
+ fetch("https://api.polytoria.com/v1/assets/serve/:id/Asset".replace(':id', window.location.pathname.split('/')[2]))
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network response was not ok');
+ }
+ return response.json();
+ })
+ .then(data => {
+ switch (ItemType) {
+ case 'shirt':
+ Avatar.shirt = data.url
+ break
+ case 'pants':
+ Avatar.pants = data.url
+ break
+ case 'face':
+ Avatar.face = data.url
+ break
+ }
+
+ TryIFrame.src = 'https://polytoria.com/ptstatic/itemview/#' + btoa(encodeURIComponent(JSON.stringify(Avatar)))
+ })
+ .catch(error => {
+ console.error('Fetch error:', error);
+ });
+ }
+ })
+ .catch(error => {
+ console.error('Fetch error:', error);
+ });
\ No newline at end of file
diff --git a/js/trick-or-treat.js b/js/trick-or-treat.js
new file mode 100755
index 0000000..9d6620e
--- /dev/null
+++ b/js/trick-or-treat.js
@@ -0,0 +1,13 @@
+// This was for the limited time 2023 halloween event
+const HauntedStudsCount = document.querySelector('[href="/event/active"] .brickBalanceCount')
+if (HauntedStudsCount !== null) {
+ HauntedStudsCount.innerHTML = HauntedStudsCount.innerHTML + ` (${parseInt(HauntedStudsCount.innerText) / 8} candies)`
+}
+
+if (window.location.pathname === '/event/trick-o-toria-2023') {
+ const LeaderboardRows = document.getElementsByClassName('leaderboard-row')
+ Array.from(LeaderboardRows).forEach(row => {
+ const _HauntedStudsCount = row.querySelector('span[style^="color:#cd60ff;"]')
+ _HauntedStudsCount.innerHTML = _HauntedStudsCount.innerHTML + `(${parseFloat(_HauntedStudsCount.innerText.replace(/,/g, '')) / 8} candies) `
+ });
+}
\ No newline at end of file
diff --git a/manifest.json b/manifest.json
new file mode 100755
index 0000000..3d22041
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,151 @@
+{
+ "manifest_version": 3,
+ "name": "Poly+",
+ "version": "1.0",
+ "version_name": "Beta",
+ "description": "This extension adds quality of life improvements and features to Polytoria's website.",
+ "permissions": ["storage", "contextMenus", "tabs", "scripting", "webNavigation"],
+ "content_scripts": [
+ {
+ "matches": ["https://polytoria.com/*"],
+ "js": ["/js/everywhere.js","/js/membership-themes.js"],
+ "css": ["/css/specific.css"],
+ "run_at": "document_start"
+ },
+
+ {
+ "matches": ["https://polytoria.com/my/settings/*"],
+ "js": ["/js/polyplus-settings.js"],
+ "run_at": "document_start"
+ },
+
+ {
+ "matches": ["https://polytoria.com/", "https://polytoria.com/home"],
+ "js": ["/js/account/home.js"],
+ "run_at": "document_idle"
+ },
+
+ {
+ "matches": ["https://polytoria.com/places/**"],
+ "js": ["/js/places/place-view.js"]
+ },
+
+ {
+ "matches": ["https://polytoria.com/join-place/**"],
+ "js": ["/js/places/place-join.js"]
+ },
+
+ {
+ "matches": ["https://polytoria.com/create/place/**"],
+ "js": ["/js/places/place-edit.js"]
+ },
+
+ {
+ "matches": ["https://polytoria.com/forum/post/**"],
+ "js": ["/js/forum/new-forum-view.js"]
+ },
+
+ {
+ "matches": ["https://polytoria.com/users/**"],
+ "js": ["/js/profile/profile.js"]
+ },
+
+ {
+ "matches": ["https://polytoria.com/profile/**"],
+ "js": ["/js/profile/simplified-profile.js"],
+ "run_at": "document_start"
+ },
+
+ {
+ "matches": ["https://polytoria.com/my/friends", "https://polytoria.com/my/friends/"],
+ "js": ["/js/account/friends.js"]
+ },
+
+ {
+ "matches": ["https://polytoria.com/store", "https://polytoria.com/store/"],
+ "js": ["/js/store/store.js"]
+ },
+
+ {
+ "matches": ["https://polytoria.com/store/**"],
+ "js": ["/js/store/item-view.js", "/js/store/try-on.js"]
+ },
+
+ {
+ "matches": ["https://polytoria.com/forum/search","https://polytoria.com/forum/search?*"],
+ "js": ["/js/forum/forum-search.js"]
+ },
+
+ {
+ "matches": ["https://polytoria.com/trade/sent/*"],
+ "js": ["/js/account/trades-outbound.js"]
+ },
+
+ {
+ "matches": ["https://polytoria.com/users/*/inventory/*"],
+ "js": ["/js/account/inventory.js"],
+ "run_at": "document_idle"
+ },
+
+ {
+ "matches": ["https://polytoria.com/create/","https://polytoria.com/create/place"],
+ "js": ["/js/account/create.js"],
+ "run_at": "document_idle"
+ },
+
+ {
+ "matches": ["https://polytoria.com/my/settings/privacy"],
+ "js": ["/js/account/settings-privacy.js"]
+ },
+
+ {
+ "matches": ["https://polytoria.com/my/settings/transactions"],
+ "js": ["/js/account/transactions.js"]
+ },
+
+ {
+ "matches": ["https://polytoria.com/store/**", "https://polytoria.com/places/**", "https://polytoria.com/guilds/**", "https://polytoria.com/feed/**"],
+ "js": ["/js/op-comments.js"]
+ },
+
+ {
+ "matches": ["https://polytoria.com/my/avatar?sandbox=true"],
+ "js": ["/js/account/avatar-sandbox2.js"]
+ }
+ ],
+ "background": {
+ "service_worker": "/js/background.js",
+ "type": "module"
+ },
+ "host_permissions": [
+ "https://*.polytoria.com/*"
+ ],
+ "web_accessible_resources": [
+ {
+ "resources": ["js/resources/currencies.json", "settings.html", "settings.js"],
+ "matches": ["https://polytoria.com/*"]
+ },
+
+ {
+ "resources": ["js/account/avatar-sandbox.html"],
+ "matches": ["https://polytoria.com/*"]
+ }
+ ],
+ "short_name": "Poly+",
+ "action": {
+ "default_popup": "popup.html",
+ "default_title": "Poly+",
+ "default_icon": {
+ "16": "/icon.png",
+ "32": "/icon.png",
+ "48": "/icon.png",
+ "128": "/icon.png"
+ }
+ },
+ "icons": {
+ "16": "/icon.png",
+ "32": "/icon.png",
+ "48": "/icon.png",
+ "128": "/icon.png"
+ }
+}
\ No newline at end of file
diff --git a/popup.html b/popup.html
new file mode 100755
index 0000000..591a634
--- /dev/null
+++ b/popup.html
@@ -0,0 +1,13 @@
+
+
+
+ Poly+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/settings.html b/settings.html
new file mode 100755
index 0000000..468b9cd
--- /dev/null
+++ b/settings.html
@@ -0,0 +1,507 @@
+
+
+ Poly+ Settings
+
+
+
+
+
+
+
Are you sure you'd like to reset all settings to their respective defaults? (this action is irreversible)
+
Yes
+
No
+
+
+
+
+
+
Unleash your creativity and customize the Polytoria website to your liking! (this feature is still in development)
+
+
+
+
Save Theme to JSON
+
+
+
Load Theme from JSON
+
+
Load
+
+
+
+
+
+
+
+
+
+
+
Primary Text Color
+
+
+
Secondary Text Color
+
+
+
+
+
+
+
+
+
+
+
+ Website Logo (URL)
+
+
+
+
+
Save
+
Cancel
+
+
+
+
+
+
Customize the navbar to your liking!
+
+
+
+
+
+
+
+
Save
+
Cancel
+
+
+
+
+
+ Pinned Games (enabled )
+ Toggle
+
+
+ Pin your favorite games to the top of the homepage!
+
+
+
+ Forum Mentions (disabled )
+ Toggle
+
+
+ Get a quick link to the popular person everyone is talking about's profile!
+
+
+
+ Best Friends (enabled )
+ Toggle
+
+
+ Prioritize the bestest of friends on applicable friend lists!
+
+
+
+ Improved Friend Lists (enabled )
+ Toggle
+
+
+
+ Accept or decline all friend requests with the click of a button or multi-remove existing friends!
+
+ * You can only remove up to 25 friends at once.
+
+
+
+
+ Show IRL price with Brick Count (enabled )
+ Toggle
+
+
+
+ See the real life currency value along with Bricks across the site!
+
+ * Currencies were calculated on [DATE].
+
+ * Currencies other than USD are purely approximations.
+
+
+ United States Dollar (USD)
+ Euro (EUR)
+ Canadian Dollar (CAD)
+ Great British Pound (GBP)
+ Mexican Peso (MXN)
+ Australian Dollar (AUD)
+ Turkish Lira (TRY)
+
+
+
+ $0.99 USD
+ $4.99 USD
+ $9.99 USD
+ $24.99 USD
+ $49.99 USD
+ $99.99 USD
+
+
+
+
+ Hide Notification Badges (disabled )
+ Toggle
+
+
+ Hide the annoying red circles on the sidebar!
+
+
+
+ Simplified Profile URLs (enabled )
+ Toggle
+
+
+ Makes all profile URLs simpler by allowing for you to go to "https://polytoria.com/profile/UsernameGoesHere" to redirect to the real profile URL!
+
+
+
+ Show "OWNED" Tag on Store Main Page (enabled )
+ Toggle
+
+
+ Quickly see if you own the item at a glance with a little tag in the top left corner of item cards on the main store page!
+
+
+
+ Theme Creator (disabled )
+ Toggle
+ Options
+
+
+ Unleash your creativity and customize the Polytoria website to your liking! (this feature is still in development)
+
+
+
+ More Search Filters (enabled )
+ Toggle
+
+
+ Easily find what you're looking for with more search filters side-wide! (this does not affect the main site search on the navbar)
+
+
+
+ Apply Membership Theme for Free (disabled )
+ Toggle
+
+
+ Ever want the fancy membership themes for completely free ? Well now you can get apply them site-wide!
+
+ Plus
+ Plus Deluxe
+
+
+
+
+ Forum Markdown (disabled )
+ Toggle
+
+
+
+ Format forum posts to make them look epic!
+
+
+
+
+ Multi-Cancel Outbound Trades (enabled )
+ Toggle
+
+
+
+ Quickly cancel several out-bound trades (trades that you have sent) all at once
+
+ * You can only cancel up to 10 trades at once.
+
+
+
+
+ Modify Navbar (disabled )
+ Toggle
+ Options
+
+
+
+ Customize the navbar to your liking!
+
+
+
+
+ Item Wishlist (enabled )
+ Toggle
+
+
+
+ Wishlist that item that you REALLY want!
+
+
+
+
+ Hide Upgrade Button (disabled )
+ Toggle
+
+
+ Hide the ugly blue "Upgrade" button on the sidebar!
+
+
+
Save
+
Reset to Default Settings
+
made by Index
+
+
+
+
\ No newline at end of file
diff --git a/settings.js b/settings.js
new file mode 100755
index 0000000..588bb50
--- /dev/null
+++ b/settings.js
@@ -0,0 +1,390 @@
+var Settings;
+var SaveBtn = document.getElementById('Save')
+var Elements = [
+ document.getElementById("PinnedGames"),
+ document.getElementById("ForumMentions"),
+ document.getElementById("BestFriends"),
+ document.getElementById("ImprovedFriendLists"),
+ document.getElementById("IRLPriceWithCurrency"),
+ document.getElementById("HideNotifBadges"),
+ document.getElementById("SimplifiedProfileURLs"),
+ document.getElementById("StoreOwnTag"),
+ document.getElementById("ThemeCreator"),
+ document.getElementById("MoreSearchFilters"),
+ document.getElementById("ApplyMembershipTheme"),
+ document.getElementById("MultiCancelOutTrades"),
+ document.getElementById("ModifyNav"),
+ document.getElementById("ItemWishlist"),
+ document.getElementById("HideUpgradeBtn")
+];
+var ExpectedSettings = {
+ PinnedGamesOn: true,
+ ForumMentsOn: false,
+ BestFriendsOn: true,
+ ImprovedFrListsOn: true,
+ IRLPriceWithCurrencyOn: true,
+ IRLPriceWithCurrencyCurrency: 0,
+ IRLPriceWithCurrencyPackage: 0,
+ HideNotifBadgesOn: false,
+ SimplifiedProfileURLsOn: true,
+ StoreOwnTagOn: true,
+ ThemeCreatorOn: false,
+ ThemeCreator: {
+ BGColor: null,
+ BGImage: null,
+ BGImageSize: 'fit',
+ PrimaryTextColor: null,
+ SecondaryTextColor: null,
+ LinkTextColor: null,
+ WebsiteLogo: null
+ },
+ ModifyNavOn: false,
+ ModifyNav: [
+ {
+ Label: "Play",
+ 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,
+ ApplyMembershipThemeOn: false,
+ ApplyMembershipThemeTheme: 0,
+ MultiCancelOutTradesOn: true,
+ ItemWishlistOn: true,
+ HideUpgradeBtnOn: false
+}
+
+var ResetDefaultsModal = document.getElementById('ResetDefaults-Modal')
+var ThemeCreatorModal = {
+ Modal: document.getElementById('ThemeCreator-Modal'),
+ Save: document.getElementById('ThemeCreator-Modal-Save'),
+ BGColor: document.getElementById('ThemeCreator-Modal-BGColor'),
+ BGImage: document.getElementById('ThemeCreator-Modal-BGImage'),
+ BGImageSize: document.getElementById('ThemeCreator-Modal-BGImageSize'),
+ PrimaryTextColor: document.getElementById('ThemeCreator-Modal-PrimaryTextColor'),
+ SecondaryTextColor: document.getElementById('ThemeCreator-Modal-SecondaryTextColor'),
+ LinkTextColor: document.getElementById('ThemeCreator-Modal-LinkTextColor'),
+ WebsiteLogo: document.getElementById('ThemeCreator-Modal-WebsiteLogo')
+}
+var ModifyNavModal = {
+ Modal: document.getElementById('ModifyNav-Modal'),
+ Save: document.getElementById('ModifyNav-Modal-Save'),
+ "1Label": document.getElementById('ModifyNav-Modal-1Label'),
+ "1Link": document.getElementById('ModifyNav-Modal-1Link'),
+ "2Label": document.getElementById('ModifyNav-Modal-2Label'),
+ "2Link": document.getElementById('ModifyNav-Modal-2Link'),
+ "3Label": document.getElementById('ModifyNav-Modal-3Label'),
+ "3Link": document.getElementById('ModifyNav-Modal-3Link'),
+ "4Label": document.getElementById('ModifyNav-Modal-4Label'),
+ "4Link": document.getElementById('ModifyNav-Modal-4Link'),
+ "5Label": document.getElementById('ModifyNav-Modal-5Label'),
+ "5Link": document.getElementById('ModifyNav-Modal-5Link'),
+}
+SaveBtn.addEventListener("click", function() {
+ Save();
+});
+Elements.forEach(element => {
+ let Button = element.getElementsByTagName('button')[0]
+ let Options = element.getElementsByTagName('button')[1]
+ let Select = element.getElementsByTagName('select') || []
+
+ if (Button) {
+ Button.addEventListener('click', function() {
+ console.log('button clicked!!!!')
+ ToggleSetting(Button.getAttribute('data-setting'), element)
+ });
+ }
+
+ if (Options) {
+ Options.addEventListener('click', function() {
+ let Modal = document.getElementById(Options.getAttribute('data-modal') + '-Modal')
+ let ModalButtons = Modal.getElementsByTagName('button')
+ let ModalInputs = Modal.getElementsByTagName('input')
+ let ModalSelect = Modal.getElementsByTagName('select')
+
+ Array.from(ModalButtons).forEach(btn => {
+ if (!(btn.getAttribute('data-ignore') === 'true')) {
+ btn.addEventListener('click', function(){
+ let Setting = btn.getAttribute('data-setting')
+ if (Setting === '[save]') {
+ Array.from(ModalInputs).forEach(input => {
+ if (!(input.getAttribute('data-ignore') === 'true')) {
+ if (!(input.getAttribute('data-parent'))) {
+ Settings[Modal.getAttribute('data-setting')][input.getAttribute('data-setting')] = input.value || null
+ } else {
+ let Parent = input.getAttribute('data-parent')
+ if (!isNaN(parseInt(Parent))) {Parent = parseInt(Parent)}
+ Settings[Modal.getAttribute('data-setting')][Parent][input.getAttribute('data-setting')] = input.value || null
+ }
+ }
+ });
+ Array.from(ModalSelect).forEach(select => {
+ if (!(select.getAttribute('data-ignore') === 'true')) {
+ if (!(select.getAttribute('data-parent'))) {
+ Settings[Modal.getAttribute('data-setting')][select.getAttribute('data-setting')] = select.selectedIndex
+ } else {
+ let Parent = input.getAttribute('data-parent')
+ if (!isNaN(parseInt(Parent))) {Parent = parseInt(Parent)}
+ Settings[Modal.getAttribute('data-setting')][Parent][select.getAttribute('data-setting')] = select.selectedIndex
+ }
+ }
+ });
+ Save();
+ setTimeout(function () {
+ LoadCurrent();
+ Modal.close();
+ }, 400)
+ } else if (Setting === '[cancel]') {
+ Modal.close();
+ } else if (Setting === '[callback]') {
+ let Function = btn.getAttribute('data-onclick')
+ if (window[Function] && typeof(window[Function]) === 'function') {
+ console.log('is')
+ window[Function]()
+ }
+ } else {
+ if (!(btn.getAttribute('data-parent'))) {
+ ToggleSetting(Modal.getAttribute('data-setting')[btn.getAttribute('data-setting')], null)
+ } else {
+ let Parent = input.getAttribute('data-parent')
+ if (!isNaN(parseInt(Parent))) {Parent = parseInt(Parent)}
+ ToggleSetting(Modal.getAttribute('data-setting')[Parent][btn.getAttribute('data-setting')], null)
+ }
+ }
+ });
+ }
+ });
+
+ Array.from(ModalInputs).forEach(input => {
+ if (!(input.getAttribute('data-ignore') === 'true')) {
+ if (!(input.getAttribute('data-parent'))) {
+ if (Settings[Modal.getAttribute('data-setting')][input.getAttribute('data-setting')] !== "undefined") {
+ input.value = Settings[Modal.getAttribute('data-setting')][input.getAttribute('data-setting')]
+ }
+ } else {
+ let Parent = input.getAttribute('data-parent')
+ if (Settings[Modal.getAttribute('data-setting')][Parent][input.getAttribute('data-setting')] !== "undefined") {
+ if (!isNaN(parseInt(Parent))) {Parent = parseInt(Parent)}
+ input.value = Settings[Modal.getAttribute('data-setting')][Parent][input.getAttribute('data-setting')]
+ }
+ }
+ }
+ });
+
+ Array.from(ModalSelect).forEach(select => {
+ if (!(select.getAttribute('data-ignore') === 'true')) {
+ if (!(select.getAttribute('data-parent'))) {
+ if (Settings[Modal.getAttribute('data-setting')][select.getAttribute('data-setting')] !== "undefined") {
+ select.selectedIndex = Settings[Modal.getAttribute('data-setting')][select.getAttribute('data-setting')]
+ }
+ } else {
+ let Parent = input.getAttribute('data-parent')
+ if (Settings[Modal.getAttribute('data-setting')][Parent][select.getAttribute('data-setting')] !== "undefined") {
+ if (!isNaN(parseInt(Parent))) {Parent = parseInt(Parent)}
+ select.selectedIndex = Settings[Modal.getAttribute('data-setting')][Parent][select.getAttribute('data-setting')]
+ }
+ }
+ }
+ });
+
+ Modal.showModal()
+ });
+ }
+
+ if (Select.length > 0) {
+ Array.from(Select).forEach(element => {
+ element.addEventListener('change', function() {
+ SetSetting(element.getAttribute('data-setting'), element, element.selectedIndex)
+ });
+ });
+ }
+});
+document.getElementById('ResetDefaults').addEventListener('click', function() {
+ ResetDefaultsModal.showModal();
+});
+document.getElementById('ResetDefaults-Modal-Yes').addEventListener('click', function() {
+ Settings = ExpectedSettings
+ Save()
+ setTimeout(function () {
+ LoadCurrent();
+ ResetDefaultsModal.close();
+ }, 400)
+});
+document.getElementById('ResetDefaults-Modal-No').addEventListener('click', function() {
+ ResetDefaultsModal.close();
+});
+
+function LoadCurrent() {
+ chrome.storage.sync.get(["PolyPlus_Settings"], function(result) {
+ Settings = MergeObjects(result.PolyPlus_Settings || ExpectedSettings, ExpectedSettings)
+
+ console.log(Settings)
+
+ Elements.forEach(element => {
+ let Status = element.getElementsByClassName('status')[0]
+ console.log(element, FormatBool(Settings[element.getElementsByTagName('button')[0].getAttribute('data-setting')]))
+ Status.innerText = FormatBool(Settings[element.getElementsByTagName('button')[0].getAttribute('data-setting')])
+ let SelectInput = element.getElementsByTagName('select')[0]
+ if (SelectInput) {
+ SelectInput.selectedIndex = Settings[SelectInput.getAttribute('data-setting')]
+ }
+ });
+ });
+}
+LoadCurrent();
+
+function ToggleSetting(Name, Element) {
+ if (Settings[Name] === true) {
+ Settings[Name] = false;
+ } else {
+ Settings[Name] = true;
+ }
+
+ if (Element != null) {
+ Element.getElementsByClassName('status')[0].innerText = FormatBool(Settings[Name])
+ }
+ if (SaveBtn.getAttribute('disabled')) {
+ SaveBtn.removeAttribute('disabled')
+ }
+}
+
+function SetSetting(Name, Element, Value) {
+ console.log(Settings)
+ Settings[Name] = Value
+
+ if (SaveBtn.getAttribute('disabled')) {
+ SaveBtn.removeAttribute('disabled')
+ }
+}
+
+function Save() {
+ SaveBtn.setAttribute('disabled', 'true')
+ chrome.storage.sync.set({ 'PolyPlus_Settings': Settings, arrayOrder: true }, function() {
+ console.log('Saved successfully!');
+ });
+
+ console.log(Settings);
+}
+
+let LoadThemeFromJSONBtn = document.getElementById('LoadThemeFromJSONBtn')
+let SaveThemeToJSONInput = document.getElementById('SaveThemeToJSONInput')
+let CopyThemeJSONBtn = document.getElementById('CopyThemeJSONBtn')
+LoadThemeFromJSONBtn.addEventListener('click', function(){
+ LoadThemeJSON(LoadThemeFromJSONBtn.previousElementSibling.value)
+});
+document.getElementById('ThemeCreator').getElementsByTagName('button')[1].addEventListener('click', function(){
+ SaveThemeToJSONInput.value = JSON.stringify(Settings.ThemeCreator)
+});
+CopyThemeJSONBtn.addEventListener('click', function(){
+ if (SaveThemeToJSONInput.value.length > 0) {
+ navigator.clipboard.writeText(SaveThemeToJSONInput.value)
+ }
+});
+
+let CurrencyDate =
+LoadFile(chrome.runtime.getURL('js/resources/currencies.json'), function(text){
+ CurrencyDate = new Date(JSON.parse(text).Date).toLocaleDateString("en-US", {day:"numeric",month:"long",year:"numeric"})
+
+ document.getElementById('IRLPriceWithCurrencyCurrency').previousElementSibling.children[1].innerText = document.getElementById('IRLPriceWithCurrencyCurrency').previousElementSibling.children[1].innerText.replace('[DATE]', CurrencyDate)
+})
+
+function LoadThemeJSON(string) {
+ try {
+ let JSONTable = JSON.parse(string)
+ if (JSONTable.length === ExpectedSettings.ThemeCreator.length) {
+ if (confirm('Are you sure you\'d like to replace this theme with the theme specified in the JSON?') === true) {
+ LoadThemeFromJSONBtn.previousElementSibling.value = ''
+ document.getElementById('ThemeCreator-Modal').close()
+ Settings.ThemeCreator = MergeObjects(JSONTable, ExpectedSettings.ThemeCreator)
+ Save();
+ console.log(JSONTable.length, JSONTable, 'applied')
+ document.getElementById('ThemeCreator').getElementsByTagName('button')[1].click();
+ }
+ } else {
+ alert('JSON is not a theme!')
+ //LoadThemeFromJSONBtn.innerText = 'JSON is too short or too long!'
+ //setTimeout(function () {LoadThemeFromJSONBtn.innerText = 'Load'}, 1250)
+ }
+ } catch (error) {
+ alert('JSON is invalid!')
+ //LoadThemeFromJSONBtn.innerText = 'JSON is invalid!'
+ //setTimeout(function () {LoadThemeFromJSONBtn.innerText = 'Load'}, 1250)
+ }
+}
+
+/*
+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];
+ } else if (obj1[key] !== obj2[key]) {
+ mergedObj[key] = obj2[key];
+ }
+ }
+
+ // Remove keys from mergedObj if they are not present in obj2
+ for (var key in mergedObj) {
+ if (!obj2.hasOwnProperty(key)) {
+ delete mergedObj[key];
+ }
+ }
+
+ return mergedObj;
+}
+*/
+
+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;
+}
+
+function FormatBool(bool){
+ if (bool === true) {
+ return 'enabled'
+ } else {
+ return 'disabled'
+ }
+}
+
+function LoadFile(path, callback) {
+ var xhr = new XMLHttpRequest();
+ xhr.onload = function () { return callback(this.responseText); }
+ xhr.open("GET", path, true);
+ xhr.send();
+}
\ No newline at end of file