Puzzle duel: Share message

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

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==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);
})();