您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Rulesy's updateApps
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/31206/204854/updateApps.js
var modules = modules || {}; modules.updateApps = { name: 'Map app updater', description: 'Keeps map apps up-to-date automatically.', icon: '/gfx/icons/item_map.gif', pages: 'outside', externalApps: { 'cartographer': { name: 'Cartographer', directoryId: 19, logo: '/file/35.dat', success: function(response) { return (response.status == 200); }, update: function(externalAppName, extendedData) { var externalApp; var key; var url; var data; externalApp = modules.updateApps.externalApps[externalAppName]; if (extendedData.hardcore) { externalApp.updating = false; externalApp.temporariyDisabled = true; externalApp.temporariyDisabledMessage = 'Hardcore not supported'; modules.updateApps.updateTooltip(); return; } url = 'http://wastelandcartographer.com/plugin'; externalApp = modules.updateApps.externalApps[externalAppName]; key = modules.updateApps.retrieveAppKey(externalAppName); if (!key) { externalApp.updating = false; externalApp.error = true; externalApp.errorMessage = 'Error retrieving key'; modules.updateApps.updateTooltip(); return; } data = 'key=' + key; modules.updateApps.sendUpdate(url, data, externalAppName); } }, 'dusk-till-dawn': { name: 'From Dusk Till Dawn', directoryId: 14, logo: '/file/25.dat', success: function(response) { return (response.status == 200); }, update: function(externalAppName, extendedData) { var items; var item; var itemKey; var i; var externalApp; var key; var data; var url; url = 'http://d2n.duskdawn.net/zone/extended'; externalApp = modules.updateApps.externalApps[externalAppName]; key = modules.updateApps.retrieveAppKey(externalAppName); if (!key) { externalApp.updating = false; externalApp.error = true; externalApp.errorMessage = 'Error retrieving key'; modules.updateApps.updateTooltip(); return; } data = 'key=' + key; data += '&zombies=' + extendedData.zombies; data += '&zone_depleted=' + (extendedData.depleted ? 'true' : 'false'); data += '&camping_topology=' + extendedData.topology; if (extendedData.building) { data += '&blueprint_available=' + (extendedData.blueprint ? 'true' : 'false'); } if (extendedData.items.length > 0) { items = {}; for (i = 0; i < extendedData.items.length; i++) { item = extendedData.items[i]; itemKey = item.id + (item.broken ? 'B' : ''); if (items[itemKey]) { items[itemKey]++; } else { items[itemKey] = 1; } } for (itemKey in items) { data += '&items=' + itemKey + '-' + items[itemKey]; } } modules.updateApps.sendUpdate(url, data, externalAppName); } }, 'mapviewer': { name: 'Map Viewer', directoryId: 1, logo: '/file/37.dat', success: function(response) { return (response.status == 200 && response.responseText.match(/Zone .* was updated successfully/)); }, update: function(externalAppName, extendedData) { var items; var item; var itemKey; var i; var externalApp; var key; var data; var url; var unique; url = 'http://die2nite.gamerz.org.uk/plugin/extended'; externalApp = modules.updateApps.externalApps[externalAppName]; key = modules.updateApps.retrieveAppKey(externalAppName); if (!key) { externalApp.updating = false; externalApp.error = true; externalApp.errorMessage = 'Error retrieving key'; modules.updateApps.updateTooltip(); return; } data = 'key=' + key; if (extendedData.building) { data += '&blueprint=' + (extendedData.blueprint ? 1 : 0); } if (extendedData.hardcore) { data += '&zombies=' + extendedData.zombies; data += '&depleted=' + (extendedData.depleted ? 1 : 0); if (extendedData.items.length > 0) { unique = 0; items = {}; for (i = 0; i < extendedData.items.length; i++) { item = extendedData.items[i]; itemKey = item.id + (item.broken ? 'B' : ''); if (items[itemKey]) { items[itemKey]++; } else { items[itemKey] = 1; unique++; } } data += '&items='; i = 1; for (itemKey in items) { data += itemKey + '-' + items[itemKey]; if (i < unique) { data += ','; } i++; } } } modules.updateApps.sendUpdate(url, data, externalAppName); } } }, campingTopologies: { 'L1_SUICIDE': 'Sleeping somewhere like this is basically a form of suicide', 'L2_SHORTAGE': 'There\'s a distinct shortage of shelter here.', 'L3_MINIMAL': 'This zone offers nothing more than minimal "natural" protection.', 'L4_HIDING_PLACE': 'After a quick look around, it looks like you could find a good hiding place here.', 'L5_FEW_HIDEOUTS': 'For those looking to spend the night, there are a few hideouts in this zone', 'L6_TOP_HIDEOUTS': 'If required, there are some top-notch hideouts here...', 'L7_IDEAL': 'This seems like the ideal place to spend the night' }, config: function() { log('modules.updateApps.config()'); var content; var externalAppName; var externalApp; var delay; var delayText; content = '<p>This module adds a small light above your rucksack. The colour of the light will change while it does its thing:' + '<ul>' + '<li><div class="modules-updateApps-config-light"></div> All apps are updated <img src="/gfx/forum/smiley/h_lol.gif"></li>' + '<li><div class="modules-updateApps-config-light waiting"></div> Waiting for the delay to pass (see below) <img src="/gfx/forum/smiley/h_sleep.gif"></li>' + '<li><div class="modules-updateApps-config-light updating"></div> One or more apps are updating <img src="/gfx/forum/smiley/h_sleep.gif"><img src="/gfx/forum/smiley/h_sleep.gif"></li>' + '<li><div class="modules-updateApps-config-light errors"></div> Something broke <img src="/gfx/forum/smiley/h_death.gif"></li>' + '</ul></p>' + '<p>Hover over the light to see the status of each app, or click it to trigger an update.</p>'; content += '<h2>External Apps</h2>'; for (externalAppName in this.externalApps) { externalApp = this.externalApps[externalAppName]; content += '<p><img src="' + externalApp.logo + '" height="16" width="16"> ' + app.settings.checkbox('modules.updateApps.externalApps.' + externalAppName + '.enabled', externalApp.name, 'true') + '</p>'; } delay = localStorage.getItem('modules.updateApps.config.delay'); if (undefined == delay) { delay = 2; } delayText = delay == 0 ? 'No delay' : delay + ' seconds'; content += '<h2>Delay</h2>'; content += '<p>This will help prevent apps getting spammed when you pick up or drop a lot of items.</p>'; content += '<div id="modules-updateApps-config-delay-slider"></div>'; content += '<span id="modules-updateApps-config-delay">' + delayText + '</span>'; return content; }, configInit: function() { var delay; delay = localStorage.getItem('modules.updateApps.config.delay'); if (undefined == delay) { delay = 2; } $('#modules-updateApps-config-delay-slider').slider({ value: delay, min: 0, max: 10, slide: function( event, ui ) { var delay = ui.value; localStorage.setItem('modules.updateApps.config.delay', delay); var delayText = delay == 0 ? 'No delay' : delay + ' seconds'; $('#modules-updateApps-config-delay').html(delayText); } }); }, init: function() { log('modules.updateApps.init()'); // see if the user has set a delay var delay = localStorage.getItem('modules.updateApps.config.delay'); delay = (undefined == delay) ? 2000 : delay * 1000; if (delay == 0) { // no delay, so update immediately this.updateApps(); } else { // (re)set the expiry time var time = new Date(); this.delayUntil = time.getTime() + delay; // and delay the update window.setTimeout(this.updateApps, delay); this.updateTooltip(); } modules.updateApps.heartbeat = modules.updateApps.heartbeat || window.setInterval(function() { if ($('#modules-updateApps-init').length == 0) { window.setTimeout(function() { if ($('#modules-updateApps-init').length == 0) { modules.updateApps.updateApps(); } }, 1000); } }, 1000); }, updateApps: function() { log('modules.updateApps.updateApps()'); var time; var externalAppName; var externalApp; var extendedData; // see if the user has set a delay if (localStorage.getItem('modules.updateApps.config.delay') == 0) { // they have, so has their delay expired? time = new Date(); if (time.getTime() < modules.updateApps.delayUntil) { // no. they must have triggered another update since this was called return false; } } extendedData = modules.updateApps.getExtendedData(); if (!extendedData) { return false; } $('#modules-updateApps-init').addClass('updating'); for (externalAppName in modules.updateApps.externalApps) { externalApp = modules.updateApps.externalApps[externalAppName]; if (localStorage.getItem("modules.updateApps.externalApps." + externalAppName + ".enabled") !== 'false') { externalApp.updating = true; externalApp.error = false; externalApp.errorMessage = false; externalApp.temporariyDisabled = false; externalApp.update(externalAppName, extendedData); } } modules.updateApps.updateTooltip(); return true; }, updateTooltip: function() { log('modules.updateApps.updateTooltip()'); var updatingCount; var errors; var tooltipContent; var delay; var time; var waiting; var externalApp; var externalAppName; var tooltipTitle; var div; var tooltip ; updatingCount = 0; errors = false; delay = localStorage.getItem('modules.updateApps.config.delay'); if (undefined == delay) { delay = 2000; } else { delay = delay * 1000; } time = new Date(); waiting = false; if (delay !== 0 && this.delayUntil !== undefined && time.getTime() < this.delayUntil) { waiting = true; } tooltipContent = '<ul class="modules-updateApps-tooltip">'; for (externalAppName in this.externalApps) { externalApp = this.externalApps[externalAppName]; if (localStorage.getItem("modules.updateApps.externalApps." + externalAppName + ".enabled") == 'false') { tooltipContent += '<li class="disabled" data-app="' + externalAppName + '"><img width="16" height="16" src="' + externalApp.logo + '" /> ' + externalApp.name + ': <span>Disabled</span></li>'; } else if (externalApp.temporariyDisabled) { tooltipContent += '<li data-app="' + externalAppName + '"><img width="16" height="16" src="' + externalApp.logo + '" /> ' + externalApp.name + ': <span>' + externalApp.temporariyDisabledMessage + '</span></li>'; } else if (waiting) { tooltipContent += '<li class="waiting" data-app="' + externalAppName + '"><img width="16" height="16" src="' + externalApp.logo + '" /> ' + externalApp.name + ': <span>Waiting...</span></li>'; } else if (externalApp.error) { errors = true; tooltipContent += '<li class="broken" data-app="' + externalAppName + '"><img width="16" height="16" src="' + externalApp.logo + '" /> ' + externalApp.name + ': <span>' + externalApp.errorMessage + '</span></li>'; } else if (externalApp.updating) { updatingCount++; tooltipContent += '<li class="updating" data-app="' + externalAppName + '"><img width="16" height="16" src="' + externalApp.logo + '" /> ' + externalApp.name + ': <span>Updating...</span></li>'; } else { tooltipContent += '<li class="updated" data-app="' + externalAppName + '"><img width="16" height="16" src="' + externalApp.logo + '" /> ' + externalApp.name + ': <span>Updated!</span></li>'; } } tooltipContent += '</ul>'; tooltipTitle = 'Map app updater <img src="http://data.die2nite.com/gfx/icons/small_archive.gif">'; div = $('#modules-updateApps-init'); if (!div.length) { div = $('<div id="modules-updateApps-init" class="updating" />'); div.attr('onmouseout', 'js.HordeTip.hide();'); $('#generic_section .right h2:first').append(div); $('#modules-updateApps-init').on('click', modules.updateApps.updateApps); } div.attr('onmouseover', 'js.HordeTip.showTip(this, \'' + tooltipTitle + '\', \'' + tooltipContent + '\')'); tooltip = $('#tooltipContent'); if ($('.title',tooltip).html() == tooltipTitle) { tooltip.html('<div class="title">' + tooltipTitle + '</div>' + tooltipContent); } if (waiting) { div.addClass('waiting'); } else { div.removeClass('waiting'); } if (errors) { div.addClass('errors'); } else { div.removeClass('errors'); } if (updatingCount > 0) { div.addClass('updating'); } else { div.removeClass('updating'); } }, sendUpdate: function(url, data, externalAppName) { (function(url, data, externalAppName) { log(url + ': ' + data); GM_xmlhttpRequest({ method: "POST", url: url, data: data, headers: { "Content-Type": "application/x-www-form-urlencoded" }, onload: function(response) { var externalApp; log(externalAppName + ' replied with:'); log(response); externalApp = modules.updateApps.externalApps[externalAppName]; externalApp.updating = false; if (!externalApp.success(response)) { externalApp.error = true; externalApp.errorMessage = 'Invalid response'; } modules.updateApps.updateTooltip(); } }); })(url, data, externalAppName); }, retrieveAppKey: function(appName) { log('modules.updateApps.retrieveAppKey(' + appName + ')'); var url; var key; var result; var sk; key = localStorage.getItem('modules.updateApps.externalApps.' + appName + '.key'); if (undefined != key) { return key; } result = window.location.hash.match(/sk\=([0-9a-f]{5})/); sk = result ? result[1] : ''; url = '/disclaimer?id=' + modules.updateApps.externalApps[appName].directoryId + ';sk=' + sk + ';rand=' + (Math.floor(Math.random()*999998) + 1); $.ajax({ async: false, url: url, success: function(data) { var search; search = data.match(/name="key" value="([0-9a-f]+)"/); if (null != search) { key = search[1]; localStorage.setItem('modules.updateApps.externalApps.' + appName + '.key', key); } else { log('key for ' + appName + ' not found'); key = false; } }, error: function() { log('ajax error while retrieving key for ' + appName); key = false; } }); return key; }, getItemNamesToIds: function() { var itemNamesToIdsUpdateTime; var itemNamesToIds; var time; var expiry; var url; itemNamesToIdsUpdateTime = localStorage.getItem('modules.updateApps.itemNamesToIdsUpdateTime'); itemNamesToIds = localStorage.getItem('modules.updateApps.itemNamesToIds'); time = new Date().getTime(); expiry = 60 * 60 * 24 * 7 * 1000; // a week if (undefined == itemNamesToIds || undefined == itemNamesToIdsUpdateTime || time > (itemNamesToIdsUpdateTime + expiry) ) { // If Map Viewer goes down, this URL will need to be replaced. It returns // a JSON object containing all the items' names and IDs: // // { // "'Wake The Dead'":"97", // "A letter with no address":"189", // "Adjustable Spanner":"13", // ... // } url = 'https://raw.githubusercontent.com/Miudod2n/die2nitestuff/master/item-names-to-ids.json'; GM_xmlhttpRequest({ url: url, beforeSend: function(x) { if(x && x.overrideMimeType) { x.overrideMimeType("application/j-son;charset=UTF-8"); } }, onload: function(response) { localStorage.setItem('modules.updateApps.itemNamesToIds', response.responseText); localStorage.setItem('modules.updateApps.itemNamesToIdsUpdateTime', new Date().getTime()); modules.updateApps.updateApps(); } }); return false; } else { return eval('(' + itemNamesToIds + ')'); } }, getExtendedData: function() { var itemNamesToIds; var extendedData; var topologyEl; var topologyKey; var re; topologyEl = $('#campInfos p:nth-child(2)'); if (topologyEl.length == 0) { return false; } itemNamesToIds = modules.updateApps.getItemNamesToIds(); if (!itemNamesToIds) { return false; } extendedData = { hardcore: ($('.day .hard').length == 1), building: ($('.outSpot').length > 0), blueprint: ($('#campInfos').text().match(/(You will earn)|(You can obtain)/)), zombies: $('#zombiePts').text().replace(/[^0-9]/g, ''), depleted: ($('.driedZone').length > 0), items: [] }; for (topologyKey in modules.updateApps.campingTopologies) { re = new RegExp(modules.updateApps.campingTopologies[topologyKey]); if (topologyEl.html().match(re)) { extendedData.topology = topologyKey; break; } } $('.outInv li span, .outInv li span a').each(function() { var match; var name; var broken; var id; var item; if (!$(this).attr('onmouseover')) { return true; } match = $(this).attr('onmouseover').match(/'([^<]*)/); if (null == match) { return true; } name = match[1].trim().replace(/\\'/g, "'"); broken = $(this).hasClass('limited') || $(this).parent().hasClass('limited'); id = itemNamesToIds[name]; if (id) { item = { name: name, id: parseInt(itemNamesToIds[name]), broken: broken }; extendedData.items.push(item); } else { // item not found, need to do something here..... } return true; }); log('Extended data:'); log(extendedData); return extendedData; } };