您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automatically upload image to Bahamut when you paste images in forum editor.
- // ==UserScript==
- // @name Clipboard image upload patch in Bahamut forum
- // @name:zh-TW 巴哈姆特論壇區剪貼簿圖片上傳補丁
- // @namespace https://jtdjdu6868.com/
- // @version 1.2
- // @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*
- // @match https://forum.gamer.com.tw/Co.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 editor = this;
- 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
- if(editor.isContentEditable)
- {
- // event from RTF or source code
- if(!bahaRte.isPlainText)
- {
- // RTF
- bahaRte.doc.execCommand("insertImage", false, url);
- Forum.Editor.detectThumbnail();
- }
- }
- else if(editor.id === "source")
- {
- // source code in post1.php editor
- if(bahaRte.isPlainText)
- {
- document.execCommand("insertText", false, `[img=${url}]`);
- Forum.Editor.detectThumbnail();
- }
- }
- else if(editor.tagName === "TEXTAREA" || editor.tagName === "INPUT" && editor.type === "text")
- {
- // event from comment or some unknown input text
- // insertText supports native undo, but baha offcial insert uses set content
- // document.execCommand("insertText", false, url);
- const selStart = editor.selectionStart,
- selEnd = editor.selectionEnd;
- const before = editor.value.substring(0, selStart),
- after = editor.value.substring(selEnd);
- editor.value = before + url + after;
- editor.focus();
- editor.selectionStart = selStart;
- editor.selectionEnd = selStart + url.length;
- }
- else
- {
- console.log("editor unknown");
- }
- }).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);
- document.querySelectorAll(".reply-input textarea").forEach((canEdit) => canEdit.addEventListener("paste", pasteHandler));
- });
- })();