// ==UserScript== // @name Osu beatmap search // @namespace Osu // @version 0.2 // @description Osu beatmap search by specific date // @author Monorail // @match https://osu.ppy.sh/beatmapsets* // @grant none // @downloadURL none // ==/UserScript== (function() { 'use strict'; let parser = new DOMParser(); function componentInitialize(){ let a = new Date(); let TimeNow = { year: a.getFullYear(), month: a.getMonth(), day: a.getDate(), hour: a.getHours() }; // 設置開啟按鍵(左下方)、搜尋頁面、輸入框樣式,以及外層DOM結構 let ty = `
S
`; // insert DOM let DOM = parser.parseFromString(ty, "text/html"); let origBody = document.querySelectorAll("body")[0]; origBody.appendChild(DOM.querySelectorAll("style")[0]); DOM.querySelectorAll("body > div").forEach((divPart) => { origBody.appendChild(divPart); }); // set eventListenser of inserted button let btn = document.querySelectorAll(".search-button")[0]; let searchBox = document.querySelectorAll(".search-container")[0]; btn.addEventListener("click", (e) => { searchBox.classList.toggle("hidden"); }); return searchBox; } let searchBox = componentInitialize(); // search action & results layout let goFind = document.querySelectorAll(".goFind")[0]; function getUnixTime(date){ return new Date(date.year, date.month, date.day, 23).getTime(); } function fetchBeatmapData(unixTime){ return fetch(`https://osu.ppy.sh/beatmapsets/search?cursor%5Bapproved_date%5D=${unixTime}&cursor%5B_id%5D=`) .then(res => res.json()); } let resultArea = searchBox.querySelectorAll(".result-area")[0]; let cursor; function resultInitialize(){ resultArea.innerHTML = ` `; let inputTime = { year: searchBox.querySelectorAll(".input-start-year")[0].value, month: searchBox.querySelectorAll(".input-start-month")[0].value - 1, day: searchBox.querySelectorAll(".input-start-day")[0].value }; cursor = getUnixTime(inputTime); console.log(inputTime, cursor); } function arrange(bms){ let bmResult = []; bms.forEach((bm) => { let rankedDate = ""; if(bm.ranked_date != undefined){ let d = new Date(bm.ranked_date); rankedDate = `${d.getFullYear()}/${d.getMonth() + 1}/${d.getDate()}_${d.getHours()}時`; } function withVideo(){ if(bm.video === true) return "video included "; return ""; } function withSB(){ if(bm.storyboard === true) return "SB included"; return ""; } function generateDifficulty(diffs){ function inRange(a, b, c){ return a >= b && a <= c; } function diffColor(rate){ if(inRange(rate, -Infinity, 1.5)){ return "easy"; } // actually 2.25 by some observation else if(inRange(rate, 1.5, 2.4)){ return "normal"; } else if(inRange(rate, 2.4, 3.75)){ return "hard"; } // 6.7 ~ 6.85 else if(inRange(rate, 3.75, 5.25)){ return "insane"; } else if(inRange(rate, 5.25, 6.75)){ return "extra"; } else { return "black"; } } let str = ""; // 1. sort by difficulty rating diffs.sort((diff1, diff2) => { return diff1.difficulty_rating - diff2.difficulty_rating; }); // 2. sort by mode(osu, taiko, mania, fruits) let diffs_class = [[], [], [], []]; diffs.forEach((diff) => { diffs_class[diff.mode_int].push(diff); }) // 3. build string diffs_class.forEach((diff_class) => { diff_class.forEach((diff) => { str = str + `${Math.round(diff.difficulty_rating * 10) / 10}`; }); }); return str; } let bmt_v2 = `
${bm.source}
${bm.title} <- ${bm.artist}
${generateDifficulty(bm.beatmaps)}
${bm.status} ${rankedDate}   mapped by ${bm.creator}   [dl] ${withVideo()}${withSB()}▶ ${bm.play_count}
`; resultArea.appendChild( parser.parseFromString(bmt_v2, "text/html").querySelector(".bm") ); // let audio = document.querySelector("audio"); // audio.addEventListener("play", (e) => { // console.log(e.target.src); // }); // audio.addEventListener("pause", (e) => { // console.log(e.target.src); // }); }); } let customScript = ` let audio = new Audio(); let preview = function (e){ // console.log(e.target.parentNode.dataset["audioUrl"]); // fetch() cannot be applied to this // https://blog.fullstacktraining.com/what-is-an-opaque-response/ // https://whatwebcando.today/articles/opaque-responses-service-worker/ // console.dir(audio); if(audio.currentSrc.indexOf(e.target.parentNode.dataset["audioUrl"]) !== -1){ if(audio.paused){ audio.play(); } else { audio.pause(); } return; } audio.src = e.target.parentNode.dataset["audioUrl"]; audio.play(); }`; let s = document.createElement("script"); s.innerHTML = customScript; document.body.append(s); let limit = 300; let bmLoaded = 0; function appendLoadMoreButton(){ let loadSection = `
load
`; let loadSectionDOM = parser.parseFromString(loadSection, "text/html").querySelector(".load-section"); let loadBtnDOM = loadSectionDOM.querySelector(".load-btn"); loadBtnDOM.addEventListener("click", SLBM); resultArea.appendChild(loadSectionDOM); } function SLBM(e){ if(e.target.classList.contains("goFind")){ resultInitialize(); } if(e.target.classList.contains("load-btn")){ resultArea.querySelector(".load-section").remove(); } fetchBeatmapData(cursor) .then(data => { console.log(data.beatmapsets); console.log(data.cursor); arrange(data.beatmapsets); appendLoadMoreButton(); cursor = data.cursor.approved_date; }); } goFind.addEventListener("click", SLBM); })();