Index
Index
DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MineConv - Conversor Avançado</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-
awesome/6.4.0/css/all.min.css">
<style>
/* --- Base & Reset --- */
:root {
--primary-color: #00ffff; /* Cyan */
--secondary-color: #ff00ff; /* Magenta */
--background-color: #0d0d1a; /* Dark blue/purple */
--surface-color: #1a1a2e;
--text-color: #e0e0e0;
--text-darker: #a0a0a0;
--success-color: #00ff7f; /* Spring Green */
--error-color: #ff4d4d;
--warning-color: #ffcc00; /* Yellowish */
--glow-color-primary: rgba(0, 255, 255, 0.7);
--glow-color-secondary: rgba(255, 0, 255, 0.7);
--font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
--alt-font-family: 'Roboto', sans-serif; /* Alternative font */
--current-font-family: var(--font-family); /* Default font */
--border-radius: 8px; /* Slightly more rounded */
--transition-speed: 0.35s; /* Slightly slower for smoother feel */
--shadow-color-light: rgba(0, 255, 255, 0.3);
--shadow-color-dark: rgba(255, 0, 255, 0.3);
}
body {
font-family: var(--current-font-family); /* Use current font variable */
background:
url('https://i.imgur.com/YOUR_8K_ANIMATED_WALLPAPER_URL.gif'); /* Replace with your
8k animated wallpaper URL */
background-size: cover;
background-attachment: fixed; /* Optional: for fixed background */
color: var(--text-color);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
overflow: hidden; /* Prevent scrollbars during transitions */
position: relative; /* For absolute positioning of elements */
}
@keyframes subtle-glow {
from { opacity: 0.6; }
to { opacity: 1; }
}
.screen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 20px;
opacity: 0;
visibility: hidden;
transition: opacity var(--transition-speed) ease-in-out, visibility
var(--transition-speed);
background-color: transparent; /* Allow body gradient */
z-index: 1;
}
.screen.active {
opacity: 1;
visibility: visible;
z-index: 10; /* Bring active screen to front */
}
.popup {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0.9);
background-color: rgba(26, 26, 46, 0.95); /* Slightly transparent surface
*/
backdrop-filter: blur(5px); /* Frosted glass effect */
border: 1px solid var(--primary-color);
box-shadow: 0 0 25px var(--glow-color-primary), 0 0 10px rgba(0,0,0,0.5);
padding: 30px 40px;
border-radius: var(--border-radius);
z-index: 100;
opacity: 0;
visibility: hidden;
transition: opacity var(--transition-speed) ease, transform var(--
transition-speed) ease, visibility var(--transition-speed);
min-width: 320px;
max-width: 90%;
text-align: center;
}
.popup.active {
opacity: 1;
visibility: visible;
transform: translate(-50%, -50%) scale(1);
}
.popup h2 {
color: var(--primary-color);
margin-bottom: 20px;
text-shadow: 0 0 8px var(--glow-color-primary);
font-weight: 600;
}
.popup p {
margin-bottom: 25px;
color: var(--text-darker);
line-height: 1.6;
}
.popup .button-group {
display: flex;
justify-content: center;
gap: 15px;
flex-wrap: wrap; /* Allow buttons to wrap on small screens */
}
.button {
background: linear-gradient(45deg, var(--primary-color), var(--secondary-
color));
color: var(--background-color);
border: none;
padding: 12px 28px; /* Slightly larger padding */
border-radius: var(--border-radius);
font-size: 1rem;
font-weight: bold;
cursor: pointer;
transition: transform var(--transition-speed) ease, box-shadow var(--
transition-speed) ease, background var(--transition-speed) ease;
text-align: center;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 10px; /* Increased gap */
text-decoration: none;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
}
.button:hover {
transform: translateY(-4px) scale(1.03); /* Enhanced hover effect */
box-shadow: 0 8px 20px var(--shadow-color-light), 0 8px 20px var(--
shadow-color-dark);
}
.button:active {
transform: translateY(-1px) scale(0.98);
}
.button.secondary {
background: var(--surface-color);
color: var(--primary-color);
border: 1px solid var(--primary-color);
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}
.button.secondary:hover {
background: rgba(0, 255, 255, 0.1); /* Subtle hover background */
box-shadow: 0 0 15px var(--glow-color-primary), 0 4px 10px rgba(0, 0, 0,
0.3);
transform: translateY(-4px) scale(1.03);
}
.button.danger {
background: linear-gradient(45deg, var(--error-color), #ff0055);
color: white;
}
.button.danger:hover {
box-shadow: 0 8px 20px rgba(255, 77, 77, 0.5);
}
.button i {
font-size: 1.1em;
line-height: 1; /* Prevent icon from affecting button height */
}
.icon-button {
background: none;
border: none;
color: var(--primary-color);
font-size: 1.6rem; /* Slightly larger */
cursor: pointer;
transition: color var(--transition-speed) ease, text-shadow var(--
transition-speed) ease, transform var(--transition-speed) ease;
padding: 8px; /* More clickable area */
position: relative; /* For badge positioning */
line-height: 1;
}
.icon-button:hover {
color: var(--secondary-color);
text-shadow: 0 0 12px var(--glow-color-secondary);
transform: scale(1.1);
}
.icon-button .badge {
position: absolute;
top: 0;
right: 0;
background-color: var(--error-color);
color: white;
border-radius: 50%;
padding: 2px 6px;
font-size: 0.7rem;
font-weight: bold;
line-height: 1;
transform: translate(40%, -40%);
pointer-events: none; /* Don't interfere with clicks */
}
.input-field {
background-color: rgba(26, 26, 46, 0.8); /* Slightly transparent surface
*/
border: 1px solid var(--primary-color);
border-radius: var(--border-radius);
padding: 12px 18px; /* Increased padding */
color: var(--text-color);
font-size: 1rem;
width: 100%;
margin-bottom: 18px; /* Increased margin */
transition: border-color var(--transition-speed) ease, box-shadow var(--
transition-speed) ease;
}
.input-field:focus {
outline: none;
border-color: var(--secondary-color);
box-shadow: 0 0 12px var(--glow-color-secondary);
}
.input-group {
position: relative;
margin-bottom: 18px;
}
.input-group .icon-button {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
font-size: 1.2rem;
padding: 5px; /* Smaller padding for inline icon */
}
#loading-screen h1 {
font-size: 3rem; /* Larger title */
color: var(--primary-color);
text-shadow: 0 0 15px var(--glow-color-primary), 0 0 5px white; /*
Enhanced glow */
margin-bottom: 40px;
letter-spacing: 2px;
}
#loading-spinner {
border: 6px solid var(--surface-color);
border-top: 6px solid var(--primary-color);
border-radius: 50%;
width: 50px;
height: 50px;
animation: spin 1.2s linear infinite;
margin-bottom: 20px; /* Space below spinner */
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.login-option {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px; /* Increased gap */
}
.login-option i {
font-size: 3.5rem; /* Larger icons */
color: var(--primary-color);
text-shadow: 0 0 12px var(--glow-color-primary);
margin-bottom: 15px;
transition: transform 0.3s ease;
}
.login-option:hover i {
transform: scale(1.1);
}
#create-account-btn.button.secondary {
margin-top: 20px;
}
/* --- Mode Select Screen --- */
#mode-select-screen h1 {
font-size: 2.5rem;
margin-bottom: 30px;
color: var(--primary-color);
text-shadow: 0 0 10px var(--glow-color-primary);
}
#mode-select-screen .mode-options {
display: flex;
gap: 40px;
margin-top: 50px;
}
.mode-option {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
}
.mode-option i {
font-size: 3.5rem;
color: var(--primary-color);
text-shadow: 0 0 12px var(--glow-color-primary);
margin-bottom: 15px;
transition: transform 0.3s ease;
}
.mode-option:hover i {
transform: scale(1.1);
}
.main-header {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 30px; /* Vertical padding */
position: absolute;
top: 0;
left: 0;
background-color: rgba(13, 13, 26, 0.6); /* Semi-transparent header */
backdrop-filter: blur(8px);
z-index: 50;
border-bottom: 1px solid rgba(0, 255, 255, 0.2);
}
.header-left {
display: flex;
align-items: center;
gap: 15px;
}
#clock-display {
font-size: 1.3rem;
font-weight: bold;
color: var(--primary-color);
text-shadow: 0 0 5px var(--glow-color-primary);
transition: color 0.5s ease, text-shadow 0.5s ease; /* Animation for
time change */
}
#clock-display.animated {
color: var(--secondary-color);
text-shadow: 0 0 8px var(--glow-color-secondary);
}
.header-right {
display: flex;
align-items: center;
gap: 15px; /* Space between icons */
}
.limits-display {
display: flex;
align-items: center;
gap: 8px;
font-size: 1.1rem; /* Slightly smaller */
cursor: pointer;
padding: 8px 12px;
border-radius: var(--border-radius);
transition: background-color var(--transition-speed) ease, color var(--
transition-speed) ease;
color: var(--text-darker);
}
.limits-display:hover {
background-color: rgba(255, 255, 255, 0.1);
color: var(--text-color);
}
.limits-display i {
color: var(--warning-color); /* Lightning color */
font-size: 1.2em;
}
#rules-btn.icon-button {
margin-right: 5px;
}
.account-menu {
position: relative;
}
#accounts-list-btn.icon-button {
margin-right: 5px;
}
#account-menu-popup {
position: absolute;
top: 55px; /* Position below the icon group */
right: 0;
background-color: var(--surface-color);
border: 1px solid var(--primary-color);
border-radius: var(--border-radius);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.5); /* Stronger shadow */
z-index: 110;
width: 220px; /* Wider menu */
overflow: hidden; /* Ensures buttons fit */
opacity: 0;
visibility: hidden;
transform: translateY(-10px) scale(0.95);
transform-origin: top right;
transition: opacity var(--transition-speed) ease, transform var(--
transition-speed) ease, visibility var(--transition-speed) ease;
}
#account-menu-popup.active {
opacity: 1;
visibility: visible;
transform: translateY(0) scale(1);
}
#account-menu-popup button {
display: flex; /* Use flex for alignment */
align-items: center; /* Align icon and text */
width: 100%;
padding: 14px 20px; /* More padding */
background: none;
border: none;
color: var(--text-color);
text-align: left;
cursor: pointer;
transition: background-color var(--transition-speed) ease, color var(--
transition-speed) ease;
font-size: 1rem; /* Standardize font size */
gap: 12px; /* Space between icon and text */
}
#account-menu-popup button i {
/* margin-right: 10px; */ /* Replaced by gap */
color: var(--primary-color);
font-size: 1.1rem; /* Adjust icon size */
width: 20px; /* Align icons */
text-align: center;
transition: color var(--transition-speed) ease;
}
#account-menu-popup button:hover {
background-color: rgba(0, 255, 255, 0.15); /* Primary color tint */
color: white;
}
#account-menu-popup button:hover i {
color: var(--secondary-color);
}
.main-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
flex-grow: 1; /* Take remaining space */
width: 100%;
max-width: 800px; /* Limit content width */
margin: 0 auto; /* Center content */
padding: 20px;
/* margin-top: 60px; */ /* Removed, padding-top on screen handles it */
}
.main-content h1 {
font-size: 2.8rem; /* Larger title */
color: var(--primary-color);
text-shadow: 0 0 12px var(--glow-color-primary);
margin-bottom: 50px; /* More space */
text-align: center;
}
.main-actions {
display: grid; /* Use grid for better layout */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); /*
Responsive columns */
gap: 25px; /* Increased gap */
width: 100%;
margin-top: 20px;
}
.main-actions .button {
width: 100%; /* Make buttons fill grid cells */
}
.main-actions .button.plus-feature {
opacity: 0.7; /* Indicate Plus feature */
cursor: not-allowed;
}
.main-actions .button.plus-feature i.fa-star {
margin-left: 5px;
}
#skin-preview {
width: 80px; /* Adjust as needed */
height: 160px; /* Adjust as needed */
background-color: grey; /* Default skin color */
display: flex;
justify-content: center;
align-items: center;
color: white;
font-size: 0.8rem;
text-align: center;
z-index: 1; /* Above grid */
cursor: grab;
transform-style: preserve-3d; /* Needed for 3D rotation */
transition: background-image 0.5s ease;
}
#skin-preview.loaded {
background-color: transparent; /* Show actual skin if loaded */
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
.wizard-back-button {
position: absolute;
top: 15px;
left: 15px;
font-size: 1.2rem; /* Smaller back button */
padding: 5px;
}
.delivery-time-inputs {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
gap: 10px;
margin-bottom: 20px;
}
.delivery-time-inputs label {
display: block;
font-size: 0.85rem;
color: var(--text-darker);
margin-bottom: 5px;
}
.delivery-time-inputs input {
padding: 8px 10px;
font-size: 0.9rem;
margin-bottom: 0; /* Remove default margin */
}
@keyframes pulse {
0% { transform: scale(1); filter: drop-shadow(0 0 10px var(--glow-color-
primary)); }
50% { transform: scale(1.1); filter: drop-shadow(0 0 15px var(--glow-
color-secondary)); }
100% { transform: scale(1); filter: drop-shadow(0 0 10px var(--glow-
color-primary)); }
}
#chatbot-popup {
width: 380px; /* Wider chat */
height: 500px; /* Taller chat */
top: auto;
left: auto;
bottom: 90px; /* Position above toggle */
right: 25px;
transform: scale(0.9) translateY(20px); /* Adjust initial transform */
transform-origin: bottom right;
display: flex;
flex-direction: column;
padding: 0; /* Remove default padding */
border-radius: var(--border-radius); /* Ensure consistent radius */
overflow: hidden; /* Clip content */
}
#chatbot-popup.active {
transform: scale(1) translateY(0);
}
.chatbot-header {
background: linear-gradient(45deg, var(--primary-color), var(--secondary-
color));
color: var(--background-color);
padding: 12px 18px; /* Adjust padding */
/* border-top-left-radius: var(--border-radius); */ /* Removed due to
overflow:hidden */
/* border-top-right-radius: var(--border-radius); */
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
}
.chatbot-header h2 {
font-size: 1.2rem; /* Larger header */
margin: 0;
color: var(--background-color);
text-shadow: none;
font-weight: 600;
}
#close-chatbot-btn {
background: none;
border: none;
color: var(--background-color);
font-size: 1.4rem; /* Larger close button */
cursor: pointer;
padding: 5px;
opacity: 0.8;
transition: opacity 0.3s ease;
}
#close-chatbot-btn:hover {
opacity: 1;
}
.chatbot-messages {
flex-grow: 1;
overflow-y: auto;
padding: 20px; /* More padding */
background-color: var(--surface-color); /* Match popup background */
display: flex;
flex-direction: column;
gap: 12px; /* Increased gap */
}
/* Scrollbar styling */
.chatbot-messages::-webkit-scrollbar {
width: 8px;
}
.chatbot-messages::-webkit-scrollbar-track {
background: rgba(0,0,0,0.2);
border-radius: 4px;
}
.chatbot-messages::-webkit-scrollbar-thumb {
background: linear-gradient(var(--primary-color), var(--secondary-
color));
border-radius: 4px;
}
.chatbot-messages::-webkit-scrollbar-thumb:hover {
background: linear-gradient(var(--secondary-color), var(--primary-
color));
}
.chat-message {
padding: 10px 15px; /* More padding */
border-radius: var(--border-radius);
max-width: 85%; /* Slightly wider max */
word-wrap: break-word;
line-height: 1.5;
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}
.chat-message.user {
background: linear-gradient(45deg, var(--primary-color), #00c6ff); /*
User message gradient */
color: var(--background-color);
align-self: flex-end;
border-bottom-right-radius: 2px; /* Slightly sharper corner */
}
.chat-message.bot {
background-color: #2a2a3e; /* Slightly different background */
color: var(--text-color);
align-self: flex-start;
border-bottom-left-radius: 2px;
}
.chatbot-input {
display: flex;
border-top: 1px solid var(--primary-color);
padding: 12px; /* More padding */
background-color: var(--surface-color); /* Match popup background */
/* border-bottom-left-radius: var(--border-radius); */ /* Removed due to
overflow:hidden */
/* border-bottom-right-radius: var(--border-radius); */
}
#chatbot-input-field {
flex-grow: 1;
margin-bottom: 0; /* Override default margin */
border-radius: var(--border-radius) 0 0 var(--border-radius);
border-right: none;
padding: 12px 18px; /* Match button height */
}
#chatbot-send-btn {
border-radius: 0 var(--border-radius) var(--border-radius) 0;
padding: 12px 18px; /* Match input height */
font-size: 1.1rem; /* Larger send icon */
}
#edit-mode-controls {
position: fixed;
bottom: 25px;
left: 50%;
transform: translateX(-50%);
background-color: rgba(26, 26, 46, 0.9); /* Surface color with
transparency */
padding: 12px 25px; /* More padding */
border-radius: var(--border-radius);
border: 1px solid var(--primary-color);
box-shadow: 0 0 20px var(--glow-color-primary);
z-index: 150;
display: flex;
gap: 20px; /* More gap */
}
#rules-popup li {
margin-bottom: 10px; /* Space between rules */
line-height: 1.6;
position: relative; /* For custom bullet */
}
#rules-popup li::before {
content: '\f054'; /* Font Awesome 'angle-right' icon */
font-family: 'Font Awesome 6 Free';
font-weight: 900; /* Solid style */
position: absolute;
left: -20px; /* Position bullet to the left */
top: 4px; /* Adjust vertical alignment */
color: var(--primary-color); /* Bullet color */
}
#rules-popup h3 {
color: var(--secondary-color);
margin-top: 20px;
margin-bottom: 10px;
border-bottom: 1px dashed var(--secondary-color);
padding-bottom: 5px;
}
</style>
</head>
<body>
<main class="main-content">
<h1 id="main-title" class="draggable">Converter Minecraft Pirata para
Original</h1>
<div class="main-actions">
<button id="convert-btn" class="button draggable">
<i class="fas fa-exchange-alt"></i>Converter Pirata → Original
</button>
<button id="convert-reverse-btn" class="button secondary draggable
plus-feature">
<i class="fas fa-exchange-alt fa-flip-horizontal"></i>Converter
Original → Pirata <i class="fas fa-star" style="color: gold; font-size:
0.8em;"></i>
</button>
<button id="manage-accounts-btn" class="button secondary draggable">
<i class="fas fa-users-cog"></i>Gerenciar Contas
</button>
<button id="free-capes-btn" class="button secondary draggable plus-
feature">
<i class="fas fa-scroll"></i>Capas Grátis <i class="fas fa-star"
style="color: gold; font-size: 0.8em;"></i>
</button>
<button id="hypixel-tags-btn" class="button secondary draggable plus-
feature">
<i class="fas fa-tags"></i>Tags Hypixel <i class="fas fa-star"
style="color: gold; font-size: 0.8em;"></i>
</button>
<button id="mushmc-tags-btn" class="button secondary draggable plus-
feature">
<i class="fas fa-tags"></i>Tags MushMC <i class="fas fa-star"
style="color: gold; font-size: 0.8em;"></i>
</button>
<button id="hylex-tags-btn" class="button secondary draggable plus-
feature">
<i class="fas fa-crown"></i>Tags Hylex <i class="fas fa-star"
style="color: gold; font-size: 0.8em;"></i>
</button>
<button id="flamemc-tags-btn" class="button secondary draggable plus-
feature">
<i class="fas fa-fire"></i>Tags FlameMC <i class="fas fa-star"
style="color: gold; font-size: 0.8em;"></i>
</button>
<button id="stardix-tags-btn" class="button secondary draggable plus-
feature">
<i class="fas fa-star-of-life"></i>Tags Stardix <i class="fas fa-
star" style="color: gold; font-size: 0.8em;"></i>
</button>
</div>
</main>
<script>
// --- Constants and State ---
const LOADING_TIME = 3000; // 3 seconds loading
const DAILY_LIMIT = 3;
const BANNED_KEYWORDS_NICK = ['hack', 'cheat', 'crack', 'bot', 'exploit',
'script', 'auto', 'burla', 'roubar']; // Nickname keywords
const BANNED_KEYWORDS_CHAT = ['xingamento_aqui', 'palavrão_aqui',
'insulto_aqui']; // Chatbot keywords
const MAX_TEMP_BANS = 3; // 3 temp bans before permanent
const MAX_PERMANENT_BANS = 3; // 3 permanent bans before final block
const MAX_NEW_ACCOUNT_CREATIONS = 5; // Limit for creating new accounts
after perm ban
const CHATBOT_BAN_DURATION_FAST_MESSAGES = 5 * 60 * 1000; // 5 minutes for
fast messages
const CHATBOT_BAN_DURATION_SWEARING = 5 * 60 * 1000; // 5 minutes for
swearing
const ACCOUNT_ABUSE_BAN_DURATION = 30 * 24 * 60 * 60 * 1000; // 30 days for
account abuse
let currentState = {
loggedInAs: null, // 'google' or 'guest'
currentScreen: 'loading-screen',
conversionLimits: DAILY_LIMIT,
lastLimitReset: null, // Store date string YYYY-MM-DD
isBanned: false,
banType: null, // 'temporary' or 'permanent'
banReason: '',
banExpiry: null, // Store timestamp for temporary bans
banHistory: [], // Store { reason: '...', type: '...', timestamp: ... }
permanentBanCount: 0, // Count how many permanent bans occurred
newAccountCreations: 0, // Count how many times 'Create New Account' was
used
createdAccounts: [], // Store { nick: '...', email: '...', skin: '...' }
elementPositions: {}, // Store { elementId: { top: '...', left: '...' } }
isEditMode: false,
originalPositions: {}, // Store original positions before dragging
unreadEmails: 0,
emails: [], // Store { id: ..., subject: '...', body: '...',
timestamp: ..., read: false }
deliveryTimerEnd: null, // Timestamp when delivery finishes
deliveryTimerInterval: null, // Interval ID for the countdown
deliveryData: null, // Store conversion data during timer
profilePic: null, // Store data URL of profile picture
language: 'pt-BR', // Default language
fontFamily: 'default', // 'default' or 'alt'
lastChatMessagesTimestamps: [], // For rate limiting chatbot messages
};
if (currentState.isBanned) {
showBanScreen();
return; // Stop further initialization if banned
}
function loadState() {
try {
const savedData = localStorage.getItem('mineConvState_v2');
if (savedData) {
const parsedData = JSON.parse(savedData);
const stateString = JSON.stringify(parsedData.state);
const checksum = btoa(stateString).substring(0, 10);
function showPopup(popupId) {
if (currentState.isBanned && !['ban-popup', 'unban-sim-popup', 'rules-
popup'].includes(popupId)) return; // Prevent most popups if banned
hideAllPopups(); // Hide others before showing new one
const popup = document.getElementById(popupId);
if (popup) {
popup.classList.add('active');
}
}
function hidePopup(popupId) {
const popup = document.getElementById(popupId);
if (popup) {
popup.classList.remove('active');
}
}
function hideAllPopups() {
popups.forEach(popup => popup.classList.remove('active'));
accountMenuPopup.classList.remove('active'); // Also hide account menu
}
notificationBanner.classList.add('show');
currentState.loggedInAs = 'google';
checkDailyLimitReset();
updateHeaderUI();
updateAccountsListBadge();
saveState();
showScreen('mode-select-screen');
showNotification('Login com Google bem-sucedido!', 'success');
});
document.getElementById('guest-login-btn').addEventListener('click', () =>
{
showPopup('guest-confirm-popup');
});
document.getElementById('guest-confirm-ok').addEventListener('click', () =>
{
console.log("Entering as Guest...");
currentState.loggedInAs = 'guest';
updateHeaderUI(); // Hide relevant icons for guest
updateAccountsListBadge();
saveState();
hidePopup('guest-confirm-popup');
showScreen('mode-select-screen');
});
document.getElementById('guest-confirm-cancel').addEventListener('click',
() => {
hidePopup('guest-confirm-popup');
});
document.getElementById('logout-btn').addEventListener('click', () => {
console.log("Logging out...");
// Simulate anti-cheat check
if (Math.random() < 0.02) { // 2% chance
applyBan('logout-suspicion', 'Atividade suspeita durante o logout.',
1);
// Don't proceed with logout if banned during the process
return;
}
currentState.loggedInAs = null;
currentState.isEditMode = false;
// Clear sensitive session data, but keep limits, bans, history etc.
currentState.elementPositions = {};
currentState.originalPositions = {};
// Stop timers
if (currentState.deliveryTimerInterval)
clearInterval(currentState.deliveryTimerInterval);
currentState.deliveryTimerInterval = null;
saveState();
updateHeaderUI(); // Hide icons
updateAccountsListBadge();
showScreen('login-screen');
showNotification('Você saiu da sua conta.', 'success');
});
document.getElementById('create-account-btn').addEventListener('click',
createNewAccountAfterBan);
document.getElementById('edit-mode-btn').addEventListener('click', () => {
if (currentState.loggedInAs === 'guest') {
showInfoPopup("Acesso Negado", "O Modo Edição não está disponível para
convidados.");
return;
}
currentState.isEditMode = true;
saveState();
enableDragAndDrop();
showScreen('main-app-screen');
editModeControls.classList.remove('hidden');
showNotification("Modo Edição Ativado. Arraste os elementos.",
"success");
});
// Limits Display
limitsDisplay.classList.toggle('hidden', isGuest);
if (isLoggedIn) {
limitsCount.textContent = currentState.conversionLimits;
}
// Chatbot Toggle
chatbotToggle.classList.toggle('hidden', !isLoggedIn);
function updateAccountsListBadge() {
const isLoggedIn = currentState.loggedInAs === 'google';
accountsListBtn.classList.toggle('hidden', !isLoggedIn);
if (isLoggedIn) {
const accountsCount = currentState.createdAccounts.length;
document.getElementById('accounts-list-badge').textContent =
accountsCount;
document.getElementById('accounts-list-
badge').classList.toggle('hidden', accountsCount === 0);
} else {
document.getElementById('accounts-list-
badge').classList.add('hidden');
}
}
document.getElementById('profile-btn').addEventListener('click', () => {
if (currentState.loggedInAs === 'guest') {
showInfoPopup("Acesso Negado", "Não é possível editar o perfil no Modo
Convidado.");
return;
}
// Load current profile data into fields
document.getElementById('profile-name').value = "Usuário Google"; //
Replace with actual name if stored
applyProfilePic(); // Ensure preview is updated
showScreen('profile-edit-screen');
});
document.getElementById('settings-btn').addEventListener('click', () => {
languageSelect.value = currentState.language; // Set current language
fontSelect.value = currentState.fontFamily; // Set current font
showScreen('settings-screen');
});
function applyProfilePic() {
if (currentState.profilePic) {
profilePicPreview.style.backgroundImage = `url($
{currentState.profilePic})`;
} else {
profilePicPreview.style.backgroundImage = 'none'; // Or a default
image
}
}
function applyLanguage() {
// In a real app, this would involve loading translation files
// Here, we just simulate by changing a few key texts if needed
console.log(`Applying language: ${currentState.language}`);
// Example: document.getElementById('main-title').textContent =
getTranslation('main_title');
document.documentElement.lang = currentState.language.split('-')[0]; //
Set lang attribute
}
function applyFont() {
if (currentState.fontFamily === 'alt') {
document.documentElement.style.setProperty('--current-font-family',
'var(--alt-font-family)');
} else {
document.documentElement.style.setProperty('--current-font-family',
'var(--font-family)');
}
}
limitsDisplay.addEventListener('click', () => {
if (currentState.loggedInAs === 'google') {
showInfoPopup("Limite de Conversão", `Você tem $
{currentState.conversionLimits} conversões restantes hoje. Assine o MineConv+ Plus
para ter vidas ilimitadas (Simulado).`);
}
});
document.getElementById('convert-btn').addEventListener('click', () => {
if (currentState.loggedInAs === 'guest') {
showInfoPopup("Acesso Negado", "A conversão de contas não está
disponível para convidados.");
return;
}
if (currentState.conversionLimits <= 0) {
showInfoPopup("Limite Atingido", "Você usou todas as suas conversões
gratuitas por hoje. Volte amanhã ou assine o MineConv+.");
return;
}
// Reset previous data and start wizard
conversionData = {};
document.getElementById('conversion-email').value = '';
document.getElementById('conversion-password').value = '';
document.getElementById('conversion-nick').value = '';
document.getElementById('skin-search-nick').value = '';
document.getElementById('skin-preview').style.backgroundImage = 'none';
document.getElementById('skin-preview').classList.remove('loaded');
document.getElementById('skin-preview').textContent = 'Gire-me!';
document.getElementById('skin-preview').style.transform = 'rotateX(0deg)
rotateY(0deg)'; // Reset rotation
// Reset delivery time inputs
['years', 'months', 'days', 'hours', 'minutes', 'seconds'].forEach(unit
=> {
document.getElementById(`delivery-${unit}`).value = '';
});
showPopup('conversion-wizard-step-1');
});
function hideConversionWizard() {
hidePopup('conversion-wizard-step-1');
hidePopup('conversion-wizard-step-2');
hidePopup('conversion-wizard-step-3');
hidePopup('conversion-wizard-step-4');
hidePopup('conversion-wizard-step-5');
}
totalDelaySeconds = seconds +
minutes * 60 +
hours * 3600 +
days * 86400 +
months * 30 * 86400 + // Approximation
years * 365 * 86400; // Approximation
} catch (e) {
showNotification("Erro ao processar o tempo.", "error");
return;
}
if (totalDelaySeconds <= 0) {
showNotification("O tempo de atraso deve ser maior que zero.",
"error");
return;
}
// Simulate anti-cheat check for excessive delay
if (totalDelaySeconds > 30 * 86400) { // More than 30 days
applyBan('excessive-delay', 'Tentativa de definir tempo de entrega
excessivo.', 1);
hideConversionWizard();
return;
}
finishConversion(totalDelaySeconds);
});
function finishConversion(delaySeconds) {
// Final validation
if (!conversionData.email || !conversionData.password || !
conversionData.nick || !conversionData.skinNick) {
showNotification("Erro interno: Dados de conversão incompletos.",
"error");
hideConversionWizard();
return;
}
if (currentState.conversionLimits <= 0) {
showNotification("Limite de conversão diário atingido.", "error");
hideConversionWizard();
return;
}
// Consume limit
currentState.conversionLimits--;
updateHeaderUI();
if (delaySeconds > 0) {
// Schedule delayed delivery
currentState.deliveryTimerEnd = Date.now() + delaySeconds * 1000;
currentState.deliveryData = finalData; // Store data for later
startDeliveryTimerIfNeeded();
updateHeaderUI(); // Show clock icon
saveState();
hideConversionWizard();
// Show confirmation popup
document.getElementById('delivery-confirm-message').textContent =
`Sua conta para ${finalData.nick} será entregue em $
{formatTimeDuration(delaySeconds)}.`;
showPopup('delivery-confirm-popup');
console.log(`Conversion scheduled for ${finalData.nick} in $
{delaySeconds}s`);
} else {
// Process immediate conversion
console.log("Simulating immediate conversion for:", finalData);
// Add to managed accounts
currentState.createdAccounts.push({ nick: finalData.nick, email:
finalData.email, skin: finalData.skinNick });
updateManageAccountsList();
updateAccountsListBadge();
saveState();
hideConversionWizard();
showNotification(`Conta para ${finalData.nick} convertida com
sucesso!`, 'success');
// Send immediate email notification
addEmail("Conversão Concluída", `Sua conta Minecraft para o nick $
{finalData.nick} foi convertida com sucesso.`);
}
}
function checkDeliveryTimer() {
if (!currentState.deliveryTimerEnd) {
clearInterval(currentState.deliveryTimerInterval);
currentState.deliveryTimerInterval = null;
return;
}
if (deliveryTimerPopup.classList.contains('active')) {
deliveryCountdown.textContent = formatTimeDuration(timeLeft);
}
if (timeLeft <= 0) {
console.log("Delivery timer finished.");
processScheduledDelivery();
}
}
function processScheduledDelivery() {
if (currentState.deliveryTimerInterval)
clearInterval(currentState.deliveryTimerInterval);
currentState.deliveryTimerInterval = null;
if (currentState.deliveryData) {
const finalData = currentState.deliveryData;
console.log("Processing scheduled conversion for:", finalData);
// Add to managed accounts
currentState.createdAccounts.push({ nick: finalData.nick, email:
finalData.email, skin: finalData.skinNick });
updateManageAccountsList();
updateAccountsListBadge();
// Send email notification
addEmail("Entrega Concluída", `Sua conta Minecraft agendada para o
nick ${finalData.nick} foi entregue com sucesso.`);
showNotification(`Entrega da conta para ${finalData.nick}
concluída!`, 'success');
} else {
console.warn("Scheduled delivery processed but no data found.");
}
function formatTimeDuration(totalSeconds) {
if (totalSeconds <= 0) return "0 segundos";
const years = Math.floor(totalSeconds / (365 * 86400));
totalSeconds %= (365 * 86400);
const months = Math.floor(totalSeconds / (30 * 86400));
totalSeconds %= (30 * 86400);
const days = Math.floor(totalSeconds / 86400);
totalSeconds %= 86400;
const hours = Math.floor(totalSeconds / 3600);
totalSeconds %= 3600;
const minutes = Math.floor(totalSeconds / 60);
totalSeconds %= 60;
const seconds = totalSeconds;
return result.trim();
}
function updateManageAccountsList() {
createdAccountsList.innerHTML = ''; // Clear previous list
if (currentState.createdAccounts.length === 0) {
createdAccountsList.innerHTML = '<li class="empty-message">Nenhuma
conta criada ainda.</li>';
} else {
currentState.createdAccounts.forEach(acc => {
const li = document.createElement('li');
li.innerHTML = `<strong>Nick:</strong> ${acc.nick}<br>
<span style="opacity:
0.8;"><strong>Email:</strong> ${acc.email} | <strong>Skin:</strong> ${acc.skin ||
'Padrão'}</span>`;
createdAccountsList.appendChild(li);
});
}
}
const newEmail = {
id: Date.now(), // Simple unique ID
subject: subject,
body: body,
timestamp: Date.now(),
read: false
};
currentState.emails.unshift(newEmail); // Add to the beginning
currentState.unreadEmails++;
updateHeaderUI(); // Update badge
saveState();
}
emailBtn.addEventListener('click', () => {
updateEmailList();
showPopup('email-popup');
// Mark all as read when opened
currentState.unreadEmails = 0;
currentState.emails.forEach(email => email.read = true);
updateHeaderUI(); // Update badge immediately
saveState();
});
function updateEmailList() {
emailList.innerHTML = ''; // Clear previous list
if (currentState.emails.length === 0) {
emailList.innerHTML = '<li class="empty-message">Você não recebeu
nenhum email.</li>';
} else {
currentState.emails.forEach(email => {
const li = document.createElement('li');
const date = new Date(email.timestamp).toLocaleString();
li.innerHTML = `<strong>${email.subject}</strong>
${email.body}<br>
<span>${date}</span>`;
// Optionally add a style for unread emails if needed visually
in the list
// if (!email.read) li.style.fontWeight = 'bold';
emailList.appendChild(li);
});
}
}
closeChatbotBtn.addEventListener('click', () => {
chatbotPopup.classList.remove('active');
});
chatbotSendBtn.addEventListener('click', sendChatMessage);
chatbotInputField.addEventListener('keypress', (e) => {
if (e.key === 'Enter' && !e.shiftKey) { // Send on Enter, allow
Shift+Enter for newline
e.preventDefault(); // Prevent default newline insertion
sendChatMessage();
}
});
function sendChatMessage() {
const messageText = chatbotInputField.value.trim();
if (!messageText) return;
appendChatMessage(messageText, 'user');
chatbotInputField.value = '';
// Add to history
currentState.banHistory.push({ reason: reason, type: banType,
timestamp: now, source: source });
// Update state
currentState.isBanned = true;
currentState.banType = banType;
currentState.banReason = reason;
currentState.banExpiry = expiryTimestamp; // Will be null for permanent
saveState();
updateHeaderUI(); // Update ban history badge
showBanScreen(); // Display the ban screen/popup
}
function checkBanStatus() {
if (currentState.isBanned) {
if (currentState.banType === 'temporary' && currentState.banExpiry)
{
const now = Date.now();
if (now >= currentState.banExpiry) {
// Temporary ban expired
console.log("Temporary ban expired. Lifting ban.");
liftBan("Seu banimento temporário expirou.");
} else {
// Ban still active
showBanScreen(); // Ensure ban screen is shown
}
} else if (currentState.banType === 'permanent') {
// Permanent ban, stays until unbanned or final block
showBanScreen();
} else {
// Inconsistent state, lift ban
console.warn("Inconsistent ban state found. Lifting ban.");
liftBan("Erro no estado de banimento, removendo.");
}
} else {
// Ensure consistency if not banned
currentState.banType = null;
currentState.banReason = '';
currentState.banExpiry = null;
}
}
function liftBan(notificationMessageText) {
currentState.isBanned = false;
currentState.banType = null;
currentState.banReason = '';
currentState.banExpiry = null;
// Don't clear history or permanent counts here
saveState();
showNotification(notificationMessageText, "success");
// Decide where to go after ban lifts
if (currentState.loggedInAs) {
startDeliveryTimerIfNeeded(); // Resume timer if needed
updateHeaderUI();
showScreen('main-app-screen'); // Or mode-select
} else {
showScreen('login-screen');
}
}
function showBanScreen() {
const banPopup = document.getElementById('ban-popup');
const titleEl = document.getElementById('ban-popup-title');
const reasonEl = document.getElementById('ban-popup-reason');
const durationEl = document.getElementById('ban-popup-duration');
const adviceEl = document.getElementById('ban-popup-advice');
const actionsEl = document.getElementById('ban-actions');
const finalBanMsgEl = document.getElementById('final-ban-message');
progressBar.style.width = '0%';
statusText.textContent = 'Progresso: 0%';
finishBtn.classList.add('hidden');
let progress = 0;
const totalTime = 10000; // 10 seconds simulation
const intervalTime = 100;
if (unbanProgressInterval) clearInterval(unbanProgressInterval);
if (unbanTimeout) clearTimeout(unbanTimeout);
document.getElementById('finish-unban-btn').addEventListener('click', () =>
{
if (unbanProgressInterval) clearInterval(unbanProgressInterval);
if (unbanTimeout) clearTimeout(unbanTimeout);
hidePopup('unban-sim-popup');
// Lift the ban, but keep the history and permanent count
currentState.isBanned = false;
currentState.banType = null;
currentState.banReason = '';
currentState.banExpiry = null;
// DO NOT reset currentState.permanentBanCount here
saveState();
showNotification("Unban adquirido com sucesso!", "success");
// Go to login screen after unban
showScreen('login-screen');
});
// Reset most of the state, similar to a fresh start but keeping ban
info
currentState = {
// Keep ban-related info
banHistory: oldBanHistory,
permanentBanCount: oldPermanentBanCount,
newAccountCreations: oldNewAccountCreations,
// Keep created accounts list
createdAccounts: oldCreatedAccounts,
// Reset user-specific data
loggedInAs: null,
currentScreen: 'login-screen', // Start at login
conversionLimits: DAILY_LIMIT,
lastLimitReset: null,
isBanned: false, // Not banned on the new "account" yet
banType: null,
banReason: '',
banExpiry: null,
elementPositions: {},
isEditMode: false,
originalPositions: {},
unreadEmails: 0,
emails: [],
deliveryTimerEnd: null,
deliveryTimerInterval: null,
deliveryData: null,
profilePic: null,
language: 'pt-BR', // Reset language
fontFamily: 'default', // Reset font
lastChatMessagesTimestamps: [], // Reset chat timestamps
};
function updateBanHistoryList() {
banHistoryList.innerHTML = ''; // Clear previous list
if (currentState.banHistory.length === 0) {
banHistoryList.innerHTML = '<li class="empty-message">Nenhum
banimento registrado.</li>';
} else {
// Show newest first
[...currentState.banHistory].reverse().forEach(ban => {
const li = document.createElement('li');
const date = new Date(ban.timestamp).toLocaleString();
const typeText = ban.type === 'permanent' ? 'Permanente' :
'Temporário';
const typeColor = ban.type === 'permanent' ? 'var(--error-
color)' : 'var(--warning-color)';
li.innerHTML = `<strong style="color: ${typeColor};">[$
{typeText}]</strong> ${ban.reason}<br>
<span>${date} (Fonte: ${ban.source ||
'Desconhecida'})</span>`;
li.style.borderLeftColor = typeColor; // Match border color
banHistoryList.appendChild(li);
});
}
}
function updateExistingAccountsList() {
existingAccountsListEl.innerHTML = ''; // Clear previous list
if (currentState.createdAccounts.length === 0) {
existingAccountsListEl.innerHTML = '<li class="empty-
message">Nenhuma conta criada ainda.</li>';
} else {
currentState.createdAccounts.forEach((acc, index) => {
const li = document.createElement('li');
li.innerHTML = `<strong>Conta #${index + 1}:</strong> $
{acc.nick || 'N/A'} (${acc.email || 'N/A'})`;
existingAccountsListEl.appendChild(li);
});
}
}
function enableDragAndDrop() {
document.querySelectorAll('.draggable').forEach(el => {
el.addEventListener('mousedown', startDrag);
el.style.position = 'absolute'; // Required for positioning
function startDrag(e) {
// Allow dragging only with left mouse button
if (e.button !== 0 || !currentState.isEditMode || !
e.target.closest('.draggable')) return;
draggedElement = e.target.closest('.draggable');
draggedElement.classList.add('dragging');
function drag(e) {
if (!draggedElement) return;
e.preventDefault(); // Prevent text selection during drag
draggedElement.style.left = `${newX}px`;
draggedElement.style.top = `${newY}px`;
}
function endDrag(e) {
if (!draggedElement) return;
draggedElement.classList.remove('dragging');
// Position is already set by the drag function
draggedElement = null;
}
document.getElementById('cancel-layout-btn').addEventListener('click', ()
=> {
disableDragAndDrop(true); // Disable and revert positions
currentState.isEditMode = false; // Exit edit mode
// Positions already reverted by disableDragAndDrop(true)
saveState(); // Save the mode change
showNotification("Alterações de layout canceladas.", "success");
showScreen('main-app-screen'); // Stay on main screen
});
document.querySelectorAll('.draggable').forEach(el => {
if (el.id && currentState.elementPositions[el.id]) {
el.style.position = 'absolute'; // Ensure it can be positioned
el.style.top = currentState.elementPositions[el.id].top;
el.style.left = currentState.elementPositions[el.id].left;
} else {
// Reset if no saved position or element has no ID
const originalStyle = currentState.originalPositions[el.id];
el.style.position = originalStyle?.position || 'relative'; //
Reset to original or default
el.style.top = originalStyle?.top || 'auto';
el.style.left = originalStyle?.left || 'auto';
}
});
}
skinPrevX = e.clientX;
skinPrevY = e.clientY;
</script>
</body>
</html>