Tidy up your Dashboard

Customizable Userscript which tidies up your Dashboard!

当前为 2015-04-06 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Tidy up your Dashboard
  3. // @namespace https://gf.qytechs.cn/users/10154
  4. // @grant none
  5. // @match https://www.warlight.net/MultiPlayer/
  6. // @description Customizable Userscript which tidies up your Dashboard!
  7. // @version 1.5.6
  8. // @icon http://i.imgur.com/XzA5qMO.png
  9. // ==/UserScript==
  10.  
  11. var lastRefresh;
  12. var myGamesTable = $("#MyGamesTable");
  13. var openGamesTable = $("#OpenGamesTable");
  14. var promotedGamesTable = $("#PromotedGamesTable");
  15.  
  16. var scrollGames;
  17. var autoRefreshOnFocus;
  18. var highlightTournaments;
  19. var hideMyGamesIcons;
  20. var hideCoinSymbol;
  21.  
  22. var showGamesActive = "ShowMyGames";
  23. var showAllGames = "";
  24. var showAllCoinGames = "";
  25.  
  26. setupRefresh();
  27. setupUserscriptMenu();
  28. readLocalstorage();
  29. expandGames();
  30.  
  31. /**
  32. * Hide coin Symbol
  33. */
  34. if (hideCoinSymbol) {
  35. createSelector('#PromotedGamesTable td:last-of-type a img', 'display:none')
  36. }
  37.  
  38. /**
  39. * Highlight Tournaments
  40. */
  41. if (highlightTournaments) {
  42. createSelector("#MyTournamentsTable tbody", "background:#4C4C33;");
  43. }
  44.  
  45. /**
  46. * Hide coin Games
  47. */
  48. if (hideMyGamesIcons) {
  49. createSelector("#MyGamesTable td img", "display:none;");
  50. }
  51.  
  52. /**
  53. * Basic CSS
  54. */
  55. createSelector(".GameRow a", "font-size:16px !important;");
  56. createSelector(".GameRow td:last-of-type span,#OpenGamesTable .GameRow td:last-of-type span:first-child, #PromotedGamesTable .GameRow td:last-of-type span:first-child", "margin:5px 0px;position:relative !important;z-index:10;");
  57. createSelector("#MyGamesTable a img, #MyGamesTable span img", "display:inline-block;");
  58. createSelector(".GameRow:hover", "background-color:rgb(50, 50, 50);cursor:pointer;");
  59. createSelector(".BootTimeLabel", "color:white !important;font-weight:normal!important;font-style:italic;font-size:13px!important;z-index:50;");
  60. createSelector(".GameRow a:hover", "text-decoration:none;");
  61. createSelector(".TournamentRow a:hover", "text-decoration:none;");
  62. createSelector(".TournamentRow:hover", "background-color:rgb(50, 50, 50);cursor:pointer;");
  63. createSelector(".ui-buttonset label", "font-size:11px;");
  64. createSelector("#OpenGamesTable label:hover", " border: 1px solid #59b4d4;background: #0078a3 50% 50% repeat-x;font-weight: bold;color: #ffffff;");
  65. createSelector("#OpenGamesTable td:last-child,#MyGamesTable td:last-child, #PromotedGamesTable td:last-child", "position: relative;");
  66. createSelector("#OpenGamesTable td:nth-child(2) a,#MyGamesTable td:nth-child(2) a, #PromotedGamesTable td:nth-child(2) a", " display: block;width: 100%;height: 100%;float: left;position: absolute;margin-top: -5px;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;");
  67. createSelector(".loading", "position: absolute;height: 100%;width: 100%;background-color: rgba(255, 255, 255, 0.2);text-align: center;z-index: 12;margin-top: 34px;display:none;");
  68. createSelector(".loading img", "position: absolute;top: 50%;left: 50%;margin-left: -16px;margin-top: -16px;");
  69. createSelector("img", "position: relative;z-index:50;");
  70. createSelector("input", "z-index: 1000;position: relative;");
  71. createSelector(".userscript", "position: fixed;width: 420px;left: 50%;background: #171717;margin-left: -250px;top: 100px;z-index: 50000001; color:white;padding:60px 30px 30px 30px;border: 2px solid gray;border-radius:8px");
  72. createSelector(".userscript-menu", "display: block;color: #555;text-decoration: none;line-height: 18px;padding: 3px 15px;margin: 0;white-space: nowrap;");
  73. createSelector(".userscript-menu:hover", "cursor:pointer;background-color: #08C;color: #FFF;cursor: pointer;");
  74. createSelector(".close-userscript", "margin-top: 40px;width: 100%;text-align: center;font-size: 15px;cursor: pointer;background: gray;line-height: 30px;border-radius: 8px;");
  75. createSelector(".close-userscript-img", "float:right;margin:5px;cursor:pointer");
  76. createSelector(".userscript label", "width: 80%;display: inline-block;font-size: 15px;margin: 5px;");
  77. createSelector(".userscript input", "width: 20px;height: 20px;margin-left:30px;margin: 5px");
  78. createSelector(".userscript-container", "display: block;position: absolute;background: white;top: 0;left: 0;right: 0;bottom: 0;z-index: 50000000;opacity: 0.5;");
  79. createSelector(".userscript .head", "position: absolute;height: 40px;background: #330000;width: 100%;left: 0;right: 0;top: 0;color: white;font-size: 15px;text-align: center;line-height: 40px;border-top-left-radius:8px;border-top-right-radius:8px;");
  80. createSelector(".userscript-show", "display:none");
  81. createSelector(".showGames table thead td", "display:table-cell;width:100%;");
  82. createSelector(".showGames table thead tr", "display:table;width:100%;");
  83. createSelector(".showGames table tbody", "display:table;width:100%;");
  84.  
  85. $.each($(".TournamentRow td"), function() {
  86. $(this).find("font:first-of-type").appendTo($(this).find("a")).css("font-size", "10px");
  87. });
  88.  
  89. /**
  90. * Fixed window with Scrollable Games
  91. */
  92. if (scrollGames) {
  93. var gameButtons = '<div style="margin: 10px;" id="switchGameRadio" class="ui-buttonset"><input type="radio" id="ShowMyGames" name="switchGames" checked="checked" class="ui-helper-hidden-accessible"><label for="ShowMyGames" class="ui-state-active ui-button ui-widget ui-state-default ui-button-text-only ui-corner-left" role="button"><span class="ui-button-text">My Games</span></label><input type="radio" id="ShowOpenGames" name="switchGames" class="ui-helper-hidden-accessible"><label for="ShowOpenGames" class="ui-button ui-widget ui-state-default ui-button-text-only" role="button"><span class="ui-button-text">Open Games</span></label><input type="radio" id="ShowCoinGames" name="switchGames" class="ui-helper-hidden-accessible"><label for="ShowCoinGames" class="ui-button ui-widget ui-state-default ui-button-text-only ui-corner-right" role="button"><span class="ui-button-text">Coin Games</span></label></div>';
  94.  
  95. var mainColumn = $(".MainColumn ");
  96. mainColumn.prepend('<div class="showGamesContainer">' + gameButtons + '<div class="showGames"></div></div>');
  97. myGamesTable.appendTo(".showGames");
  98.  
  99. mainColumn.after('<div class="showSide"></div>');
  100. $(".SideColumn").appendTo(".showSide");
  101.  
  102. /**
  103. * Fixed Titles in Side Column
  104. */
  105. var blogTable = $("#BlogTable");
  106. var realTimeLadderTable = $("#RealTimeLadderTable");
  107. var forumTable = $("#ForumTable");
  108. var clanForumTable = $("#ClanForumTable");
  109. var mapOfTheWeekTable = $("#MapOfTheWeekTable");
  110. var leaderboardTable = $("#LeaderboardTable");
  111. var myTournamentsTable = $("#MyTournamentsTable");
  112.  
  113. blogTable.before("<div class='followMeBar'>" + blogTable.find("thead > tr > td").html() + "</div>");
  114. realTimeLadderTable.before("<div class='followMeBar'>" + realTimeLadderTable.find("thead > tr > td").html() + "</div>");
  115. forumTable.before("<div class='followMeBar'>" + forumTable.find("thead > tr > td").html() + "</div>");
  116. clanForumTable.before("<div class='followMeBar'>" + clanForumTable.find("thead > tr > td").html() + "</div>");
  117. mapOfTheWeekTable.before("<div class='followMeBar'>" + mapOfTheWeekTable.find("thead > tr > td").html() + "</div>");
  118. leaderboardTable.before("<div class='followMeBar'>" + leaderboardTable.find("thead > tr > td").html() + "</div>");
  119. myTournamentsTable.before("<div class='followMeBar'>" + myTournamentsTable.find("thead > tr > td").html() + "</div>");
  120.  
  121. createSelector(".followMeBar", "background: #330000;padding: 5px 0px;position: relative;z-index: 1;color: #fff;border-top-right-radius:8px;border-top-left-radius:8px;border: 1px solid gray;border-bottom:none");
  122. var top = parseInt($(".showSide").offset().top) + parseInt(43);
  123. createSelector(".followMeBar.fixed", "position: fixed;top: " + top + "px;z-index: 0;z-index:100;");
  124. createSelector(".followMeBar.fixed.absolute", "position: absolute;");
  125.  
  126. createSelector(".showSide", "overflow-y:scroll;float: left;margin-top: 43px;padding-right: 6px;");
  127. createSelector(".showSide thead", "display:none");
  128. createSelector(".showSide table", "border-top-right-radius:0;border-top-left-radius:0");
  129.  
  130. /**
  131. * Fixed Column CSS
  132. */
  133. createSelector("#switchGameRadio label", "margin-left: 6px !important");
  134. createSelector(".showGames table", "display:block !important");
  135. createSelector("#switchGameRadio label:hover", "border: 1px solid rgb(89, 180, 212);border-image-source: initial;border-image-slice: initial;border-image-width: initial;border-image-outset: initial;border-image-repeat: initial;background:rgb(0, 120, 163);font-weight: bold;color: rgb(255, 255, 255);");
  136. createSelector("#MyGamesTable, #PromotedGamesTable, #OpenGamesTable", "display:none");
  137. createSelector("#MainSiteContent > table > tbody > tr > td", "width:100%");
  138. createSelector(".MainColumn", "min-width:535px");
  139. createSelector(".MainColumn", "width:40.55% !important");
  140. createSelector(".SideColumn", "float:left !important");
  141. createSelector("h2 + span", "margin-right: 50px;");
  142. createSelector("body", "overflow:hidden");
  143. createSelector(".SideColumn", "width: 100% !important;");
  144. createSelector("#MyGamesFilter", "width:200px");
  145. createSelector(".showGames table thead", "position:fixed; z-index:500; border-top-left-radius:8px");
  146. createSelector(".showGames table", "display:block; overflow-y:scroll; overflow-x:hidden; border:1px gray solid; border-radius:8px");
  147. createSelector(".adsbygoogle", "margin-top: 25px;");
  148. createSelector(".showSide", "overflow-y:scroll;float: left;margin-top: 43px;padding-right: 6px;width:33.55%; min-width:500px;margin-left: 20px;border-top-left-radius:8px;border-top-right-radius:8px");
  149. createSelector("#refreshAll", "position: absolute;top: 20px;right: 31px;");
  150.  
  151. new StickyTitles(jQuery(".followMeBar")).load();
  152. refreshSingleColumnSize();
  153.  
  154. $("#switchGameRadio").find("label").on("click", function () {
  155. var newShowGames = $(this).attr("for");
  156. if (newShowGames != showGamesActive) {
  157. $.each($("#switchGameRadio").find("label"), function () {
  158. $(this).removeClass("ui-state-active");
  159. });
  160. $(this).addClass("ui-state-active");
  161.  
  162. if (newShowGames == "ShowMyGames") {
  163. showGamesActive = newShowGames;
  164. promotedGamesTable.appendTo("body");
  165. openGamesTable.appendTo("body");
  166. myGamesTable.appendTo(".showGames");
  167. } else if (newShowGames == "ShowCoinGames") {
  168. showGamesActive = newShowGames;
  169. myGamesTable.appendTo("body");
  170. openGamesTable.appendTo("body");
  171. promotedGamesTable.appendTo(".showGames");
  172. } else if (newShowGames == "ShowOpenGames") {
  173. showGamesActive = newShowGames;
  174. myGamesTable.appendTo("body");
  175. promotedGamesTable.appendTo("body");
  176. openGamesTable.appendTo(".showGames");
  177. }
  178.  
  179. showAllGames.trigger("click");
  180. refreshSingleColumnSize()
  181.  
  182. }
  183. });
  184. }
  185. var label = $("label");
  186. label.find("[for='MultiDayRadio']").on("click", function () {
  187. openGamesTable.scrollTop(0);
  188.  
  189. });
  190. label.find("[for='RealTimeRadio']").on("click", function () {
  191. openGamesTable.scrollTop(0);
  192. });
  193. label.find("[for='BothRadio']").on("click", function () {
  194. openGamesTable.scrollTop(0);
  195. });
  196.  
  197. $(window).resize(function () {
  198. if (scrollGames) {
  199. refreshSingleColumnSize();
  200. }
  201. });
  202.  
  203. /**
  204. * Triggers a click on the expand Games Button
  205. */
  206. function triggerExpandGames() {
  207. if (showAllGames == "") {
  208. showAllGames = $("#ShowMoreOpenGamesLink");
  209. showAllGames.trigger("click");
  210. }
  211. if (showAllCoinGames == "") {
  212. showAllCoinGames = $("#ShowMorePromotedGamesLink");
  213. showAllCoinGames.trigger("click");
  214. }
  215. }
  216.  
  217. /**
  218. * Stores User-Settings to local Storage
  219. */
  220. function storeVariables() {
  221. localStorage.setItem("autoRefreshOnFocus", $("#autoRefreshOnFocus").prop("checked"));
  222. localStorage.setItem("highlightTournaments", $("#highlightTournaments").prop("checked"));
  223. localStorage.setItem("hideMyGamesIcons", $("#hideMyGamesIcons").prop("checked"));
  224. localStorage.setItem("scrollGames", $("#scrollGames").prop("checked"));
  225. }
  226.  
  227. /**
  228. * Refreshes Width & Height of Columns
  229. */
  230. function refreshSingleColumnSize() {
  231. var showSide = $(".showSide");
  232. var showGames = $(".showGames");
  233. showSide.scrollTop(0);
  234. /**
  235. * Sticky Titles
  236. */
  237. $(".followMeBar").each(function () {
  238. $(this).removeClass("fixed");
  239. if ($(this).parent().hasClass("followWrap")) {
  240. $(this).unwrap();
  241. }
  242. var thisSticky = $(this).wrap('<div class="followWrap" />');
  243. thisSticky.parent().height(thisSticky.outerHeight());
  244.  
  245. var pos = parseInt(thisSticky.offset().top) - parseInt(showSide.offset().top);
  246. $.data(thisSticky[0], 'pos', pos);
  247. });
  248. var width = $("#ForumTable").width();
  249. createSelector(".followMeBar", "width:" + width + "px;");
  250.  
  251. showGames.find("table").css({
  252. height: window.innerHeight - 150
  253. });
  254. showGames.find("table thead").css({
  255. width: showGames.width() - 20
  256. });
  257. var height = showGames.find("table thead").height() + 6;
  258. createSelector(".showGames table tbody tr:first-of-type td", "padding-top:" + height + "px");
  259.  
  260. showSide.css({
  261. height: window.innerHeight - 150
  262. });
  263. showGames.find("table tbody tr:first-of-type td").css("padding-top", showGames.find("table thead").height() + 6)
  264.  
  265. }
  266.  
  267. /**
  268. * Create a CSS selector
  269. * @param name The name of the object, which the rules are applied to
  270. * @param rules The CSS rules
  271. */
  272. function createSelector(name, rules) {
  273. var style = document.createElement('style');
  274. style.type = 'text/css';
  275. document.getElementsByTagName('head')[0].appendChild(style);
  276. if (!(style.sheet || {}).insertRule) {
  277. (style.styleSheet || style.sheet).addRule(name, rules);
  278. } else {
  279. style.sheet.insertRule(name + "{" + rules + "}", 0);
  280. }
  281. }
  282.  
  283. /**
  284. * Reloads all Games
  285. */
  286. function refreshAllGames() {
  287.  
  288. myGamesTable.find("tbody").fadeTo('slow', 0.15);
  289. openGamesTable.find("tbody").fadeTo('slow', 0.15);
  290. promotedGamesTable.find("tbody").fadeTo('slow', 0.15);
  291.  
  292. var page = $('<div />').load('https://www.warlight.net/MultiPlayer/ ', function () {
  293. var myGames = page.find('#MyGamesTable tbody tr');
  294. var openGames = page.find('#OpenGamesTable tbody tr');
  295. var promotedGames = page.find('#PromotedGamesTable tbody tr');
  296.  
  297. $.each(promotedGamesTable.find("tbody tr"), function (key, value) {
  298. if ($(value).html().indexOf("PastGames") < 0) {
  299. $(value).remove();
  300. }
  301. });
  302.  
  303. openGamesTable.find("tbody tr").remove();
  304. promotedGamesTable.find("tbody tr").remove();
  305.  
  306. $.each(myGamesTable.find("tbody tr"), function (key, value) {
  307. if ($(value).html().indexOf("PastGames") < 0) {
  308. $(value).remove();
  309. }
  310. });
  311.  
  312. openGamesTable.scrollTop(0);
  313. myGamesTable.scrollTop(0);
  314. promotedGamesTable.scrollTop(0);
  315.  
  316. myGamesTable.find("tbody").prepend(myGames);
  317. openGamesTable.find("tbody").prepend(openGames);
  318. promotedGamesTable.find("tbody").prepend(promotedGames);
  319.  
  320. $("#ShowMorePromotedGamesLinkContainer").remove();
  321. showAllGames.trigger("click");
  322. showAllCoinGames.trigger("click");
  323.  
  324. myGamesTable.find("tbody").fadeTo('slow', 1);
  325. openGamesTable.find("tbody").fadeTo('slow', 1);
  326. promotedGamesTable.find("tbody").fadeTo('slow', 1);
  327.  
  328. if (scrollGames) {
  329. refreshSingleColumnSize();
  330. }
  331. });
  332. }
  333.  
  334. /**
  335. * Setups the refresh functionality
  336. */
  337. function setupRefresh() {
  338. lastRefresh = new Date();
  339. var oldRefreshBtn = $("#RefreshBtn");
  340. if(oldRefreshBtn.length) {
  341. var newRefreshBtn = $("#refreshAll");
  342. oldRefreshBtn.replaceWith(oldRefreshBtn.clone().removeAttr("id").attr("id", "refreshAll").attr("value","Refresh"));
  343. newRefreshBtn.appendTo("body");
  344. $("#refreshAll").on("click", function () {
  345. if (new Date() - lastRefresh > 3000) {
  346. lastRefresh = new Date();
  347. refreshAllGames();
  348. }
  349. });
  350. }
  351.  
  352. if (autoRefreshOnFocus) {
  353. $(window).on('focus', function () {
  354. if (new Date() - lastRefresh > 30000) {
  355. lastRefresh = new Date();
  356. refreshAllGames();
  357. }
  358. });
  359. }
  360.  
  361. $("body").keyup(function (event) {
  362. if (event.which == 82) {
  363. if (new Date() - lastRefresh > 3000) {
  364. lastRefresh = new Date();
  365. refreshAllGames();
  366. }
  367. }
  368. });
  369.  
  370. openGamesTable.prepend("<div class='loading loading-open'><img src='https://www.adobe.com/business/calculator/VIP/image/loader.gif' height='32' width='32'></div>");
  371. myGamesTable.prepend("<div class='loading loading-my'><img src='https://www.adobe.com/business/calculator/VIP/image/loader.gif' height='32' width='32'></div>");
  372. promotedGamesTable.prepend("<div class='loading loading-prom'><img src='https://www.adobe.com/business/calculator/VIP/image/loader.gif' height='32' width='32'></div>");
  373. }
  374.  
  375. /**
  376. * Delayed function for expanding Games
  377. */
  378. function expandGames() {
  379. var styleInterval = setInterval(triggerExpandGames, 100);
  380. setTimeout(function () {
  381. clearInterval(styleInterval)
  382. }, 3000);
  383. }
  384.  
  385. /**
  386. * Creates the Userscript-Menu
  387. */
  388. function setupUserscriptMenu() {
  389. var inputs = "";
  390. inputs += '<label for="scrollGames">Fixed Window with scrollable Games</label><input type="checkbox" id="scrollGames"><br>';
  391. inputs += '<label for="hideMyGamesIcons">Hide Icons in "My Games"</label><input type="checkbox" id="hideMyGamesIcons"><br>';
  392. inputs += '<label for="autoRefreshOnFocus">Automatically refresh Games on Tab-Focus</label><input type="checkbox" id="autoRefreshOnFocus"><br>';
  393. inputs += '<label for="highlightTournaments">Highlight Tournament invites</label><input type="checkbox" id="highlightTournaments"><br>';
  394. inputs += '<div class="close-userscript">Close and Refresh</div>';
  395.  
  396. $("body").append("<div class='userscript-container userscript-show'></div><div class='userscript userscript-show'><div class='head'>Change Userscript Settings<img class='close-userscript-img' src='https://i.imgur.com/RItbpDS.png' height='25' width='25'></div>" + inputs + "</div>");
  397. $(".userscript").on("change", function () {
  398. storeVariables();
  399. });
  400. $("#TopRightDropDown").find("ul").append('<li><div class="userscript-menu">Userscript</div></li>');
  401.  
  402. $(".userscript-menu").on("click", function () {
  403. $(".userscript-show").fadeToggle();
  404. $("#TopRightDropDown").fadeToggle();
  405. });
  406.  
  407. $(".close-userscript").on("click", function () {
  408. $(".userscript-show").fadeToggle();
  409. location.reload();
  410. });
  411.  
  412. $(".close-userscript-img").on("click", function () {
  413. $(".userscript-show").fadeToggle();
  414. });
  415. }
  416.  
  417. /**
  418. * Reads the User-Settings from Localstorage
  419. */
  420. function readLocalstorage() {
  421. scrollGames = localStorage.getItem("scrollGames") == "true";
  422. $("#scrollGames").prop("checked", scrollGames);
  423.  
  424. autoRefreshOnFocus = localStorage.getItem("autoRefreshOnFocus") == "true";
  425. $("#autoRefreshOnFocus").prop("checked", autoRefreshOnFocus);
  426.  
  427. highlightTournaments = localStorage.getItem("highlightTournaments") == "true";
  428. $("#highlightTournaments").prop("checked", highlightTournaments);
  429.  
  430. hideMyGamesIcons = localStorage.getItem("hideMyGamesIcons") == "true";
  431. $("#hideMyGamesIcons").prop("checked", hideMyGamesIcons);
  432.  
  433. hideCoinSymbol = true;
  434. }
  435.  
  436. /**
  437. * Creates fixed Titles
  438. * @param stickies
  439. * @constructor
  440. */
  441. function StickyTitles(stickies) {
  442. var thisObj = this;
  443. thisObj.load = function () {
  444. stickies.each(function () {
  445. var thisSticky = $(this).wrap('<div class="followWrap" />');
  446. thisSticky.parent().height(thisSticky.outerHeight());
  447. var pos = parseInt(thisSticky.offset().top) - parseInt($(".showSide").offset().top);
  448. $.data(thisSticky[0], 'pos', pos);
  449. });
  450. $(".showSide").off("scroll.stickies").on("scroll.stickies", function () {
  451. thisObj.scroll();
  452. });
  453. };
  454.  
  455. thisObj.scroll = function () {
  456. stickies.each(function (i) {
  457. var thisSticky = $(this),
  458. nextSticky = stickies.eq(i + 1),
  459. prevSticky = stickies.eq(i - 1),
  460. pos = $.data(thisSticky[0], 'pos');
  461. var showSide = $(".showSide");
  462. if (pos <= showSide.scrollTop()) {
  463. thisSticky.addClass("fixed");
  464. if (nextSticky.length > 0 && thisSticky.offset().top >= $.data(nextSticky[0], 'pos') - thisSticky.outerHeight()) {
  465. thisSticky.addClass("absolute").css("top", jQuery.data(nextSticky[0], 'pos') - thisSticky.outerHeight());
  466. }
  467. } else {
  468. thisSticky.removeClass("fixed");
  469. if (prevSticky.length > 0 && showSide.scrollTop() <= $.data(thisSticky[0], 'pos') - prevSticky.outerHeight()) {
  470. prevSticky.removeClass("absolute").removeAttr("style");
  471. }
  472. }
  473. });
  474. }
  475. }
  476.  
  477. jQuery.fn.outerHTML = function (s) {
  478. return s ? this.before(s).remove() : jQuery("<p>").append(this.eq(0).clone()).html();
  479. };

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址