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 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 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);
    }
})();