// ==UserScript==
// @name ASF STM
// @language English
// @namespace https://greasyfork.org/users/2205
// @description ASF bot list trade matcher
// @include http*://steamcommunity.com/id/*/badges
// @include http*://steamcommunity.com/id/*/badges/
// @include http*://steamcommunity.com/profiles/*/badges
// @include http*://steamcommunity.com/profiles/*/badges/
// @version 1.0
// @connect asf.justarchi.net
// @grant GM.xmlhttpRequest
// @grant GM_xmlhttpRequest
// ==/UserScript==
/* global g_steamID */
(function()
{
const limiter = 0;
const debug = false;
const maxErrors = 5;
let errors=0;
let bots;
let assets=[];
let descriptions=[];
let mybadges=[];
let userbadges=[];
let maxpages;
function debugProfile(name){
if (debug) {
console.time(name);
}
}
function debugProfileEnd(name){
if (debug) {
console.timeEnd(name);
}
}
function debugPrint(msg){
if (debug) {
console.log(msg);
}
}
function getPartner(str) {
return (BigInt(str)%BigInt(4294967296)).toString(); // eslint-disable-line
}
function EnableButton(){
let buttondiv=document.getElementById("asf_stm_button_div");
buttondiv.setAttribute("class","profile_small_header_additional");
let button=document.getElementById("asf_stm_button");
button.addEventListener("click",ButtonPressed, false);
}
function DisableButton(){
let buttondiv=document.getElementById("asf_stm_button_div");
buttondiv.setAttribute("class","profile_small_header_additional btn_disabled");
let button=document.getElementById("asf_stm_button");
button.removeEventListener("click",ButtonPressed, false);
}
function UpdateMessage(text){
let message=document.getElementById("asf_stm_message");
message.textContent=text;
}
function HideMessage(){
let messagebox=document.getElementById("asf_stm_messagebox");
messagebox.setAttribute("style","display: none;");
}
function HideThrobber(){
let throbber=document.getElementById("throbber");
throbber.setAttribute("style","display: none;");
}
function UpdateProgress(index){
let bar=document.getElementById("asf_stm_progress");
let progress = 100*((index+1)/bots.length);
bar.setAttribute("style","width: "+progress+"%;");
}
function populateCards(item) {
let classlist = "";
let htmlCards = "";
for (let j=0;j<item.cards.length; j++) {
let item_icon = item.cards[j].icon_url;
let item_name = item.cards[j].item.substring(item.cards[j].item.indexOf("-")+1);
for (let k=0; k<item.cards[j].count; k++) {
if (classlist!=""){
classlist+=";";
}
classlist+=item.cards[j].class;
let cardTemplate =`
<div class="showcase_slot">
<img class="image-container" src="https://steamcommunity-a.akamaihd.net/economy/image/${item_icon}/98x115">
<div class="commentthread_subscribe_hint" style="width: 98px;">${item_name}</div>
</div>
`;
htmlCards+=cardTemplate;
}
}
return {"htmlCards":htmlCards,"classlist": classlist};
}
function getClasses(item){
let classes="";
for (let j=0;j<item.cards.length; j++) {
for (let k=0; k<item.cards[j].count; k++) {
if (classes!=""){
classes+=";";
}
classes+=item.cards[j].class;
}
}
return classes;
}
function UpdateTrade(row) {
let index=row.id.split("_")[1];
let tradelink = row.getElementsByClassName("full_trade_url")[0];
let spliturl=tradelink.href.split("&");
let them = "";
let you = "";
let filterWidget = document.getElementById("asf_stm_filters");
for (let i = 0; i < bots[index].itemsToSend.length; i++){
let appid=bots[index].itemsToSend[i].appid;
let checkbox=filterWidget.getElementsBySelector("#astm_"+appid)[0];
if (checkbox.checked) {
if (you!=""){
you+=";";
}
you=you+getClasses(bots[index].itemsToSend[i]);
if (them!=""){
them+=";";
}
them=them+getClasses(bots[index].itemsToReceive[i]);
}
}
spliturl[3]="them="+them;
spliturl[4]="you="+you;
tradelink.href=spliturl.join("&");
}
function CheckRow(row){
debugPrint("CheckRow");
let matches = row.getElementsByClassName("badge_row");
let visible = false;
for (let i=0; i<matches.length;i++) {
if (matches[i].parentElement.visible()){
visible = true;
break;
}
}
if (visible) {
row.show();
UpdateTrade(row);
} else {
row.hide();
}
}
function AddMatchRow(index,botname){
debugPrint("AddMatchRow "+index);
let itemsToSend=bots[index].itemsToSend;
let itemsToReceive=bots[index].itemsToReceive;
let tradeurl="https://steamcommunity.com/tradeoffer/new/?partner="+getPartner(bots[index].steam_id)+"&token="+bots[index].trade_token+"&source=stm";
let globalyou="";
let globalthem="";
let matches = "";
let any = "";
if (bots[index].match_everything==1) {
any=` <sup><span class="avatar_block_status_in-game" style="font-size: 8px; cursor:help" title="This bots trades for any cards within same set"> ANY </span></sup>`;
}
for (let i=0;i<itemsToSend.length;i++) {
let appid = itemsToSend[i].appid;
let itemToReceive = itemsToReceive.find(a => a.appid == appid);
let gameName = itemsToSend[i].title;
let display = "inline-block";
//remove placeholder
let filterWidget = document.getElementById("asf_stm_filters");
let placeholder = filterWidget.getElementsBySelector("#asf_stm_placeholder");
if (placeholder.length!=0) {
placeholder[0].remove();
}
//add filter
let checkboxes=filterWidget.getElementsBySelector("#astm_"+appid);
if (checkboxes.length==0) {
let newFilter=`<span style="margin-right: 15px; white-space: nowrap; display: inline-block;"><input type="checkbox" id="astm_${appid}" checked="">${gameName}</span>`
let spanTemplate = document.createElement('template');
spanTemplate.innerHTML = newFilter.trim();
filterWidget.appendChild(spanTemplate.content.firstChild);
} else {
if (checkboxes[0].checked == false){
display = "none"
}
}
let sendResult = populateCards(itemsToSend[i]);
let receiveResult = populateCards(itemToReceive);
let tradeurlappid=tradeurl+"&them="+receiveResult.classlist+"&you="+sendResult.classlist;
let matchTemplate = `
<div class="asf_stm_appid_${appid}" style="display:${display}">
<div class="badge_row is_link goo_untradable_note showcase_slot">
<div class="notLoggedInText">
<img alt="${gameName}" src="https://steamcdn-a.akamaihd.net/steam/apps/${appid}/capsule_184x69.jpg">
<div>
<div title="View badge progress for this game">
<a target="_blank" href="https://steamcommunity.com/my/gamecards/${appid}/">${gameName}</a>
</div>
</div>
<div class="btn_darkblue_white_innerfade btn_medium">
<span>
<a href="${tradeurlappid}" target="_blank" rel="noopener">Offer a trade</a>
</span>
</div>
</div>
<div class="showcase_slot">
<div class="showcase_slot profile_header">
<div class="badge_info_unlocked profile_xp_block_mid avatar_block_status_in-game badge_info_title badge_row_overlay" style="height: 15px;">You</div>
${sendResult.htmlCards}
</div>
<span class="showcase_slot badge_info_title booster_creator_actions">
<h1>➡</h1>
</span>
</div>
<div class="showcase_slot profile_header">
<div class="badge_info_unlocked profile_xp_block_mid avatar_block_status_online badge_info_title badge_row_overlay ellipsis" style="height: 15px;">
${botname}
</div>
${receiveResult.htmlCards}
</div>
</div>
</div>
`;
if (checkboxes.length==0 || checkboxes[0].checked) {
matches+=matchTemplate;
if (globalyou!=""){
globalyou+=";";
};
globalyou+=sendResult.classlist;
if (globalthem!=""){
globalthem+=";";
};
globalthem+=receiveResult.classlist
}
}
let tradeurlfull = tradeurl+"&them="+globalthem+"&you="+globalyou;
let rowTemplate = `
<div id="asfstmbot_${index}" class="badge_row">
<div class="badge_row_inner">
<div class="badge_title_row guide_showcase_contributors">
<div class="badge_title_stats">
<div class="btn_darkblue_white_innerfade btn_medium">
<span>
<a class="full_trade_url" href="${tradeurlfull}" target="_blank" rel="noopener" >Offer a trade for all</a>
</span>
</div>
</div>
<div class="badge_title">
${botname}${any}
</div>
</div>
<div class="badge_title_rule"></div>
${matches}
</div>
</div>
`;
let template = document.createElement('template');
template.innerHTML = rowTemplate.trim();
let maincontent = document.getElementsByClassName("maincontent")[0];
let newchild = template.content.firstChild;
maincontent.appendChild(newchild);
CheckRow(newchild);
}
function DeepClone(object) {
return JSON.parse(JSON.stringify(object));
}
function fetchinventory(steamid,startasset,callback) {
let url="https://steamcommunity.com/inventory/"+steamid+"/753/6?l=english&count=5000&l=english";
if (startasset>0) {
url=url+"&start_assetid="+startasset.toString();
} else {
assets.clear();
descriptions.clear();
}
debugPrint(url);
let xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'json';
xhr.onload = function() {
debugPrint("...");
let status = xhr.status;
let lastasset=startasset;
if (status === 200) {
errors = 0;
if (typeof(xhr.response) !== 'undefined') {
if (typeof(xhr.response.descriptions) !== 'undefined') {
assets=assets.concat(xhr.response.assets);
descriptions=descriptions.concat(xhr.response.descriptions);
if (typeof(xhr.response.last_assetid) == 'undefined') { //end of inventory
debugPrint("total_inventory_count = "+xhr.response.total_inventory_count);
callback();
return;
} else {
lastasset=xhr.response.last_assetid;
}
}
}
} else {
errors++;
debugPrint("HTTP Error="+status);
}
if (status==403) {
assets.clear(); //switch to next bot
callback();
} else if ((status<400 || status>=500 || status==408)&&(errors <= maxErrors)) {
setTimeout((function(steamid,startasset,callback) { return function(){ fetchinventory(steamid,startasset,callback); };})(steamid,lastasset,callback), limiter);
} else {
UpdateMessage("Error getting inventory, ERROR "+status);
HideThrobber();
EnableButton();
}
}
xhr.onerror = function() {
errors++;
if (errors <= maxErrors) {
setTimeout((function(steamid,startasset,callback) { return function(){ fetchinventory(steamid,startasset,callback); };})(steamid,startasset,callback), limiter);
} else {
debugPrint("error getting inventory");
UpdateMessage("Error getting inventory");
HideThrobber();
EnableButton();
}
}
xhr.send();
}
function CalcState(badge) { //state 0 - less than max sets; state 1 - we have max sets, even out the rest, state 2 - all even
let state = 0;
if (badge.cards[0].count == badge.lastset) {
return 2; //nothing to do
} else if (badge.cards[badge.maxcards-1].count == badge.maxsets) {
return 1; //max sets are here, but we can distribute cards further
}
return 0; //less than max sets
}
function CompareCards(index,callback) {
let itemsToSend=[];
let itemsToReceive=[];
userbadges.clear();
userbadges = DeepClone(mybadges);
for (let i = 0; i < userbadges.length; i++) {
userbadges[i].cards.clear();
}
PopulateExistingCards(userbadges,false);
debugPrint("bot's cards");
debugPrint(DeepClone(userbadges));
debugPrint("our cards");
debugPrint(DeepClone(mybadges));
for(let i = 0; i < userbadges.length; i++) {
let mybadge = DeepClone(mybadges[i]);
let theirbadge = DeepClone(userbadges[i]);
let mystate=CalcState(mybadge);
while (mystate<2) {
let foundmatch=false;
for (let j = 0; j<theirbadge.maxcards; j++) { //index of card they give
if (theirbadge.cards[j].count > 0) {
//try to match
//if (bots[index].match_everything) {}
let myInd = mybadge.cards.findIndex(a => a.item == theirbadge.cards[j].item); //index of slot where we receive card
if (myInd==-1) {
debugPrint("we don't have it");
let empty = mybadge.cards.find(card => card.item==null);
if (empty != undefined) {
debugPrint("found a place!");
empty.item=theirbadge.cards[j].item;
empty.icon_url=theirbadge.cards[j].icon_url;
myInd=mybadge.cards.indexOf(empty);
} else {
debugPrint("Error! We found more cards than expected");
debugPrint(DeepClone(mybadge.cards));
debugPrint(DeepClone(theirbadge.cards));
}
}
if ((mystate==0 && mybadge.cards[myInd].count < mybadge.maxsets) ||
(mystate==1 && mybadge.cards[myInd].count < mybadge.lastset)) { //we need this ^Kfor the Emperor
debugPrint("we need this: "+theirbadge.cards[j].item+" ("+theirbadge.cards[j].count+")");
//find a card to match.
for (let k = 0; k < myInd; k++) { //index of card we give
debugPrint("i="+i+" j="+j+" k="+k+" mystate="+mystate);
debugPrint("we have this: "+mybadge.cards[k].item+" ("+mybadge.cards[k].count+")");
if ((mystate==0 && mybadge.cards[k].count>mybadge.maxsets) ||
(mystate==1 && mybadge.cards[k].count>mybadge.lastset)) { //that's fine for us
debugPrint("it's a good trade for us");
let theirInd = theirbadge.cards.findIndex(a => a.item == mybadge.cards[k].item); //index of slot where they will receive card
if (theirInd == -1) { //they don't even know this card
theirInd = theirbadge.cards.findIndex(a => a.item == null); //index of empty space
//it's safe to assign item name to this card, they don't have it
theirbadge.cards[theirInd].item = mybadge.cards[k].item;
}
if (bots[index].match_everything==0) { //make sure it's neutral+ for them
if (theirbadge.cards[theirInd].count >= theirbadge.cards[j].count) {
debugPrint("Not fair for them")
debugPrint("they have this: "+theirbadge.cards[theirInd].item+" ("+theirbadge.cards[theirInd].count+")");
continue; //it's not neutral+, check other options
}
}
debugPrint("it's a match!");
let itemToSend = {"item":mybadge.cards[k].item,"count":1, "class":mybadge.cards[k].class, "icon_url":mybadge.cards[k].icon_url};
let itemToReceive = {"item":theirbadge.cards[j].item,"count":1, "class":theirbadge.cards[j].class, "icon_url":theirbadge.cards[j].icon_url};
//fill items to send
let sendmatch = itemsToSend.find(item => item.appid == mybadges[i].appid);
if (sendmatch == undefined) {
let newmatch = {"appid":mybadges[i].appid, "title":mybadge.title ,"cards":[ itemToSend ]};
itemsToSend.push(newmatch);
} else {
let existingCard = sendmatch.cards.find(a => a.item == itemToSend.item);
if (existingCard == undefined) {
sendmatch.cards.push(itemToSend);
} else {
existingCard.count += 1;
}
}
//add this item to their inventory
theirbadge.cards[theirInd].count +=1;
//remove this item from our inventory
mybadge.cards[k].count -= 1;
//fill items to receive
let receivematch = itemsToReceive.find(item => item.appid == mybadges[i].appid);
if (receivematch == undefined) {
let newmatch = {"appid":mybadges[i].appid,"title":mybadge.title,"cards":[ itemToReceive ]};
itemsToReceive.push(newmatch);
} else {
let existingCard = sendmatch.cards.find(a => a.item == itemToReceive.item);
if (existingCard == undefined) {
receivematch.cards.push(itemToReceive);
} else {
existingCard.count += 1;
}
}
//add this item to our inventory
mybadge.cards[myInd].count +=1;
//remove this item from their inventory
theirbadge.cards[j].count -= 1;
foundmatch=true;
break; //found a match!
}
}
}
}
}
if (!foundmatch) {
break; //found no matches - move to next badge
}
mybadge.cards.sort((a,b)=>b.count-a.count);
theirbadge.cards.sort((a,b)=>b.count-a.count);
mystate=CalcState(mybadge);
}
}
debugPrint("items to send");
debugPrint(DeepClone(itemsToSend));
debugPrint("items to receive");
debugPrint(DeepClone(itemsToReceive));
bots[index].itemsToSend = itemsToSend;
bots[index].itemsToReceive = itemsToReceive;
if (itemsToSend.length>0){
getUsername(index,callback);
} else {
debugPrint("no matches");
callback();
}
}
function getUsername(index,callback){
let url="https://steamcommunity.com/profiles/"+bots[index].steam_id+"?xml=1";
let xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'text';
//xhr.setRequestHeader("Range","bytes=0-200"); //fuck it, get the whole page
xhr.onload = function() {
let status = xhr.status;
let username=bots[index].steam_id;
debugPrint("getting username");
if (status === 200) {
errors = 0;
let re = /<steamID><!\[CDATA\[(.+)]]><\/steamID>/g;
username = re.exec(xhr.response)[1];
debugPrint(username);
AddMatchRow(index,username);
callback();
} else {
errors++;
if (errors <= maxErrors) {
setTimeout((function(index,callback) {return function(){ getUsername(index,callback); } })(index,callback), limiter);
} else {
debugPrint("error HTTP Status="+status);
UpdateMessage("Error getting username data, ERROR="+status);
HideThrobber();
EnableButton();
}
}
};
xhr.onerror = function() {
errors++;
if (errors <= maxErrors) {
setTimeout((function(index,callback) {return function(){ getUsername(index,callback); } })(index,callback), limiter);
} else {
debugPrint("error");
UpdateMessage("Error getting username data");
HideThrobber();
EnableButton();
}
};
xhr.send();
}
function checkuser(index){
debugPrint(index);
UpdateMessage("Fetching bot "+(index+1).toString()+" of "+bots.length.toString());
UpdateProgress(index);
fetchinventory(bots[index].steam_id,0,function() {
debugPrint(bots[index].steam_id);
debugPrint(assets.length);
CompareCards(index, function() {
if (index<bots.length-1) {
setTimeout((function(index) { return function(){ checkuser(index); };})(index+1), limiter);
} else {
debugPrint("finished");
debugPrint(new Date(Date.now()));
console.log(new Date(Date.now()));
HideThrobber();
HideMessage();
UpdateProgress(bots.length-1);
EnableButton();
}
});
});
}
function PopulateExistingCards(badges, filter){
debugProfile("PopulateExistingCards1");
debugPrint(DeepClone(assets));
debugPrint(DeepClone(descriptions));
descriptions=descriptions.filter(desc=>badges.find(item=>item.appid==desc.market_hash_name.split("-")[0])!=undefined);
assets=assets.filter(asset=>descriptions.find(item=>item.classid==asset.classid)!=undefined);
for (let i = 0; i < assets.length; i++){
debugPrint(".");
let descr = descriptions.find(desc=>desc.classid==assets[i].classid); // eslint-disable-line
if (descr != undefined) {
let appid=descr.market_hash_name.split("-")[0];
let title=appid;
let game_tag=descr.tags.find(tag=>tag.category=="Game");
if (game_tag != undefined) {
title=game_tag.localized_tag_name;
}
let item_class_tag=descr.tags.find(tag=>tag.category=="item_class");
if (item_class_tag != undefined) {
if (item_class_tag.internal_name == "item_class_2") {
let cardborder_tag=descr.tags.find(tag=>tag.category=="cardborder");
if (cardborder_tag != undefined) {
if (cardborder_tag.internal_name == "cardborder_0") {
let badge = badges.find(badge=>badge.appid==appid);
if (badge != undefined) {
let card=badge.cards.find(card=>card.item==descr.market_hash_name);
if (card == undefined) {
let newcard = {"item":descr.market_hash_name, "count":1,"class": assets[i].classid ,"icon_url":descr.icon_url};
badge.cards.push(newcard);
badge.title = title;
} else {
card.count+=1;
}
}
}
}
}
}
}
}
debugProfileEnd("PopulateExistingCards1");
debugProfile("PopulateExistingCards2");
for (let i = badges.length-1; i >=0; i--) {
for (let j = badges[i].cards.length; j < badges[i].maxcards; j++){
badges[i].cards.push({"item":null, "count":0,"class":0, "icon_url":null}); //fill missing cards with dummy element
}
badges[i].cards.sort((a,b)=>b.count-a.count);
if (filter) {
if (badges[i].cards[0].count-badges[i].cards[badges[i].cards.length-1].count<2) {
//nothing to match, remove from list.
badges.splice(i,1);
continue;
}
}
let totalcards = 0;
for (let j = 0; j<badges[i].maxcards; j++) {
totalcards+=badges[i].cards[j].count;
}
badges[i].maxsets = Math.floor(totalcards/badges[i].maxcards);
badges[i].lastset = Math.ceil(totalcards/badges[i].maxcards);
}
debugProfileEnd("PopulateExistingCards2");
}
function PopulateMaxcards(index){
while (index < mybadges.length) {
if (mybadges[index].maxcards === 0) {
let url="https://steamcommunity.com/my/gamecards/"+mybadges[index].appid+"?l=english";
let xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'document';
xhr.onload = function() { // eslint-disable-line
let status = xhr.status;
let lastasset=0;
if (status === 200) {
errors = 0;
debugPrint("processing badge "+mybadges[index].appid);
UpdateMessage("Getting badge data for "+mybadges[index].appid);
let maxcards = xhr.response.documentElement.getElementsByClassName("gamecard").length;
mybadges[index].maxcards=maxcards;
index++;
} else {
errors++;
}
if ((status<400 || status>=500)&&(errors <= maxErrors)) {
setTimeout((function(index) { return function(){ PopulateMaxcards(index); };})(index), limiter);
} else {
UpdateMessage("Error getting badge data, ERROR "+status);
HideThrobber();
EnableButton();
}
};
xhr.onerror = function() { // eslint-disable-line
errors++;
if (errors <= maxErrors) {
setTimeout((function(index) { return function(){ PopulateMaxcards(index); };})(index), limiter);
return;
} else {
debugPrint("error");
UpdateMessage("Error getting badge data");
HideThrobber();
EnableButton();
}
};
xhr.send();
return; //do this synchronously to avoid rate limit
} else {
index++;
}
}
debugPrint("populated");
UpdateMessage("Fetching own inventory");
//g_steamID is a global steam variable
fetchinventory(g_steamID,0,function(){
debugPrint("fetched");
debugPrint(DeepClone(assets));
debugPrint(DeepClone(descriptions));
debugPrint("our cards");
debugPrint(DeepClone(mybadges));
PopulateExistingCards(mybadges,true);
checkuser(0);
});
}
function getbadges(page){
let url="https://steamcommunity.com/my/badges?p="+page+"&l=english";
let xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'document';
xhr.onload = function() {
let status = xhr.status;
if (status === 200) {
errors = 0;
debugPrint("processing page "+page);
UpdateMessage("Processing badges page "+page);
if (page===1) {
let pagelinks=xhr.response.documentElement.getElementsByClassName("pagelink");
if (pagelinks.length>0) {
maxpages=Number(pagelinks[pagelinks.length-1].textContent.trim());
}
}
let badges=xhr.response.documentElement.getElementsByClassName("badge_row_inner");
for (let i=0;i<badges.length;i++){
if (badges[i].getElementsByClassName("owned").length>0){ //we only need badges where we have at least one card, and no special badges
let appidNodes = badges[i].getElementsByClassName("card_drop_info_dialog");
if (appidNodes.length>0) {
let appidText=appidNodes[0].getAttribute("id");
let appidSplitted = appidText.split("_");
if (appidSplitted.length >= 5) {
let appid = Number(appidSplitted[4]);
let maxcards=0;
if (badges[i].getElementsByClassName("badge_craft_button").length === 0 ){
let maxcardsText=badges[i].getElementsByClassName("badge_progress_info")[0].innerText.trim()
let maxcardsSplitted=maxcardsText.split(" ");
maxcards = Number(maxcardsSplitted[2]);
}
let badge_stub = {"appid":appid,"title":null, "maxcards":maxcards, "maxsets":0, "lastset":0, "cards":[]};
mybadges.push(badge_stub);
}
}
}
}
page++;
} else {
errors++;
}
if ((status<400 || status>=500)&&(errors <= maxErrors)) {
if (page<=maxpages) {
setTimeout((function(page) { return function(){ getbadges(page); };})(page), limiter);
} else {
debugPrint("all badge pages processed");
if (mybadges.length===0){
HideThrobber();
UpdateMessage("No cards to match");
return;
} else {
PopulateMaxcards(0);
}
}
} else {
UpdateMessage("Error getting badge data, ERROR "+status);
HideThrobber();
EnableButton();
}
};
xhr.onerror = function() {
errors++;
if (errors <= maxErrors) {
setTimeout((function(page) { return function(){ getbadges(page); };})(page), limiter);
} else {
debugPrint("error getting badge page");
UpdateMessage("Error getting badge page");
HideThrobber();
EnableButton();
}
};
xhr.send();
}
function FilterEventHandler(event){
let appid = event.target.id.split("_")[1];
let matches = document.getElementsByClassName("asf_stm_appid_"+appid);
for (let i = 0; i<matches.length; i++) {
matches[i].style.display = event.target.checked ? "inline-block" : "none";
CheckRow(matches[i].parentElement.parentElement);
}
}
function FiltersButton(){
let filterWidget = document.getElementById("asf_stm_filters");
if (filterWidget.style.marginRight == "-50%") {
filterWidget.style.marginRight ="unset";
} else {
filterWidget.style.marginRight ="-50%";
}
}
function ButtonPressed(){
DisableButton();
debugPrint(new Date(Date.now()));
console.log(new Date(Date.now()));
let maincontent = document.getElementsByClassName("maincontent")[0];
maincontent.textContent="";
maincontent.style.width="90%";
maincontent.innerHTML=`
<div class="profile_badges_header">
<div id="throbber">
<div class="LoadingWrapper">
<div class="LoadingThrobber">
<div class="Bar Bar1"></div>
<div class="Bar Bar2"></div>
<div class="Bar Bar3"></div>
</div>
</div>
</div>
<div>
<div id="asf_stm_messagebox" class="profile_badges_header">
<div id="asf_stm_message" class="profile_badges_header_title" style="text-align: center;">Initialization</div>
</div>
</div>
<div class="profile_xp_block_remaining_bar">
<div id="asf_stm_progress" class="profile_xp_block_remaining_bar_progress" style="width: 0%"></div>
</div>
</div>
<div id="asf_stm_filters" style="position: fixed; z-index: 1000; right: 5px; bottom: 45px; transition-duration: 500ms; transition-timing-function: ease; margin-right: -50%;padding: 5px;max-width: 40%;display: inline-block;border-radius: 2px;background: rgba( 103, 193, 245, 0.2 );color: #67c1f5;">
<span id="asf_stm_placeholder" style="margin-right: 15px;">No matches to filter</span>
</div>
<div style="position: fixed;z-index: 1000;right: 5px;bottom: 5px;" id="asf_stm_filters_button_div">
<a id="asf_stm_filters_button" class="btnv6_blue_hoverfade btn_medium">
<span>Filters</span>
</a>
</div>
`;
document.getElementById("asf_stm_filters").addEventListener("input",FilterEventHandler);
document.getElementById("asf_stm_filters_button").addEventListener("click", FiltersButton, false);
maxpages=1;
getbadges(1);
}
if (document.getElementsByClassName("badge_details_set_favorite").length != 0) {
let requestURL = 'https://asf.justarchi.net/Api/Bots';
GM_xmlhttpRequest({
method: "GET",
url: requestURL,
onload: function(response) {
let re = /("steam_id":)(\d+)/g;
let fixedjson = response.response.replace(re, '$1\"$2\"'); //because fuck js
bots = JSON.parse(fixedjson);
//bots.filter(bot=>bot.matchable_cards===1||bot.matchable_foil_cards===1); //I don't think this is really needed
bots.sort(function(a,b) { //sort received array as I like it.
let result = b.match_everything - a.match_everything; //bots with match_everything go first
if (result===0) {
result = b.items_count - a.items_count; //then by items_counts descending
}
if (result===0) {
result = b.games_count - a.games_count; //then by games_count descending
}
return result;
});
debugPrint ("found total "+bots.length+" bots");
let buttondiv =document.createElement("div");
buttondiv.setAttribute("class","profile_small_header_additional");
buttondiv.setAttribute("style","margin-top: 40px;");
buttondiv.setAttribute("id","asf_stm_button_div");
let button = document.createElement("a");
button.setAttribute("class","btnv6_blue_hoverfade btn_medium");
button.setAttribute("id","asf_stm_button");
button.appendChild(document.createElement("span"));
button.firstChild.appendChild(document.createTextNode("Scan ASF STM"))
buttondiv.appendChild(button);
let anchor = document.getElementsByClassName("profile_small_header_texture")[0];
anchor.appendChild(buttondiv);
EnableButton();
}
});
}
})();