Decklog To Tabletop simulator script

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

  1. // ==UserScript==
  2. // @name Decklog To Tabletop simulator script
  3. // @namespace http://tampermonkey.net/
  4. // @version 2.1
  5. // @description Download TCG card from Decklog and import to Tabletop simulator as deck item
  6. // @author Royal
  7. // @match https://decklog.bushiroad.com/view/*
  8. // @grant GM_download
  9. // @grant GM_setClipboard
  10. // @grant GM_xmlhttpRequest
  11. // @require http://code.jquery.com/jquery-3.4.1.min.js
  12. // @require https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js
  13. // @require https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.3/js/bootstrap.min.js
  14. // ==/UserScript==
  15.  
  16.  
  17. (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);
  18.  
  19. //declare all globle var
  20. var scrUIdata = "";
  21. var urllisttostring = "";
  22. var cardidtostring = "";
  23. var cardtitletostring = "";
  24. var carddesctostring = "";
  25. var allfinish = false;
  26. var totalnum = "";
  27. var lua_base = "";
  28. var carddata = "";
  29. var cardback = "";
  30. var cardid = "";
  31. var craddescarray = [];
  32. var cardidarray = [];
  33. var target = document.querySelector("#loader-bg");
  34. var runcheck = true;
  35. // create an observer instance
  36. var observer = new MutationObserver(function (mutations) {
  37. mutations.forEach(async function (mutation) {
  38. //alert("mutation");
  39. await doruncheck();
  40. });
  41. });
  42.  
  43. // configuration of the observer:
  44. var config = { attributes: true };
  45. var target2 = document.querySelector(".body-page-view");
  46. // create an observer instance
  47. var observer2 = new MutationObserver(function (mutations) {
  48. mutations.forEach(function (mutation) {
  49. setTimeout(function () {
  50. //Code to run After timeout elapses
  51. remove_landscape_card();
  52. }, 500); //Two seconds will elapse and Code will execute.
  53. });
  54. });
  55.  
  56. // configuration of the observer:
  57. var config2 = { attributes: true, childList: true, characterData: true };
  58. var sqlcardid = "";
  59. var deckname = "";
  60. var deckdesc = "";
  61.  
  62. //finish declare
  63.  
  64. (function () {
  65. "use strict";
  66.  
  67. // Your code here...
  68. $(document).ready(function () {
  69. //When document has loaded
  70. console.log("start");
  71.  
  72. observer.observe(target, config);
  73. observer2.observe(target2, config2);
  74. });
  75. })();
  76.  
  77. async function doruncheck() {
  78. if (runcheck == true) {
  79. //check for page finish
  80. var stats = $("#loader-bg").attr("style");
  81. //console.log(stats);
  82. if (stats.includes("none") == true) {
  83. await startpage();
  84. runcheck = false;
  85. }
  86. } else {
  87. //console.log("no check");
  88. }
  89. }
  90.  
  91. function startpage() {
  92. runcheck = false;
  93. //build UI
  94. get_UI();
  95. setTimeout(function () {
  96. $(".deckview").append(scrUIdata);
  97. $("#collapseOne").addClass("collapse");
  98. set_UI_button();
  99. //show_debug();
  100. }, 2000);
  101. }
  102.  
  103. async function get_UI() {
  104. await GM_xmlhttpRequest({
  105. method: "GET",
  106. url:
  107. "https://raw.githubusercontent.com/RoyalShooter/Decklog-To-Tabletop-simulator-script/main/UI_code/UIhtml_public",
  108. headers: {
  109. "User-agent": "Mozilla/4.0 (compatible) Greasemonkey",
  110. Accept: "application/atom+xml,application/xml,text/xml",
  111. },
  112. onload: function (responseDetails) {
  113. scrUIdata = responseDetails.responseText || "<h1>Error on loding UI</h1>";
  114. //console.log(scrUIdata);
  115. },
  116. });
  117. }
  118. //start hooking all button control
  119. function set_UI_button() {
  120. $("#scr_download_lua").click(download_TTS_Lua_code);
  121. $("#scr_download_as_image").click(download_Image);
  122. }
  123.  
  124. function show_debug() {
  125. $("#collapseOne").append(
  126. '<button type="button" id="Testbbt">Testbbt</button>'
  127. );
  128. $("#Testbbt").click(Testbbt);
  129. }
  130. //finish set button
  131. function download_Image(zEvent) {
  132. alert("Downloading as TTS card set");
  133. $(".deckview")
  134. .find(".card-item")
  135. .each(function (index) {
  136. //console.log(index + ": " + $(this).find("img").attr("title"));
  137. var name = $(this).find("img").attr("title").replace("/", "-");
  138. var dl_url = $(this).find("img").attr("src");
  139. var num =
  140. "0" +
  141. $(this).find(".card-controller-inner").find(".num").first().text() +
  142. "x";
  143. var path = "Decklog_TTS/"; // use a special folder for all the images
  144. var arg = {
  145. url: dl_url,
  146. name: path + num + " " + name + ".png",
  147. };
  148. var result = GM_download(arg);
  149. //console.log(result);
  150. });
  151. //download card back
  152. var arg = {
  153. url: "https://www.tcgcard.tw/wp-content/uploads/2020/05/ws_cardback.png",
  154. name: "Decklog_TTS/00 back.png",
  155. };
  156. var result = GM_download(arg);
  157. //console.log(result);
  158. }
  159.  
  160. async function download_TTS_Lua_code(zEvent) {
  161. $("#scr_loding").removeClass("d-none");
  162. // alert ("Test");
  163. var urllist = [];
  164. var cardidlist = [];
  165. var cardtitlelist = [];
  166. var carddesc = [];
  167. totalnum = $(".graph-sum-value").text();
  168. deckname = $("h2").text().replace("デッキ名「", "").replace("」のデッキ", "");
  169. var deckid = $(location).attr("href");
  170. console.log(deckid);
  171. var deckseries = $(".col-lg-6").find("span").first().text();
  172. deckdesc = deckseries + " \\n" + deckid;
  173.  
  174. $(".deckview")
  175. .find(".card-item")
  176. .each(function (index) {
  177. //console.log( index + ": " + $(this).find("img").attr("title"));
  178.  
  179. var num = $(this)
  180. .find(".card-controller-inner")
  181. .find(".num")
  182. .first()
  183. .text();
  184. var i;
  185. for (i = 0; i < num; i++) {
  186. var dl_url = $(this).find("img").attr("src");
  187. urllist.push(dl_url);
  188. var name = $(this).find("img").attr("title");
  189. var spname = name.split(" : ");
  190. cardidlist.push(spname[0]);
  191. var escaped_name = escape_charater(spname[1])
  192. cardtitlelist.push(escaped_name);
  193. }
  194. });
  195. //console.log("'" + urllist.join("','") + "'");
  196. //console.log("'" + cardidlist.join("','") + "'");
  197. //console.log("'" + cardtitlelist.join("','") + "'");
  198. //console.log("'" + carddesc.join("','") + "'");
  199. //GM_setClipboard("'" + urllist.join("','") + "'");
  200. urllisttostring = "'" + urllist.join("','") + "'";
  201. cardidtostring = "'" + cardidlist.join("','") + "'";
  202. cardtitletostring = "'" + cardtitlelist.join("','") + "'";
  203.  
  204.  
  205.  
  206. var download_desc = $("#scr_progress_bar_show").hasClass("d-none")
  207. if (download_desc == false){
  208. //alert("do download "+download_desc)
  209. }else{
  210. //alert("do nothing "+download_desc)
  211. }
  212. carddesctostring = "'" + craddescarray.join("','") + "'" || "";
  213. combine();
  214. $("#scr_loding").addClass("d-none");
  215. }
  216.  
  217. function remove_landscape_card(zEvent) {
  218. //alert ("Test");
  219. const img = new Image();
  220. $(".deckview")
  221. .find(".card-item")
  222. .each(function (index) {
  223. //console.log( index + ": " + $(this).find("img"));
  224. const img = new Image();
  225. //img.onload = function() {
  226. // console.log( index + ": " + this.width + 'x' + this.height);
  227. //}
  228. img.src = $(this).find("img").attr("src");
  229. //console.log( index + ": " + img.width + 'x' + img.height);
  230.  
  231. if (img.width > img.height) {
  232. $("#scr_loding").removeClass("d-none");
  233. var name = $(this).find("img").attr("title");
  234. var spname = name.split(" : ");
  235. var yyturl1 =
  236. "https://yuyu-tei.jp/game_ws/sell/sell_price.php?name=" + spname[0];
  237.  
  238. let getimg = new Promise((resolve, reject) => {
  239. GM_xmlhttpRequest({
  240. method: "GET",
  241. url: yyturl1,
  242. headers: {
  243. "User-agent": "Mozilla/4.0 (compatible) Greasemonkey",
  244. Accept: "application/atom+xml,application/xml,text/xml",
  245. },
  246. onload: function (responseDetails) {
  247. //console.log('Request for Atom feed returned ' + responseDetails.status + ' ' + responseDetails.statusText + '\n\n' +'Feed data:\n' + responseDetails.responseText);
  248. //console.log(responseDetails.responseText)
  249. var yyturl2 =
  250. "https://yuyu-tei.jp" +
  251. $(responseDetails.responseText)
  252. .find(".card_list_box")
  253. .find("a")
  254. .attr("href");
  255.  
  256. GM_xmlhttpRequest({
  257. method: "GET",
  258. url: yyturl2,
  259. headers: {
  260. "User-agent": "Mozilla/4.0 (compatible) Greasemonkey",
  261. Accept: "application/atom+xml,application/xml,text/xml",
  262. },
  263. onload: function (responseDetails) {
  264. //console.log('Request for Atom feed returned ' + responseDetails.status + ' ' + responseDetails.statusText + '\n\n' +'Feed data:\n' + responseDetails.responseText);
  265. //console.log(responseDetails.responseText)
  266. var data = responseDetails.responseText;
  267. var newimg = $(data)
  268. .find(".image_box")
  269. .find("img")
  270. .first()
  271. .attr("src");
  272. //console.log(newimg);
  273. if (newimg != "") {
  274. resolve(newimg);
  275. } else {
  276. reject("img no found");
  277. }
  278. },
  279. });
  280. },
  281. });
  282. });
  283.  
  284. getimg.then((successdata) => {
  285. console.log("replace image = "+$(this).find("img").attr("src", successdata));
  286. $("#scr_loding").addClass("d-none");
  287. });
  288. }
  289.  
  290. //alert(name);
  291. });
  292. }
  293.  
  294. function get_card_id_list() {
  295. //alert("get_card_id_list");
  296. var urllist = [];
  297. var cardidlist = [];
  298. var cardidtop = [];
  299. var cardidback = [];
  300. var cardidtemparray = [];
  301. var cardidtemp = "";
  302. var cardtitlelist = [];
  303. var carddesc = [];
  304. totalnum = $(".graph-sum-value").text();
  305.  
  306. $(".deckview")
  307. .find(".card-item")
  308. .each(function (index) {
  309. //console.log( index + ": " + $(this).find("img").attr("title"));
  310.  
  311. var num = $(this)
  312. .find(".card-controller-inner")
  313. .find(".num")
  314. .first()
  315. .text();
  316. var i;
  317. for (i = 0; i < num; i++) {
  318. var dl_url = $(this).find("img").attr("src");
  319. urllist.push(dl_url);
  320. var name = $(this).find("img").attr("title");
  321. var spname = name.split(" : ");
  322. cardidtemparray = spname[0].split("-");
  323. cardidtop = cardidtemparray[0];
  324. cardidback = cardidtemparray[1].substring(0, 3);
  325. //console.log(cardidback);
  326. cardidtemp = cardidtop + "-" + cardidback;
  327. cardidlist.push(cardidtemp);
  328. cardidarray = cardidlist;
  329. }
  330. });
  331. //pass "cardidarray[]" to globle var
  332. }
  333.  
  334. function download_card_id_list(zEvent) {
  335. get_card_id_list();
  336. //console.log('"' + cardidarray.join('","') + '"');
  337. sqlcardid = "cardid = [" + '"' + cardidarray.join('","') + '"' + "]";
  338. var totext = sqlcardid;
  339. GM_setClipboard(totext);
  340. alert("Card ID list complete, Please paste into handler.");
  341. }
  342.  
  343. function card_desc_download_enable(zEvent) {
  344. //console.log("card_desc_download_enable");
  345. $("#scr_progress_bar_show").toggleClass("d-none");
  346. }
  347.  
  348. function scr_cardback_input_show(zEvent) {
  349. $("#scr_progress_bar_show").toggleClass("d-none");
  350. }
  351.  
  352. let get_lua_code = new Promise((resolve, reject) => {
  353. GM_xmlhttpRequest({
  354. method: "GET",
  355. url:
  356. "https://raw.githubusercontent.com/RoyalShooter/Decklog-To-Tabletop-simulator-script/main/base2",
  357. headers: {
  358. "User-agent": "Mozilla/4.0 (compatible) Greasemonkey",
  359. Accept: "application/atom+xml,application/xml,text/xml",
  360. },
  361. onload: function (responseDetails) {
  362. //console.log('Request for Atom feed returned ' + responseDetails.status + ' ' + responseDetails.statusText + '\n\n' +'Feed data:\n' + responseDetails.responseText);
  363. //console.log(responseDetails.responseText)
  364. lua_base = responseDetails.responseText;
  365. //GM_setClipboard (lua_base);
  366. if (lua_base != "") {
  367. resolve(lua_base);
  368. } else {
  369. reject("err on base lua");
  370. }
  371. },
  372. });
  373. });
  374.  
  375. function combine() {
  376. cardback =
  377. "https://www.tcgcard.tw/wp-content/uploads/2020/05/ws_cardback.png";
  378. get_lua_code.then((successdata) => {
  379. lua_base = successdata;
  380. });
  381. var lua_top =
  382. "local testurl = {" +
  383. urllisttostring +
  384. "} \n local cardid = {" +
  385. cardidtostring +
  386. "} \n local cardname = {" +
  387. cardtitletostring +
  388. "} \n local carddesc = {" +
  389. carddesctostring +
  390. "} \n local totalnum = '" +
  391. totalnum +
  392. "' \n local deckname = '" +
  393. deckname +
  394. "' \n local deckdesc = '" +
  395. deckdesc +
  396. "' \n local cardBack = '" +
  397. cardback +
  398. "'\n";
  399.  
  400. var lua = lua_top + "\n" + lua_base;
  401. GM_setClipboard(lua);
  402. //alert("Lua code finished, please paste lua in the scripting tab");
  403. $.bootstrapGrowl("Lua code finished, please paste lua in the scripting tab", {
  404. type: 'success', // (null, 'info', 'danger', 'success')
  405. allow_dismiss: true, // If true then will display a cross to close the popup.
  406. stackup_spacing: 10 // spacing between consecutively stacked growls.
  407. });
  408. }
  409.  
  410. function Testbbt(zEvent) {
  411. alert("Test2");
  412. //get_card_data("BFR/S78-042");
  413. var download_desc = $("#scr_progress_bar_show").hasClass("d-none")
  414. if (download_desc == false){
  415. //alert("do download "+download_desc)
  416. }else{
  417. //alert("do nothing "+download_desc)
  418. }
  419.  
  420. }
  421.  
  422. // TTS somehow can't read special charater, dev said this will be fix in upcomming update, for now this funtion will increase readability
  423. function fix_charater(data){
  424. return new Promise((resolve, reject) => {
  425. var text = data ;
  426. text = text.replace("【", "<")
  427. text = text.replace("】", ">")
  428. text = text.replace("(", "(")
  429. text = text.replace(")", ")")
  430. text = text.replace(":", ":")
  431. text = text.replace("。", ".")
  432. text = text.replace(",", ",")
  433. text = text.replace("《", "<")
  434. text = text.replace("》", ">")
  435. text = text.replace("「", "<")
  436. text = text.replace("」", ">")
  437. text = text.replace("【", "<")
  438. text = text.replace("】", ">")
  439. text = text.replace("【", "<")
  440. text = text.replace("】", ">")
  441. text = text.replace("《", "<")
  442. text = text.replace("》", ">")
  443. text = text.replace("「", "<")
  444. text = text.replace("」", "<")
  445. text = text.replace("[", "[")
  446. text = text.replace("]", "]")
  447. text = text.replace("『", "[")
  448. text = text.replace("』", "]")
  449. text = text.replace("+", "+")
  450. text = text.replace("。", ".")
  451. text = text.replace("、", ",")
  452. text = text.replace("。", ".")
  453. //console.log(text)
  454. resolve(text)
  455. });
  456. }
  457.  
  458. function escape_charater(data){
  459. var text = data ;
  460. text = text.replace('"', ' ')
  461. text = text.replace("'", " ")
  462.  
  463. return(text)
  464. }