Greasy Fork

Greasy Fork is available in English.

osu! my download

ous beatmap download from mirror.osu beatmap镜像站下载。支持的镜像站点:inso.link、osu.sayobot.cn、osu.direct、nerinyan.moe。也可以自行添加。

当前为 2024-05-29 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name           osu! my download
// @description    ous beatmap download from mirror.osu beatmap镜像站下载。支持的镜像站点:inso.link、osu.sayobot.cn、osu.direct、nerinyan.moe。也可以自行添加。
// @author         dazzulay
// @copyright      2024, dazzulay
// @version        2.4.4
// @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      http://greasyfork.icu/scripts/3916
// @homepageURL    http://greasyfork.icu/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'
                },
                kitsu: {
                    url: 'https://osu.direct/api/d/{bmid}',
                    text: 'DOWNLOAD KITSU',
                    class: 'my_purpule',
                    style: '',
                    target: '_blank'
                },
                nerinyan: {
                    url: 'https://api.nerinyan.moe/d/{beatmapset_id}',
                    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__box--main').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];
            }
        }
    }
})();