mirror of
https://gitea.tendokyu.moe/pinapelz/Mirage.git
synced 2026-09-22 22:38:04 +03:00
add FLO/EAG Dancerush import methods
This commit is contained in:
@@ -19,7 +19,7 @@ const EagleUserscriptModal = lazy(() => import("../components/modals/EagleUsersc
|
||||
const TaikoDonderHirobaModal = lazy(() => import("../components/modals/TaikoDonderHirobaModal"));
|
||||
const TaikoEGTSModal = lazy(() => import("../components/modals/TaikoEGTSModal"));
|
||||
|
||||
type ModalType = 'json' | 'dancerush' | 'dancearound' | 'divanet' | 'musicdiver' | 'nostalgiaFlower' | 'nostalgiaEagle' | 'reflecbeatFlower' | 'reflecbeatEagle' | 'taiko' | 'taikoEGTS';
|
||||
type ModalType = 'json' | 'dancerush' | 'dancerushFlower' | 'dancerushEagle' | 'dancearound' | 'divanet' | 'musicdiver' | 'nostalgiaFlower' | 'nostalgiaEagle' | 'reflecbeatFlower' | 'reflecbeatEagle' | 'taiko' | 'taikoEGTS';
|
||||
|
||||
const Import = () => {
|
||||
const { user, isLoading, logout } = useAuth();
|
||||
@@ -144,6 +144,14 @@ const Import = () => {
|
||||
mainGameName="DANCERUSH"
|
||||
onClick={() => setOpenModal('dancerush')}
|
||||
/>
|
||||
<FlowerUserscriptCard
|
||||
mainGameName="DANCERUSH"
|
||||
onClick={() => setOpenModal('dancerushFlower')}
|
||||
/>
|
||||
<EagleUserscriptCard
|
||||
mainGameName="DANCERUSH"
|
||||
onClick={() => setOpenModal('dancerushEagle')}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
case "dancearound":
|
||||
@@ -353,6 +361,32 @@ const Import = () => {
|
||||
}]}
|
||||
/>
|
||||
)}
|
||||
{openModal === 'dancerushFlower' && (
|
||||
<FlowerUserscriptModal
|
||||
isOpen={true}
|
||||
onClose={() => setOpenModal(null)}
|
||||
mainGameName="DANCERUSH"
|
||||
userPage="https://projectflower.eu"
|
||||
importPage="https://projectflower.eu/game/dancerush/profile/7414"
|
||||
scripts={[{
|
||||
name: "Flower Play History (Exports only the page you are on)",
|
||||
url: "https://github.com/pinapelz/Mirage/raw/refs/heads/main/scripts/dancerush/flower/dancerush_flower_scraper.user.js"
|
||||
}]}
|
||||
/>
|
||||
)}
|
||||
{openModal === 'dancerushEagle' && (
|
||||
<EagleUserscriptModal
|
||||
isOpen={true}
|
||||
onClose={() => setOpenModal(null)}
|
||||
mainGameName="DANCERUSH"
|
||||
userPage="https://eagle.ac"
|
||||
importPage="https://eagle.ac/game/dancerush/profile/7414"
|
||||
scripts={[{
|
||||
name: "Eagle Play History (Exports only the page you are on)",
|
||||
url: "https://github.com/pinapelz/Mirage/raw/refs/heads/main/scripts/dancerush/flower/dancerush_flower_scraper.user.js"
|
||||
}]}
|
||||
/>
|
||||
)}
|
||||
{openModal === 'dancearound' && (
|
||||
<EamusementUserscriptModal
|
||||
isOpen={true}
|
||||
@@ -405,7 +439,7 @@ const Import = () => {
|
||||
onClose={() => setOpenModal(null)}
|
||||
mainGameName="NOSTALGIA"
|
||||
userPage="https://eagle.ac"
|
||||
importPage="https://eagle.ac/game/nostalgia/54827307"
|
||||
importPage="https://eagle.ac/game/nostalgia/43711497"
|
||||
scripts={[{
|
||||
name: "Eagle Play History (Exports only the page you are on)",
|
||||
url: "https://github.com/pinapelz/Mirage/raw/refs/heads/main/scripts/nostalgia/flower/nostalgia_flower_scraper.user.js"
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
// ==UserScript==
|
||||
// @name DANCERUSH STARDOM (Flower/Eagle) Play History Scraper + Artist
|
||||
// @version 1.1
|
||||
// @description Export DANCERUSH scores including full judgements, timestamps, and fetched Artist names as JSON
|
||||
// @match https://eagle.ac/game/dancerush/profile/*
|
||||
// @downloadUrl https://github.com/pinapelz/Mirage/raw/refs/heads/main/scripts/dancerush/flower/dancerush_flower_scraper.user.js
|
||||
// @grant none
|
||||
// ==/UserScript==
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const artistCache = {};
|
||||
|
||||
const btn = document.createElement('button');
|
||||
btn.textContent = 'Mirage Export Dancerush JSON';
|
||||
btn.style.position = 'fixed';
|
||||
btn.style.top = '10px';
|
||||
btn.style.right = '10px';
|
||||
btn.style.zIndex = 9999;
|
||||
btn.style.padding = '8px 12px';
|
||||
btn.style.background = '#00bcd4';
|
||||
btn.style.color = 'white';
|
||||
btn.style.border = 'none';
|
||||
btn.style.borderRadius = '4px';
|
||||
btn.style.cursor = 'pointer';
|
||||
btn.style.fontWeight = 'bold';
|
||||
document.body.appendChild(btn);
|
||||
|
||||
btn.addEventListener('click', async () => {
|
||||
const originalText = btn.textContent;
|
||||
btn.disabled = true;
|
||||
btn.style.background = '#9e9e9e';
|
||||
btn.textContent = 'Processing (Fetching Artists)...';
|
||||
|
||||
try {
|
||||
const scores = await parseDancerushLog();
|
||||
const blob = new Blob([JSON.stringify(scores, null, 2)], { type: 'application/json' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = `dancerush_scores_${Date.now()}.json`;
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
} catch (error) {
|
||||
console.error("Scraping failed:", error);
|
||||
alert("An error occurred while fetching song details. Check console.");
|
||||
} finally {
|
||||
btn.textContent = originalText;
|
||||
btn.disabled = false;
|
||||
btn.style.background = '#00bcd4';
|
||||
}
|
||||
});
|
||||
|
||||
async function fetchArtistName(url) {
|
||||
if (!url) return "Unknown Artist";
|
||||
if (artistCache[url]) return artistCache[url];
|
||||
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
const html = await response.text();
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(html, 'text/html');
|
||||
|
||||
// Find the table row that contains "Song Artist"
|
||||
const rows = Array.from(doc.querySelectorAll('table.table tr'));
|
||||
const artistRow = rows.find(r => r.querySelector('th')?.innerText.includes('Song Artist'));
|
||||
const artistName = artistRow?.querySelector('td b')?.innerText.trim() || "Unknown Artist";
|
||||
|
||||
artistCache[url] = artistName;
|
||||
return artistName;
|
||||
} catch (e) {
|
||||
console.warn(`Could not fetch artist for ${url}`, e);
|
||||
return "Unknown Artist";
|
||||
}
|
||||
}
|
||||
|
||||
async function parseDancerushLog() {
|
||||
const rows = document.querySelectorAll('table.table tbody tr.accordion-toggle');
|
||||
const scores = [];
|
||||
for (let index = 0; index < rows.length; index++) {
|
||||
const row = rows[index];
|
||||
const titleElem = row.querySelector('td.text-right.text-middle strong');
|
||||
const diffElem = row.querySelector('td.success div strong');
|
||||
const scoreElem = row.querySelector('td:nth-child(4) strong');
|
||||
const lampElem = row.querySelector('td:nth-child(5) strong');
|
||||
const timestampElem = row.querySelector('td.text-right small');
|
||||
const songLink = row.querySelector('td.text-right.text-middle a')?.href || "";
|
||||
const artistName = await fetchArtistName(songLink);
|
||||
|
||||
const targetId = row.getAttribute('data-target')?.replace('#', '');
|
||||
const detailContainer = document.getElementById(targetId);
|
||||
|
||||
let judgements = { perfect: 0, great: 0, good: 0, bad: 0 };
|
||||
let maxCombo = 0;
|
||||
|
||||
if (detailContainer) {
|
||||
const statDivs = detailContainer.querySelectorAll('div.col-sm-1');
|
||||
statDivs.forEach(div => {
|
||||
const label = div.querySelector('strong')?.innerText.trim();
|
||||
const value = parseInt(div.innerHTML.split('<br>')[1]) || 0;
|
||||
|
||||
if (label === 'Perfect') judgements.perfect = value;
|
||||
if (label === 'Great') judgements.great = value;
|
||||
if (label === 'Good') judgements.good = value;
|
||||
if (label === 'Bad') judgements.bad = value;
|
||||
if (label === 'Combo') maxCombo = value;
|
||||
});
|
||||
}
|
||||
|
||||
const diffText = diffElem ? diffElem.innerText.trim().split(/\s+/) : ["UNKNOWN", "0"];
|
||||
const diffLamp = diffText[0];
|
||||
const difficultyLevel = parseInt(diffText[1]);
|
||||
const rawScorePercent = parseFloat(scoreElem?.innerText.trim()) || 0;
|
||||
const scoreInt = Math.round(rawScorePercent * 1000);
|
||||
|
||||
let lampId = 4;
|
||||
if (lampElem?.innerText.includes("Full Combo")) lampId = 5;
|
||||
if (lampElem?.innerText.includes("Excellent")) lampId = 6;
|
||||
if (lampElem?.innerText.includes("Failed")) lampId = 1;
|
||||
|
||||
let timestampMs = Date.now();
|
||||
if (timestampElem) {
|
||||
timestampMs = new Date(timestampElem.innerText.trim()).getTime();
|
||||
}
|
||||
|
||||
scores.push({
|
||||
timestamp: timestampMs,
|
||||
lamp: lampId,
|
||||
score: scoreInt,
|
||||
title: titleElem?.innerText.trim() || "Unknown",
|
||||
artist: artistName,
|
||||
optional: {
|
||||
maxCombo: maxCombo
|
||||
},
|
||||
diff_lamp: diffLamp,
|
||||
timestamp: timestampMs,
|
||||
difficulty: difficultyLevel,
|
||||
judgements: judgements,
|
||||
num_players: 1
|
||||
});
|
||||
}
|
||||
return {
|
||||
"meta": {
|
||||
"game": "dancerush",
|
||||
"playtype": "Single",
|
||||
"service": "FLOWER/EAGLE Dancerush Export",
|
||||
},
|
||||
"scores": scores
|
||||
};
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user