MAL Date Fix

Script that sets your Start/Finish Dates on MAL

  1. // ==UserScript==
  2. // @name MAL Date Fix
  3. // @namespace Fix your dates on MAL
  4. // @version 2.2
  5. // @description Script that sets your Start/Finish Dates on MAL
  6. // @author NurarihyonMaou
  7. // @match https://anime.plus/*/history,anime
  8. // @match https://myanimelist.net/ownlist/*
  9. // @match https://myanimelist.net/profile/*
  10. // @match https://anime.plus/*
  11. // @grant GM_xmlhttpRequest
  12. // @grant GM_setValue
  13. // @grant GM_getValue
  14. // @grant GM_deleteValue
  15. // @grant GM_listValues
  16. // @require http://code.jquery.com/jquery-3.5.1.min.js
  17. // ==/UserScript==
  18.  
  19.  
  20. // Variables
  21.  
  22. const $ = window.jQuery;
  23.  
  24. var id = [];
  25. var startDay = [];
  26. var startMonth = [];
  27. var startYear = [];
  28. var endDay = [];
  29. var endMonth = [];
  30. var endYear = [];
  31.  
  32. var csrf_token;
  33.  
  34. var how_much, startDate, endDate;
  35.  
  36. var aeps = [], astatus = [], status = [], num_watched_episodes = [], score = [], tags = [], priority = [], storage_type = [], storage_value = [], num_watched_times = [], rewatch_value = [], comments = [], is_asked_to_discuss = [], sns_post_type = [], is_rewatching = [], submitIt = [], checkIfCorrect =[];
  37.  
  38.  
  39. if(GM_getValue('storage_type') != undefined){
  40. storage_type = GM_getValue('storage_type');
  41. storage_value = GM_getValue('storage_value');
  42. is_rewatching = GM_getValue('is_rewatching');
  43. aeps = GM_getValue('aeps');
  44. status = GM_getValue('status');
  45. astatus = GM_getValue('astatus');
  46. num_watched_times = GM_getValue('num_watched_times');
  47. num_watched_episodes = GM_getValue('num_watched_episodes');
  48. comments = GM_getValue('comments');
  49. sns_post_type = GM_getValue('sns_post_type');
  50. score = GM_getValue('score');
  51. rewatch_value = GM_getValue('rewatch_value');
  52. tags = GM_getValue('tags');
  53. priority = GM_getValue('priority');
  54. is_asked_to_discuss = GM_getValue('is_asked_to_discuss');
  55. }
  56.  
  57. if(GM_getValue('startYear') != undefined){
  58. startDay = GM_getValue('startDay');
  59. startMonth = GM_getValue('startMonth');
  60. startYear = GM_getValue('startYear');
  61. }
  62.  
  63. if(GM_getValue('endYear') != undefined){
  64. endDay = GM_getValue('endDay');
  65. endMonth = GM_getValue('endMonth');
  66. endYear = GM_getValue('endYear');
  67. }
  68.  
  69.  
  70. $(window).ready(async () => {
  71.  
  72. // Function to return requests in orginal order, without making them sync
  73.  
  74. function SendGetRequest(url) {
  75. return new Promise((resolve, reject) => {
  76. GM_xmlhttpRequest({
  77. method: "GET",
  78. url: url,
  79. onload: function (response) {
  80. if(response.status != 200){
  81.  
  82. GM_setValue('i', i); GM_setValue('storage_type', storage_type); GM_setValue('num_watched_episodes', num_watched_episodes); GM_setValue('sns_post_type', sns_post_type);
  83. GM_setValue('aeps', aeps); GM_setValue('storage_value', storage_value); GM_setValue('score', score);
  84. GM_setValue('astatus', astatus); GM_setValue('num_watched_times', num_watched_times); GM_setValue('tags', tags);
  85. GM_setValue('status', status); GM_setValue('rewatch_value', rewatch_value); GM_setValue('priority', priority);
  86. GM_setValue('is_rewatching', is_rewatching); GM_setValue('comments', comments); GM_setValue('is_asked_to_discuss', is_asked_to_discuss);
  87.  
  88.  
  89. GM_setValue('f', f);
  90. GM_setValue('storage_type', storage_type); GM_setValue('num_watched_episodes', num_watched_episodes); GM_setValue('sns_post_type', sns_post_type);
  91. GM_setValue('aeps', aeps); GM_setValue('storage_value', storage_value); GM_setValue('score', score);
  92. GM_setValue('astatus', astatus); GM_setValue('num_watched_times', num_watched_times); GM_setValue('tags', tags);
  93. GM_setValue('status', status); GM_setValue('rewatch_value', rewatch_value); GM_setValue('priority', priority);
  94. GM_setValue('is_rewatching', is_rewatching); GM_setValue('comments', comments); GM_setValue('is_asked_to_discuss', is_asked_to_discuss);
  95. GM_setValue('startDay', startDay);
  96. GM_setValue('startMonth', startMonth);
  97. GM_setValue('startYear', startYear);
  98. GM_setValue('endDay', endDay);
  99. GM_setValue('endMonth', endMonth);
  100. GM_setValue('endYear', endYear);
  101. GM_setValue('e', e);
  102.  
  103. GM_setValue('storage_type', storage_type); GM_setValue('num_watched_episodes', num_watched_episodes); GM_setValue('sns_post_type', sns_post_type);
  104. GM_setValue('aeps', aeps); GM_setValue('storage_value', storage_value); GM_setValue('score', score);
  105. GM_setValue('astatus', astatus); GM_setValue('num_watched_times', num_watched_times); GM_setValue('tags', tags);
  106. GM_setValue('status', status); GM_setValue('rewatch_value', rewatch_value); GM_setValue('priority', priority);
  107. GM_setValue('is_rewatching', is_rewatching); GM_setValue('comments', comments); GM_setValue('is_asked_to_discuss', is_asked_to_discuss);
  108. GM_setValue('startDay', startDay);
  109. GM_setValue('startMonth', startMonth);
  110. GM_setValue('startYear', startYear);
  111. GM_setValue('endDay', endDay);
  112. GM_setValue('endMonth', endMonth);
  113. GM_setValue('endYear', endYear);
  114.  
  115.  
  116. setTimeout(function () { location.reload(); }, 500);
  117.  
  118. }
  119. else resolve(response.responseText);
  120. },
  121. onerror: function (error) {
  122. reject(error);
  123.  
  124. }
  125. });
  126. });
  127. }
  128.  
  129. if(window.location.pathname.split('/')[1] === 'profile'){
  130. alert("Start");
  131. let UserName = $("a.header-profile-link").text();
  132. GM_setValue("UserName", UserName);
  133. document.location = "https://anime.plus/"+UserName+"?referral=search";
  134. }
  135.  
  136.  
  137.  
  138. if(window.location.pathname.split('/')[1] === GM_getValue("UserName")){
  139. (function init() {
  140. let Completed = $("div.section.anime-summary");
  141. if (Completed.length > 0) {
  142. if($("div.left.mini-section").children().children(".value").text() == 0) location.reload();
  143. else document.location = "https://anime.plus/"+GM_getValue("UserName")+"/history,anime";
  144. }
  145. else {
  146. setTimeout(init, 0);
  147. }
  148. })();
  149. }
  150.  
  151.  
  152. if (window.location.pathname.split('/')[2] === 'history,anime') {
  153.  
  154. // Checks the URL, then proceeds to gather ID's of titles that got missing dates
  155. let keys = await GM_listValues(); for (let key of keys) { GM_deleteValue(key); }
  156.  
  157. $('a.entries-trigger')[0].click();
  158.  
  159. how_much = parseInt($('a.entries-trigger').text());
  160.  
  161. $('#month-unknown ul li a').each(function () {
  162.  
  163. id.push(parseInt($(this).attr('href').slice(30)));
  164. });
  165.  
  166. if (id.length == how_much) {
  167. GM_setValue('id', id);
  168.  
  169. // After getting all of the ID's, redirects You to MAL, to avoid CROSS-ORIGIN problems
  170. document.location = "https://myanimelist.net/ownlist/anime/" + id[0] + "/edit";
  171. }
  172.  
  173. }
  174.  
  175.  
  176.  
  177.  
  178. if (window.location.pathname.split('/')[1] === 'ownlist') {
  179.  
  180. if ($(".g-recaptcha").length > 0) {
  181. $(".g-recaptcha").click();
  182. }
  183. else {
  184.  
  185. id = GM_getValue('id');
  186.  
  187. if (id == null) alert("No Data, please Start from the Beginning");
  188. $("body").css("background-color", "#585858");
  189. $("body").html("<label for='p1'>Fetching information</label></br><progress id='p1' value='0' max='" + id.length + "'></progress></br><label for='p2'>Fetching Dates</label></br><progress id='p2' value='0' max='" + id.length + "'></progress></br><label for='p3'>Sending Update Requests</label></br><progress id='p3' value='0' max='" + id.length + "'></progress>");
  190.  
  191. csrf_token = $("meta[name='csrf_token']").attr('content');
  192.  
  193. // After redirecting fetches data saved in the TamperMonkey, then gets csrf_token to allow sending update requests, and starts requesting current data of all the titles using previously obtained ID's
  194.  
  195. // in case when you got temporaly block to avoid request spam
  196.  
  197. var i;
  198. if (GM_getValue('i') == null) i = 0;
  199. else i = GM_getValue('i');
  200.  
  201. var f;
  202. if (GM_getValue('f') == null) f = 0;
  203. else f = GM_getValue('f');
  204.  
  205. var e;
  206. if (GM_getValue('e') == null) e = 0;
  207. else e = GM_getValue('e');
  208.  
  209.  
  210.  
  211. for (i; i < id.length; i++) {
  212. $("#p1").attr("value", i + 1);
  213.  
  214. try {
  215. const response = await SendGetRequest("https://myanimelist.net/ownlist/anime/" + id[i] + "/edit");
  216. $(response).find("#main-form :input").each(function (x) {
  217.  
  218. // Gets all the current data except dates, by checking values of the inputs
  219.  
  220. if (x == 1)
  221. aeps.push($(this).val());
  222. if (x == 2)
  223. astatus.push($(this).val());
  224. if (x == 3)
  225. status.push($(this).val());
  226. if (x == 4)
  227. is_rewatching.push($(this).val());
  228. if (x == 5)
  229. num_watched_episodes.push($(this).val());
  230. if (x == 6)
  231. score.push($(this).val());
  232. if (x == 7 && $(this).val() != "")
  233. startMonth[i] = $(this).val();
  234. if (x == 8 && $(this).val() != "")
  235. startDay[i] = $(this).val();
  236. if (x == 9 && $(this).val() != "")
  237. startYear[i] = $(this).val();
  238. if (x == 15)
  239. tags.push($(this).val());
  240. if (x == 16)
  241. priority.push($(this).val());
  242. if (x == 17)
  243. storage_type.push($(this).val());
  244. if (x == 18)
  245. storage_value.push($(this).val());
  246. if (x == 19)
  247. num_watched_times.push($(this).val());
  248. if (x == 20)
  249. rewatch_value.push($(this).val());
  250. if (x == 21)
  251. comments.push($(this).val());
  252. if (x == 22)
  253. is_asked_to_discuss.push($(this).val());
  254. if (x == 23)
  255. sns_post_type.push($(this).val());
  256.  
  257. });
  258.  
  259. } catch (error) {
  260. if (error.status != null) {
  261. console.log("Error");
  262. break;
  263. }
  264. }
  265.  
  266. }
  267.  
  268. if (aeps.length == id.length) {
  269.  
  270.  
  271. // After obtaining current data, it proceeds to get Missing Dates
  272.  
  273. for (f; f < id.length; f++) {
  274.  
  275. $("#p2").attr("value", f + 1);
  276.  
  277. try {
  278. const response = await SendGetRequest("https://myanimelist.net/ajaxtb.php?keepThis=true&detailedaid=" + id[f] + "&TB_iframe=true&height=420&width=390");
  279. var EPSlength = $(response).find('.spaceit_pad').length;
  280.  
  281. if (EPSlength == 0) {
  282. checkIfCorrect.push("https://myanimelist.net/anime/"+id[f]);
  283. var userID = dataLayer[0].userId;
  284. $.ajax({
  285. method: "POST",
  286. url: "https://myanimelist.net/includes/ajax-no-auth.inc.php?t=6",
  287. data: { "color": 1, "id": id[f], "memId": userID, "type": "anime", "csrf_token": csrf_token },
  288. success: function (data, textStatus, xhr) {
  289. if(xhr.status != 200){
  290.  
  291. GM_setValue('i', i); GM_setValue('storage_type', storage_type); GM_setValue('num_watched_episodes', num_watched_episodes); GM_setValue('sns_post_type', sns_post_type);
  292. GM_setValue('aeps', aeps); GM_setValue('storage_value', storage_value); GM_setValue('score', score);
  293. GM_setValue('astatus', astatus); GM_setValue('num_watched_times', num_watched_times); GM_setValue('tags', tags);
  294. GM_setValue('status', status); GM_setValue('rewatch_value', rewatch_value); GM_setValue('priority', priority);
  295. GM_setValue('is_rewatching', is_rewatching); GM_setValue('comments', comments); GM_setValue('is_asked_to_discuss', is_asked_to_discuss);
  296.  
  297.  
  298. GM_setValue('f', f);
  299. GM_setValue('storage_type', storage_type); GM_setValue('num_watched_episodes', num_watched_episodes); GM_setValue('sns_post_type', sns_post_type);
  300. GM_setValue('aeps', aeps); GM_setValue('storage_value', storage_value); GM_setValue('score', score);
  301. GM_setValue('astatus', astatus); GM_setValue('num_watched_times', num_watched_times); GM_setValue('tags', tags);
  302. GM_setValue('status', status); GM_setValue('rewatch_value', rewatch_value); GM_setValue('priority', priority);
  303. GM_setValue('is_rewatching', is_rewatching); GM_setValue('comments', comments); GM_setValue('is_asked_to_discuss', is_asked_to_discuss);
  304. GM_setValue('startDay', startDay);
  305. GM_setValue('startMonth', startMonth);
  306. GM_setValue('startYear', startYear);
  307. GM_setValue('endDay', endDay);
  308. GM_setValue('endMonth', endMonth);
  309. GM_setValue('endYear', endYear);
  310. GM_setValue('e', e);
  311.  
  312. GM_setValue('storage_type', storage_type); GM_setValue('num_watched_episodes', num_watched_episodes); GM_setValue('sns_post_type', sns_post_type);
  313. GM_setValue('aeps', aeps); GM_setValue('storage_value', storage_value); GM_setValue('score', score);
  314. GM_setValue('astatus', astatus); GM_setValue('num_watched_times', num_watched_times); GM_setValue('tags', tags);
  315. GM_setValue('status', status); GM_setValue('rewatch_value', rewatch_value); GM_setValue('priority', priority);
  316. GM_setValue('is_rewatching', is_rewatching); GM_setValue('comments', comments); GM_setValue('is_asked_to_discuss', is_asked_to_discuss);
  317. GM_setValue('startDay', startDay);
  318. GM_setValue('startMonth', startMonth);
  319. GM_setValue('startYear', startYear);
  320. GM_setValue('endDay', endDay);
  321. GM_setValue('endMonth', endMonth);
  322. GM_setValue('endYear', endYear);
  323.  
  324.  
  325. setTimeout(function () { location.reload(); }, 500);
  326.  
  327. }
  328. var LastUpdated = data.split(' ');
  329. if (LastUpdated.length > 2) {
  330.  
  331. LastUpdated = LastUpdated[$.inArray("Updated:", LastUpdated) + 26];
  332.  
  333. if (startYear[f] == null) {
  334. startDay[f] = parseInt(LastUpdated.split('-')[1], 10);
  335. startMonth[f] = parseInt(LastUpdated.split('-')[0], 10);
  336. startYear[f] = parseInt(""+20+LastUpdated.split('-')[2], 10);
  337.  
  338. }
  339. if(endYear[f] == null){
  340. endDay[f] = parseInt(LastUpdated.split('-')[1], 10);
  341. endMonth[f] = parseInt(LastUpdated.split('-')[0], 10);
  342. endYear[f] = parseInt(""+20+LastUpdated.split('-')[2], 10);
  343.  
  344. }
  345.  
  346.  
  347. }
  348. },
  349. error: function () {
  350. console.log("Something went wrong");
  351. }
  352. });
  353. }
  354. else {
  355.  
  356. $($(response).find('.spaceit_pad').get().reverse()).each(function (x) {
  357.  
  358. // Takes first record as the start date, and first one (to get first watch dates, not the rewatch ones) that got the number of the last ep as the Finish Date
  359.  
  360. if (x == 0) {
  361. if(startYear[f] == null){
  362. startDate = $(this).html().match(/\d{2}([\/.-])\d{2}\1\d{4}/g);
  363. startDate = startDate.toString();
  364.  
  365. startDay[f] = parseInt(startDate.split('/')[1], 10);
  366. startMonth[f] = parseInt(startDate.split('/')[0], 10);
  367. startYear[f] = parseInt(startDate.split('/')[2], 10);
  368.  
  369. }
  370. }
  371.  
  372. if (x < EPSlength && $(this).html().indexOf("Ep " + aeps[f]) == 0) {
  373. endDate = $(this).html().match(/\d{2}([\/.-])\d{2}\1\d{4}/g);
  374. endDate = endDate.toString();
  375.  
  376. if(endYear[f] == null){
  377. endDay[f] = parseInt(endDate.split('/')[1], 10);
  378. endMonth[f] = parseInt(endDate.split('/')[0], 10);
  379. endYear[f] = parseInt(endDate.split('/')[2], 10);
  380.  
  381. }
  382. return false;
  383. }
  384.  
  385. x++
  386.  
  387.  
  388. });
  389. }
  390.  
  391.  
  392. } catch (error) {
  393.  
  394. if (error.status != null) {
  395.  
  396. console.log("Error");
  397. break;
  398. }
  399. }
  400.  
  401. }
  402.  
  403. }
  404.  
  405. if (endYear.length == id.length) {
  406.  
  407.  
  408. if(GM_getValue("p3Val") != undefined) $("#p3").attr("value", GM_getValue("p3Val"));
  409.  
  410. // Last Stage - just sends update requests
  411.  
  412. for (e; e < id.length; e++) {
  413.  
  414.  
  415.  
  416. $.ajax({
  417. method: 'POST',
  418. url: 'https://myanimelist.net/ownlist/anime/' + id[e] + '/edit',
  419. data: {
  420. 'anime_id': id[e],
  421. 'aeps': aeps[e],
  422. 'astatus': astatus[e],
  423. 'add_anime[status]': status[e],
  424. 'add_anime[num_watched_episodes]': num_watched_episodes[e],
  425. 'add_anime[score]': score[e],
  426. 'add_anime[start_date][month]': startMonth[e],
  427. 'add_anime[start_date][day]': startDay[e],
  428. 'add_anime[start_date][year]': startYear[e],
  429. 'add_anime[finish_date][month]': endMonth[e],
  430. 'add_anime[finish_date][day]': endDay[e],
  431. 'add_anime[finish_date][year]': endYear[e],
  432. 'add_anime[tags]': tags[e],
  433. 'add_anime[priority]': priority[e],
  434. 'add_anime[storage_type]': storage_type[e],
  435. 'add_anime[storage_value]': storage_value[e],
  436. 'add_anime[num_watched_times]': num_watched_times[e],
  437. 'add_anime[rewatch_value]': rewatch_value[e],
  438. 'add_anime[comments]': comments[e],
  439. 'add_anime[is_asked_to_discuss]': is_asked_to_discuss[e],
  440. 'add_anime[sns_post_type]': sns_post_type[e],
  441. 'submitIt': 0,
  442. 'csrf_token': csrf_token
  443. },
  444. complete: function (xhr, textStatus) {
  445. if(xhr.status != 200){
  446.  
  447. GM_setValue('i', i); GM_setValue('storage_type', storage_type); GM_setValue('num_watched_episodes', num_watched_episodes); GM_setValue('sns_post_type', sns_post_type);
  448. GM_setValue('aeps', aeps); GM_setValue('storage_value', storage_value); GM_setValue('score', score);
  449. GM_setValue('astatus', astatus); GM_setValue('num_watched_times', num_watched_times); GM_setValue('tags', tags);
  450. GM_setValue('status', status); GM_setValue('rewatch_value', rewatch_value); GM_setValue('priority', priority);
  451. GM_setValue('is_rewatching', is_rewatching); GM_setValue('comments', comments); GM_setValue('is_asked_to_discuss', is_asked_to_discuss);
  452.  
  453.  
  454. GM_setValue('f', f);
  455. GM_setValue('storage_type', storage_type); GM_setValue('num_watched_episodes', num_watched_episodes); GM_setValue('sns_post_type', sns_post_type);
  456. GM_setValue('aeps', aeps); GM_setValue('storage_value', storage_value); GM_setValue('score', score);
  457. GM_setValue('astatus', astatus); GM_setValue('num_watched_times', num_watched_times); GM_setValue('tags', tags);
  458. GM_setValue('status', status); GM_setValue('rewatch_value', rewatch_value); GM_setValue('priority', priority);
  459. GM_setValue('is_rewatching', is_rewatching); GM_setValue('comments', comments); GM_setValue('is_asked_to_discuss', is_asked_to_discuss);
  460. GM_setValue('startDay', startDay);
  461. GM_setValue('startMonth', startMonth);
  462. GM_setValue('startYear', startYear);
  463. GM_setValue('endDay', endDay);
  464. GM_setValue('endMonth', endMonth);
  465. GM_setValue('endYear', endYear);
  466. GM_setValue('e', e);
  467.  
  468. GM_setValue('storage_type', storage_type); GM_setValue('num_watched_episodes', num_watched_episodes); GM_setValue('sns_post_type', sns_post_type);
  469. GM_setValue('aeps', aeps); GM_setValue('storage_value', storage_value); GM_setValue('score', score);
  470. GM_setValue('astatus', astatus); GM_setValue('num_watched_times', num_watched_times); GM_setValue('tags', tags);
  471. GM_setValue('status', status); GM_setValue('rewatch_value', rewatch_value); GM_setValue('priority', priority);
  472. GM_setValue('is_rewatching', is_rewatching); GM_setValue('comments', comments); GM_setValue('is_asked_to_discuss', is_asked_to_discuss);
  473. GM_setValue('startDay', startDay);
  474. GM_setValue('startMonth', startMonth);
  475. GM_setValue('startYear', startYear);
  476. GM_setValue('endDay', endDay);
  477. GM_setValue('endMonth', endMonth);
  478. GM_setValue('endYear', endYear);
  479. GM_setValue('p3Val', $("#p3").attr("value"));
  480.  
  481. setTimeout(function () { location.reload(); }, 500);
  482.  
  483. }
  484. $("#p3").attr("value", $("#p3").attr("value")+1);
  485. if ($("#p3").attr("value") == id.length-1) { setTimeout(async function () { $("body").html("<h1>The End</h1>"); if(checkIfCorrect.length > 0){ $("body h1").append("</br>Below Entries might have incorrect Dates"); for(let check = 0; check < checkIfCorrect.length; check++){ $("body h1").after("<a href='"+checkIfCorrect[check]+"'>"+checkIfCorrect[check]+"</a></br>");} }let keys = await GM_listValues(); for (let key of keys) { GM_deleteValue(key); } }, 500); }
  486. },
  487. error: function () {
  488. console.log("Error");
  489. }
  490. });
  491.  
  492. }
  493. }
  494.  
  495. }
  496. }
  497. });