lava / me.html
Reaperxxxx's picture
Update me.html
6769a8c verified
Raw
History Blame Contribute Delete
22.3 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Finral - Telegram Profile</title>
<script src="https://telegram.org/js/telegram-web-app.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #0a0a0a 0%, #1a1a2e 50%, #16213e 100%);
color: #e0e6ed;
padding: 0;
margin: 0;
min-height: 100vh;
position: relative;
overflow-x: hidden;
max-width: 100vw;
}
.header {
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
border-bottom: 2px solid #00bcd4;
padding: 10px 10px 0;
text-align: center;
box-shadow: 0 4px 20px rgba(0, 188, 212, 0.3);
position: relative;
}
.header::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(45deg, transparent 30%, rgba(0, 188, 212, 0.1) 50%, transparent 70%);
animation: shimmer 3s infinite;
}
@keyframes shimmer {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
.page-title {
font-size: 1.8rem;
font-weight: 900;
background: linear-gradient(45deg, #00bcd4, #87ceeb, #ffffff, #00bcd4);
background-size: 300% 300%;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 3px;
text-shadow: 0 0 30px rgba(0, 188, 212, 0.8);
animation: gradientShift 4s ease-in-out infinite;
letter-spacing: 1px;
position: relative;
z-index: 3;
}
.page-title::after {
content: 'πŸ‘€';
position: absolute;
right: -30px;
top: -3px;
font-size: 1rem;
animation: spark 2s infinite;
}
@keyframes gradientShift {
0%, 100% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
}
@keyframes spark {
0%, 100% { transform: rotate(0deg) scale(1); opacity: 0.7; }
50% { transform: rotate(15deg) scale(1.2); opacity: 1; }
}
.creator {
font-size: 0.75rem;
background: linear-gradient(45deg, #87ceeb, #00bcd4);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 5px;
font-weight: 600;
letter-spacing: 0.5px;
position: relative;
z-index: 3;
}
.page-subtitle {
font-size: 0.7rem;
color: rgba(135, 206, 235, 0.8);
margin-bottom: 15px;
font-style: italic;
font-weight: 300;
position: relative;
z-index: 3;
}
.banner-container {
position: relative;
margin-bottom: 0;
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
padding: 0;
}
.banner {
width: 100%;
height: 140px;
object-fit: cover;
border-radius: 0;
border: 2px solid #00bcd4;
border-left: none;
border-right: none;
box-shadow: 0 0 20px rgba(0, 188, 212, 0.3);
position: relative;
z-index: 1;
}
.banner-overlay {
position: absolute;
top: 2px;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(
to bottom,
rgba(0, 0, 0, 0.1) 0%,
rgba(0, 0, 0, 0.3) 50%,
rgba(26, 26, 46, 0.8) 100%
);
z-index: 2;
}
.pfp {
position: absolute;
bottom: -50px;
left: 50%;
transform: translateX(-50%);
width: 130px;
height: 130px;
object-fit: cover;
border-radius: 0%;
border: 4px solid #00bcd4;
box-shadow:
0 0 25px rgba(0, 188, 212, 0.8),
0 0 50px rgba(0, 188, 212, 0.4);
background: #1a1a2e;
z-index: 4;
}
.profile-glow {
position: absolute;
bottom: -50px;
left: 50%;
transform: translateX(-50%);
width: 120px;
height: 120px;
border-radius: 50%;
background: radial-gradient(circle, rgba(0, 188, 212, 0.4) 0%, rgba(0, 188, 212, 0.2) 50%, transparent 70%);
z-index: 3;
animation: profileGlow 3s ease-in-out infinite alternate;
}
@keyframes profileGlow {
0% { transform: translateX(-50%) scale(1); opacity: 0.6; }
100% { transform: translateX(-50%) scale(1.1); opacity: 0.9; }
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 60px 10px 20px;
width: 100%;
}
.user-info-section {
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
border: 1px solid #00bcd4;
border-radius: 10px;
padding: 12px;
margin-bottom: 15px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
position: relative;
overflow: hidden;
text-align: center;
}
.user-info-section::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, transparent, #00bcd4, transparent);
}
.username {
font-size: 1.3rem;
font-weight: bold;
color: #e0e6ed;
margin-bottom: 4px;
background: linear-gradient(45deg, #e0e6ed, #87ceeb);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.user-id {
font-size: 0.85rem;
color: #87ceeb;
margin-bottom: 0;
}
.stats-container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 15px;
margin-bottom: 15px;
}
.stats {
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
border: 1px solid #00bcd4;
border-radius: 10px;
padding: 15px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
position: relative;
overflow: hidden;
}
.stats::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, transparent, #00bcd4, transparent);
}
.stats h3 {
font-size: 1.1rem;
color: #00bcd4;
margin-bottom: 12px;
display: flex;
align-items: center;
gap: 6px;
border-bottom: 1px solid rgba(0, 188, 212, 0.3);
padding-bottom: 6px;
}
.stats h3::before {
content: '';
width: 3px;
height: 15px;
background: linear-gradient(45deg, #00bcd4, #87ceeb);
border-radius: 2px;
}
.stat-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
margin-bottom: 12px;
}
.stat-item {
background: rgba(0, 188, 212, 0.1);
border: 1px solid rgba(0, 188, 212, 0.3);
border-radius: 6px;
padding: 8px 6px;
text-align: center;
transition: all 0.3s ease;
}
.stat-item:hover {
border-color: #00bcd4;
box-shadow: 0 2px 8px rgba(0, 188, 212, 0.3);
transform: translateY(-1px);
}
.stat-value {
font-weight: bold;
color: #00bcd4;
font-size: 0.95rem;
display: block;
margin-bottom: 2px;
}
.stat-label {
font-size: 0.7rem;
color: #87ceeb;
line-height: 1;
}
.rank-badge {
display: inline-flex;
align-items: center;
gap: 4px;
background: linear-gradient(45deg, #00bcd4, #87ceeb);
color: #0a0a0a;
font-weight: bold;
padding: 4px 8px;
border-radius: 15px;
font-size: 0.75rem;
margin-bottom: 8px;
}
.progress {
margin-top: 10px;
height: 12px;
background: rgba(0, 0, 0, 0.3);
border-radius: 6px;
overflow: hidden;
border: 1px solid rgba(0, 188, 212, 0.3);
position: relative;
}
.bar {
height: 100%;
background: linear-gradient(90deg, #00bcd4, #87ceeb, #4caf50);
width: 0%;
transition: width 1.5s ease-in-out;
border-radius: 6px;
position: relative;
overflow: hidden;
}
.bar::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
animation: progressShine 2s infinite;
}
@keyframes progressShine {
0% { left: -100%; }
100% { left: 100%; }
}
.progress-text {
font-size: 0.7rem;
color: #87ceeb;
margin-top: 4px;
text-align: center;
}
.loading {
text-align: center;
color: #87ceeb;
font-size: 1rem;
padding: 40px 20px;
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
border: 1px solid #00bcd4;
border-radius: 10px;
margin: 20px;
}
.loading::after {
content: '';
display: inline-block;
width: 18px;
height: 18px;
border: 2px solid #87ceeb;
border-top: 2px solid #00bcd4;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-left: 8px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.error {
background: linear-gradient(135deg, #2d1b2d 0%, #4a1a2e 100%);
border: 1px solid #ff6b6b;
color: #ff9999;
text-align: center;
padding: 30px;
border-radius: 10px;
margin: 20px;
}
/* Mobile optimizations */
@media (max-width: 768px) {
.stats-container {
grid-template-columns: 1fr;
gap: 12px;
}
.stat-grid {
grid-template-columns: repeat(4, 1fr);
gap: 6px;
}
.stat-item {
padding: 6px 4px;
}
.stat-value {
font-size: 0.8rem;
}
.stat-label {
font-size: 0.65rem;
}
}
@media (max-width: 480px) {
.page-title {
font-size: 1.5rem;
letter-spacing: 0.5px;
}
.page-title::after {
right: -25px;
font-size: 0.9rem;
}
.creator {
font-size: 0.7rem;
}
.page-subtitle {
font-size: 0.65rem;
}
.banner {
height: 120px;
}
.pfp {
width: 80px;
height: 80px;
bottom: -40px;
border-width: 3px;
}
.profile-glow {
width: 100px;
height: 100px;
bottom: -40px;
}
.container {
padding: 50px 8px 20px;
}
.stats {
padding: 12px;
}
.username {
font-size: 1.1rem;
}
.user-info-section {
padding: 10px;
margin-bottom: 12px;
}
.stats-container {
gap: 10px;
margin-bottom: 12px;
}
.stat-grid {
grid-template-columns: 1fr 1fr;
gap: 4px;
}
.stat-item {
padding: 6px 4px;
}
.stat-value {
font-size: 0.8rem;
}
.stat-label {
font-size: 0.6rem;
}
.rank-badge {
font-size: 0.7rem;
padding: 3px 6px;
}
.progress {
height: 10px;
}
.progress-text {
font-size: 0.65rem;
}
}
/* Extra small screens */
@media (max-width: 360px) {
.page-title {
font-size: 1.3rem;
}
.banner {
height: 100px;
}
.pfp {
width: 70px;
height: 70px;
bottom: -35px;
border-width: 3px;
}
.profile-glow {
width: 90px;
height: 90px;
bottom: -35px;
}
.container {
padding: 45px 6px 20px;
}
.username {
font-size: 1rem;
}
.stats h3 {
font-size: 1rem;
}
.stat-value {
font-size: 0.75rem;
}
.stat-label {
font-size: 0.55rem;
}
}
</style>
</head>
<body>
<div class="header">
<div class="page-title">FINRAL | USER PROFILE</div>
<div class="creator">✨ Crafted with Excellence by Saul ✨</div>
<div class="page-subtitle">"Your Telegram Journey"</div>
</div>
<div id="profile-content" class="loading">Loading profile...</div>
<script>
Telegram.WebApp.ready();
const startParam = Telegram.WebApp.initDataUnsafe?.start_param;
function formatCode(code) {
return code.replace(/-(jpg|jpeg|png|webp|gif)$/i, '.$1');
}
function escapeHtml(text) {
return text.replace(/[&<>"']/g, m => ({
"&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;"
})[m]);
}
function getNextLevelXp(level) {
if (level <= 10) return 100;
if (level <= 20) return 200;
if (level <= 30) return 300;
if (level <= 40) return 400;
if (level <= 50) return 500;
return 600;
}
function getTotalXpForLevel(level) {
let total = 0;
for (let i = 1; i < level; i++) total += getNextLevelXp(i);
return total;
}
function getGlobalRank(level) {
if (level >= 300) return { rank: 'Legendary', emoji: 'πŸ”₯' };
if (level >= 200) return { rank: 'Master', emoji: 'πŸ‘‘' };
if (level >= 120) return { rank: 'Heroic', emoji: 'βš”οΈ' };
if (level >= 75) return { rank: 'Diamond', emoji: 'πŸ”·' };
if (level >= 45) return { rank: 'Platinum', emoji: 'πŸ’Ž' };
if (level >= 25) return { rank: 'Gold', emoji: 'πŸ₯‡' };
if (level >= 10) return { rank: 'Silver', emoji: 'πŸ₯ˆ' };
return { rank: 'Bronze', emoji: 'πŸ₯‰' };
}
function getGroupRank(level) {
if (level >= 101) return { rank: 'Legendary', emoji: 'πŸ”₯' };
if (level >= 51) return { rank: 'Master', emoji: 'πŸ‘‘' };
if (level >= 31) return { rank: 'Heroic', emoji: 'βš”οΈ' };
if (level >= 19) return { rank: 'Diamond', emoji: 'πŸ”·' };
if (level >= 13) return { rank: 'Platinum', emoji: 'πŸ’Ž' };
if (level >= 9) return { rank: 'Gold', emoji: 'πŸ₯‡' };
if (level >= 4) return { rank: 'Silver', emoji: 'πŸ₯ˆ' };
return { rank: 'Bronze', emoji: 'πŸ₯‰' };
}
function createProgressBar(currentXp, level) {
// Auto-correct level if user's XP is actually higher than level shown
while (currentXp >= getTotalXpForLevel(level + 1)) {
level++;
}
const prevXp = getTotalXpForLevel(level);
const nextXp = getTotalXpForLevel(level + 1);
const progress = currentXp - prevXp;
const needed = nextXp - prevXp;
return `
<div class="progress">
<div class="bar" style="width: 0%" data-target="${Math.min((progress / needed) * 100, 100).toFixed(1)}%"></div>
</div>
<div class="progress-text">${progress} / ${needed} XP to level ${level + 1}</div>
`;
}
function calculateGlobalProgress(groups) {
let totalCurrentProgress = 0;
let totalNeededProgress = 0;
let combinedLevel = 0;
groups.forEach(group => {
let groupLevel = group.level;
let groupXp = group.xp;
// Auto-correct level if user's XP is actually higher than level shown
while (groupXp >= getTotalXpForLevel(groupLevel + 1)) {
groupLevel++;
}
const prevXp = getTotalXpForLevel(groupLevel);
const nextXp = getTotalXpForLevel(groupLevel + 1);
const progress = groupXp - prevXp;
const needed = nextXp - prevXp;
totalCurrentProgress += progress;
totalNeededProgress += needed;
combinedLevel += groupLevel;
});
const globalProgressPercentage = totalNeededProgress > 0 ?
Math.min((totalCurrentProgress / totalNeededProgress) * 100, 100) : 0;
return {
currentProgress: totalCurrentProgress,
neededProgress: totalNeededProgress,
progressPercentage: globalProgressPercentage,
nextCombinedLevel: combinedLevel + groups.length
};
}
function animateBars() {
document.querySelectorAll('.bar').forEach(bar => {
const target = bar.getAttribute('data-target');
setTimeout(() => {
bar.style.width = target;
}, 100);
});
}
if (startParam) {
const parts = decodeURIComponent(startParam).split('__');
if (parts.length === 6) {
const [bannerCode, userId, username, pfpCode, groupId, groupNameRaw] = parts;
const fallbackPfp = 'https://files.catbox.moe/wjq5bl.jpeg';
const fallbackBanner = 'https://files.catbox.moe/khw4sn.jpeg';
const bannerUrl = bannerCode === 'nobanner' ? fallbackBanner : `https://files.catbox.moe/${formatCode(bannerCode)}`;
const pfpUrl = pfpCode === 'nopfp' ? fallbackPfp : `https://files.catbox.moe/${formatCode(pfpCode)}`;
const groupName = escapeHtml(groupNameRaw.replace(/_/g, ' '));
fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/info`)
.then(res => res.json())
.then(data => {
if (!data.status) throw new Error("User data fetch failed");
const {
totalXP, totalLevel, totalRoyalties, totalDailyMessages,
globalRank, groupRank, groups
} = data;
const globalRankObj = getGlobalRank(totalLevel);
const groupInfo = groups.find(g => g.groupId === groupId);
const userGroupRank = groupRank?.[groupId] ?? "β€”";
// Calculate global progress using all groups
const globalProgress = calculateGlobalProgress(groups);
let groupStatsHTML = `<div class="stat-item"><span class="stat-value">No Data</span><span class="stat-label">Group not found</span></div>`;
if (groupInfo) {
const groupRankObj = getGroupRank(groupInfo.level);
groupStatsHTML = `
<div class="stat-grid">
<div class="stat-item">
<span class="stat-value">${groupInfo.level}</span>
<span class="stat-label">πŸ”Ή Level</span>
</div>
<div class="stat-item">
<span class="stat-value">${groupInfo.xp.toLocaleString()}</span>
<span class="stat-label">✨ XP</span>
</div>
<div class="stat-item">
<span class="stat-value">${groupInfo.royalties.toLocaleString()}</span>
<span class="stat-label">πŸ‘‘ Royalties</span>
</div>
<div class="stat-item">
<span class="stat-value">${groupInfo.dailyMessages}</span>
<span class="stat-label">πŸ’¬ Daily</span>
</div>
</div>
<div style="text-align: center;">
<div class="rank-badge">
πŸ₯‡ Rank #${userGroupRank} β€” ${groupRankObj.emoji} ${groupRankObj.rank}
</div>
</div>
${createProgressBar(groupInfo.xp, groupInfo.level)}
`;
}
document.getElementById('profile-content').innerHTML = `
<div class="banner-container">
<img src="${bannerUrl}" alt="Banner Image" class="banner" />
<div class="banner-overlay"></div>
<div class="profile-glow"></div>
<img src="${pfpUrl}" alt="Profile Picture" class="pfp" />
</div>
<div class="container">
<div class="user-info-section">
<div class="username">@${escapeHtml(username)}</div>
<div class="user-id">πŸ†” ${userId}</div>
</div>
<div class="stats-container">
<div class="stats">
<h3>🌍 Global Stats</h3>
<div class="stat-grid">
<div class="stat-item">
<span class="stat-value">${totalLevel}</span>
<span class="stat-label">🧬 Level</span>
</div>
<div class="stat-item">
<span class="stat-value">${totalXP.toLocaleString()}</span>
<span class="stat-label">✨ XP</span>
</div>
<div class="stat-item">
<span class="stat-value">${totalRoyalties.toLocaleString()}</span>
<span class="stat-label">πŸ‘‘ Royalties</span>
</div>
<div class="stat-item">
<span class="stat-value">${totalDailyMessages}</span>
<span class="stat-label">πŸ’¬ Daily</span>
</div>
</div>
<div style="text-align: center;">
<div class="rank-badge">
πŸ… Global #${globalRank ?? "β€”"} β€” ${globalRankObj.emoji} ${globalRankObj.rank}
</div>
</div>
<div class="progress">
<div class="bar" style="width: 0%" data-target="${globalProgress.progressPercentage.toFixed(1)}%"></div>
</div>
<div class="progress-text">${globalProgress.currentProgress} / ${globalProgress.neededProgress} XP to next level</div>
</div>
<div class="stats">
<h3>πŸ“ ${groupName}</h3>
${groupStatsHTML}
</div>
</div>
</div>
`;
animateBars();
})
.catch(err => {
console.error(err);
document.getElementById('profile-content').innerHTML = `<div class="error">⚠️ Failed to load user data.</div>`;
});
} else {
document.getElementById('profile-content').innerHTML = `<div class="error">⚠️ Invalid profile data format.</div>`;
}
} else {
document.getElementById('profile-content').innerHTML = `<div class="error">❌ No profile data provided (start_param missing).</div>`;
}
</script>
</body>
</html>