Đăng Nhanh

Đăng truyện nhanh TTV với nhiều tính năng mới và tự động tách chương

As of 2025-03-06. See the latest version.

// ==UserScript==
// @name         Đăng Nhanh
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  Đăng truyện nhanh TTV với nhiều tính năng mới và tự động tách chương
// @author       HA
// @match        https://tangthuvien.net/dang-chuong/story/*
// @match        https://tangthuvien.net/danh-sach-chuong/story/*
// @grant        none
// @required     https://code.jquery.com/jquery-3.2.1.min.js
// @icon         https://tangthuvien.net/images/icon-favico.png
// @copyright 2021-2023, by HA
// @license AGPL-3.0-only
// @collaborator HA
// ==/UserScript==

var headerSign = "";
var footerSign = "";
var dăngnhanhTTV =  {
    YEAR_ALIVE: 2021,
    MAX_CHAPTER_POST: 10,
    CHAP_NUMBER: 1,
    CHAP_STT: 1,
    CHAP_SERIAL: 1,
    CHAP_NUMBER_ORIGINAL: 1,
    CHAP_STT_ORIGINAL: 1,
    CHAP_SERIAL_ORIGINAL: 1,
    addNewChapter: function () {
        var me = this;
        if ((me.CHAP_NUMBER + 1) <= me.MAX_CHAPTER_POST) {
            me.updateChapNumber(true);
            var chap_vol = parseInt(jQuery('.chap_vol').val());
            var chap_vol_name = jQuery('.chap_vol_name').val();
            var html =
                '<div data-gen="MK_GEN" id="COUNT_CHAP_' + me.CHAP_NUMBER + '_MK">' +
                '<div class="col-xs-12 form-group"></div>' +
                '<div class="form-group">' +
                '<label class="col-sm-2" for="chap_stt">STT</label>' +
                '<div class="col-sm-8">' +
                '<input class="form-control" required name="chap_stt[' + me.CHAP_NUMBER + ']" value="' + me.CHAP_STT +
                '" placeholder="Số thứ tự của chương" type="text"/>' +
                '</div>' +
                '</div>' +
                '<div class="form-group">' +
                '<label class="col-sm-2" for="chap_number">Chương thứ..</label>' +
                '<div class="col-sm-8">' +
                '<input value="' + me.CHAP_SERIAL + '" required class="form-control" name="chap_number[' + me.CHAP_NUMBER +
                ']" placeholder="Chương thứ.. (1,2,3..)" type="text"/>' +
                '</div>' +
                '</div>' +
                '<div class="form-group">' +
                '<label class="col-sm-2" for="chap_name">Quyển số</label>' +
                '<div class="col-sm-8">' +
                '<input class="form-control" name="vol[' + me.CHAP_NUMBER +
                ']" placeholder="Quyển số" type="number" value="' + chap_vol + '" required/>' +
                '</div>' +
                '</div>' +
                '<div class="form-group">' +
                '<label class="col-sm-2" for="chap_name">Tên quyển</label>' +
                '<div class="col-sm-8">' +
                '<input class="form-control chap_vol_name" name="vol_name[' + me.CHAP_NUMBER +
                ']" placeholder="Tên quyển" type="text" value="' + chap_vol_name + '" />' +
                '</div>' +
                '</div>' +
                '<div class="form-group">' +
                '<label class="col-sm-2" for="chap_name">Tên chương</label>' +
                '<div class="col-sm-8">' +
                '<input required class="form-control" name="chap_name[' + me.CHAP_NUMBER +
                ']" placeholder="Tên chương" type="text"/>' +
                '</div>' +
                '</div>' +
                '<div class="form-group">' +
                '<label class="col-sm-2" for="introduce">Nội dung</label>' +
                '<div class="col-sm-8">' +
                '<textarea maxlength="75000" style="color:#000;font-weight: 400;" required class="form-control" ' +
                'name="introduce[' + me.CHAP_NUMBER + ']" rows="20" placeholder="Nội dung" type="text"></textarea>' +
                '</div>' +
                '</div>' +
                '<div class="form-group">' +
                '<label class="col-sm-2" for="adv">Quảng cáo</label>' +
                '<div class="col-sm-8">' +
                '<textarea maxlength="1000" class="form-control" name="adv[' + me.CHAP_NUMBER +
                ']" placeholder="Quảng cáo" type="text"></textarea>' +
                '</div>' +
                '</div>' +
                '</div>';
            jQuery('#add-chap').before(html);
        }
        else {
            var chapterLeft = me.MAX_CHAPTER_POST - me.CHAP_NUMBER;
            chapterLeft = chapterLeft < 0 ? 0 : chapterLeft;
            alert('Bạn nên đăng tối đa ' + me.MAX_CHAPTER_POST + ' chương một lần, số chương đã tạo ' +
                me.CHAP_NUMBER + ' chương, bạn có thể đăng thêm ' + chapterLeft + ' chương nữa.');
        }
    },
    createListAddChapter: function (isSilent) {
        var me = this;
        var chapterAdd = 0;
        chapterAdd = parseInt(jQuery("#qpNumberOfChapter").val());
        if ((me.CHAP_NUMBER + chapterAdd) <= me.MAX_CHAPTER_POST) {
            for (var i = 0; i < chapterAdd; i++) {
                me.addNewChapter();
            }
            if (!isSilent) {
                alert('Đã tạo thêm ' + chapterAdd + ' chương, hãy copy và dán nội dung cần đăng.');
            }
        }
        else {
            alert('Bạn nên đăng tối đa ' + me.MAX_CHAPTER_POST + ' chương một lần, số chương đã tạo ' + me.CHAP_NUMBER + ' chương, bạn có thể đăng thêm ' + (me.MAX_CHAPTER_POST - me.CHAP_NUMBER) + ' chương nữa.');
        }
    },
    removeLastedPost: function () {
        var me = this;
        jQuery("#COUNT_CHAP_" + me.CHAP_NUMBER + "_MK").remove();
        me.updateChapNumber();
    },
    updateChapNumber: function (isAdd) {
        var me = this;
        try {
            if (isAdd) {
                var chap_stt = parseInt(jQuery('.chap_stt1').val());
                var chap_serial = parseInt(jQuery('.chap_serial').val());
                if (parseInt(jQuery('#chap_stt').val()) > chap_stt) {
                    chap_stt = parseInt(jQuery('#chap_stt').val());
                }
                if (parseInt(jQuery('#chap_serial').val()) > chap_serial) {
                    chap_serial = parseInt(jQuery('#chap_serial').val());
                }
                me.CHAP_STT = chap_stt;
                me.CHAP_SERIAL = chap_serial;
                me.CHAP_NUMBER++;
                me.CHAP_STT++;
                me.CHAP_SERIAL++;
            }
            else {
                if (me.CHAP_NUMBER > me.CHAP_NUMBER_ORIGINAL) {
                    me.CHAP_NUMBER--;
                }
                if (me.CHAP_STT > me.CHAP_STT_ORIGINAL) {
                    me.CHAP_STT--;
                }
                if (me.CHAP_SERIAL > me.CHAP_SERIAL_ORIGINAL) {
                    me.CHAP_SERIAL--;
                }
            }
            jQuery('#chap_number').val(me.CHAP_NUMBER);
            jQuery('#chap_stt').val(me.CHAP_STT);
            jQuery('#chap_serial').val(me.CHAP_SERIAL);
            jQuery('#countNumberPost').text(me.CHAP_NUMBER);
        }
        catch (e) {
            console.log("Lỗi: " + e);
        }
    },
    createEl: function (n) {
        return document.createElement(n);
    },
    addStyle: function (style) {
        var me = this;
        var s = me.createEl("style"),
            h = document.getElementById('HA');
        s.type = "text/css";
        s.appendChild(document.createTextNode(style));
        h.appendChild(s);
    },
    addCss: function () {
        var me = this;
        var s =
            '#HA { ' +
            'background-color: rgb(255, 255, 255) !important;' +
            'padding: 3px 15px;' +
            'color: black !important;' +
            'border-radius: 5px 0px 0px 5px;' +
            'margin-bottom: 15px;' +
            'position: fixed;' +
            'right: 10px;' +
            'top: 10px;' +
            'max-width: 400px;' +
            'z-index: 9999;' +
            'box-shadow: -2px 0 5px rgba(0,0,0,0.1);' +
            '}' +
            '#HA > .form-group > div {' +
            'font-size: 13px;' +
            'color: black !important;' +
            '}' +
            '#HA > p {' +
            'font-size: 13px;' +
            'color: black !important;' +
            'text-align: right;' +
            '}' +
            '#HA .HA-option {' +
            'padding: 5px;' +
            'border: 1px dashed #4CAF50;' +
            'border-radius: 5px;' +
            'margin-bottom: 32px;' +
            '}' +
            '#HA .HA-option-label {' +
            'width: 100%;' +
            'background-color: black;' +
            'padding: 10px;' +
            'border-radius: 5px 5px 0px 0px;' +
            'margin: 0;' +
            '}' +
            '#qpn {' +
            'max-height: 300px;' +
            'overflow-y: auto;' +
            'margin-top: 10px;' +
            'font-size: 12px;' +
            '}' +
            '#qpn div {' +
            'font-size: 12px;' +
            'margin: 2px 0;' +
            '}' +
            '.hidden-element, .hidden-config-section {' +
            'display: none !important;' +
            'height: 0 !important;' +
            'overflow: hidden !important;' +
            'visibility: hidden !important;' +
            'padding: 0 !important;' +
            'margin: 0 !important;' +
            'position: absolute !important;' +
            'left: -9999px !important;' +
            '}';
        me.addStyle(s);
        setTimeout(function () {
            const elementsToHide = [
                document.querySelector('.hidden-config-section'),
                document.getElementById('qpSplitValue'),
                document.getElementById('qpSplitValueReplace'),
                document.getElementById('qpNumberOfChapter')
            ];
            elementsToHide.forEach(function (el) {
                if (el) {
                    el.style.display = 'none';
                    el.style.visibility = 'hidden';
                    el.style.height = '0px';
                    el.style.overflow = 'hidden';
                    el.style.position = 'absolute';
                    el.style.left = '-9999px';
                    el.setAttribute('aria-hidden', 'true');
                }
            });
        }, 100);
    },
    createInjectHTML: function () {
        var me = this;
        var h =
            '<div id="HA">' +
            '<div class="form-group"></div>' +
            '<center>' +
            '<h3>CÔNG CỤ ĐĂNG NHANH</h3>' +
            '</center>' +
            '<center>' +
            '<h4><span id="short-chapter-warning" style="display:none; color:red;"></span></h4>' +
            '</center>' +
            '<div class="form-group">' +
            '<textarea placeholder="Nội dung truyện (Dán vào đây để tự động tách chương)" id="qpContent" class="form-control" rows="5"></textarea>' +
            '<div class="form-group" id="qpAdv" class="form-control" rows="2"></div>' +
            '<div class="form-group" style="text-align: center; margin-top: 10px;">' +
            '<button type="button" id="qpButtonSubmit" class="btn btn-default" style="margin: 0 auto;" onclick="javascript:;">Đăng chương</button>' +
            '<input type="button" id="qpButtonRemoveEmpty" value="Xóa chương trống" class="btn btn-danger" style="display:none;" />' +

            '</div>' +
            '<div class="form-group">' +
            '<span id="qpn" style="margin:0px 15px;font-weight:bold"></span>' +
            '</div>' +
            '</div>' +
            '<div class="hidden-config-section" style="display:none;height:0;overflow:hidden;visibility:hidden;">' +
            '<h4></h4>' +
            '<div class="form-group">' +
            '<input type="text" id="qpSplitValue" class="form-control" value="/[c|C]hương\\s?\\d+\\s?:?\\s?/">' +
            '</div>' +
            '<div class="form-group" id="qpSplitValueReplace"></div>' +
            '<div class="form-group">' +
            '<input type="number" placeholder="Thêm" value="9" id="qpNumberOfChapter" class="form-control">' +
            '</div>' +
            '</div>' +
            '<div class="form-group">' +
            '<b><center>' +
            '</center></b>' +
            '</div>' +
            '</div>';
        jQuery(".list-in-user").before(h);
    },
    performAction: function () {
        try {
            var me = this;
            var a = jQuery("#qpContent").val(),
                s = jQuery("#qpSplitValue").val(),
                st = jQuery('#qpSplitValueReplace').val().trim(),
                titles = jQuery("[name^=chap_name]"),
                contents = jQuery("[name^=introduce]"),
                advs = jQuery("[name^=adv]"),
                error = false,
                advContent = jQuery("#qpAdv").val();
            me.fillEmptyForms(titles, contents, advs, advContent, st);
            if (s.startsWith('/') && s.endsWith('/') && s.length > 0) {
                s = new RegExp(s.substring(1, s.length - 1));
            }
            a = a.split(s).filter(function (entry) {
                return entry.trim() !== "";
            });
            if (!loop && a.length < titles.length) {
                error = true;
            }
            if (loop && (a.length / 2) < titles.length) {
                error = true;
            }
            var splitTitle = st.toLowerCase();
            if (!loop) {
                jQuery.each(titles, (function (k, v) {
                    if (k < a.length) {
                        var at = a[k].trim(),
                            content = at.split('\n'),
                            originalTitle = content.shift().trim(),
                            title = originalTitle.toLowerCase();
                        originalTitle = me.ucFirst(originalTitle);
                        if (title.startsWith(splitTitle)) {
                            titles[k].value = originalTitle;
                            contents[k].value = headerSign + "\r\n" + content.join('\n') + "\r\n" + footerSign;
                            advs[k].value = advContent;
                        }
                        else {
                            titles[k].value = st + " " + originalTitle;
                            contents[k].value = headerSign + "\r\n" + content.join('\n') + "\r\n" + footerSign;
                            advs[k].value = advContent;
                        }
                    }
                    else {
                        jQuery("#qpContent").val("Đã thực hiện được " + k + " /" + (titles.length) + " nhập ban đầu, có thể nhấn Xóa chương trống, sau đó nhấn Đăng chương");
                        return false;
                    }
                }));
            }
            else {
                var j = 0,
                    ha = a.length / 2;
                jQuery.each(titles, (function (k, v) {
                    if (k < ha) {
                        var at = a[++j].trim(),
                            content = at.split('\n'),
                            originalTitle = content.shift().trim(),
                            title = '';
                        title = originalTitle.toLowerCase();
                        if (title === '') {
                            while (title === '' && content.length > 0) {
                                originalTitle = content.shift().trim();
                                title = originalTitle.toLowerCase();
                            }
                        }
                        originalTitle = me.ucFirst(originalTitle);
                        if (title.startsWith(splitTitle)) {
                            titles[k].value = originalTitle;
                            contents[k].value = headerSign + "\r\n" + content.join('\n') + "\r\n" + footerSign;
                            advs[k].value = advContent;
                        }
                        else {
                            titles[k].value = st + " " + originalTitle;
                            contents[k].value = headerSign + "\r\n" + content.join('\n') + "\r\n" + footerSign;
                            advs[k].value = advContent;
                        }
                    }
                    else {
                        jQuery("#qpContent").val("Đã thực hiện được " + k + " /" + (titles.length) + " nhập ban đầu, có thể nhấn Vẫn Đăng để tiếp tục");
                        return false;
                    }
                    j++;
                }));
            }
            if (!error) {
                jQuery("#qpButtonSubmit").removeClass("btn-disable").addClass("btn-success");
                jQuery("#qpContent").val("Đã thực hiện xong, OK");
            }
        }
        catch (e) {
            console.log("Lỗi: " + e);
        }
    },
    removeEmptyList: function () {
        try {
            var me = this;
            var titles = jQuery("[name^=chap_name]"),
                contents = jQuery("[name^=introduce]"),
                count = 0;
            jQuery("#qpn").html('');
            if (titles && titles.length) {
                for (var i = 0; i < titles.length; i++) {
                    var t = titles[i];
                    var c = contents[i];
                    if (t) {
                        if (!t.value || (c && !c.value.trim().replace(headerSign, '').replace(footerSign, '').trim())) {
                            if (t.parentElement.parentElement.parentElement.tagName != 'FORM') {
                                t.parentElement.parentElement.parentElement.remove();
                            }
                            me.updateChapNumber();
                            count++;
                        }
                    }
                }
            }
            alert('Đã loại bỏ ' + count + ' chương trống. Đã có thể nhấn Đăng chương');
            me.checkEmptyForms(); // Kiểm tra lại sau khi xóa
        }
        catch (e) {
            console.log("Lỗi: " + e);
        }
    },
    registerEvents: function () {
        var me = this;
        jQuery("#qpContent").on("paste", function (e) {
            jQuery(this).val("");
            var processingMsg = jQuery("<div>", {
                id: "processing-notification",
                text: "Đang xử lý tách chương...",
                css: {
                    position: "fixed",
                    top: "50%",
                    left: "50%",
                    transform: "translate(-50%, -50%)",
                    backgroundColor: "rgba(0, 0, 0, 0.7)",
                    color: "white",
                    padding: "15px 20px",
                    borderRadius: "5px",
                    zIndex: "10000",
                    fontSize: "16px"
                }
            });
            jQuery("body").append(processingMsg);
            setTimeout(function () {
                dăngnhanhTTV.splitChapters();
                jQuery("#processing-notification").fadeOut(300, function () {
                    jQuery(this).remove();
                });
                me.checkEmptyForms();
                var completeMsg = jQuery("<div>", {
                    id: "complete-notification",
                    text: "Đã tách chương tự động!",
                    css: {
                        position: "fixed",
                        top: "20px",
                        right: "20px",
                        backgroundColor: "#4CAF50",
                        color: "white",
                        padding: "10px 15px",
                        borderRadius: "5px",
                        zIndex: "10000",
                        fontSize: "14px"
                    }
                });
                jQuery("body").append(completeMsg);
                completeMsg.fadeIn(300).delay(2000).fadeOut(500, function () {
                    jQuery(this).remove();
                });
            }, 500);
        });
        jQuery("#qpButtonRemoveLast").on('click', function (e) {
            e.preventDefault();
            dăngnhanhTTV.removeLastedPost();
        });
        jQuery("#qpButtonGenChapter").on('click', function (e) {
            e.preventDefault();
            dăngnhanhTTV.createListAddChapter();
        });
        me.readCookies();
    },
    readCookies: function () {
        try {
            var cookieValue = null;
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = cookies[i].trim();
                if (cookie.indexOf('HAconfig=') === 0) {
                    cookieValue = decodeURIComponent(cookie.substring('HAconfig='.length));
                    break;
                }
            }
            if (cookieValue) {
                try {
                    var settings = JSON.parse(cookieValue);
                    if (settings.splitValue) jQuery("#qpSplitValue").val(settings.splitValue);
                    if (settings.optionLoop !== undefined) jQuery("#qpOptionLoop")[0].checked = settings.optionLoop;
                    if (settings.numberChapter) jQuery("#qpNumberOfChapter").val(settings.numberChapter);
                    if (settings.splitValueReplace) jQuery("#qpSplitValueReplace").val(settings.splitValueReplace);
                } catch (e) {
                    console.log("Lỗi khi parse cookie: " + e);
                }
            }
        } catch (e) {
            console.log("Lỗi khi đọc cookie: " + e);
        }
    },
    setCopyRight: function () {
        try {
            var me = this;
            var str = "© " + me.YEAR_ALIVE;
            var d = new Date(),
                y = d.getFullYear();
            if (y > me.YEAR_ALIVE) {
                str += " - " + y;
            }
            jQuery('#mkcopyright').text(str);
        }
        catch (e) {
            console.log("Lỗi: " + e);
        }
    },
    replaceTitle: function () {
        var me = this,
            titles = jQuery("[name^=chap_name]"),
            replaceVal = jQuery("#qpTextTitleReplace").val(),
            findVal = jQuery("#qpTextTitleFind").val();
        if (findVal.startsWith('/') && findVal.endsWith('/') && findVal.length > 2) {
            var re = findVal.substring(1, findVal.length - 1);
            findVal = new RegExp(re);
        }
        if (titles && titles.length > 0) {
            for (var i = 0; i < titles.length; i++) {
                var t = titles[i];
                if (t && t.value) {
                    t.value = t.value.replace(findVal, replaceVal);
                }
            }
            alert('Đã thay thế xong.');
        }
    },
    ucFirst: function (str) {
        if (str && typeof str === 'string' && str.length > 0) {
            let fst = str[0].toUpperCase();
            str = str.length === 1 ? fst : fst + str.substring(1);
        }
        return str;
    },
    init: function () {
        try {
            var me = this;
            var chap_number = parseInt(jQuery('#chap_number').val());
            var chap_stt = parseInt(jQuery('.chap_stt1').val());
            var chap_serial = parseInt(jQuery('.chap_serial').val());
            if (parseInt(jQuery('#chap_stt').val()) > chap_stt) {
                chap_stt = parseInt(jQuery('#chap_stt').val());
            }
            if (parseInt(jQuery('#chap_serial').val()) > chap_serial) {
                chap_serial = parseInt(jQuery('#chap_serial').val());
            }
            me.CHAP_NUMBER = me.CHAP_NUMBER_ORIGINAL = chap_number;
            me.CHAP_STT = me.CHAP_STT_ORIGINAL = chap_stt;
            me.CHAP_SERIAL = me.CHAP_STT_ORIGINAL = chap_serial;
            me.createInjectHTML();
            me.addCss();
            me.registerEvents();
            me.setCopyRight();
            me.createListAddChapter(true);
            jQuery('#qpNumberOfChapter').attr('max', me.MAX_CHAPTER_POST);
            jQuery("#qpContent").focus();
            var style = document.createElement('style');
            style.innerHTML = `
                @keyframes blink-red {
                    0% { box-shadow: 0 0 5px rgba(255, 0, 0, 0.5); }
                    50% { box-shadow: 0 0 15px rgba(255, 0, 0, 0.8); }
                    100% { box-shadow: 0 0 5px rgba(255, 0, 0, 0.5); }
                }
                textarea[style*='border: 3px solid red'] {
                    animation: blink-red 2s infinite;
                }
                #short-chapter-warning {
                    animation: blink-red 2s infinite;
                }
            `;
            document.head.appendChild(style);
        }
        catch (e) {
            console.log("Lỗi: " + e);
        }
    },
    copyToClipboard: function (text) {
        var textarea = document.createElement('textarea');
        textarea.value = text;
        textarea.setAttribute('readonly', '');
        textarea.style.position = 'absolute';
        textarea.style.left = '-9999px';
        document.body.appendChild(textarea);
        textarea.select();
        document.execCommand('copy');
        document.body.removeChild(textarea);
    },
    fillEmptyForms: function (titles, contents, advs, advContent, st) {
        var me = this;
        try {
            var maxIterations = 3;
            var iteration = 0;
            var hasEmptyForms = true;
            while (hasEmptyForms && iteration < maxIterations) {
                hasEmptyForms = false;
                for (var i = 0; i < titles.length; i++) {
                    var currentTitle = titles[i];
                    var currentContent = contents[i];
                    if (currentTitle && (!currentTitle.value || (currentContent && !currentContent.value.trim().replace(headerSign, '').replace(footerSign, '').trim()))) {
                        hasEmptyForms = true;
                        var foundNextValid = false;
                        for (var j = i + 1; j < titles.length; j++) {
                            var nextTitle = titles[j];
                            var nextContent = contents[j];
                            if (nextTitle && nextTitle.value && nextContent && nextContent.value.trim().replace(headerSign, '').replace(footerSign, '').trim()) {
                                currentTitle.value = nextTitle.value;
                                currentContent.value = nextContent.value;
                                if (advs && advs[i]) {
                                    advs[i].value = advs[j] ? advs[j].value : advContent;
                                }
                                nextTitle.value = "";
                                nextContent.value = "";
                                if (advs && advs[j]) {
                                    advs[j].value = "";
                                }
                                foundNextValid = true;
                                break;
                            }
                        }
                    }
                }
                iteration++;
            }
            var emptyFormCount = 0;
            for (var i = 0; i < titles.length; i++) {
                var currentTitle = titles[i];
                var currentContent = contents[i];
                if (currentTitle && (!currentTitle.value || (currentContent && !currentContent.value.trim().replace(headerSign, '').replace(footerSign, '').trim()))) {
                    emptyFormCount++;
                }
            }
        } catch (e) {
            console.log("Lỗi khi đẩy chương lên form trống: " + e);
        }
    },
    checkEmptyForms: function() {
        var titles = jQuery("[name^=chap_name]");
        var contents = jQuery("[name^=introduce]");
        var hasEmptyForms = false;
        
        if (titles && titles.length) {
            for (var i = 0; i < titles.length; i++) {
                var t = titles[i];
                var c = contents[i];
                if (t && (!t.value || (c && !c.value.trim().replace(headerSign, '').replace(footerSign, '').trim()))) {
                    if (t.parentElement.parentElement.parentElement.tagName != 'FORM') {
                        hasEmptyForms = true;
                        break;
                    }
                }
            }
        }
        
        if (hasEmptyForms) {
            jQuery("#qpButtonRemoveEmpty").show();
        } else {
            jQuery("#qpButtonRemoveEmpty").hide();
        }
        
        return hasEmptyForms;
    },
    
    splitChapters: function () {
        var me = this;
        try {
            window.shortChapterNotified = false;
            var warningEl = document.getElementById('short-chapter-warning');
            if (warningEl) {
                warningEl.style.display = 'none';
            }
            var content = jQuery("#qpContent").val(),
                st = jQuery('#qpSplitValueReplace').val().trim(),
                advContent = jQuery("#qpAdv").val();
            var lines = content.split('\n');
            var chapters = [];
            var currentChapter = [];
            var regex = /^\s+[Cc]hương\s*\d+:/;
            for (var i = 0; i < lines.length; i++) {
                var line = lines[i];
                if (line.match(regex)) {
                    if (currentChapter.length > 0) {
                        chapters.push(currentChapter.join('\n'));
                        currentChapter = [];
                    }
                    currentChapter.push(line);
                } else {
                    currentChapter.push(line);
                }
            }
            if (currentChapter.length > 0) {
                chapters.push(currentChapter.join('\n'));
            }
            chapters = chapters.filter(function (chapter) {
                var lines = chapter.split('\n');
                return lines.some(function (line, index) {
                    return index > 0 && line.trim().length > 0;
                });
            });
            var i = 0;
            while (i < chapters.length) {
                if (chapters[i].length > 19000) {
                    var largeChapter = chapters[i];
                    var lines = largeChapter.split('\n');
                    var chapterTitle = lines.shift();
                    var contentToSplit = lines.join('\n');
                    var contentLength = contentToSplit.length;
                    var numSubChapters = Math.ceil(contentLength / 15000);
                    var chunkSize = Math.floor(contentLength / numSubChapters);
                    var subChapters = [];
                    var startPos = 0;
                    for (var j = 0; j < numSubChapters; j++) {
                        var endPos = (j === numSubChapters - 1) ? contentLength : startPos + chunkSize;
                        if (j < numSubChapters - 1) {
                            var lookAhead = Math.min(200, contentLength - endPos);
                            var segment = contentToSplit.substring(endPos, endPos + lookAhead);
                            var sentenceEnd = segment.search(/[.!?][^.!?]*$/);
                            if (sentenceEnd !== -1) {
                                endPos += sentenceEnd + 1;
                            }
                        }
                        var subContent = contentToSplit.substring(startPos, endPos);
                        var subTitle = chapterTitle.trim() + " (Phần " + (j + 1) + "/" + numSubChapters + ")";
                        subChapters.push(subTitle + "\n" + subContent);
                        startPos = endPos;
                    }
                    chapters.splice(i, 1, ...subChapters);
                    i += numSubChapters;
                } else {
                    i++;
                }
            }
            var titles = jQuery("[name^=chap_name]");
            var contents = jQuery("[name^=introduce]");
            var advs = jQuery("[name^=adv]");
            var validChapters = 0;
            var processedChapters = 0;
            for (var i = 0; i < Math.min(chapters.length, titles.length); i++) {
                var chapterLines = chapters[i].split('\n');
                var title = chapterLines.shift().trim();
                var content = chapterLines.join('\n');
                if (content) {
                    validChapters++;
                    if (title.includes(':')) {
                        title = title.split(':').slice(1).join(':').trim();
                    }
                    title = me.ucFirst(title);
                    if (title.toLowerCase().startsWith(st.toLowerCase())) {
                        titles[i].value = title;
                    } else {
                        titles[i].value = st + " " + title;
                    }
                    contents[i].value = headerSign + "\r\n" + content + "\r\n" + footerSign;
                    advs[i].value = advContent;
                    var contentWithoutEmpty = content.split('\n')
                        .filter(line => line.trim().length > 0)
                        .join('\n');
                    var charCount = contentWithoutEmpty.length;
                    if (charCount < 3000) {
                        contents[i].style.border = '3px solid red';
                        contents[i].style.borderRadius = '5px';
                        contents[i].style.backgroundColor = 'rgba(255, 0, 0, 0.1)';
                        if (!window.shortChapterNotified) {
                            window.shortChapterNotified = true;
                            var numbershortChapters = document.querySelectorAll("textarea[style*='border: 3px solid red']").length;
                            var warningEl = document.getElementById('short-chapter-warning');
                            if (warningEl) {
                                warningEl.textContent = '⚠️ Có chương dưới 3000 ký tự. ⚠️';
                                warningEl.style.display = 'block';
                            }
                            setTimeout(function () {
                                alert('Cảnh báo: Phát hiện có chương dưới 3000 ký tự.');
                            }, 500);
                        }
                    }
                    processedChapters++;
                }
            }
            var totalProcessedChapters = chapters.length;
            var splitChaptersCount = 0;
            for (var i = 0; i < chapters.length; i++) {
                var firstLine = chapters[i].split('\n')[0];
                if (firstLine && firstLine.includes(" (Phần ")) {
                    splitChaptersCount++;
                }
            }
            var originalChapterCount = totalProcessedChapters - splitChaptersCount + Math.ceil(splitChaptersCount / 2);
            var largeChapters = [];
            for (var i = 0; i < chapters.length; i++) {
                if (chapters[i].length > 19000) {
                    largeChapters.push(i);
                }
            }
            var newChaptersFromSplit = splitChaptersCount;
            var mainSummary = "";
            mainSummary += "Đã xử lý " + totalProcessedChapters + " chương\n";
            mainSummary += "Đã lấy " + Math.min(chapters.length, titles.length) + " chương";
            if (chapters.length > titles.length) {
                mainSummary += "\nĐã lưu " + (chapters.length - titles.length) + " chương vào Clipboard";
            }
            var detailedSummary = "\n";
            detailedSummary += "Đã xử lý " + totalProcessedChapters + " chương\n";
            detailedSummary += "Đã lấy " + Math.min(chapters.length, titles.length) + " chương\n";
            if (chapters.length > titles.length) {
                detailedSummary += "Đã lưu " + (chapters.length - titles.length) + " chương vào Clipboard\n";
            }
            var splitChapterGroups = [];
            var totalSplitParts = 0;
            for (var i = 0; i < chapters.length; i++) {
                var firstLine = chapters[i].split('\n')[0];
                if (firstLine && firstLine.includes(" (Phần ")) {
                    var parts = firstLine.match(/\(Phần (\d+)\/(\d+)\)/);
                    if (parts && parts[1] && parts[2]) {
                        var partNum = parseInt(parts[1]);
                        var totalPartNum = parseInt(parts[2]);
                        var chapterBaseName = firstLine.replace(/\s*\(Phần \d+\/\d+\)/, "").trim();
                        var chapterId = chapterBaseName + "_" + totalPartNum;
                        if (partNum === 1) {
                            splitChapterGroups.push({
                                id: chapterId,
                                name: chapterBaseName,
                                totalParts: totalPartNum
                            });
                        }
                        totalSplitParts++;
                    }
                }
            }
            var largeChapterCount = splitChapterGroups.length;
            var totalParts = totalSplitParts;
            if (largeChapterCount > 0) {
                var mainMsg = "Có " + largeChapterCount + " chương dài được chia thành " + totalParts + " chương\n";
                detailedSummary += mainMsg;
                if (splitChapterGroups.length > 0) {
                    for (var i = 0; i < splitChapterGroups.length; i++) {
                        var chapterMatch = splitChapterGroups[i].name.match(/[Cc]hương\s*(\d+):/);
                        var chapterNum = chapterMatch ? chapterMatch[0] : "Chương";
                        detailedSummary += " - " + chapterNum + " chia thành " + 
                                          splitChapterGroups[i].totalParts + " chương\n";
                    }
                }
            }
            if (largeChapters.length > 0) {
                var largeChaptersProcessed = 0;
                var newChaptersGenerated = 0;
                for (var i = 0; i < chapters.length; i++) {
                    var firstLine = chapters[i].split('\n')[0];
                    if (firstLine && firstLine.includes(" (Phần ")) {
                        var parts = firstLine.match(/\(Phần (\d+)\/(\d+)\)/);
                        if (parts && parts[1] && parts[2]) {
                            if (parts[1] === "1") {
                                largeChaptersProcessed++;
                                newChaptersGenerated += parseInt(parts[2]);
                            }
                        }
                    }
                }
                var mainMsg = "Có " + largeChaptersProcessed + " chương dài được chia thành " + newChaptersFromSplit + " chương\n";
                detailedSummary += mainMsg;
            }
            var titleCounts = {};
            var duplicateTitles = [];
            for (var i = 0; i < titles.length; i++) {
                var title = titles[i].value;
                if (title) {
                    if (titleCounts[title]) {
                        titleCounts[title]++;
                        if (titleCounts[title] === 2) {
                            duplicateTitles.push(title);
                        }
                    } else {
                        titleCounts[title] = 1;
                    }
                }
            }
            if (duplicateTitles.length > 0) {
                detailedSummary += "Có " + duplicateTitles.length + " chương tiêu đề bị lặp lại\n";
                for (var i = 0; i < duplicateTitles.length; i++) {
                    detailedSummary += " - " + duplicateTitles[i] + "\n";
                }
            }
            var shortChapters = [];
            for (var i = 0; i < Math.min(chapters.length, titles.length); i++) {
                var content = contents[i].value.trim().replace(headerSign, '').replace(footerSign, '');
                var charCount = content.length;
                if (charCount < 3000) {
                    var chapterMatch = titles[i].value.match(/[Cc]hương\s*(\d+)/);
                    var chapterNum = chapterMatch ? chapterMatch[1] : (i + 1);
                    shortChapters.push("Chương " + chapterNum + " chỉ có " + charCount + " ký tự");
                }
            }
            if (shortChapters.length > 0) {
                detailedSummary += shortChapters.join("\n");
            }
            if (chapters.length > titles.length) {
                var remainingContent = chapters.slice(titles.length).join("\n\n");
                me.copyToClipboard(remainingContent);
            }
            jQuery("#qpContent").val(mainSummary);
            jQuery("#qpn").html(detailedSummary.replace(/\n/g, '<br>'));
            jQuery("#qpButtonSubmit").removeClass("btn-disable").addClass("btn-success");
        } catch (e) {
            console.log("Lỗi khi tách chương: " + e);
            jQuery("#qpn").html("Có lỗi xảy ra khi tách chương: " + e).addClass("text-danger");
        }
    }
};
if (window.location.href.includes('tangthuvien.net/message/successchapter')) {
    setTimeout(function () {
        var previousUrl = document.referrer;
        var storyId = '';
        if (previousUrl.includes('/dang-chuong/story/')) {
            var matches = previousUrl.match(/\/dang-chuong\/story\/(\d+)/);
            if (matches && matches[1]) {
                storyId = matches[1];
                window.location.href = 'https://tangthuvien.net/dang-chuong/story/' + storyId;
            }
        }
    }, 3000);
}
else if (window.location.href.includes('/story/') && window.location.href.includes('/danh-sach-chuong')) {
    setTimeout(function () {
        var matches = window.location.href.match(/\/story\/(\d+)/);
        if (matches && matches[1]) {
            var storyId = matches[1];
            window.location.href = 'https://tangthuvien.net/dang-chuong/story/' + storyId;
        }
    }, 3000);
} else {
    dăngnhanhTTV.init();
}