Decklog To Tabletop simulator script

Download TCG card from Decklog and import to Tabletop simulator as deck item

// ==UserScript==
// @name         Decklog To Tabletop simulator script
// @namespace    http://tampermonkey.net/
// @version      2.1
// @description  Download TCG card from Decklog and import to Tabletop simulator as deck item
// @author       Royal
// @match        https://decklog.bushiroad.com/view/*
// @grant        GM_download
// @grant        GM_setClipboard
// @grant        GM_xmlhttpRequest
// @require http://code.jquery.com/jquery-3.4.1.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js
// @require https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.3/js/bootstrap.min.js
// ==/UserScript==


(function(){var c;c=jQuery;c.bootstrapGrowl=function(f,a){var b,e,d;a=c.extend({},c.bootstrapGrowl.default_options,a);b=c("<div>");b.attr("class","bootstrap-growl alert");a.type&&b.addClass("alert-"+a.type);a.allow_dismiss&&(b.addClass("alert-dismissible"),b.append('<button class="close" data-dismiss="alert" type="button"><span aria-hidden="true">&#215;</span><span class="sr-only">Close</span></button>'));b.append(f);a.top_offset&&(a.offset={from:"top",amount:a.top_offset});d=a.offset.amount;c(".bootstrap-growl").each(function(){return d= Math.max(d,parseInt(c(this).css(a.offset.from))+c(this).outerHeight()+a.stackup_spacing)});e={position:"body"===a.ele?"fixed":"absolute",margin:0,"z-index":"9999",display:"none"};e[a.offset.from]=d+"px";b.css(e);"auto"!==a.width&&b.css("width",a.width+"px");c(a.ele).append(b);switch(a.align){case "center":b.css({left:"50%","margin-left":"-"+b.outerWidth()/2+"px"});break;case "left":b.css("left","20px");break;default:b.css("right","20px")}b.fadeIn();0<a.delay&&b.delay(a.delay).fadeOut(function(){return c(this).alert("close")}); return b};c.bootstrapGrowl.default_options={ele:"body",type:"info",offset:{from:"top",amount:20},align:"right",width:250,delay:4E3,allow_dismiss:!0,stackup_spacing:10}}).call(this);

//declare all globle var
var scrUIdata = "";
var urllisttostring = "";
var cardidtostring = "";
var cardtitletostring = "";
var carddesctostring = "";
var allfinish = false;
var totalnum = "";
var lua_base = "";
var carddata = "";
var cardback = "";
var cardid = "";
var craddescarray = [];
var cardidarray = [];
var target = document.querySelector("#loader-bg");
var runcheck = true;
// create an observer instance
var observer = new MutationObserver(function (mutations) {
  mutations.forEach(async function (mutation) {
    //alert("mutation");
    await doruncheck();
  });
});

// configuration of the observer:
var config = { attributes: true };
var target2 = document.querySelector(".body-page-view");
// create an observer instance
var observer2 = new MutationObserver(function (mutations) {
  mutations.forEach(function (mutation) {
    setTimeout(function () {
      //Code to run After timeout elapses
      remove_landscape_card();
    }, 500); //Two seconds will elapse and Code will execute.
  });
});

// configuration of the observer:
var config2 = { attributes: true, childList: true, characterData: true };
var sqlcardid = "";
var deckname = "";
var deckdesc = "";

//finish declare

(function () {
  "use strict";

  // Your code here...
  $(document).ready(function () {
    //When document has loaded
    console.log("start");

    observer.observe(target, config);
    observer2.observe(target2, config2);
  });
})();

async function doruncheck() {
  if (runcheck == true) {
    //check for page finish
    var stats = $("#loader-bg").attr("style");
    //console.log(stats);
    if (stats.includes("none") == true) {
      await startpage();
      runcheck = false;
    }
  } else {
    //console.log("no check");
  }
}

function startpage() {
  runcheck = false;
  //build UI
  get_UI();
  setTimeout(function () {
    $(".deckview").append(scrUIdata);
    $("#collapseOne").addClass("collapse");
    set_UI_button();
    //show_debug();
  }, 2000);
}

async function get_UI() {
  await GM_xmlhttpRequest({
    method: "GET",
    url:
      "https://raw.githubusercontent.com/RoyalShooter/Decklog-To-Tabletop-simulator-script/main/UI_code/UIhtml_public",
    headers: {
      "User-agent": "Mozilla/4.0 (compatible) Greasemonkey",
      Accept: "application/atom+xml,application/xml,text/xml",
    },
    onload: function (responseDetails) {
      scrUIdata = responseDetails.responseText || "<h1>Error on loding UI</h1>";
      //console.log(scrUIdata);
    },
  });
}
//start hooking all button control
function set_UI_button() {
  $("#scr_download_lua").click(download_TTS_Lua_code);
  $("#scr_download_as_image").click(download_Image);
}

function show_debug() {
  $("#collapseOne").append(
    '<button type="button" id="Testbbt">Testbbt</button>'
  );
  $("#Testbbt").click(Testbbt);
}
//finish set button
function download_Image(zEvent) {
  alert("Downloading as TTS card set");
  $(".deckview")
    .find(".card-item")
    .each(function (index) {
      //console.log(index + ": " + $(this).find("img").attr("title"));
      var name = $(this).find("img").attr("title").replace("/", "-");
      var dl_url = $(this).find("img").attr("src");
      var num =
        "0" +
        $(this).find(".card-controller-inner").find(".num").first().text() +
        "x";
      var path = "Decklog_TTS/"; // use a special folder for all the images
      var arg = {
        url: dl_url,
        name: path + num + " " + name + ".png",
      };
      var result = GM_download(arg);
      //console.log(result);
    });
  //download card back
  var arg = {
    url: "https://www.tcgcard.tw/wp-content/uploads/2020/05/ws_cardback.png",
    name: "Decklog_TTS/00 back.png",
  };
  var result = GM_download(arg);
  //console.log(result);
}

async function download_TTS_Lua_code(zEvent) {
$("#scr_loding").removeClass("d-none");
  // alert ("Test");
  var urllist = [];
  var cardidlist = [];
  var cardtitlelist = [];
  var carddesc = [];
  totalnum = $(".graph-sum-value").text();
  deckname = $("h2").text().replace("デッキ名「", "").replace("」のデッキ", "");
  var deckid = $(location).attr("href");
  console.log(deckid);
  var deckseries = $(".col-lg-6").find("span").first().text();
  deckdesc = deckseries + " \\n" + deckid;

  $(".deckview")
    .find(".card-item")
    .each(function (index) {
      //console.log( index + ": " + $(this).find("img").attr("title"));

      var num = $(this)
        .find(".card-controller-inner")
        .find(".num")
        .first()
        .text();
      var i;
      for (i = 0; i < num; i++) {
        var dl_url = $(this).find("img").attr("src");
        urllist.push(dl_url);
        var name = $(this).find("img").attr("title");
        var spname = name.split(" : ");
        cardidlist.push(spname[0]);
        var escaped_name = escape_charater(spname[1])
        cardtitlelist.push(escaped_name);
      }
    });
  //console.log("'" + urllist.join("','") + "'");
  //console.log("'" + cardidlist.join("','") + "'");
  //console.log("'" + cardtitlelist.join("','") + "'");
  //console.log("'" + carddesc.join("','") + "'");
  //GM_setClipboard("'" + urllist.join("','") + "'");
  urllisttostring = "'" + urllist.join("','") + "'";
  cardidtostring = "'" + cardidlist.join("','") + "'";
  cardtitletostring = "'" + cardtitlelist.join("','") + "'";



var download_desc = $("#scr_progress_bar_show").hasClass("d-none")
if (download_desc == false){
  //alert("do download "+download_desc)
}else{
  //alert("do nothing "+download_desc)
}
  carddesctostring = "'" + craddescarray.join("','") + "'" || "";
  combine();
  $("#scr_loding").addClass("d-none");
}

function remove_landscape_card(zEvent) {
  //alert ("Test");
  const img = new Image();
  $(".deckview")
    .find(".card-item")
    .each(function (index) {
      //console.log( index + ": " + $(this).find("img"));
      const img = new Image();
      //img.onload = function() {
      //    console.log( index + ": " + this.width + 'x' + this.height);
      //}
      img.src = $(this).find("img").attr("src");
      //console.log( index + ": " + img.width + 'x' + img.height);

      if (img.width > img.height) {
        $("#scr_loding").removeClass("d-none");
        var name = $(this).find("img").attr("title");
        var spname = name.split(" : ");
        var yyturl1 =
          "https://yuyu-tei.jp/game_ws/sell/sell_price.php?name=" + spname[0];

        let getimg = new Promise((resolve, reject) => {
          GM_xmlhttpRequest({
            method: "GET",
            url: yyturl1,
            headers: {
              "User-agent": "Mozilla/4.0 (compatible) Greasemonkey",
              Accept: "application/atom+xml,application/xml,text/xml",
            },
            onload: function (responseDetails) {
              //console.log('Request for Atom feed returned ' + responseDetails.status + ' ' + responseDetails.statusText + '\n\n' +'Feed data:\n' + responseDetails.responseText);
              //console.log(responseDetails.responseText)
              var yyturl2 =
                "https://yuyu-tei.jp" +
                $(responseDetails.responseText)
                  .find(".card_list_box")
                  .find("a")
                  .attr("href");

              GM_xmlhttpRequest({
                method: "GET",
                url: yyturl2,
                headers: {
                  "User-agent": "Mozilla/4.0 (compatible) Greasemonkey",
                  Accept: "application/atom+xml,application/xml,text/xml",
                },
                onload: function (responseDetails) {
                  //console.log('Request for Atom feed returned ' + responseDetails.status + ' ' + responseDetails.statusText + '\n\n' +'Feed data:\n' + responseDetails.responseText);
                  //console.log(responseDetails.responseText)
                  var data = responseDetails.responseText;
                  var newimg = $(data)
                    .find(".image_box")
                    .find("img")
                    .first()
                    .attr("src");
                  //console.log(newimg);
                  if (newimg != "") {
                    resolve(newimg);
                  } else {
                    reject("img no found");
                  }
                },
              });
            },
          });
        });

        getimg.then((successdata) => {
          console.log("replace image = "+$(this).find("img").attr("src", successdata));
          $("#scr_loding").addClass("d-none");
        });
      }

      //alert(name);
    });
}

function get_card_id_list() {
  //alert("get_card_id_list");
  var urllist = [];
  var cardidlist = [];
  var cardidtop = [];
  var cardidback = [];
  var cardidtemparray = [];
  var cardidtemp = "";
  var cardtitlelist = [];
  var carddesc = [];
  totalnum = $(".graph-sum-value").text();

  $(".deckview")
    .find(".card-item")
    .each(function (index) {
      //console.log( index + ": " + $(this).find("img").attr("title"));

      var num = $(this)
        .find(".card-controller-inner")
        .find(".num")
        .first()
        .text();
      var i;
      for (i = 0; i < num; i++) {
        var dl_url = $(this).find("img").attr("src");
        urllist.push(dl_url);
        var name = $(this).find("img").attr("title");
        var spname = name.split(" : ");
        cardidtemparray = spname[0].split("-");
        cardidtop = cardidtemparray[0];
        cardidback = cardidtemparray[1].substring(0, 3);
        //console.log(cardidback);
        cardidtemp = cardidtop + "-" + cardidback;
        cardidlist.push(cardidtemp);
        cardidarray = cardidlist;
      }
    });
  //pass "cardidarray[]" to globle var
}

function download_card_id_list(zEvent) {
  get_card_id_list();
  //console.log('"' + cardidarray.join('","') + '"');
  sqlcardid = "cardid = [" + '"' + cardidarray.join('","') + '"' + "]";
  var totext = sqlcardid;
  GM_setClipboard(totext);
  alert("Card ID list complete, Please paste into handler.");
}

function card_desc_download_enable(zEvent) {
  //console.log("card_desc_download_enable");
  $("#scr_progress_bar_show").toggleClass("d-none");
}

function scr_cardback_input_show(zEvent) {
  $("#scr_progress_bar_show").toggleClass("d-none");
}

let get_lua_code = new Promise((resolve, reject) => {
  GM_xmlhttpRequest({
    method: "GET",
    url:
      "https://raw.githubusercontent.com/RoyalShooter/Decklog-To-Tabletop-simulator-script/main/base2",
    headers: {
      "User-agent": "Mozilla/4.0 (compatible) Greasemonkey",
      Accept: "application/atom+xml,application/xml,text/xml",
    },
    onload: function (responseDetails) {
      //console.log('Request for Atom feed returned ' + responseDetails.status + ' ' + responseDetails.statusText + '\n\n' +'Feed data:\n' + responseDetails.responseText);
      //console.log(responseDetails.responseText)
      lua_base = responseDetails.responseText;
      //GM_setClipboard (lua_base);
      if (lua_base != "") {
        resolve(lua_base);
      } else {
        reject("err on base lua");
      }
    },
  });
});

function combine() {
  cardback =
    "https://www.tcgcard.tw/wp-content/uploads/2020/05/ws_cardback.png";
  get_lua_code.then((successdata) => {
    lua_base = successdata;
  });
  var lua_top =
    "local testurl = {" +
    urllisttostring +
    "} \n local cardid = {" +
    cardidtostring +
    "} \n local cardname = {" +
    cardtitletostring +
    "} \n local carddesc = {" +
    carddesctostring +
    "} \n local totalnum = '" +
    totalnum +
    "' \n local deckname = '" +
    deckname +
    "' \n local deckdesc = '" +
    deckdesc +
    "' \n local cardBack = '" +
    cardback +
    "'\n";

  var lua = lua_top + "\n" + lua_base;
  GM_setClipboard(lua);
  //alert("Lua code finished, please paste lua in the scripting tab");
  $.bootstrapGrowl("Lua code finished, please paste lua in the scripting tab", {
    type: 'success', // (null, 'info', 'danger', 'success')
    allow_dismiss: true, // If true then will display a cross to close the popup.
    stackup_spacing: 10 // spacing between consecutively stacked growls.
  });
}

function Testbbt(zEvent) {
  alert("Test2");
  //get_card_data("BFR/S78-042");
  var download_desc = $("#scr_progress_bar_show").hasClass("d-none")
if (download_desc == false){
  //alert("do download "+download_desc)
}else{
  //alert("do nothing "+download_desc)
}

}

// TTS somehow can't read special charater, dev said this will be fix in upcomming update, for now this funtion will increase readability
function fix_charater(data){
    return new Promise((resolve, reject) => {
        var text = data ;
    text = text.replace("【", "<")
    text = text.replace("】", ">")
    text = text.replace("(", "(")
    text = text.replace(")", ")")
    text = text.replace(":", ":")
    text = text.replace("。", ".")
    text = text.replace(",", ",")
    text = text.replace("《", "<")
    text = text.replace("》", ">")
    text = text.replace("「", "<")
    text = text.replace("」", ">")
    text = text.replace("【", "<")
    text = text.replace("】", ">")
    text = text.replace("【", "<")
    text = text.replace("】", ">")
    text = text.replace("《", "<")
    text = text.replace("》", ">")
    text = text.replace("「", "<")
    text = text.replace("」", "<")
    text = text.replace("[", "[")
    text = text.replace("]", "]")
    text = text.replace("『", "[")
    text = text.replace("』", "]")
    text = text.replace("+", "+")
    text = text.replace("。", ".")
    text = text.replace("、", ",")
    text = text.replace("。", ".")
    //console.log(text)
    resolve(text)
  });
}

function escape_charater(data){
    var text = data ;
    text = text.replace('"', ' ')
    text = text.replace("'", " ")

    return(text)
}