Open Passerby1011 opened 6 days ago
这个佬很强,主要是获取全文数据这块我卡住了,所以没做这个功能,期待有更强的佬帮我完善一下。
主要是现在的脚本界面易用性太差了,佬如果有能力可以合并进增强脚本了,把界面改的易用一点
主要是现在的脚本界面易用性太差了,佬如果有能力可以合并进增强脚本了,把界面改的易用一点
他的算法加密了,我技术不行,搞不出来 😫
主要是现在的脚本界面易用性太差了,佬如果有能力可以合并进增强脚本了,把界面改的易用一点
他的算法加密了,我技术不行,搞不出来 😫
悄悄的说一声,这个加密claude可以直接读,我用claude改了一下UI,prompt可能有点问题,帖子的处理逻辑完全没动
// ==UserScript==
// @name Linux.do 回复内容总结 (修改版)
// @namespace http://tampermonkey.net/
// @version 0.4
// @description 总结Linux.do论坛帖子中指定楼层之间的回复内容,修改了UI
// @author NullUser
// @match https://linux.do/*
// @icon https://linux.do/uploads/default/optimized/1X/3a18b4b0da3e8cf96f7eea15241c3d251f28a39b_2_180x180.png
// @grant GM_setValue
// @grant GM_getValue
// @license MIT
// ==/UserScript==
(function() {
'use strict';
async function summarizeSomething(txt) {
const API_KEY = GM_getValue('apiKey', '');
const url = GM_getValue('apiUrl', 'https://xxxx.xxxx.xxxx/v1/chat/completions');
const model = GM_getValue('model', 'deepseek-chat');
const headers = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${API_KEY}`
};
const data = {
model: model,
messages: [
{ role: 'system', content: '你可以帮我很好的总结帖子内容,所有的回复都以中文返回。' },
{ role: 'user', content: txt }
],
stream: false
};
try {
const response = await fetch(url, {
method: 'POST',
headers: headers,
body: JSON.stringify(data)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
console.log(result.choices[0].message.content);
return result.choices[0].message.content;
} catch (error) {
console.error('Error fetching data:', error);
return null;
}
}
function formatDialogues(data) {
const dialogues = data.post_stream.posts.map(post => {
const {cooked, username, reply_to_user} = post;
return reply_to_user ? `${username}回复${reply_to_user.username}说:${cooked}` : `${username}说:${cooked}`;
});
console.log(dialogues);
return dialogues;
}
function safeSlice(arr, start, end) {
start = Math.max(start, 0);
end = end === undefined || end > arr.length ? arr.length : end;
return arr.slice(start, end);
}
async function postid_to_url(building, startFloor, endFloor) {
try {
const url = `https://linux.do/t/${building}/post_ids.json?post_number=0&limit=99999`;
const response = await fetch(url, fetchOptions);
const data = await response.json();
const post_ids = safeSlice(data.post_ids, startFloor - 1, endFloor - 1);
if (startFloor == 1) {
const url = `https://linux.do/t/${building}.json`;
const response = await fetch(url, fetchOptions);
const data = await response.json();
const first_post_id = data.post_stream.posts[0].id;
post_ids.unshift(first_post_id);
}
const chunk_size = 200;
const urls = [];
for (let i = 0; i < post_ids.length; i += chunk_size) {
const chunk = post_ids.slice(i, i + chunk_size);
const post_ids_param = chunk.map(id => `post_ids[]=${id}`).join('&');
const url = `https://linux.do/t/${building}/posts.json?${post_ids_param}&include_suggested=false`;
urls.push(url);
}
console.log(urls);
return urls;
} catch (error) {
console.error(error);
throw error;
}
}
async function json_to_txt(building, startFloor, endFloor) {
try {
const urls = await postid_to_url(building, startFloor, endFloor);
let dialogues = [];
for (const url of urls) {
const response = await fetch(url, fetchOptions);
const json = await response.json();
const formatted = formatDialogues(json);
dialogues = dialogues.concat(formatted);
}
console.log(dialogues);
return dialogues;
} catch (error) {
console.error(error);
}
}
async function main(building, startFloor, endFloor) {
try {
const dialogues = await json_to_txt(building, startFloor, endFloor);
const txt = "Role: Summarization AssistantProfileauthor: LangGPTversion: 1.0language: 中文description: 本助手专注于总结论坛帖子的评论区,提供整体风向和多样内容的概要。Skills1. 能够快速扫描和解析大量评论信息。2. 精确捕捉评论中的主要观点和情感倾向。3. 提供简洁明了的总结,助您一眼把握评论区的整体风向。4. 识别评论中的不同主题或关注点,并分别总结。Background(可选项):Goals(可选项):OutputFormat(可选项):Rules1. 理解评论内容的多样性,确保总结涵盖不同观点。2. 避免偏见,提供中立的评论风向分析。3. 保持简洁,确保总结信息易于阅读和理解。Workflows1. 收集并扫描论坛帖子的评论区。2. 分析评论的整体情感倾向和主要观点。3. 总结评论区的大致风向和多样内容。4. 向用户提供最终总结,并解释评论区的主题分布。Init友好的欢迎用户,并介绍 LangGPT, 介绍完后将 LangGPT 的结构化提示词模板打印出来。请总结以下对话内容:\n" + dialogues.join('\n');
const summary = await summarizeSomething(txt);
console.log(summary);
return summary;
} catch (error) {
console.error("Error in main function:", error);
return error;
}
}
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
const fetchOptions = {
headers: {
'accept': 'application/json, text/javascript, */*; q=0.01',
'accept-language': 'zh-CN,zh;q=0.9',
'discourse-logged-in': 'true',
'discourse-present': 'true',
'x-csrf-token': csrfToken,
'x-requested-with': 'XMLHttpRequest'
},
'method': 'GET',
'mode': 'cors',
'credentials': 'include'
};
// 创建侧边栏
const sidebar = document.createElement('div');
sidebar.style.cssText = `
position: fixed;
top: 0;
right: -500px; /* 增加侧边栏宽度 */
width: 400px; /* 增加侧边栏宽度 */
height: 100vh;
background-color: white;
box-shadow: -2px 0 5px rgba(0,0,0,0.2);
transition: right 0.3s;
z-index: 1000;
overflow-y: auto;
padding: 20px; /* 添加内边距 */
`;
document.body.appendChild(sidebar);
// 创建悬浮按钮
const toggleButton = document.createElement('div');
toggleButton.style.cssText = `
position: fixed;
top: 50%;
right: 0;
width: 20px;
height: 40px;
background-color: #f0f0f0;
border-radius: 5px 0 0 5px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
z-index: 1001;
`;
toggleButton.innerHTML = '◀';
toggleButton.addEventListener('click', () => {
if (sidebar.style.right === '0px') {
sidebar.style.right = '-500px'; // 更新为新宽度
toggleButton.innerHTML = '◀';
} else {
sidebar.style.right = '0px';
toggleButton.innerHTML = '▶';
}
});
document.body.appendChild(toggleButton);
// 创建设置按钮
const settingsButton = document.createElement('div');
settingsButton.style.cssText = `
position: absolute;
top: 10px;
right: 10px;
cursor: pointer;
font-size: 20px;
`;
settingsButton.innerHTML = '⚙️';
settingsButton.addEventListener('click', showSettings);
sidebar.appendChild(settingsButton);
// 创建表单
const form = document.createElement('form');
form.innerHTML = `
<h3>总结帖子内容</h3>
<label for="building">帖子ID:</label>
<input type="number" id="building" name="building" required style="width: 100%;"><br><br>
<label for="startFloor">起始楼层:</label>
<input type="number" id="startFloor" name="startFloor" required style="width: 100%;"><br><br>
<label for="endFloor">结束楼层:</label>
<input type="number" id="endFloor" name="endFloor" required style="width: 100%;"><br><br>
<button type="submit">总结</button>
`;
sidebar.appendChild(form);
// 创建结果显示区域
const resultArea = document.createElement('div');
resultArea.id = 'result-area';
resultArea.style.marginTop = '20px';
resultArea.style.border = '1px solid #ccc';
resultArea.style.padding = '10px';
resultArea.style.maxHeight = '500px'; // 限制高度
resultArea.style.overflowY = 'auto'; // 添加滚动条
resultArea.style.backgroundColor = '#f9f9f9'; // 设置背景颜色
sidebar.appendChild(resultArea);
// 处理表单提交
form.addEventListener('submit', async function(e) {
e.preventDefault();
const building = parseInt(form.building.value);
const startFloor = parseInt(form.startFloor.value);
const endFloor = parseInt(form.endFloor.value);
if (endFloor < startFloor) {
alert("结束楼层不能小于起始楼层");
return;
}
const maxFloors = 500;
if (endFloor - startFloor > maxFloors) {
alert(`一次最多只能总结${maxFloors}层`);
return;
}
displayResultAsMarkdown("正在总结中...");
try {
const result = await main(building, startFloor, endFloor);
let summary = `以下为https://linux.do/t/topic/${building}的${startFloor}层--${endFloor}层的总结:\n\n`;
displayResultAsMarkdown(summary + result);
} catch (error) {
displayResultAsMarkdown("总结出错");
console.error("Error:", error);
}
});
// 显示设置界面
function showSettings() {
const settingsForm = document.createElement('form');
settingsForm.innerHTML = `
<h3>设置</h3>
<label for="apiKey">API密钥:</label>
<input type="text" id="apiKey" value="${GM_getValue('apiKey', '')}" style="width: 100%;"><br><br>
<label for="model">模型:</label>
<input type="text" id="model" value="${GM_getValue('model', 'deepseek-chat')}" style="width: 100%;"><br><br>
<label for="apiUrl">API地址:</label>
<input type="text" id="apiUrl" value="${GM_getValue('apiUrl', 'https://oneapi.passerbywtj.club/v1/chat/completions')}" style="width: 100%;"><br><br>
<button type="submit">保存</button>
`;
settingsForm.style.cssText = `
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: white;
z-index: 1002;
padding: 20px;
box-sizing: border-box;
`;
settingsForm.addEventListener('submit', function(e) {
e.preventDefault();
GM_setValue('apiKey', settingsForm.querySelector('#apiKey').value);
GM_setValue('model', settingsForm.querySelector('#model').value);
GM_setValue('apiUrl', settingsForm.querySelector('#apiUrl').value);
sidebar.removeChild(settingsForm);
});
// 添加关闭按钮
const closeButton = document.createElement('button');
closeButton.textContent = '关闭';
closeButton.style.cssText = `
position: absolute;
top: 10px;
right: 10px;
`;
closeButton.addEventListener('click', (e) => {
e.preventDefault();
sidebar.removeChild(settingsForm);
});
settingsForm.appendChild(closeButton);
sidebar.appendChild(settingsForm);
}
function displayResultAsMarkdown(text) {
const resultDiv = document.createElement('div');
resultDiv.style.whiteSpace = 'pre-wrap'; // 保留换行和空格
resultDiv.style.wordWrap = 'break-word'; // 长单词自动换行
resultDiv.style.fontFamily = 'monospace'; // 使用等宽字体
resultDiv.style.fontSize = '14px';
resultDiv.textContent = text;
const existingResult = sidebar.querySelector('#result-area');
if (existingResult) {
existingResult.innerHTML = '';
existingResult.appendChild(resultDiv);
}
}
// 从URL提取帖子ID
function extractTopicId() {
let url = window.location.href;
const matches = url.match(/\/topic\/(\d+)/);
return matches ? matches[1] : null;
}
// 更新楼层号
function updateFloornumber() {
setTimeout(() => {
const lastFloor = Number(document.getElementsByClassName('timeline-replies')[0]?.dataset.lastReply?.split('last-reply')[1]);
if (lastFloor) {
const startFloor = Math.max(1, parseInt(lastFloor) - 200);
form.startFloor.value = startFloor;
form.endFloor.value = lastFloor;
}
}, 500);
}
// 监控URL变化并更新表单
function monitorURLChangeAndUpdateButton() {
let currentTopicId = extractTopicId();
setInterval(() => {
const newTopicId = extractTopicId();
if (newTopicId !== currentTopicId) {
currentTopicId = newTopicId;
form.building.value = extractTopicId();
updateFloornumber();
}
}, 1000);
}
// 初始化
form.building.value = extractTopicId();
updateFloornumber();
monitorURLChangeAndUpdateButton();
})();
这个很不错啊,我将会参考使用。
提出你的创意和功能想法,如果有参考的实现方法可以贴上链接。 https://linux.do/t/topic/186528