// ==UserScript==
// @name Linux do Level Enhanced
// @namespace http://tampermonkey.net/
// @version 0.0.1
// @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==
(async function() {
'use strict';
const ABOUT_DATA_URL = `https://linux.do/about.json`;
const USER_DATA_URL_PREFIX = `https://linux.do/u/`;
const USER_DATA_URL_SUFFIX = `/summary.json`;
const FETCH_REQUEST_OPTIONS = {
headers: {
"Accept": "application/json",
"User-Agent": "Mozilla/5.0"
},
method: "GET",
};
const 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 } // posts_read_count and topics_entered will be dynamically adjusted
};
const levelDescriptions = {
0: "游客", 1: "基本用户", 2: "成员", 3: "活跃用户",
};
async function fetchAboutData() {
try {
const response = await fetch(ABOUT_DATA_URL, FETCH_REQUEST_OPTIONS);
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
return await response.json();
} catch (error) {
console.error("Failed to fetch about data: ", error);
}
}
async function fetchUserData(username) {
try {
const response = await fetch(`${USER_DATA_URL_PREFIX}${username}${USER_DATA_URL_SUFFIX}`, FETCH_REQUEST_OPTIONS);
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
return await response.json();
} catch (error) {
console.error("Failed to fetch user data: ", error);
}
}
function updatePopupContent(userSummary, user, status) {
const popup = document.getElementById('linuxDoLevelPopupContent');
if (popup && userSummary && user) {
let content = `<strong>User Level:</strong> ${levelDescriptions[user.trust_level]}<br><strong>User Stats:</strong><br>`;
const requirements = levelRequirements[user.trust_level];
if (user.trust_level === 2) {
// Adjusting the dynamic requirements for level 2 with the updated posts read limit
requirements['posts_read_count'] = Math.min(Math.floor(status.posts_30_days / 4), 20000); // Updated posts read limit
requirements['topics_entered'] = Math.min(Math.floor(status.topics_30_days / 4), 500);
}
for (const stat in requirements) {
const currentVal = userSummary[stat] || 0;
const targetVal = requirements[stat];
const color = currentVal >= targetVal ? "green" : "red";
content += `${stat.replace(/_/g, ' ').replace('count', '')}: <span style="color: ${color};">${currentVal}`;
if (targetVal !== undefined) {
content += ` / ${targetVal}`;
}
content += `</span><br>`;
}
popup.innerHTML = content;
}
}
async function handleSearch() {
const searchInput = document.getElementById('linuxDoUserSearch');
const username = searchInput.value.trim();
if (username) {
const aboutData = await fetchAboutData();
const userData = await fetchUserData(username);
if (userData && aboutData) {
const userSummary = userData.user_summary;
const user = userData.users[0];
const status = aboutData.about.stats;
updatePopupContent(userSummary, user, status);
}
}
}
function createPopup() {
const popup = document.createElement('div');
popup.setAttribute('style', `position: fixed; bottom: 20px; right: 20px; width: 250px; height: auto; background-color: white; box-shadow: 0 0 10px rgba(0,0,0,0.5); padding: 15px; z-index: 10000; font-size: 14px; border-radius: 5px; overflow: auto;`);
popup.id = 'linuxDoLevelPopup';
const content = document.createElement('div');
content.id = 'linuxDoLevelPopupContent';
content.innerHTML = 'Loading user stats...';
popup.appendChild(content);
const searchBox = document.createElement('input');
searchBox.setAttribute('type', 'text');
searchBox.setAttribute('placeholder', 'Enter username...');
searchBox.setAttribute('style', 'width: 100%; margin-top: 10px;');
searchBox.id = 'linuxDoUserSearch';
popup.appendChild(searchBox);
const searchButton = document.createElement('button');
searchButton.textContent = 'Search';
searchButton.setAttribute('style', 'width: 100%; margin-top: 5px;');
searchButton.addEventListener('click', handleSearch);
popup.appendChild(searchButton);
document.body.appendChild(popup);
}
createPopup();
})();