[GC] - TP Enhancements

Tp

  1. // ==UserScript==
  2. // @name [GC] - TP Enhancements
  3. // @namespace https://gf.qytechs.cn/en/users/1225524-kaitlin
  4. // @match https://www.grundos.cafe/island/tradingpost/*
  5. // @version 1.3.2
  6. // @license MIT
  7. // @description
  8. // @author Cupkait
  9. // @icon https://i.imgur.com/4Hm2e6z.png
  10. // @description Tp
  11. // ==/UserScript==
  12.  
  13.  
  14.  
  15.  
  16. function pageCheck() {
  17. const headerCheck = document.querySelector('.trading_post > div.header').textContent.trim();
  18.  
  19. if (headerCheck === 'Create a New Lot') {
  20. initiateNewTrade();
  21. } else if (headerCheck === 'Your Lots') {
  22. generateCancelButtons();
  23. generateSortElement();
  24. } else if (headerCheck === 'Select Your Search Criteria') {
  25. generateUserDropdown();
  26. } else if (headerCheck === 'Offers You Have Made') {
  27. } else if (headerCheck === 'Offers on Lot') {
  28. } else if (headerCheck.startsWith('Make an Offer on Lot')) {
  29.  
  30. } else {
  31. error();
  32. }
  33. }
  34.  
  35. pageCheck();
  36.  
  37.  
  38.  
  39. function addGlobalStyles(){
  40. const tradeStyles = document.createElement('style');
  41. //Insert any CSS styling that applies to newly created elements, etc.
  42. tradeStyles.innerHTML = `
  43. .user-dropdown {
  44. display: block;
  45. position: absolute;
  46. top: 100%;
  47. left: 100%;
  48. background-color: var(--bgcolor);
  49. box-shadow: 0 8px 16px 0 rgba(0,0,0,.2);
  50. z-index: 2;
  51. min-width: 150px;
  52. padding: 0;
  53. border: 1px solid var(--color);
  54. border-radius: 5px;
  55. overflow: hidden;
  56. }
  57. .user-icon {
  58. cursor: pointer;
  59. }
  60.  
  61. .user-dropdown p {
  62. font-size: 12px;
  63. padding-left: 10px;}
  64. .cancelbtn, #sortSelect {
  65. margin:5px;
  66. width:47%;
  67. box-sizing: border-box;
  68. font-family: inherit;
  69. font-size: inherit;
  70. font-weight: normal;
  71. line-height: 1.5em;
  72. min-height: 1.5em;
  73. }
  74. .createbtn {
  75. margin:5px;
  76. width:75%;
  77. box-sizing: border-box;
  78. font-family: inherit;
  79. font-size: inherit;
  80. font-weight: normal;
  81. line-height: 1.5em;
  82. min-height: 1.5em;
  83. }
  84. .trade-lot {
  85. border-top: 2px solid black;
  86. }
  87.  
  88. #tradeSettings {
  89. text-align:center !important;
  90. padding: 10px;
  91. }
  92.  
  93. #exitSettings {
  94. height:auto;
  95. width:75%;
  96. margin:auto;}
  97. #newContainer {
  98. text-align:center;
  99. }
  100.  
  101. #createFilter {
  102. width: 70%;
  103. margin-right:5px;
  104. }
  105.  
  106. #submitBtn, #createBtn {
  107. width: 45%;
  108. margin:5px;
  109. height:auto;
  110.  
  111. }
  112. #checkedCounter {
  113. text-transform:uppercase;
  114. font-weight:bold;
  115. margin:5px;
  116. color:blue;
  117. }
  118.  
  119. #selectFirst, #selectMax, #selectNone {
  120. margin:5px;
  121. height:auto;
  122. width:31%;
  123. }
  124. .quick {
  125. margin-bottom:5px;
  126. }
  127.  
  128. input.quick {
  129. width: 60% !important;
  130. }
  131.  
  132. button.quick {
  133. margin-right:5px !important;
  134. }
  135.  
  136. #wishlist {
  137. width: 100%;
  138. height: 1.5em;
  139. }
  140. #quicksale-neopoints {
  141. width: 230px;
  142. height: 1.5em;
  143. margin-left: 10px;
  144. }
  145. .tp_header {
  146. text-align:center;
  147. margin: auto;
  148. margin-bottom:10px;
  149. width: 75%;
  150. overflow-wrap: break-word;
  151. padding: 4px;
  152. }
  153. .tp_header button {
  154. height:auto;
  155. width: auto;
  156. margin-left:10px;
  157. margin-right:10px;
  158. padding-left:10px;
  159. padding-right:10px;
  160. }
  161. .tp_header a {
  162. font-size:10px;
  163. margin:5px;
  164. font-style:italic;
  165. }
  166.  
  167.  
  168.  
  169.  
  170. `;
  171.  
  172. document.head.appendChild(tradeStyles);
  173. }
  174. addGlobalStyles();
  175.  
  176.  
  177. function addGlobalSettings() {
  178. const tpHeader = document.querySelector('main h1').textContent
  179.  
  180. if (tpHeader === 'The Mystery Island Trading Post') {
  181. const navBar = document.querySelector('main nav');
  182. navBar.innerHTML += `| <a href="#settings" id="tpSettings">Trading Post Settings</a>`
  183.  
  184. var tpSettings = document.getElementById('tpSettings');
  185. tpSettings.addEventListener('click', function () {
  186. var tradeDetails = document.querySelector('.trading_post');
  187. if (tradeDetails.style.display != 'none') {
  188. openTradeSettings();}
  189. })}
  190. }
  191. addGlobalSettings();
  192.  
  193. function addGlobalHeader() {
  194. const mainTP = document.querySelector('.trading_post');
  195. let mainHeader = document.createElement('div');
  196. mainHeader.classList.add('tp_header');
  197. mainTP.parentNode.insertBefore(mainHeader, mainTP);
  198.  
  199. let headerButton = document.createElement('button');
  200. headerButton.id = 'createHeader';
  201. headerButton.textContent = 'Create a new trade!';
  202.  
  203. let linkLots = document.createElement('a');
  204. let user = document.querySelector("#user-info-username").text;
  205. linkLots.href = `https://www.grundos.cafe/island/tradingpost/lot/user/${user}/`;
  206. linkLots.textContent = 'Link to your Lots';
  207.  
  208. let clipboardIcon = document.createElement('span');
  209. clipboardIcon.classList.add('clipboard-icon');
  210. clipboardIcon.textContent = '📋';
  211. clipboardIcon.style.cursor = 'pointer';
  212. clipboardIcon.title = 'Copy Link to Clipboard';
  213.  
  214. let quickSearch = document.createElement('input');
  215. quickSearch.placeholder = 'Enter TP Search Term Here';
  216. quickSearch.classList.add('quick');
  217.  
  218. // Add an event listener for the 'Enter' key on the quickSearch input
  219. quickSearch.addEventListener('keydown', (event) => {
  220. if (event.key === 'Enter' && quickSearch.value.trim() !== '') {
  221. event.preventDefault(); // Prevent form submission if inside a form
  222. tpQuickSearch(); // Call the quick search function
  223. }
  224. });
  225.  
  226. let qsButton = document.createElement('button');
  227. qsButton.textContent = "Quick Search";
  228. qsButton.onclick = function() { tpQuickSearch(); };
  229. qsButton.classList.add('quick');
  230.  
  231. const headerCheck = document.querySelector('.trading_post > div.header').textContent;
  232.  
  233. if (headerCheck !== '\nSelect Your Search Criteria\n') {
  234. mainHeader.append(quickSearch);
  235. mainHeader.append(qsButton);
  236. }
  237. mainHeader.append(headerButton);
  238. mainHeader.append(linkLots);
  239. mainHeader.append(clipboardIcon);
  240.  
  241. document.getElementById('createHeader').addEventListener('click', function() {
  242. window.location.href = '/island/tradingpost/createtrade/';
  243. });
  244.  
  245. clipboardIcon.addEventListener('click', function() {
  246. const tempInput = document.createElement('input');
  247. tempInput.value = linkLots.href;
  248. document.body.appendChild(tempInput);
  249.  
  250. tempInput.select();
  251. document.execCommand('copy');
  252.  
  253. document.body.removeChild(tempInput);
  254.  
  255. clipboardIcon.textContent = '✓ Copied!';
  256. setTimeout(function() {
  257. clipboardIcon.textContent = '📋';
  258. }, 1500);
  259. });
  260. }
  261. addGlobalHeader();
  262.  
  263.  
  264. function openTradeSettings() {
  265. const tradeDetails = document.querySelector('.trading_post'),
  266. tradeSettings = Object.assign(document.createElement('div'), {
  267. id: 'tradeSettings',
  268. className: 'trading_post bg-dm-gray flex-column margin-auto',
  269. style: { display: 'none' },
  270. innerHTML: `<div class="header"><strong>Trading Post Script Settings</strong></div><div></div>`
  271. }),
  272. wishContainer = Object.assign(document.createElement('div'), {
  273. id: 'wishContainer',
  274. innerHTML: `<p><strong>Default Wishlists</strong></p>`
  275. }),
  276. hiddenContainer = Object.assign(document.createElement('div'), {
  277. id: 'hiddenContainer',
  278. innerHTML: `<p><strong>Trade-Blocked Users</strong></p>`
  279. }),
  280. exitSettingsBtn = Object.assign(document.createElement('button'), {
  281. id: 'exitSettings',
  282. textContent: "Save and Exit Settings"
  283. });
  284.  
  285. tradeDetails.insertAdjacentElement('afterend', tradeSettings);
  286. tradeSettings.append(wishContainer, hiddenContainer, exitSettingsBtn);
  287.  
  288.  
  289.  
  290.  
  291. exitSettingsBtn.addEventListener('click', function() {
  292. tradeSettings.remove();
  293. tradeDetails.style.display = "";
  294. })
  295.  
  296. }
  297.  
  298. async function initiateNewTrade() {
  299. const inventItems = document.querySelectorAll('.trade-item');
  300. const itemDetails = await getItemDetails(inventItems);
  301. const lotCount = await fetchLotCount();
  302. const lotsLeft = 20 - lotCount;
  303. const heading = document.querySelector('.trading_post > div.header > strong');
  304. heading.textContent = `${heading.textContent} (${lotsLeft} lots left)`;
  305.  
  306. let checkedCount = 0;
  307. const counterDisplay = createCounterDisplay(checkedCount);
  308. const itemButtons = document.querySelector('#tp-buttons');
  309. const filterInput = createFilterInput();
  310. const autoSelect = createSelectButtons();
  311. const createBtn = document.querySelector('.center input.form-control');
  312. createBtn.value = "Submit and View Trades";
  313. const submitBtn = createSubmitButton();
  314. const wishList = document.querySelector('#wishlist');
  315. wishlist.placeholder = "WISHLIST: Optionally, list what you are seeking."
  316. const slotsData = document.querySelector('.flex-column.med-gap > span');
  317. const [slotsOpen, slotsAvail] = slotsData.textContent.match(/\d+/g).map(Number);
  318.  
  319. const quickSale = document.querySelector('#quicksale-neopoints');
  320.  
  321.  
  322. const container = document.createElement('div');
  323. container.id = "newContainer";
  324.  
  325. document.querySelector('#tp-buttons').insertAdjacentElement('afterend', container);
  326. container.append(filterInput);
  327. container.append(counterDisplay);
  328. container.append(autoSelect);
  329. if (slotsOpen != 0) {
  330. quickSale.placeholder = "Name an auto sale price."
  331. container.append(slotsData);
  332. container.append(quickSale);}
  333. container.append(wishList);
  334. container.append(submitBtn);
  335. container.append(createBtn);
  336. document.querySelector('.med-gap').replaceWith(itemButtons)
  337.  
  338.  
  339. document.querySelectorAll('input[type="checkbox"]').forEach(checkbox => {
  340. checkbox.addEventListener('change', event => handleCheckboxChange(event, counterDisplay));
  341. });
  342.  
  343. filterInput.addEventListener('input', () => filterShownItems(itemDetails, filterInput.value));
  344. filterInput.dispatchEvent(new Event('input'));
  345.  
  346. filterInput.addEventListener('input', () => filterShownItems(itemDetails, filterInput.value));
  347. submitBtn.addEventListener('click', event => submitTradeForm(itemDetails));
  348. }
  349.  
  350. function submitTradeForm(itemDetails){
  351. event.preventDefault();
  352.  
  353. const tokenVal = document.querySelector('form [name="csrfmiddlewaretoken"]').value;
  354. const wishList = document.querySelector('textarea#wishlist').value;
  355. const checkedItems = Array.from(document.querySelectorAll('.trade-item input')).filter(item => item.checked);
  356. const quickSale = document.querySelector('input#quicksale-neopoints') ? document.querySelector('input#quicksale-neopoints').value : '';
  357.  
  358. var formData = new FormData();
  359. formData.append('csrfmiddlewaretoken', tokenVal);
  360. formData.append('quicksale-neopoints', quickSale)
  361. formData.append('wishlist', wishList);
  362.  
  363. checkedItems.forEach(item => {
  364. formData.append('checks', item.value);
  365. });
  366.  
  367. fetch('/island/tradingpost/processcreation/', {
  368. method: 'POST',
  369. body: formData
  370. })
  371. .then(response => {
  372. if (response.redirected) {
  373. window.location.reload();
  374. } else {
  375. console.log('Form submitted successfully');
  376. }
  377. })
  378. .catch(error => {
  379. console.error('Error submitting form:', error);
  380. });
  381. }
  382.  
  383. function createSubmitButton() {
  384. const submitBtn = document.createElement('button');
  385. submitBtn.id = "submitBtn";
  386. submitBtn.textContent = "Submit and Create Next"
  387.  
  388. return submitBtn;
  389.  
  390. }
  391.  
  392. async function getItemDetails(inventItems) {
  393. return Array.from(inventItems).map(item => {
  394. let itemName = item.querySelector('.item-info > span').textContent;
  395. let itemRarity = parseInt(item.querySelector('.item-info > span:nth-child(2)').textContent.replace(/\D/g, ''), 10) || 0;
  396. let itemID = item.querySelector('input').value;
  397. return { item, itemName, itemRarity, itemID };
  398. });
  399. }
  400.  
  401. function createSelectButtons() {
  402. const selectFirst = document.createElement('button');
  403. const selectMax = document.createElement('button');
  404. const selectNone = document.createElement('button');
  405. const buttonCont = document.createElement('span');
  406. selectFirst.id = 'selectFirst';
  407. selectMax.id = 'selectMax';
  408. selectNone.id = 'selectNone';
  409. buttonCont.append(selectFirst, selectMax, selectNone);
  410. selectFirst.textContent = "Select First";
  411. selectMax.textContent = "Select 15";
  412. selectNone.textContent = "Clear All";
  413.  
  414. selectFirst.addEventListener('click', (event) => {
  415. event.preventDefault();
  416. selectFirstAction();
  417. });
  418. selectMax.addEventListener('click', (event) => {
  419. event.preventDefault();
  420. selectMaxAction();
  421. });
  422. selectNone.addEventListener('click', (event) => {
  423. event.preventDefault();
  424. selectNoneAction();
  425. });
  426.  
  427. return buttonCont;
  428. }
  429.  
  430. function selectFirstAction() {
  431. const checkboxes = document.querySelectorAll('input[type="checkbox"]');
  432. let index = 0;
  433. checkboxes.forEach(checkbox => {
  434. let parent = checkbox.parentElement;
  435. while (parent) {
  436. const style = window.getComputedStyle(parent);
  437. if (style.display === 'none') {
  438. return;
  439. }
  440. parent = parent.parentElement;
  441. }
  442. checkbox.checked = (index === 0);
  443. index++;
  444. });
  445.  
  446. updateCheckedCount();
  447. }
  448.  
  449. function selectMaxAction() {
  450. const checkboxes = document.querySelectorAll('input[type="checkbox"]');
  451. let selectedCount = 0;
  452.  
  453. checkboxes.forEach(checkbox => {
  454. if (selectedCount >= 15) {
  455. return;
  456. }
  457. let parent = checkbox.parentElement;
  458. let hidden = false;
  459. while (parent) {
  460. const style = window.getComputedStyle(parent);
  461. if (style.display === 'none') {
  462. hidden = true;
  463. break;
  464. }
  465. parent = parent.parentElement;
  466. }
  467. if (!hidden) {
  468. checkbox.checked = true;
  469. selectedCount++;
  470. }
  471. });
  472.  
  473. updateCheckedCount();
  474. }
  475.  
  476. function selectNoneAction() {
  477. const checkboxes = document.querySelectorAll('input[type="checkbox"]');
  478. checkboxes.forEach(checkbox => {
  479. checkbox.checked = false;
  480. });
  481. updateCheckedCount();
  482. }
  483.  
  484. function updateCheckedCount() {
  485. const counterDisplay = document.getElementById('checkedCounter');
  486. const checkboxes = document.querySelectorAll('input[type="checkbox"]');
  487. const checkedCount = Array.from(checkboxes).filter(checkbox => checkbox.checked).length;
  488. counterDisplay.textContent = `Selected: ${checkedCount}`;
  489. }
  490.  
  491. function createCounterDisplay(initialCount) {
  492. const counterDisplay = document.createElement('span');
  493. counterDisplay.id = 'checkedCounter';
  494. counterDisplay.textContent = `Selected: ${initialCount}`;
  495. return counterDisplay;
  496. }
  497.  
  498. function createFilterInput() {
  499. const filterInput = document.createElement('input');
  500. filterInput.placeholder = "Filter by Name or Rarity";
  501. filterInput.id = "createFilter";
  502. filterInput.value = sessionStorage.getItem('filterValue') || '';
  503. return filterInput;
  504. }
  505.  
  506. function filterShownItems(itemDetails) {
  507. let filterValue = document.querySelector('#createFilter').value;
  508. sessionStorage.setItem('filterValue', filterValue);
  509. const lowerCaseFilterValue = filterValue.toLowerCase();
  510. itemDetails.forEach(({ item, itemName, itemRarity }) => {
  511. item.parentElement.style.display = itemName.toLowerCase().includes(lowerCaseFilterValue) || itemRarity.toString().includes(lowerCaseFilterValue) ? '' : 'none';
  512. });
  513. }
  514.  
  515. function handleCheckboxChange(event, counterDisplay) {
  516. const checkboxes = document.querySelectorAll('input[type="checkbox"]');
  517. let checkedCount = Array.from(checkboxes).filter(checkbox => checkbox.checked).length;
  518.  
  519. if (checkedCount > 15) {
  520. alert(`You can only select up to 15 items.`);
  521. event.target.checked = false;
  522. checkedCount--;
  523. }
  524.  
  525. counterDisplay.textContent = `Selected: ${checkedCount}`;
  526. }
  527.  
  528. async function capturelotDetails() {
  529. const tradeLots = document.querySelectorAll('.trade-lot');
  530. let tokenVal = document.querySelector('.button-group [type="hidden"][name="csrfmiddlewaretoken"]').value;
  531. document.querySelectorAll('.flex-column [action="/island/tradingpost/createtrade/"]')
  532. .forEach(element => element.style.display = "none");
  533. document.querySelector('.trading_post .small-gap').style.display="none";
  534.  
  535.  
  536. let lotDetails = [];
  537. tradeLots.forEach(lot => {
  538. let lotNum = lot.querySelector('.button-group input[type="hidden"][name="lotno"]').value;
  539. let offerCt = parseInt(lot.querySelector('span').textContent.replace(/\D/g, ''), 10) || 0;
  540. let lotDate = new Date(lot.querySelector('span:nth-of-type(3)').textContent.split(':').slice(1).join(':').replace('NST', '').trim().replace(' at ', ` ${new Date().getFullYear()} `));
  541. let autoSale = parseInt(lot.querySelector(`span#quicksale-text-${lotNum}`).textContent.replace(/\D/g, ''), 10) || null;
  542.  
  543.  
  544. let entry = { lotNum: lotNum, offerCt: offerCt, element: lot , autoSale: autoSale, lotDate: lotDate};
  545. lotDetails.push(entry);
  546. });
  547.  
  548. return { tokenVal, lotDetails, tradeLots };
  549. }
  550.  
  551. function generateCancelButtons() {
  552.  
  553. const createLotBtn = document.querySelector('form.center [type="submit"]');
  554. const cancelContainer = document.createElement('div');
  555. const cancelAllBtn = document.createElement('span');
  556.  
  557. cancelContainer.id = "cancelContainer";
  558. cancelAllBtn.classList = "cancelbtn";
  559. cancelAllBtn.id = "cancelBtn";
  560. cancelAllBtn.textContent = "Sort Options:";
  561.  
  562.  
  563.  
  564. cancelAllBtn.onclick = function() {
  565. const confirmed = confirm('Are you sure you wish to cancel ALL trades at once? This may take a moment and will not include any trades with pending offers.');
  566. if (confirmed) {
  567. cancelAllBtn.disabled = true;
  568. cancelAllBtn.textContent = "Cancellation in progress...";
  569. cancelAllTrades();
  570. } else {
  571. //Do Nothing
  572. }
  573. };
  574.  
  575.  
  576.  
  577. createLotBtn.parentNode.insertAdjacentElement('afterend', cancelContainer);
  578. cancelContainer.append(cancelAllBtn);
  579. }
  580.  
  581. function generateSortElement() {
  582. const sortSelect = document.createElement('select');
  583. sortSelect.id = "sortSelect";
  584.  
  585. var options = ['Sort by Newest', 'Sort by Oldest', 'Show Offers First', 'Show Offers Only', 'Show Autosale Only'];
  586. for (var i = 0; i < options.length; i++) {
  587. var option = document.createElement('option');
  588.  
  589. option.value = [i + 1];
  590. option.text = options[i];
  591. sortSelect.appendChild(option);
  592. }
  593.  
  594. var selectedOption = localStorage.getItem('selectedOption');
  595. if (selectedOption) {
  596. sortSelect.value = selectedOption;
  597. }
  598. applySelectedOption();
  599.  
  600.  
  601. document.querySelector('#cancelContainer').append(sortSelect);
  602. sortSelect.addEventListener('change', function () {
  603. applySelectedOption();
  604. localStorage.setItem('selectedOption', sortSelect.value);
  605. });
  606. }
  607.  
  608. async function applySelectedOption() {
  609. const { tokenVal, lotDetails, tradeLots } = await capturelotDetails();
  610. const linehr = document.querySelectorAll('hr');
  611. linehr.forEach(line => {line.remove();})
  612. const sortSelect = document.getElementById('sortSelect');
  613. const selectedValue = parseInt(sortSelect.value);
  614.  
  615. if (selectedValue === 1) { //newest
  616. lotDetails.sort((a, b) => b.lotDate - a.lotDate);
  617. } else if (selectedValue === 2) { //oldest
  618. lotDetails.sort((a, b) => a.lotDate - b.lotDate);
  619. } else if (selectedValue === 3) { //offers first
  620. lotDetails.sort((a, b) => b.offerCt - a.offerCt);
  621. } else if (selectedValue === 4) { //offers only
  622. lotDetails.forEach(lot => {
  623. lot.element.style.display = '';
  624. if (lot.offerCt === 0) {
  625. lot.element.style.display = 'none';
  626. } else {
  627. lot.element.style.display = 'visible';
  628. }
  629. });
  630. } else if (selectedValue === 5) { //autosale only
  631. lotDetails.forEach(lot => {
  632. lot.element.style.display = '';
  633. if (lot.autoSale === null) {
  634. lot.element.style.display = 'none';
  635. } else {
  636. lot.element.style.display = 'visible';
  637. }
  638. }); }
  639.  
  640. if (selectedValue !== 4 && selectedValue !== 5) {
  641. const parent = tradeLots[0].parentElement;
  642. lotDetails.forEach(lot => {
  643. parent.appendChild(lot.element);
  644. lot.element.style.display = ''; // Ensure all elements are displayed for sorting options 1 and 2
  645. });
  646. }
  647. }
  648.  
  649. async function tpQuickSearch() {
  650.  
  651. const tokenVal = document.querySelector('form [name="csrfmiddlewaretoken"]').value;
  652.  
  653.  
  654. function submitForm() {
  655. const searchVal = document.querySelector('input.quick').value;
  656.  
  657. var form = document.createElement('form');
  658. form.method = 'POST';
  659. form.action = '/island/tradingpost/browse/';
  660.  
  661. var input1 = document.createElement('input');
  662. input1.type = 'hidden';
  663. input1.name = 'csrfmiddlewaretoken';
  664. input1.value = tokenVal;
  665.  
  666. var input2 = document.createElement('input');
  667. input2.type = 'hidden';
  668. input2.name = 'qty';
  669. input2.value = '0';
  670.  
  671. var input3 = document.createElement('input');
  672. input3.type = 'hidden';
  673. input3.name = 'category';
  674. input3.value = '1';
  675.  
  676. var input4 = document.createElement('input');
  677. input4.type = 'hidden';
  678. input4.name = 'query';
  679. input4.value = searchVal;
  680.  
  681. var input5 = document.createElement('input');
  682. input5.type = 'hidden';
  683. input5.name = 'type';
  684. input5.value = '-1';
  685.  
  686. var input6 = document.createElement('input');
  687. input6.type = 'hidden';
  688. input6.name = 'sort';
  689. input6.value = 'newest';
  690.  
  691.  
  692. form.appendChild(input1);
  693. form.appendChild(input2);
  694. form.appendChild(input3);
  695. form.appendChild(input4);
  696. form.appendChild(input5);
  697. form.appendChild(input6);
  698.  
  699.  
  700. document.body.appendChild(form);
  701. form.submit();
  702. }
  703. submitForm();
  704. }
  705.  
  706. async function cancelAllTrades() {
  707. // Submit the form to cancel all trades on the page.
  708. const { tokenVal, lotDetails, tradeLots } = await capturelotDetails();
  709. const cancelAllBtn = document.getElementById('cancelAllBtn');
  710. if (cancelAllBtn) {
  711. cancelAllBtn.disabled = true}
  712.  
  713.  
  714. function submitForm(lotNum) {
  715. var form = document.createElement('form');
  716. form.method = 'POST';
  717. form.action = '/island/tradingpost/canceltrade/';
  718.  
  719. var input1 = document.createElement('input');
  720. input1.type = 'hidden';
  721. input1.name = 'csrfmiddlewaretoken';
  722. input1.value = tokenVal;
  723.  
  724. var input2 = document.createElement('input');
  725. input2.type = 'hidden';
  726. input2.name = 'lotno';
  727. input2.value = lotNum.lotNum;
  728.  
  729. form.appendChild(input1);
  730. form.appendChild(input2);
  731.  
  732. document.body.appendChild(form);
  733. form.submit();
  734. }
  735.  
  736. lotDetails.forEach((lotNum, index) => {
  737.  
  738. if (lotNum.offerCt === 0) {
  739. setTimeout(() => {
  740. submitForm(lotNum);
  741. }, index * 500);
  742. } else {
  743.  
  744. }
  745. });
  746. }
  747. function generateUserDropdown() {
  748. const tradeLots = document.querySelectorAll('.trade-lot');
  749.  
  750.  
  751.  
  752. tradeLots.forEach(lot => {
  753. const user = lot.querySelector('span');
  754. var lotNumber = parseInt(lot.querySelector('strong').textContent.match(/\d+/)[0], 10);
  755. var lotlink = `https://www.grundos.cafe/island/tradingpost/lot/${lotNumber}`;
  756. const username = user.querySelector('a').textContent;
  757. const icon = document.createElement('span');
  758. const dropdown = document.createElement('div');
  759.  
  760. dropdown.classList.add('user-dropdown');
  761. icon.classList.add('user-icon');
  762. dropdown.innerHTML = `
  763. <p><a href="https://www.grundos.cafe/neomessages/sendmessage/?username=${username}">Send Neomail</a></p>
  764. <p><a href="https://www.grundos.cafe/island/tradingpost/lot/user/${username}">View All Trades</a></p>
  765. <p><a href="https://www.grundos.cafe/userlookup/?user=${username}">Visit Userlookup</a></p>
  766. <p><a href="https://www.grundos.cafe/wishlist/?user=${username}">View Wishlist</a></p>
  767. <p class="copy-link">Copy Link to Lot 📋</p>
  768. `;
  769. dropdown.style.display = 'none';
  770. icon.innerText = ' ⤵️';
  771.  
  772. user.style.position = 'relative';
  773. user.append(icon);
  774. icon.appendChild(dropdown);
  775.  
  776. icon.addEventListener('click', (event) => {
  777. event.stopPropagation();
  778. if (dropdown.style.display === 'none') {
  779. dropdown.style.display = 'block';
  780. } else {
  781. dropdown.style.display = 'none';
  782. }
  783. });
  784. dropdown.addEventListener('click', (event) => {
  785. event.stopPropagation();
  786. });
  787. const copyLink = dropdown.querySelector('.copy-link');
  788. copyLink.addEventListener('click', () => {
  789. navigator.clipboard.writeText(lotlink).then(() => {
  790. copyLink.textContent = 'Copied!';
  791. setTimeout(() => {
  792. copyLink.textContent = 'Copy Link to Lot 📋';
  793. }, 5000);
  794. }).catch(err => {
  795. console.error('Failed to copy: ', err);
  796. });
  797. });
  798. });
  799. }
  800.  
  801. async function fetchLotCount() {
  802. try {
  803. const response = await fetch('https://www.grundos.cafe/island/tradingpost/');
  804. const text = await response.text();
  805.  
  806. const parser = new DOMParser();
  807. const doc = parser.parseFromString(text, 'text/html');
  808.  
  809. const tradeLots = doc.querySelectorAll('.trade-lot');
  810. const lotCount = tradeLots.length;
  811.  
  812. return lotCount;
  813. } catch (error) {
  814. console.error('Error fetching lot count:', error);
  815. return 0;
  816. }
  817. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址