Created
April 19, 2024 02:50
-
-
Save kanjieater/2f7d796a81ce0b682f24b8f5092b3dee to your computer and use it in GitHub Desktop.
Find inactive users on tadoku
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const logsBaseUrl = "https://tadoku.app/api/internal/immersion/contests/32b33801-c412-4187-9d78-31d58cd06588/logs"; | |
const pageSize = 10; // Adjust page size as needed | |
const includeDeleted = false; // Include deleted as per your example | |
// Function to check if a date is older than one month | |
function isOlderThanOneMonth(dateString) { | |
const oneMonthAgo = new Date(); | |
oneMonthAgo.setMonth(oneMonthAgo.getMonth() - 1); | |
const logDate = new Date(dateString); | |
return logDate < oneMonthAgo; | |
} | |
async function fetchLogs() { | |
let allLogs = []; | |
let nextPageToken = "0"; | |
try { | |
do { | |
const url = `${logsBaseUrl}?page_size=${pageSize}&page=${nextPageToken}&include_deleted=${includeDeleted}`; | |
const response = await fetch(url); | |
if (!response.ok) throw new Error(`Failed to fetch logs: ${response.statusText}`); | |
const logsData = await response.json(); | |
const logs = logsData.logs; | |
allLogs = allLogs.concat(logs); | |
nextPageToken = logsData.next_page_token; | |
} while (nextPageToken); | |
return allLogs; | |
} catch (error) { | |
console.error("Error fetching logs:", error); | |
return []; | |
} | |
} | |
async function fetchReadersAndLogs() { | |
try { | |
const logs = await fetchLogs(); | |
// Now, process the data to find active, inactive, and dead users | |
const activeUsers = []; | |
const inactiveUsers = []; | |
const deadUsers = []; | |
// Fetch leaderboard data to match with user IDs | |
const leaderboardUrl = "https://tadoku.app/api/internal/immersion/contests/32b33801-c412-4187-9d78-31d58cd06588/leaderboard?page_size=50&page=0"; | |
const leaderboardResponse = await fetch(leaderboardUrl); | |
if (!leaderboardResponse.ok) throw new Error(`Failed to fetch leaderboard: ${leaderboardResponse.statusText}`); | |
const leaderboardData = await leaderboardResponse.json(); | |
const leaderboardEntries = leaderboardData.entries; | |
leaderboardEntries.forEach(entry => { | |
const lastActivityDate = logs.filter(log => log.user_id === entry.user_id) | |
.map(log => new Date(log.created_at)) | |
.sort((a, b) => b - a)[0]; | |
if (!lastActivityDate) { | |
deadUsers.push({ username: entry.user_display_name, lastReadDate: null }); | |
} else { | |
const userHasLogged = logs.some(log => log.user_id === entry.user_id && !isOlderThanOneMonth(log.created_at)); | |
if (userHasLogged) { | |
activeUsers.push({ username: entry.user_display_name, lastReadDate: lastActivityDate }); | |
} else { | |
const twoMonthsAgo = new Date(); | |
twoMonthsAgo.setMonth(twoMonthsAgo.getMonth() - 2); | |
if (lastActivityDate < twoMonthsAgo) { | |
deadUsers.push({ username: entry.user_display_name, lastReadDate: lastActivityDate }); | |
} else { | |
inactiveUsers.push({ username: entry.user_display_name, lastReadDate: lastActivityDate }); | |
} | |
} | |
} | |
}); | |
console.log("Active Users:", activeUsers); | |
console.log("Inactive Users:", inactiveUsers); | |
console.log("Dead Users:", deadUsers); | |
return { activeUsers, inactiveUsers, deadUsers }; | |
} catch (error) { | |
console.error("Error fetching data:", error); | |
return { activeUsers: [], inactiveUsers: [], deadUsers: [] }; | |
} | |
} | |
async function applyStyling(inactiveUsers, deadUsers) { | |
// Apply strike-through and color change for inactive and dead users | |
inactiveUsers.forEach(user => { | |
const username = user.username; | |
const lastReadDate = user.lastReadDate; | |
const userElements = document.querySelectorAll(`tr td:nth-child(2) .reset.text-lg`); | |
userElements.forEach(element => { | |
if (element.textContent.trim() === username) { | |
element.style.color = "#ffbf47"; // Yellowish color for inactive users | |
if (lastReadDate) { | |
element.textContent += ` (Last read: ${lastReadDate.toDateString()})`; | |
} | |
} | |
}); | |
}); | |
deadUsers.forEach(user => { | |
const username = user.username; | |
const lastReadDate = user.lastReadDate; | |
const userElements = document.querySelectorAll(`tr td:nth-child(2) .reset.text-lg`); | |
userElements.forEach(element => { | |
if (element.textContent.trim() === username) { | |
element.style.color = "tomato"; // Tomato color for dead users | |
element.style.textDecoration = "line-through"; | |
if (lastReadDate) { | |
element.textContent += ` (Last read: ${lastReadDate.toDateString()})`; | |
} | |
} | |
}); | |
}); | |
console.log("Styling applied."); | |
// Print final lists of dead users and inactive users with "@" in front of their names | |
console.log("Styling applied.\n"); | |
// Build final lists of dead users and inactive users with "@" in front of their names | |
let finalOutput = ":sob: Inactive Users:\n"; | |
inactiveUsers.forEach(user => finalOutput += `@${user.username}\n`); | |
finalOutput += "\n:headstone: Dead Users:\n"; | |
deadUsers.forEach(user => finalOutput += `@${user.username}\n`); | |
// Print the final block | |
console.log(finalOutput); | |
} | |
async function applyUserStyling() { | |
const { inactiveUsers, deadUsers } = await fetchReadersAndLogs(); | |
applyStyling(inactiveUsers, deadUsers); | |
} | |
applyUserStyling(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment