Обновление цен на элементы
// ==UserScript== // @name GN_ElementPriceLoader // @namespace Gradient // @description Обновление цен на элементы // @include /^https{0,1}:\/\/(www\.heroeswm\.ru|178\.248\.235\.15|my\.lordswm\.com)\/.+/ // @exclude /^https{0,1}:\/\/(www\.heroeswm\.ru|178\.248\.235\.15|my\.lordswm\.com)\/(login|war|cgame|frames|chat|chatonline|ch_box|chat_line|ticker|chatpost|chat2020|battlechat|campaign)\.php.*/ // @version 1.0.11 // ==/UserScript== "use strict"; //----------------------------------------------------------------------------// var script_name = 'GN_ElementPriceLoader'; // Enter your script name here //----------------------------------------------------------------------------// (function(){ try{ // wrapper start //----------------------------------------------------------------------------// // UnifiedLibrary 1.7.0 start //----------------------------------------------------------------------------// //----------------------------------------------------------------------------// // SysUtils //----------------------------------------------------------------------------// var GN_SysUtils = new SysUtils(script_name); var SU = GN_SysUtils; //----------------------------------------------------------------------------// function SysUtils(name){ // wrapper start //----------------------------------------------------------------------------// this.show_error = function(error_string, use_alert){ if(use_alert) alert(error_string); throw new Error(error_string); }; if(arguments.length != 1) this.show_error('Wrong SysUtils arguments'); if(!arguments[0]) this.show_error('Empty SysUtils argument'); //----------------------------------------------------------------------------// this.save_value = function(desc, value){ var div = document.getElementById('GN_GM_Handler'); div.setAttribute('desc', desc); div.setAttribute('value', value); div.setAttribute('operation', 'save'); div.click(); if(div.getAttribute('state') != 'complete') this.show_error('Ошибка при сохранении значения'); }; //----------------------------------------------------------------------------// this.load_value = function(value, def){ var div = document.getElementById('GN_GM_Handler'); div.setAttribute('desc', value); div.setAttribute('operation', 'load'); div.click(); if(div.getAttribute('state') != 'complete') this.show_error('Ошибка при загрузке значения'); return (div.getAttribute('is_null') == 'true' ? def : div.getAttribute('value')); }; //----------------------------------------------------------------------------// var current_id = null; //----------------------------------------------------------------------------// function check_mandatory_scripts(alerter){ var persistent_storage_sign = document.getElementById('GN_GM_Handler'); var common_values_sign = document.getElementById('GN_CommonValuesSign'); var alert_sign = document.getElementById('GN_AlertSign'); if(!alert_sign){ alert_sign = document.createElement('div'); alert_sign.id = 'GN_AlertSign'; alert_sign.setAttribute('alerted', 'false'); document.body.appendChild(alert_sign); } var alerted = alert_sign.getAttribute('alerted') != 'false'; if(!persistent_storage_sign){ alert_sign.setAttribute('alerted', 'true'); alerter('Скрипт ' + name + ' требует для своей работы скрипт управления данными (GN_PersistentStorage), который должен стоять первым в порядке выполнения скриптов.\n' + 'Подробнее здесь: "https://greasyfork.org/ru/scripts/14049-Как-устанавливать-скрипты-читать-здесь"', !alerted); } if(!common_values_sign){ alert_sign.setAttribute('alerted', 'true'); alerter('Скрипт ' + name + ' требует для своей работы скрипт, хранящий данные (GN_CommonValuesFiller), который должен стоять вторым в порядке выполнения скриптов.\n' + 'Подробнее здесь: "https://greasyfork.org/ru/scripts/14049-Как-устанавливать-скрипты-читать-здесь"', !alerted); } } this.check_login = function(){ var re = /.*?pl_id=(\d+)[^\d]*?/gmi; var matches = re.exec(document.cookie.toString()); if(matches){ current_id = +matches[1]; check_mandatory_scripts(this.show_error); } }; //----------------------------------------------------------------------------// function get_char(e){ if(e.which && e.charCode){ if(e.which < 32) return null; return String.fromCharCode(+e.which) } return null; } this.number_input = function(e){ if(e.ctrlKey || e.altKey || e.metaKey) return false; var chr = get_char(e); return chr == null || (chr >= '0' && chr <= '9'); }; //----------------------------------------------------------------------------// this.reload_page = function(){ document.location.href = document.location.href; }; //----------------------------------------------------------------------------// this.check_login(); //----------------------------------------------------------------------------// } // wrapper end //----------------------------------------------------------------------------// // CommonValues //----------------------------------------------------------------------------// var GN_CommonValues = new CommonValues(); //----------------------------------------------------------------------------// function CommonValues(){ // wrapper start //----------------------------------------------------------------------------// // Elements //----------------------------------------------------------------------------// this.elements = JSON.parse(SU.load_value('GN_CommonValues_Elements', '[]')); //----------------------------------------------------------------------------// } // wrapper end //----------------------------------------------------------------------------// // GUIController //----------------------------------------------------------------------------// var GN_GUIController = new GUIController(); //----------------------------------------------------------------------------// function GUIController(){ // wrapper start //----------------------------------------------------------------------------// clear_flash_z_index(); //----------------------------------------------------------------------------// var script_name = 'GN_GUIController'; this.script_name = function(){ return script_name; }; //----------------------------------------------------------------------------// this.registerObject = function(object){ root_div = document.getElementById(root.div.id); if(!root_div) root_div = create_node(root, document.body); else{ var custom = root_div.getAttribute('custom').split('|'); root.div.top = +custom[0]; root.div.left = +custom[1]; root.div.width = +custom[2]; root.div.height = +custom[3]; } object.div.left = root.div.left + left; object.div.top = top; var childs = root_div.childNodes; for(var i = 0; i < childs.length; ++i) if(childs[i].nodeName.toLowerCase() == 'div'){ var height = +childs[i].getAttribute('custom').split('|')[3]; object.div.top += height; } create_node(object, root_div); align_childs(root_div); collapse_childs(root_div); }; //----------------------------------------------------------------------------// this.hide_all = function(){ if(!root_div) return; var childs = root_div.childNodes; for(var i = 0; i < childs.length; ++i) if(childs[i].nodeName.toLowerCase() == 'div') childs[i].style.top = +childs[i].getAttribute('custom').split('|')[0]; align_childs(root_div); collapse_childs(root_div); }; var hide_all = this.hide_all; //----------------------------------------------------------------------------// const left = 10; const top = 10; var root = { div: { id: script_name + 'MainDiv', top: top, left: left, width: 0, height: 0 }, input: { id: script_name + 'MainInput', value: 'Скрипты', title: 'Конфигурация и запуск скриптов, не относящихся к определенной странице' }, child_divs: [] }; var root_div = document.getElementById(root.div.id); //----------------------------------------------------------------------------// function create_node(object, parent){ var div_ = div(object.div); div_.setAttribute('expanded', 'false'); parent.appendChild(div_); set_div_style(object.div); var input_ = input(object.input); div_.appendChild(input_); set_input_style(object.input); object.div.left += div_.clientWidth; object.div.width = div_.clientWidth; object.div.height = div_.clientHeight; var custom = [ object.div.top, object.div.left, object.div.width, object.div.height ]; div_.setAttribute('custom', custom.join('|')); if(object.child_divs.length || object.div.id == root.div.id){ input_.addEventListener('click', function(){ expand_childs(div_); }); create_child_nodes(object, div_); } return div_; } //----------------------------------------------------------------------------// function create_child_nodes(object, parent){ var childs = object.child_divs; for(var i = 0; i < childs.length; ++i){ var child = childs[i]; child.div.top = top; child.div.left = left; if(i){ var total_height = 0; for(var j = 0; j < i; ++j){ var sibling = childs[j]; var sibling_div = document.getElementById(sibling.div.id); total_height += sibling_div.clientHeight; } child.div.top += total_height; } child.div.left += object.div.left; create_node(child, parent); } } //----------------------------------------------------------------------------// function expand_childs(el){ var now_expanded = (el.getAttribute('expanded') == 'true'); if(now_expanded && el == root_div){ hide_all(); return; } var childs = el.childNodes; for(var i = 0; i < childs.length; ++i) if(childs[i].nodeName.toLowerCase() == 'div') childs[i].style.display = !now_expanded ? 'block' : 'none'; if(now_expanded){ collapse_childs(el); if(el.parentNode == root_div){ childs = root_div.childNodes; for(i = 0; i < childs.length; ++i) if(childs[i].nodeName.toLowerCase() == 'div' && childs[i] != el) childs[i].style.display = 'block'; el.style.top = +el.getAttribute('custom').split('|')[0]; el.style.width = +el.getAttribute('custom').split('|')[2]; align_childs(root_div); } } if(!now_expanded && el.parentNode == root_div){ childs = root_div.childNodes; for(i = 0; i < childs.length; ++i){ if(childs[i].nodeName.toLowerCase() == 'div' && childs[i] != el) childs[i].style.display = 'none'; } el.style.top = top; el.style.width = +el.getAttribute('custom').split('|')[2]; } el.setAttribute('expanded', now_expanded ? 'false' : 'true'); } //----------------------------------------------------------------------------// function align_childs(el){ var max_width = 0; var childs = el.childNodes; for(var i = 0; i < childs.length; ++i) if(childs[i].nodeName.toLowerCase() == 'div'){ var width = +childs[i].getAttribute('custom').split('|')[2]; if(width >= max_width) max_width = width; } for(i = 0; i < childs.length; ++i) if(childs[i].nodeName.toLowerCase() == 'div') childs[i].style.width = max_width; } //----------------------------------------------------------------------------// function collapse_childs(el){ var divs = el.querySelectorAll('div'); for(var i = 0; i < divs.length; ++i){ divs[i].setAttribute('expanded', 'false'); divs[i].style.display = 'none'; } el.setAttribute('expanded', 'false'); } //----------------------------------------------------------------------------// function div(object){ var div = document.createElement('div'); div.id = object.id; return div; } //----------------------------------------------------------------------------// function set_div_style(object){ var div = document.getElementById(object.id); var style = div.style; style.position = 'fixed'; style.top = object.top + 'px'; style.left = object.left + 'px'; style.zIndex = 100; } //----------------------------------------------------------------------------// function input(object){ var input = document.createElement('input'); input.type = 'button'; input.id = object.id; input.value = object.value; input.title = object.title; return input; } //----------------------------------------------------------------------------// function set_input_style(object){ var input = document.getElementById(object.id); var style = input.style; style.display = 'block'; style.width = '95%'; style.border = '1px solid rgb(153, 153, 153)'; style.padding = '1px'; style.margin = '2px'; style.background = 'none repeat scroll 0% 0% rgb(204, 204, 204)'; style.fontSize = '12px'; style.cursor = 'pointer'; style.zIndex = 100; } //----------------------------------------------------------------------------// function clear_flash_z_index(){ var objects = document.querySelectorAll('object'); for(var i = 0; i < objects.length; ++i){ var o = objects[i]; if(!o.querySelector('param[name="wmode"]')){ var param = document.createElement('param'); param.setAttribute('name', 'wmode'); param.setAttribute('value', 'opaque'); o.insertBefore(param, o.firstChild); } } } //----------------------------------------------------------------------------// } // wrapper end //----------------------------------------------------------------------------// // UnifiedLibrary end //----------------------------------------------------------------------------// var CV = GN_CommonValues; var elements = CV.elements; var save_value = SU.save_value; var load_value = SU.load_value; var show_error = SU.show_error; var number_input = SU.number_input; var reload_page = SU.reload_page; var GC = GN_GUIController; GC.registerObject( { div: { id: GC.script_name() + '_' + script_name + 'Div' }, input: { id: GC.script_name() + '_' + script_name + 'Input', value: 'Обновление цен элементов', title: 'Обновление цен элементов' }, child_divs: [] } ); var start_button = document.getElementById(GC.script_name() + '_' + script_name + 'Input'); start_button.addEventListener('click', function(e){ draw_div(document.body); }); var elements_array = [ { id: 'abrasive' }, { id: 'snake_poison' }, { id: 'tiger_tusk' }, { id: 'ice_crystal' }, { id: 'moon_stone' }, { id: 'fire_crystal' }, { id: 'meteorit' }, { id: 'witch_flower' }, { id: 'wind_flower' }, { id: 'fern_flower' }, { id: 'badgrib' } ]; var market_objects = []; //----------------------------------------------------------------------------// function draw_div(parent){ var div = document.createElement('div'); div.id = script_name + 'Div'; div.style.position = 'fixed'; div.style.display = 'block'; div.style.top = start_button.parentNode.style.top; div.style.zIndex = 100; var left = /(\d+)px/.exec(start_button.parentNode.style.left); div.style.left = +left[1] + start_button.parentNode.clientWidth + 'px'; div.style.width = '300px'; div.style.background = start_button.style.backgroundColor; parent.appendChild(div); draw_content(div); } //----------------------------------------------------------------------------// function draw_content(parent){ var table = document.createElement('table'); table.style.width = '100%'; table.style.border = 'medium none'; parent.appendChild(table); draw_header(table); elements.forEach(function(current){ draw_row(table, current); }); draw_buttons(table); } //----------------------------------------------------------------------------// function draw_header(parent){ var upd_date = JSON.parse(load_value(script_name + '_LastUpdate', '0')); if(upd_date) upd_date = new Date(Date.parse(upd_date)); var tr = document.createElement('tr'); parent.appendChild(tr); var td = document.createElement('td'); td.setAttribute('colspan', '4'); td.id = script_name + '_LastUpdate'; td.textContent = 'Дата последнего обновления: ' + (upd_date ? upd_date.toLocaleString() : 'еще не считывалось'); tr.appendChild(td); tr = document.createElement('tr'); tr.setAttribute('bgColor', '#DCDCDC'); parent.appendChild(tr); ['Наименование', 'Текущее значение', 'Новое значение', 'Разница' ].forEach(function(current){ td = document.createElement('td'); td.textContent = current; tr.appendChild(td); }); } //----------------------------------------------------------------------------// function draw_row(parent, object_){ var tr = document.createElement('tr'); tr.id = object_.id; parent.appendChild(tr); var td = document.createElement('td'); td.textContent = object_.name + ':'; tr.appendChild(td); td = document.createElement('td'); td.textContent = object_.average_price; tr.appendChild(td); td = document.createElement('td'); var input = document.createElement('input'); input.type = 'text'; input.style.width = 40; input.value = object_.average_price; input.onkeypress = number_input; input.addEventListener('input', function(e){ show_difference(input); }); td.appendChild(input); tr.appendChild(td); td = document.createElement('td'); var font = document.createElement('font'); font.color = 'black'; font.textContent = 0; td.appendChild(font); tr.appendChild(td); } //----------------------------------------------------------------------------// function draw_buttons(parent){ var tr = document.createElement('tr'); parent.appendChild(tr); var td = document.createElement('td'); td.setAttribute('align', 'right'); td.setAttribute('colspan', '4'); tr.appendChild(td); var button = document.createElement('input'); button.type = 'button'; button.value = 'Применить'; button.addEventListener('click', function(e){ save_prices(); }); td.appendChild(button); button = document.createElement('input'); button.type = 'button'; button.value = 'Обновить'; button.addEventListener('click', function(e){ load_prices(); }); td.appendChild(button); button = document.createElement('input'); button.type = 'button'; button.value = 'Отмена'; button.addEventListener('click', function(e){ remove_div(); }); td.appendChild(button); } //----------------------------------------------------------------------------// function save_prices(){ var errors = []; var div = document.getElementById(script_name + 'Div'); var trs = div.querySelectorAll('table > tr[id]'); for(var i = 0; i < trs.length; ++i){ var input = trs[i].querySelector('input'); if(isNaN(+input.value) || +input.value <= 0){ errors.push('Цена элемента должна быть положительной'); break; } } if(errors.length){ alert('Ошибки при сохранении:\n\n' + errors.join('\n')); return; } var el_prices = []; for(var i = 0; i < trs.length; ++i){ var input = trs[i].querySelector('input'); el_prices.push({ id: trs[i].id, price: input.value }); } save_value('GN_CommonValues_ElementPrices', JSON.stringify(el_prices)); reload_page(); } //----------------------------------------------------------------------------// function load_prices(){ document.body.style.cursor = 'wait'; var end = 0; for(var i = 0; i < elements_array.length; ++i) if(!elements_array[i].stop) send_async_get(elements_array[i]); else ++end; if(end < elements_array.length) setTimeout(load_prices, 500); else { var objects = filter_objects(market_objects); var div = document.getElementById(script_name + 'Div'); objects.forEach(function(current){ var tr = div.querySelector('table > tr[id="' + current.id + '"]'); if(tr){ var input = tr.querySelector('input'); input.value = Math.floor(current.sum/current.count); show_difference(input); } }); var upd_date = new Date(); var td = document.getElementById(script_name + '_LastUpdate'); td.textContent = 'Дата последнего обновления: ' + upd_date.toLocaleString(); save_value(script_name + '_LastUpdate', JSON.stringify(upd_date)); for(var i = 0; i < elements_array.length; ++i) elements_array[i].stop = false; market_objects = []; document.body.style.cursor = 'default'; } } //----------------------------------------------------------------------------// function send_async_get(obj) { var xhr = new XMLHttpRequest(); xhr.open('GET', '/auction.php?cat=elements&sort=0&art_type=' + obj.id, true); xhr.overrideMimeType('text/plain; charset=windows-1251'); xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ if(xhr.status == 200){ obj.stop = true; var objects = parse_page(xhr.response); market_objects = market_objects.concat(objects); } } }; xhr.send(null); } //----------------------------------------------------------------------------// function parse_page(response){ var all_objects = []; response = response.replace(/(\n(\r)?)/g, ' '); var re = /.*?(<tr bgcolor='#(?:ffffff|eeeeee)' class=wb>.+?gold.png.+?show_js_button.+?<\/tr>).*?/gmi; var matches = []; while(matches = re.exec(response)) { var el_re = /.+\<img.+?([^\/]+?)\.(gif|png)[^']*?'.+?gold.png.+?<td>([0-9,]+?)<\/td>.+?onclick=.+?/gmi; var el_matches = el_re.exec(matches[1]); if(!el_matches) show_error('Ошибка при парсинге ' + matches[1]); var object = { id: el_matches[1], price: +(el_matches[3].replace(/,/g, '')), count: 1 }; var count_re = /.*<b>(\d+?) шт.<\/b>/i; var c_matches = count_re.exec(matches[1]); if(c_matches) object.count = +c_matches[1]; all_objects.push(object); } return all_objects; } //----------------------------------------------------------------------------// function filter_objects(objects){ var el_objects = []; var step = 1.05; var max_count = 45; objects.forEach(function(current){ var el = get_object(current.id, el_objects); if(!el) el_objects.push({ id: current.id, max_price: current.price, sum: current.price*current.count, count: current.count }); else{ if(current.price >= el.max_price && current.price <= el.max_price*step) el.max_price = current.price; if(current.price <= el.max_price*step && el.count < max_count){ el.count += current.count; el.sum += current.price*current.count; } } }); return el_objects; } //----------------------------------------------------------------------------// function show_difference(input){ var diff = +input.parentNode.previousSibling.textContent - +input.value; var font = input.parentNode.nextSibling.firstChild; font.color = diff === 0 ? 'black' : diff > 0 ? 'green' : 'red'; font.textContent = diff + ''; } //----------------------------------------------------------------------------// function get_object(id, array_){ for(var i = 0; i < array_.length; ++i) if(array_[i].id == id) return array_[i]; return null; } //----------------------------------------------------------------------------// function remove_div(){ var div = document.getElementById(script_name + 'Div'); div.parentNode.removeChild(div); } //----------------------------------------------------------------------------// } catch(e){ alert('Ошибка в скрипте ' + script_name + ', обратитесь к разработчику:\n' + e); throw e; }}()); // wrapper end //----------------------------------------------------------------------------//