NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Desura Collection Key Scraper // @author wisnoskij // @version 2.8.1 // @namespace http://indie-elitist.blogspot.ca/ // @description Gets, stores, and displays the keys of your games. With the appropriate notifications for changes. // @match http://www.desura.com/collection* // @include http://www.desura.com/collection* // @match http://www.desura.com/games/* // @include http://www.desura.com/games/* // @match https://www.desura.com/collection* // @include https://www.desura.com/collection* // @match https://www.desura.com/games/* // @include https://www.desura.com/games/* // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_listValues // @grant GM_addStyle // @grant GM_setClipboard // @require https://gist.github.com/raw/2625891/waitForKeyElements.js // @require http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js // @require http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.min.js // ==/UserScript== /** Change Log ** ** Fixed download issue by using more robouse encoding scheme (encodeURIComponent()). **/ //Make the icon list that will go below every game box var icons = $('<div name="dcks_icons"><a title="Steam Keys" class="dcks_cat dcks_keyslist dcks_steamicon dcks_hide"></a> <a title="Desura Keys" class="dcks_cat dcks_keyslist dcks_desuraicon dcks_hide"></a> <a title="GOG Keys" class="dcks_cat dcks_keyslist dcks_gogicon dcks_hide"></a> <a title="In-Game Keys" class="dcks_cat dcks_keyslist dcks_ingameicon dcks_hide"></a> <a title="Misc Keys" class="dcks_cat dcks_keyslist dcks_miscicon dcks_hide"></a> <a title="New Keys" class="dcks_keyslist dcks_newicon dcks_remove"></a><a title="Not Scanned" class="dcks_keyslist dcks_notscanedicon"></a><a title="Scrape Keys" class="dcks_keysearch"></a></div>'); //Create icons list icons.find('.dcks_keysearch').bind('click', function(ev){ ev.preventDefault(); getKeys($(this).closest('.box')); }); //Make it search that particular game's Keys page var catLabels = ['_STEAM', '_DESURA', '_GOG', '_INGAME', '_MISC']; //GM_Value category names var catNames = ['Steam', 'Desura', 'GOG', 'In-Game', 'Misc']; //Nice readable names var stats = $('<span id="dcks_stats">(<span id="dcks_gamecount"></span><span id="dcks_newexist" class="dcks_remove">:<span id="dcks_newcount"></span></span>)<span title="Scrape Keys" class="dcks_keysearch"></span><span id="dcks_proc" class="dcks_remove">(<span id="dcks_procdata"></span>)</span><span id="dcks_collmenu" style="font-size: small;cursor: pointer;">▼</span></span>'); stats.find('.dcks_keysearch').bind('click', function(ev){ ev.preventDefault(); getKeys($('.box:not(.dcks_remove)')); }); //Make it search all games var mainMenu = $('<ul id="dcksmenu" style="z-index: 55;position: relative;top: 32px;left: 9px;width: 133px;display: none;">\ <li id="dcksmenu_filter">Filter\ <ul><li id="dcksmenuclearfilter">Clear</li>\ <hr>\ <li id="dcksmenuscanstar">Unscanned & Starred</li>\ <li id="dcksmenuunclaim">Unclaimed Keys</li>\ <li id="dcksmenusteam">Steam Keys</li>\ <li id="dcksmenudesura">Desura Keys</li>\ <li id="dcksmenugog">GOG Keys</li>\ <li id="dcksmenuingame">In-Game Keys</li>\ <li id="dcksmenumisc">Misc Keys</li>\ </ul></li>\ <li id="dcksmenusearch">Search\ <ul><li id="dcksmenusearchall">All</li>\ <li id="dcksmenusearchunscanned">Unscanned</li>\ </ul></li>\ <hr>\ <li id="dcksclearallstar" class="dcks_ar">Clear All<span class="dcks_newicon dcks_keyslist"></span></li>\ <li id="dcksclearalldata" class="dcks_ar">Clear Storage<span class="dcks_notscanedicon dcks_keyslist"></span></li>\ <li id="dcksex">Import/Export\ <ul><li id="dcksexdelete">Delete All</li>\ <li id="dcksexexport">Export</li>\ <li id="dckseximport">Import</li>\ <li id="dcksexexportdl">Export Download List</li>\ </ul></li>\ <hr>\ <li id="dcksinfomenu">Info\ <ul><li><b><a target="_blank" href="https://openuserjs.org/scripts/wisnoskij/Desura_Collection_Key_Scraper">Desura Collection Key Scraper</a></b></li>\ <li>Version: ' + GM_info.script.version + '</li>\ <li><i>By: Wisnoskij</i></li>\ </ul></li>\ <li id="dcksinfomenu">Controls\ <ul><li>Your Collection(#1[:#2])<span title="Scrape Keys" class="dcks_keysearch"></span><span style="font-size: small;cursor: pointer;">▼</span>\ <ul><li><b>#1</b>: The number of games in your collection.</li>\ <li><b>#2</b>: The number of new/unscanned games in your collection.</li>\ <li><span title="Scrape Keys" class="dcks_keysearch"></span> Scan entire selection</li>\ <li><span style="font-size: small;cursor: pointer;">▼</span>: The Main Menu for this script (The one you are in right now).</li></ul></li>\ <li><div name="dcks_icons"><a title="Steam Keys" class="dcks_cat dcks_keyslist dcks_steamicon"></a>(Steam) <a title="Desura Keys" class="dcks_cat dcks_keyslist dcks_desuraicon"></a>(Desura) <a title="GOG Keys" class="dcks_cat dcks_keyslist dcks_gogicon"></a>(GOG) <a title="In-Game Keys" class="dcks_cat dcks_keyslist dcks_ingameicon"></a>(In-Game) <a title="Misc Keys" class="dcks_cat dcks_keyslist dcks_miscicon"></a>(Misc)<br><a title="New Keys" class="dcks_keyslist dcks_newicon"></a>(New) <a title="Not Scanned" class="dcks_keyslist dcks_notscanedicon"></a>(Unscanned) <span title="Scrape Keys" class="dcks_keysearch"></span>(Scan)</div>\ <ul><li>Greyed-out game icons mean that the key has been claimed to this account.<br>Non greyed-out icons means the the key still needs to be requested.</li>\ <li>A <b>Star</b> icon means that that game has new or changed keys.\ <ul><li>The <b>Star</b> sticks around until you dismiss it enmass through the script menu,<br>or individually my mouseing over a game\'s icons.</li>\ <li>A greyed-out <b>Star</b> means that all the keys for that game have been claimed.</li></ul></li>\ <li>An <b>Unscanned</b> icon means that the script has no data for this game.</li>\ <li>Click the <b>Scan</b> icon to scan just that single game.</li>\ <li>Click any of the game icons to open a menu to:\ <ul><li>Toggle the game\'s Star on/off.</li>\ <li>Clear the game\'s saved key data.</li>\ <li>Look at the game\'s saved keys.\ <ul><li>Clicking on any of these keys will transfer them to your clipboard, if supported.<br>Else a prompt will open up with the key.</li></ul></li></ul></li></ul></li>\ </ul></li>\ </ul>'); mainMenu.find('#dcksmenuclearfilter').bind('click', function(ev){ ev.preventDefault(); $('.box.dcks_remove').removeClass('dcks_remove'); setStats(); }); mainMenu.find('#dcksmenuscanstar').bind('click', function(ev){ ev.preventDefault(); $('.box').addClass('dcks_remove'); $('a.dcks_newicon:not(.dcks_remove),a.dcks_notscanedicon:not(.dcks_remove)').closest('.box').removeClass('dcks_remove'); setStats(); }); mainMenu.find('#dcksmenuunclaim').bind('click', function(ev){ ev.preventDefault(); $('.box').addClass('dcks_remove'); $('.dcks_cat:not(.dcks_hide,.dcks_greyout)').closest('.box').removeClass('dcks_remove'); setStats(); }); mainMenu.find('#dcksmenusteam').bind('click', function(ev){ ev.preventDefault(); $('.box').addClass('dcks_remove'); $('.dcks_steamicon:not(.dcks_hide)').closest('.box').removeClass('dcks_remove'); setStats(); }); mainMenu.find('#dcksmenudesura').bind('click', function(ev){ ev.preventDefault(); $('.box').addClass('dcks_remove'); $('.dcks_desuraicon:not(.dcks_hide)').closest('.box').removeClass('dcks_remove'); setStats(); }); mainMenu.find('#dcksmenugog').bind('click', function(ev){ ev.preventDefault(); $('.box').addClass('dcks_remove'); $('.dcks_gogicon:not(.dcks_hide)').closest('.box').removeClass('dcks_remove'); setStats(); }); mainMenu.find('#dcksmenuingame').bind('click', function(ev){ ev.preventDefault(); $('.box').addClass('dcks_remove'); $('.dcks_ingameicon:not(.dcks_hide)').closest('.box').removeClass('dcks_remove'); setStats(); }); mainMenu.find('#dcksmenumisc').bind('click', function(ev){ ev.preventDefault(); $('.box').addClass('dcks_remove'); $('.dcks_miscicon:not(.dcks_hide)').closest('.box').removeClass('dcks_remove'); setStats(); }); mainMenu.find('#dcksmenusearchunscanned').bind('click', function(ev){ ev.preventDefault(); getKeys($('a.dcks_notscanedicon:not(.dcks_remove)').closest('.box:not(.dcks_remove)')); }); mainMenu.find('#dcksmenusearchall').bind('click', function(ev){ ev.preventDefault(); getKeys($('.box:not(.dcks_remove)')); }); mainMenu.find('#dcksclearallstar').bind('click', function(ev){ ev.preventDefault(); if(confirm('Are you sure you want to Clear All Stars from every game in your current selection?')){ $('.box:not(.dcks_remove)').find('a.dcks_newicon:not(.dcks_remove)').closest('[name=dcks_icons]').trigger('mouseenter'); } }); mainMenu.find('#dcksclearalldata').bind('click', function(ev){ ev.preventDefault(); if(confirm('Are you sure you want to Clear All Key Data from every game in your current selection?')){ clearStorage($('.box:not(.dcks_remove)')); } }); mainMenu.find('#dcksexdelete').bind('click', function(ev){ ev.preventDefault(); $('.box').removeClass('dcks_remove'); if(confirm('Are you sure you want to Delete everything?')){ deleteStorage(); location.reload(); } setStats(); }); mainMenu.find('#dcksexexport').bind('click', function(ev){ ev.preventDefault(); $('.box').removeClass('dcks_remove'); setStats(); var list = GM_listValues(); var datastr = ''; var sep = askSep(); var tmpval; for(var i=0; i<list.length; i++){ tmpval = GM_getValue(list[i],''); if(typeof tmpval === 'string'){ tmpval = tmpval.replace(new RegExp('":"', 'g'), sep[1]).replace(new RegExp('","', 'g'), sep[2]); } datastr += list[i] + sep[0] + tmpval + sep[3]; } download('DCKS_data.csv', datastr); }); mainMenu.find('#dckseximport').bind('click', function(ev){ ev.preventDefault(); $('.box').removeClass('dcks_remove'); if(confirm('Are you sure you want to Import some data? This will DELETE all of your current data.')){ deleteStorage(); var input = prompt('Enter Data'); var sep = askSep(); var nvPair = input.split(sep[3]); if(nvPair[nvPair.length-1] === ''){ nvPair.splice(nvPair.length-1, 1); } var tmpval; for(var i=0; i<nvPair.length; i++){ tmpval = nvPair[i].split(sep[0]); GM_setValue(tmpval[0], tmpval[1].replace(new RegExp(sep[1], 'g'), '":"').replace(new RegExp(sep[2], 'g'), '","')); } } location.reload(); }); mainMenu.find('#dcksexexportdl').bind('click', function(ev){ ev.preventDefault(); $('.box').removeClass('dcks_remove'); setStats(); var list = $('a.more'); var datastr = ''; var tmpval; var requests = []; proc = 0; for(var i=0; i<list.length; i++){ proc++; setProc(stats); $.get(list.eq(i).prop('href'), function(data){ var title = $(data).find('.title>a').prop('href').split('/').pop(); var downloads = $(data).find('a.clear[href*="gamedownloads"]'); for(var i=0; i<downloads.length; i++){ datastr += title + '\t' + downloads.eq(i).find('.icons').justtext() + '\t' + downloads.eq(i).find('.desc').justtext() + '\t' + downloads.eq(i).find('.buy').justtext() + '\t' + downloads.eq(i).prop('href') + '\r\n'; } }, 'html') .always(function(){ proc--; setProc(stats); if(proc === 0){ download('DCKS_downlod_links.csv', datastr); } }).fail(function(data, textStatus, jqXHR){ alert(textStatus); }); } }); mainMenu.menu(); jQuery.fn.justtext = function(){ return $(this).clone().children().remove().end().text(); }; //Run for every BOX element that gets loaded by ajax waitForKeyElements(".box", main); waitForKeyElements(".boxrowheading", collection); function download(name, data){ data = data.replace(/#/g, ""); var a = document.createElement('a'); a.setAttribute('download', name); a.setAttribute('title', name); a.setAttribute('name', name); a.href = 'data:application/csv;charset=utf-8;filename='+name+','+encodeURI(data); a.innerHTML = name; a.style.display = 'none'; document.body.appendChild(a); a.click(); } function deleteStorage(){ var list = GM_listValues(); for(var i=0; i<list.length; i++){ GM_deleteValue(list[i]); } } function askSep(){ var sep = ['"="', '":"', '","', '\\r\\n']; var ask = ['Enter Name/Value Pair Separator:', 'Enter Title:Key Separator:', 'Enter Keys Separtor:', 'Enter Name/Value Pair Ending:']; sep[0] = prompt(ask[0], sep[0]); sep[3] = prompt(ask[3], sep[3]).replace(new RegExp('\\\\n', 'g'), '\n').replace(new RegExp('\\\\r', 'g'), '\r') sep[1] = prompt(ask[1], sep[1]); sep[2] = prompt(ask[2], sep[2]); return(sep); } $("head").append('<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/themes/ui-lightness/jquery-ui.min.css" rel="stylesheet" type="text/css">'); //JQuery UI Theme $('html').bind('click', function(ev){ var clickNode = $(ev.target); if(clickNode.closest('.ui-menu').length === 0){ //Do not do anything, if you clicked a menu $('.ui-menu').hide(); if(clickNode.closest('.dcks_keyslist').length){ clickNode.closest('.box').find('>.ui-menu').show(); //Show the menu if you clicked its icon list }else if(clickNode.closest('#dcks_collmenu').length){ $('#dcksmenu').show(); //Show the menu if you clicked its icon list } } }); //Close all menus on click, open one if its icons were clicked. If a menu was clicked, do not close it. window.onhashchange = function(){ setStats(); proc = 0; }; //The main function that gets called one for every loaded game box function main(box){ var gameId = getGameId(box); box.attr('id', gameId); box.append(setIcons(icons.clone(true), gameId)); //Clone generic icons, set them for this specific game, then append to game box box.append(setMenu(gameId)); box.find('>#' + gameId + '_dcksmenu').menu(); //Make menu setStats(); //Redundant except for Alpha/favourites } function collection(collNode){ setStats(); collNode.append(stats); collNode.after(mainMenu); } function setStats(){ stats.find('#dcks_gamecount').html($('.box:not(.dcks_remove)').length); setNew(); } function setNew(){ var count = $('.box:not(.dcks_remove)').find('a.dcks_newicon:not(.dcks_remove),a.dcks_notscanedicon:not(.dcks_remove)').length; if(count > 0){ stats.find('#dcks_newexist').removeClass('dcks_remove'); }else{ stats.find('#dcks_newexist').addClass('dcks_remove'); } stats.find('#dcks_newcount').html(count); } function setProc(statsNode){ if(proc > 0){ statsNode.find('#dcks_proc').removeClass('dcks_remove'); }else{ statsNode.find('#dcks_proc').addClass('dcks_remove'); } statsNode.find('#dcks_procdata').html(proc); return(statsNode); } //Set the icons based on stored data function setIcons(gameIcons, gameId){ var status = GM_getValue(gameId, null); if(status !== null){ //Never scanned, don't need to change anything so skip gameIcons.find('.dcks_notscanedicon').addClass('dcks_remove'); //remove the Not Scanned icon switch(status){ //Set the new star case(0): //Nothing new this scan, or nothing found. Do nothing break; case(1): //Newly scanned content(greyed out star) gameIcons.find('.dcks_newicon').removeClass('dcks_remove').addClass('dcks_greyout'); gameIcons.bind('mouseenter', function(){GM_setValue(gameId, 0); gameIcons.unbind('mouseenter').find('.dcks_newicon').addClass('dcks_remove'); setNew(); }); break; case(2): //New content(never before retrieved keys) gameIcons.find('.dcks_newicon').removeClass('dcks_remove'); gameIcons.bind('mouseenter', function(){GM_setValue(gameId, 0); gameIcons.unbind('mouseenter').find('.dcks_newicon').addClass('dcks_remove'); setNew(); }); break; } var data, node; for(var index=0; index<catLabels.length; index++){ //Set the category icons data = GM_getValue(gameId + catLabels[index], null); if(data !== null){ //if no data skip node = gameIcons.find('a').eq(index); node.removeClass('dcks_hide'); if(data.indexOf('":"Not Yet Reclaimed') === -1){ //If there exists non reclaimed keys. node.addClass('dcks_greyout'); } } } } return(gameIcons); } var clearStorageNode = $('<li class="dcks_ar">Clear<span class="dcks_notscanedicon dcks_keyslist"></li>').bind('click', function(ev){ ev.preventDefault(); clearStorage($(this).closest('.box')); }); var toggleStarNode = $('<li class="dcks_ar">Toggle<span class="dcks_newicon dcks_keyslist"></span></li>').bind('click', function(ev){ ev.preventDefault(); toggleStar($(this).closest('.box')); }); var menuTempDL = $('<ul name="dcks_menu"><hr></ul>').prepend(toggleStarNode, clearStorageNode).hide(); var menuTempDT = $('<li><ul></ul></li>\n').bind('click', function(ev){ ev.preventDefault(); var keyNode = $(this).find('li.ui-menu-item:eq(0)'); if(typeof GM_setClipboard === "function"){ GM_setClipboard(keyNode.find('.dcks_key').text(), 'text'); }else{ prompt(keyNode.find('.dcks_title').text(), keyNode.find('.dcks_key').text()); } }); var menuTempDD = $('<li></li>\n'); //Set the menu based on the stored data function setMenu(gameId){ var menu = menuTempDL.clone(true).attr('id', gameId + '_dcksmenu'); var tmpNode, data; for(var i=0; i<catNames.length; i++){ //It better be the same length data = GM_getValue(gameId + catLabels[i], null); if(data !== null){ tmpNode = menuTempDT.clone(true).prepend(catNames[i]); data = data.split('","'); for(var j=0; j<data.length; j++){ data[j] = data[j].split('":"'); tmpNode.find('ul').append(menuTempDD.clone().html('<span class="dcks_title">' + data[j][0] + '</span> - <span class="dcks_key">' + data[j][1] + '</span>')); } menu.append(tmpNode); } } return(menu); } function toggleStar(box){ var gameId, curS; for(var i=0; i<box.length; i++){ gameId = box.eq(i).attr('id'); curS = GM_getValue(gameId, null); if(curS === 0){ GM_setValue(gameId, 2); }else if(curS === null){ return(false); }else{ GM_setValue(gameId, 0); } propigate(gameId); } } function clearStorage(box){ var gameId; for(var i=0; i<box.length; i++){ gameId = box.eq(i).attr('id'); GM_deleteValue(gameId); for(var j=0; j<catLabels.length; j++){ GM_deleteValue(gameId + catLabels[j]); } propigate(gameId); } } //Get game id, what it is called in the website url. Example: "ice-cream-surfer" function getGameId(gameNode){ return(gameNode.find('.btnsfour>a:eq(1)').attr('href').split('/')[2]); //Select the keys anchor (Could use "nth-of-type" for multiple game selection). Extract the gameid. } var proc = 0; //Send a get request to the game key URL function getKeys(element){ element.addClass('dcks_processing'); var url; for(var i=0; i<element.length; i++){ processing(element.eq(i)); url = '/games/' + getGameId(element.eq(i)) + '/keys/'; $.get(url, process_html, 'html') .fail( function(){ proc--; element.removeClass('dcks_processing'); alert("Getting (" + url + ") failed."); setProc(stats); }); } } function processing(element){ proc++; setProc(stats); } //Process the key page data function process_html(data){ var content = $(data).find('.content'); var gameId = content.find('>p:first-of-type>a:first-of-type').attr('href').split('/')[2]; //Use the necessarily unique game URL as a unique identifier content = content.find('>span, >a'); var categoriedata = [[], [], [], [], []]; var newkey = false, changekey = false; content.each(function(index, element){ //List of already reclaimed keys, and the list of not yet reclaimed keys var keycontent = $(element); var type = keycontent.find('.action').text(); var title = keycontent.find('.heading>span').text(); var value = keycontent.find('input[name=key]').val(); if($.trim(keycontent.find('.price').text().toUpperCase()) == 'GET'){ //If the key is not available value = 'Not Yet Reclaimed'; newkey = true; } switch(type){ //Sort all the keys into the categories case('Steam Key'): categoriedata[0].push(title + '":"' + value); break; case('Desura Key'): categoriedata[1].push(title + '":"' + value); break; case('GOG Key'): categoriedata[2].push(title + '":"' + value); break; case('In-Game Key'): categoriedata[3].push(title + '":"' + value); break; default: categoriedata[4].push(type + ' - ' + title + '":"' + value); break; } }); categoriedata[0] = categoriedata[0].join('","'); //Convert the arrays into strings categoriedata[1] = categoriedata[1].join('","'); categoriedata[2] = categoriedata[2].join('","'); categoriedata[3] = categoriedata[3].join('","'); categoriedata[4] = categoriedata[4].join('","'); for(var index=0;index<catLabels.length;index++){ //Check current data against old stored data, replace and note if different if(GM_getValue(gameId + catLabels[index], '') !== categoriedata[index]){ GM_setValue(gameId + catLabels[index], categoriedata[index]); changekey = true; } } if(changekey){ //Calculate the new game id status changekey = 1; if(newkey){ changekey = 2; } }else{ changekey = 0; } var oldstatus = GM_getValue(gameId, null); if(oldstatus !== changekey){ //Set the game status (star) if((oldstatus === null) || (changekey > 0)){ //Don't remove the star just because scanned again. Wait for mouse-over. GM_setValue(gameId, changekey); } } propigate(gameId); proc--; setProc(stats); } function propigate(gameId){ var propig = $('#' + gameId).removeClass('dcks_processing'); propig.find('[name="dcks_icons"],[name="dcks_menu"]').remove(); main(propig); setNew(); } //Additional CSS, appended with acronym dcks if creating completely new class GM_addStyle( '#boxesholder{\ overflow: visible;\ top: -10px;\ }\ #footer{\ top: -10px;\ position: relative;\ }\ .box>ul{\ width: 76px;\ position: absolute;\ z-index: 9;\ }\ ul>li>ul.ui-menu{\ white-space: nowrap;\ z-index: 9;\ }\ .box{\ padding: 1px 10px !important;\ }\ .dcks_processing{\ opacity: 0.4;\ filter: alpha(opacity=40);\ }\ #dcks_proc{\ font-size: xx-small;\ vertical-align: super;\ }\ .ui-menu-item>.dcks_keyslist{\ float: left;\ margin-top: 2px;\ }\ .dcks_ar{\ text-align: right;\ }\ .dcks_keysearch{\ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAAACXBIWXMAAAsSAAALEgHS3X78AAAAz0lEQVQokY3RsUpDMRQG4O9WKAiunZwKTsIFwQfwDQqCT+Lq6gP4AILgKhQEJ6e+gZs4OYjSohRcBeG4nAuhCdRACOTkC/9JRISIgBM84hMvuMZkqJdzAOcIvOfhOX7ygr5C6PGLe+wWhSN846mFLvPWKkqR4LDcH+EAq4j4Uo/nXKfl5ghv2O+6btJAx7l+bBb6jDDH3kZP62ZPeeAi4RI3eMjHiex3VqHinxb5Yq+4TTzA0wo1P5Fxxh7g2VZUwLsy6lbUgFf/Qgl3MMP4D7gTDyqkNgiQAAAAAElFTkSuQmCC);\ background-repeat: no-repeat;\ cursor: pointer;\ }\ a.dcks_keysearch{\ float: right;\ background-size: 12px Auto;\ width: 12px;\ height: 12px;\ }\ span.dcks_keysearch{\ width: 13px;\ height: 13px;\ background-size: 14px Auto;\ display: inline-block;\ }\ .dcks_greyout{\ opacity: 0.6;\ filter: alpha(opacity=60);\ }\ .dcks_hide{\ visibility:hidden;\ }\ .dcks_remove{\ display:none !important;\ }\ #dcks_searchall{\ width: 12px;\ height: 12px;\ background-size: 12px Auto;\ position: relative;\ top: 1px;\ }\ .dcks_keyslist{\ background-repeat: no-repeat;\ background-size: Auto 13px;\ display: inline-block;\ width: 13px;\ height: 13px;\ cursor: pointer;\ }\ .dcks_steamicon{\ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAARCQAAEQkBwOWiGAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAARoSURBVFiFxZdfiFRlGMZ/77czWlu7G5GhYhCVUnuRer5zZsW2cqMbTSQyilaKsLIs6A+E/QEtb4SiyLIywi4ityIkQTMo0LEs2W3OdwZruqu9CXYRNNxVYlznnLeLObOOtqP7D3tuBp7vfd/nmfOe837fJ6oKgIiI53mPi8gqwAJzmF4MAk5V90RRtENTYVFVPM+ba4zpAZZNs2gjHEySZE0URQNGROQSiwMsM8b0SPrYnxCRj6ex+CmgCAxxkVaq6rpM2vPpwHequiGKopKqJjUybe964GUgU58gIqvEWjtwIZfjwD/Ac2EY7qgRvu9nM5nM5b29vcM1zlprRWQncHNd7qBYa3UK4gBPh2G4HSAIguVJkmwWkVuBGcCfwGctLS1b8vl8xVp7k4gcAZpryWYqyiKy3zn3USr+uqp+KyKzReRTEXkLOA5sPnny5KGurq7LnHN/AK/U15iSgTiON6qq5nK5O1V1E7C7XC63FwqFJwuFwoYwDJeo6gvAkuHh4S0AzrltwNHpMFBpa2srpkZeAv6O43htqVQ6VR/knNsK7BaRZ33fb9YqoukwUMrn82UAEfFF5IdisXhirEAR2Q00GWMWpdTUDajq52lxAWao6ulGsUmSnE5/Z6Y5o7GTMiAi+6Moejs1olT/Uef8+fNnNoi/G6jFAXhTMXBMVR+uHzbpJL2ura3tjfSJjCIIghXAYyLyVRiGQym9eDR3EnNgZRiG+84nfd/vAbpV9bAxZhcwpKp3AI8AfzU1NXl9fX3HgyBYraq7JmMgBraGYfjiWIsiIr7vP6OqrwHXpPRp4Ms4jp8vFosnPM+bZYz5HZhVb+ADYAVw/Rh1K6q6Dfg+m80erh+tF4Lv+zeq6lUi8msYhmdSbg7QA3SdY7x2ILHW3iIiK4B7gE5gWFUfcM4dSAtky+WylEqlkfGYGBWo7rjdIvIecPV/1msG6tHZ2dlSqVSae3t7j3Z0dCyI43h7agogUtUNzrlDjURzudwNqvqUqvpUt+TWhgbHMjBGwUVJkiwHVgFLqH599zvnvj4/1vf9bmD7hUQnbKAeQRA8pKo7gePlcnlerSULFy68IpvNvg88OpF6JgiCtblcbvZ4EwqFwheqegCY1dzc3J6aWpzNZqOJigNkVPUTVVXf9yNgX5Ike6MoCi+SdwygUqm0Aqjqu8CCiYrD2UkoVF+WTcaYXzzPmwsQBMFtS5cuPefN9TxvrojcB8TGmCMiYqibbBNFZgxOjDH3Ah8CjIyMDFhrnYj8qKrXGmMepLr5vOmcG/I8zweunKyBRpOwP45jWywWT1hr14nIRmBeupYA75TL5Vfb29vj/v7+n6h+GZM2MOahVFX3tLa2rs7n85V0mHSIyGygLwzDQRERa+0WqqfdyWJQrLV7gZUNAn4TkfWFQuHnejIdTjuA26cgDvDNeC8mA1QvG2cAn7PtmBJUdZ1QbcMBLu3VDOCgc+4uo6qaJMka4OClFE+SZI2q6ugo/r+u5/8C4FUFsbigklwAAAAASUVORK5CYII=);\ width: 14px !important;\ }\ .dcks_desuraicon{\ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAASCAYAAACw50UTAAAACXBIWXMAAAsSAAALEgHS3X78AAAEjUlEQVQ4jYVUS2hcZRQ+/+O+73+ncydkRqdhMqQ3N5kMI1HIpLmRuGhVEIqv+sAXLrrqouBSfBVx4UqotIKgIBVRjC4shApdFARFK92kaUPCNDakxpqbSZnJzNw/9/G76KSMpdUPDgcOh+8//3l8AP8DhBAFAFBVdch13W81TXN64/8FsssBABghhBFCpOsxQogIISLTNCcdx/nBsqwpy7IOtdvtXznnqwghqScXI4RQl+tf5AAAomtJr2UymWeHh4fPUEozm5ub3zHG9vf19b3COV9qt9vzd+TvctyuGGRZzhWLxS+iKLoZhuFfYRiucc5XVVUdGRgYeC9JkrhWq71Qr9dnbdt+emho6BuMMV1bWzseBMGiLMsDkiTlJUm6j1Jqr6ysvLazs/MnAgDIZDIvua775c7ODiCEgFIKt34I0Ol0NpaXl5/gnP/hOM5Xy8vLL8qyXBgeHp7Tdb1fCAFCCIjjGJIkAVmWYWlp6VXf909TAIBUKvW4ECJZXV096vv+Z5Ik9VNK7zcMY6zRaPwcx3GjVCr9pmnaYKlU+n1xcXHqypUr05Zlea1WayGKovUwDP/u6+t7fWho6JRlWY/5vn+aUkoZY+xgGIbJ1tbWbCaTeZlSanPOa5ubm9/HcdwYHR39RVGUQc55oChKYd++fWcWFhYeiqLItyxrxrKsmSiK6ltbW7NhGH7MGDtAKWXUNM0pTdOy9Xr9XBRF/sDAwClZllVCCFy9evXN9fX1DwkhthAiQQjRrmcAgPv7+48Wi8X3oyiCMAy57/ufNxqN87ZtHzRNcwqn0+nDCKF4Y2PjpGma05IkqUEQNMMwjAghDACSJEnaAIC7m4CTJGkBQIIxVsMwjDjnTVmWFdM0pzc2Nk4ihOI9e/Y8gw3DmAAAIoTgQRAsBUFQkySJCSGQqqolAEBxHPvdAQuEEMRxvAkASFXVMSEEkiSJtdvtpU6nczlJkgAAiGma+3GtVjvcbDYvjoyMzDHGZubn58vNZvM8IYTouj4OAKLdbs8jhES3JaLT6cwDgNB1/UFCCNne3j5/6dKlSiqVOjA6Onq20WhcrNVqzwEAAKU05brunOd5Ip/Pvw0AMDg4+InneULX9Qpj7OFqtSrGx8d5tVoVjLFpwzAe8DxPFIvFTwEA9u7d+47necJ13TlCSGpXO0jXQ6FQOOF5nnAcZxYhhPP5/Fuu654FAKhUKivValVUKpUVAADXdX/M5/PvIoSw4ziznueJQqFwokeTbl8/7hrkcrljk5OTolwuX6CU2rZtP6lpmsMYm5mYmLhpWdYjmqY5tm0/RSlNl8vlC5OTkyKXyx27k6sXaDeoKEohnU4fNAyjDAAgSZKFMca6ro9gjIkkSQwAwDCMcjqdflRRlEIP8W3h6pVN0d0Gyjm/RilN5/P544yxA3Ec8yRJAiFEgBBSMcYqIURpNpvnrl+//gHn/Fr3BqI7q70bMAAkhBDTtu3ns9nsG4ZhlIQQgBCCVqt1+caNGx/V6/Wv4zje3s2/B9c9H7hVAUIkm80eGRsb+ymbzR7pHRbcpb+7+AcRzOEBa7Dd+wAAAABJRU5ErkJggg==);\ width: 17px !important;\ }\ .dcks_gogicon{\ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsSAAALEgHS3X78AAACLElEQVQ4jZ2SO2hUURRF1znvzceMwiikcEQRVGwkOGCwEk1SCAFFG2MQVLCxESQghGAjNmI6BUGQBC3U3iqFdiK2gSGJweCH4HfGmXzI+95j8cwQB22yu3vZ+1zOXleq1epLVe1nE3LOvdLNhgFUtd83M+4+DdhzIA/Ap/mIG8MFxp+F7bufXxOunfa5PRGy/1ABgIWZiLGLRdQ5R7nicf5oyFBvSLnikaYp5YrHUG/IuSMh5MEvxGzrVi73BVw6sUZph2Bm+GZGvZkgIkSRUm8mOOdRb6aAIAKNZkKaCo2WYSbEkdBopTjnUIDadMD1RzFbthrffyWYGbXpgJHJmJHJmI+fI8I15d1cyJXxGBHlRysBwBcRJkZLAOSLRr2VoFpkYrSEmWFmqBZQVR7fzHyl7SmNjQOGxpfazX6YcagqItmOACICwJlbTXLFzLe44BARpFqtWpIkOOfa5lwuh6p2MudfPl9E8DyvHVh/vVP/8/kAzx9GHNyXMR+8EPPgjrF3dw6AufcRw1cLvHgSsWtnDsiGr6ymHD/ro2ZGWaGnL6KnL2Xxi9JdEKoDEdWBiEqXkKYplZJy7FTA6reEw/0htpRh9M0MXXUU8h5J6uGcw1tx5HOgarBsOCfQMqLISFspcSKw7LKPBDA7H/H2fhGIGByD2mzIm3sFQHhdC4AubM2ybgJD1cOCDONfFNaLcc79hVBV2+eNWFUVH5jyff+kc3+4dgQ6cXZo6jd1wxLPH4vlBAAAAABJRU5ErkJggg==);\ }\ .dcks_ingameicon{\ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAA5klEQVRIieXVQUoDQRCF4S/ZqGcQXIgGPIMuFARXuha8hgdwmVu58xLRIBLPoOJiXEw6RhmTeSMDgg8KuodH/dNVM1201wgTVC3jBeMgv+sgeYnXBDDCYwoZJIRAVVkMewIs9KcAV9juE7CPO+z2BYAd3CaQLj2IIAMc4BIba7xHOFza3+MYzw3eankzlf+hJSaaG7/wDOen6KpNbK0ylBKdtwCdzqNohhN1qb6rani2Vjc+j/6gbvZP+lKiVFP1mz+1MaeAKHkKmOEsSc7vvqBV+qfXdTL0OwEusBf44S0xp0P/HeMPWXZrqsn3BSEAAAAASUVORK5CYII=);\ }\ .dcks_miscicon{\ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAABuUlEQVRIibXVMWtUQRQF4G/jQgptlAgGVBQjoo2VthY2msaYtCIWWigBxcZ/IIK1FqawEBtBQrDRVixTipFgQgyCSrBIFJLC3VjM2zC8zOwbgx64MMw958ybeXfutPTHMC7jEg5hfzW/gmXMYBrfGny2YQQv0MFmQ3Qq7kip+QR+FRjX4yfGmszvorsD83g3d2LDVjQew0sMJBaewyy+YxCHcQrHE9xu5fUqnjyItcQXvceZPjs+i3cJ3apQIFt4miAtY6iPeQ9tvE3op3qEI9LVcjMyGcQz4Ueu4zl2RflzCf1vobTdTiQ3cTQyuJ7Ij0b53RmPyTYuZrb+UPhhcDqR34jGezMeozCfWT0XXdyvGd3LcOdIV08uVnChZn6t2k2Kv0r5rf2BY5HxHjxq0Kz9zRFN1cw/FGg+DmBRGT5F4/M4WaBZJF+m9fgstItZLBVqJlvCRVuQ7kExpoXjhH240cDviO7Sk4KvGY/EJwr4j+PVcs1upwtsNbt2JfiCq/LtGq4I3ZNwRDl0K+7XVPKfPzgp/Ncns4chPBBac5PxesUteTu2YRi38EYo5Y0qFvBaeDMO9DP4A+C1MWXpJ5scAAAAAElFTkSuQmCC);\ }\ .dcks_newicon{\ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsSAAALEgHS3X78AAACS0lEQVQ4jZWSTUhUURzFf+/D0ZkxrcbxTSM5DKGEKSImpYsQaqMN4aKVkIsisGiTG0HQnUtxkyAUFX1sWuVOMlAwamELP5Ig08n8wiZnZBgdZ95797bwFRZj1B/O5tx7zj3c84fDR40On7uz+uD8EKD95d6h49l5d8tOvbkpgcL/FWvzg7UD5sqINFdG5Pxg7cBhKdRc5O2WE75Sw+jSjSC6EaTUMLqAgn810O9eDgx5qtoQ8TFEfAxPVRsL9+oe50qhA9raw6anirRqNOxqhA15XlyBAGJ3DgBX4DRFhd6rm/frLFQNG+2DVLS5sutvr+mAW1flleKmG978cD3StkD1ITaeISyxHzMzg7/9EYgtFDLsLY5XJ6dehQG3AhQBp5aHz7721YSOu0qKkUKAVEFxEksbFIGiqWRjSeJzy/HyzqlLwKIKpIHNUOf7yMzE5/FsLInqrkRKGymsfUgb1VNJZiPBzMTCeHnnVATYBNIqYAIxYKm5b7ZbmDpoRUhb/A7Fi0hrNPfNdgNLjsb82YIJJEZ7zzTmlVZgJT8ihQ0IQCCFQKQ+ofsrGO2tbgQSjgb9QCNKwOeuVz0F2NsxxE6Wva8JAArKj4HXRDtSglGcVw8oufbA5Q+dbBGpL2RWE6xNr0eDHZOtwY7J1rXp9WhmNYG0tvGXBVoAV66l8sVfRuS3J02ivz3cAzQAIQcN/e3hntjzC2LrxUUJ+H7FPmBwFAgDbuC780kp56wQ8AMlTmtRYPtPAxfgdbhdIAPIAw/lAx6H2wGyAD8AKT3q7OJ/X3kAAAAASUVORK5CYII=);\ width: 14px !important;\ }\ .dcks_notscanedicon{\ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABYklEQVR4Xn3TP0vDQBgG8PckqCj+qYIKKhQLgouDi0OXfpP2lvYztUvTzW/gJN3SqYtLQVSColCRSBUx2mh8rn0IR0nvgZcbkueX8MIpsZKK1HC0xR0fJS1MBsQse82ms500GhNkKU21UmoKjFhe6XYlDUP50nousIwPxEQ2RLQasryJ8mKlIiax78u7A1kD8kFEPYikBag/QSBbKDLyCSRyIKbzBsT7BvOHiTodGePcJbJaq8kvzpc8hB3T9WIACSY2Q+SAyDqRpxyEHf4BNZMhEAMWiRSAmOehjVidBQOM+n0DZPMM5BZFRraBHLbb9jvsEEio2fMIZGAhO0COLCSxdzDmDmYTcien3Mked3KtddbxLC0399zJGZF9IlGvN+moC5EqTr9Ur8tdqyXzUqxW5ZzIaxDIVbnMe4F0iBwDuXEgJSDmnUuWUdJKmCaREyCuDKYf8Ov2ZZpFxB2/YV3nf9DqsZVlYlPZAAAAAElFTkSuQmCC);\ }\ .dcks_keydetails table{\ width: 898px;\ border: 1px dotted #ccc;\ }\ .dcks_keydetails th{\ border-left: 1px dotted #ccc;\ border-right: 1px dotted #ccc;\ border-bottom: 1px dotted #000;\ font-size: 15px;\ line-height: 20px;\ font-weight: bold;\ color: #1480cd;\ padding-left: 6px;\ width: 179.6px;\ }\ .dcks_keydetails td{\ border-left: 1px dotted #ccc;\ border-right: 1px dotted #ccc;\ text-align: center;\ width: 179.6px;\ }\ .dcks_closekeydetail{\ float: right;\ padding-right: 2px;\ font-weight: bolder;\ font-size: large;\ cursor: pointer;\ }');