đéo có hình chó nó tin
Cái nồi có lắp

Cái này chỉ dành cho mấy thằng có kiến thức IT nên tao chỉ nói sơ.
Đầu tiên đăng ký API key Gemini.
Tao chỉ có API key Gemini free nên chỉ test được trên Model gemini-2.0-flash thôi.
Muốn xài API key ChatGPT hay con AI nào khác là ko được.
Và yêu cầu là xài PC, cái này ko dành cho dân ko có kiến thức IT nên tao ko tối ưu cho điện thoại.
- Hướng dẫn sử dụng.
Xài Violentmonkey hoặc Tampermonkey, điền code bên dưới vào, xong rồi vào Quản lý API key điền API key Gemini.
Reply 1 thằng nào đó, rồi chọn Trả lời bằng AI, đợi vài giây để nó lấy kết quả rồi hẵng Post.
Chú ý: Gemini bị block ở Hongkong nên thằng nào xài VPN thì đổi IP qua nước khác nha.
Cãi nhau bằng AI thì thằng đéo nào chơi lại nữa.
Đầu tiên đăng ký API key Gemini.
Tao chỉ có API key Gemini free nên chỉ test được trên Model gemini-2.0-flash thôi.
Muốn xài API key ChatGPT hay con AI nào khác là ko được.
Và yêu cầu là xài PC, cái này ko dành cho dân ko có kiến thức IT nên tao ko tối ưu cho điện thoại.
- Hướng dẫn sử dụng.
Xài Violentmonkey hoặc Tampermonkey, điền code bên dưới vào, xong rồi vào Quản lý API key điền API key Gemini.
JavaScript:
// ==UserScript==
// @name XenForo AI Reply (Gemini API)
// @namespace http://tampermonkey.net/
// @version 4.0
// @description Trả lời bài viết bằng AI Gemini trên XenForo + Quản lý API key & domain trong Violentmonkey menu
// @author Bạn
// @match *://xamvn.nl/*
// @match *://*.xamvn.nl/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @grant GM_xmlhttpRequest
// ==/UserScript==
(function() {
'use strict';
// 🛠️ Load API Key & Model từ storage
let apiKey = GM_getValue('apiKey', '');
let model = GM_getValue('model', 'gemini-2.0-flash');
// 📝 Thêm nút "Trả lời bằng AI" khi reply
function addAIReplyButton() {
// Kiểm tra các container reply phổ biến của XenForo, bao gồm "thread_reply" và các selector khác
let replyContainers = document.querySelectorAll('.message-editorWrapper, .quickReply, [data-template="thread_reply"], .message-reply, .message-userContent');
if (!replyContainers.length) {
console.log("⚠️ Không tìm thấy container reply! Kiểm tra HTML để điều chỉnh selector. Các container đã thử:", document.querySelectorAll('.message-editorWrapper, .quickReply, [data-template="thread_reply"], .message-reply, .message-userContent'));
return;
}
replyContainers.forEach(container => {
if (container.dataset.aiButtonAdded) return;
container.dataset.aiButtonAdded = true;
// Tìm container chứa nút "Gửi đi" để thêm nút AI vào cùng dòng
let submitButton = container.querySelector('.button--primary[type="submit"]');
if (!submitButton) {
console.log("⚠️ Không tìm thấy nút 'Gửi đi' trong container:", container);
return;
}
let submitContainer = submitButton.parentElement;
// Tạo nút "Trả lời bằng AI"
let aiReplyBtn = document.createElement('button');
aiReplyBtn.innerText = 'Trả lời bằng AI';
aiReplyBtn.type = 'button';
aiReplyBtn.style.backgroundColor = '#007bff'; // Màu xanh giống nút "Gửi đi"
aiReplyBtn.style.color = 'white';
aiReplyBtn.style.border = '1px solid #007bff';
aiReplyBtn.style.padding = '5px 15px';
aiReplyBtn.style.borderRadius = '4px';
aiReplyBtn.style.fontSize = 'inherit'; // Kế thừa font từ nút "Gửi đi"
aiReplyBtn.style.cursor = 'pointer';
aiReplyBtn.style.marginRight = '10px'; // Khoảng cách với nút "Gửi đi"
// Đặt nút AI bên trái tận cùng, giữ nút "Gửi đi" bên phải
submitContainer.style.display = 'flex';
submitContainer.style.justifyContent = 'space-between'; // Phân bố nút AI bên trái, "Gửi đi" bên phải
submitContainer.style.paddingLeft = '0'; // Loại bỏ padding bên trái
submitContainer.style.marginLeft = '0'; // Loại bỏ margin bên trái
submitContainer.insertBefore(aiReplyBtn, submitButton);
aiReplyBtn.onclick = function(e) {
e.preventDefault();
let textArea = container.querySelector('textarea');
let richTextEditor = container.querySelector('.fr-element');
if (!textArea && !richTextEditor) {
console.error("⚠️ Không tìm thấy textarea hoặc rich-text editor!");
return;
}
let fullText = textArea ? textArea.value.trim() : richTextEditor.innerHTML.trim();
if (!fullText) {
alert('⚠️ Bạn chưa nhập nội dung để AI trả lời!');
return;
}
// Lọc chỉ lấy nội dung reply, bỏ phần quote
let replyText = extractReplyContent(fullText);
if (!replyText) {
alert('⚠️ Bạn chưa nhập nội dung reply riêng, chỉ có quote!');
return;
}
generateAIReply(replyText, textArea, richTextEditor);
};
});
}
// Hàm lọc nội dung reply, bỏ phần quote
function extractReplyContent(fullText) {
// Xóa các đoạn [QUOTE] và nội dung bên trong
let replyText = fullText.replace(/\[QUOTE="[^"]+", post: \d+\][\s\S]*?\[\/QUOTE\]/gi, '').trim();
// Xóa các thẻ HTML nếu có (rich-text mode)
replyText = replyText.replace(/<[^>]+>/g, '').trim();
return replyText;
}
// 🤖 Gửi API request đến Gemini để tạo câu trả lời
function generateAIReply(replyText, textArea, richTextEditor) {
if (!apiKey) {
alert('❌ Bạn chưa nhập API Key! Vào cài đặt để nhập.');
return;
}
if (!textArea && !richTextEditor) {
alert('❌ Không tìm thấy ô nhập văn bản để hiển thị kết quả!');
return;
}
// Chỉ yêu cầu AI trả lời hoàn toàn bằng tiếng Việt
let apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${apiKey}`;
let requestData = {
contents: [
{
role: "user",
parts: [{ text: "hello test" }]
},
{
role: "model",
parts: [{ text: "Xin chào! Tôi sẽ trả lời hoàn toàn bằng tiếng Việt, không sử dụng bất kỳ ngôn ngữ nào khác. Làm sao tôi có thể giúp bạn hôm nay?\n" }]
},
{
role: "user",
parts: [{ text: replyText + "\nVui lòng chỉ trả lời hoàn toàn bằng tiếng Việt, không sử dụng bất kỳ ngôn ngữ nào khác." }]
}
],
generationConfig: {
temperature: 1,
topK: 40,
topP: 0.95,
maxOutputTokens: 8192,
responseMimeType: "text/plain"
}
};
GM_xmlhttpRequest({
method: 'POST',
url: apiUrl,
headers: {
'Content-Type': 'application/json'
},
data: JSON.stringify(requestData),
onload: function(response) {
console.log("🔹 API Response:", response.responseText);
let json = JSON.parse(response.responseText);
let aiReply = json.candidates?.[0]?.content?.parts?.[0]?.text || '';
if (aiReply) {
console.log("🔍 Nội dung AI:", aiReply);
let currentContent = textArea ? textArea.value : (richTextEditor ? richTextEditor.innerHTML : '');
let newContent = currentContent + (currentContent ? '\n\n' : '') + aiReply;
if (richTextEditor) {
richTextEditor.innerHTML = newContent.replace(/\n/g, '<br>');
if (typeof $ !== 'undefined' && $(richTextEditor).data('froala.editor')) {
$(richTextEditor).froalaEditor('html.set', newContent.replace(/\n/g, '<br>'));
}
richTextEditor.dispatchEvent(new Event('input', { bubbles: true }));
} else if (textArea) {
textArea.value = newContent;
textArea.dispatchEvent(new Event('input', { bubbles: true }));
}
} else {
console.error("⚠️ Lỗi từ API Gemini:", json);
alert('⚠️ Lỗi AI không trả lời được! Kiểm tra API Key hoặc quota.');
}
},
onerror: function(error) {
console.error("❌ Lỗi kết nối API:", error);
alert('❌ Lỗi kết nối API Gemini!');
}
});
}
// 🚀 Đăng ký menu "Quản lý API key" trong Violentmonkey
GM_registerMenuCommand("⚙️ Quản lý API key", function() {
let newApiKey = prompt("Nhập API Key:", apiKey);
if (newApiKey !== null) {
GM_setValue('apiKey', newApiKey.trim());
alert("✅ API Key đã được lưu!");
}
});
// 🚀 Khởi chạy script
function init() {
addAIReplyButton();
// Thêm observer để bắt các thay đổi động (như "Reply to thread")
const observer = new MutationObserver(() => {
addAIReplyButton();
});
observer.observe(document.body, { childList: true, subtree: true });
// Thêm event listener cho nút "Reply" để kích hoạt lại khi bấm
const replyButtons = document.querySelectorAll('.actionBar-action.actionBar-action--reply');
replyButtons.forEach(button => {
button.addEventListener('click', () => {
setTimeout(addAIReplyButton, 1000); // Tăng thời gian chờ lên 1000ms để nội dung tải xong
});
});
// Theo dõi các nút "Reply" mới được thêm động
const buttonObserver = new MutationObserver(() => {
const newReplyButtons = document.querySelectorAll('.actionBar-action.actionBar-action--reply');
newReplyButtons.forEach(button => {
if (!button.dataset.eventAdded) {
button.dataset.eventAdded = true;
button.addEventListener('click', () => {
setTimeout(addAIReplyButton, 1000); // Tăng thời gian chờ lên 1000ms để nội dung tải xong
});
}
});
});
buttonObserver.observe(document.body, { childList: true, subtree: true });
}
// Gọi hàm init khi trang tải
init();
// Dừng observer khi không cần thiết (nếu muốn)
window.addEventListener('unload', () => {
observer.disconnect();
if (buttonObserver) buttonObserver.disconnect();
});
})();
Reply 1 thằng nào đó, rồi chọn Trả lời bằng AI, đợi vài giây để nó lấy kết quả rồi hẵng Post.
Chú ý: Gemini bị block ở Hongkong nên thằng nào xài VPN thì đổi IP qua nước khác nha.
Cãi nhau bằng AI thì thằng đéo nào chơi lại nữa.
Sửa lần cuối: