Clipboard image upload patch in Bahamut forum

Automatically upload image to Bahamut when you paste images in forum editor.

目前为 2024-02-07 提交的版本。查看 最新版本

// ==UserScript==
// @name         Clipboard image upload patch in Bahamut forum
// @name:zh-TW   巴哈姆特論壇區剪貼簿圖片上傳補丁
// @namespace    https://jtdjdu6868.com/
// @version      1.1
// @description        Automatically upload image to Bahamut when you paste images in forum editor.
// @description:zh-TW  在編輯討論區文章時貼上支援的圖片格式,自動上傳至巴哈圖庫
// @author       jtdjdu6868
// @match        https://forum.gamer.com.tw/post1.php*
// @match        https://forum.gamer.com.tw/C.php*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=gamer.com.tw
// @grant        none
// @run-at       document-idle
// @license      BY
// ==/UserScript==

(function() {
    'use strict';
    function pasteHandler(e)
    {
        const items = (e.clipboardData || e.originalEvent.clipboardData).items;
        for(let i = 0; i < items.length; ++i)
        {
            if("image/gif,image/jpeg,image/png,image/webp".split(",").includes(items[i].type))
            {
                e.preventDefault();
                console.log("paste image");
                toastr.info("上傳中...");

                const blob = items[i].getAsFile();
                const bsn = +new URL(window.location.href).searchParams.get("bsn");

                // get upload token (piccToken)
                fetch(`https://api.gamer.com.tw/forum/v1/image_token.php?bsn=${bsn}`, {
                    credentials: "include",
                }).then((res) => res.json()).then((res) => {
                    if(res.code !== void 0 && res.message || res.error)
                    {
                        throw res.message || res.error.message;
                    }
                    const piccToken = res.token || res.data.token;
                    return piccToken;
                }).then((piccToken) => {
                    // pack payload
                    const payload = new FormData();
                    payload.append("token", piccToken);
                    payload.append("dzfile", blob);

                    return payload;
                }).then((payload) => {

                    // upload payoad with piccToken
                    // use xhr because server returns a readablestream, xhr is more simpler
                    return new Promise((resolve, reject) => {
                        const xhr = new XMLHttpRequest();
                        xhr.open("POST", "https://picc.gamer.com.tw/ajax/truth_image_upload.php", true);
                        xhr.withCredentials = true;
                        xhr.onload = (e) => {
                            // return image token
                            resolve(e.target.responseText);
                        };

                        const headers = {
                            "Accept": "application/json",
                            "Cache-Control": "no-cache",
                            "X-Requested-With": "XMLHttpRequest"
                        };
                        Object.keys(headers).forEach((key) => xhr.setRequestHeader(key, headers[key]));

                        xhr.send(payload);
                    });
                }).then((res) => JSON.parse(res)).then((res) => {
                    if(res.token === void 0)
                    {
                        throw res;
                    }

                    // get image url by token
                    return fetch(`https://api.gamer.com.tw/forum/v1/image_upload.php?token=${res.token}&bsn=${bsn}`, {
                        credentials: "include",
                    });
                }).then((res) => res.json()).then((res) => {
                    // receive url
                    if(res.code !== void 0 && res.message || res.error)
                    {
                        throw res.message || res.error.message;
                    }
                    let urlList = res.data ? res.data.list : res;

                    // extract first url
                    return urlList[0];
                }).then((url) => {
                    toastr.clear();
                    toastr.success("上傳成功");
                    // insert to RTF or source
                    if(bahaRte.isPlainText)
                    {
                        // source
                        document.execCommand("insertText", false, `[img=${url}]`);
                    }
                    else
                    {
                        // RTF
                        bahaRte.doc.execCommand("insertImage", false, url);
                    }
                    Forum.Editor.detectThumbnail();
                }).catch((err) => {
                    toastr.clear();
                    toastr.error(err);
                });
            }
            else if(items[i].type.indexOf('image') === 0)
            {
                // unsupported image type
                toastr.warning("目前巴哈圖庫只支援png, jpg, gif, webp");
                e.preventDefault();
            }
        }
    };
    // bind event after bahaRte loaded
    jQuery(window).on('load', () => {
        bahaRte.doc.body.addEventListener("paste", pasteHandler);
        document.getElementById("source")?.addEventListener?.("paste", pasteHandler);
    });
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址