// ==UserScript==
// @name TTV Auto Upload
// @namespace http://tampermonkey.net/
// @version 1.3
// @description Tự động điền form đăng chương trên tangthuvien.net với tính năng nâng cao
// @author HA
// @match https://tangthuvien.net/dang-chuong/story/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
// Thêm CSS cho thông báo và nút
const style = document.createElement('style');
style.textContent = `
.ttv-notification {
position: fixed;
top: 20px;
right: 20px;
padding: 10px 20px;
background: #4CAF50;
color: white;
border-radius: 4px;
z-index: 9999;
display: none;
}
.ttv-error {
background: #f44336;
}
.ttv-control-panel {
position: fixed;
top: 50px;
right: 20px;
background: white;
padding: 25px;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
z-index: 9998;
width: 500px;
margin-bottom: 20px;
transition: all 0.3s ease;
}
.ttv-control-panel.minimized {
width: auto;
height: auto;
padding: 10px;
opacity: 0.8;
transform: translateX(calc(100% - 40px));
transition: all 0.3s ease;
}
.ttv-control-panel.minimized:hover {
opacity: 1;
transform: translateX(0);
}
.ttv-control-panel.minimized .ttv-button-group,
.ttv-control-panel.minimized .ttv-header {
display: none;
}
// Điều chỉnh toolbar và các nút điều khiển
.ttv-toolbar {
display: flex;
gap: 6px;
align-items: center;
}
.ttv-toolbar button {
padding: 2px 8px;
font-size: 11px;
color: #555;
background: #f5f5f5;
border: 1px solid #ddd;
border-radius: 3px;
cursor: pointer;
transition: all 0.2s ease;
}
.ttv-toolbar button:hover {
background: #e9e9e9;
transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.ttv-button-group {
display: flex;
flex-direction: column;
gap: 15px;
}
.ttv-file-label {
width: 100%;
padding: 12px;
background: #5bc0de;
color: white;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
text-align: center;
transition: all 0.2s ease;
margin: 0;
}
.ttv-file-label:hover {
background: #46b8da;
transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.ttv-content-editor {
width: 100%;
height: 180px;
margin: 6px 0;
padding: 10px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 13px;
line-height: 1.5;
resize: vertical;
transition: all 0.2s ease;
}
.ttv-content-editor:focus {
border-color: #5bc0de;
outline: none;
box-shadow: 0 0 8px rgba(91,192,222,0.2);
}
.ttv-preview {
display: none;
width: 100%;
height: 180px;
margin: 6px 0;
padding: 10px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 13px;
line-height: 1.5;
overflow-y: auto;
background: #f9f9f9;
transition: all 0.2s ease;
}
.ttv-heading {
font-size: 15px;
color: #555;
margin: 12px 0;
display: flex;
justify-content: space-between;
align-items: center;
}
.ttv-word-count {
font-size: 12px;
color: #888;
padding: 3px 8px;
background: #f5f5f5;
border-radius: 4px;
transition: all 0.2s ease;
}
// Tối ưu chế độ toàn màn hình
.ttv-control-panel.fullscreen {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 0;
z-index: 9999;
padding: 15px;
display: flex;
flex-direction: column;
}
.ttv-control-panel.fullscreen .ttv-content-editor,
.ttv-control-panel.fullscreen .ttv-preview {
height: calc(100vh - 100px);
margin: 4px 0;
font-size: 14px;
}
.ttv-header {
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 2px solid #eee;
font-weight: bold;
font-size: 16px;
color: #444;
display: flex;
justify-content: space-between;
align-items: center;
}
button.btn-warning {
background: #f0ad4e;
color: white;
border: none;
padding: 12px;
border-radius: 6px;
width: 100%;
font-size: 14px;
transition: all 0.2s ease;
}
button.btn-warning:hover {
background: #ec971f;
transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
button.ttv-minimize {
padding: 2px 8px;
background: none;
border: none;
cursor: pointer;
font-size: 16px;
color: #666;
transition: all 0.2s ease;
}
button.ttv-minimize:hover {
color: #333;
}
`;
document.head.appendChild(style);
// Tạo div thông báo
const notification = document.createElement('div');
notification.className = 'ttv-notification';
document.body.appendChild(notification);
// Hiển thị thông báo
function showNotification(message, isError = false) {
notification.textContent = message;
notification.className = 'ttv-notification' + (isError ? ' ttv-error' : '');
notification.style.display = 'block';
setTimeout(() => {
notification.style.display = 'none';
}, 3000);
}
// Đọc nội dung file
function readFileContent(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => resolve(e.target.result);
reader.onerror = (e) => reject(new Error('Lỗi đọc file: ' + e.target.error));
reader.readAsText(file, 'UTF-8');
});
}
// Đếm số từ và ký tự
function updateWordCount(content) {
const wordCount = content.trim().split(/\s+/).length;
const charCount = content.length;
return `${wordCount} từ | ${charCount} ký tự`;
}
// Xử lý khi chọn file
async function handleFileSelect(event) {
try {
const file = event.target.files[0];
if (!file) return;
// Đọc nội dung file
const content = await readFileContent(file);
// Điền vào khung soạn thảo nội dung
const contentEditor = document.querySelector('.ttv-content-editor');
if (contentEditor) {
contentEditor.value = content;
// Cập nhật số từ
const wordCountSpan = document.querySelector('.ttv-word-count');
if (wordCountSpan) {
wordCountSpan.textContent = updateWordCount(content);
}
showNotification('Đã tải nội dung từ file thành công!');
} else {
showNotification('Không tìm thấy khung soạn thảo!', true);
}
} catch (error) {
console.error('Lỗi xử lý file:', error);
showNotification('Có lỗi xảy ra khi đọc file!', true);
}
}
// Chuyển nội dung từ khung soạn thảo sang form
function transferContent() {
const contentEditor = document.querySelector('.ttv-content-editor');
const contentInput = document.querySelector('textarea[name="introduce[1]"]');
if (contentEditor && contentInput) {
contentInput.value = contentEditor.value;
showNotification('Đã chuyển nội dung sang form đăng chương!');
} else {
showNotification('Không tìm thấy form đăng chương!', true);
}
}
// Chuyển đổi giữa chế độ soạn thảo và xem trước
function togglePreview() {
const contentEditor = document.querySelector('.ttv-content-editor');
const preview = document.querySelector('.ttv-preview');
const previewBtn = document.querySelector('.ttv-preview-btn');
if (contentEditor.style.display !== 'none') {
contentEditor.style.display = 'none';
preview.style.display = 'block';
preview.innerHTML = contentEditor.value.replace(/\n/g, '<br>');
previewBtn.textContent = 'Soạn thảo';
} else {
contentEditor.style.display = 'block';
preview.style.display = 'none';
previewBtn.textContent = 'Xem trước';
}
}
// Chuyển đổi chế độ toàn màn hình
function toggleFullscreen() {
const panel = document.querySelector('.ttv-control-panel');
const fullscreenBtn = document.querySelector('.ttv-fullscreen-btn');
panel.classList.toggle('fullscreen');
fullscreenBtn.textContent = panel.classList.contains('fullscreen') ? 'Thu nhỏ' : 'Toàn màn hình';
}
// Thêm panel điều khiển
function addControlPanel() {
// Tạo panel
const panel = document.createElement('div');
panel.className = 'ttv-control-panel';
// Thêm header
const header = document.createElement('div');
header.className = 'ttv-header';
header.innerHTML = `
<div>Soạn Thảo Nội Dung</div>
<div class="ttv-toolbar">
<button class="ttv-preview-btn" onclick="togglePreview()">Xem trước</button>
<button class="ttv-fullscreen-btn" onclick="toggleFullscreen()">Toàn màn hình</button>
<button class="ttv-minimize">−</button>
</div>
`;
// Container cho các nút
const buttonGroup = document.createElement('div');
buttonGroup.className = 'ttv-button-group';
// Input chọn file
const fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.accept = '.txt';
fileInput.className = 'ttv-file-input';
fileInput.id = 'ttv-file-input';
fileInput.onchange = handleFileSelect;
// Label cho input file
const fileLabel = document.createElement('label');
fileLabel.htmlFor = 'ttv-file-input';
fileLabel.className = 'ttv-file-label';
fileLabel.innerHTML = '<span>Chọn file txt chứa nội dung</span>';
// Khung soạn thảo nội dung
const contentEditorLabel = document.createElement('div');
contentEditorLabel.className = 'ttv-heading';
contentEditorLabel.innerHTML = `
Nội dung chương:
<span class="ttv-word-count">0 từ | 0 ký tự</span>
`;
const contentEditor = document.createElement('textarea');
contentEditor.className = 'ttv-content-editor';
contentEditor.placeholder = 'Nhập hoặc dán nội dung chương vào đây...';
// Khung xem trước
const preview = document.createElement('div');
preview.className = 'ttv-preview';
// Cập nhật số từ khi nhập nội dung
contentEditor.oninput = () => {
const wordCountSpan = document.querySelector('.ttv-word-count');
if (wordCountSpan) {
wordCountSpan.textContent = updateWordCount(contentEditor.value);
}
};
// Nút chuyển nội dung
const transferBtn = document.createElement('button');
transferBtn.type = 'button';
transferBtn.className = 'btn btn-warning';
transferBtn.innerHTML = '<span>Chuyển nội dung sang form</span>';
transferBtn.onclick = transferContent;
// Thêm các phần tử vào panel
panel.appendChild(header);
buttonGroup.appendChild(fileInput);
buttonGroup.appendChild(fileLabel);
buttonGroup.appendChild(contentEditorLabel);
buttonGroup.appendChild(contentEditor);
buttonGroup.appendChild(preview);
buttonGroup.appendChild(transferBtn);
panel.appendChild(buttonGroup);
document.body.appendChild(panel);
// Thêm xử lý sự kiện cho các nút trong toolbar
const minimizeBtn = panel.querySelector('.ttv-minimize');
minimizeBtn.onclick = () => {
panel.classList.toggle('minimized');
minimizeBtn.innerHTML = panel.classList.contains('minimized') ? '+' : '−';
};
window.togglePreview = togglePreview;
window.toggleFullscreen = toggleFullscreen;
}
// Thêm control panel khi trang đã load
window.addEventListener('load', function() {
addControlPanel();
});
})();// ==UserScript==
// @name TTV Auto Upload
// @namespace http://tampermonkey.net/
// @version 1.3
// @description Tự động điền form đăng chương trên tangthuvien.net với tính năng nâng cao
// @author HA
// @match https://tangthuvien.net/dang-chuong/story/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
// Thêm CSS cho thông báo và nút
const style = document.createElement('style');
style.textContent = `
.ttv-notification {
position: fixed;
top: 20px;
right: 20px;
padding: 10px 20px;
background: #4CAF50;
color: white;
border-radius: 4px;
z-index: 9999;
display: none;
}
.ttv-error {
background: #f44336;
}
.ttv-control-panel {
position: fixed;
top: 50px;
right: 20px;
background: white;
padding: 25px;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
z-index: 9998;
width: 500px;
margin-bottom: 20px;
transition: all 0.3s ease;
}
.ttv-control-panel.minimized {
width: auto;
height: auto;
padding: 10px;
opacity: 0.8;
transform: translateX(calc(100% - 40px));
transition: all 0.3s ease;
}
.ttv-control-panel.minimized:hover {
opacity: 1;
transform: translateX(0);
}
.ttv-control-panel.minimized .ttv-button-group,
.ttv-control-panel.minimized .ttv-header {
display: none;
}
// Điều chỉnh toolbar và các nút điều khiển
.ttv-toolbar {
display: flex;
gap: 6px;
align-items: center;
}
.ttv-toolbar button {
padding: 2px 8px;
font-size: 11px;
color: #555;
background: #f5f5f5;
border: 1px solid #ddd;
border-radius: 3px;
cursor: pointer;
transition: all 0.2s ease;
}
.ttv-toolbar button:hover {
background: #e9e9e9;
transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.ttv-button-group {
display: flex;
flex-direction: column;
gap: 15px;
}
.ttv-file-label {
width: 100%;
padding: 12px;
background: #5bc0de;
color: white;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
text-align: center;
transition: all 0.2s ease;
margin: 0;
}
.ttv-file-label:hover {
background: #46b8da;
transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.ttv-content-editor {
width: 100%;
height: 180px;
margin: 6px 0;
padding: 10px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 13px;
line-height: 1.5;
resize: vertical;
transition: all 0.2s ease;
}
.ttv-content-editor:focus {
border-color: #5bc0de;
outline: none;
box-shadow: 0 0 8px rgba(91,192,222,0.2);
}
.ttv-preview {
display: none;
width: 100%;
height: 180px;
margin: 6px 0;
padding: 10px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 13px;
line-height: 1.5;
overflow-y: auto;
background: #f9f9f9;
transition: all 0.2s ease;
}
.ttv-heading {
font-size: 15px;
color: #555;
margin: 12px 0;
display: flex;
justify-content: space-between;
align-items: center;
}
.ttv-word-count {
font-size: 12px;
color: #888;
padding: 3px 8px;
background: #f5f5f5;
border-radius: 4px;
transition: all 0.2s ease;
}
// Tối ưu chế độ toàn màn hình
.ttv-control-panel.fullscreen {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 0;
z-index: 9999;
padding: 15px;
display: flex;
flex-direction: column;
}
.ttv-control-panel.fullscreen .ttv-content-editor,
.ttv-control-panel.fullscreen .ttv-preview {
height: calc(100vh - 100px);
margin: 4px 0;
font-size: 14px;
}
.ttv-header {
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 2px solid #eee;
font-weight: bold;
font-size: 16px;
color: #444;
display: flex;
justify-content: space-between;
align-items: center;
}
button.btn-warning {
background: #f0ad4e;
color: white;
border: none;
padding: 12px;
border-radius: 6px;
width: 100%;
font-size: 14px;
transition: all 0.2s ease;
}
button.btn-warning:hover {
background: #ec971f;
transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
button.ttv-minimize {
padding: 2px 8px;
background: none;
border: none;
cursor: pointer;
font-size: 16px;
color: #666;
transition: all 0.2s ease;
}
button.ttv-minimize:hover {
color: #333;
}
`;
document.head.appendChild(style);
// Tạo div thông báo
const notification = document.createElement('div');
notification.className = 'ttv-notification';
document.body.appendChild(notification);
// Hiển thị thông báo
function showNotification(message, isError = false) {
notification.textContent = message;
notification.className = 'ttv-notification' + (isError ? ' ttv-error' : '');
notification.style.display = 'block';
setTimeout(() => {
notification.style.display = 'none';
}, 3000);
}
// Đọc nội dung file
function readFileContent(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => resolve(e.target.result);
reader.onerror = (e) => reject(new Error('Lỗi đọc file: ' + e.target.error));
reader.readAsText(file, 'UTF-8');
});
}
// Đếm số từ và ký tự
function updateWordCount(content) {
const wordCount = content.trim().split(/\s+/).length;
const charCount = content.length;
return `${wordCount} từ | ${charCount} ký tự`;
}
// Xử lý khi chọn file
async function handleFileSelect(event) {
try {
const file = event.target.files[0];
if (!file) return;
// Đọc nội dung file
const content = await readFileContent(file);
// Điền vào khung soạn thảo nội dung
const contentEditor = document.querySelector('.ttv-content-editor');
if (contentEditor) {
contentEditor.value = content;
// Cập nhật số từ
const wordCountSpan = document.querySelector('.ttv-word-count');
if (wordCountSpan) {
wordCountSpan.textContent = updateWordCount(content);
}
showNotification('Đã tải nội dung từ file thành công!');
} else {
showNotification('Không tìm thấy khung soạn thảo!', true);
}
} catch (error) {
console.error('Lỗi xử lý file:', error);
showNotification('Có lỗi xảy ra khi đọc file!', true);
}
}
// Chuyển nội dung từ khung soạn thảo sang form
function transferContent() {
const contentEditor = document.querySelector('.ttv-content-editor');
const contentInput = document.querySelector('textarea[name="introduce[1]"]');
if (contentEditor && contentInput) {
contentInput.value = contentEditor.value;
showNotification('Đã chuyển nội dung sang form đăng chương!');
} else {
showNotification('Không tìm thấy form đăng chương!', true);
}
}
// Chuyển đổi giữa chế độ soạn thảo và xem trước
function togglePreview() {
const contentEditor = document.querySelector('.ttv-content-editor');
const preview = document.querySelector('.ttv-preview');
const previewBtn = document.querySelector('.ttv-preview-btn');
if (contentEditor.style.display !== 'none') {
contentEditor.style.display = 'none';
preview.style.display = 'block';
preview.innerHTML = contentEditor.value.replace(/\n/g, '<br>');
previewBtn.textContent = 'Soạn thảo';
} else {
contentEditor.style.display = 'block';
preview.style.display = 'none';
previewBtn.textContent = 'Xem trước';
}
}
// Chuyển đổi chế độ toàn màn hình
function toggleFullscreen() {
const panel = document.querySelector('.ttv-control-panel');
const fullscreenBtn = document.querySelector('.ttv-fullscreen-btn');
panel.classList.toggle('fullscreen');
fullscreenBtn.textContent = panel.classList.contains('fullscreen') ? 'Thu nhỏ' : 'Toàn màn hình';
}
// Thêm panel điều khiển
function addControlPanel() {
// Tạo panel
const panel = document.createElement('div');
panel.className = 'ttv-control-panel';
// Thêm header
const header = document.createElement('div');
header.className = 'ttv-header';
header.innerHTML = `
<div>Soạn Thảo Nội Dung</div>
<div class="ttv-toolbar">
<button class="ttv-preview-btn" onclick="togglePreview()">Xem trước</button>
<button class="ttv-fullscreen-btn" onclick="toggleFullscreen()">Toàn màn hình</button>
<button class="ttv-minimize">−</button>
</div>
`;
// Container cho các nút
const buttonGroup = document.createElement('div');
buttonGroup.className = 'ttv-button-group';
// Input chọn file
const fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.accept = '.txt';
fileInput.className = 'ttv-file-input';
fileInput.id = 'ttv-file-input';
fileInput.onchange = handleFileSelect;
// Label cho input file
const fileLabel = document.createElement('label');
fileLabel.htmlFor = 'ttv-file-input';
fileLabel.className = 'ttv-file-label';
fileLabel.innerHTML = '<span>Chọn file txt chứa nội dung</span>';
// Khung soạn thảo nội dung
const contentEditorLabel = document.createElement('div');
contentEditorLabel.className = 'ttv-heading';
contentEditorLabel.innerHTML = `
Nội dung chương:
<span class="ttv-word-count">0 từ | 0 ký tự</span>
`;
const contentEditor = document.createElement('textarea');
contentEditor.className = 'ttv-content-editor';
contentEditor.placeholder = 'Nhập hoặc dán nội dung chương vào đây...';
// Khung xem trước
const preview = document.createElement('div');
preview.className = 'ttv-preview';
// Cập nhật số từ khi nhập nội dung
contentEditor.oninput = () => {
const wordCountSpan = document.querySelector('.ttv-word-count');
if (wordCountSpan) {
wordCountSpan.textContent = updateWordCount(contentEditor.value);
}
};
// Nút chuyển nội dung
const transferBtn = document.createElement('button');
transferBtn.type = 'button';
transferBtn.className = 'btn btn-warning';
transferBtn.innerHTML = '<span>Chuyển nội dung sang form</span>';
transferBtn.onclick = transferContent;
// Thêm các phần tử vào panel
panel.appendChild(header);
buttonGroup.appendChild(fileInput);
buttonGroup.appendChild(fileLabel);
buttonGroup.appendChild(contentEditorLabel);
buttonGroup.appendChild(contentEditor);
buttonGroup.appendChild(preview);
buttonGroup.appendChild(transferBtn);
panel.appendChild(buttonGroup);
document.body.appendChild(panel);
// Thêm xử lý sự kiện cho các nút trong toolbar
const minimizeBtn = panel.querySelector('.ttv-minimize');
minimizeBtn.onclick = () => {
panel.classList.toggle('minimized');
minimizeBtn.innerHTML = panel.classList.contains('minimized') ? '+' : '−';
};
window.togglePreview = togglePreview;
window.toggleFullscreen = toggleFullscreen;
}
// Thêm control panel khi trang đã load
window.addEventListener('load', function() {
addControlPanel();
});
})();