見出し画像

[BMS] LR2IRを拡張するTampermonkeyスクリプトを作りました [LR2, LR2IR-Helper, Tampermonkey]

背景

当スクリプトは以下を参考に作ったTampermonkey用スクリプトです。現在、ribbit.xyzが鯖落ちしており、譜面ビューアへのリンクも有志のミラーサイトにする必要がありました。

機能

bmsid, MD5, 譜面ビューアへのリンクをページ上部に表示するようにします。

拡張機能が動作する様子

MD5を含むURLでのアクセス(LR2本体や難易度表からのアクセス)の場合高速に動きます。外部へこのbmsidのMD5を問い合わせる必要がないからです。

bmsidで曲ページに来ている場合、外部にMD5の値を問い合わせる必要があるため読み込み中…と出てきます。MD5が不明な譜面の場合には譜面へのリンクは得られません。2024/8くらいまでの譜面ならbmsidとmd5のマッピングができていますが、今後新規に増えていく譜面はbmsidでのアクセスだと変換できません。

読み込み中がmd5に解決される様子

導入方法

まずTampermonkey拡張機能を導入してください。ChromeやChrome系であるブラウザ(Edge, Vivaldi)なら使うことができます。この拡張機能は、ユーザーが作ったスクリプトをブラウザで実行することができるというものです。

以下のスクリプトをダウンロードするか、コピペして導入してください。

// ==UserScript==
// @name         LR2IR-Helper
// @namespace
// @version      2024-09-05
// @description  これ(https://github.com/ladymade-star/LR2IR-Helper)を参考にBMS Score Viewerのミラーサイトにリンクするように変更
// @author       マンハッタンカフェ
// @match        http://www.dream-pro.info/~lavalse/LR2IR/search.cgi*
// @icon
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // 曲ページ「更新履歴」リンクのGETパラメータからbmsidを取得
    let bmsid;
    const a = document.getElementsByTagName("a");
    for (let i = 0; i < a.length; i++) {
        if (a[i].innerText == "更新履歴") {
            bmsid = new URL(a[i].href).searchParams.get('bmsid');
        }
    }

    // 現在のウィンドウのGETパラメータを取得
    const params = new URL(window.location.href).searchParams;
    let bmsmd5 = params.get('bmsmd5');

    //bmsidかbmsmd5が取得できている場合は曲ページと判定
    if (bmsid || bmsmd5) {
        // LERIR-Helperの<H3>見出しを作る
        const h3_element = document.createElement('h3');
        h3_element.textContent = 'LR2IR-Helper';

        // テーブルを作る
        const table_element = document.createElement("table");
        // bmsid
        const bmsid_tr_element = document.createElement("tr");
        const bmsid_th_element = document.createElement("th");
        bmsid_th_element.textContent = "bmsid";
        bmsid_th_element.width = "15%";
        const bmsid_td_element = document.createElement("td");
        bmsid_td_element.id = "bmsid_td";
        const bmsid_a_element = document.createElement("a");
        bmsid_a_element.href = "http://www.dream-pro.info/~lavalse/LR2IR/search.cgi?mode=ranking&bmsid=" + bmsid;
        bmsid_a_element.textContent = bmsid;
        bmsid_td_element.appendChild(bmsid_a_element);
        bmsid_tr_element.appendChild(bmsid_th_element);
        bmsid_tr_element.appendChild(bmsid_td_element);
        table_element.appendChild(bmsid_tr_element);
        // bmsmd5
        const bmsmd5_tr_element = document.createElement("tr");
        const bmsmd5_th_element = document.createElement("th");
        bmsmd5_th_element.textContent = "bmsmd5";
        bmsmd5_th_element.width = "15%";
        const bmsmd5_td_element = document.createElement("td");
        const bmsmd5_a_element = document.createElement("a");
        bmsmd5_td_element.id = "bmsmd5_td";
        bmsmd5_td_element.appendChild(bmsmd5_a_element);
        bmsmd5_tr_element.appendChild(bmsmd5_th_element);
        bmsmd5_tr_element.appendChild(bmsmd5_td_element);
        table_element.appendChild(bmsmd5_tr_element);
        // BMS Score Viewer
        const viewer_tr_element = document.createElement("tr");
        const viewer_th_element = document.createElement("th");
        viewer_th_element.textContent = "BMS Score Viewer";
        viewer_th_element.width = "15%";
        const viewer_td_element = document.createElement("td");
        const viewer_a_element = document.createElement("a");
        viewer_td_element.id = "viewer_td";
        viewer_td_element.appendChild(viewer_a_element);
        viewer_tr_element.appendChild(viewer_th_element);
        viewer_tr_element.appendChild(viewer_td_element);
        table_element.appendChild(viewer_tr_element);

        const h3 = document.querySelectorAll("h3");
        // 見出しとテーブルを追加、LR2IRに登録されているかどうかで分岐
        if (!document.querySelectorAll("h3").length){
            // 「この曲は登録されていません。」の場合
            document.getElementById("search").after(table_element)
            document.getElementById("search").after(h3_element)
        } else {
            // 登録されている場合
            h3[0].before(h3_element);
            h3[0].before(table_element);
        }

        // GETパラメータの状態で分岐
        if (bmsmd5) {
            // LR2から飛んできているなど、GETでパラメータbmsmd5がセットされている場合
            // bmsmd5
            bmsmd5_a_element.href = "http://www.dream-pro.info/~lavalse/LR2IR/search.cgi?mode=ranking&bmsmd5=" + bmsmd5;
            bmsmd5_a_element.textContent = bmsmd5;
            // BMS Score Viewer
            viewer_a_element.href = "https://bms-score-viewer.pages.dev/view?md5=" + bmsmd5;
            viewer_a_element.textContent = "https://bms-score-viewer.pages.dev/view?md5=" + bmsmd5;
        } else {
            // bmsmd5がセットされていない場合(=bmsidで曲ページに来ている)
            bmsmd5_a_element.textContent = "読み込み中...";
            viewer_a_element.textContent = "読み込み中...";
            (async() => {
                const url = "https://script.google.com/macros/s/AKfycby-nDrmsJ70lmA8oNf9Yw1nwwto-w6nThdiu90Tm7VbX7im7xqCb1_WyL5e6Jk_V2VhSA/exec?method=getmd5&bmsid=" + bmsid;
                try {
                    const response = await fetch(url);
                    if (!response.ok) {
                        throw new Error(`レスポンスステータス: ${response.status}`);
                    }
                    bmsmd5 = await response.text();
                    // bmsmd5
                    bmsmd5_a_element.href = "http://www.dream-pro.info/~lavalse/LR2IR/search.cgi?mode=ranking&bmsmd5=" + bmsmd5;
                    bmsmd5_a_element.textContent = bmsmd5;
                    // BMS Score Viewer
                    viewer_a_element.href = "https://bms-score-viewer.pages.dev/view?md5=" + bmsmd5;
                    viewer_a_element.textContent = "https://bms-score-viewer.pages.dev/view?md5=" + bmsmd5;
                } catch (error) {
                    console.error(error.message);
                }
            })();
        }
    }
})();

詳細な導入方法

まず、ダッシュボードを開く

「ダッシュボード」を開いてください

つぎに、ダッシュボード画面へダウンロードした「LR2IR-Helper-2024-09-05.user.js」をドラッグアンドドロップする

LR2IR-Helper-2024-09-05.user.jsをドラッグ&ドロップする様子

「インストール」ボタンを押せばOK

インストール直前の様子

おまけ

bmsid-md5のマッピング情報スプシ

上記スプシのGAS(bmsidでmd5を検索してreturn)

function test() {
  const sheetId = "1RCrvKGHAkIfsAx5PV7-2W0d080DBUMwPvahmmL48T68";  // スプレッドシートのIDを指定
  const sheetName = "data";  // シート名を指定

  Logger.log(getMd5ByBmsId(sheetId, sheetName, 307669));
  Logger.log(getMd5ByBmsId(sheetId, sheetName, 148141));
  Logger.log(getMd5ByBmsId(sheetId, sheetName, 0));
}

function doGet(e) {
  // シートのIDと名前を指定
  const sheetId = "1RCrvKGHAkIfsAx5PV7-2W0d080DBUMwPvahmmL48T68";  // スプレッドシートのIDを指定
  const sheetName = "data";  // シート名を指定

  // GETパラメータを取得
  const method = e.parameter.method;
  const bmsid = e.parameter.bmsid;

  switch (method) {
    case 'getmd5':
      // bmsidがnullまたはundefinedの場合は「illegal access」を返す
      if (!bmsid) {
        return ContentService.createTextOutput("illegal access");
      }
      // bmsidに対応するmd5を取得
      const md5 = getMd5ByBmsId(sheetId, sheetName, bmsid);
      // レスポンスをTEXT形式で返す
      return ContentService.createTextOutput(md5);
    default:
      // 未対応のmethodの場合「illegal access」を返す
      return ContentService.createTextOutput("illegal access");
  }
}

function getMd5ByBmsId(sheetId, sheetName, bmsid) {
  // スプレッドシートをIDで取得
  const spreadsheet = SpreadsheetApp.openById(sheetId);
  
  // シートを名前で取得
  const sheet = spreadsheet.getSheetByName(sheetName);
  
  // A列(bmsid列)を範囲として取得
  const range = sheet.getRange("A:A");
  
  // TextFinderを使ってbmsidを完全一致で検索
  const textFinder = range.createTextFinder(bmsid).matchEntireCell(true);
  const foundCell = textFinder.findNext();
  
  // bmsidが見つかった場合、対応するmd5を返す
  if (foundCell) {
    const row = foundCell.getRow();
    return sheet.getRange(row, 2).getValue();  // B列(md5列)を返す
  }
  
  // bmsidが見つからない場合
  return "not found";
}

この記事が気に入ったらサポートをしてみませんか?