603 lines
21 KiB
HTML
603 lines
21 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>2uf</title>
|
|
<link rel="icon" href="images/favicon.ico" type="image/x-icon">
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
<style>
|
|
body, html {
|
|
margin: 0;
|
|
padding: 0;
|
|
height: 100%;
|
|
font-family: 'Poppins', sans-serif;
|
|
overflow: hidden;
|
|
color: white;
|
|
}
|
|
|
|
#video-background {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
z-index: -1;
|
|
}
|
|
|
|
.preload-screen {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
background: rgba(0, 0, 0, 0.8);
|
|
backdrop-filter: blur(10px);
|
|
-webkit-backdrop-filter: blur(10px);
|
|
z-index: 100;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.preload-text {
|
|
font-size: 2rem;
|
|
font-weight: bold;
|
|
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
|
|
animation: pulse 2s infinite;
|
|
}
|
|
|
|
@keyframes pulse {
|
|
0% { opacity: 0.6; }
|
|
50% { opacity: 1; }
|
|
100% { opacity: 0.6; }
|
|
}
|
|
|
|
.main-content {
|
|
opacity: 0;
|
|
transition: opacity 0.5s ease;
|
|
}
|
|
|
|
.container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-height: 100vh;
|
|
padding: 20px;
|
|
gap: 15px;
|
|
}
|
|
|
|
.discord-box,
|
|
.github-repos {
|
|
width: 100%;
|
|
max-width: 600px;
|
|
box-sizing: border-box;
|
|
background-color: rgba(24, 23, 23, 0.411);
|
|
color: #efe6e6;
|
|
backdrop-filter: blur(10px);
|
|
border-radius: 5px;
|
|
border: 1px solid #14181B;
|
|
position: relative;
|
|
z-index: 2;
|
|
opacity: 0;
|
|
transform: translateY(20px);
|
|
transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1);
|
|
}
|
|
|
|
.discord-box.animate-in,
|
|
.github-repos.animate-in {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
|
|
@keyframes fadeInUp {
|
|
from { opacity: 0; transform: translateY(20px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
|
|
.discord-box {
|
|
padding: 20px;
|
|
text-decoration: none;
|
|
color: white;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
animation: fadeInUp 0.8s ease-out 0.3s forwards;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.discord-header {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 15px;
|
|
}
|
|
|
|
.discord-pic {
|
|
width: 55px;
|
|
height: 55px;
|
|
border-radius: 50%;
|
|
border: 5px solid #14181B;
|
|
}
|
|
|
|
.discord-info {
|
|
flex-grow: 1;
|
|
text-align: left;
|
|
}
|
|
|
|
.discord-name {
|
|
font-weight: bold;
|
|
font-size: 19px;
|
|
margin-bottom: 3px;
|
|
}
|
|
|
|
.discord-status {
|
|
display: flex;
|
|
align-items: center;
|
|
font-size: 13px;
|
|
opacity: 0.8;
|
|
}
|
|
|
|
.status-indicator {
|
|
width: 10px;
|
|
height: 10px;
|
|
border-radius: 50%;
|
|
margin-right: 5px;
|
|
}
|
|
|
|
.status-online {
|
|
background: #3ba55c;
|
|
}
|
|
|
|
.status-idle {
|
|
background: #faa61a;
|
|
}
|
|
|
|
.status-dnd {
|
|
background: #ed4245;
|
|
}
|
|
|
|
.status-offline {
|
|
background: #747f8d;
|
|
}
|
|
|
|
#dm-button {
|
|
padding: 8px 15px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 10px;
|
|
background-color: #101517;
|
|
border: 1px solid #13191B;
|
|
color: white;
|
|
font-size: 16px;
|
|
font-weight: 500;
|
|
transition: all 0.2s ease;
|
|
text-decoration: none;
|
|
flex-shrink: 0;
|
|
gap: 8px;
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
|
|
}
|
|
|
|
#dm-button:hover {
|
|
background-color: rgba(255, 255, 255, 0.2);
|
|
transform: scale(1.02);
|
|
}
|
|
|
|
.discord-activity {
|
|
font-size: 14px;
|
|
padding: 8px;
|
|
background: rgba(0, 0, 0, 0.2);
|
|
border-radius: 8px;
|
|
display: none;
|
|
flex-direction: column;
|
|
gap: 6px;
|
|
}
|
|
|
|
.activity-game-image {
|
|
width: 100%;
|
|
max-height: 60px;
|
|
object-fit: cover;
|
|
border-radius: 10px;
|
|
margin-top: 5px;
|
|
display: none;
|
|
}
|
|
|
|
.activity-label {
|
|
font-weight: bold;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.spotify-image-small {
|
|
width: 60px;
|
|
height: 60px;
|
|
object-fit: cover;
|
|
border-radius: 8px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.spotify-flex-content {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
}
|
|
|
|
#spotify-progress-container {
|
|
width: 100%;
|
|
height: 5px;
|
|
background: rgba(255, 255, 255, 0.3);
|
|
border-radius: 5px;
|
|
margin-top: 5px;
|
|
}
|
|
|
|
#spotify-progress-bar {
|
|
height: 100%;
|
|
background: #1DB954;
|
|
border-radius: 5px;
|
|
width: 0%;
|
|
transition: width 1s linear;
|
|
}
|
|
|
|
.time-info {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
font-size: 12px;
|
|
opacity: 0.7;
|
|
}
|
|
|
|
.github-repos {
|
|
padding: 20px;
|
|
animation: fadeInUp 0.8s ease-out 0.5s forwards;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 15px;
|
|
border: 1px solid #14181B;
|
|
background-color: rgba(24, 23, 23, 0.411)
|
|
}
|
|
|
|
.github-repos h3 {
|
|
font-size: 20px;
|
|
font-weight: bold;
|
|
color: #c9d1d9;
|
|
margin-top: 0px;
|
|
margin-bottom: 15px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
}
|
|
|
|
.repo-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
}
|
|
|
|
.repo-link {
|
|
padding: 10px 15px;
|
|
background-color: rgba(24, 23, 23, 0.411);
|
|
border-radius: 10px;
|
|
text-decoration: none;
|
|
color: #efe6e6;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
transition: background-color 0.2s ease, transform 0.2s ease;
|
|
font-size: 15px;
|
|
}
|
|
|
|
.repo-link:hover {
|
|
background-color: rgba(255, 255, 255, 0.15);
|
|
transform: translateX(5px);
|
|
}
|
|
|
|
.repo-link span {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,200;0,300;0,400;0,500;0,600;0,700;0,800;1,400&display=swap');
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<video id="video-background" autoplay muted loop>
|
|
<source src="images/background.mp4" type="video/mp4" onerror="this.onerror=null; this.remove(); this.src='https://assets.mixkit.co/videos/preview/mixkit-flying-through-a-dark-abstract-tunnel-4493-large.mp4';">
|
|
</video>
|
|
|
|
<audio id="music-player" loop>
|
|
<source src="music/song.mp3" type="audio/mpeg" onerror="this.src='#';">
|
|
Your browser does not support the audio element.
|
|
</audio>
|
|
|
|
<div class="preload-screen">
|
|
<div class="preload-text">Click to reveal</div>
|
|
</div>
|
|
|
|
<div class="main-content">
|
|
<div class="container">
|
|
<div class="discord-box" id="discord-profile">
|
|
<div class="discord-header">
|
|
<img id="discord-avatar" class="discord-pic" src="images/discord.jpg" alt="Discord Avatar" onerror="this.src='https://placehold.co/55x55/5865f2/FFFFFF?text=DIS'">
|
|
<div class="discord-info">
|
|
<div class="discord-name" id="discord-username">Loading...</div>
|
|
<div class="discord-status">
|
|
<div class="status-indicator" id="status-indicator"></div>
|
|
<span id="discord-status-text">Status: -</span>
|
|
</div>
|
|
</div>
|
|
<a href="#" id="dm-button" title="Send a DM (Opens Discord Profile)">
|
|
<i class="fas fa-comment-dots"></i> DM
|
|
</a>
|
|
</div>
|
|
|
|
<div class="discord-activity" id="activity-section">
|
|
<div class="activity-label">Activity:</div>
|
|
<div id="discord-activity-name">-</div>
|
|
<div id="discord-activity-time">Time: -</div>
|
|
|
|
<img id="activity-image" class="activity-game-image" src="" alt="Activity Image" onerror="this.style.display='none'">
|
|
</div>
|
|
|
|
<div class="discord-activity" id="spotify-section">
|
|
<div class="activity-label">Listening on Spotify:</div>
|
|
|
|
<div class="spotify-flex-content">
|
|
<img id="spotify-image" class="spotify-image-small" src="" alt="Spotify Album Cover" onerror="this.style.display='none'" >
|
|
|
|
<div style="flex-grow: 1; align-self: center; overflow: hidden; display: flex; flex-direction: column; gap: 2px;">
|
|
<div id="discord-spotify-info" style="font-weight: 600; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;">-</div>
|
|
|
|
<div id="spotify-progress-container">
|
|
<div id="spotify-progress-bar"></div>
|
|
</div>
|
|
|
|
<div class="time-info" id="spotify-time-info">
|
|
<span id="spotify-current-time">0:00</span>
|
|
<span id="spotify-duration">0:00</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="github-repos animate-in">
|
|
<h3><i class="fab fa-github"></i> Github Repos</h3>
|
|
|
|
<a href="https://github.com/luuooss" target="_blank" class="repo-link">
|
|
<span><i class="fas fa-user-circle"></i> Profil (luuooss)</span>
|
|
<i class="fas fa-arrow-right"></i>
|
|
</a>
|
|
|
|
<a href="https://github.com/luuooss/module-patcher" target="_blank" class="repo-link">
|
|
<span><i class="fas fa-code"></i> Module Patcher</span>
|
|
<i class="fas fa-arrow-right"></i>
|
|
</a>
|
|
|
|
<a href="https://github.com/luuooss/remove-text-from-filenames" target="_blank" class="repo-link">
|
|
<span><i class="fab fa-roblox"></i> Remove Text Form Files Names</span>
|
|
<i class="fas fa-arrow-right"></i>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.querySelector('.preload-screen').addEventListener('click', function() {
|
|
this.style.display = 'none';
|
|
document.querySelector('.main-content').style.opacity = '1';
|
|
|
|
document.querySelector('.discord-box').classList.add('animate-in');
|
|
document.querySelector('.github-repos').classList.add('animate-in');
|
|
|
|
fetchDiscordStatus();
|
|
});
|
|
|
|
const titleText = "2uf";
|
|
let currentIndex = 0;
|
|
let isDeleting = false;
|
|
const typingSpeed = 150;
|
|
|
|
function typeTitle() {
|
|
const currentTitle = titleText.slice(0, currentIndex) + "|";
|
|
document.title = currentTitle;
|
|
|
|
if (!isDeleting && currentIndex < titleText.length) {
|
|
currentIndex++;
|
|
} else if (isDeleting && currentIndex > 0) {
|
|
currentIndex--;
|
|
}
|
|
|
|
if (currentIndex === titleText.length && !isDeleting) {
|
|
setTimeout(() => isDeleting = true, 1000);
|
|
} else if (currentIndex === 0 && isDeleting) {
|
|
isDeleting = false;
|
|
}
|
|
|
|
setTimeout(typeTitle, isDeleting ? typingSpeed / 2 : typingSpeed);
|
|
}
|
|
|
|
typeTitle();
|
|
|
|
const userId = "1316227800281124976";
|
|
let spotifyUrl = "#";
|
|
let spotifyProgressInterval;
|
|
|
|
function formatTime(ms) {
|
|
const totalSeconds = Math.floor(ms / 1000);
|
|
const minutes = Math.floor(totalSeconds / 60);
|
|
const seconds = Math.floor(totalSeconds % 60);
|
|
return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
|
|
}
|
|
|
|
function formatDuration(startTimestamp) {
|
|
const now = Date.now();
|
|
const diff = now - startTimestamp;
|
|
const minutes = Math.floor(diff / 60000);
|
|
const seconds = Math.floor((diff % 60000) / 1000);
|
|
return `${minutes}m ${seconds}s`;
|
|
}
|
|
|
|
function updateSpotifyProgress(startTimestamp, endTimestamp) {
|
|
const now = Date.now();
|
|
const start = new Date(startTimestamp).getTime();
|
|
const end = new Date(endTimestamp).getTime();
|
|
const duration = end - start;
|
|
let current = now - start;
|
|
|
|
if (current > duration) {
|
|
current = duration;
|
|
}
|
|
|
|
const progressPercent = (current / duration) * 100;
|
|
const progressBar = document.getElementById('spotify-progress-bar');
|
|
const currentTimeElement = document.getElementById('spotify-current-time');
|
|
const durationElement = document.getElementById('spotify-duration');
|
|
|
|
if (progressBar && currentTimeElement && durationElement) {
|
|
progressBar.style.width = `${progressPercent}%`;
|
|
currentTimeElement.textContent = formatTime(current);
|
|
durationElement.textContent = formatTime(duration);
|
|
}
|
|
}
|
|
|
|
|
|
async function fetchDiscordStatus() {
|
|
clearInterval(spotifyProgressInterval);
|
|
|
|
try {
|
|
let data = null;
|
|
const maxRetries = 3;
|
|
for (let i = 0; i < maxRetries; i++) {
|
|
try {
|
|
const res = await fetch(`https://api.lanyard.rest/v1/users/${userId}`);
|
|
data = await res.json();
|
|
if (data.success) break;
|
|
} catch (e) {
|
|
if (i < maxRetries - 1) {
|
|
const delay = Math.pow(2, i) * 1000;
|
|
await new Promise(resolve => setTimeout(resolve, delay));
|
|
} else {
|
|
throw e;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!data || !data.success) return;
|
|
|
|
const d = data.data;
|
|
|
|
const avatarURL = `https://cdn.discordapp.com/avatars/${d.discord_user.id}/${d.discord_user.avatar}.png?size=128`;
|
|
document.getElementById("discord-avatar").src = avatarURL;
|
|
|
|
const username = `${d.discord_user.username}`;
|
|
document.getElementById("discord-username").textContent = username;
|
|
|
|
const statusText = {
|
|
online: "Online",
|
|
idle: "Idle",
|
|
dnd: "Do Not Disturb",
|
|
offline: "Offline"
|
|
};
|
|
|
|
document.getElementById("discord-status-text").textContent = statusText[d.discord_status] || d.discord_status;
|
|
|
|
const statusIndicator = document.getElementById("status-indicator");
|
|
statusIndicator.className = "status-indicator";
|
|
statusIndicator.classList.add(`status-${d.discord_status}`);
|
|
|
|
document.getElementById("activity-section").style.display = "none";
|
|
document.getElementById("spotify-section").style.display = "none";
|
|
|
|
const game = d.activities.find(a => a.type === 0);
|
|
const gameImg = document.getElementById("activity-image");
|
|
|
|
gameImg.classList.add('activity-game-image');
|
|
|
|
|
|
if (game) {
|
|
document.getElementById("activity-section").style.display = "flex";
|
|
document.getElementById("discord-activity-name").textContent = game.name;
|
|
|
|
if (game.timestamps?.start) {
|
|
document.getElementById("discord-activity-time").textContent = `For: ${formatDuration(game.timestamps.start)}`;
|
|
} else {
|
|
document.getElementById("discord-activity-time").textContent = "Time: unknown";
|
|
}
|
|
|
|
if (game.assets?.large_image) {
|
|
let imgKey = game.assets.large_image;
|
|
if (imgKey.startsWith("mp:external")) {
|
|
gameImg.src = imgKey.replace(/^mp:/, "https:");
|
|
} else {
|
|
gameImg.src = `https://cdn.discordapp.com/app-assets/${game.application_id}/${imgKey}.png`;
|
|
}
|
|
gameImg.style.display = "block";
|
|
} else {
|
|
gameImg.style.display = "none";
|
|
}
|
|
} else {
|
|
gameImg.style.display = "none";
|
|
}
|
|
|
|
const spotifyImg = document.getElementById("spotify-image");
|
|
|
|
if (d.listening_to_spotify && d.spotify) {
|
|
document.getElementById("spotify-section").style.display = "flex";
|
|
const song = `${d.spotify.song} - ${d.spotify.artist}`;
|
|
document.getElementById("discord-spotify-info").textContent = song;
|
|
|
|
spotifyUrl = `https://open.spotify.com/track/${d.spotify.track_id}`;
|
|
|
|
spotifyImg.src = d.spotify.album_art_url;
|
|
spotifyImg.style.display = "block";
|
|
|
|
const { start, end } = d.spotify.timestamps;
|
|
updateSpotifyProgress(start, end);
|
|
|
|
spotifyProgressInterval = setInterval(() => {
|
|
updateSpotifyProgress(start, end);
|
|
}, 1000);
|
|
|
|
} else {
|
|
spotifyUrl = "#";
|
|
}
|
|
} catch (error) {
|
|
console.error("Error fetching Discord status:", error);
|
|
document.getElementById("discord-username").textContent = "Load error";
|
|
document.getElementById("discord-status-text").textContent = "Status: unknown";
|
|
spotifyUrl = "#";
|
|
}
|
|
}
|
|
|
|
document.getElementById('dm-button').addEventListener('click', function(e) {
|
|
e.stopPropagation();
|
|
window.open(`https://discord.com/users/${userId}`, '_blank');
|
|
});
|
|
|
|
document.getElementById('discord-profile').addEventListener('click', function(e) {
|
|
if (document.getElementById("spotify-section").style.display === "flex" && spotifyUrl !== "#") {
|
|
window.open(spotifyUrl, '_blank');
|
|
} else {
|
|
window.open(`https://discord.com/users/${userId}`, '_blank');
|
|
}
|
|
});
|
|
|
|
let statusInterval;
|
|
document.addEventListener('visibilitychange', function() {
|
|
if (document.visibilityState === 'visible') {
|
|
fetchDiscordStatus();
|
|
statusInterval = setInterval(fetchDiscordStatus, 10000);
|
|
} else {
|
|
clearInterval(statusInterval);
|
|
clearInterval(spotifyProgressInterval);
|
|
}
|
|
});
|
|
|
|
if (document.querySelector('.preload-screen').style.display === 'none') {
|
|
statusInterval = setInterval(fetchDiscordStatus, 10000);
|
|
}
|
|
</script>
|
|
</body>
|
|
</html> |