Last active
September 25, 2017 21:50
-
-
Save vatho/90f9885d8f95ca446541f87f2f2365ce to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Enhance Dota builds page | |
// @namespace https://gist.github.com/parnakra/90f9885d8f95ca446541f87f2f2365ce | |
// @version 0.6 | |
// @updateURL https://gist.github.com/parnakra/90f9885d8f95ca446541f87f2f2365ce/raw/ | |
// @description Adds sorting, searching, filtering and publishing functionality to Dota builds list | |
// @author Parnakra | |
// @match http://www.dota2.com/workshop/builds | |
// @grant none | |
// ==/UserScript== | |
(function() { | |
var intervalId = window.setInterval(function() { if(g_bHeroDataReady) { enhance(); window.clearInterval(intervalId); }}, 1000); | |
function enhance() { | |
var startDateId = 'startDate', | |
endDateId = 'endDate', | |
buildsTableId = 'buildsTable'; | |
addPublishButton(); | |
$.getScript("//cdn.datatables.net/1.10.11/js/jquery.dataTables.min.js", function() { | |
addCss(); | |
initializeTable(); | |
addDateFilters(); | |
loadExtension(); | |
//hideOriginal(); | |
}); | |
function addPublishButton() { | |
$('#fileOperationsContent > h3')[0].insertAdjacentHTML('afterend', '<input type="button" class="largeButton" onclick="publishBuilds()" value="Publish all builds" />'); | |
} | |
window.publishBuilds = function() { | |
let buildsToPublish = []; | |
jQuery.ajaxSetup({async:false}); | |
for(let i=0;i<g_Builds.buildInfo.length;i++) { | |
let build = g_Builds.buildInfo[i]; | |
if(build.published && build.localEdits) { | |
let buildUrl = 'http://www.dota2.com/workshop/builds/update?fileid=' + build.ugcid + '&publishedfileid=' + build.publishedFileId; | |
buildsToPublish.push({ | |
'buildUrl': buildUrl, | |
'agree': 'on', | |
'cloudFileName': build.filename, | |
'heroName': build.heroName, | |
'heroTag': g_rgHeroData[build.heroName].dname.replace("'", ""), | |
'title': build.title, | |
'publishedfileid': build.publishedFileId | |
}); | |
} | |
} | |
var maxBuildsToPublish = 10; | |
if(buildsToPublish.length > 0) { | |
var confirmationMessage = 'Will now publish the following ' + Math.min(maxBuildsToPublish, buildsToPublish.length) + ' out of ' + buildsToPublish.length + ' builds:\n\n'; | |
for(let i=0;i<Math.min(maxBuildsToPublish, buildsToPublish.length);i++) { | |
let build = buildsToPublish[i]; | |
$.get(build.buildUrl, function(data) { | |
var desc = $(data).find('[name="desc"]').val(); | |
var privacy = $(data).find('[name="privacy"]').val(); | |
var language = $(data).find('[name="language"]').val(); | |
build.desc = desc; | |
build.language = language; | |
build.privacy = privacy; | |
}); | |
confirmationMessage += build.title + ' - ' + build.desc + '\n'; | |
} | |
if(window.confirm(confirmationMessage)) { | |
console.log('updating builds'); | |
let skippedBuilds = ''; | |
for(let i=0;i<buildsToPublish.length;i++) { | |
let request = new XMLHttpRequest(); | |
let formData = new FormData(); | |
let build = buildsToPublish[i]; | |
if(!build.desc || !build.language || !build.privacy) { | |
skippedBuilds += 'skipped ' + build.title + '\n'; | |
continue; | |
} | |
formData.append("desc", build.desc); | |
formData.append("language", build.language); | |
formData.append("privacy", build.privacy); | |
formData.append("agree", build.agree); | |
formData.append("cloudFileName", build.cloudFileName); | |
formData.append("heroName", build.heroName); | |
formData.append("heroTag", build.heroTag); | |
formData.append("title", build.title); | |
formData.append("publishedfileid", build.publishedfileid); | |
request.open("POST", "http://www.dota2.com/workshop/builds/submit_update"); | |
request.send(formData); | |
console.log('updated build ' + build.title); | |
}; | |
if(skippedBuilds) { | |
alert('Not all builds were published succesfully. Try again or publish them manually.\n' + skippedBuilds) | |
} else { | |
alert('All builds published!'); | |
} | |
window.location.reload(); | |
}; | |
} else { | |
alert('No builds to publish'); | |
} | |
jQuery.ajaxSetup({async:true}); | |
} | |
function hideOriginal() { | |
let heading = $("#fileOperationsContent > h3"); | |
heading.click(function() { $('#files').toggle();}); | |
heading.css('cursor', 'pointer') | |
$('#files').hide(); | |
} | |
function loadExtension() { | |
$.fn.dataTableExt.afnFiltering.push( | |
function( oSettings, aData, iDataIndex ) { | |
var startDate = document.getElementById(startDateId).value, | |
endDate = document.getElementById(endDateId).value, | |
dateCol = 5, | |
buildDate=new Date(aData[dateCol]); | |
if ( startDate === "" && endDate === "" ) | |
{ | |
return true; | |
} | |
else if ( startDate !== "" && endDate === "") | |
{ | |
return new Date(startDate) <= buildDate; | |
} | |
else if (endDate !== "" && startDate === "") | |
{ | |
return new Date(endDate) >= buildDate; | |
} | |
else if (new Date(startDate) <= buildDate && new Date(endDate) >= buildDate) | |
{ | |
return true; | |
} | |
return false; | |
} | |
); | |
} | |
function addCss() { | |
var dataTablesCssId = 'datatablesCss'; | |
if($('#' +dataTablesCssId).length === 0) { | |
console.log('datatables css not found, adding now'); | |
$('head').append('<link id="' + dataTablesCssId + '" rel="stylesheet" href="//cdn.datatables.net/1.10.11/css/jquery.dataTables.min.css" type="text/css" />'); | |
} | |
} | |
function redrawTable() { | |
$('#' + buildsTableId).DataTable().draw(); | |
} | |
function addDateFilters() { | |
var startDateInput = $('<input id="' + startDateId + '" type="datetime-local"></input>'); | |
var endDateInput = $('<input id="' + endDateId + '" type="datetime-local"></input>'); | |
startDateInput.change(redrawTable); | |
endDateInput.change(redrawTable); | |
$('#fileOperationsContent').append(startDateInput); | |
$('#fileOperationsContent').append(endDateInput); | |
} | |
function initializeTable() { | |
jQuery.ajaxSetup({async:false}); | |
customQueryForCloudFileDetails(0); // get build info for all builds (not only the ones on current page) | |
jQuery.ajaxSetup({async:true}); | |
var buildsTable = $('#'+buildsTableId); | |
if(buildsTable.length === 0) { | |
console.log('No table found, creating new one'); | |
buildsTable = $('<table id="' + buildsTableId + '" />'); | |
$('#fileOperationsContent').append(buildsTable); | |
} else { | |
return; | |
} | |
var builds = []; | |
for(var i=0;i<g_Builds.buildInfo.length;i++){ | |
let build = g_Builds.buildInfo[i]; | |
let heroData = g_rgHeroData[build.heroName]; | |
if(!heroData) { | |
console.log('No data found for', build, g_rgHeroData); | |
} | |
builds.push([ | |
i, | |
build.heroPortrait, | |
build.heroName + ' ' + heroData.dname, | |
build.title, | |
build.filename, | |
new Date(build.timestamp*1000)]); | |
} | |
buildsTable.DataTable({ | |
data: builds, | |
columns: [ | |
{ title: "index", render: function(data, type, row) { return '<div class="fileOperationSelector disableClickClear" index="' + data + '" onclick="selectorClicked(this)"></div>'; }}, | |
{ title: ""}, | |
{ title: "Hero", visible: false}, | |
{ title: "Title", | |
width: '80%', | |
render: function(data, type, row) { return '<div style="cursor: pointer" onclick="fileSectionClicked(' + row[0] + ')">' + data + '</div>'} }, | |
{ title: "filename", visible: false }, | |
{ title: "Time" } | |
], | |
paging: false, | |
}); | |
}} | |
function customQueryForCloudFileDetails(startIndex) { | |
// Post for our details | |
var numResults = Math.min( NUM_BUILDS_PER_PAGE, g_TotalFiles ); | |
var targetFileIds = []; | |
for ( var i = startIndex; i < g_Builds.buildInfo.length; i++ ) { | |
// Don't cache something we already have | |
if ( g_Builds.buildInfo[i].hasOwnProperty('cached') && g_Builds.buildInfo[i].cached ) | |
continue; | |
// Add to the request | |
targetFileIds.push({ | |
ugcid: g_Builds.buildInfo[i].ugcid, | |
filename: g_Builds.buildInfo[i].filename, | |
timestamp: g_Builds.buildInfo[i].timestamp | |
}); | |
} | |
// Handle the "all cached" case | |
if ( targetFileIds.length == 0 ) { | |
populateCloudFiles(); | |
return; | |
} | |
showLoadingEffects(); | |
// Do the actual POST | |
$.post( 'http://www.dota2.com/workshop/builds/details', | |
{ "files": targetFileIds } | |
).success( function( data ) { | |
if ( data.success != 1 ) { | |
showErrorMessageBox("Failed to enumerate Steam Cloud files. Please try again shortly!"); | |
return; | |
} | |
// Pull the data into our internal format | |
for ( var key in data.files ) { | |
if ( !data.files.hasOwnProperty( key ) ) | |
continue; | |
addBuildInfo( data.files[key] ); | |
} | |
// Actually fill in the data now | |
populateCloudFiles(); | |
}).fail( function() { | |
if ( !g_PageUnloading ) { | |
showErrorMessageBox( "Failed to enumerate Steam Cloud files. Please try again shortly!" ); | |
} | |
}); | |
} | |
})() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment