Files
popa-launcher/src/renderer/pages/Login.tsx
2025-07-05 05:47:53 +05:00

340 lines
9.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Box, Button, Slider, TextField, Typography } from '@mui/material';
import { useEffect, useState } from 'react';
export default function Login() {
const [config, setConfig] = useState({
username: '',
password: '',
memory: 4096,
comfortVersion: '',
accessToken: '',
clientToken: '',
});
const [status, setStatus] = useState('');
const loadInitialConfig = () => {
try {
const savedConfig = localStorage.getItem('launcher_config');
if (savedConfig) {
return JSON.parse(savedConfig);
}
} catch (error) {
console.log('Ошибка загрузки конфигурации:', error);
}
// Возвращаем значения по умолчанию
return {
username: '',
password: '',
memory: 4096,
comfortVersion: '',
accessToken: '',
clientToken: '',
};
};
useEffect(() => {
const savedConfig = loadInitialConfig();
setConfig(savedConfig);
}, []);
const handleInputChange = (e) => {
const { name, value } = e.target;
setConfig((prev) => ({ ...prev, [name]: value }));
};
const saveConfig = (
username,
memory,
accessToken = '',
clientToken = '',
comfortVersion = '',
password = '',
) => {
try {
const newConfig = {
username,
memory,
accessToken: accessToken || config.accessToken,
clientToken: clientToken || config.clientToken,
comfortVersion: comfortVersion || config.comfortVersion,
password: password || config.password,
};
setConfig(newConfig);
localStorage.setItem('launcher_config', JSON.stringify(newConfig));
} catch (error) {
console.log(`Ошибка при сохранении конфигурации: ${error.message}`);
}
};
const loadConfig = () => {
try {
const savedConfig = localStorage.getItem('launcher_config');
if (savedConfig) {
const parsedConfig = JSON.parse(savedConfig);
setConfig(parsedConfig);
return parsedConfig;
}
} catch (error) {
console.log(`Ошибка при загрузке конфигурации: ${error.message}`);
}
return config;
};
const refreshSession = async (accessToken, clientToken) => {
try {
const refreshData = {
accessToken: accessToken,
clientToken: clientToken,
};
const response = await fetch('https://authserver.ely.by/auth/refresh', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(refreshData),
});
if (response.ok) {
const data = await response.json();
const newAccessToken = data.accessToken;
const profile = data.selectedProfile;
const uuid = profile.id;
const name = profile.name;
if (newAccessToken && uuid && name) {
saveConfig(
config.username,
config.memory,
newAccessToken,
clientToken,
);
return {
accessToken: newAccessToken,
uuid: uuid,
username: name,
clientToken: clientToken,
};
}
}
return null;
} catch (error) {
console.log(`Ошибка при обновлении сессии: ${error.message}`);
return null;
}
};
const authenticateWithElyBy = async (username, password) => {
try {
const clientToken = crypto.randomUUID();
const authData = {
username: username,
password: password,
clientToken: clientToken,
requestUser: true,
};
console.log(`Аутентификация пользователя ${username} на Ely.by...`);
const response = await fetch(
'https://authserver.ely.by/auth/authenticate',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(authData),
},
);
const responseData = await response.json();
if (response.ok) {
const accessToken = responseData.accessToken;
const profile = responseData.selectedProfile;
const uuid = profile.id;
const name = profile.name;
if (accessToken && uuid && name) {
saveConfig(
username,
config.memory,
accessToken,
clientToken,
'',
password,
);
console.log(`Аутентификация успешна: UUID=${uuid}, Username=${name}`);
return {
accessToken: accessToken,
uuid: uuid,
username: name,
clientToken: clientToken,
};
}
} else {
if (responseData.error === 'Account protected with two factor auth') {
const totpToken = prompt(
'Введите код двухфакторной аутентификации:',
'',
);
if (totpToken) {
authData.password = `${password}:${totpToken}`;
const totpResponse = await fetch(
'https://authserver.ely.by/auth/authenticate',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(authData),
},
);
if (totpResponse.ok) {
const totpData = await totpResponse.json();
const newAccessToken = totpData.accessToken;
const newProfile = totpData.selectedProfile;
const newUuid = newProfile.id;
const newName = newProfile.name;
if (newAccessToken && newUuid && newName) {
saveConfig(
username,
config.memory,
newAccessToken,
clientToken,
'',
password,
);
return {
accessToken: newAccessToken,
uuid: newUuid,
username: newName,
clientToken: clientToken,
};
}
}
}
}
throw new Error(responseData.error || 'Ошибка авторизации');
}
} catch (error) {
console.log(`Ошибка авторизации: ${error.message}`);
return null;
}
};
const authorization = async () => {
console.log('Начинаем процесс авторизации...');
if (!config.username.trim()) {
console.log('Ошибка: не указан никнейм');
alert('Введите никнейм!');
return;
}
try {
// Проверяем, есть ли сохранённый токен
if (config.accessToken && config.clientToken) {
console.log('Проверка валидности существующего токена...');
const isValid = await validateSession(config.accessToken);
if (!isValid) {
console.log('Токен недействителен, пытаемся обновить...');
const refreshedSession = await refreshSession(
config.accessToken,
config.clientToken,
);
if (!refreshedSession) {
console.log(
'Не удалось обновить токен, требуется новая авторизация',
);
const newSession = await authenticateWithElyBy(
config.username,
config.password,
);
if (!newSession) {
console.log('Авторизация не удалась');
return;
}
}
} else {
console.log('Токен действителен');
}
} else {
console.log('Токен отсутствует, выполняем авторизацию...');
const session = await authenticateWithElyBy(
config.username,
config.password,
);
if (!session) {
console.log('Авторизация не удалась');
return;
}
}
console.log('Авторизация успешно завершена');
// Здесь можно добавить логику для запуска игры
} catch (error) {
console.log(`ОШИБКА при авторизации: ${error.message}`);
}
};
return (
<Box>
<Box sx={{ display: 'flex' }}>
<Typography variant="h3">POPA</Typography>
<Typography variant="h3">-</Typography>
<Typography
variant="h3"
sx={{
background: '-webkit-linear-gradient(200.96deg, #88BCFF, #FD71FF)',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
}}
>
POPA
</Typography>
</Box>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: '1.5vw' }}>
<TextField
required
name="username"
label="Введите ник"
variant="outlined"
value={config.username}
onChange={handleInputChange}
/>
<TextField
required
type="password"
name="password"
label="Введите пароль"
variant="outlined"
value={config.password}
onChange={handleInputChange}
/>
<Slider
name="memory"
aria-label="Temperature"
defaultValue={4096}
valueLabelDisplay="auto"
shiftStep={1024}
step={1024}
marks
min={1024}
max={32628}
value={config.memory}
onChange={handleInputChange}
/>
<Button onClick={authorization} variant="contained">
Войти
</Button>
</Box>
</Box>
);
}