// ==UserScript==
// @name dcms论坛增强插件
// @namespace http://3g.cx/
// @version 3.5
// @description 为dcms论坛提供多种增强功能,提升用户体验,集成AI助手
// @author 42hz,pulana
// @match https://3g.cx/*
// @match http://3g.cx/*
// @grant GM_addStyle
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
// @grant GM_listValues
// @grant GM_xmlhttpRequest
// @grant GM_registerMenuCommand
// @run-at document-start
// @require https://code.jquery.com/jquery-3.6.0.min.js
// ==/UserScript==
(function() {
'use strict';
// 初始化配置
function initializeConfig() {
// 初始化默认配置
const defaultConfig = {
apiUrl: 'https://apis.iflow.cn/v1/chat/completions',
apiKey: '',
customApiEnabled: false,
modelId: 'tstars2.0',
maxTokens: 512,
temperature: 0.7,
topP: 0.7,
topK: 50,
frequencyPenalty: 0.5,
aiLongTermMemory: [],
aiContext: [],
aiMemoryLimit: 10,
highlightOwn: true,
hideOldMessages: false,
autoRefreshChat: false,
refreshInterval: 30,
blockedUsers: [],
nightMode: false
};
if (GM_getValue('config', null) === null) {
GM_setValue('config', defaultConfig);
}
}
// 获取配置
function getConfig() {
const config = GM_getValue('config', {
apiUrl: 'https://apis.iflow.cn/v1/chat/completions',
apiKey: '',
customApiEnabled: false,
modelId: 'tstars2.0',
maxTokens: 512,
temperature: 0.7,
topP: 0.7,
topK: 50,
frequencyPenalty: 0.5,
aiLongTermMemory: [],
aiContext: [],
aiMemoryLimit: 10,
highlightOwn: true,
hideOldMessages: false,
autoRefreshChat: false,
refreshInterval: 30,
blockedUsers: [],
nightMode: false
});
// 确保数组字段存在
if (!Array.isArray(config.aiLongTermMemory)) {
config.aiLongTermMemory = [];
}
if (!Array.isArray(config.aiContext)) {
config.aiContext = [];
}
return config;
}
// 保存配置
function saveConfig(config) {
GM_setValue('config', config);
}
// 检查jQuery是否已加载
function waitForJQuery() {
if (typeof $ !== 'undefined') {
initialize();
} else {
setTimeout(waitForJQuery, 100);
}
}
// 初始化脚本
function initialize() {
initializeConfig();
// 添加全局样式
addGlobalStyles();
// 添加导航栏快捷功能
addQuickFeatures();
// 添加论坛页面增强功能
if (window.location.href.includes('/forum/')) {
enhanceForum();
}
// 添加聊天室增强功能
if (window.location.href.includes('/chat/')) {
enhanceChat();
}
// 添加日记页面增强功能
if (window.location.href.includes('/plugins/notes/')) {
enhanceNotes();
}
// 添加留言板增强功能
if (window.location.href.includes('/guest/')) {
enhanceGuestbook();
}
// 添加用户页面增强功能
if (window.location.href.includes('/user/info.php')) {
enhanceUserProfile();
}
// 添加快速搜索功能
addQuickSearch();
// 添加夜间模式切换
addNightMode();
// 添加一键清空浏览历史功能
addClearHistoryButton();
// 添加AI助手功能
addAIAssistant();
// 添加页面加载完成后的处理
$(document).ready(function() {
// 应用已保存的设置
applySavedSettings();
// 添加页面特定功能
addPageSpecificFeatures();
});
}
// 添加全局样式
function addGlobalStyles() {
GM_addStyle(`
/* 全局增强样式 */
.gm-enhancement-panel {
background: #f0f0f0;
border: 1px solid #ccc;
padding: 10px;
margin: 10px 0;
border-radius: 5px;
}
.gm-btn {
background: #007cba;
color: white;
border: none;
padding: 5px 10px;
margin: 0 2px;
border-radius: 3px;
cursor: pointer;
font-size: 12px;
}
.gm-btn:hover {
background: #005a87;
}
.gm-btn-danger {
background: #d9534f;
}
.gm-btn-danger:hover {
background: #c9302c;
}
.gm-btn-success {
background: #5cb85c;
}
.gm-btn-success:hover {
background: #449d44;
}
.gm-btn-warning {
background: #f0ad4e;
}
.gm-btn-warning:hover {
background: #ec971f;
}
.gm-btn-config {
background: #5bc0de;
}
.gm-btn-config:hover {
background: #31b0d5;
}
.gm-night-mode {
background-color: #2c2c2c !important;
color: #e0e0e0 !important;
}
.gm-night-mode a {
color: #64b5f6 !important;
}
.gm-night-mode input, .gm-night-mode textarea {
background-color: #424242 !important;
color: #e0e0e0 !important;
border: 1px solid #666 !important;
}
.gm-night-mode table {
border-color: #666 !important;
}
.gm-night-mode .gm-enhancement-panel {
background: #3c3c3c;
border-color: #666;
}
.gm-quick-actions {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 9999;
}
.gm-quick-action-btn {
display: block;
width: 40px;
height: 40px;
background: #007cba;
color: white;
border-radius: 50%;
text-align: center;
line-height: 40px;
margin: 5px 0;
text-decoration: none;
box-shadow: 0 2px 10px rgba(0,0,0,0.3);
cursor: pointer;
}
.gm-quick-action-btn:hover {
background: #005a87;
}
.gm-search-box {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 10000;
background: white;
padding: 15px;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0,0,0,0.3);
display: none;
width: 90%;
max-width: 500px;
max-height: 80vh;
overflow-y: auto;
}
.gm-night-mode .gm-search-box {
background: #3c3c3c;
color: #e0e0e0;
}
.gm-hidden-content {
display: none !important;
}
.gm-highlighted {
background-color: #e6f3ff !important;
border: 2px solid #007cba !important;
}
.gm-night-mode .gm-highlighted {
background-color: #1a237e !important;
border: 2px solid #64b5f6 !important;
}
.gm-ai-assistant {
position: fixed;
bottom: 20px;
left: 20px;
z-index: 9999;
width: 300px;
background: white;
border: 1px solid #ccc;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0,0,0,0.3);
display: none;
}
.gm-night-mode .gm-ai-assistant {
background: #3c3c3c;
border-color: #666;
}
.gm-ai-header {
background: #007cba;
color: white;
padding: 10px;
border-radius: 8px 8px 0 0;
cursor: move;
}
.gm-night-mode .gm-ai-header {
background: #005a87;
}
.gm-ai-content {
padding: 10px;
max-height: 200px;
overflow-y: auto;
}
.gm-ai-input {
width: calc(100% - 20px);
padding: 5px;
margin: 10px 0;
}
.gm-ai-message {
margin: 5px 0;
padding: 5px;
border-radius: 5px;
}
.gm-ai-user {
background: #e6f3ff;
text-align: right;
}
.gm-night-mode .gm-ai-user {
background: #1a237e;
}
.gm-ai-assistant-response {
background: #f0f0f0;
}
.gm-night-mode .gm-ai-assistant-response {
background: #424242;
}
.gm-ai-typing {
font-style: italic;
color: #888;
}
.gm-night-mode .gm-ai-typing {
color: #aaa;
}
.gm-api-error {
color: #d9534f;
font-weight: bold;
}
.gm-api-success {
color: #5cb85c;
font-weight: bold;
}
.gm-search-highlight {
background-color: yellow !important;
font-weight: bold;
}
.gm-ai-config-panel {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: white;
border: 1px solid #ccc;
border-radius: 8px;
padding: 15px;
margin: 10px 0;
box-shadow: 0 4px 20px rgba(0,0,0,0.3);
z-index: 10001;
width: 90%;
max-width: 400px;
max-height: 80vh;
overflow-y: auto;
}
.gm-night-mode .gm-ai-config-panel {
background: #3c3c3c;
border-color: #666;
}
.gm-ai-memory-item {
padding: 5px;
margin: 5px 0;
border: 1px solid #ddd;
border-radius: 3px;
word-wrap: break-word;
}
.gm-night-mode .gm-ai-memory-item {
border-color: #666;
}
.gm-ai-memory-controls {
margin-top: 10px;
padding-top: 10px;
border-top: 1px solid #ddd;
}
.gm-night-mode .gm-ai-memory-controls {
border-top: 1px solid #666;
}
.gm-ai-advanced-settings {
margin: 10px 0;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
}
.gm-night-mode .gm-ai-advanced-settings {
border-color: #666;
}
.gm-ai-tool-call {
background: #e8f4f8;
border-left: 3px solid #007cba;
padding: 5px;
margin: 5px 0;
font-size: 12px;
}
.gm-night-mode .gm-ai-tool-call {
background: #1a237e;
border-left: 3px solid #64b5f6;
}
`);
}
// 添加导航栏快捷功能
function addQuickFeatures() {
$(document).ready(function() {
// 添加快速导航按钮
if ($('.gm-enhancement-panel').length === 0) {
const quickPanel = `
DCMS增强功能:
`;
$('body').prepend(quickPanel);
// 绑定快速导航事件
$('#gm-go-home').click(function() { window.location.href = '/'; });
$('#gm-go-forum').click(function() { window.location.href = '/forum/'; });
$('#gm-go-chat').click(function() { window.location.href = '/chat/'; });
$('#gm-go-notes').click(function() { window.location.href = '/plugins/notes/'; });
$('#gm-go-guest').click(function() { window.location.href = '/guest/'; });
$('#gm-go-downloads').click(function() { window.location.href = '/down/'; });
$('#gm-go-users').click(function() { window.location.href = '/user/users.php'; });
$('#gm-go-night-mode').click(function() { toggleNightMode(); });
$('#gm-go-settings').click(function() { showSettingsPanel(); });
$('#gm-go-ai-assistant').click(function() { toggleAIAssistant(); });
}
});
}
// 增强论坛页面功能
function enhanceForum() {
$(document).ready(function() {
const config = getConfig();
// 添加快速发帖按钮
const quickPostBtn = `
`;
// 找到合适的插入位置
const container = $('body').find('table').first();
if (container.length > 0) {
container.before(quickPostBtn);
} else {
$('body').prepend(quickPostBtn);
}
// 绑定事件
$('#gm-new-topic').click(function() {
window.location.href = '/forum/new_t.php';
});
$('#gm-expand-all-posts').click(function() {
// 展开所有帖子内容(模拟点击"»"链接)
$('a:contains("»")').each(function() {
if (!$(this).hasClass('gm-expanded')) {
$(this).addClass('gm-expanded');
// 显示可能被隐藏的内容
$(this).closest('div').nextAll().show();
}
});
});
$('#gm-collapse-all-posts').click(function() {
$('.gm-expanded').removeClass('gm-expanded');
$('a:contains("»")').closest('div').nextAll().hide();
});
$('#gm-filter-by-user').click(function() {
const username = $('#gm-user-filter-input').val();
if (username) {
filterPostsByUser(username);
}
});
$('#gm-highlight-own').click(function() {
config.highlightOwn = !config.highlightOwn;
saveConfig(config);
if (config.highlightOwn) {
$(this).addClass('gm-btn-success');
highlightOwnPosts();
} else {
$(this).removeClass('gm-btn-success');
$('.gm-highlighted').removeClass('gm-highlighted');
}
});
// 添加帖子列表增强功能
addForumListEnhancements();
// 如果设置了自动高亮,应用它
if (config.highlightOwn) {
setTimeout(highlightOwnPosts, 500);
}
});
}
// 高亮自己的帖子
function highlightOwnPosts() {
const username = getCurrentUsername();
if (username) {
// 查找所有包含用户名的元素,并高亮其最近的容器
$('a, span, div, p').each(function() {
if ($(this).text().includes(username) && !$(this).parents('.gm-hidden-content').length) {
const container = $(this).closest('div, table, tr, p').first();
if (container.length > 0) {
container.addClass('gm-highlighted');
} else {
$(this).addClass('gm-highlighted');
}
}
});
}
}
// 获取当前用户名
function getCurrentUsername() {
// 检查页面中可能包含用户名的元素
const usernamePatterns = [
// 检查退出按钮附近的用户名
$('a:contains("退出")').siblings('a').first(),
// 检查顶部用户链接
$('a[href*="/user/info.php"]').first(),
// 检查页面顶部的其他用户相关信息
$('.user-info a').first(),
// 检查页面顶部导航
$('nav a[href*="/user/info.php"]').last()
];
for (let i = 0; i < usernamePatterns.length; i++) {
if (usernamePatterns[i] && usernamePatterns[i].length > 0) {
const text = usernamePatterns[i].text().trim();
if (text && text.length > 0 && text.length < 30 &&
!text.includes('用户') && !text.includes('退出') && !text.includes('登录') && !text.includes('注册')) {
return text;
}
}
}
return null;
}
// 过滤特定用户的帖子
function filterPostsByUser(username) {
// 先显示所有内容
$('.gm-hidden-content').removeClass('gm-hidden-content');
// 遍历所有可能包含帖子信息的容器
$('body').find('div, table, tr, p').each(function() {
const elem = $(this);
if (elem.text().includes(username)) {
// 包含目标用户名,保留
elem.removeClass('gm-hidden-content');
} else {
// 检查是否包含用户链接
let hasTargetUser = false;
elem.find('a').each(function() {
if ($(this).attr('href') && $(this).attr('href').includes('/user/info.php?id=')) {
if ($(this).text().includes(username)) {
hasTargetUser = true;
}
}
});
if (!hasTargetUser) {
elem.addClass('gm-hidden-content');
} else {
elem.removeClass('gm-hidden-content');
}
}
});
}
// 增强论坛列表页面
function addForumListEnhancements() {
$(document).ready(function() {
// 添加一键复制帖子链接功能
$('a[href*="/forum/"]').each(function() {
if ($(this).attr('href').match(/\/forum\/\d+\/\d+\/\d+\//)) {
const link = $(this).attr('href');
const postId = extractPostId(link);
if (postId) {
const copyBtn = ``;
$(this).after(copyBtn);
}
}
});
// 绑定复制链接事件
$(document).on('click', '.gm-copy-link', function() {
const link = $(this).data('link');
navigator.clipboard.writeText(window.location.origin + link);
alert('链接已复制到剪贴板!');
});
});
}
// 提取帖子ID
function extractPostId(url) {
const match = url.match(/\/forum\/\d+\/\d+\/(\d+)\//);
return match ? match[1] : null;
}
// 增强聊天室功能
function enhanceChat() {
$(document).ready(function() {
const config = getConfig();
// 添加聊天室增强功能
const chatEnhancement = `
聊天室增强功能:
`;
$('body').prepend(chatEnhancement);
// 绑定事件
$('#gm-chat-refresh').click(function() {
location.reload();
});
$('#gm-chat-auto-refresh').click(function() {
config.autoRefreshChat = !config.autoRefreshChat;
saveConfig(config);
if (config.autoRefreshChat) {
$(this).addClass('gm-btn-success').text('停止刷新');
startAutoRefresh();
} else {
$(this).removeClass('gm-btn-success').text('自动刷新');
stopAutoRefresh();
}
});
$('#gm-chat-filter').click(function() {
const keyword = $('#gm-chat-filter-input').val();
if (keyword) {
filterChatMessages(keyword);
}
});
$('#gm-chat-highlight-own').click(function() {
config.highlightOwn = !config.highlightOwn;
saveConfig(config);
if (config.highlightOwn) {
$(this).addClass('gm-btn-success');
highlightOwnChatMessages();
} else {
$(this).removeClass('gm-btn-success');
$('.gm-highlighted').removeClass('gm-highlighted');
}
});
$('#gm-chat-hide-old').click(function() {
config.hideOldMessages = !config.hideOldMessages;
saveConfig(config);
if (config.hideOldMessages) {
$(this).addClass('gm-btn-success');
// 隐藏较早的消息(保留最新的50条)
const allMessages = $('body').find('a[href*="/chat/room/"]').closest('div, p');
if (allMessages.length > 50) {
allMessages.slice(0, allMessages.length - 50).addClass('gm-hidden-content');
}
} else {
$(this).removeClass('gm-btn-success');
$('.gm-hidden-content').removeClass('gm-hidden-content');
}
});
// 如果开启了自动刷新,启动定时器
if (config.autoRefreshChat) {
startAutoRefresh();
$('#gm-chat-auto-refresh').addClass('gm-btn-success').text('停止刷新');
}
// 如果设置了自动高亮,应用它
if (config.highlightOwn) {
setTimeout(highlightOwnChatMessages, 500);
}
});
}
// 启动自动刷新
function startAutoRefresh() {
const config = getConfig();
stopAutoRefresh(); // 先停止之前的定时器
window.chatRefreshInterval = setInterval(function() {
location.reload();
}, config.refreshInterval * 1000);
}
// 停止自动刷新
function stopAutoRefresh() {
if (window.chatRefreshInterval) {
clearInterval(window.chatRefreshInterval);
window.chatRefreshInterval = null;
}
}
// 高亮聊天室中自己的消息
function highlightOwnChatMessages() {
const username = getCurrentUsername();
if (username) {
$('a, span, div, p').each(function() {
if ($(this).text().includes(username) && !$(this).parents('.gm-hidden-content').length) {
const container = $(this).closest('div, p').first();
if (container.length > 0) {
container.addClass('gm-highlighted');
} else {
$(this).addClass('gm-highlighted');
}
}
});
}
}
// 过滤聊天消息
function filterChatMessages(keyword) {
// 先显示所有内容
$('.gm-hidden-content').removeClass('gm-hidden-content');
$('body').find('a, div, span, p').each(function() {
if ($(this).text().toLowerCase().includes(keyword.toLowerCase())) {
// 包含关键词的消息保留
$(this).closest('div, p').removeClass('gm-hidden-content');
} else {
// 不包含关键词的消息隐藏
$(this).closest('div, p').addClass('gm-hidden-content');
}
});
}
// 增强日记页面功能
function enhanceNotes() {
$(document).ready(function() {
// 添加日记增强功能
const notesEnhancement = `
日记增强功能:
`;
$('body').prepend(notesEnhancement);
// 修正写日记按钮的链接
$('#gm-new-note').click(function() {
window.location.href = '/plugins/notes/add.php';
});
// 绑定事件
$('#gm-notes-filter').click(function() {
const user = $('#gm-notes-user-filter').val();
if (user) {
filterNotesByUser(user);
}
});
$('#gm-notes-search').click(function() {
const keyword = $('#gm-notes-search-input').val();
if (keyword) {
searchNotes(keyword);
}
});
$('#gm-notes-highlight-own').click(function() {
highlightOwnNotes();
});
});
}
// 过滤指定用户的日记
function filterNotesByUser(username) {
// 先显示所有内容
$('.gm-hidden-content').removeClass('gm-hidden-content');
// 为每个日志条目检查是否包含指定用户名
$('body').find('a').each(function() {
const link = $(this);
if (link.attr('href') && link.attr('href').includes('/user/info.php')) {
if (link.text().includes(username)) {
// 找到包含用户名的用户链接,显示其相关内容
const container = link.closest('div, p, table').first();
if (container.length > 0) {
container.removeClass('gm-hidden-content');
}
} else {
// 不包含用户名的用户链接,检查是否需要隐藏
const container = link.closest('div, p, table').first();
if (container.length > 0) {
container.addClass('gm-hidden-content');
}
}
}
});
}
// 搜索日记内容(页面内搜索)
function searchNotes(keyword) {
if (!keyword) return;
// 先移除之前的高亮和隐藏
$('.gm-search-highlight').removeClass('gm-search-highlight');
$('.gm-hidden-content').removeClass('gm-hidden-content');
let foundAny = false;
// 在页面中搜索关键词
$('body').find('a, div, p, span').each(function() {
const element = $(this);
const text = element.text();
if (text.toLowerCase().includes(keyword.toLowerCase())) {
// 高亮包含关键词的元素
element.addClass('gm-search-highlight');
foundAny = true;
// 确保包含关键词的容器可见
const container = element.closest('div, p, table');
if (container.length > 0) {
container.removeClass('gm-hidden-content');
}
}
});
// 如果没有找到结果,显示提示
if (!foundAny) {
alert(`未找到包含"${keyword}"的内容`);
}
}
// 高亮自己的日记
function highlightOwnNotes() {
const username = getCurrentUsername();
if (username) {
$('body').find('a, span, div, p').each(function() {
if ($(this).text().includes(username) &&
!$(this).parents('.gm-hidden-content').length &&
($(this).closest('div, p').find('a[href*="/plugins/notes/list.php"]').length > 0 ||
$(this).closest('div, p').find('a[href*="/user/info.php"]').length > 0)) {
const container = $(this).closest('div, p').first();
if (container.length > 0) {
container.addClass('gm-highlighted');
} else {
$(this).addClass('gm-highlighted');
}
}
});
}
}
// 增强留言板功能
function enhanceGuestbook() {
$(document).ready(function() {
const config = getConfig();
// 添加留言板增强功能
const guestbookEnhancement = `
留言板增强功能:
`;
$('body').prepend(guestbookEnhancement);
// 绑定事件
$('#gm-guest-hide-replies').click(function() {
hideOwnReplies();
});
$('#gm-guest-highlight').click(function() {
config.highlightOwn = !config.highlightOwn;
saveConfig(config);
if (config.highlightOwn) {
$(this).addClass('gm-btn-success');
highlightOwnGuestbookMessages();
} else {
$(this).removeClass('gm-btn-success');
$('.gm-highlighted').removeClass('gm-highlighted');
}
});
$('#gm-guest-filter-users').click(function() {
const user = $('#gm-guest-filter-user').val();
if (user) {
filterGuestbookByUser(user);
}
});
$('#gm-guest-refresh').click(function() {
location.reload();
});
// 如果启用了相关功能,立即应用
if (config.highlightOwn) {
setTimeout(highlightOwnGuestbookMessages, 500);
}
});
}
// 隐藏自己的回复
function hideOwnReplies() {
const username = getCurrentUsername();
if (username) {
$('body').find('a, span, div, p').each(function() {
if ($(this).text().includes(username) && !$(this).parents('.gm-hidden-content').length) {
// 找到包含用户留言的容器并隐藏
const container = $(this).closest('div, p').first();
if (container.length > 0) {
container.addClass('gm-hidden-content');
}
}
});
}
}
// 高亮留言板中的自己的留言
function highlightOwnGuestbookMessages() {
const username = getCurrentUsername();
if (username) {
$('body').find('a, span, div, p').each(function() {
if ($(this).text().includes(username) && !$(this).parents('.gm-hidden-content').length) {
const container = $(this).closest('div, p').first();
if (container.length > 0) {
container.addClass('gm-highlighted');
} else {
$(this).addClass('gm-highlighted');
}
}
});
}
}
// 过滤留言板中的指定用户
function filterGuestbookByUser(username) {
// 先显示所有内容
$('.gm-hidden-content').removeClass('gm-hidden-content');
let foundUserEntries = false;
$('body').find('a').each(function() {
const link = $(this);
if (link.attr('href') && link.attr('href').includes('/user/info.php')) {
if (link.text().includes(username)) {
// 找到指定用户名,显示其留言
const container = link.closest('div, p, table').first();
if (container.length > 0) {
container.removeClass('gm-hidden-content');
foundUserEntries = true;
}
} else {
// 不是目标用户,隐藏其留言
const container = link.closest('div, p, table').first();
if (container.length > 0) {
container.addClass('gm-hidden-content');
}
}
}
});
if (!foundUserEntries) {
alert(`未找到用户"${username}"的留言`);
}
}
// 增强用户个人页面
function enhanceUserProfile() {
$(document).ready(function() {
// 添加用户页面增强功能
const profileEnhancement = `
用户页面增强功能:
`;
$('body').prepend(profileEnhancement);
// 绑定事件
$('#gm-profile-send-msg').click(function() {
const userId = getParameterByName('id');
if (userId) {
window.location.href = `/user/mail.php?id=${userId}`;
} else {
alert('无法获取用户ID');
}
});
$('#gm-profile-block-user').click(function() {
const userId = getParameterByName('id');
if (userId) {
if (confirm('确定要屏蔽此用户吗?')) {
const config = getConfig();
if (!config.blockedUsers.includes(userId)) {
config.blockedUsers.push(userId);
saveConfig(config);
alert('用户已屏蔽');
} else {
alert('用户已在屏蔽列表中');
}
}
} else {
alert('无法获取用户ID');
}
});
});
}
// 添加快速搜索功能
function addQuickSearch() {
const searchBox = `
`;
$('body').append(searchBox);
// 添加搜索按钮
const searchBtn = `
🔍
`;
$('body').append(`${searchBtn}
`);
// 绑定事件
$('#gm-search-trigger').click(function() {
$('#gm-quick-search').show();
$('#gm-search-input').focus();
});
$('#gm-search-close').click(function() {
$('#gm-quick-search').hide();
});
$('#gm-search-submit').click(function() {
const query = $('#gm-search-input').val();
const type = $('#gm-search-type').val();
if (query) {
performSearch(query, type);
}
});
// 回车键搜索
$('#gm-search-input').keypress(function(e) {
if (e.which === 13) {
$('#gm-search-submit').click();
}
});
}
// 执行搜索
function performSearch(query, type) {
const resultsDiv = $('#gm-search-results');
resultsDiv.html('搜索中...
');
switch(type) {
case 'forum':
window.location.href = `/forum/search.php?search=${encodeURIComponent(query)}`;
break;
case 'notes':
// 在当前页面搜索日记
resultsDiv.html(`已在当前日记页面执行搜索,请使用页面上的搜索功能。
`);
break;
case 'users':
window.location.href = `/user/users.php?search=${encodeURIComponent(query)}`;
break;
case 'guest':
// 在当前页面搜索留言板
resultsDiv.html(`已在当前留言板页面执行搜索,请使用页面上的搜索功能。
`);
break;
case 'ai':
queryAI(query, (response) => {
resultsDiv.html(`${response}
`);
});
break;
}
}
// 添加夜间模式
function addNightMode() {
const config = getConfig();
if (config.nightMode) {
toggleNightMode(true);
}
}
// 切换夜间模式
function toggleNightMode(forceOn = null) {
const config = getConfig();
const isOn = forceOn !== null ? forceOn : !config.nightMode;
config.nightMode = isOn;
saveConfig(config);
if (isOn) {
$('body').addClass('gm-night-mode');
} else {
$('body').removeClass('gm-night-mode');
}
}
// 添加一键清空浏览历史功能
function addClearHistoryButton() {
// 添加到快速操作面板
const clearBtn = `
🗑️
`;
$('.gm-quick-actions').append(clearBtn);
$('#gm-clear-history').click(function() {
if (confirm('确定要清空浏览历史记录吗?')) {
// 清空GM值中的浏览历史相关数据
const keys = GM_listValues();
for (let i = 0; i < keys.length; i++) {
if (keys[i].includes('history') || keys[i].includes('visited')) {
GM_deleteValue(keys[i]);
}
}
alert('浏览历史已清空');
}
});
}
// 显示设置面板
function showSettingsPanel() {
const config = getConfig();
const settingsPanel = `
`;
// 移除现有的设置面板(如果存在)
$('#gm-settings-panel').remove();
$('body').append(settingsPanel);
// 绑定事件
$('#gm-settings-save').click(function() {
const newConfig = getConfig();
newConfig.nightMode = $('#gm-setting-night-mode').is(':checked');
newConfig.autoRefreshChat = $('#gm-setting-auto-refresh').is(':checked');
newConfig.refreshInterval = parseInt($('#gm-setting-refresh-interval').val()) || 30;
newConfig.highlightOwn = $('#gm-setting-highlight-own').is(':checked');
newConfig.hideOldMessages = $('#gm-setting-hide-old').is(':checked');
const blockedUsers = $('#gm-setting-blocked-users').val().split(',').map(id => id.trim()).filter(id => id);
newConfig.blockedUsers = blockedUsers;
saveConfig(newConfig);
// 应用新的设置
if (newConfig.nightMode !== config.nightMode) {
toggleNightMode(newConfig.nightMode);
}
if (newConfig.autoRefreshChat !== config.autoRefreshChat) {
if (newConfig.autoRefreshChat) {
startAutoRefresh();
} else {
stopAutoRefresh();
}
}
alert('设置已保存,部分设置需刷新页面生效');
});
$('#gm-settings-reset').click(function() {
if (confirm('确定要重置所有设置吗?')) {
GM_deleteValue('config');
initializeConfig();
alert('设置已重置,刷新页面生效');
location.reload();
}
});
$('#gm-settings-close').click(function() {
$('#gm-settings-panel').remove();
});
}
// 应用已保存的设置
function applySavedSettings() {
const config = getConfig();
// 应用夜间模式
if (config.nightMode) {
$('body').addClass('gm-night-mode');
}
// 应用自动刷新
if (config.autoRefreshChat && window.location.href.includes('/chat/')) {
startAutoRefresh();
}
}
// 添加页面特定功能
function addPageSpecificFeatures() {
// 在论坛帖子页面添加AI助手按钮
if (window.location.href.match(/\/forum\/\d+\/\d+\/\d+\//)) {
const postContent = $('body').find('div, p').filter(function() {
return $(this).text().length > 50; // 找到可能的帖子内容
}).first();
if (postContent.length > 0) {
const aiAnalyzeBtn = `
`;
postContent.before(aiAnalyzeBtn);
$('#gm-ai-analyze-post').click(function() {
const postText = postContent.text().substring(0, 500); // 限制长度
if (postText.length > 10) {
queryAI(`请分析以下帖子内容:${postText}`, (response) => {
showAIResponse(`AI分析结果:\n${response}`);
});
}
});
}
}
}
// 添加AI助手功能
function addAIAssistant() {
const config = getConfig();
const aiAssistant = `
`;
$('body').append(aiAssistant);
// 绑定AI助手事件
$('#gm-ai-send').click(function() {
const question = $('#gm-ai-input').val().trim();
if (question) {
addAIUserMessage(question);
$('#gm-ai-input').val('');
// 获取当前页面内容作为上下文
const pageContent = getCurrentPageContent();
queryAIWithContext(question, pageContent, (response) => {
addAIResponseMessage(response);
// 更新上下文
const config = getConfig();
config.aiContext.push({
question: question,
response: response,
timestamp: new Date().toISOString(),
pageUrl: window.location.href
});
// 限制上下文长度
if (config.aiContext.length > config.aiMemoryLimit) {
config.aiContext = config.aiContext.slice(-config.aiMemoryLimit);
}
saveConfig(config);
});
}
});
$('#gm-ai-config').click(function() {
showAIConfigPanel();
});
$('#gm-ai-close').click(function() {
$('#gm-ai-assistant').hide();
});
$('#gm-ai-clear').click(function() {
$('#gm-ai-content').html('对话已清空
');
// 清空上下文
const config = getConfig();
config.aiContext = [];
saveConfig(config);
});
// 回车键发送
$('#gm-ai-input').keypress(function(e) {
if (e.which === 13) {
$('#gm-ai-send').click();
}
});
// 拖拽功能
dragElement(document.getElementById('gm-ai-assistant'), document.querySelector('#gm-ai-assistant .gm-ai-header'));
}
// 显示AI配置面板
function showAIConfigPanel() {
const config = getConfig();
const configPanel = `
`;
// 移除现有的配置面板(如果存在)
$('#gm-ai-config-panel').remove();
$('body').append(configPanel);
// 绑定事件
$('#gm-ai-config-save').click(function() {
const newConfig = getConfig();
newConfig.customApiEnabled = $('#gm-ai-custom-api').is(':checked');
newConfig.apiUrl = $('#gm-ai-api-url').val();
newConfig.apiKey = $('#gm-ai-api-key').val();
newConfig.modelId = $('#gm-ai-model-id').val();
newConfig.maxTokens = parseInt($('#gm-ai-max-tokens').val()) || 512;
newConfig.temperature = parseFloat($('#gm-ai-temperature').val()) || 0.7;
newConfig.topP = parseFloat($('#gm-ai-top-p').val()) || 0.7;
newConfig.topK = parseInt($('#gm-ai-top-k').val()) || 50;
newConfig.frequencyPenalty = parseFloat($('#gm-ai-frequency-penalty').val()) || 0.5;
newConfig.aiMemoryLimit = parseInt($('#gm-ai-memory-limit').val()) || 10;
saveConfig(newConfig);
alert('配置已保存');
$('#gm-ai-config-panel').remove();
});
$('#gm-ai-config-cancel').click(function() {
$('#gm-ai-config-panel').remove();
});
$('#gm-ai-config-reset').click(function() {
if (confirm('确定要重置所有AI记忆吗?')) {
const newConfig = getConfig();
newConfig.aiContext = [];
newConfig.aiLongTermMemory = [];
saveConfig(newConfig);
alert('AI记忆已重置');
}
});
// 添加记忆
$('#gm-ai-add-memory').click(function() {
const title = $('#gm-ai-memory-title').val().trim();
const content = $('#gm-ai-memory-content').val().trim();
if (title && content) {
const newConfig = getConfig();
if (!Array.isArray(newConfig.aiLongTermMemory)) {
newConfig.aiLongTermMemory = [];
}
newConfig.aiLongTermMemory.push({
title: title,
content: content,
timestamp: new Date().toISOString()
});
saveConfig(newConfig);
// 清空输入框
$('#gm-ai-memory-title').val('');
$('#gm-ai-memory-content').val('');
// 重新显示记忆列表
showAIConfigPanel();
alert('记忆已添加');
} else {
alert('请填写标题和内容');
}
});
// 删除记忆项目
$(document).on('click', '.gm-ai-delete-memory', function() {
const index = parseInt($(this).data('index'));
const newConfig = getConfig();
if (Array.isArray(newConfig.aiLongTermMemory) && newConfig.aiLongTermMemory.length > index) {
newConfig.aiLongTermMemory.splice(index, 1);
saveConfig(newConfig);
showAIConfigPanel(); // 重新显示面板
alert('记忆已删除');
}
});
}
// 强化版页面内容抓取函数
function getCurrentPageContent() {
const url = window.location.href;
let content = '';
try {
// 获取页面基本信息
const title = $('title').text().trim() || document.title || '未知标题';
const pathname = window.location.pathname;
content += `页面URL: ${url}\n`;
content += `页面标题: ${title}\n`;
content += `页面路径: ${pathname}\n\n`;
// 根据不同页面类型进行深度内容抓取
if (url.includes('/forum/')) {
content += '=== 论坛页面内容 ===\n';
content += getForumPageContent(url);
} else if (url.includes('/plugins/notes/')) {
content += '=== 日记页面内容 ===\n';
content += getNotesPageContent(url);
} else if (url.includes('/chat/')) {
content += '=== 聊天室页面内容 ===\n';
content += getChatPageContent(url);
} else if (url.includes('/guest/')) {
content += '=== 留言板页面内容 ===\n';
content += getGuestbookPageContent(url);
} else if (url.includes('/user/info.php')) {
content += '=== 用户资料页面内容 ===\n';
content += getUserPageContent(url);
} else {
content += '=== 首页内容 ===\n';
content += getHomePageContent(url);
}
// 限制内容长度以避免过长
if (content.length > 2000) {
content = content.substring(0, 2000) + '... (内容已截断)';
}
} catch (error) {
console.error('页面内容抓取错误:', error);
content = `页面URL: ${url}\n页面内容抓取失败: ${error.message}`;
}
return content;
}
// 获取论坛页面内容
function getForumPageContent(url) {
let content = '';
// 获取论坛标题和描述
const forumTitle = $('h1, h2, h3').first().text().trim();
if (forumTitle) {
content += `论坛标题: ${forumTitle}\n`;
}
// 获取帖子列表或帖子内容
if (url.match(/\/\d+\/\d+\/\d+\//)) {
// 具体帖子页面
content += '帖子内容:\n';
const postElements = $('body').find('div, p, span').filter(function() {
return $(this).text().trim().length > 10 &&
!$(this).find('script, style').length &&
!$(this).hasClass('gm-') && // 排除插件生成的内容
!$(this).parents('.gm-').length;
});
postElements.each(function(index) {
if (index < 10) { // 限制抓取数量
const text = $(this).text().trim();
if (text.length > 20) {
content += `- ${text.substring(0, 100)}...\n`;
}
}
});
} else {
// 论坛列表页面
content += '帖子列表:\n';
$('a[href*="/forum/"]').each(function(index) {
if (index < 15) { // 限制抓取数量
const linkText = $(this).text().trim();
const href = $(this).attr('href');
if (linkText && href && linkText.length > 5) {
content += `- ${linkText} (${href})\n`;
}
}
});
}
return content;
}
// 获取日记页面内容
function getNotesPageContent(url) {
let content = '';
// 获取日记标题(如果有)
const noteTitle = $('h1, h2, h3').first().text().trim();
if (noteTitle) {
content += `日记标题: ${noteTitle}\n`;
}
// 获取日记列表或具体日记内容
if (url.includes('/plugins/notes/list.php')) {
// 具体日记页面
content += '日记内容:\n';
const noteContent = $('body').text().substring(0, 500);
content += noteContent + '\n';
} else {
// 日记列表页面
content += '日记列表:\n';
$('a[href*="/plugins/notes/list.php"]').each(function(index) {
if (index < 10) {
const linkText = $(this).text().trim();
const userText = $(this).prevAll('a[href*="/user/info.php"]').first().text().trim();
if (linkText && linkText.length > 5) {
content += `- ${userText}: ${linkText}\n`;
}
}
});
}
return content;
}
// 获取聊天室页面内容
function getChatPageContent(url) {
let content = '';
// 获取聊天室名称
const roomName = $('h1, h2, h3').first().text().trim();
if (roomName) {
content += `聊天室: ${roomName}\n`;
}
// 获取最近聊天记录
content += '最近聊天记录:\n';
const chatMessages = $('body').find('div, p, span').filter(function() {
return $(this).text().trim().length > 5 &&
!$(this).find('script, style').length &&
!$(this).hasClass('gm-') &&
!$(this).parents('.gm-').length;
});
chatMessages.slice(0, 8).each(function() {
const text = $(this).text().trim();
if (text.length > 10 && text.length < 200) {
content += `- ${text}\n`;
}
});
return content;
}
// 获取留言板页面内容
function getGuestbookPageContent(url) {
let content = '';
// 获取留言板标题
const guestbookTitle = $('h1, h2, h3').first().text().trim();
if (guestbookTitle) {
content += `留言板: ${guestbookTitle}\n`;
}
// 获取留言内容
content += '最新留言:\n';
$('body').find('div, p').each(function(index) {
if (index < 10) {
const text = $(this).text().trim();
if (text.length > 15 && text.length < 150) {
// 检查是否包含时间或用户名特征
if (text.includes(':') || text.match(/\d{1,2}:\d{2}/)) {
content += `- ${text}\n`;
}
}
}
});
return content;
}
// 获取用户页面内容
function getUserPageContent(url) {
let content = '';
// 获取用户名
const username = $('h1, h2, h3').first().text().trim() ||
$('a[href*="/user/info.php"]').first().text().trim();
if (username) {
content += `用户名: ${username}\n`;
}
// 获取用户ID
const userId = getParameterByName('id');
if (userId) {
content += `用户ID: ${userId}\n`;
}
// 获取用户信息
content += '用户信息:\n';
const userInfoElements = $('body').find('div, p, span').filter(function() {
return $(this).text().trim().length > 5 &&
!$(this).find('script, style').length &&
!$(this).hasClass('gm-') &&
!$(this).parents('.gm-').length;
});
userInfoElements.slice(0, 5).each(function() {
const text = $(this).text().trim();
if (text.length > 10 && text.length < 100) {
content += `- ${text}\n`;
}
});
return content;
}
// 获取首页内容
function getHomePageContent(url) {
let content = '';
// 获取新闻和公告
content += '首页内容:\n';
const homeElements = $('body').find('div, p, span').filter(function() {
return $(this).text().trim().length > 10 &&
!$(this).find('script, style').length &&
!$(this).hasClass('gm-') &&
!$(this).parents('.gm-').length;
});
homeElements.slice(0, 10).each(function() {
const text = $(this).text().trim();
if (text.length > 15 && text.length < 150) {
content += `- ${text}\n`;
}
});
return content;
}
// 带上下文的AI查询
function queryAIWithContext(question, pageContent, callback) {
const config = getConfig();
// 构建提示词,包含页面内容、上下文和长期记忆
let systemPrompt = "你是一个智能助手,可以帮助用户处理各种问题。你可以访问以下信息:\n\n";
// 添加页面内容
systemPrompt += `当前页面信息:\n${pageContent}\n\n`;
// 添加长期记忆
if (Array.isArray(config.aiLongTermMemory) && config.aiLongTermMemory.length > 0) {
systemPrompt += `用户的长期记忆:\n`;
config.aiLongTermMemory.forEach((item, index) => {
systemPrompt += `${index + 1}. ${item.title}: ${item.content}\n`;
});
systemPrompt += `\n`;
}
// 添加短期上下文
if (Array.isArray(config.aiContext) && config.aiContext.length > 0) {
systemPrompt += `最近对话历史:\n`;
config.aiContext.slice(-5).forEach((item, index) => { // 只取最近5条对话
systemPrompt += `用户: ${item.question}\n助手: ${item.response}\n`;
});
systemPrompt += `\n`;
}
// 添加工具说明
systemPrompt += `你可以使用以下工具来帮助用户:\n`;
systemPrompt += `1. 长期记忆存储工具 - 用于记住对用户重要的信息\n`;
systemPrompt += ` 使用方法: 在回答中包含 "[存储记忆: 标题 | 内容]" 来存储重要信息到长期记忆\n`;
systemPrompt += `2. 页面内容分析工具 - 用于分析当前页面内容\n`;
systemPrompt += ` 使用方法: 在回答中包含 "[分析页面]" 来深入分析当前页面\n\n`;
systemPrompt += `请根据用户的问题提供帮助,并在适当时候使用工具。`;
// 构建完整提示
const fullPrompt = `${systemPrompt}\n\n用户问题: ${question}`;
queryAI(fullPrompt, (response) => {
// 检查是否有工具调用
handleToolCalls(response, question, callback);
});
}
// 处理工具调用
function handleToolCalls(response, originalQuestion, callback) {
const config = getConfig();
// 检查是否有存储记忆的指令
const memoryMatch = response.match(/\[存储记忆:\s*([^\|]+)\s*\|\s*([^\]]+)\]/);
if (memoryMatch) {
const title = memoryMatch[1].trim();
const content = memoryMatch[2].trim();
// 存储到长期记忆
if (!Array.isArray(config.aiLongTermMemory)) {
config.aiLongTermMemory = [];
}
config.aiLongTermMemory.push({
title: title,
content: content,
timestamp: new Date().toISOString()
});
saveConfig(config);
// 在AI响应中显示工具调用
const toolCallDisplay = `✓ 已存储记忆: ${title}
`;
addAIResponseMessage(toolCallDisplay);
// 移除工具调用标记后返回响应
const cleanResponse = response.replace(/\[存储记忆:[^\]]+\]/g, '').trim();
if (cleanResponse) {
callback(cleanResponse);
} else {
callback('我已经为您存储了这条重要信息到长期记忆中。');
}
} else {
// 直接返回响应
callback(response);
}
}
// 显示AI响应
function showAIResponse(response) {
const aiDiv = $('#gm-ai-assistant');
if (aiDiv.is(':hidden')) {
aiDiv.show();
}
addAIResponseMessage(response);
}
// 添加AI用户消息
function addAIUserMessage(message) {
const contentDiv = $('#gm-ai-content');
const userMessage = `您: ${message}
`;
contentDiv.append(userMessage);
contentDiv.scrollTop(contentDiv[0].scrollHeight);
}
// 添加AI响应消息
function addAIResponseMessage(message) {
const contentDiv = $('#gm-ai-content');
const responseMessage = `AI: ${message}
`;
contentDiv.append(responseMessage);
contentDiv.scrollTop(contentDiv[0].scrollHeight);
}
// AI聊天查询(根据讯飞星火API文档)
function queryAI(question, callback) {
const config = getConfig();
const apiUrl = config.customApiEnabled ? config.apiUrl : 'https://apis.iflow.cn/v1/chat/completions';
// 准備请求参数(根据讯飞星火API文档)
const payload = {
model: config.modelId || 'tstars2.0',
messages: [
{
role: 'user',
content: question
}
],
stream: false,
max_tokens: config.maxTokens || 512,
temperature: config.temperature || 0.7,
top_p: config.topP || 0.7,
top_k: config.topK || 50,
frequency_penalty: config.frequencyPenalty || 0.5,
n: 1,
response_format: {
type: 'text'
}
};
// 准備请求头
const headers = {
'Content-Type': 'application/json'
};
// 如果提供了API Key,添加认证头
if (config.apiKey) {
headers['Authorization'] = `Bearer ${config.apiKey}`;
}
// 添加错误处理
GM_xmlhttpRequest({
method: 'POST',
url: apiUrl,
headers: headers,
data: JSON.stringify(payload),
timeout: 20000, // 20秒超时
onload: function(response) {
if (response.status === 200) {
let result = response.responseText.trim();
// 尝试解析JSON
try {
const jsonResult = JSON.parse(result);
if (jsonResult && jsonResult.choices && jsonResult.choices.length > 0) {
const choice = jsonResult.choices[0];
if (choice.message && choice.message.content) {
result = choice.message.content;
} else if (typeof jsonResult === 'string') {
result = jsonResult;
}
} else if (jsonResult && jsonResult.content) {
result = jsonResult.content;
} else if (jsonResult && jsonResult.msg) {
result = jsonResult.msg;
} else if (jsonResult && jsonResult.response) {
result = jsonResult.response;
}
} catch (e) {
// 不是JSON格式,使用原始文本
console.log('响应不是JSON格式:', result);
}
// 检查返回内容是否有效
if (result && result.length > 0 && !result.toLowerCase().includes('error') && !result.toLowerCase().includes('404')) {
callback(result);
} else {
console.log('API返回错误内容:', result);
callback('AI助手暂时无法响应:API返回错误内容');
}
} else {
console.log('API请求失败,状态码:', response.status);
callback('AI助手暂时无法响应:HTTP错误 ' + response.status);
}
},
onerror: function(error) {
console.error('AI API请求错误:', error);
callback('AI助手暂时无法响应:网络请求失败');
},
ontimeout: function() {
console.log('API请求超时');
callback('AI助手暂时无法响应:请求超时');
}
});
}
// 切换AI助手显示
function toggleAIAssistant() {
const aiDiv = $('#gm-ai-assistant');
if (aiDiv.is(':hidden')) {
aiDiv.show();
} else {
aiDiv.hide();
}
}
// 拖拽元素功能
function dragElement(elmnt, header) {
let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
if (header) {
header.onmousedown = dragMouseDown;
} else {
elmnt.onmousedown = dragMouseDown;
}
function dragMouseDown(e) {
e = e || window.event;
e.preventDefault();
pos3 = e.clientX;
pos4 = e.clientY;
document.onmouseup = closeDragElement;
document.onmousemove = elementDrag;
}
function elementDrag(e) {
e = e || window.event;
e.preventDefault();
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
}
function closeDragElement() {
document.onmouseup = null;
document.onmousemove = null;
}
}
// 获取URL参数
function getParameterByName(name, url = window.location.href) {
name = name.replace(/[\[\]]/g, '\\$&');
const regex = new RegExp('[?&]' + name + '(=([^]*)|&|#|$)');
const results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, ' '));
}
// 等待jQuery加载完成
waitForJQuery();
})();