Custom Anime Scheduler

Schedules anime from any season

当前为 2023-12-31 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Custom Anime Scheduler
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1.6.3
  5. // @description Schedules anime from any season
  6. // @author You
  7. // @icon https://www.google.com/s2/favicons?sz=64&domain=tampermonkey.net
  8. // @grant GM_setValue
  9. // @grant GM_getValue
  10. // @match *.livechart.me/*
  11. // @require https://code.jquery.com/jquery-3.6.4.min.js
  12. // @run-at document-end
  13. // @license MIT
  14. // ==/UserScript==
  15.  
  16. const $ = window.jQuery;
  17.  
  18. function convertToDateLinkText(date) {
  19. let realMonth = date.getMonth() + 1;
  20. let dateString = date.getDate();
  21. if (dateString < 10) {
  22. dateString = '0' + dateString;
  23. }
  24. if (realMonth < 10) {
  25. realMonth = '0' + realMonth;
  26. }
  27. const dateLinkFormat_ = date.getFullYear() + '-' + realMonth + '-' + dateString;
  28. return dateLinkFormat_;
  29. }
  30.  
  31. function convertToDateObject(dateString) {
  32. const modifiedDateString = dateString + " 00:00:00";
  33. const dateObject = new Date(modifiedDateString);
  34. return dateObject;
  35. }
  36.  
  37. function speedChange(diff) {
  38. const daysString = GM_getValue("days_speed");
  39. const speed = Number(daysString);
  40. const newDiff = diff * Math.ceil(7 / speed);
  41. return newDiff;
  42. }
  43.  
  44. function daysSinceStartingDay(date) {
  45. let daysSince;
  46. const startingDay_ = GM_getValue("starting_day");
  47. if (startingDay_ == "monday") {
  48. daysSince = (date.getDay() + 6) % 7;
  49. }
  50. else if (startingDay_ == "relative") {
  51. //daysSince = (date.getDay() + speedChange(1) - 1) % 7;
  52. daysSince = speedChange(1) - 1;
  53. }
  54. else {
  55. daysSince = date.getDay();
  56. }
  57. return daysSince;
  58. }
  59.  
  60. function shiftDate(date, diff) {
  61. const daysShifted = date.getDate() + diff;
  62. date.setDate(daysShifted);
  63. }
  64.  
  65. function getDayTextFromNum(num) {
  66. let weekDay;
  67. switch(num) {
  68. case 0:
  69. weekDay = "Sun";
  70. break;
  71. case 1:
  72. weekDay = "Mon";
  73. break;
  74. case 2:
  75. weekDay = "Tue";
  76. break;
  77. case 3:
  78. weekDay = "Wed";
  79. break;
  80. case 4:
  81. weekDay = "Thu";
  82. break;
  83. case 5:
  84. weekDay = "Fri";
  85. break;
  86. case 6:
  87. weekDay = "Sat";
  88. break;
  89. }
  90. return weekDay;
  91. }
  92.  
  93. function getDayText(date) {
  94. let weekDay;
  95. const dayNum = date.getDay();
  96. weekDay = getDayTextFromNum(dayNum);
  97. return weekDay;
  98. }
  99.  
  100. function convertToDateButtonText(date) {
  101. let retString;
  102. let dateString = date.getDate();
  103. const weekDay = getDayText(date);
  104. const realMonth = date.getMonth() + 1;
  105.  
  106.  
  107. if (dateString < 10) {
  108. dateString = '0' + dateString;
  109. }
  110. retString = weekDay + ' ' + realMonth + '/' + dateString;
  111. return retString;
  112. }
  113.  
  114. function GetURLParameter(sParam) {
  115. const sPageURL = window.location.search.substring(1);
  116. const sURLVariables = sPageURL.split('&');
  117. for (let i = 0; i < sURLVariables.length; i++) {
  118. let sParameterName = sURLVariables[i].split('=');
  119. if (sParameterName[0] == sParam) {
  120. return decodeURIComponent(sParameterName[1]);
  121. }
  122. }
  123. }
  124.  
  125. function highlightTTDay(dayText, dayStatus) {
  126. let timeTableBox = $('.timetable');
  127. const tTDayQuery = 'h2:contains("' + dayText + '")';
  128. let TTDayH2 = timeTableBox.find(tTDayQuery);
  129. let TTDay = TTDayH2.parent().parent();
  130. TTDay.removeClass("past");
  131. TTDay.addClass(dayStatus);
  132. }
  133.  
  134. $(window).bind("load", function () {
  135. const $today = new Date();
  136. const todayHoursToMidnight = convertToDateObject(convertToDateLinkText($today));
  137. let scheduleDate = convertToDateObject(GM_getValue("start_date"));
  138. const settingDate = convertToDateObject(GM_getValue("setting_date"));
  139. const daysDiff = (todayHoursToMidnight - settingDate) / (1000 * 60 * 60 * 24);
  140. const daysDiffWithSpeed = speedChange(daysDiff);
  141.  
  142. shiftDate(scheduleDate, daysDiffWithSpeed);
  143.  
  144. const currentCustomDateText = convertToDateLinkText(scheduleDate);
  145.  
  146. const weekStartDiff = -daysSinceStartingDay(scheduleDate);
  147. shiftDate(scheduleDate, weekStartDiff);
  148.  
  149. const dateLinkFormat = convertToDateLinkText(scheduleDate);
  150. const scheduleDateLink = 'https://www.livechart.me/timetable?date=' + dateLinkFormat;
  151.  
  152. const SettingsTab = '<li class="hide-for-small-only"><a class="nav-link schedule-settings-button" href="https://www.livechart.me/preferences/general">Settings</a></li>';
  153. let CustomScheduleTab;
  154. if (GM_getValue("start_date") == undefined) {
  155. CustomScheduleTab = '<li class="hide-for-small-only"><a class="nav-link" id="default-cschedule-button">Custom Schedule</a></li>';
  156. }
  157. else {
  158. CustomScheduleTab = '<li class="hide-for-small-only"><a class="nav-link" href="' + scheduleDateLink + '">Custom Schedule</a></li>';
  159. }
  160.  
  161. $(SettingsTab).insertBefore('.site-header--navigation>.flex-spacer');
  162.  
  163. let headlinesButton = $('a[href="/headlines"]').parent();
  164. $(headlinesButton).attr('id', 'headlines-button');
  165. $(CustomScheduleTab).insertBefore('.site-header--navigation>#headlines-button');
  166.  
  167. const urlDateText = GetURLParameter('date');
  168. let urlDateObject = convertToDateObject(urlDateText);
  169. shiftDate(urlDateObject, -7);
  170. const urlDateLastWeekText = convertToDateLinkText(urlDateObject);
  171. const urlDateButtonText = convertToDateButtonText(urlDateObject);
  172.  
  173. const lastWeekButton = '<div class="column small-6"><a class="button clear" href="/timetable?date=' + urlDateLastWeekText + '" rel="nofollow"><i class="icon-navigate_first"></i>' + urlDateButtonText + '</a></div>';
  174. let weekChangeRow = $('div.column.small-6.float-right.text-right').parent()
  175.  
  176. if (weekChangeRow.find("a").length == 1) {
  177. weekChangeRow.prepend(lastWeekButton);
  178. }
  179.  
  180. let currentCustomDate = convertToDateObject(currentCustomDateText);
  181. const scheduleDayText = getDayText(currentCustomDate);
  182. let futureDayText
  183.  
  184. if (urlDateText == dateLinkFormat) {
  185. highlightTTDay(scheduleDayText, "today");
  186.  
  187. const scheduleDayNum = currentCustomDate.getDay();
  188. for (let i = scheduleDayNum; i < 7; i++) {
  189. futureDayText = getDayTextFromNum(i);
  190. highlightTTDay(futureDayText, "future");
  191. }
  192. const startingDay = GM_getValue("starting_day");
  193. if (startingDay == "monday") {
  194. highlightTTDay("Sun", "future");
  195. }
  196. else if (startingDay == "relative") {
  197. const relDaysDiff = speedChange(1);
  198. let _thisDay = (scheduleDayNum + 1) % 7;
  199. for (let i = 0; i < 7 - relDaysDiff; i++) {
  200. futureDayText = getDayTextFromNum(_thisDay);
  201. highlightTTDay(futureDayText, "future");
  202. _thisDay = (_thisDay + 1) % 7;
  203. }
  204. }
  205. }
  206.  
  207.  
  208. let BrowseList = $('.small-up-4');
  209.  
  210. $('.small-up-4 > div:last-child').remove();
  211.  
  212. const rowsNum = 20;
  213. const colsNum = 4;
  214. let yearGrid = new Array (colsNum);
  215. for (let i = 0; i < colsNum; i++) {
  216. yearGrid[i] = new Array(rowsNum);
  217. }
  218.  
  219. let i = 0;
  220. let k = 0;
  221. $('.small-up-4 div').each(function() {
  222. if (i < rowsNum) {
  223. yearGrid[k][i] = $(this);
  224. i++;
  225. }
  226. else {
  227. k++;
  228. if (k < colsNum) {
  229. i = 0;
  230. yearGrid[k][i] = $(this);
  231. }
  232. }
  233. });
  234.  
  235. const thisYear = $today.getFullYear();
  236.  
  237. for (let year = (thisYear - 3); year >= 1960; year--) {
  238. if (i < rowsNum) {
  239. yearGrid[k][i] = ('<div class="cell"><a class="px0" href="/winter-' + year + '/tv">' + year + '</a></div>');
  240. i++;
  241. }
  242. else {
  243. k++;
  244. if (k < colsNum) {
  245. i = 0;
  246. year++;
  247. }
  248. }
  249. }
  250.  
  251.  
  252. $(BrowseList).empty();
  253. let r = 0;
  254. let c = 0;
  255. for (let r = 0; r < rowsNum; r++) {
  256. for (let c = 0; c < colsNum; c++) {
  257. $(BrowseList).append(yearGrid[c][r]);
  258. }
  259. }
  260.  
  261. $(BrowseList).removeClass('grid-padding-x');
  262.  
  263. let PreferencesList = '.large-push-2 > div[class="ul-tabs-overflow"] > ul[class="ul-tabs"]';
  264. const ScheduleSettingsPrefTab = '<li class="ul-tab schedule-pref-tab"><a>Edit Schedule</a></li>';
  265.  
  266. $(PreferencesList).append(ScheduleSettingsPrefTab);
  267.  
  268. let prefBody = $('form[action*="/preferences/"]');
  269.  
  270. $(".schedule-pref-tab").click(function() {
  271. const SchedulePrefFormStart = '<div class="callout">';
  272. const StartDate = '<label class="string required" for="start_date"><abbr title="required">Type out the date that your custom schedule starts (YYYY-MM-DD)</label><input class="string required" required="required" aria-required="true" placeholder="2013-05-23" maxlength="20" pattern="*" size="20" type="text" value="" name="user[username]" id="start-date">';
  273. const StartingDay = '<label for="starting_day">The starting day of the week is</label><select name="preferences[titles]" id="starting-day">';
  274. const StartingDayOptions = '<option value="monday">Monday (Mo. Tu. We. Th. Fr. Sa. Su.)</option><option value="sunday">Sunday (Su. Mo. Tu. We. Th. Fr. Sa.)</option><option value="relative">Relative to the date</option></select>';
  275. const DaysSpeed = '<label for="days_speed">Speed that schedule time passes <h5 style="display:inline"><a id="time-pass-info" title="The program will change the date that shows up in the Custom Schedule with every day that passes, and with one of these options selected, it will jump 2 days ahead for every day of real time, all the way up to 7 days ahead for every real time day. (Selecting respectively: [Each week lasts 4 days] and [Each week lasts 1 day])">&#x1F6C8</a></h5></label><select name="preferences[titles]" id="days-speed">';
  276. const DaysSpeedOptions = '<option value="7">Each week lasts 7 days</option><option value="1">Each week lasts 1 day</option></option><option value="1.5">Each week lasts 1.5 days</option><option value="2">Each week lasts 2 days</option><option value="3">Each week lasts 3 days</option><option value="4">Each week lasts 4 days</option></select>';
  277. const SchedulePrefFormEnd = '<hr><button class="button" name="schedule-button">Save</button></div>';
  278.  
  279. $('.ul-tabs li').each(function() {
  280. $(this).removeClass('active');
  281. });
  282. $(".schedule-pref-tab").addClass('active');
  283.  
  284. prefBody.empty();
  285. prefBody.append(SchedulePrefFormStart + StartDate + StartingDay + StartingDayOptions + DaysSpeed + DaysSpeedOptions + SchedulePrefFormEnd);
  286.  
  287. let startDateValue = $('label[for="starting_day"]').val();
  288.  
  289. const prevStartingDayOption = 'option[value="' + GM_getValue("starting_day") + '"]';
  290. $(prevStartingDayOption).attr("selected", "selected");
  291.  
  292. const prevSpeedOption = 'option[value="' + GM_getValue("days_speed") + '"]';
  293. $(prevSpeedOption).attr("selected", "selected");
  294.  
  295. $('button[name="schedule-button"]').on('click', function(event) {
  296. event.preventDefault();
  297.  
  298. let startDateValue = $('#start-date').val();
  299. let startingDayValue = $('#starting-day').val();
  300. let daysSpeedValue = $('#days-speed').val();
  301.  
  302. GM_setValue("start_date", startDateValue);
  303. GM_setValue("starting_day", startingDayValue);
  304. GM_setValue("days_speed", daysSpeedValue);
  305.  
  306. let $thisDate = new Date();
  307. let thisDateText = convertToDateLinkText($thisDate);
  308.  
  309. GM_setValue("setting_date", thisDateText);
  310.  
  311. location.reload();
  312. });
  313.  
  314. $("#time-pass-info").hover(function() {
  315. $("#time-info-text").css('visibility', function(i, visibility) {
  316. return (visibility == 'visible') ? 'hidden' : 'visible';
  317. });
  318. });
  319. });
  320.  
  321. $("#default-cschedule-button").click(function() {
  322. const setupInstructions = '<h3>&nbsp;Click on the "Settings" tab, then from there, click on "Edit Schedule"<br>&nbsp;to add a new custom schedule.</h3>';
  323. $("#content").empty();
  324. $("#content").append(setupInstructions);
  325. });
  326.  
  327. });