mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-12 20:16:15 -08:00
fix(epg): remove cached XMLTV data after source deletion
This commit is contained in:
1 parent
b55a3cc322
commit
ffcbee8140
32 files changed
+1051
-82
No files matched your search
@@ -14,7 +14,12 @@ import {
|
||||
} from '@iptvnator/workspace/shell/util';
|
||||
import { MockProvider } from 'ng-mocks';
|
||||
import { EMPTY, of } from 'rxjs';
|
||||
import { DataService, RuntimeCapabilitiesService } from '@iptvnator/services';
|
||||
import {
|
||||
DataService,
|
||||
EpgSourceSettingsService,
|
||||
SettingsStore,
|
||||
RuntimeCapabilitiesService,
|
||||
} from '@iptvnator/services';
|
||||
import {
|
||||
Language,
|
||||
Settings,
|
||||
@@ -235,6 +240,37 @@ describe('AppComponent', () => {
|
||||
expect(snackBar.open).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not reimport a deleted source from a late startup freshness response', async () => {
|
||||
await TestBed.inject(SettingsStore).loadSettings();
|
||||
let finishFreshness!: (value: {
|
||||
freshUrls: string[];
|
||||
staleUrls: string[];
|
||||
}) => void;
|
||||
epgBridge.checkFreshness = jest.fn(
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
finishFreshness = resolve;
|
||||
})
|
||||
);
|
||||
const pending = (
|
||||
component as unknown as {
|
||||
fetchStaleEpgData(urls: string[]): Promise<void>;
|
||||
}
|
||||
).fetchStaleEpgData(['https://removed.example/guide.xml']);
|
||||
await Promise.resolve();
|
||||
const sources = TestBed.inject(EpgSourceSettingsService);
|
||||
sources.revision.update((value) => value + 1);
|
||||
sources.changed$.next();
|
||||
finishFreshness({
|
||||
freshUrls: [],
|
||||
staleUrls: ['https://removed.example/guide.xml'],
|
||||
});
|
||||
await pending;
|
||||
expect(epgService.fetchEpg).not.toHaveBeenCalledWith([
|
||||
'https://removed.example/guide.xml',
|
||||
]);
|
||||
});
|
||||
|
||||
it('does not fetch EPG settings when the EPG bridge cannot import EPG', async () => {
|
||||
const settings: Settings = {
|
||||
...DEFAULT_SETTINGS,
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
DataService,
|
||||
RuntimeCapabilitiesService,
|
||||
SettingsStore,
|
||||
EpgSourceSettingsService,
|
||||
} from '@iptvnator/services';
|
||||
import {
|
||||
AUTO_UPDATE_PLAYLISTS,
|
||||
@@ -63,6 +64,7 @@ export class AppComponent implements OnInit {
|
||||
private translate = inject(TranslateService);
|
||||
private settingsService = inject(SettingsService);
|
||||
private settingsStore = inject(SettingsStore);
|
||||
private readonly epgSources = inject(EpgSourceSettingsService);
|
||||
private playbackKeepAwake = inject(PlaybackKeepAwakeService);
|
||||
private playlistOpenRequests = inject(PlaylistOpenRequestService);
|
||||
private runtime = inject(RuntimeCapabilitiesService);
|
||||
@@ -188,8 +190,15 @@ export class AppComponent implements OnInit {
|
||||
* Data is considered fresh if updated within the last 12 hours.
|
||||
*/
|
||||
private async fetchStaleEpgData(urls: string[]): Promise<void> {
|
||||
await this.settingsStore.loadSettings();
|
||||
const revision = this.epgSources.revision();
|
||||
const fetchCurrentSources = (sources: string[]) => {
|
||||
this.epgService.fetchEpg(
|
||||
this.epgSources.retainCurrentSources(sources, revision)
|
||||
);
|
||||
};
|
||||
if (!this.epgBridge.supportsSourceFreshness) {
|
||||
this.epgService.fetchEpg(urls);
|
||||
fetchCurrentSources(urls);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -197,7 +206,7 @@ export class AppComponent implements OnInit {
|
||||
const result = await this.epgBridge.checkFreshness(urls, 12);
|
||||
|
||||
if (!result) {
|
||||
this.epgService.fetchEpg(urls);
|
||||
fetchCurrentSources(urls);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -219,12 +228,12 @@ export class AppComponent implements OnInit {
|
||||
debugAppComponent(
|
||||
`EPG: Fetching ${result.staleUrls.length} stale source(s)`
|
||||
);
|
||||
this.epgService.fetchEpg(result.staleUrls);
|
||||
fetchCurrentSources(result.staleUrls);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error checking EPG freshness, fetching all:', error);
|
||||
// Fallback: fetch all URLs if freshness check fails
|
||||
this.epgService.fetchEpg(urls);
|
||||
fetchCurrentSources(urls);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,10 @@ import { MatIconModule } from '@angular/material/icon';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { SettingsContextService } from '@iptvnator/workspace/shell/util';
|
||||
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
||||
import { RuntimeCapabilitiesService } from '@iptvnator/services';
|
||||
import {
|
||||
EpgSourceReconciliationError,
|
||||
RuntimeCapabilitiesService,
|
||||
} from '@iptvnator/services';
|
||||
import { VodSourceDiscoveryService } from '@iptvnator/portal/shared/data-access';
|
||||
import { Language, StreamFormat } from '@iptvnator/shared/interfaces';
|
||||
import { firstValueFrom, map } from 'rxjs';
|
||||
@@ -307,7 +310,13 @@ export class SettingsComponent
|
||||
try {
|
||||
await this.form.save(() => this.applyChangedSettings());
|
||||
return true;
|
||||
} catch {
|
||||
} catch (error) {
|
||||
if (error instanceof EpgSourceReconciliationError) {
|
||||
this.settingsSnackbar.open(
|
||||
this.translate.instant('SETTINGS.EPG_DATA_CLEAR_FAILED')
|
||||
);
|
||||
return false;
|
||||
}
|
||||
// The store already applied the change in memory, so without
|
||||
// this the save looks successful until the next restart. The
|
||||
// unsaved-changes bar stays visible so it can be retried.
|
||||
|
||||
Reference in new issue
Block a user