mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-10 01:56:16 -08:00
refactor: enhance error handling for playlist updates and add missing i18n strings
This commit is contained in:
1 parent
0012fcfa7b
commit
188ebb6fd9
3 files changed
+144
-45
No files matched your search
@@ -313,27 +313,26 @@ export class ElectronService extends DataService {
|
||||
filePath?: string;
|
||||
title: string;
|
||||
}) {
|
||||
let methodToCall = null;
|
||||
if (data.url && !data.filePath) {
|
||||
// fetch from url
|
||||
methodToCall = window.electron.fetchPlaylistByUrl(
|
||||
data.url,
|
||||
data.title
|
||||
);
|
||||
} else if (data.filePath && !data.url) {
|
||||
// update from file path
|
||||
methodToCall = window.electron.updatePlaylistFromFilePath(
|
||||
data.filePath,
|
||||
data.title
|
||||
);
|
||||
} else {
|
||||
console.error(
|
||||
'Either url or filePath must be provided, but not both.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
let playlistObject: Playlist;
|
||||
if (data.url && !data.filePath) {
|
||||
playlistObject = await window.electron.fetchPlaylistByUrl(
|
||||
data.url,
|
||||
data.title
|
||||
);
|
||||
} else if (data.filePath && !data.url) {
|
||||
playlistObject =
|
||||
await window.electron.updatePlaylistFromFilePath(
|
||||
data.filePath,
|
||||
data.title
|
||||
);
|
||||
} else {
|
||||
console.error(
|
||||
'Either url or filePath must be provided, but not both.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
methodToCall.then((playlistObject) => {
|
||||
this.store.dispatch(
|
||||
PlaylistActions.updatePlaylist({
|
||||
playlist: {
|
||||
@@ -351,7 +350,66 @@ export class ElectronService extends DataService {
|
||||
null,
|
||||
{ duration: 2000 }
|
||||
);
|
||||
});
|
||||
} catch (error: unknown) {
|
||||
console.error('Playlist refresh error:', error);
|
||||
this.snackBar.open(
|
||||
this.getPlaylistRefreshErrorMessage(error, data),
|
||||
this.translateService.instant('CLOSE'),
|
||||
{ duration: 5000 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private getPlaylistRefreshErrorMessage(
|
||||
error: unknown,
|
||||
data: { url?: string; filePath?: string }
|
||||
): string {
|
||||
if (data.filePath) {
|
||||
const errorMessage = String(
|
||||
this.getErrorDetails(error)?.message ?? error ?? ''
|
||||
);
|
||||
|
||||
if (
|
||||
/(ENOENT|no such file or directory|not found)/i.test(
|
||||
errorMessage
|
||||
)
|
||||
) {
|
||||
return this.translateWithFallback(
|
||||
'HOME.PLAYLISTS.PLAYLIST_UPDATE_FILE_NOT_FOUND',
|
||||
'Playlist refresh failed. The local file is no longer available. Check the file path or re-import the playlist.'
|
||||
);
|
||||
}
|
||||
|
||||
if (/(EACCES|EPERM|permission denied)/i.test(errorMessage)) {
|
||||
return this.translateWithFallback(
|
||||
'HOME.PLAYLISTS.PLAYLIST_UPDATE_FILE_ACCESS_ERROR',
|
||||
'Playlist refresh failed. The app can no longer access the local file.'
|
||||
);
|
||||
}
|
||||
|
||||
return this.translateService.instant(
|
||||
'HOME.PLAYLISTS.PLAYLIST_UPDATE_ERROR'
|
||||
);
|
||||
}
|
||||
|
||||
const statusCode = this.extractHttpStatusCode(error);
|
||||
if (statusCode === 404) {
|
||||
return this.translateService.instant('HOME.URL_UPLOAD.ERROR_404');
|
||||
}
|
||||
if (statusCode === 403) {
|
||||
return this.translateService.instant('HOME.URL_UPLOAD.ERROR_403');
|
||||
}
|
||||
if (statusCode === 401) {
|
||||
return this.translateService.instant('HOME.URL_UPLOAD.ERROR_401');
|
||||
}
|
||||
return this.translateService.instant(
|
||||
'HOME.URL_UPLOAD.ERROR_FETCH_FAILED'
|
||||
);
|
||||
}
|
||||
|
||||
private translateWithFallback(key: string, fallback: string): string {
|
||||
const translated = this.translateService.instant(key);
|
||||
return translated === key ? fallback : translated;
|
||||
}
|
||||
|
||||
/* private getErrorMessageByStatusCode(status: number) {
|
||||
|
||||
@@ -131,10 +131,8 @@ export class PwaService extends DataService {
|
||||
.pipe(
|
||||
catchError((error) => {
|
||||
this.snackBar.open(
|
||||
`Error: ${error.message ?? 'Unknown error'}, status: ${
|
||||
error.status ?? 500
|
||||
}`,
|
||||
'Close',
|
||||
this.getPlaylistRefreshErrorMessage(error),
|
||||
this.translateService.instant('CLOSE'),
|
||||
{
|
||||
duration: 5000,
|
||||
}
|
||||
@@ -160,6 +158,25 @@ export class PwaService extends DataService {
|
||||
});
|
||||
}
|
||||
|
||||
private getPlaylistRefreshErrorMessage(error: unknown): string {
|
||||
const statusCode =
|
||||
this.getErrorDetails(error)?.status ??
|
||||
this.extractHttpStatusCode(error);
|
||||
|
||||
if (statusCode === 404) {
|
||||
return this.translateService.instant('HOME.URL_UPLOAD.ERROR_404');
|
||||
}
|
||||
if (statusCode === 403) {
|
||||
return this.translateService.instant('HOME.URL_UPLOAD.ERROR_403');
|
||||
}
|
||||
if (statusCode === 401) {
|
||||
return this.translateService.instant('HOME.URL_UPLOAD.ERROR_401');
|
||||
}
|
||||
return this.translateService.instant(
|
||||
'HOME.URL_UPLOAD.ERROR_FETCH_FAILED'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches playlist from the specified url
|
||||
* @param payload playlist payload
|
||||
@@ -189,19 +206,38 @@ export class PwaService extends DataService {
|
||||
}
|
||||
|
||||
getErrorMessageByStatusCode(status: number) {
|
||||
let message = 'Something went wrong';
|
||||
let messageKey = 'HOME.URL_UPLOAD.ERROR_FETCH_FAILED';
|
||||
switch (status) {
|
||||
case 0:
|
||||
message = 'The backend is not reachable';
|
||||
break;
|
||||
case 413:
|
||||
message =
|
||||
'This file is too big. Use standalone or self-hosted version of the app.';
|
||||
return 'This file is too big. Use standalone or self-hosted version of the app.';
|
||||
case 403:
|
||||
messageKey = 'HOME.URL_UPLOAD.ERROR_403';
|
||||
break;
|
||||
case 404:
|
||||
messageKey = 'HOME.URL_UPLOAD.ERROR_404';
|
||||
break;
|
||||
case 401:
|
||||
messageKey = 'HOME.URL_UPLOAD.ERROR_401';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return message;
|
||||
return this.translateService.instant(messageKey);
|
||||
}
|
||||
|
||||
private extractHttpStatusCode(error: unknown): number | null {
|
||||
if (
|
||||
error &&
|
||||
typeof error === 'object' &&
|
||||
'status' in error &&
|
||||
typeof error.status === 'number'
|
||||
) {
|
||||
return error.status;
|
||||
}
|
||||
|
||||
const msg = String((error as { message?: string })?.message ?? error);
|
||||
const match = msg.match(/status code (\d{3})/);
|
||||
return match ? parseInt(match[1], 10) : null;
|
||||
}
|
||||
|
||||
async forwardXtreamRequest(payload: {
|
||||
@@ -242,21 +278,23 @@ export class PwaService extends DataService {
|
||||
try {
|
||||
let result: PwaErrorResult | PwaXtreamResult;
|
||||
const response = (await firstValueFrom(
|
||||
this.http.get<PwaXtreamResponse>(`${this.corsProxyUrl}/xtream`, {
|
||||
params: {
|
||||
url: payload.url,
|
||||
...payload.params,
|
||||
},
|
||||
...headers,
|
||||
})
|
||||
this.http.get<PwaXtreamResponse>(
|
||||
`${this.corsProxyUrl}/xtream`,
|
||||
{
|
||||
params: {
|
||||
url: payload.url,
|
||||
...payload.params,
|
||||
},
|
||||
...headers,
|
||||
}
|
||||
)
|
||||
)) as PwaXtreamResponse;
|
||||
|
||||
if (!response.payload) {
|
||||
const action = payload.params.action;
|
||||
const isSilentAction = this.silentXtreamActions.has(action);
|
||||
const normalizedMessage = this.getReadableXtreamErrorMessage(
|
||||
response
|
||||
);
|
||||
const normalizedMessage =
|
||||
this.getReadableXtreamErrorMessage(response);
|
||||
logPortalDebugEvent(
|
||||
createPortalDebugErrorEvent(context, response)
|
||||
);
|
||||
@@ -347,9 +385,10 @@ export class PwaService extends DataService {
|
||||
if (
|
||||
maybeError.error &&
|
||||
typeof maybeError.error === 'object' &&
|
||||
'message' in (maybeError.error as Record<string, unknown>) &&
|
||||
typeof (maybeError.error as Record<string, unknown>).message ===
|
||||
'string'
|
||||
'message' in
|
||||
(maybeError.error as Record<string, unknown>) &&
|
||||
typeof (maybeError.error as Record<string, unknown>)
|
||||
.message === 'string'
|
||||
) {
|
||||
return (maybeError.error as Record<string, string>).message;
|
||||
}
|
||||
|
||||
@@ -77,6 +77,8 @@
|
||||
"MY_PLAYLISTS_SUBTITLE": "all available playlists",
|
||||
"PLAYLIST_UPDATE_SUCCESS": "Success! The playlist was successfully updated.",
|
||||
"PLAYLIST_UPDATE_ERROR": "Error updating playlist details.",
|
||||
"PLAYLIST_UPDATE_FILE_NOT_FOUND": "Playlist refresh failed. The local file is no longer available. Check the file path or re-import the playlist.",
|
||||
"PLAYLIST_UPDATE_FILE_ACCESS_ERROR": "Playlist refresh failed. The app can no longer access the local file.",
|
||||
"AUTO_REFRESH_UPDATE_SUCCESS": "Success! The playlists were successfully updated",
|
||||
"AUTO_REFRESH_ENABLED": "Auto-refresh enabled"
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user