// ==UserScript==
// @name Linux do Level Enhanced
// @namespace http://tampermonkey.net/
// @version 0.0.3
// @description Enhanced script to track progress towards next trust level on linux.do with added search functionality and adjusted posts read limit.
// @author Hua, Reno
// @match https://linux.do/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=linux.do
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
const levelEnhancement = {
ABOUT_DATA_URL: `https://linux.do/about.json`,
USER_DATA_URL_PREFIX: `https://linux.do/u/`,
USER_DATA_URL_SUFFIX: `/summary.json`,
FETCH_REQUEST_OPTIONS: {
headers: {
"Accept": "application/json",
"User-Agent": "Mozilla/5.0"
},
method: "GET",
},
levelRequirements: {
0: { 'topics_entered': 5, 'posts_read_count': 30, 'time_read': 600 },
1: { 'days_visited': 15, 'likes_given': 1, 'likes_received': 1, 'post_count': 3, 'topics_entered': 20, 'posts_read_count': 100, 'time_read': 3600 },
2: { 'days_visited': 50, 'likes_given': 30, 'likes_received': 20, 'post_count': 10, 'posts_read_count': 0, 'topics_entered': 0 }
},
levelDescriptions: {
0: "游客", 1: "基本用户", 2: "成员", 3: "活跃用户", 4: "领导者"
},
isPopupMinimized: false,
popup: null,
content: null,
searchBox: null,
searchButton: null,
minimizeButton: null,
init: function() {
this.createPopup();
},
fetchAboutData: async function() {
try {
const response = await fetch(this.ABOUT_DATA_URL, this.FETCH_REQUEST_OPTIONS);
if (!response.ok) throw new Error(`HTTP 错误!状态:${response.status}`);
return await response.json();
} catch (error) {
console.error("获取关于页面数据失败:", error);
this.displayError("获取关于页面数据失败");
}
},
fetchUserData: async function(username) {
try {
const response = await fetch(`${this.USER_DATA_URL_PREFIX}${username}${this.USER_DATA_URL_SUFFIX}`, this.FETCH_REQUEST_OPTIONS);
if (!response.ok) throw new Error(`HTTP 错误!状态:${response.status}`);
return await response.json();
} catch (error) {
console.error("获取用户数据失败:", error);
this.displayError("获取用户数据失败");
}
},
displayError: function(message) {
if (this.content) {
this.content.innerHTML = `<strong>错误:</strong>${message}`;
}
},
updatePopupContent: function(userSummary, user, status) {
if (this.content && userSummary && user) {
let content = `<strong>信任等级:</strong>${this.levelDescriptions[user.trust_level]}<br><strong>升级进度:</strong><br>`;
if (user.trust_level === 3) {
content += `联系管理员以升级到领导者<br>`;
} else if (user.trust_level === 4) {
content += `您已是最高信任等级<br>`;
} else {
const requirements = this.levelRequirements[user.trust_level];
if (user.trust_level === 2) {
requirements['posts_read_count'] = Math.min(Math.floor(status.posts_30_days / 4), 20000);
requirements['topics_entered'] = Math.min(Math.floor(status.topics_30_days / 4), 500);
}
Object.entries(this.levelRequirements[user.trust_level]).forEach(([key, val]) => {
const currentVal = userSummary[key] || 0;
const color = currentVal >= val ? "green" : "red";
const label = this.translateStat(key);
content += `${label}: <span style="color: ${color};">${currentVal} / ${val}</span><br>`;
});
}
this.content.innerHTML = content;
}
},
translateStat: function(stat) {
const translations = {
'days_visited': '访问天数',
'likes_given': '给出的赞',
'likes_received': '收到的赞',
'post_count': '帖子数量',
'posts_read_count': '阅读的帖子数',
'topics_entered': '进入的主题数',
'time_read': '阅读时间'
};
return translations[stat] || stat;
},
handleSearch: async function() {
const username = this.searchBox.value.trim();
if (username) {
const aboutData = await this.fetchAboutData();
const userData = await this.fetchUserData(username);
if (userData && aboutData) {
const userSummary = userData.user_summary;
const user = userData.users[0];
const status = aboutData.about.stats;
this.updatePopupContent(userSummary, user, status);
}
}
},
togglePopupSize: function() {
const minimizedStyles = {
width: '20px',
height: '20px',
borderRadius: '50%',
contentDisplay: 'none',
searchBoxDisplay: 'none',
searchButtonDisplay: 'none',
minimizeButtonText: '',
minimizeButtonWidth: '100%',
minimizeButtonHeight: '100%'
};
const maximizedStyles = {
width: '250px',
height: 'auto',
borderRadius: '5px',
contentDisplay: 'block',
searchBoxDisplay: 'block',
searchButtonDisplay: 'block',
minimizeButtonText: '隐藏',
minimizeButtonWidth: 'auto',
minimizeButtonHeight: 'auto'
};
const applyStyles = (styles) => {
this.popup.style.width = styles.width;
this.popup.style.height = styles.height;
this.popup.style.borderRadius = styles.borderRadius;
this.content.style.display = styles.contentDisplay;
this.searchBox.style.display = styles.searchBoxDisplay;
this.searchButton.style.display = styles.searchButtonDisplay;
this.minimizeButton.textContent = styles.minimizeButtonText;
this.minimizeButton.style.width = styles.minimizeButtonWidth;
this.minimizeButton.style.height = styles.minimizeButtonHeight;
};
if (this.isPopupMinimized) {
applyStyles(maximizedStyles);
this.isPopupMinimized = false;
} else {
applyStyles(minimizedStyles);
this.isPopupMinimized = true;
}
},
createPopup: function() {
this.popup = document.createElement('div');
this.setStyle(this.popup, {
position: 'fixed',
bottom: '20px',
right: '20px',
width: '250px',
height: 'auto',
backgroundColor: 'white',
boxShadow: '0 0 10px rgba(0,0,0,0.5)',
padding: '15px',
zIndex: '10000',
fontSize: '14px',
borderRadius: '5px'
});
this.popup.id = 'linuxDoLevelPopup';
this.content = document.createElement('div');
this.content.id = 'linuxDoLevelPopupContent';
this.content.innerHTML = '欢迎使用 Linux do 等级增强插件';
this.popup.appendChild(this.content);
this.searchBox = document.createElement('input');
this.searchBox.type = 'text';
this.searchBox.placeholder = '请输入用户名...';
this.setStyle(this.searchBox, { width: '100%', marginTop: '10px' });
this.searchBox.id = 'linuxDoUserSearch';
this.popup.appendChild(this.searchBox);
this.searchButton = document.createElement('button');
this.searchButton.textContent = '搜索';
this.setStyle(this.searchButton, { width: '100%', marginTop: '10px' });
this.searchButton.addEventListener('click', this.handleSearch.bind(this));
this.popup.appendChild(this.searchButton);
this.minimizeButton = document.createElement('button');
this.minimizeButton.textContent = '隐藏';
this.setStyle(this.minimizeButton, {
position: 'absolute',
top: '5px',
right: '5px',
zIndex: '10001',
background: 'transparent',
border: 'none',
cursor: 'pointer'
});
this.minimizeButton.addEventListener('click', this.togglePopupSize.bind(this));
this.popup.appendChild(this.minimizeButton);
document.body.appendChild(this.popup);
},
setStyle: function(element, styles) {
Object.assign(element.style, styles);
}
};
levelEnhancement.init();
})();