osu beatmap download from mirror. osu beatmap镜像站下载。支持的镜像站点:inso.link、osu.sayobot.cn、osu.direct、nerinyan.moe。也可以自行添加。
// ==UserScript== // @name osu! my download // @description osu beatmap download from mirror. osu beatmap镜像站下载。支持的镜像站点:inso.link、osu.sayobot.cn、osu.direct、nerinyan.moe。也可以自行添加。 // @author dazzulay // @copyright 2024, dazzulay // @version 2.4.8 // @license GPLv3 // @icon http://osu.ppy.sh/favicon.ico // @match http*://osu.ppy.sh/* // @match http*://old.ppy.sh/* // @grant GM_registerMenuCommand // @grant GM_setValue // @grant GM_getValue // @namespace https://greasyfork.org/scripts/3916 // @homepageURL https://greasyfork.org/scripts/3916 // ==/UserScript== (function () { function init() { const has_init = GM_getValue("has_init", null); if (has_init === null) { GM_setValue("mirros", { sayobot: { url: 'https://osu.sayobot.cn/home?search={bmid}', text: 'DOWNLOAD SAYOBOT', class: 'my_green', style: '', target: '_blank' }, insolink: { url: 'https://inso.link/?source=osu_my_download&m={bmid}', text: 'DOWNLOAD INSO.LINK', class: 'my_pink', style: '', target: '_blank' }, osu_direct: { url: 'https://osu.direct/api/d/{bmid}', text: 'DOWNLOAD OSU.DIRECT', class: 'my_purpule', style: '', target: '_blank' }, nerinyan: { url: 'https://api.nerinyan.moe/d/{bmid}', text: 'DOWNLOAD NERINYAN', class: 'my_orange', style: '', target: '_blank' } }); GM_setValue("has_init", 1); } } init() function settingBox() { // css样式 设置 $('head').append(` <style> #my_setting_box{ max-width: 800px; position: fixed; top: 100px; bottom: 100px; left: 0; right: 0; margin: auto; padding: 20px; display: flex; gap: 20px; flex-direction: column; background: #fff; color: #000; } #my_setting_mirros{ flex: 1; } .my_setting_buttons{ display: flex; gap: 20px; height: 50px; } .my_setting_buttons > *{ display: block; } #my_setting_save{ flex: 2; } #my_setting_reset{ flex: 1; } #my_setting_cancel{ flex: 1; } </style> `); GM_registerMenuCommand("Setting", function () { if ($('#my_setting_box').length == 0) { var mirros = GM_getValue("mirros") mirros = JSON.stringify(mirros, null, "\t") var box = ` <div id="my_setting_box"> <div>osu! my download Setting</div> <textarea id="my_setting_mirros">${mirros}</textarea> <div class="my_setting_buttons"> <button id="my_setting_save">保存 Save</button> <button id="my_setting_reset">重置 Reset</button> <button id="my_setting_cancel">取消 Cancel</button> </div> </div> `; $('body').append(box); $('#my_setting_cancel').on('click', function () { $('#my_setting_box').remove() }); $('#my_setting_reset').on('click', function () { GM_setValue("has_init", null); window.location.reload(); }); $('#my_setting_save').on('click', function () { try { var mirros = JSON.parse($('#my_setting_mirros').val()); GM_setValue("mirros", mirros); window.location.reload(); } catch (e) { alert("Error:" + e) } }); } }); } settingBox() var domain = document.domain; var drive = domain.replace(/\./g, '_'); function myJQueryCode() { function osu_my_downoad() { var self = this; this.mirros = GM_getValue("mirros") /* 渲染mirro模板,返回渲染的字符串。暂时只渲染url的bmid */ this.mirros_parse = function (bmid) { var return_mirros = $.extend(true, {}, self.mirros); var _param = 'url'; $.each(return_mirros, function (k, v) { return_mirros[k][_param] = str_render(v[_param], { bmid: bmid }); }); return return_mirros; }; this.drives = { osu_ppy_sh: function () { var is_new = $('.osu-layout').length; if (is_new) { // css样式 设置 $('head').append(` <style> .my_container .btn-osu-big__text-top { white-space: normal; } .my_container .btn-osu-big{ position: relative; } .my_container .btn-osu-big__content{ position: relative; } .my_container a:before { content: " "; position: absolute; left: 0; right: 0; top: 0; bottom: 0; border-radius: 4px; } .my_orange:before { background-color: rgba(255,141,0,.5) } .my_green:before { background-color: rgba(0,101,0,.5) } .my_pink:before { background-color: rgba(255, 102, 170,.5) } .my_purpule:before { background-color: rgba(169, 10, 165,0.5); } </style> `); var beatmapset_page = '.js-react--beatmapset-page'; var ready = function (event) { var _timer = setInterval(function () { var $bp = $(beatmapset_page); if ($bp.length == 0) { clearInterval(_timer); return; } if ($('.beatmapset-header__box--main').length > 0) { loaded(); clearInterval(_timer); } }, 200); function loaded() { if ($('.my_container').length > 0) { return; } // 获取beatmapid var bmsrc = $('.js-audio--play').attr('data-audio-url'); if (!bmsrc) { return false; } var bmid = bmsrc.substring(bmsrc.lastIndexOf("/") + 1, bmsrc.lastIndexOf(".")); // 设置url var parsed_mirros = self.mirros_parse(bmid); // 添加按钮 var $container = $('<div class="my_container"></div>'); var btn_tpl = '<a href="{url}" class="btn-osu-big btn-osu-big--beatmapset-header {class}" style="{style}" target="{target}"><div class="btn-osu-big__content"><div class="btn-osu-big__left"><span class="btn-osu-big__text-top">{text}</span></div><div class="btn-osu-big__icon"><span class="fa fa-download"></span></div></div></a>'; $.each(parsed_mirros, function (k, v) { $container.append(str_render(btn_tpl, parsed_mirros[k])); }); $('.beatmapset-header__buttons').append($container); } }; document.addEventListener('turbolinks:load', ready); ready(); } else { // 获取beatmapid var bmsrc = $('.bmt').attr('src'); if (!bmsrc) { return false; } var bmid = bmsrc.substring(bmsrc.indexOf("thumb/") + 6, bmsrc.lastIndexOf("l")); // css样式 设置 $('head').append(` <style> .my_container { position: fixed; top: 20px; right: 0px; } .my_btn { text-align: center; width: 150px; height: 111px; display: table-cell; vertical-align: middle; margin: 0 0 10px 0; padding: 10px; font-family: Haettenschweiler,Impact,"Arial Grande",Tahoma,Helvetica,Arial,sans-serif; font-size: 32px; font-weight: normal; color: #fff; border: 4px solid #fff; border-radius: 6px; } .my_btn:hover { text-shadow: 0 0 20px floralwhite; color: #fff; } .my_btn span { display: inline-block; vertical-align: middle; text-align: center } .my_orange { background: linear-gradient(to bottom,darkorange,wheat,darkorange); } .my_blue { background: linear-gradient(to bottom,darkblue,lightblue,darkblue); } .my_green { background: linear-gradient(to bottom,darkgreen,lightgreen,darkgreen); } .my_pink { background: linear-gradient(to bottom,HotPink,pink,HotPink); } .my_purpule { background: linear-gradient(to bottom,#261326,#E064E0,#261326); } </style> `); // 设置url var parsed_mirros = self.mirros_parse(bmid); // 添加按钮 var $container = $('<div class="my_container"></div>'); var btn_tpl = '<a class="my_btn {class}" style="{style}" href="{url}" target="{target}"><span>{text}</span></a><br/>'; $.each(parsed_mirros, function (k, v) { $container.append(str_render(btn_tpl, parsed_mirros[k])); }); $('body').append($container); } } }; this.init = function () { // var domain = document.domain; // var drive = domain.replace(/\./g, '_'); // self.drives[drive](); self.drives.osu_ppy_sh(); }; self.init(); } osu_my_downoad(); } if (typeof jQuery == 'undefined') { var headTag = document.getElementsByTagName("head")[0]; var jqTag = document.createElement('script'); jqTag.type = 'text/javascript'; jqTag.src = '//code.jquery.com/jquery-1.8.3.min.js'; jqTag.onload = myJQueryCode; headTag.appendChild(jqTag); } else { myJQueryCode(); } function str_render(template, context) { var tokenReg = /(\\)?\{([^\{\}\\]+)(\\)?\}/g; return template.replace(tokenReg, function (word, slash1, token, slash2) { if (slash1 || slash2) { return word.replace('\\', ''); } var variables = token.replace(/\s/g, '').split('.'); var currentObject = context; var i, length, variable; for (i = 0, length = variables.length; i < length; ++i) { variable = variables[i]; currentObject = currentObject[variable]; if (currentObject === undefined || currentObject === null) return ''; } return currentObject; }); } function getUrlParameter(sParam) { var sPageURL = decodeURIComponent(window.location.search.substring(1)), sURLVariables = sPageURL.split('&'), sParameterName, i; for (i = 0; i < sURLVariables.length; i++) { sParameterName = sURLVariables[i].split('='); if (sParameterName[0] === sParam) { return sParameterName[1] === undefined ? true : sParameterName[1]; } } } })();