Enhance myTischtennis URL controller with improved error handling and logging
Updated MyTischtennisUrlController to include detailed error messages for missing user IDs and team configurations. Added logging for session details and automatic login attempts, improving debugging capabilities. Enhanced request logging for API calls to myTischtennis, ensuring all requests are logged, even in case of errors. Updated requestLoggingMiddleware to only log myTischtennis-related requests, streamlining log management. Improved validation checks in autoFetchMatchResultsService for team and league data integrity.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import myTischtennisUrlParserService from '../services/myTischtennisUrlParserService.js';
|
||||
import myTischtennisService from '../services/myTischtennisService.js';
|
||||
import autoFetchMatchResultsService from '../services/autoFetchMatchResultsService.js';
|
||||
import apiLogService from '../services/apiLogService.js';
|
||||
import ClubTeam from '../models/ClubTeam.js';
|
||||
import League from '../models/League.js';
|
||||
import Season from '../models/Season.js';
|
||||
@@ -228,6 +229,10 @@ class MyTischtennisUrlController {
|
||||
throw new HttpError(400, 'clubTeamId is required');
|
||||
}
|
||||
|
||||
if (!userIdOrEmail) {
|
||||
throw new HttpError(401, 'User-ID fehlt. Bitte melden Sie sich an.');
|
||||
}
|
||||
|
||||
// Get actual user ID (userid header might be email address)
|
||||
let userId = userIdOrEmail;
|
||||
if (isNaN(userIdOrEmail)) {
|
||||
@@ -246,17 +251,63 @@ class MyTischtennisUrlController {
|
||||
try {
|
||||
session = await myTischtennisService.getSession(userId);
|
||||
console.log('Session found:', !!session);
|
||||
if (session) {
|
||||
console.log('Session details:', {
|
||||
hasCookie: !!session.cookie,
|
||||
hasAccessToken: !!session.accessToken,
|
||||
expiresAt: session.expiresAt ? new Date(session.expiresAt * 1000).toISOString() : null
|
||||
});
|
||||
}
|
||||
} catch (sessionError) {
|
||||
console.log('Session invalid, attempting login...', sessionError.message);
|
||||
console.error('Session error details:', {
|
||||
message: sessionError.message,
|
||||
stack: sessionError.stack,
|
||||
name: sessionError.name
|
||||
});
|
||||
|
||||
// Versuche automatischen Login mit gespeicherten Credentials
|
||||
try {
|
||||
await myTischtennisService.verifyLogin(userId);
|
||||
console.log('Attempting automatic login for userId:', userId);
|
||||
|
||||
// Check if account exists and has password
|
||||
const accountCheck = await myTischtennisService.getAccount(userId);
|
||||
if (!accountCheck) {
|
||||
throw new Error('MyTischtennis-Account nicht gefunden');
|
||||
}
|
||||
|
||||
console.log('Account found:', {
|
||||
email: accountCheck.email,
|
||||
hasPassword: !!accountCheck.encryptedPassword,
|
||||
hasAccessToken: !!accountCheck.accessToken,
|
||||
hasCookie: !!accountCheck.cookie
|
||||
});
|
||||
|
||||
if (!accountCheck.encryptedPassword) {
|
||||
throw new Error('Kein Passwort gespeichert. Bitte melden Sie sich in den MyTischtennis-Einstellungen an und speichern Sie Ihr Passwort.');
|
||||
}
|
||||
|
||||
console.log('Calling verifyLogin...');
|
||||
const verifyResult = await myTischtennisService.verifyLogin(userId);
|
||||
console.log('verifyLogin result:', verifyResult);
|
||||
|
||||
session = await myTischtennisService.getSession(userId);
|
||||
console.log('Automatic login successful');
|
||||
console.log('Automatic login successful, session:', {
|
||||
hasCookie: !!session?.cookie,
|
||||
hasAccessToken: !!session?.accessToken
|
||||
});
|
||||
} catch (loginError) {
|
||||
console.error('Automatic login failed:', loginError.message);
|
||||
throw new HttpError(401, 'MyTischtennis-Session abgelaufen und automatischer Login fehlgeschlagen. Bitte melden Sie sich in den MyTischtennis-Einstellungen an.');
|
||||
console.error('Automatic login failed - DETAILED ERROR:', {
|
||||
message: loginError.message,
|
||||
stack: loginError.stack,
|
||||
name: loginError.name,
|
||||
userId: userId,
|
||||
response: loginError.response?.data,
|
||||
status: loginError.response?.status
|
||||
});
|
||||
|
||||
const errorMessage = loginError.message || 'Automatischer Login fehlgeschlagen';
|
||||
throw new HttpError(401, `MyTischtennis-Session abgelaufen und automatischer Login fehlgeschlagen: ${errorMessage}. Bitte melden Sie sich in den MyTischtennis-Einstellungen an.`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,7 +342,7 @@ class MyTischtennisUrlController {
|
||||
});
|
||||
|
||||
if (!team) {
|
||||
throw new HttpError(404, 'Team not found');
|
||||
throw new HttpError(404, `Team mit ID ${clubTeamId} nicht gefunden`);
|
||||
}
|
||||
|
||||
console.log('Team data:', {
|
||||
@@ -309,11 +360,74 @@ class MyTischtennisUrlController {
|
||||
} : null
|
||||
});
|
||||
|
||||
if (!team.myTischtennisTeamId || !team.league || !team.league.myTischtennisGroupId) {
|
||||
throw new HttpError(400, 'Team is not configured for myTischtennis');
|
||||
// Verbesserte Validierung mit detaillierten Fehlermeldungen
|
||||
if (!team.myTischtennisTeamId) {
|
||||
throw new HttpError(400, `Team "${team.name}" (interne ID: ${team.id}) ist nicht für myTischtennis konfiguriert: myTischtennisTeamId fehlt. Bitte konfigurieren Sie das Team zuerst über die MyTischtennis-URL.`);
|
||||
}
|
||||
|
||||
// Stelle sicher, dass die myTischtennisTeamId auch wirklich verwendet wird
|
||||
console.log(`Verwende myTischtennisTeamId: ${team.myTischtennisTeamId} (nicht die interne clubTeamId: ${team.id})`);
|
||||
|
||||
if (!team.league) {
|
||||
throw new HttpError(400, 'Team ist keiner Liga zugeordnet. Bitte ordnen Sie das Team einer Liga zu.');
|
||||
}
|
||||
|
||||
if (!team.league.myTischtennisGroupId) {
|
||||
throw new HttpError(400, 'Liga ist nicht für myTischtennis konfiguriert: myTischtennisGroupId fehlt. Bitte konfigurieren Sie die Liga zuerst über die MyTischtennis-URL.');
|
||||
}
|
||||
|
||||
// Validate season before proceeding
|
||||
if (!team.league.season || !team.league.season.season) {
|
||||
throw new HttpError(400, 'Liga ist keiner Saison zugeordnet. Bitte ordnen Sie die Liga einer Saison zu.');
|
||||
}
|
||||
|
||||
// Build the URL that will be used - do this early so we can log it even if errors occur
|
||||
const seasonFull = team.league.season.season;
|
||||
const seasonParts = seasonFull.split('/');
|
||||
const seasonShort = seasonParts.length === 2
|
||||
? `${seasonParts[0].slice(-2)}/${seasonParts[1].slice(-2)}`
|
||||
: seasonFull;
|
||||
const seasonStr = seasonShort.replace('/', '--');
|
||||
const teamnameEncoded = encodeURIComponent(team.name.replace(/\s/g, '_'));
|
||||
const myTischtennisUrl = `https://www.mytischtennis.de/click-tt/${team.league.association}/${seasonStr}/ligen/${team.league.groupname}/gruppe/${team.league.myTischtennisGroupId}/mannschaft/${team.myTischtennisTeamId}/${teamnameEncoded}/spielerbilanzen/gesamt`;
|
||||
|
||||
// Log the request to myTischtennis BEFORE making the call
|
||||
// This ensures we always see what WILL BE sent, even if the call fails
|
||||
const requestStartTime = Date.now();
|
||||
console.log('=== ABOUT TO FETCH FROM MYTISCHTENNIS ===');
|
||||
console.log('URL:', myTischtennisUrl);
|
||||
console.log('myTischtennisTeamId:', team.myTischtennisTeamId);
|
||||
console.log('clubTeamId:', team.id);
|
||||
|
||||
try {
|
||||
await apiLogService.logRequest({
|
||||
userId: account.userId,
|
||||
method: 'GET',
|
||||
path: myTischtennisUrl.replace('https://www.mytischtennis.de', ''),
|
||||
statusCode: null,
|
||||
requestBody: JSON.stringify({
|
||||
url: myTischtennisUrl,
|
||||
myTischtennisTeamId: team.myTischtennisTeamId,
|
||||
clubTeamId: team.id,
|
||||
teamName: team.name,
|
||||
leagueName: team.league.name,
|
||||
association: team.league.association,
|
||||
groupId: team.league.myTischtennisGroupId,
|
||||
groupname: team.league.groupname,
|
||||
season: seasonFull
|
||||
}),
|
||||
responseBody: null,
|
||||
executionTime: null,
|
||||
errorMessage: 'Request wird ausgeführt...',
|
||||
logType: 'api_request',
|
||||
schedulerJobType: 'mytischtennis_fetch'
|
||||
});
|
||||
} catch (logError) {
|
||||
console.error('Error logging request (non-critical):', logError);
|
||||
}
|
||||
|
||||
// Fetch data for this specific team
|
||||
// Note: fetchTeamResults will also log and update with actual response
|
||||
const result = await autoFetchMatchResultsService.fetchTeamResults(
|
||||
{
|
||||
userId: account.userId,
|
||||
@@ -326,32 +440,63 @@ class MyTischtennisUrlController {
|
||||
team
|
||||
);
|
||||
|
||||
// Also fetch and update league table data
|
||||
let tableUpdateResult = null;
|
||||
// Also fetch and update league table data
|
||||
let tableUpdateResult = null;
|
||||
try {
|
||||
await autoFetchMatchResultsService.fetchAndUpdateLeagueTable(account.userId, team.league.id);
|
||||
tableUpdateResult = 'League table updated successfully';
|
||||
console.log('✓ League table updated for league:', team.league.id);
|
||||
} catch (error) {
|
||||
console.error('Error fetching league table data:', error);
|
||||
tableUpdateResult = 'League table update failed: ' + error.message;
|
||||
// Don't fail the entire request if table update fails
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: `${result.fetchedCount} Datensätze abgerufen und verarbeitet`,
|
||||
data: {
|
||||
fetchedCount: result.fetchedCount,
|
||||
teamName: team.name,
|
||||
tableUpdate: tableUpdateResult
|
||||
tableUpdateResult = 'League table updated successfully';
|
||||
console.log('✓ League table updated for league:', team.league.id);
|
||||
} catch (error) {
|
||||
console.error('Error fetching league table data:', error);
|
||||
tableUpdateResult = 'League table update failed: ' + error.message;
|
||||
// Don't fail the entire request if table update fails
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in fetchTeamData:', error);
|
||||
console.error('Error stack:', error.stack);
|
||||
next(error);
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: `${result.fetchedCount} Datensätze abgerufen und verarbeitet`,
|
||||
data: {
|
||||
fetchedCount: result.fetchedCount,
|
||||
teamName: team.name,
|
||||
tableUpdate: tableUpdateResult
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in fetchTeamData:', error);
|
||||
console.error('Error stack:', error.stack);
|
||||
|
||||
// Update log with error information if we got far enough to build the URL
|
||||
if (typeof myTischtennisUrl !== 'undefined' && account && team) {
|
||||
const requestExecutionTime = Date.now() - requestStartTime;
|
||||
try {
|
||||
await apiLogService.logRequest({
|
||||
userId: account.userId,
|
||||
method: 'GET',
|
||||
path: myTischtennisUrl.replace('https://www.mytischtennis.de', ''),
|
||||
statusCode: 0,
|
||||
requestBody: JSON.stringify({
|
||||
url: myTischtennisUrl,
|
||||
myTischtennisTeamId: team.myTischtennisTeamId,
|
||||
clubTeamId: team.id,
|
||||
teamName: team.name,
|
||||
leagueName: team.league?.name,
|
||||
association: team.league?.association,
|
||||
groupname: team.league?.groupname,
|
||||
groupId: team.league?.myTischtennisGroupId
|
||||
}),
|
||||
responseBody: null,
|
||||
executionTime: requestExecutionTime,
|
||||
errorMessage: error.message || String(error),
|
||||
logType: 'api_request',
|
||||
schedulerJobType: 'mytischtennis_fetch'
|
||||
});
|
||||
} catch (logError) {
|
||||
console.error('Error logging failed request:', logError);
|
||||
}
|
||||
}
|
||||
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user