Puzzle duel: Share message

Add a share button in the pop-up modal after finishing a puzzle.

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

You will need to install an extension such as Tampermonkey to install this script.

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         Puzzle duel: Share message
// @namespace    http://tampermonkey.net/
// @version      2026-01-10
// @description  Add a share button in the pop-up modal after finishing a puzzle.
// @author       WYXkk
// @match        https://puzzleduel.club/
// @match        https://puzzleduel.club/single/*
// @icon         https://puzzleduel.club/images/favicon.ico
// @license      MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    function addButton(puzzle){
        if(document.querySelector(puzzle.controls.card+' [name=voteShare]')) return;
        let voteSave=document.querySelector(puzzle.controls.voteSave);
        const shareButton=document.createElement('button');
        shareButton.type='button';
        shareButton.className='btn btn-info';
        shareButton.textContent='Share';
        shareButton.name='voteShare';
        voteSave.before(shareButton);
        let error=0;
        let originalError=puzzle.showError;
        puzzle.showError=function(...args){
            error+=1;
            return originalError.apply(this,args);
        }
        function generateShareMessage(){
            let context=puzzle.controls.card.slice(1,-8);
            if(context) context=`[${context[0].toUpperCase()}${context.slice(1)}] `;
            let puzzleType=document.querySelector(puzzle.controls.card).children[0].children[0].innerText;
            let size=puzzle.dimension;
            let time=document.querySelector(puzzle.controls.timer).innerText;
            let err=error==0?"":` (${error} error${error==1?'':'s'})`;
            let link=window.location.href;
            return `${context}${puzzleType} (${size}): ${time}${err}\n${link}`;
        }
        shareButton.addEventListener('click',()=>{
            let message=generateShareMessage();
            navigator.clipboard.writeText(message);
            shareButton.innerText='Copied!';
            setTimeout(()=>{shareButton.innerText='Share';},1500);
        })
    }

    function prework(){
        let originalStart=basePuzzle.prototype.start;
        basePuzzle.prototype.start=function(...args){
            addButton(this);
            return originalStart.apply(this,args);
        }
    }
    let timer=setInterval(()=>{
        if(basePuzzle){
            if(basePuzzle.prototype.start){
                clearInterval(timer);
                prework();
            }
        }
    },100);
})();