聆音club图书发布辅助

在聆音书箱发布页面上收集豆瓣书籍信息并回填

// ==UserScript==
// @name         聆音club图书发布辅助
// @namespace    http://tampermonkey.net/
// @version      2024-09-27
// @description  在聆音书箱发布页面上收集豆瓣书籍信息并回填
// @author       Euzen
// @match        https://pt.soulvoice.club/upload.php
// @icon         https://www.google.com/s2/favicons?sz=64&domain=soulvoice.club
// @grant        GM_xmlhttpRequest
// @license MIT
// ==/UserScript==


(function() {
    'use strict';
    let pstorageToken='Lfx9NiLmGyCkdvn3UkYFQzcchhQEr3hVlYRJ6bh7vQS2QSzhrK+u8/UaukXzSZvoVrv776zu57KlclazY9cpYw==';
    // let pstorageToken='KQeyogJdfHnIZmv5leud125URwXzLUoQl4LoxeBhZ0CYEC3FpcHot5FlSm4gcm5/noq2vziPhKh9D/qeLmcr9A==';
    let ImgbbToken='1304252c56a973a9bb9626276e225268304ec4d8';

    let ImgbbApikey = 'your_api_key';
    //需在ImgURL注册用户和申请uid和token
    //https://www.imgurl.org/vip/user#user=login
    let ImgurlUid='your_api_uid';
    let ImgurlToken='your_api_token';

    // 从 url 下载 blob
    let getBlobFromUrl = (downurl,site) => {
        return new Promise(function (resolve, reject) {
            GM_xmlhttpRequest({
                method: 'GET',
                responseType: 'blob',
                url: downurl,
                onload: function (res){
                    if (site == "ImgBBu")
                    {
                        let reader = new FileReader();
                        reader.readAsDataURL(res.response);
                        reader.onloadend = function () {
                            let base64String = reader.result;
                            // console.log('Base64 String - ', base64String);
                            // Simply Print the Base64 Encoded String,
                            // without additional data: Attributes.
                            // console.log('Base64 String without Tags- ', base64String.substr(base64String.indexOf(',') + 1));
                            resolve(base64String.substr(base64String.indexOf(',') + 1));
                        }
                    }
                    else
                    {
                        resolve(res.response);
                    }
                },
                onerror: res =>{reject('Resoonse error'+res.status)},
                ontimeout: function(){reject('Timeout')},
            });
        });
    }

    //上传到图床
    let uploadCoverPic = (picBlob,site) => {

        return new Promise(function (resolve, reject) {
            console.log("图床:",site);
            let formData = new FormData();
            let upUrl = "https://api.imgbb.com/1/upload";
            if (site == "pstorage")
            {
                formData.append('authenticity_token',pstorageToken);
                formData.append('upload[uploaded_file]',picBlob,"image.jpg");
                upUrl = "https://pstorage.space/uploads";
            }
            else if (site == "ImgBBu")
            {
                formData.append('image', picBlob);
                formData.append('key',ImgbbApikey);
                upUrl = "https://api.imgbb.com/1/upload";
            }
            else if (site == "ImgBB")
            {
                formData.append('type','file');
                formData.append('action','upload');
                formData.append('auth_token',ImgbbToken);
                formData.append('source',picBlob,"image.jpg");
                upUrl = "https://imgbb.com/json";
            }
            else if (site == "ImgURL")
            {
                formData.append('uid',ImgurlUid);
                formData.append('token',ImgurlToken);
                formData.append('file',picBlob,"image.jpg");
                upUrl = 'https://www.imgurl.org/api/v2/upload';
            }
            GM_xmlhttpRequest({
                method:'POST',
                url:upUrl,
                data:formData,
                onload:function(response){
                    console.log(response.responseText);
                    let data={}
                    let imgUrl='error image url';
                    try {
                        data = JSON.parse(response.responseText);
                        if (site=='ImgBBu' || site=='ImgURL')
                        {
                            imgUrl = data.data.url;
                        }
                        else if (site=='pstorage')
                        {
                            imgUrl = data.files[0].url;
                        }
                        else if (site=='ImgBB')
                        {
                            imgUrl = data.image.url;
                        }
                        resolve(imgUrl);
                    }
                    catch (e) {
                        console.log(e);
                        resolve(false);
                    }
                },
                onerror:response =>{reject('Resoonse error'+response.status);},
                ontimeout:function(){reject('Upload Timeout.');}
            });
        })
            // .then(res=>{console.log('yyyyyy'+res)}).catch(e=>{console.log('xxxxx:'+e);})

    }

    let isCJK = (char) => {
        return /\p{Unified_Ideograph}/u.test(char);
    }
    function getBookInfo() {
        let obj=document.querySelector("#input01");
        let sel=document.querySelector("#select01");
        let msgdiv=document.querySelector("#div01");
        let msgspan=document.querySelector("#span01");
        msgdiv.style.display="";

        if (obj.value != "")
        {
            GM_xmlhttpRequest({
                method: "GET",
                timeout: 3000,
                url: obj.value,
                onload: function(response){
                    console.log("请求成功");
                    //console.log(response.responseText);
                    // let dt=document.implementation.createDocumentType("html", "-//W3C//DTD HTML 4.01 Transitional//EN", "http://www.w3.org/TR/html4/loose.dtd");
                    // let doc = document.implementation.createDocument(null, null, dt);
                    let html = document.createElement('html');
                    html.innerHTML = response.responseText.replace(/^[\s]*/mg, "").replace(/\n(<a)/mg, "$1");
                    let bookInfo={};
                    // 标题
                    bookInfo.title = html.querySelector('#wrapper h1 span').innerText;
                    let elDivArticle = html.querySelector('#content .article');
                    // 封面
                    bookInfo.coverPicUrl = elDivArticle.querySelector('#mainpic a').href;
                    // console.log(bookInfo.coverPicUrl);

                    // info块
                    let infoBlockText = elDivArticle.querySelector('#info').innerText.trimEnd();
                    // console.log(elDivArticle.querySelector('#info'));
                    // console.log(infoBlockText);
                    let infoBlockItems = infoBlockText
                    .split('\n')
                    .map((i) => {
                        let [key, value] = i.split(':');
                        if (key != undefined)
                        {
                            key = key.trim();
                        }
                        if (value != undefined)
                        {
                            value = value.trim();
                        }
                        return [key, value];
                    });
                    let infoBlock = Object.fromEntries(infoBlockItems);
                    bookInfo.infoBlockText = infoBlockText;
                    bookInfo.infoBlockItems = infoBlockItems;
                    bookInfo.infoBlock = infoBlock;
                    //console.log(bookInfo.infoBlock);
                    //简介
                    let elDivRelatedInfo = elDivArticle.querySelector('.related_info');
                    // console.log(elDivRelatedInfo);
                    for (let elH2 of elDivRelatedInfo.querySelectorAll('h2')) {
                        let getText = (el) => {
                            let elDivIntro = el.nextElementSibling.querySelector('.all .intro');
                            if (!elDivIntro) {
                                elDivIntro = el.nextElementSibling.querySelector('.intro');
                            }
                            return Array.from(elDivIntro.querySelectorAll('p'))
                                .map(i => i.innerText)
                                .join('\n\n');
                        };
                        if (elH2.innerText.startsWith('\n内容')) {
                            bookInfo.contentIntro = getText(elH2);
                        }
                        if (elH2.innerText.startsWith('作者简介')) {
                            bookInfo.authorIntro = getText(elH2);
                        }
                    }

                    let uploadBookCoverPic = async (site) => {
                        if (!bookInfo.coverPicBlob) {
                            console.log(`[DEBUG] 下载封面图片 ${bookInfo.coverPicUrl}`);
                            msgspan.innerText = "正在处理,下载封面中...";
                            bookInfo.coverPicBlob = await getBlobFromUrl(bookInfo.coverPicUrl,site);
                            console.log(`[DEBUG] 封面图片下载成功`);
                        }
                        if (!bookInfo.newCoverPicUrl) {
                            console.log(`[DEBUG] 上传封面图片到${site}`);
                            msgspan.innerText = "正在处理,上传封面到图床...";
                            let newPicUrl = await uploadCoverPic(bookInfo.coverPicBlob,site);
                            // let newPicUrl = uploadCoverPic(bookInfo.coverPicBlob,site);
                            console.log('[DEBUG] 上传结果', newPicUrl);
                            bookInfo.newCoverPicUrl = newPicUrl;
                            if (!newPicUrl)
                            {
                                msgspan.innerText = '上传到图床失败!';
                            }
                        }
                        fillForm(bookInfo);
                    }

                    //上传到图床
                    let site=sel.options[sel.selectedIndex].value;
                    if (site == "ImgBBu")
                    {
                        if (ImgbbApikey.length != 32)
                        {
                            msgspan.innerText = "ImgBB未申请Apikey,申请后填写到脚本上";
                            return false;
                        }
                    }
                    else if (site == "ImgURL")
                    {
                        if (ImgurlUid.length != 32 || ImgurlToken.length != 32)
                        {
                            msgspan.innerText = "ImgURL未申请Apikey,申请后填写到脚本上";
                            return false;
                        }
                    }
                    uploadBookCoverPic(site);

                    let fillForm = (bookInfo) => {
                        // console.log(bookInfo.contentIntro);
                        // 标题(完整书名)
                        if (bookInfo.title) {
                            let fullname;
                            if (bookInfo.infoBlock['副标题']) {
                                fullname = `${bookInfo.title}:${bookInfo.infoBlock['副标题']}`;
                            } else {
                                fullname = bookInfo.title;
                            }
                            let fillText = document.querySelector('#name');
                            fillText.value = fullname;
                        }
                        // 副标题
                        if (bookInfo.infoBlock['作者']) {
                            let items = [];
                            let fields = ['作者', '译者', '出版社', '出版年'];
                            for (let field of fields) {
                                if (bookInfo.infoBlock[field]) {
                                    items.push(`${field}: ${bookInfo.infoBlock[field]}`);
                                }
                            }
                            let fillText = document.querySelector('#compose > table > tbody > tr:nth-child(4) > td.rowfollow > input[type=text]');
                            fillText.value = items.join(' | ');
                        }
                        //拼接简介部分
                        let desc = [];
                        // 封面
                        if (bookInfo.coverPicUrl) {
                            // console.log('new',bookInfo.newCoverPicUrl);
                            // console.log('old',bookInfo.coverPicUrl);
                            let coverPicUrl = bookInfo.newCoverPicUrl || bookInfo.coverPicUrl;
                            desc.push(...[
                                `[img]${coverPicUrl}[/img]`,
                                '\n\n',
                            ]);
                        }
                        // info块
                        if (bookInfo.infoBlockText) {
                            for (let [field, value] of bookInfo.infoBlockItems) {
                                if (Array.from(field).every(isCJK)) {
                                    if (field.length === 1) {
                                        let c1 = field;
                                        field = `◎${c1}   `;
                                    }
                                    else if (field.length === 2) {
                                        let [c1, c2] = field;
                                        field = `◎${c1}  ${c2}`;
                                    } else if (field.length === 3) {
                                        let [c1, c2, c3] = field;
                                        field = `◎${c1}  ${c2}  ${c3}`;
                                    } else {
                                        field = '◎' + field;
                                    }
                                } else if (field === 'ISBN') {
                                    field = '◎ISBN     ';
                                } else {
                                    field = '◎' + field;
                                }
                                if (value != undefined)
                                {
                                    desc.push(`${field} ${value}\n`);
                                }
                            }
                            desc.push('\n');
                        }
                        // 作者简介
                        if (bookInfo.contentIntro) {
                            desc.push(...[
                                `[b][size=4]内容简介[/size][/b]\n\n`,
                                bookInfo.contentIntro,
                                '\n\n\n',
                            ]);
                        }

                        // 作者简介
                        if (bookInfo.authorIntro) {
                            desc.push(...[
                                `[b][size=4]作者简介[/size][/b]\n\n`,
                                bookInfo.authorIntro,
                                '\n\n\n',
                            ]);
                        }

                        // 豆瓣链接
                        let bookUrl = obj.value;
                        // console.log(bookUrl);
                        desc.push(...[
                            `[img]https://i.loli.net/2021/10/25/TdO1JRobApl2C6Y.png[/img]\n\n`,
                            `[size=5][url=${bookUrl}]${bookUrl}[/url][/size]\n`,
                        ]);
                        let fillText = document.querySelector('#descr');
                        fillText.value = desc.join("");
                        //完成后提示
                        if (bookInfo.newCoverPicUrl)
                        {
                            msgspan.innerText = "操作完成。";
                            msgdiv.style.backgroundColor = "green";
                        }
                    }
                },
                onerror: function(response){
                    console.log("请求失败");
                    msgspan.innerText="读取豆瓣数据失败,请重试";
                },
                ontimeout: function() {
                    console.log("请求超时");
                    msgspan.innerText="读取豆瓣数据超时,请重试";
                }
            });
        }
        else
        {
            alert("豆瓣书籍url不能为空");
        }
    }

    // Your code here...
    // let obj=document.querySelector('#compose > table > tbody > tr:nth-child(4) > td.rowfollow > input[type=text]');
    // obj.value="isok";
    function CrElem(action)
    {
        let obj=document.querySelector('#compose > table > tbody > tr:nth-child(1) > td');
        let n1=document.createElement("p");
        let n2=document.createElement("span");
        n2.innerText = "豆瓣URL:";

        let inp1=document.createElement("input");
        inp1.name="input01";
        inp1.id="input01";
        inp1.size="60";
        inp1.type="text";
        inp1.value='https://book.douban.com/subject/20632628/';

        let sel=document.createElement("select");
        let opt1 = document.createElement("option");
        let opt2 = document.createElement("option");
        let opt0 = document.createElement("option");
        sel.style = "margin-left:5px;margin-right:5px;";
        sel.id = "select01";
        opt0.text="pstorage";
        opt0.value="pstorage";
        sel.add(opt0);
        opt1.text = "ImgBB";
        opt1.value = "ImgBB";
        sel.add(opt1);
        opt2.text = "ImgURL";
        opt2.value = "ImgURL";
        sel.add(opt2);


        let but1=document.createElement("input");
        but1.name="button01";
        but1.id="button01";
        but1.type="button";
        but1.value="提交";
        but1.onclick=action;
        //提醒信息
        let span = document.createElement('span');
        span.innerText = "正在处理,请稍候...";
        span.id="span01";
        let div = document.createElement('div');
        div.id="div01";
        div.style.cssText = 'background-color:red; padding-top: 2px;padding-bottom: 4px;display:none;';
        div.appendChild(span);

        obj.appendChild(n1);
        obj.appendChild(n2);
        obj.appendChild(inp1);
        obj.appendChild(sel);
        obj.appendChild(but1);
        obj.appendChild(div);
    }
    CrElem(getBookInfo);
})();