Pret Inter Extractor (ctrl + shift + l)

Extracts interlibrary loans sorted by section and then by call number, then downloads the info as a text file when a shortcut is pressed.

当前为 2025-03-23 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Pret Inter Extractor (ctrl + shift + l)
// @version      1.0
// @description  Extracts interlibrary loans sorted by section and then by call number, then downloads the info as a text file when a shortcut is pressed.
// @author       Mojo Jojo
// @match        https://bgmdolly.gminvent.fr/*
// @grant        none
// @namespace https://greasyfork.org/users/1448578
// ==/UserScript==

(function() {
    'use strict';

    // Set the shortcut key to CTRL + SHIFT + L
    const shortcutKey = "l";

    document.addEventListener("keydown", function(event) {
        if (event.key.toLowerCase() === shortcutKey && event.ctrlKey && event.shiftKey) {
            event.preventDefault(); // Prevent default browser actions
            console.log("✅ Shortcut CTRL + SHIFT + L detected! Running script...");
            extractAndDownload();
        }
    });

    function extractAndDownload() {
        const targetHeaders = [
            "Mise à disposition pour Bibliothèque publique de Robermont",
            "Mise à disposition pour Navette de la province",
            "Mise à disposition pour Séminaire"
        ];

        function normalizeText(text) {
            return text
                .normalize("NFD").replace(/[\u0300-\u036f]/g, "")
                .replace(/\s+/g, " ")
                .replace(/ç/g, "c")
                .trim().toLowerCase();
        }

        let bookSections = {
            "Section jeunesse": [],
            "Section adulte": [],
            "Réserve": [],
            "Others": []
        };

        let processedBooks = new Set();
        let outputText = "";

        const allDivs = Array.from(document.querySelectorAll("div"));

        let headerDivs = allDivs.filter(div =>
            targetHeaders.some(header => normalizeText(div.innerText).includes(normalizeText(header)))
        );

        headerDivs = Array.from(new Set(headerDivs.map(div => div.innerText))).map(text =>
            allDivs.find(div => normalizeText(div.innerText) === normalizeText(text))
        );

        // outputText += `📚 Found headers: ${headerDivs.length}\n\n`;

        headerDivs.forEach(headerDiv => {
            let possibleTable = headerDiv.closest("td")?.parentElement?.nextElementSibling?.querySelector("table")
                || headerDiv.closest("tr")?.nextElementSibling?.querySelector("table")
                || headerDiv.closest("td")?.parentElement?.parentElement?.querySelector("table");

            if (!possibleTable) {
                console.warn("No table found for:", headerDiv.innerText.trim());
                return;
            }

            let rows = possibleTable.querySelectorAll("tbody > tr");

            rows.forEach(row => {
                try {
                    let columns = Array.from(row.querySelectorAll("td"));

                    if (columns.length < 4) {
                        console.warn("⚠️ Skipping row due to missing columns:", row.innerText.trim());
                        return;
                    }

                    let titleCell = columns[2];
                    let coteCell = columns[3];

                    if (titleCell && coteCell) {
                        let title = titleCell.innerText.trim();
                        let coteLines = coteCell.innerText.trim().split("\n").map(line => normalizeText(line));
                        let coteFirstRow = coteLines.length > 0 ? coteLines[0] : "⚠️⚠️";
                        let coteSecondRow = coteLines.length > 1 ? coteLines[1] : "⚠️⚠️";
                        let fullCoteInfo = coteLines.join("\n");

                        let bookKey = `${title}-${coteSecondRow}`;
                        if (processedBooks.has(bookKey)) {
                            return;
                        }
                        processedBooks.add(bookKey);

                        let section = "Others";

                        if (coteFirstRow.includes("jeunesse")) {
                            section = "Section jeunesse";
                        } else if (coteFirstRow.includes("adulte")) {
                            section = "Section adulte";
                        } else if (coteFirstRow.includes("reserve") || coteFirstRow.includes("réserve")) {
                            section = "Réserve";
                        }

                        bookSections[section].push({ title, coteSecondRow, fullCoteInfo });

                    }
                } catch (error) {
                    console.error("❌ Error processing row:", error);
                }
            });
        });

        function sortByCote(a, b) {
            return a.coteSecondRow.localeCompare(b.coteSecondRow);
        }

        for (let section in bookSections) {
            bookSections[section].sort(sortByCote);
        }

        if (bookSections["Others"].length === 0) {
            delete bookSections["Others"];
        }

        outputText += `📚 Found books: ${Object.values(bookSections).flat().length}`;

        for (let section in bookSections) {
            outputText += `\n===================== ${section} =====================\n`;

            bookSections[section].forEach(book => {
                outputText += `📖 ${book.title}\n👀 COTE: ${book.coteSecondRow.toUpperCase()}\n`;

                if (section === "Others") {
                    outputText += `📜 Full Cote Info:\n${book.fullCoteInfo}\n`;
                }

                outputText += "------------------\n";
            });
        }

        function downloadTextFile(filename, text) {
            let element = document.createElement("a");
            let file = new Blob([text], { type: "text/plain" });
            element.href = URL.createObjectURL(file);
            element.download = filename;
            document.body.appendChild(element);
            element.click();
            document.body.removeChild(element);
        }

        downloadTextFile("pret_inter_sorted.txt", outputText);
    }
})();