public async Task <Playlist> FetchProviderPlaylistAsync(PlaylistProvider provider) { Playlist playlist = await GetPlaylistAsync(provider); if (Playlist.IsNullOrEmpty(playlist)) { logger.Debug( MyOperation.PlaylistFetching, OperationStatus.Failure, new LogInfo(MyLogInfoKey.Provider, provider.Name)); return(null); } if (!string.IsNullOrWhiteSpace(provider.ChannelNameOverride)) { foreach (Channel channel in playlist.Channels) { channel.Name = provider.ChannelNameOverride; } } logger.Debug( MyOperation.PlaylistFetching, OperationStatus.Success, new LogInfo(MyLogInfoKey.Provider, provider.Name)); return(playlist); }
public async Task <IActionResult> GetFile(string publicId, [FromQuery] string provider = "m3u", CancellationToken cancellationToken = default) { var idGuid = GetInternalPlaylistId(publicId); var playlist = await _dbContext.Playlist.FirstOrDefaultAsync(x => x.UniqueId == idGuid, cancellationToken); if (playlist == null) { return(NotFound(publicId)); } PlaylistProvider <Playlist <TvgMedia>, TvgMedia> sourceProvider = null; try { sourceProvider = _providerFactory.CreateInstance(playlist.SynkConfig.Uri, provider); } catch (Exception ex) { return(BadRequest(ex.Message)); } using (sourceProvider) using (var pl = new Playlist <TvgMedia>(sourceProvider)) using (var sourcePl = new Playlist <TvgMedia>(playlist.TvgMedias.Where(x => x.Enabled && !x.MediaGroup.Disabled))) { return(await pl.PushAsync(sourcePl, cancellationToken).ContinueWith(t => { return File(sourceProvider.PlaylistStream.ToArray(), "text/plain"); })); } }
public async Task <IActionResult> Import(string playlistName, string playlistUrl, string provider, IFormFile file, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(playlistName)) { throw new ArgumentNullException(nameof(provider)); } if (string.IsNullOrEmpty(playlistName)) { playlistName = file.FileName.Replace(Path.GetExtension(file.FileName), string.Empty); //TODO : catch all ArgumentException et les passer en BadRequest } //Vérifier si la playlist existe bien avant PlaylistProvider <Playlist <TvgMedia>, TvgMedia> providerInstance = null; try { providerInstance = _providerFactory.CreateInstance(playlistUrl, provider); } catch (Exception ex) { return(BadRequest(ex.Message)); } var playlistStream = file.OpenReadStream(); if (string.IsNullOrEmpty(playlistUrl)) { //TODO : Save file and get Url throw new ApplicationException("Import playlist from file not supported yet !!"); } using (providerInstance) { var user = await _dbContext.Users.FindAsync(new object[] { UserId }, cancellationToken); if (user == null) { return(BadRequest($"User {this.UserEmail} not found")); } var pl = await _playlistService.SynkPlaylistAsync(() => new Playlist { UserId = user.Id, Freindlyname = playlistName, Status = PlaylistStatus.Enabled, SynkConfig = null, Tags = new Dictionary <string, string> { { PlaylistTags.ImportProvider, provider } } }, providerInstance, _xtreamService.IsXtreamPlaylist(playlistUrl), true, cancellationToken); ClearCache(); var result = PlaylistModel.ToLightModel(pl, Url); return(Created(result.PublicUrl, result)); } }
public async Task ExecuteAsync(CancellationToken cancellationToken) { IQueryable <Playlist> playlists = _dbContext.Playlist .Include(x => x.User) //.ThenInclude(u => u.Devices) .Where(x => x.Status == PlaylistStatus.Enabled); playlists.AsParallel().WithCancellation(cancellationToken).ForAll(async pl => { try { PlaylistProvider <Playlist <TvgMedia>, TvgMedia> provider = null; try { provider = _providerFactory.CreateInstance(pl.SynkConfig.Uri, pl.SynkConfig.Provider); } catch (Exception) { throw new ApplicationException("Can't resolve playlist provider"); } (IEnumerable <TvgMedia> tvgMedia, IEnumerable <TvgMedia> removed) = await _playlistService.DiffWithSourceAsync(() => pl, provider, false, cancellationToken); if (removed.Any() || tvgMedia.Any()) { _logger.LogInformation($"Diff detected for the playlist {pl.Id} of user {pl.UserId}"); //publish message to Rabbit await _bus.Publish(new DiffPlaylistEvent { Id = pl.Id, PlaylistName = pl.Freindlyname, UserId = pl.User.Email, RemovedMediasCount = removed.Count(), RemovedMedias = removed.Take(10), NewMediasCount = tvgMedia.Count(), NewMedias = tvgMedia.Take(10) }, cancellationToken); } } catch (Exception ex) { _logger.LogError(ex, ex.Message); await _bus.Publish(new TraceEvent { Message = $"playlistId : {pl.Id}, Exception :{ex.Message}", UserId = pl.User.Email, Level = TraceEvent.LevelTrace.Error, Source = nameof(DiffHostedService) }, cancellationToken); } } ); }
async Task <Playlist> GetPlaylistAsync(PlaylistProvider provider) { Playlist playlist = await GetPlaylistForTodayAsync(provider); if (Playlist.IsNullOrEmpty(playlist)) { playlist = GetPlaylistForPastDays(provider); } return(playlist); }
public async Task <Playlist> FetchProviderPlaylistAsync(PlaylistProvider provider) { Playlist playlist = null; for (int i = 0; i < applicationSettings.DaysToCheck; i++) { DateTime date = DateTime.Now.AddDays(-i); playlist = LoadPlaylistFromCache(provider, date); if (playlist is null) { string playlistFile = await DownloadPlaylistFileAsync(provider, date); playlist = playlistFileBuilder.TryParseFile(playlistFile); if (!Playlist.IsNullOrEmpty(playlist) && !provider.DontCache) { cache.StorePlaylistFile(provider.Id, date, playlistFile); } } if (!(playlist is null)) { break; } } if (Playlist.IsNullOrEmpty(playlist)) { logger.Debug( MyOperation.PlaylistFetching, OperationStatus.Failure, new LogInfo(MyLogInfoKey.Provider, provider.Name)); return(null); } if (!string.IsNullOrWhiteSpace(provider.ChannelNameOverride)) { foreach (Channel channel in playlist.Channels) { channel.Name = provider.ChannelNameOverride; } } logger.Debug( MyOperation.PlaylistFetching, OperationStatus.Success, new LogInfo(MyLogInfoKey.Provider, provider.Name)); return(playlist); }
internal static PlaylistProvider ToServiceModel(this PlaylistProviderEntity dataObject) { PlaylistProvider serviceModel = new PlaylistProvider(); serviceModel.Id = dataObject.Id; serviceModel.IsEnabled = dataObject.IsEnabled; serviceModel.Priority = dataObject.Priority; serviceModel.DontCache = dataObject.DontCache; serviceModel.Name = dataObject.Name; serviceModel.UrlFormat = dataObject.UrlFormat; serviceModel.ChannelNameOverride = dataObject.ChannelNameOverride; return(serviceModel); }
internal static PlaylistProviderEntity ToDataObject(this PlaylistProvider serviceModel) { PlaylistProviderEntity dataObject = new PlaylistProviderEntity(); dataObject.Id = serviceModel.Id; dataObject.IsEnabled = serviceModel.IsEnabled; dataObject.Priority = serviceModel.Priority; dataObject.DontCache = serviceModel.DontCache; dataObject.Name = serviceModel.Name; dataObject.UrlFormat = serviceModel.UrlFormat; dataObject.ChannelNameOverride = serviceModel.ChannelNameOverride; return(dataObject); }
/// <summary> /// Synk playlist and match epg, logos and groups /// </summary> /// <param name="playlist">Playlist</param> /// <param name="resetAndSynch">Reset and synchronize playlist from scrach</param> /// <param name="cancellationToken"></param> /// <returns></returns> public async Task <Playlist> SynkPlaylistAsync(Playlist playlist, bool resetAndSynch = false, CancellationToken cancellationToken = default) { if (playlist == null) { throw new ArgumentNullException($"Playlist not found"); } if (!playlist.IsSynchronizable || playlist.SynkConfig.AutoSynchronize) { throw new ApplicationException($"Playlist isn't synchronizable or not auto synchrizable is disabled"); } PlaylistProvider <Playlist <TvgMedia>, TvgMedia> provider = null; try { provider = _providerFactory.CreateInstance(playlist.SynkConfig.Uri, playlist.SynkConfig.Provider); } catch (Exception) { throw new ApplicationException("Can't resolve playlist provider"); } if (resetAndSynch) { return(await SynkPlaylistAsync(() => _dbcontext.Playlist.Find(playlist.Id), provider, false, resetAndSynch, cancellationToken)); } var(tvgMedia, removed) = await DiffWithSourceAsync(() => playlist, provider, true, cancellationToken); var changed = false; if (removed != null && removed.Any()) { playlist.TvgMedias.RemoveAll(x => removed.Any(r => r.Id == x.Id)); changed = true; } if (tvgMedia != null && tvgMedia.Any()) { playlist.TvgMedias.AddRange(tvgMedia); changed = true; } if (changed) { playlist.TvgMedias = playlist.TvgMedias; var resRq = await _dbcontext.SaveChangesAsync(cancellationToken); } return(playlist); }
/// <summary> /// Synk playlist and match epg, logos and groups /// </summary> /// <param name="getPlaylist"></param> /// <param name="provider"></param> /// <param name="isXtreamPlaylist"></param> /// <param name="force"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public async Task <Playlist> SynkPlaylistAsync(Func <Playlist> getPlaylist, PlaylistProvider <Playlist <TvgMedia>, TvgMedia> provider = default, bool isXtreamPlaylist = false, bool force = false, CancellationToken cancellationToken = default) { var playlistEntity = getPlaylist(); if (playlistEntity == null) { throw new ArgumentNullException($"Playlist not found"); } if (!playlistEntity.IsSynchronizable) { throw new ApplicationException($"Playlist isn't synchronizable"); } try { provider = _providerFactory.CreateInstance(playlistEntity.SynkConfig.Uri, playlistEntity.SynkConfig.Provider); } catch (Exception) { throw new ApplicationException("Can't resolve playlist provider"); } using (var playlist = new Playlist <TvgMedia>(provider)) { var sourceList = await playlist.PullAsync(cancellationToken); //Faire passer les handlers sourceList = ExecuteHandlersAsync(sourceList, cancellationToken); if (sourceList.Any()) { playlistEntity.TvgMedias = sourceList.Where(x => x.IsValid).ToList(); } UpdateIsXtreamTag(isXtreamPlaylist, playlistEntity); } if (playlistEntity.CreatedDate == default) { await _dbcontext.Playlist.AddAsync(playlistEntity, cancellationToken); } playlistEntity.TvgMedias = playlistEntity.TvgMedias; var res = await _dbcontext.SaveChangesAsync(cancellationToken); return(playlistEntity); }
public async Task <IActionResult> DiffAsync([FromBody] PlaylistPostModel playlistPostModel, CancellationToken cancellationToken = default) { //TODO: Déduire le provider from playlist (isXtream => xtreamProvider, m3u ou tvlist) // Load dynmaiquement all providers (singleton) PlaylistProvider <Playlist <TvgMedia>, TvgMedia> providerInstance = null; try { providerInstance = _providerFactory.CreateInstance(playlistPostModel.Url, playlistPostModel.Provider); } catch (Exception ex) { return(BadRequest(ex.Message)); } try { var user = await _dbContext.Users.FindAsync(new object[] { UserId }, cancellationToken); if (user == null) { return(BadRequest($"User {this.UserEmail} not found")); } var playlist = await _dbContext.Playlist .FirstOrDefaultAsync(x => x.SynkConfig.Url == playlistPostModel.Url, cancellationToken) ?? new Playlist { UserId = user.Id, Freindlyname = playlistPostModel.Freindlyname, Status = playlistPostModel.Status, SynkConfig = new SynkConfig { Url = playlistPostModel.Url, Provider = playlistPostModel.Provider } }; using (providerInstance) { var pl = await _playlistService .DiffWithSourceAsync(() => playlist, providerInstance, cancellationToken : cancellationToken); return(Ok(pl)); } } catch (HttpRequestException) { throw new BusinessException($"Playlist url {playlistPostModel.Url} not reachable"); } }
Playlist LoadPlaylistFromCache(PlaylistProvider provider, DateTime date) { if (provider.DontCache) { return(null); } string content = cache.GetPlaylistFile(provider.Id, date); if (string.IsNullOrWhiteSpace(content)) { return(null); } return(playlistFileBuilder.TryParseFile(content)); }
public async Task <IActionResult> ImportFromUrl([FromBody] PlaylistPostModel playlistPostModel, CancellationToken cancellationToken) { //Vérifier si la playlist existe-elle avant var stopwatch = Stopwatch.StartNew(); PlaylistProvider <Playlist <TvgMedia>, TvgMedia> providerInstance = null; try { providerInstance = _providerFactory.CreateInstance(playlistPostModel.Url, playlistPostModel.Provider); } catch (Exception ex) { return(BadRequest(ex.Message)); } using (providerInstance) { var user = await _dbContext.Users.FindAsync(new object[] { UserId }, cancellationToken); if (user == null) { return(BadRequest($"User {this.UserEmail} not found")); } var pl = await _playlistService.SynkPlaylistAsync(() => new Playlist { UserId = user.Id, Freindlyname = playlistPostModel.Freindlyname, Status = PlaylistStatus.Enabled, SynkConfig = new SynkConfig { Url = playlistPostModel.Url }, Tags = new Dictionary <string, string> { { PlaylistTags.ImportProvider, playlistPostModel.Provider } } }, providerInstance, _xtreamService.IsXtreamPlaylist(playlistPostModel.Url), cancellationToken : cancellationToken); ClearCache(); stopwatch.Stop(); _logger.LogInformation($"Elapsed time : {stopwatch.Elapsed.ToString("c")}"); var model = PlaylistModel.ToLightModel(pl, Url); return(Created(model.PublicUrl, model)); } }
async Task <Playlist> GetPlaylistForTodayAsync(PlaylistProvider provider) { string playlistFile = await DownloadPlaylistFileAsync(provider, DateTime.UtcNow); Playlist playlist = LoadPlaylistFromCache(provider, DateTime.UtcNow); if (playlist is null) { playlist = playlistFileBuilder.TryParseFile(playlistFile); } if (!Playlist.IsNullOrEmpty(playlist) && !provider.DontCache) { cache.StorePlaylistFile(provider.Id, DateTime.UtcNow, playlistFile); } return(playlist); }
public MusicDataManager() { _databaseFile = new FileInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Hurricane", "database.sqlite")); Images = new ImagesProvider(); Artists = new ArtistProvider(Images); Albums = new AlbumsProvider(Artists); Tracks = new TrackProvider(Artists, Images, Albums); Playlists = new PlaylistProvider(Tracks); UserData = new UserDataProvider(); LastfmApi = new LastfmApi(Artists); MusicManager = new MusicManager(); MusicManager.TrackChanged += MusicManager_TrackChanged; MusicManager.NewTrackOpened += MusicManager_NewTrackOpened; MusicStreamingPluginManager = new MusicStreamingPluginManager(); }
public ViewManager(PlaylistProvider playlistProvider) { ViewItems = new ObservableCollection <ISideListItem> { new HomeView(), new CollectionView(), new ChartsView(), new QueueView(), new HistoryView() }; playlistProvider.PlaylistAdded += PlaylistProvider_PlaylistAdded; playlistProvider.PlaylistRemoved += PlaylistProvider_PlaylistRemoved; foreach (var userPlaylist in playlistProvider.Playlists) { ViewItems.Add(new PlaylistView(userPlaylist)); } ViewSource = CollectionViewSource.GetDefaultView(ViewItems); ViewSource.GroupDescriptions.Add(new PropertyGroupDescription("ViewCategorie")); }
Playlist GetPlaylistForPastDays(PlaylistProvider provider) { if (!provider.UrlFormat.Contains("{0")) { return(null); } Playlist playlist = null; for (int i = 1; i < applicationSettings.DaysToCheck; i++) { DateTime date = DateTime.UtcNow.AddDays(-i); playlist = LoadPlaylistFromCache(provider, date); if (!(playlist is null)) { break; } } return(playlist); }
/// <summary> /// Genére un rapport avec les new medias et /// les médias qui n'existes plus /// </summary> /// <param name="id"></param> /// <param name="force"></param> /// <param name="token"></param> /// <returns></returns> public async Task <(IEnumerable <TvgMedia> tvgMedia, IEnumerable <TvgMedia> removed)> DiffWithSourceAsync(Func <Playlist> getPlaylist, PlaylistProvider <Playlist <TvgMedia>, TvgMedia> provider, bool force = false, CancellationToken cancellationToken = default) { var pl = getPlaylist(); if (pl == null) { throw new ArgumentNullException($"Playlist not found"); } if (!pl.IsSynchronizable) { throw new ApplicationException($"Playlist isn't synchronizable"); } using (var playlist = new Playlist <TvgMedia>(provider)) { var sourceList = await playlist.PullAsync(cancellationToken); if (sourceList == null) { return(new List <TvgMedia>(), pl.TvgMedias ?? new List <TvgMedia>()); } if (pl.TvgMedias == null || !pl.TvgMedias.Any()) { return(sourceList, null); } return(sourceList.Where(s => pl.TvgMedias.All(t => t.Url != s.Url)).ToList(), pl.TvgMedias.Where(s => sourceList.All(t => t.Url != s.Url)).ToList()); } }
async Task <string> DownloadPlaylistFileAsync(PlaylistProvider provider, DateTime date) { string url = string.Format(provider.UrlFormat, date); return(await fileDownloader.TryDownloadStringAsync(url)); }