TTV

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

目前為 2025-03-06 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         TTV
// @namespace    http://tampermonkey.net/
// @version      2.9
// @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 5px;" onclick="javascript:;">Đăng chương</button>' +
            '<button type="button" id="qpButtonRemoveEmpty" class="btn btn-danger" style="margin: 0 5px; display: none;">Xóa chương trống</button>' +
            '</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>';
        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');
        }
        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();
                });
                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();
        });
        jQuery("#qpButtonResetChapter").on('click', function (e) {
            e.preventDefault();
            if (confirm('Bạn có chắc chắn xóa toàn bộ danh sách đã tạo, chú ý sẽ xóa toàn bộ nội dung đã dán trước đó')) {
                var count = jQuery('[data-gen="MK_GEN"]').length;
                jQuery('[data-gen="MK_GEN"]').remove();
                for (var i = 0; i < count; i++) {
                    me.updateChapNumber();
                }
            }
        });
        jQuery("#qpSaveConfig").on("click", function (e) {
            e.preventDefault();
            me.saveCookies();
        });
        jQuery('#qpButtonRemoveEmpty').on('click', function (e) {
            e.preventDefault();
            me.removeEmptyList();
            var titles = jQuery("[name^=chap_name]");
            var contents = jQuery("[name^=introduce]");
            var advs = jQuery("[name^=adv]");
            var advContent = jQuery("#qpAdv").val();
            var st = jQuery('#qpSplitValueReplace').val().trim();
            me.fillEmptyForms(titles, contents, advs, advContent, st);
        });
        jQuery('#qpButtonTitleReplace').on('click', function (e) {
            e.preventDefault();
            me.replaceTitle();
        });
        jQuery("#qpButtonSubmit").on('click', function (e) {
            e.preventDefault();
            var titles = jQuery("[name^=chap_name]");
            var contents = jQuery("[name^=introduce]");
            var advs = jQuery("[name^=adv]");
            var advContent = jQuery("#qpAdv").val();
            var st = jQuery('#qpSplitValueReplace').val().trim();
            me.fillEmptyForms(titles, contents, advs, advContent, st);
            jQuery('form button[type=submit]')[0].click();
        });
        me.readCookies();
    },
    saveCookies: function () {
        try {
            var value = {
                splitValue: jQuery("#qpSplitValue").val(),
                optionLoop: jQuery("#qpOptionLoop")[0].checked,
                numberChapter: jQuery('#qpNumberOfChapter').val(),
                splitValueReplace: jQuery('#qpSplitValueReplace').val()
            };
            var cookieValue = JSON.stringify(value);
            var d = new Date();
            d.setTime(d.getTime() + (30 * 24 * 60 * 60 * 1000));
            var expires = "expires=" + d.toUTCString();
            document.cookie = "HAconfig=" + encodeURIComponent(cookieValue) + ";" + expires + ";path=/;domain=tangthuvien.net";
            alert("Đã lưu lại thiết lập thành công");
        } catch (e) {
            console.log("Lỗi khi lưu thiết lập: " + e);
            alert("Có lỗi xảy ra khi lưu thiết lập");
        }
    },
    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;
                    border: 2px solid #ea4335 !important;
                    border-radius: 8px !important;
                    background-color: rgba(255, 235, 238, 0.2) !important;
                }
                #short-chapter-warning {
                    animation: blink-red 2s infinite;
                    display: inline-block;
                    padding: 8px 12px;
                    border-radius: 6px;
                }
                .form-control {
                    border: 1px solid #e0e0e0;
                    border-radius: 6px;
                    padding: 10px;
                    font-size: 14px;
                    transition: all 0.3s ease;
                }
                .form-control:focus {
                    border-color: #4285f4;
                    box-shadow: 0 0 5px rgba(66, 133, 244, 0.3);
                    outline: none;
                }
                .btn {
                    padding: 8px 16px;
                    border-radius: 6px;
                    font-weight: 500;
                    cursor: pointer;
                    transition: all 0.2s ease;
                    border: none;
                    font-size: 14px;
                    margin: 5px;
                }
                .btn-success {
                    background-color: #4285f4;
                    color: white;
                }
                .btn-success:hover {
                    background-color: #3367d6;
                }
                .btn-danger {
                    background-color: #ea4335;
                    color: white;
                }
                .btn-danger:hover {
                    background-color: #d33426;
                }
                .btn-default {
                    background-color: #f1f3f4;
                    color: #333333;
                }
                .btn-default:hover {
                    background-color: #e8eaed;
                }
                
                /* Styles for summary sections */
                .summary-section {
                    padding: 10px;
                    margin-bottom: 8px;
                    border-radius: 6px;
                    background-color: #ffffff;
                    border-left: 4px solid #4285f4;
                    box-shadow: 0 1px 3px rgba(0,0,0,0.05);
                }
                .summary-section.warning {
                    border-left-color: #fbbc05;
                    background-color: #fffde7;
                }
                .summary-section.error {
                    border-left-color: #ea4335;
                    background-color: #fef2f2;
                }
                .summary-label {
                    font-weight: 600;
                    color: #202124;
                    display: inline-block;
                    min-width: 140px;
                }
                .summary-value {
                    color: #3c4043;
                    font-weight: 500;
                }
                .summary-details {
                    margin: 5px 0 5px 15px;
                    padding: 5px 0 5px 10px;
                    border-left: 2px solid #e0e0e0;
                }
                .detail-item {
                    padding: 5px 0;
                    color: #5f6368;
                    font-size: 13px;
                }
            `;
            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++;
                }
            }
            if (emptyFormCount > 0) {
                jQuery("#qpn").html(jQuery("#qpn").html() + "<br><b style='color:red'>Cảnh báo: Vẫn còn " + emptyFormCount + " chương trống.</b>");
                jQuery('#qpButtonRemoveEmpty').show();
            } else {
                jQuery('#qpButtonRemoveEmpty').hide();
            }
        } catch (e) {
            console.log("Lỗi khi đẩy chương lên form trống: " + e);
        }
    },
    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 chương có chương dưới 3000 ký tự.');
                            }, 500);
                        }
                    }
                    processedChapters++;
                }
            }
            var totalProcessedChapters = chapters.length;
            var splitChaptersCount = 0;
            // Khai báo các biến thiếu
            var largeChapterCount = 0;
            var totalParts = 0;
            var splitChapterGroups = [];
            var duplicateTitles = [];
            var shortChapters = [];
            
            // Đếm số chương dài đã được chia
            for (var i = 0; i < chapters.length; i++) {
                var firstLine = chapters[i].split('\n')[0];
                if (firstLine && firstLine.includes(" (Phần ")) {
                    splitChaptersCount++;
                    
                    // Phân tích thông tin phần
                    var parts = firstLine.match(/\(Phần (\d+)\/(\d+)\)/);
                    if (parts && parts[2]) {
                        var totalPartsInChapter = parseInt(parts[2]);
                        if (parts[1] === "1") { // Chỉ đếm khi là phần đầu tiên
                            largeChapterCount++;
                            totalParts += totalPartsInChapter;
                            
                            // Lưu thông tin nhóm chương đã chia
                            var chapterName = firstLine.replace(/\s*\(Phần \d+\/\d+\)/, "");
                            splitChapterGroups.push({
                                name: chapterName,
                                totalParts: totalPartsInChapter
                            });
                        }
                    }
                }
            }
            
            // Kiểm tra chương ngắn
            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) {
                    var contentWithoutEmpty = content.split('\n')
                        .filter(line => line.trim().length > 0)
                        .join('\n');
                    var charCount = contentWithoutEmpty.length;
                    if (charCount < 3000) {
                        shortChapters.push(title);
                    }
                }
            }
            
            // Kiểm tra chương trùng lặp
            var titleMap = {};
            for (var i = 0; i < Math.min(chapters.length, titles.length); i++) {
                if (titles[i] && titles[i].value) {
                    var titleText = titles[i].value.toLowerCase();
                    if (titleMap[titleText]) {
                        duplicateTitles.push(titles[i].value);
                    } else {
                        titleMap[titleText] = true;
                    }
                }
            }
            
            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;
            
            // Cải thiện hiển thị thông báo
            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";
            }
            // Tạo thông báo chi tiết với định dạng tốt hơn
            var detailedSummary = "";
            detailedSummary += "<div class='summary-section'><span class='summary-label'>Tổng số chương:</span> <span class='summary-value'>" + totalProcessedChapters + "</span></div>";
            detailedSummary += "<div class='summary-section'><span class='summary-label'>Đã xử lý:</span> <span class='summary-value'>" + Math.min(chapters.length, titles.length) + " chương</span></div>";
            if (chapters.length > titles.length) {
                detailedSummary += "<div class='summary-section'><span class='summary-label'>Đã lưu vào Clipboard:</span> <span class='summary-value'>" + (chapters.length - titles.length) + " chương</span></div>";
            }
            // Hiển thị thông tin về chương dài
            if (largeChapterCount > 0) {
                detailedSummary += "<div class='summary-section warning'><span class='summary-label'>Chương dài:</span> <span class='summary-value'>" + largeChapterCount + " chương được chia thành " + totalParts + " phần</span></div>";
                
                if (splitChapterGroups.length > 0) {
                    detailedSummary += "<div class='summary-details'>";
                    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 += "<div class='detail-item'>" + chapterNum + " chia thành " + 
                                          splitChapterGroups[i].totalParts + " chương</div>";
                    }
                    detailedSummary += "</div>";
                }
            }
            // Hiển thị thông tin về chương trùng lặp
            if (duplicateTitles.length > 0) {
                detailedSummary += "<div class='summary-section error'><span class='summary-label'>Chương trùng lặp:</span> <span class='summary-value'>" + duplicateTitles.length + " chương</span></div>";
                detailedSummary += "<div class='summary-details'>";
                for (var i = 0; i < duplicateTitles.length; i++) {
                    detailedSummary += "<div class='detail-item'>" + duplicateTitles[i] + "</div>";
                }
                detailedSummary += "</div>";
            }
            // Hiển thị thông tin về chương ngắn
            if (shortChapters.length > 0) {
                detailedSummary += "<div class='summary-section error'><span class='summary-label'>Chương ngắn:</span> <span class='summary-value'>" + shortChapters.length + " chương</span></div>";
                detailedSummary += "<div class='summary-details'>";
                for (var i = 0; i < shortChapters.length; i++) {
                    detailedSummary += "<div class='detail-item'>" + shortChapters[i] + "</div>";
                }
                detailedSummary += "</div>";
            }
            
            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);
            jQuery("#qpButtonSubmit").removeClass("btn-disable").addClass("btn-success");
            var emptyChaptersExist = 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()))) {
                    emptyChaptersExist = true;
                    break;
                }
            }
            if (emptyChaptersExist) {
                jQuery('#qpButtonRemoveEmpty').show();
            } else {
                jQuery('#qpButtonRemoveEmpty').hide();
            }
        } catch (e) {
            console.log("Lỗi khi tách chương: " + e);
            jQuery("#qpn").html("<div class='summary-section error'><span class='summary-label'>Lỗi:</span> <span class='summary-value'>" + e + "</span></div>").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();
}