编程猫发帖助手

编程猫论坛发帖辅助工具,包含防屏蔽、MarkDown、HTML、帖子更新、帖子协作等功能

// ==UserScript==
// @name        编程猫发帖助手
// @namespace   https://shequ.codemao.cn/user/15753247
// @match       *://shequ.codemao.cn/community*
// @grant       none
// @icon        https://shequ.codemao.cn/favicon.ico
// @version     0.1.0-2023.08.06
// @author      smyluke
// @license     MIT
// @description 编程猫论坛发帖辅助工具,包含防屏蔽、MarkDown、HTML、帖子更新、帖子协作等功能
// @require     https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js
// ==/UserScript==
'use strict';

const SERVER = 'https://smyluke.pythonanywhere.com',
    HOST = 'smyluke.pythonanywhere.com',
    BOARD_DATA = {
        "热门活动": 17,
        "积木编程乐园": 2,
        "工作室&师徒": 10,
        "你问我答": 5,
        "神奇代码岛": 3,
        "图书馆": 6,
        "CoCo应用创作": 27,
        "Python乐园": 11,
        "源码精灵": 26,
        "NOC编程猫比赛": 13,
        "灌水池塘": 7,
        "通天塔": 4,
        "训练师小课堂": 28
    },
    GET_FORUM_DATA = 'getForumData',
    SET_DATA = 'setData',
    version = 'v0.1.0-2023.08.06';

setTimeout(() => {
    try {
        const optionsDiv = document.querySelector('.r-community-c-forum_sender--bottom_options'),
            forumEditDiv = optionsDiv.parentNode.children[2],
            forumTypeDiv = document.createElement('div'),
            sendButton = document.createElement('a'),
            saveButton = document.createElement('a'),
            manageButton = document.createElement('a'),
            tokenInput = document.createElement('input'),
            idInput = document.createElement('input'),
            space = document.createElement('span'),
            forumTypeSelectButton_richText = document.createElement('div'),
            forumTypeSelectButton_markDown = document.createElement('div'),
            forumTypeSelectButton_HTML = document.createElement('div'),
            markDownEdit = document.createElement('iframe'),
            HTMLEdit = document.createElement('iframe'),
            css = document.createElement('style'),
            help = document.createElement('div'),
            helpShowMoreButton = document.createElement('a'),
            manageBoard = document.createElement('div'),
            manager = new ForumManager(localStorage, manageBoard);
        let helpShowMore = true;

        globalThis.CodemaoForumHelper_forumManager = manager;

        optionsDiv.innerHTML = '';

        tokenInput.classList.add('infoInput');
        tokenInput.placeholder = '帖子token';
        optionsDiv.appendChild(tokenInput);
        space.innerHTML = ' '.repeat(20);
        optionsDiv.appendChild(space);
        idInput.classList.add('infoInput');
        idInput.placeholder = '帖子id';
        optionsDiv.appendChild(idInput);

        optionsDiv.appendChild(document.createElement('br'));

        sendButton.innerText = '发布';
        saveButton.innerText = '保存';
        manageButton.innerText = '管理';
        sendButton.classList.add('r-community-c-forum_sender--option');
        saveButton.classList.add('r-community-c-forum_sender--option');
        manageButton.classList.add('r-community-c-forum_sender--option');
        optionsDiv.appendChild(sendButton);
        optionsDiv.appendChild(saveButton);
        optionsDiv.appendChild(manageButton);

        help.style.marginLeft = help.style.marginRight = '50px';
        helpShowMoreButton.style.color = '#5AD9AA';
        helpShowMoreButton.style.fontWeight = 'bold';
        helpShowMoreButton.onclick = () => {
            if (helpShowMore) {
                help.innerHTML = `当前版本:${version}
<br>
注意事项:
<br>
1.MarkDown/HTML类型帖子完全使用Editor.md的语法,支持流程图、表格、目录、TeX等……
<br>
`;
                helpShowMoreButton.innerText = '展开 ∨';
                help.appendChild(helpShowMoreButton);
            } else {
                help.innerHTML = `当前版本:${version}
<br>
注意事项:
<br>
1.MarkDown/HTML类型帖子完全使用Editor.md的语法,支持流程图、表格、目录、TeX等,具体语法参考<a href="http://editor.md.ipandao.com/" style="color: #2cc9ff" target="_blank">这里</a>;
<br>
2.MarkDown/HTML中的表情可能会无法加载;
<br>
3.帖子token自动随机生成,相当于是帖子的密码,帖子的编辑不限账号,只需要有token和id就可以;
<br>
4.插件自带帖子管理器,会自动记录使用过的token和id;
<br>
5.请不要在帖子中进行xss注入或发布违规内容,违者会对帖子进行删除,情节严重或多次违规将封禁ip;
<br>
6.发布帖子时若帖子未创建,会自动进行创建;
<br>
7.开启编创协MarkDown编辑器等其它插件可能会产生不兼容等情况,如遇到问题请先尝试关闭除本插件外的所有插件。
<br>
8.开启AdGuard等防广告扩展可能会对MarkDown/HTML的部分图标进行屏蔽。
<br>
`;
                helpShowMoreButton.innerText = '\n收起 ∧';
                help.appendChild(helpShowMoreButton);
            }
            helpShowMore = !helpShowMore;
        }
        helpShowMoreButton.click();
        optionsDiv.parentNode.appendChild(help);

        forumTypeDiv.classList.add('r-community-c-forum_sender--type_select');
        forumEditDiv.insertBefore(forumTypeDiv, forumEditDiv.children[1]);
        forumTypeSelectButton_richText.innerText = '富文本';
        forumTypeSelectButton_markDown.innerText = 'MarkDown/HTML';
        forumTypeSelectButton_HTML.innerText = 'HTML';
        forumTypeDiv.appendChild(forumTypeSelectButton_richText);
        forumTypeDiv.appendChild(forumTypeSelectButton_markDown);
        forumTypeDiv.appendChild(forumTypeSelectButton_HTML);
        forumTypeSelectButton_richText.style.color = 'red';
        forumTypeSelectButton_richText.style.borderColor = 'red';

        markDownEdit.src = `${SERVER}/static/MDEdit.html`;
        markDownEdit.style.display = 'none';
        markDownEdit.style.height = '600px';
        markDownEdit.style.width = '100%';
        markDownEdit.id = 'markDownEdit';
        document.querySelector(".r-community-c-forum_sender--container > div:nth-child(3)").appendChild(markDownEdit);

        HTMLEdit.src = `${SERVER}/static/HTMLEdit.html`;
        HTMLEdit.style.display = 'none';
        HTMLEdit.style.height = '600px';
        HTMLEdit.style.width = '100%';
        HTMLEdit.id = 'HTMLEdit';
        document.querySelector(".r-community-c-forum_sender--container > div:nth-child(3)").appendChild(HTMLEdit);

        document.querySelector(".c-model_box--content_wrap > div").appendChild(manageBoard)
        manager.elementInit();

        forumTypeSelectButton_richText.onclick = () => {
            document.querySelector(".r-community-c-forum_sender--container").style.width = '856px';
            forumTypeSelectButton_markDown.style.color = 'black';
            forumTypeSelectButton_markDown.style.borderColor = 'black';
            forumTypeSelectButton_HTML.style.color = 'black';
            forumTypeSelectButton_HTML.style.borderColor = 'black';
            forumTypeSelectButton_richText.style.color = 'red';
            forumTypeSelectButton_richText.style.borderColor = 'red';
            document.querySelector(".r-community-c-forum_sender--container > div:nth-child(3)").children[0].style.display = 'block';
            document.querySelector(".r-community-c-forum_sender--container > div:nth-child(3)").children[1].style.display = 'none';
            document.querySelector(".r-community-c-forum_sender--container > div:nth-child(3)").children[2].style.display = 'none';
        };

        forumTypeSelectButton_markDown.onclick = () => {
            document.querySelector(".r-community-c-forum_sender--container").style.width = 'auto';
            forumTypeSelectButton_richText.style.color = 'black';
            forumTypeSelectButton_richText.style.borderColor = 'black';
            forumTypeSelectButton_HTML.style.color = 'black';
            forumTypeSelectButton_HTML.style.borderColor = 'black';
            forumTypeSelectButton_markDown.style.color = 'red';
            forumTypeSelectButton_markDown.style.borderColor = 'red';
            document.querySelector(".r-community-c-forum_sender--container > div:nth-child(3)").children[1].style.display = 'block';
            document.querySelector(".r-community-c-forum_sender--container > div:nth-child(3)").children[0].style.display = 'none';
            document.querySelector(".r-community-c-forum_sender--container > div:nth-child(3)").children[2].style.display = 'none';
        };

        forumTypeSelectButton_HTML.onclick = () => {
            document.querySelector(".r-community-c-forum_sender--container").style.width = 'auto';
            forumTypeSelectButton_richText.style.color = 'black';
            forumTypeSelectButton_richText.style.borderColor = 'black';
            forumTypeSelectButton_markDown.style.color = 'black';
            forumTypeSelectButton_markDown.style.borderColor = 'black';
            forumTypeSelectButton_HTML.style.color = 'red';
            forumTypeSelectButton_HTML.style.borderColor = 'red';
            document.querySelector(".r-community-c-forum_sender--container > div:nth-child(3)").children[2].style.display = 'block';
            document.querySelector(".r-community-c-forum_sender--container > div:nth-child(3)").children[0].style.display = 'none';
            document.querySelector(".r-community-c-forum_sender--container > div:nth-child(3)").children[1].style.display = 'none';
        };

        document.querySelector("div.r-community-c-forum_sender--container > div:nth-child(1) > input").placeholder = '【发帖关键字】请输入标题(50字符以内)';

        sendButton.onclick = async () => {
            await sendForum(tokenInput, idInput, forumTypeSelectButton_richText, forumTypeSelectButton_markDown, markDownEdit, HTMLEdit);
        };
        saveButton.onclick = async () => {
            await saveForum(tokenInput, idInput, forumTypeSelectButton_richText, forumTypeSelectButton_markDown, markDownEdit, HTMLEdit);
        };
        manageButton.onclick = () => {
            manager.display();
        };

        css.innerHTML = `
.r-community-c-forum_sender--option {
    margin: 30px;
}

.r-community-c-forum_sender--type_select {
    width: 100%;
    height: 35px;
    margin-bottom: 20px;
    text-align: center;
}

.r-community-c-forum_sender--type_select:hover {
    font-size: 15px;
    cursor: pointer;
}

.r-community-c-forum_sender--type_select > div {
    display: inline-block;
    width: 32%;
    height: 100%;
    border-style: solid;
    border-color: hsla(0,0%,40%,.28);
    border-width: 1px;
    border-radius: 4px;
    margin: 5px;
    text-align: center;
    line-height: 35px;
    font-size: 15px;
}

.infoInput {
    padding: 5px;
    border-style: solid;
    border-width: 2px !important;
    border-color: rgba(128,128,128,0.5);
    width: 200px;
    align-self: center;
}

.infoInput:focus {
    border-color: black;
}

.forum:hover {
    background-color: rgba(252,194,51,0.5);
}

.forumSelect {
    background-color: rgba(252,194,51,0.8) !important;
}

.forumManagerButton {
    display: inline-block;
    text-align: center;
    width: 100px;
    padding: 5px 0;
    background: #fec433;
    border-radius: 4px;
    color: #fff;
    margin: 15px;
}

.forumManagerButton:hover {
    color: white;
    background: #ffbb10
}

.lockedButton {
    background-color: #cccc !important;
    color: #000 !important;
    cursor: default;
}
    `;
        document.head.appendChild(css);

        console.log('----- 编程猫发帖助手 运行成功 -----');
    } catch (e) {

    }
}, 3000);

class Forum {
    constructor(token, id, name, type, time) {
        this.token = token;
        this.id = id;
        this.name = name;
        this.type = type;
        this.time = time;
    }

    async updateInfo(name, type, token) {
        this.token = token;
        axios({
            method: 'POST',
            url: SERVER + '/forum/update/info',
            data: {
                id: this.id,
                token: this.token,
                title: name,
                type: type
            }
        }).then(res => {
            if (res.status === 201) {
                this.time = new Date().valueOf();
                this.name = name;
                this.type = type;
                CodemaoForumHelper_forumManager.save();
                return true;
            } else {
                err(res);
                return false;
            }
        });
    }

    get data() {
        return {
            token: this.token,
            id: this.id,
            name: this.name,
            type: this.type,
            time: this.time
        };
    }

    elementShow(parent) {
        const element = document.createElement('div');
        element.classList.add('forum');
        element.style.width = '100%';
        element.style.height = '10%';
        element.style.padding = '2%';
        element.style.borderStyle = 'solid';
        element.style.borderColor = 'rgba(0,0,0,0.45)';
        element.style.borderWidth = '1px';
        element.style.fontSize = '13px';
        element.style.fontWeight = 'bold';
        element.style.whiteSpace = 'pre';
        element.innerText = `${this.id}    ${this.name}\n${new Date(this.time).toLocaleString()}     ${['富文本', 'MarkDown/HTML', 'HTML'][this.type]}`;
        element.forum = this;
        parent.appendChild(element);
        return element;
    }
}

class ForumManager {
    constructor(storage, element) {
        this.storage = storage;
        this.element = element;
        this.forums = [];
        if (!storage.getItem('CodemaoForumHelperData')) storage.setItem('CodemaoForumHelperData', '[]');
        for (const forum of JSON.parse(storage.getItem('CodemaoForumHelperData'))) this.forums.push(new Forum(forum['token'], forum['id'], forum['name'], forum['type'], forum['time']));
    }

    elementInit() {
        this.element.style.display = 'none';
        this.element.style.width = '110%';
        this.element.style.height = '70%';
        this.element.style.borderRadius = '4px';
        this.element.style.position = 'absolute';
        this.element.style.top = '50%';
        this.element.style.left = '50%';
        this.element.style.transform = 'translate(-50%,-50%)';
        this.element.style.zIndex = '2';
        this.element.style.background = '#fff';
        this.element.style.boxShadow = '0 6px 28px 0 rgba(0,0,0,.12)'
        this.mask = document.createElement('div');
        this.mask.style.display = 'none';
        this.mask.style.position = 'absolute';
        this.mask.style.top = this.mask.style.bottom = this.mask.style.left = this.mask.style.right = '0';
        this.mask.style.background = 'rgba(0,0,0,0.3)';
        this.element.parentElement.appendChild(this.mask);
        this.closeButton = document.createElement('a');
        this.closeButton.style.position = 'absolute';
        this.closeButton.style.right = '20px';
        this.closeButton.style.top = '10px';
        this.closeButton.style.padding = '10px'
        this.element.appendChild(this.closeButton);
        this.closeIcon = document.createElement('i');
        this.closeIcon.style.background = 'url(https://cdn-community.codemao.cn/community_frontend/asset/bind_phone_close_9b02e.svg) no-repeat -5px -5px';
        this.closeIcon.style.width = this.closeIcon.style.height = '14px';
        this.closeIcon.style.display = 'inline-block';
        this.closeButton.appendChild(this.closeIcon);
        this.closeButton.close = this.close;
        this.closeButton.onclick = () => {
            this.close();
        };
        this.forumShowBox = document.createElement('div');
        this.forumShowBox.id = 'forumShowBox';
        this.forumShowBox.style.borderStyle = 'solid';
        this.forumShowBox.style.borderColor = 'rgba(0,0,0,0.45)';
        this.forumShowBox.style.borderWidth = '1px';
        this.forumShowBox.style.width = '40%';
        this.forumShowBox.style.height = '80%';
        this.forumShowBox.style.margin = '5%';
        this.forumShowBox.style.overflowY = 'auto';
        this.forumShowBox.style.display = 'inline-block';
        this.element.appendChild(this.forumShowBox);
        for (const forum of this.forums) forum.elementShow(this.forumShowBox).onclick = ({srcElement}) => {
            this.forumOnclick(srcElement);
        };
        this.selectedForum = null;
        this.optionsDiv = document.createElement('div');
        this.optionsDiv.style.width = '45%'
        this.optionsDiv.style.height = '100%';
        this.optionsDiv.style.position = 'absolute';
        this.optionsDiv.style.top = '50px';
        this.optionsDiv.style.display = 'inline-block';
        this.element.appendChild(this.optionsDiv)
        this.tokenInput = document.createElement('input');
        this.tokenInput.classList.add('infoInput');
        this.tokenInput.placeholder = '帖子token';
        this.optionsDiv.appendChild(this.tokenInput);
        this.space = document.createElement('span');
        this.space.innerHTML = '&nbsp;'.repeat(5);
        this.optionsDiv.appendChild(this.space);
        this.idInput = document.createElement('input');
        this.idInput.classList.add('infoInput');
        this.idInput.placeholder = '帖子id';
        this.optionsDiv.appendChild(this.idInput);
        this.newForumButton = document.createElement('a');
        this.openButton = document.createElement('a');
        this.deleteButton = document.createElement('a');
        this.newForumButton.innerText = '添加';
        this.openButton.innerText = '打开';
        this.deleteButton.innerText = '删除';
        this.newForumButton.classList.add('forumManagerButton');
        this.openButton.classList.add('forumManagerButton');
        this.deleteButton.classList.add('forumManagerButton');
        this.openButton.classList.add('lockedButton');
        this.deleteButton.classList.add('lockedButton');
        this.newForumButton.onclick = () => CodemaoForumHelper_forumManager.newForumButtonOnclick();
        this.openButton.onclick = () => CodemaoForumHelper_forumManager.openButtonOnclick();
        this.deleteButton.onclick = () => CodemaoForumHelper_forumManager.deleteButtonOnclick();
        this.optionsDiv.appendChild(this.newForumButton);
        this.optionsDiv.appendChild(this.openButton);
        this.optionsDiv.appendChild(this.deleteButton);
    }

    forumOnclick(element) {
        this.selectedForum && this.selectedForum.classList.remove('forumSelect');
        this.selectedForum = element;
        element.classList.add('forumSelect');
        this.openButton.classList.remove('lockedButton');
        this.deleteButton.classList.remove('lockedButton');
        this.tokenInput.value = element.forum.token;
        this.idInput.value = element.forum.id;
    }

    display() {
        this.element.style.display = 'inline-block';
        this.mask.style.display = 'inline-block';
    }

    close() {
        this.element.style.display = 'none';
        this.mask.style.display = 'none';
    }

    appendForum(token, id, name, type) {
        for (const f of this.forums) if (f.id === id) return [f, false];
        const time = new Date().valueOf(),
            forum = new Forum(token, id, name, type, time);
        this.forums.push(forum);
        forum.elementShow(this.forumShowBox).onclick = ({srcElement}) => {
            this.forumOnclick(srcElement);
        };
        this.save();
        return [forum, true];
    }

    save() {
        this.storage.setItem('CodemaoForumHelperData', JSON.stringify(this.data));
    }

    async newForumButtonOnclick() {
        if (this.tokenInput.value && this.idInput.value) {
            const res = await getForumInfo(this.idInput.value);
            if (res.status === 200) {
                const result = this.appendForum(this.tokenInput.value, this.idInput.value, res.data[1], res.data[2]);
                if (!result[1]) alert('帖子已存在!');
            } else err(res);
        } else alert('请输入token和id!');
    }

    async openButtonOnclick() {
        if (this.selectedForum) {
            const forum = this.selectedForum.forum;
            document.querySelector("div.r-community-c-forum_sender--container > div:nth-child(1) > input").value = forum.name;
            document.querySelector(".r-community-c-forum_sender--type_select").children[forum.type].click();
            document.querySelector(".r-community-c-forum_sender--bottom_options > input:nth-child(1)").value = forum.token;
            document.querySelector(".r-community-c-forum_sender--bottom_options > input:nth-child(3)").value = forum.id;
            this.close();
            if (forum.type === 0) {
                const res = await getForumData(forum.id);
                if (res.status === 200) {
                    document.querySelector("#react-tinymce-0_ifr").contentDocument.body.innerHTML = res.data;
                } else err(res);
            } else if (forum.type === 1) {
                const res = await waitMessageResponse(document.querySelector('#markDownEdit'), SET_DATA + forum.id);
                if (res.startsWith('error: ')) alert(res);
            } else {
                const res = await waitMessageResponse(document.querySelector('#HTMLEdit'), SET_DATA + forum.id);
                if (res.startsWith('error: ')) alert(res);
            }
        }
    }

    deleteButtonOnclick() {
        if (this.selectedForum) {
            const forum = this.selectedForum;
            forum.remove();
            this.forums = this.forums.filter(f => f !== forum.forum);
            this.save();
            this.selectedForum = null;
            this.openButton.classList.add('lockedButton');
            this.deleteButton.classList.add('lockedButton');
        }
    }

    get data() {
        return this.forums.map(forum => forum.data);
    }
}

function err(res) {
    alert(`错误\n状态码:${res.status}\n错误信息:${res.data}`);
}

function suc(res) {
    alert(`操作成功:${res.data}`);
}

async function waitMessageResponse(iframe, text) {
    return new Promise(resolve => {
        const res = ({data}) => {
            resolve(data);
            removeEventListener('message', res);
        };
        addEventListener('message', res);
        iframe.contentWindow.postMessage(text, '*');
        setTimeout(() => removeEventListener('message', res), 5000);
    });
}

async function saveForum(tokenInput, idInput, forumTypeSelectButton_richText, forumTypeSelectButton_markDown, markDownEdit, HTMLEdit) {
    let type,
        token = tokenInput.value,
        id = parseInt(idInput.value),
        name = document.querySelector("div.r-community-c-forum_sender--container > div:nth-child(1) > input").value,
        data;
    if (forumTypeSelectButton_richText.style.color === 'red') type = 0;
    else if (forumTypeSelectButton_markDown.style.color === 'red') type = 1;
    else type = 2;
    if (type === 0) data = document.querySelector("#react-tinymce-0_ifr").contentDocument.body.innerHTML;
    else if (type === 1) {
        data = await waitMessageResponse(markDownEdit, GET_FORUM_DATA);
    } else {
        data = await waitMessageResponse(HTMLEdit, GET_FORUM_DATA);
    }
    if (token) {
        axios({
            method: 'POST',
            url: SERVER + '/forum/update/data',
            data: {
                id: id,
                token: token,
                data: data
            }
        }).then(async res => {
            suc(res);
            await CodemaoForumHelper_forumManager.appendForum(token, id, name, type)[0].updateInfo(name, type, token);
        }).catch(err);
    } else {
        axios({
            method: 'POST',
            url: SERVER + '/forum/create',
            data: {
                title: name,
                type: type,
                data: data
            }
        }).then(async res => {
            alert('操作成功:创建成功(success-0003)');
            [id, token] = res.data.split(' ');
            tokenInput.value = token;
            idInput.value = id;
            await CodemaoForumHelper_forumManager.appendForum(token, parseInt(id), name, type, token);
        }).catch(err);
    }
}

async function sendForum(tokenInput, idInput, forumTypeSelectButton_richText, forumTypeSelectButton_markDown, markDownEdit, HTMLEdit) {
    let type,
        token = tokenInput.value,
        id = parseInt(idInput.value),
        name = document.querySelector("div.r-community-c-forum_sender--container > div:nth-child(1) > input").value,
        data;
    if (forumTypeSelectButton_richText.style.color === 'red') type = 0;
    else if (forumTypeSelectButton_markDown.style.color === 'red') type = 1;
    else type = 2;
    if (type === 0) data = document.querySelector("#react-tinymce-0_ifr").contentDocument.body.innerHTML;
    else if (type === 1) {
        data = await waitMessageResponse(markDownEdit, GET_FORUM_DATA);
    } else {
        data = await waitMessageResponse(HTMLEdit, GET_FORUM_DATA);
    }
    if (token) {
        axios({
            method: 'POST',
            url: SERVER + '/forum/update/data',
            data: {
                id: id,
                token: token,
                data: data
            }
        }).then(async () => {
            await CodemaoForumHelper_forumManager.appendForum(token, id, name, type)[0].updateInfo(name, type);
            if (getBoardId()) {
                const response = await sendForumApi(name, id, getBoardId());
                if (response.status === 201) {
                    open('https://shequ.codemao.cn/community/' + response.data.id);
                } else err(response);
            } else alert('请选择板块!');
        }).catch(err);
    } else {
        axios({
            method: 'POST',
            url: SERVER + '/forum/create',
            data: {
                title: name,
                type: type,
                data: data
            }
        }).then(async res => {
            [id, token] = res.data.split(' ');
            tokenInput.value = token;
            idInput.value = id;
            await CodemaoForumHelper_forumManager.appendForum(token, parseInt(id), name, type);
            if (getBoardId()) {
                const response = await sendForumApi(name, id, getBoardId());
                if (response.status === 201) {
                    open('https://shequ.codemao.cn/community/' + response.data.id);
                } else err(response);
            } else alert('请选择板块!');
        }).catch(err);
    }
}

async function sendForumApi(title, id, boardId) {
    while (title.length < 5) title += '\u200B';
    return new Promise(resolve => axios({
        method: 'POST',
        url: 'https://api.codemao.cn/web/forums/boards/' + boardId + '/posts',
        data: {
            title: title,
            content: '<iframe src="//' + HOST + '/forum/' + id + '" style="width: 1000px; height: 1000px" allowfullscreen="true"></iframe>'
        },
        withCredentials: true
    }).then(resolve).catch(resolve));
}

function getBoardId() {
    const board = document.querySelector('.r-community-c-forum_sender--active');
    if (board === null) return false;
    return BOARD_DATA[board.innerText];
}

async function getForumInfo(id) {
    return new Promise(resolve => axios({
        method: 'GET',
        url: SERVER + '/forum/info/' + id
    }).then(resolve).catch(resolve));
}

async function getForumData(id) {
    return new Promise(resolve => axios({
        method: 'GET',
        url: SERVER + '/forum/data/' + id
    }).then(resolve).catch(resolve));
}

globalThis._axios = axios;
axios = (arg) => {
    arg.validateStatus = () => true;
    return _axios(arg);
}

for (const key of ['forum_sender_board', 'forum_sender_content', 'forum_sender_title']) {
    localStorage.removeItem(key);
}