mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
feat(database): implement database service for playlist management and operations
This commit is contained in:
1 parent
9cb326aa44
commit
e710f472b4
3 files changed
+221
No files matched your search
@@ -0,0 +1,131 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import Database from '@tauri-apps/plugin-sql';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class DatabaseService {
|
||||
private static db: Database | null = null;
|
||||
|
||||
async getConnection(): Promise<Database> {
|
||||
if (!DatabaseService.db) {
|
||||
DatabaseService.db = await Database.load('sqlite:database.db');
|
||||
}
|
||||
return DatabaseService.db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a playlist and all its related data
|
||||
* @param playlistId ID of the playlist to delete
|
||||
* @returns True if deletion was successful
|
||||
*/
|
||||
async deletePlaylist(playlistId: string): Promise<boolean> {
|
||||
try {
|
||||
const db = await this.getConnection();
|
||||
|
||||
// Start a transaction to ensure all related data is deleted
|
||||
await db.execute('BEGIN TRANSACTION');
|
||||
|
||||
try {
|
||||
// Delete from recently_viewed table (related to content which is related to playlist)
|
||||
await db.execute(
|
||||
`
|
||||
DELETE FROM recently_viewed
|
||||
WHERE content_id IN (
|
||||
SELECT c.id
|
||||
FROM content c
|
||||
JOIN categories cat ON c.category_id = cat.id
|
||||
WHERE cat.playlist_id = ?
|
||||
)
|
||||
`,
|
||||
[playlistId]
|
||||
);
|
||||
|
||||
// Delete content related to the playlist's categories
|
||||
await db.execute(
|
||||
`
|
||||
DELETE FROM content
|
||||
WHERE category_id IN (
|
||||
SELECT id FROM categories WHERE playlist_id = ?
|
||||
)
|
||||
`,
|
||||
[playlistId]
|
||||
);
|
||||
|
||||
// Delete categories related to the playlist
|
||||
await db.execute(
|
||||
'DELETE FROM categories WHERE playlist_id = ?',
|
||||
[playlistId]
|
||||
);
|
||||
|
||||
// Finally, delete the playlist itself
|
||||
await db.execute('DELETE FROM playlists WHERE id = ?', [
|
||||
playlistId,
|
||||
]);
|
||||
|
||||
// Commit the transaction
|
||||
await db.execute('COMMIT');
|
||||
return true;
|
||||
} catch (error) {
|
||||
// If any error occurs, rollback the transaction
|
||||
await db.execute('ROLLBACK');
|
||||
throw error;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error deleting playlist:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async updateXtreamPlaylist(playlist: any): Promise<boolean> {
|
||||
try {
|
||||
const db = await this.getConnection();
|
||||
await db.execute('UPDATE playlists SET name = ? WHERE id = ?', [
|
||||
playlist.name,
|
||||
playlist.id,
|
||||
]);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error updating playlist:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async updateXtreamPlaylistDetails(playlist: {
|
||||
id: string;
|
||||
title: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
serverUrl?: string;
|
||||
}): Promise<boolean> {
|
||||
try {
|
||||
const db = await this.getConnection();
|
||||
const updateFields: string[] = ['name = ?'];
|
||||
const params: any[] = [playlist.title];
|
||||
|
||||
if (playlist.username) {
|
||||
updateFields.push('username = ?');
|
||||
params.push(playlist.username);
|
||||
}
|
||||
if (playlist.password) {
|
||||
updateFields.push('password = ?');
|
||||
params.push(playlist.password);
|
||||
}
|
||||
if (playlist.serverUrl) {
|
||||
updateFields.push('serverUrl = ?');
|
||||
params.push(playlist.serverUrl);
|
||||
}
|
||||
|
||||
params.push(playlist.id);
|
||||
|
||||
console.log(params);
|
||||
|
||||
const query = `UPDATE playlists SET ${updateFields.join(', ')} WHERE id = ?`;
|
||||
await db.execute(query, params);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error updating playlist details:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,8 @@ export class TauriService extends DataService {
|
||||
return invoke('open_in_mpv', {
|
||||
url: (payload as any).url,
|
||||
path: (payload as any).mpvPlayerPath || '',
|
||||
title: (payload as any).title ?? '',
|
||||
thumbnail: (payload as any).thumbnail ?? '',
|
||||
}).catch((error) => {
|
||||
window.postMessage({
|
||||
type: ERROR,
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { listen } from '@tauri-apps/api/event';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
export interface MpvProcess {
|
||||
id: number;
|
||||
url: string;
|
||||
start_time: number;
|
||||
last_known_time: number | null;
|
||||
thumbnail?: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class MpvPlayerService {
|
||||
private activeProcessesSubject = new BehaviorSubject<MpvProcess[]>([]);
|
||||
public activeProcesses$ = this.activeProcessesSubject.asObservable();
|
||||
|
||||
constructor() {
|
||||
this.initializeEventListeners();
|
||||
this.loadActiveProcesses();
|
||||
}
|
||||
|
||||
private async initializeEventListeners() {
|
||||
// Listen for new processes
|
||||
await listen('mpv-process-added', (event: any) => {
|
||||
const newProcess = event.payload as MpvProcess;
|
||||
if (newProcess) {
|
||||
const currentProcesses = this.activeProcessesSubject.value;
|
||||
this.activeProcessesSubject.next([
|
||||
...currentProcesses,
|
||||
newProcess,
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
// Listen for removed processes
|
||||
await listen('mpv-process-removed', (event: any) => {
|
||||
const removedProcess = event.payload as MpvProcess;
|
||||
if (removedProcess) {
|
||||
const currentProcesses = this.activeProcessesSubject.value;
|
||||
this.activeProcessesSubject.next(
|
||||
currentProcesses.filter((p) => p.id !== removedProcess.id)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async loadActiveProcesses() {
|
||||
try {
|
||||
const processes = await invoke<MpvProcess[]>(
|
||||
'get_active_mpv_processes'
|
||||
);
|
||||
this.activeProcessesSubject.next(processes);
|
||||
} catch (error) {
|
||||
console.error('Failed to load active MPV processes:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async openStream(
|
||||
url: string,
|
||||
title: string,
|
||||
thumbnail?: string,
|
||||
mpvPath: string = ''
|
||||
): Promise<number> {
|
||||
return await invoke<number>('open_in_mpv', {
|
||||
url,
|
||||
path: mpvPath,
|
||||
title,
|
||||
thumbnail,
|
||||
});
|
||||
}
|
||||
|
||||
async playStream(processId: number): Promise<void> {
|
||||
await invoke('mpv_play', { processId });
|
||||
}
|
||||
|
||||
async pauseStream(processId: number): Promise<void> {
|
||||
await invoke('mpv_pause', { processId });
|
||||
}
|
||||
|
||||
async closeStream(processId: number): Promise<void> {
|
||||
await invoke('close_mpv_process', { processId });
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user