diff --git a/Dockerfile b/Dockerfile index 322bdce..af954ea 100644 --- a/Dockerfile +++ b/Dockerfile @@ -54,7 +54,13 @@ RUN apt-get update && apt-get install -y sqlite3 libsqlite3-dev ffmpeg && rm -rf # Create directory for HLS stream output RUN mkdir -p /tmp/streams && chmod 777 /tmp/streams -# Copy entire bin directory (API, database, etc.) +# Copy pubspec.yaml (required for dependencies) +COPY pubspec.yaml ./ + +# Copy lib directory (required for shared models) +COPY lib/ ./lib/ + +# Copy bin directory COPY bin/ ./bin/ # Get dependencies @@ -67,5 +73,5 @@ COPY --from=builder /app/build/web /app/web EXPOSE 8089 # Serve web application with API proxy -WORKDIR /app/bin -CMD ["dart", "run", "server.dart", "--port", "8089", "--path", "/app/web"] +WORKDIR /app +CMD ["dart", "run", "bin/server.dart", "--port", "8089", "--path", "/app/web"] diff --git a/bin/api/streaming_handler.dart b/bin/api/streaming_handler.dart index 9fe4325..c958eb1 100644 --- a/bin/api/streaming_handler.dart +++ b/bin/api/streaming_handler.dart @@ -34,13 +34,19 @@ PlaylistConfig? _getCurrentPlaylist(Request request) { Handler createLiveStreamHandler(Future Function(Request) getPlaylist) { final router = Router(); - // Route: /api/live/{streamId}.ts - router.get('/.ts', (Request request, String streamId) async { - final playlist = await getPlaylist(request); - if (playlist == null) { - return Response.internalServerError(body: 'No playlist configured'); + // Route: /api/live/{streamId} (Catch all pattern to debug) + router.get('/', (Request request, String streamId) async { + print('[Live] Incoming request for streamId: $streamId'); + + // Remove .ts extension if present + if (streamId.endsWith('.ts')) { + streamId = streamId.substring(0, streamId.length - 3); } + final playlist = await getPlaylist(request); + + // ... existing logic ... + final targetUrl = Uri.parse('${playlist.dns}/live/${playlist.username}/${playlist.password}/$streamId.ts'); print('[Live] Proxying: $targetUrl'); diff --git a/bin/pubspec.yaml b/bin/pubspec.yaml index ad951e4..cd99d09 100644 --- a/bin/pubspec.yaml +++ b/bin/pubspec.yaml @@ -15,3 +15,5 @@ dependencies: sqlite3: ^2.4.0 crypto: ^3.0.3 uuid: ^4.3.3 + hive: ^2.2.3 + equatable: ^2.0.5 diff --git a/bin/server.dart b/bin/server.dart index 351b98d..d4eb661 100644 --- a/bin/server.dart +++ b/bin/server.dart @@ -10,7 +10,7 @@ import 'package:args/args.dart'; import 'database/database.dart'; import 'models/user.dart'; import 'models/playlist.dart'; -import 'package:xtremflow/core/models/playlist_config.dart'; +import '../lib/core/models/playlist_config.dart'; import 'api/auth_handler.dart'; import 'api/users_handler.dart'; import 'api/playlists_handler.dart'; @@ -153,12 +153,16 @@ void main(List args) async { return null; } + // Create Streaming Router (Mount handlers on correct paths) + final streamingRouter = Router() + ..mount('/api/live', createLiveStreamHandler(_getPlaylist)) + ..mount('/api/vod', createVodStreamHandler(_getPlaylist)); + // Main handler with API proxy and NEW Streaming Handlers final handler = Cascade() - .add(_createApiHandler(apiRouter)) + .add(apiRouter.call) /* Standard API endpoints */ .add(_createXtreamProxyHandler()) /* Keep for general API calls */ - .add(createLiveStreamHandler(_getPlaylist)) - .add(createVodStreamHandler(_getPlaylist)) + .add(streamingRouter.call) /* Streaming endpoints */ .add(staticHandler) .handler; @@ -190,22 +194,7 @@ void main(List args) async { }); } -/// Create API handler -Handler _createApiHandler(Router apiRouter) { - return (Request request) async { - final path = request.url.path; - - // Only handle /api/* requests (excluding special handlers) - if (path.startsWith('api/') && - !path.startsWith('api/xtream/') && - !path.startsWith('api/live/') && - !path.startsWith('api/vod/')) { - return apiRouter(request); - } - - return Response.notFound('Not found'); - }; -} + /// CORS middleware to allow cross-origin requests Middleware _corsMiddleware() { diff --git a/build_log.txt b/build_log.txt new file mode 100644 index 0000000..1c0f614 Binary files /dev/null and b/build_log.txt differ diff --git a/build_log_2.txt b/build_log_2.txt new file mode 100644 index 0000000..7892e8f Binary files /dev/null and b/build_log_2.txt differ diff --git a/lib/features/iptv/providers/settings_provider.dart b/lib/features/iptv/providers/settings_provider.dart index eb3733b..d055984 100644 --- a/lib/features/iptv/providers/settings_provider.dart +++ b/lib/features/iptv/providers/settings_provider.dart @@ -299,7 +299,6 @@ class IptvSettingsNotifier extends StateNotifier { preferredAspectRatio: getValue(_SettingsKeys.preferredAspectRatio), playerType: remoteSettings[_SettingsKeys.playerType] != null ? PlayerType.values[remoteSettings[_SettingsKeys.playerType] as int] : null, - forceVodTranscoding: getValue(_SettingsKeys.forceVodTranscoding), ); } _initialized = true; diff --git a/lib/features/iptv/widgets/streaming_settings_tab.dart b/lib/features/iptv/widgets/streaming_settings_tab.dart index 8b2c53c..0d4eaf4 100644 --- a/lib/features/iptv/widgets/streaming_settings_tab.dart +++ b/lib/features/iptv/widgets/streaming_settings_tab.dart @@ -150,20 +150,7 @@ class StreamingSettingsTab extends ConsumerWidget { activeColor: Colors.blueAccent, onChanged: (v) => notifier.setPreferDirectPlay(v), ), - Divider(height: 1, color: Colors.white.withOpacity(0.1)), - SwitchListTile( - title: Text( - 'Forcer audio VOD (Films/Séries)', - style: GoogleFonts.roboto(fontSize: 14, color: Colors.white), - ), - subtitle: Text( - 'Active FFmpeg pour garantir le son\n⚠️ Désactive le seeking', - style: GoogleFonts.roboto(fontSize: 12, color: Colors.white54), - ), - value: settings.forceVodTranscoding, - activeColor: Colors.orangeAccent, - onChanged: (v) => notifier.setForceVodTranscoding(v), - ), + ], ), const SizedBox(height: 16),