OJ Downloader

Download OJ problems as markdown files

// ==UserScript==
// @name         OJ Downloader
// @namespace    iai-sh-cn
// @version      0.1
// @description  Download OJ problems as markdown files
// @license      AGPL-3.0-or-later
// @author       Y.V
// @match        https://iai.sh.cn/*
// @icon         https://iai.sh.cn/images/logo.png
// @grant        GM_xmlhttpRequest
// @require      https://code.jquery.com/jquery-3.6.0.min.js
// @require      https://cdn.jsdelivr.net/npm/axios@1.1.2/dist/axios.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js
// ==/UserScript==


(function() {
    'use strict';

    // Create a download button with style
    var button = $('<button id="download-button">下载题目</button>');
    button.css({
        'position': 'fixed',
        'top': '10px',
        'right': '10px',
        'width': '100px',
        'height': '40px',
        'border': 'none',
        'border-radius': '5px',
        'background': '#00a0e9',
        'color': '#fff',
        'font-size': '16px',
        'font-weight': 'bold',
        'cursor': 'pointer'
    });

    // Append the button to the body
    $('body').append(button);

    // Add click event listener with async keyword
    button.click(async function() { // add async here

        // Disable the button and show loading text
        button.prop('disabled', true);
        button.text('加载中...');

        // Get the contest id from the url
        var url = window.location.href;
        var contestId = url.split('/')[4];

        try {
            // Send a get request to the api with await keyword
            let response = await axios.get('https://api.iai.sh.cn/contest/listProblem?contestId=' + contestId); // add await here

            // Get the data array from the response
            var data = response.data;

            var zipName = $('h2.ant-typography').text()

            // Group the data by level
            var groups = {};
            for (var i = 0; i < data.length; i++) {
                var level = data[i].level;
                if (!groups[level]) {
                    groups[level] = [];
                }
                groups[level].push(data[i]);
            }

            // Create a new zip object
            var zip = new JSZip();

            // Loop through each group
            for (var level in groups) {

                var md = '';
                // Loop through each problem in the group
                for (var j = 0; j < groups[level].length; j++) {

                    // Get the problem object
                    var problem = groups[level][j];

                    // Generate a markdown string for the problem
                    md += '### 题目' + (j + 1) + '\n\n';
                    md += problem.title + '\n\n';
                    md += '#### 题目描述\n\n';
                    md += problem.description + '\n\n';
                    md += '#### 输入格式\n\n';
                    md += problem.inputFormat + '\n\n';
                    md += '#### 输出格式\n\n';
                    md += problem.outputFormat + '\n\n';
                    md += '#### 数据范围\n\n';
                    md += problem.dataRange + '\n\n';
                    md += '#### 样例数据\n\n';
                    for (var k = 0; k < problem.exampleList.length; k++) {
                        var example = problem.exampleList[k];
                        var input = example.input.replace(/\n/g, '\n> ');
                        var output = example.output.replace(/\n/g, '\n> ');
                        md += '输入\n\n> ' + input + '\n\n';
                        md += '输出\n\n> ' + output + '\n\n';
                        if (example.note) {
                            md += '说明\n\n';
                            md += example.note + '\n\n';
                        }
                    }

                    md += '\n';
                    md += '\n';
                    md += '\n';
                }

                zip.file(level + '.md', md);
            }


            // Generate the zip file and download it with await keyword
            let blob = await zip.generateAsync({type: 'blob'}); // add await here

            var link = document.createElement('a');
            link.href = URL.createObjectURL(blob);
            link.download =  zipName + '.zip';
            link.click();

            // Enable the button and restore text
            button.prop('disabled', false);
            button.text('下载题目');

        } catch (error) {
            // Handle error
            console.log(error);

            // Enable the button and restore text
            button.prop('disabled', false);
            button.text('下载题目');
        }
    });
})();