My Collection to CC98 QMD

同步CC98抽卡游戏的收藏至CC98签名档

// ==UserScript==
// @name         My Collection to CC98 QMD
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  同步CC98抽卡游戏的收藏至CC98签名档
// @author       Q&A
// @match        https://card.cc98.org/Home/Collection
// @match        https://www.cc98.org
// @icon         https://www.google.com/s2/favicons?sz=64&domain=cc98.org
// @require      https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.js
// @resource     toastrCSS https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.css
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_getResourceText
// @grant        GM_addStyle
// @grant        GM_xmlhttpRequest
// @license MIT

// ==/UserScript==
/* globals html2canvas, toastr */
(function() {
    'use strict';
    GM_addStyle(GM_getResourceText("toastrCSS"));
    let toastr_title = "My Collection to CC98 QMD";
    toastr.options.timeOut = 5000;
    toastr.options.extendedTimeOut = 5000;
    toastr.options.newestOnTop = false;
    toastr.options.progressBar = true;
    toastr.options.positionClass = "toast-top-center";

    // 从 www.cc98.org 的 localStorage 获取 accessToken
    if ("www.cc98.org" === location.host) {
        if(!GM_getValue("update_token", false)) return;
        let access_token = localStorage.getItem("accessToken");
        if(null !== access_token) {
            GM_setValue("access_token", access_token.slice(4));
            toastr.success("获取accessToken成功!",toastr_title);
            GM_setValue("update_token", false);
        } else {
            toastr.error("获取accessToken失败!",toastr_title);
        }
        return;
    }
    // 日期格式化字符串
    Date.prototype.format = function(fmt) {
        var o = {
            "M+" : this.getMonth()+1,
            "d+" : this.getDate(),
            "h+" : this.getHours(),
            "m+" : this.getMinutes(),
            "s+" : this.getSeconds(),
            "q+" : Math.floor((this.getMonth()+3)/3),
            "S"  : this.getMilliseconds()
        };
        if(/(y+)/.test(fmt)) {
            fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length));
        }
        for(var k in o) {
            if(new RegExp("("+ k +")").test(fmt)){
                fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
            }
        }
        return fmt;
    }
    // base64转文件
    function dataURLtoFile(base64Str, fileName) {
        var arr = base64Str.split(','),
            mime = arr[0].match(/:(.*?);/)[1], //base64解析出来的图片类型
            bstr = atob(arr[1]), //对base64串进行操作,去掉url头,并转换为byte   atob为window内置方法
            len = bstr.length,
            ab = new ArrayBuffer(len), //将ASCII码小于0的转换为大于0
            u8arr = new Uint8Array(ab); //
        while (len--) {
            u8arr[len] = bstr.charCodeAt(len)
        }
        // 创建新的 File 对象实例[utf-8内容,文件名称或者路径,[可选参数,type:文件中的内容mime类型]]
        return new File([u8arr], fileName, {
            type: mime
        })
    }

    // 添加按钮
    document.getElementsByClassName("alert alert-info")[0].innerHTML += "<a href=\"javascript:myCollection2CC98()\" class=\"alert-link\">单击这里</a>同步我的收藏至CC98签名档。"
    unsafeWindow.myCollection2CC98 = function() {
        console.log("My Collection to CC98 QMD!");
        let card_group = document.getElementsByClassName("card-group")[0];
        html2canvas(card_group).then(canvas => {
            // 生成图片
            var image = new Image();
            image.src = canvas.toDataURL("image/png");
            let image_file = dataURLtoFile(image.src, "card-group.png");
            // 获取accessToken
            let access_token = GM_getValue("access_token", "");
            if("" === access_token) {
                GM_setValue("update_token", true);
                toastr.error("【0/3】请<button onclick=\"window.open('https://www.cc98.org')\">点我打开cc98.org</button>获取accessToken!",toastr_title);
                return;
            }
            toastr.success("【1/3】已成功获取accessToken!(token: "+access_token.slice(0,5) + "……" + access_token.slice(-5)+")",toastr_title);
            // 上传文件至cc98服务器,获取图片URL
            var form = new FormData();
            form.append("files", image_file, "card-group.png");
            GM_xmlhttpRequest({
                method: "POST",
                url: "https://api.cc98.org/file",
                headers: {
                    Authorization: access_token
                },
                data: form,
                onload: function(res){
                    if(res.status === 200){
                        let img_url = JSON.parse(res.response)[0];
                        toastr.success("【2/3】已成功上传图片至98服务器!(URL: " + img_url +")",toastr_title);
                        // 更新签名档
                        GM_xmlhttpRequest({
                            method: "GET",
                            url: "https://api.cc98.org/me",
                            headers:  {
                                Authorization: access_token
                            },
                            onload: function(res){
                                if(res.status == 200) {
                                    let me = JSON.parse(res.response);
                                    let birthday = new Date(me.birthday);
                                    let update_me = {
                                        Birthday: birthday.format("yyyy-MM-dd"),
                                        DisplayTitleId: me.displatTitleId?me.displatTitleId:0,
                                        EmailAddress: me.emailAddress,
                                        Gender: me.gender,
                                        Introduction: me.introduction,
                                        QQ: me.qq,
                                        SignatureCode: "[img]" + img_url + "[/img]\n[right]Updated at " + new Date().format("yy-MM-dd hh:mm:ss")+" | Powered by [url=https://greasyfork.org/zh-CN/scripts/449683][b][u]My Collection to CC98 QMD[/u][/b][/url][/right]",
                                        birthdayDay: birthday.getDate(),
                                        birthdayMonth: birthday.getMonth()+1,
                                        birthdayYear: birthday.getFullYear(),
                                        userTitleIds: me.userTitleIds
                                    }
                                    GM_xmlhttpRequest({
                                        method: "PUT",
                                        url: "https://api.cc98.org/me",
                                        headers:  {
                                            Authorization: access_token,
                                            "Content-Type": "application/json"
                                        },
                                        data: JSON.stringify(update_me),
                                        onload: function(res) {
                                            if(res.status == 200) {
                                                toastr.success("【3/3】已成功更新个人资料,请<button onclick=\"window.open('https://www.cc98.org/usercenter')\">点我打开cc98.org</button>查看!",toastr_title)
                                            } else {
                                                console.log(res);
                                                toastr.error("【2/3】更新个人资料失败,请重试!",toastr_title);
                                            }
                                        }
                                    });
                                } else {
                                    console.log(res);
                                    toastr.error("【2/3】获取个人资料失败,请重试!",toastr_title);
                                }
                            }
                        });
                    }else{
                        console.log(res);
                        GM_setValue("update_token", true);
                        toastr.error("【1/3】上传失败,请<button onclick=\"window.open('https://www.cc98.org')\">点我打开cc98.org</button>重新获取accessToken!",toastr_title);
                    }
                },
                onerror : function(err){
                    console.log(err);
                }
            });
        });
    }
})();