feat(myTischtennis): integrate Playwright for CAPTCHA handling and enhance login form functionality
- Added Playwright as a dependency to handle CAPTCHA challenges during login attempts. - Implemented a new endpoint to retrieve the login form from myTischtennis, parsing necessary fields for user input. - Enhanced the login process to utilize Playwright for browser automation when CAPTCHA is required. - Updated the MyTischtennisDialog component to support local login form submission instead of using an iframe. - Refactored the MyTischtennisController to include proxy functionality for serving resources and handling login submissions. - Improved error handling and user feedback during login attempts, ensuring a smoother user experience.
This commit is contained in:
@@ -58,6 +58,15 @@ class MyTischtennisService {
|
||||
|
||||
// Login-Versuch bei myTischtennis
|
||||
loginResult = await myTischtennisClient.login(email, password);
|
||||
if (!loginResult.success && loginResult.requiresCaptcha) {
|
||||
console.log('[myTischtennisService.upsertAccount] CAPTCHA-Fehler, versuche Playwright-Fallback...');
|
||||
const playwrightResult = await myTischtennisClient.loginWithBrowserAutomation(email, password);
|
||||
if (playwrightResult.success) {
|
||||
loginResult = playwrightResult;
|
||||
} else {
|
||||
console.warn('[myTischtennisService.upsertAccount] Playwright-Fallback fehlgeschlagen:', playwrightResult.error);
|
||||
}
|
||||
}
|
||||
if (!loginResult.success) {
|
||||
const statusCode = loginResult.requiresCaptcha ? 400 : 401;
|
||||
const errorMessage = loginResult.error || 'myTischtennis-Login fehlgeschlagen. Bitte überprüfen Sie Ihre Zugangsdaten.';
|
||||
@@ -74,10 +83,14 @@ class MyTischtennisService {
|
||||
const now = new Date();
|
||||
|
||||
if (account) {
|
||||
const effectiveAutoUpdateRatings = autoUpdateRatings === undefined
|
||||
? account.autoUpdateRatings
|
||||
: Boolean(autoUpdateRatings);
|
||||
|
||||
// Update existing
|
||||
account.email = email;
|
||||
account.savePassword = savePassword;
|
||||
account.autoUpdateRatings = autoUpdateRatings;
|
||||
account.autoUpdateRatings = savePassword ? effectiveAutoUpdateRatings : false;
|
||||
|
||||
if (password && savePassword) {
|
||||
account.setPassword(password);
|
||||
@@ -115,7 +128,7 @@ class MyTischtennisService {
|
||||
userId,
|
||||
email,
|
||||
savePassword,
|
||||
autoUpdateRatings,
|
||||
autoUpdateRatings: savePassword ? Boolean(autoUpdateRatings) : false,
|
||||
lastLoginAttempt: password ? now : null,
|
||||
lastLoginSuccess: loginResult?.success ? now : null
|
||||
};
|
||||
@@ -225,18 +238,48 @@ class MyTischtennisService {
|
||||
// Login-Versuch mit Passwort
|
||||
console.log('[myTischtennisService.verifyLogin] Attempting login for user:', account.email);
|
||||
const loginResult = await myTischtennisClient.login(account.email, password);
|
||||
console.log('[myTischtennisService.verifyLogin] Login result:', { success: loginResult.success, error: loginResult.error, requiresCaptcha: loginResult.requiresCaptcha });
|
||||
let effectiveLoginResult = loginResult;
|
||||
if (!effectiveLoginResult.success && effectiveLoginResult.requiresCaptcha) {
|
||||
console.log('[myTischtennisService.verifyLogin] CAPTCHA-Fehler, versuche Playwright-Fallback...');
|
||||
try {
|
||||
const playwrightResult = await myTischtennisClient.loginWithBrowserAutomation(account.email, password);
|
||||
if (playwrightResult.success) {
|
||||
effectiveLoginResult = playwrightResult;
|
||||
} else {
|
||||
console.warn('[myTischtennisService.verifyLogin] Playwright-Fallback fehlgeschlagen:', playwrightResult.error);
|
||||
effectiveLoginResult = {
|
||||
success: false,
|
||||
error: playwrightResult.error || 'Playwright-Fallback fehlgeschlagen',
|
||||
requiresCaptcha: true,
|
||||
status: 400
|
||||
};
|
||||
}
|
||||
} catch (playwrightError) {
|
||||
console.warn('[myTischtennisService.verifyLogin] Playwright-Fallback Exception:', playwrightError?.message || playwrightError);
|
||||
effectiveLoginResult = {
|
||||
success: false,
|
||||
error: `Playwright-Fallback Exception: ${playwrightError?.message || 'Unbekannter Fehler'}`,
|
||||
requiresCaptcha: true,
|
||||
status: 400
|
||||
};
|
||||
}
|
||||
}
|
||||
console.log('[myTischtennisService.verifyLogin] Login result:', {
|
||||
success: effectiveLoginResult.success,
|
||||
error: effectiveLoginResult.error,
|
||||
requiresCaptcha: effectiveLoginResult.requiresCaptcha
|
||||
});
|
||||
|
||||
if (loginResult.success) {
|
||||
if (effectiveLoginResult.success) {
|
||||
account.lastLoginSuccess = now;
|
||||
account.accessToken = loginResult.accessToken;
|
||||
account.refreshToken = loginResult.refreshToken;
|
||||
account.expiresAt = loginResult.expiresAt;
|
||||
account.cookie = loginResult.cookie;
|
||||
account.userData = loginResult.user;
|
||||
account.accessToken = effectiveLoginResult.accessToken;
|
||||
account.refreshToken = effectiveLoginResult.refreshToken;
|
||||
account.expiresAt = effectiveLoginResult.expiresAt;
|
||||
account.cookie = effectiveLoginResult.cookie;
|
||||
account.userData = effectiveLoginResult.user;
|
||||
|
||||
// Hole Club-ID und Federation
|
||||
const profileResult = await myTischtennisClient.getUserProfile(loginResult.cookie);
|
||||
const profileResult = await myTischtennisClient.getUserProfile(effectiveLoginResult.cookie);
|
||||
|
||||
if (profileResult.success) {
|
||||
account.clubId = profileResult.clubId || account.clubId;
|
||||
@@ -250,25 +293,31 @@ class MyTischtennisService {
|
||||
|
||||
return {
|
||||
success: true,
|
||||
accessToken: loginResult.accessToken,
|
||||
refreshToken: loginResult.refreshToken,
|
||||
expiresAt: loginResult.expiresAt,
|
||||
user: loginResult.user,
|
||||
accessToken: effectiveLoginResult.accessToken,
|
||||
refreshToken: effectiveLoginResult.refreshToken,
|
||||
expiresAt: effectiveLoginResult.expiresAt,
|
||||
user: effectiveLoginResult.user,
|
||||
clubId: account.clubId,
|
||||
clubName: account.clubName
|
||||
};
|
||||
} else {
|
||||
// Prevent stale "success" from previously valid sessions after an explicit failed login attempt.
|
||||
account.accessToken = null;
|
||||
account.refreshToken = null;
|
||||
account.cookie = null;
|
||||
account.expiresAt = null;
|
||||
account.userData = null;
|
||||
await account.save(); // Save lastLoginAttempt
|
||||
const errorMessage = loginResult.error || 'myTischtennis-Login fehlgeschlagen';
|
||||
const errorMessage = effectiveLoginResult.error || 'myTischtennis-Login fehlgeschlagen';
|
||||
// Verwende den Status-Code vom myTischtennisClient, falls vorhanden, sonst 401
|
||||
// Wenn CAPTCHA erforderlich ist, verwende 400 statt 401
|
||||
const statusCode = loginResult.requiresCaptcha
|
||||
const statusCode = effectiveLoginResult.requiresCaptcha
|
||||
? 400
|
||||
: (loginResult.status && loginResult.status >= 400 && loginResult.status < 600
|
||||
? loginResult.status
|
||||
: (effectiveLoginResult.status && effectiveLoginResult.status >= 400 && effectiveLoginResult.status < 600
|
||||
? effectiveLoginResult.status
|
||||
: 401);
|
||||
console.error('[myTischtennisService.verifyLogin] Login failed:', errorMessage, `(Status: ${statusCode})`, loginResult.requiresCaptcha ? '(CAPTCHA erforderlich)' : '');
|
||||
if (loginResult.requiresCaptcha) {
|
||||
console.error('[myTischtennisService.verifyLogin] Login failed:', errorMessage, `(Status: ${statusCode})`, effectiveLoginResult.requiresCaptcha ? '(CAPTCHA erforderlich)' : '');
|
||||
if (effectiveLoginResult.requiresCaptcha) {
|
||||
throw new HttpError({ code: 'ERROR_MYTISCHTENNIS_CAPTCHA_REQUIRED', params: { message: errorMessage } }, statusCode);
|
||||
}
|
||||
throw new HttpError(errorMessage, statusCode);
|
||||
|
||||
@@ -115,7 +115,6 @@ class SchedulerService {
|
||||
|
||||
/**
|
||||
* Manually trigger rating updates (for testing)
|
||||
* HINWEIS: Deaktiviert - automatische MyTischtennis-Abrufe sind nicht mehr verfügbar
|
||||
*/
|
||||
async triggerRatingUpdates() {
|
||||
devLog('[Scheduler] Manual rating updates trigger called');
|
||||
@@ -124,7 +123,6 @@ class SchedulerService {
|
||||
|
||||
/**
|
||||
* Manually trigger match results fetch (for testing)
|
||||
* HINWEIS: Deaktiviert - automatische MyTischtennis-Abrufe sind nicht mehr verfügbar
|
||||
*/
|
||||
async triggerMatchResultsFetch() {
|
||||
devLog('[Scheduler] Manual match results fetch trigger called');
|
||||
|
||||
Reference in New Issue
Block a user