返回首頁 

Greasy Fork is available in English.

POE2 Seller Status Check

Monitor seller status on POE trade site and get notifications when they come online

  1. // ==UserScript==// @name POE2 Seller Status Check// @namespace http://tampermonkey.net/// @version 0.2// @description Monitor seller status on POE trade site and get notifications when they come online// @author WSDev// @match https://www.pathofexile.com/trade2/search/poe2/*// @grant GM_addStyle// @grant GM_notification// @grant GM_getValue// @grant GM_setValue// @grant GM_registerMenuCommand// @license MIT// ==/UserScript==(function() {'use strict';// Default configurationconst DEFAULT_CONFIG = {checkInterval: 30000,volume: 0.7,soundType: 'alert1',soundDuration: 200,soundRepeat: 3};// Get current configurationlet config = GM_getValue('config', DEFAULT_CONFIG);// Sound generation functionsconst audioContext = new (window.AudioContext || window.webkitAudioContext)();const SOUND_TYPES = {alert1: {frequency: 880,type: 'square'},alert2: {frequency: [440, 880],type: 'sine'},alert3: {frequency: [587.33, 880],type: 'triangle'}};function playNotification() {const soundConfig = SOUND_TYPES[config.soundType];const frequencies = Array.isArray(soundConfig.frequency) ? soundConfig.frequency : [soundConfig.frequency];frequencies.forEach(frequency => {for (let i = 0; i < config.soundRepeat; i++) {const oscillator = audioContext.createOscillator();const gainNode = audioContext.createGain();oscillator.connect(gainNode);gainNode.connect(audioContext.destination);oscillator.type = soundConfig.type;oscillator.frequency.setValueAtTime(frequency, audioContext.currentTime + (i * config.soundDuration * 2) / 1000);gainNode.gain.setValueAtTime(0, audioContext.currentTime + (i * config.soundDuration * 2) / 1000);gainNode.gain.linearRampToValueAtTime(config.volume, audioContext.currentTime + (i * config.soundDuration * 2 + 10) / 1000);gainNode.gain.linearRampToValueAtTime(0, audioContext.currentTime + (i * config.soundDuration * 2 + config.soundDuration) / 1000);oscillator.start(audioContext.currentTime + (i * config.soundDuration * 2) / 1000);oscillator.stop(audioContext.currentTime + (i * config.soundDuration * 2 + config.soundDuration) / 1000);}});}// Styles for the UIGM_addStyle(`.alert-button {background-color: #4CAF50;border: none;color: white;padding: 5px 10px;text-align: center;text-decoration: none;display: inline-block;font-size: 12px;margin: 2px;cursor: pointer;border-radius: 3px;}.alert-button.active {background-color: #f44336;}#poeStatusConfig {position: fixed;top: 50%;left: 50%;transform: translate(-50%, -50%);background: #2d2d2d;padding: 20px;border-radius: 5px;z-index: 10000;color: white;font-family: Arial, sans-serif;box-shadow: 0 0 10px rgba(0,0,0,0.5);min-width: 300px;}#poeStatusConfig h2 {margin-top: 0;color: #4CAF50;}#poeStatusConfig label {display: block;margin: 10px 0 5px;}#poeStatusConfig input, #poeStatusConfig select {width: 100%;padding: 5px;margin-bottom: 10px;background: #1a1a1a;border: 1px solid #4CAF50;color: white;border-radius: 3px;}#poeStatusConfig button {background: #4CAF50;color: white;border: none;padding: 8px 15px;border-radius: 3px;cursor: pointer;margin-right: 10px;}#poeStatusConfig button:hover {background: #45a049;}.config-overlay {position: fixed;top: 0;left: 0;right: 0;bottom: 0;background: rgba(0,0,0,0.7);z-index: 9999;}`);// Create configuration panelfunction createConfigPanel() {const confi###erlay = document.createElement('div');confi###erlay.className = 'config-overlay';const configPanel = document.createElement('div');configPanel.id = 'poeStatusConfig';const configHtml = `<h2>POE2 Seller Status Check Configuration</h2><label for="checkInterval">Check Interval (ms):</label><input type="number" id="checkInterval" value="${config.checkInterval}" min="5000"><label for="soundType">Alert Sound:</label><select id="soundType"><option value="alert1" ${config.soundType === 'alert1' ? 'selected' : ''}>Alert 1 (High Beep)</option><option value="alert2" ${config.soundType === 'alert2' ? 'selected' : ''}>Alert 2 (Double Tone)</option><option value="alert3" ${config.soundType === 'alert3' ? 'selected' : ''}>Alert 3 (Musical)</option></select><label for="volume">Volume:</label><input type="number" id="volume" value="${config.volume}" step="0.1" min="0"><p style="color: yellow; margin-top: 5px;">Warning: Values above 1 may cause audio distortion.</p><label for="soundDuration">Sound Duration (ms):</label><input type="number" id="soundDuration" value="${config.soundDuration}" min="50" max="1000"><label for="soundRepeat">Repeat Count:</label><input type="number" id="soundRepeat" value="${config.soundRepeat}" min="1" max="5"><div style="margin-top: 20px;"><button id="testSound">Test Sound</button><button id="saveConfig">Save</button><button id="closeConfig">Close</button></div>`;configPanel.innerHTML = configHtml;confi###erlay.appendChild(configPanel);document.body.appendChild(confi###erlay);// Event listenersdocument.getElementById('testSound').addEventListener('click', () => {if (audioContext.state === 'suspended') {audioContext.r###me();}playNotification();});document.getElementById('saveConfig').addEventListener('click', () => {config.checkInterval = Math.max(5000, parseInt(document.getElementById('checkInterval').value));config.soundType = document.getElementById('soundType').value;config.volume = Math.max(0, parseFloat(document.getElementById('volume').value));config.soundDuration = Math.max(50, Math.min(1000, parseInt(document.getElementById('soundDuration').value)));config.soundRepeat = Math.max(1, Math.min(5, parseInt(document.getElementById('soundRepeat').value)));GM_setValue('config', config);confi###erlay.remove();});document.getElementById('closeConfig').addEventListener('click', () => {confi###erlay.remove();});}// Register menu commandGM_registerMenuCommand('POE2 Seller Status Check Configuration', createConfigPanel);// Store monitored items and their last alert timeconst monitoredItems = new Map();// Function to add alert buttonfunction addAlertButton(row) {if (row.querySelector('.alert-button')) return;const refreshButton = row.querySelector('.refresh');if (!refreshButton) return;const alertButton = document.createElement('button');alertButton.className = 'alert-button';alertButton.textContent = 'Alert';alertButton.title = 'Get notified when seller comes online';alertButton.addEventListener('click', () => {const itemId = row.getAttribute('data-id');if (monitoredItems.has(itemId)) {monitoredItems.delete(itemId);alertButton.classList.remove('active');} else {monitoredItems.set(itemId, {row,lastCheck: Date.now(),lastAlert: null});alertButton.classList.add('active');}});refreshButton.parentNode.insertBefore(alertButton, refreshButton.nextSibling);}// Function to check seller statusfunction checkSellerStatus(itemId, item) {const statusElement = item.row.querySelector('.status');if (!statusElement) return;const wasOffline = statusElement.classList.contains('status-offline');const wasAFK = statusElement.classList.contains('status-away');item.row.querySelector('.refresh').click();// Wait for status updatesetTimeout(() => {const isNowOnline = item.row.querySelector('.status').classList.contains('status-online');const now = Date.now();if ((wasOffline || wasAFK) && isNowOnline) {if (!item.lastAlert || now - item.lastAlert >= 300000) { // 5 minutesplayNotification();GM_notification({title: 'POE Seller Online',text: 'A monitored seller has come online!',timeout: 5000});item.lastAlert = now;}} else if (!isNowOnline) {item.lastAlert = null; // Reset last alert time if seller goes offline or AFK}}, 2000);}// Monitor items periodicallysetInterval(() => {const now = Date.now();monitoredItems.forEach((item, itemId) => {if (now - item.lastCheck >= config.checkInterval) {checkSellerStatus(itemId, item);item.lastCheck = now;}});}, 1000);// Add alert buttons to existing itemsfunction addAlertButtonsToExisting() {document.querySelectorAll('.row[data-id]').forEach(addAlertButton);}// Watch for new items being addedconst observer = new MutationObserver((mutations) => {mutations.forEach((mutation) => {mutation.addedNodes.forEach((node) => {if (node.nodeType === 1 && node.matches('.row[data-id]')) {addAlertButton(node);}});});});// Start observingobserver.observe(document.body, {childList: true,subtree: true});// Initial setupaddAlertButtonsToExisting();})();