Esempio n. 1
0
        private string GetLanguage(ListingsProviderInfo info)
        {
            if (!string.IsNullOrWhiteSpace(info.PreferredLanguage))
            {
                return(info.PreferredLanguage);
            }

            return(_config.Configuration.PreferredMetadataLanguage);
        }
Esempio n. 2
0
        public Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings)
        {
            // Assume all urls are valid. check files for existence
            if (!info.Path.StartsWith("http", StringComparison.OrdinalIgnoreCase) && !_fileSystem.FileExists(info.Path))
            {
                throw new FileNotFoundException("Could not find the XmlTv file specified:", info.Path);
            }

            return(Task.FromResult(true));
        }
Esempio n. 3
0
        public async Task <List <NameIdPair> > GetLineups(ListingsProviderInfo info, string country, string location)
        {
            // In theory this should never be called because there is always only one lineup
            var channels = await GetChannels(info, CancellationToken.None);

            return(channels.Select(i => new NameIdPair
            {
                Name = i.Name,
                Id = i.Id
            }).ToList());
        }
Esempio n. 4
0
        public async Task <List <NameIdPair> > GetHeadends(ListingsProviderInfo info, string country, string location, CancellationToken cancellationToken)
        {
            var token = await GetToken(info, cancellationToken);

            var lineups = new List <NameIdPair>();

            if (string.IsNullOrWhiteSpace(token))
            {
                return(lineups);
            }

            var options = new HttpRequestOptions()
            {
                Url                  = ApiUrl + "/headends?country=" + country + "&postalcode=" + location,
                UserAgent            = UserAgent,
                CancellationToken    = cancellationToken,
                LogErrorResponseBody = true
            };

            options.RequestHeaders["token"] = token;

            try
            {
                using (Stream responce = await Get(options, false, info).ConfigureAwait(false))
                {
                    var root = _jsonSerializer.DeserializeFromStream <List <ScheduleDirect.Headends> >(responce);

                    if (root != null)
                    {
                        foreach (ScheduleDirect.Headends headend in root)
                        {
                            foreach (ScheduleDirect.Lineup lineup in headend.lineups)
                            {
                                lineups.Add(new NameIdPair
                                {
                                    Name = string.IsNullOrWhiteSpace(lineup.name) ? lineup.lineup : lineup.name,
                                    Id   = lineup.uri.Substring(18)
                                });
                            }
                        }
                    }
                    else
                    {
                        _logger.Info("No lineups available");
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.Error("Error getting headends", ex);
            }

            return(lineups);
        }
Esempio n. 5
0
        private async Task <List <ScheduleDirect.ShowImages> > GetImageForPrograms(
            ListingsProviderInfo info,
            List <string> programIds,
            CancellationToken cancellationToken)
        {
            if (programIds.Count == 0)
            {
                return(new List <ScheduleDirect.ShowImages>());
            }

            var imageIdString = "[";

            foreach (var i in programIds)
            {
                var imageId = i.Substring(0, 10);

                if (!imageIdString.Contains(imageId))
                {
                    imageIdString += "\"" + imageId + "\",";
                }
            }

            imageIdString = imageIdString.TrimEnd(',') + "]";

            var httpOptions = new HttpRequestOptions()
            {
                Url                  = ApiUrl + "/metadata/programs",
                UserAgent            = UserAgent,
                CancellationToken    = cancellationToken,
                RequestContent       = imageIdString,
                LogErrorResponseBody = true,
                // The data can be large so give it some extra time
                TimeoutMs = 60000
            };

            try
            {
                using (var innerResponse2 = await Post(httpOptions, true, info).ConfigureAwait(false))
                {
                    return(_jsonSerializer.DeserializeFromStream <List <ScheduleDirect.ShowImages> >(
                               innerResponse2.Content));
                }
            }
            catch (Exception ex)
            {
                _logger.ErrorException("Error getting image info from schedules direct", ex);

                return(new List <ScheduleDirect.ShowImages>());
            }
        }
Esempio n. 6
0
        public async Task <List <NameIdPair> > GetLineups(ListingsProviderInfo info, string country, string location)
        {
            // In theory this should never be called because there is always only one lineup
            var path = await GetXml(info.Path, CancellationToken.None).ConfigureAwait(false);

            var reader  = new XmlTvReader(path, GetLanguage());
            var results = reader.GetChannels();

            // Should this method be async?
            return(results.Select(c => new NameIdPair()
            {
                Id = c.Id, Name = c.DisplayName
            }).ToList());
        }
Esempio n. 7
0
        private bool IsListingProviderEnabledForTuner(ListingsProviderInfo info, string tunerHostId)
        {
            if (info.EnableAllTuners)
            {
                return(true);
            }

            if (string.IsNullOrWhiteSpace(tunerHostId))
            {
                throw new ArgumentNullException("tunerHostId");
            }

            return(info.EnabledTuners.Contains(tunerHostId, StringComparer.OrdinalIgnoreCase));
        }
Esempio n. 8
0
        public async Task <List <NameIdPair> > GetHeadends(ListingsProviderInfo info, string country, string location, CancellationToken cancellationToken)
        {
            var token = await GetToken(info, cancellationToken).ConfigureAwait(false);

            var lineups = new List <NameIdPair>();

            if (string.IsNullOrWhiteSpace(token))
            {
                return(lineups);
            }

            using var options = new HttpRequestMessage(HttpMethod.Get, ApiUrl + "/headends?country=" + country + "&postalcode=" + location);
            options.Headers.TryAddWithoutValidation("token", token);

            try
            {
                using var httpResponse = await Send(options, false, info, cancellationToken).ConfigureAwait(false);

                await using var response = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);

                var root = await _jsonSerializer.DeserializeFromStreamAsync <List <ScheduleDirect.Headends> >(response).ConfigureAwait(false);

                if (root != null)
                {
                    foreach (ScheduleDirect.Headends headend in root)
                    {
                        foreach (ScheduleDirect.Lineup lineup in headend.lineups)
                        {
                            lineups.Add(new NameIdPair
                            {
                                Name = string.IsNullOrWhiteSpace(lineup.name) ? lineup.lineup : lineup.name,
                                Id   = lineup.uri.Substring(18)
                            });
                        }
                    }
                }
                else
                {
                    _logger.LogInformation("No lineups available");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting headends");
            }

            return(lineups);
        }
Esempio n. 9
0
        public async Task <IEnumerable <ProgramInfo> > GetProgramsAsync(ListingsProviderInfo info, string channelNumber, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
        {
            channelNumber = NormalizeNumber(channelNumber);

            var url = "https://data.emby.media/service/listings?id=" + info.ListingsId;

            // Normalize
            startDateUtc = startDateUtc.Date;
            endDateUtc   = startDateUtc.AddDays(7);

            url += "&start=" + startDateUtc.ToString("s", CultureInfo.InvariantCulture) + "Z";
            url += "&end=" + endDateUtc.ToString("s", CultureInfo.InvariantCulture) + "Z";

            var response = await GetResponse <ListingInfo[]>(url).ConfigureAwait(false);

            return(response.Where(i => IncludeInResults(i, channelNumber)).Select(GetProgramInfo).OrderBy(i => i.StartDate));
        }
Esempio n. 10
0
        public async Task <IEnumerable <ProgramInfo> > GetProgramsAsync(ListingsProviderInfo info, string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
        {
            if (string.IsNullOrWhiteSpace(channelId))
            {
                throw new ArgumentNullException(nameof(channelId));
            }

            _logger.LogDebug("Getting xmltv programs for channel {Id}", channelId);

            string path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false);

            _logger.LogDebug("Opening XmlTvReader for {Path}", path);
            var reader = new XmlTvReader(path, GetLanguage(info));

            return(reader.GetProgrammes(channelId, startDateUtc, endDateUtc, cancellationToken)
                   .Select(p => GetProgramInfo(p, info)));
        }
Esempio n. 11
0
        public async Task <List <ChannelInfo> > GetChannels(ListingsProviderInfo info, CancellationToken cancellationToken)
        {
            // In theory this should never be called because there is always only one lineup
            var path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false);

            var reader  = new XmlTvReader(path, GetLanguage());
            var results = reader.GetChannels();

            // Should this method be async?
            return(results.Select(c => new ChannelInfo()
            {
                Id = c.Id,
                Name = c.DisplayName,
                ImageUrl = c.Icon != null && !String.IsNullOrEmpty(c.Icon.Source) ? c.Icon.Source : null,
                Number = c.Id
            }).ToList());
        }
Esempio n. 12
0
        private async Task <bool> HasLineup(ListingsProviderInfo info, CancellationToken cancellationToken)
        {
            if (string.IsNullOrWhiteSpace(info.ListingsId))
            {
                throw new ArgumentException("Listings Id required");
            }

            var token = await GetToken(info, cancellationToken);

            if (string.IsNullOrWhiteSpace(token))
            {
                throw new Exception("token required");
            }

            _logger.Info("Headends on account ");

            var options = new HttpRequestOptions()
            {
                Url                  = ApiUrl + "/lineups",
                UserAgent            = UserAgent,
                CancellationToken    = cancellationToken,
                LogErrorResponseBody = true
            };

            options.RequestHeaders["token"] = token;

            try
            {
                using (var response = await Get(options, false, null).ConfigureAwait(false))
                {
                    var root = _jsonSerializer.DeserializeFromStream <ScheduleDirect.Lineups>(response);

                    return(root.lineups.Any(i => string.Equals(info.ListingsId, i.lineup, StringComparison.OrdinalIgnoreCase)));
                }
            }
            catch (HttpException ex)
            {
                // Apparently we're supposed to swallow this
                if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.BadRequest)
                {
                    return(false);
                }

                throw;
            }
        }
Esempio n. 13
0
        public async Task <IEnumerable <ProgramInfo> > GetProgramsAsync(ListingsProviderInfo info, string channelNumber, string channelName, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
        {
            if (!await EmbyTV.EmbyTVRegistration.Instance.EnableXmlTv().ConfigureAwait(false))
            {
                var length = endDateUtc - startDateUtc;
                if (length.TotalDays > 1)
                {
                    endDateUtc = startDateUtc.AddDays(1);
                }
            }

            var path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false);

            var reader = new XmlTvReader(path, GetLanguage(), null);

            var results = reader.GetProgrammes(channelNumber, startDateUtc, endDateUtc, cancellationToken);

            return(results.Select(p => new ProgramInfo()
            {
                ChannelId = p.ChannelId,
                EndDate = GetDate(p.EndDate),
                EpisodeNumber = p.Episode == null ? null : p.Episode.Episode,
                EpisodeTitle = p.Episode == null ? null : p.Episode.Title,
                Genres = p.Categories,
                Id = String.Format("{0}_{1:O}", p.ChannelId, p.StartDate), // Construct an id from the channel and start date,
                StartDate = GetDate(p.StartDate),
                Name = p.Title,
                Overview = p.Description,
                ShortOverview = p.Description,
                ProductionYear = !p.CopyrightDate.HasValue ? (int?)null : p.CopyrightDate.Value.Year,
                SeasonNumber = p.Episode == null ? null : p.Episode.Series,
                IsSeries = p.Episode != null,
                IsRepeat = p.IsRepeat,
                IsPremiere = p.Premiere != null,
                IsKids = p.Categories.Any(c => info.KidsCategories.Contains(c, StringComparer.InvariantCultureIgnoreCase)),
                IsMovie = p.Categories.Any(c => info.MovieCategories.Contains(c, StringComparer.InvariantCultureIgnoreCase)),
                IsNews = p.Categories.Any(c => info.NewsCategories.Contains(c, StringComparer.InvariantCultureIgnoreCase)),
                IsSports = p.Categories.Any(c => info.SportsCategories.Contains(c, StringComparer.InvariantCultureIgnoreCase)),
                ImageUrl = p.Icon != null && !String.IsNullOrEmpty(p.Icon.Source) ? p.Icon.Source : null,
                HasImage = p.Icon != null && !String.IsNullOrEmpty(p.Icon.Source),
                OfficialRating = p.Rating != null && !String.IsNullOrEmpty(p.Rating.Value) ? p.Rating.Value : null,
                CommunityRating = p.StarRating.HasValue ? p.StarRating.Value : (float?)null,
                SeriesId = p.Episode != null ? p.Title.GetMD5().ToString("N") : null
            }));
        }
Esempio n. 14
0
        private async Task <List <ScheduleDirect.ShowImages> > GetImageForPrograms(
            ListingsProviderInfo info,
            List <string> programIds,
            CancellationToken cancellationToken)
        {
            if (programIds.Count == 0)
            {
                return(new List <ScheduleDirect.ShowImages>());
            }

            var imageIdString = "[";

            foreach (var i in programIds)
            {
                var imageId = i.Substring(0, 10);

                if (!imageIdString.Contains(imageId, StringComparison.Ordinal))
                {
                    imageIdString += "\"" + imageId + "\",";
                }
            }

            imageIdString = imageIdString.TrimEnd(',') + "]";

            using var message = new HttpRequestMessage(HttpMethod.Post, ApiUrl + "/metadata/programs")
                  {
                      Content = new StringContent(imageIdString, Encoding.UTF8, MediaTypeNames.Application.Json)
                  };

            try
            {
                using var innerResponse2 = await Send(message, true, info, cancellationToken).ConfigureAwait(false);

                await using var response = await innerResponse2.Content.ReadAsStreamAsync().ConfigureAwait(false);

                return(await _jsonSerializer.DeserializeFromStreamAsync <List <ScheduleDirect.ShowImages> >(
                           response).ConfigureAwait(false));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting image info from schedules direct");

                return(new List <ScheduleDirect.ShowImages>());
            }
        }
Esempio n. 15
0
        public async Task <List <ChannelInfo> > GetChannels(ListingsProviderInfo info, CancellationToken cancellationToken)
        {
            // In theory this should never be called because there is always only one lineup
            string path = await GetXml(info, cancellationToken).ConfigureAwait(false);

            _logger.LogDebug("Opening XmlTvReader for {Path}", path);
            var reader  = new XmlTvReader(path, GetLanguage(info));
            var results = reader.GetChannels();

            // Should this method be async?
            return(results.Select(c => new ChannelInfo
            {
                Id = c.Id,
                Name = c.DisplayName,
                ImageUrl = c.Icon != null && !string.IsNullOrEmpty(c.Icon.Source) ? c.Icon.Source : null,
                Number = string.IsNullOrWhiteSpace(c.Number) ? c.Id : c.Number
            }).ToList());
        }
Esempio n. 16
0
        private async Task <IReadOnlyList <ShowImagesDto> > GetImageForPrograms(
            ListingsProviderInfo info,
            IReadOnlyList <string> programIds,
            CancellationToken cancellationToken)
        {
            if (programIds.Count == 0)
            {
                return(Array.Empty <ShowImagesDto>());
            }

            StringBuilder str = new StringBuilder("[", 1 + (programIds.Count * 13));

            foreach (ReadOnlySpan <char> i in programIds)
            {
                str.Append('"')
                .Append(i.Slice(0, 10))
                .Append("\",");
            }

            // Remove last ,
            str.Length--;
            str.Append(']');

            using var message = new HttpRequestMessage(HttpMethod.Post, ApiUrl + "/metadata/programs")
                  {
                      Content = new StringContent(str.ToString(), Encoding.UTF8, MediaTypeNames.Application.Json)
                  };

            try
            {
                using var innerResponse2 = await Send(message, true, info, cancellationToken).ConfigureAwait(false);

                await using var response = await innerResponse2.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);

                return(await JsonSerializer.DeserializeAsync <IReadOnlyList <ShowImagesDto> >(response, _jsonOptions, cancellationToken).ConfigureAwait(false));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting image info from schedules direct");

                return(Array.Empty <ShowImagesDto>());
            }
        }
Esempio n. 17
0
        public async Task <IEnumerable <ProgramInfo> > GetProgramsAsync(ListingsProviderInfo info, string channelNumber, string channelName, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
        {
            if (!await EmbyTV.EmbyTVRegistration.Instance.EnableXmlTv().ConfigureAwait(false))
            {
                var length = endDateUtc - startDateUtc;
                if (length.TotalDays > 1)
                {
                    endDateUtc = startDateUtc.AddDays(1);
                }
            }

            var path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false);

            var reader = new XmlTvReader(path, GetLanguage());

            var results = reader.GetProgrammes(channelNumber, startDateUtc, endDateUtc, cancellationToken);

            return(results.Select(p => GetProgramInfo(p, info)));
        }
Esempio n. 18
0
        private async Task <bool> HasLineup(ListingsProviderInfo info, CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(info.ListingsId))
            {
                throw new ArgumentException("Listings Id required");
            }

            var token = await GetToken(info, cancellationToken).ConfigureAwait(false);

            if (string.IsNullOrEmpty(token))
            {
                throw new Exception("token required");
            }

            _logger.LogInformation("Headends on account ");

            using var options = new HttpRequestMessage(HttpMethod.Get, ApiUrl + "/lineups");
            options.Headers.TryAddWithoutValidation("token", token);

            try
            {
                using var httpResponse = await Send(options, false, null, cancellationToken).ConfigureAwait(false);

                httpResponse.EnsureSuccessStatusCode();
                await using var stream = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);

                using var response = httpResponse.Content;
                var root = await JsonSerializer.DeserializeAsync <ScheduleDirect.Lineups>(stream, _jsonOptions, cancellationToken).ConfigureAwait(false);

                return(root.lineups.Any(i => string.Equals(info.ListingsId, i.lineup, StringComparison.OrdinalIgnoreCase)));
            }
            catch (HttpRequestException ex)
            {
                // SchedulesDirect returns 400 if no lineups are configured.
                if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.BadRequest)
                {
                    return(false);
                }

                throw;
            }
        }
Esempio n. 19
0
        private ProgramInfo GetProgramInfo(XmlTvProgram p, ListingsProviderInfo info)
        {
            var episodeTitle = p.Episode == null ? null : p.Episode.Title;

            var programInfo = new ProgramInfo
            {
                ChannelId                          = p.ChannelId,
                EndDate                            = GetDate(p.EndDate),
                EpisodeNumber                      = p.Episode == null ? null : p.Episode.Episode,
                EpisodeTitle                       = episodeTitle,
                Genres                             = p.Categories,
                Id                                 = String.Format("{0}_{1:O}", p.ChannelId, p.StartDate), // Construct an id from the channel and start date,
                StartDate                          = GetDate(p.StartDate),
                Name                               = p.Title,
                Overview                           = p.Description,
                ShortOverview                      = p.Description,
                ProductionYear                     = !p.CopyrightDate.HasValue ? (int?)null : p.CopyrightDate.Value.Year,
                SeasonNumber                       = p.Episode == null ? null : p.Episode.Series,
                IsSeries                           = p.Episode != null,
                IsRepeat                           = p.IsPreviouslyShown && !p.IsNew,
                IsPremiere                         = p.Premiere != null,
                IsKids                             = p.Categories.Any(c => info.KidsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)),
                IsMovie                            = p.Categories.Any(c => info.MovieCategories.Contains(c, StringComparer.OrdinalIgnoreCase)),
                IsNews                             = p.Categories.Any(c => info.NewsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)),
                IsSports                           = p.Categories.Any(c => info.SportsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)),
                ImageUrl                           = p.Icon != null && !String.IsNullOrEmpty(p.Icon.Source) ? p.Icon.Source : null,
                HasImage                           = p.Icon != null && !String.IsNullOrEmpty(p.Icon.Source),
                OfficialRating                     = p.Rating != null && !String.IsNullOrEmpty(p.Rating.Value) ? p.Rating.Value : null,
                CommunityRating                    = p.StarRating.HasValue ? p.StarRating.Value : (float?)null,
                SeriesId                           = p.Episode != null?p.Title.GetMD5().ToString("N") : null,
                                            ShowId = ((p.Title ?? string.Empty) + (episodeTitle ?? string.Empty)).GetMD5().ToString("N")
            };

            if (programInfo.IsMovie)
            {
                programInfo.IsSeries      = false;
                programInfo.EpisodeNumber = null;
                programInfo.EpisodeTitle  = null;
            }

            return(programInfo);
        }
Esempio n. 20
0
        private async Task AddLineupToAccount(ListingsProviderInfo info, CancellationToken cancellationToken)
        {
            var token = await GetToken(info, cancellationToken).ConfigureAwait(false);

            if (string.IsNullOrEmpty(token))
            {
                throw new ArgumentException("Authentication required.");
            }

            if (string.IsNullOrEmpty(info.ListingsId))
            {
                throw new ArgumentException("Listings Id required");
            }

            _logger.LogInformation("Adding new LineUp ");

            using var options = new HttpRequestMessage(HttpMethod.Put, ApiUrl + "/lineups/" + info.ListingsId);
            options.Headers.TryAddWithoutValidation("token", token);
            using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
        }
Esempio n. 21
0
        private async Task <string> GetXml(ListingsProviderInfo info, string path, CancellationToken cancellationToken)
        {
            _logger.Info("xmltv path: {0}", path);

            if (!path.StartsWith("http", StringComparison.OrdinalIgnoreCase))
            {
                return(UnzipIfNeeded(path, path));
            }

            var cacheFilename = DateTime.UtcNow.DayOfYear.ToString(CultureInfo.InvariantCulture) + "-" + DateTime.UtcNow.Hour.ToString(CultureInfo.InvariantCulture) + ".xml";
            var cacheFile     = Path.Combine(_config.ApplicationPaths.CachePath, "xmltv", cacheFilename);

            if (_fileSystem.FileExists(cacheFile))
            {
                return(UnzipIfNeeded(path, cacheFile));
            }

            _logger.Info("Downloading xmltv listings from {0}", path);

            var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions
            {
                CancellationToken = cancellationToken,
                Url                 = path,
                Progress            = new SimpleProgress <Double>(),
                DecompressionMethod = CompressionMethod.Gzip,

                // It's going to come back gzipped regardless of this value
                // So we need to make sure the decompression method is set to gzip
                EnableHttpCompression = true,

                UserAgent = string.IsNullOrEmpty(info.UserAgent) ? "Emby/3.0" : info.UserAgent
            }).ConfigureAwait(false);

            _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFile));

            _fileSystem.CopyFile(tempFile, cacheFile, true);

            return(UnzipIfNeeded(path, cacheFile));
        }
Esempio n. 22
0
        public async Task AddMetadata(ListingsProviderInfo info, List <ChannelInfo> channels, CancellationToken cancellationToken)
        {
            // Add the channel image url
            var path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false);

            var reader  = new XmlTvReader(path, GetLanguage());
            var results = reader.GetChannels().ToList();

            if (channels != null)
            {
                foreach (var c in channels)
                {
                    var channelNumber = info.GetMappedChannel(c.Number);
                    var match         = results.FirstOrDefault(r => string.Equals(r.Id, channelNumber, StringComparison.OrdinalIgnoreCase));

                    if (match != null && match.Icon != null && !String.IsNullOrEmpty(match.Icon.Source))
                    {
                        c.ImageUrl = match.Icon.Source;
                    }
                }
            }
        }
Esempio n. 23
0
        private async Task <string> GetXml(ListingsProviderInfo info, CancellationToken cancellationToken)
        {
            _logger.LogInformation("xmltv path: {Path}", info.Path);

            if (!info.Path.StartsWith("http", StringComparison.OrdinalIgnoreCase))
            {
                return(UnzipIfNeeded(info.Path, info.Path));
            }

            string cacheFilename = info.Id + ".xml";
            string cacheFile     = Path.Combine(_config.ApplicationPaths.CachePath, "xmltv", cacheFilename);

            if (File.Exists(cacheFile) && File.GetLastWriteTimeUtc(cacheFile) >= DateTime.UtcNow.Subtract(_maxCacheAge))
            {
                return(UnzipIfNeeded(info.Path, cacheFile));
            }

            // Must check if file exists as parent directory may not exist.
            if (File.Exists(cacheFile))
            {
                File.Delete(cacheFile);
            }

            _logger.LogInformation("Downloading xmltv listings from {Path}", info.Path);

            Directory.CreateDirectory(Path.GetDirectoryName(cacheFile));

            using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(info.Path, cancellationToken).ConfigureAwait(false);

            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);

            await using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, FileOptions.Asynchronous))
            {
                await stream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
            }

            return(UnzipIfNeeded(info.Path, cacheFile));
        }
Esempio n. 24
0
        private async Task <List <ScheduleDirect.ShowImages> > GetImageForPrograms(
            ListingsProviderInfo info,
            List <string> programIds,
            CancellationToken cancellationToken)
        {
            var imageIdString = "[";

            foreach (var i in programIds)
            {
                if (!imageIdString.Contains(i.Substring(0, 10)))
                {
                    imageIdString += "\"" + i.Substring(0, 10) + "\",";
                }
            }

            imageIdString = imageIdString.TrimEnd(',') + "]";

            var httpOptions = new HttpRequestOptions()
            {
                Url                  = ApiUrl + "/metadata/programs",
                UserAgent            = UserAgent,
                CancellationToken    = cancellationToken,
                RequestContent       = imageIdString,
                LogErrorResponseBody = true,
                // The data can be large so give it some extra time
                TimeoutMs = 60000
            };
            List <ScheduleDirect.ShowImages> images;

            using (var innerResponse2 = await Post(httpOptions, true, info).ConfigureAwait(false))
            {
                images = _jsonSerializer.DeserializeFromStream <List <ScheduleDirect.ShowImages> >(
                    innerResponse2.Content);
            }

            return(images);
        }
Esempio n. 25
0
        public async Task AddMetadata(ListingsProviderInfo info, List <ChannelInfo> channels, CancellationToken cancellationToken)
        {
            var response = await GetResponse <LineupDetailResponse>("https://data.emby.media/service/lineups?id=" + info.ListingsId).ConfigureAwait(false);

            foreach (var channel in channels)
            {
                var station = response.stations.FirstOrDefault(i =>
                {
                    var itemNumber = NormalizeNumber(channel.Number);

                    if (string.Equals(itemNumber, NormalizeNumber(i.number), StringComparison.OrdinalIgnoreCase))
                    {
                        return(true);
                    }

                    var channelNumber = i.channelNumber.ToString(CultureInfo.InvariantCulture);
                    if (i.subChannelNumber > 0)
                    {
                        channelNumber += "." + i.subChannelNumber.ToString(CultureInfo.InvariantCulture);
                    }

                    return(string.Equals(channelNumber, itemNumber, StringComparison.OrdinalIgnoreCase));
                });

                if (station != null)
                {
                    //channel.Name = station.name;

                    if (!string.IsNullOrWhiteSpace(station.logoFilename))
                    {
                        channel.HasImage = true;
                        channel.ImageUrl = "http://cdn.tvpassport.com/image/station/100x100/" + station.logoFilename;
                    }
                }
            }
        }
Esempio n. 26
0
        public async Task <List <ChannelInfo> > GetChannels(ListingsProviderInfo info, CancellationToken cancellationToken)
        {
            var listingsId = info.ListingsId;

            if (string.IsNullOrWhiteSpace(listingsId))
            {
                throw new Exception("ListingsId required");
            }

            var token = await GetToken(info, cancellationToken);

            if (string.IsNullOrWhiteSpace(token))
            {
                throw new Exception("token required");
            }

            var httpOptions = new HttpRequestOptions()
            {
                Url                  = ApiUrl + "/lineups/" + listingsId,
                UserAgent            = UserAgent,
                CancellationToken    = cancellationToken,
                LogErrorResponseBody = true,
                // The data can be large so give it some extra time
                TimeoutMs = 60000
            };

            httpOptions.RequestHeaders["token"] = token;

            var list = new List <ChannelInfo>();

            using (var response = await Get(httpOptions, true, info).ConfigureAwait(false))
            {
                var root = _jsonSerializer.DeserializeFromStream <ScheduleDirect.Channel>(response);
                _logger.Info("Found " + root.map.Count + " channels on the lineup on ScheduleDirect");
                _logger.Info("Mapping Stations to Channel");

                var allStations = root.stations ?? new List <ScheduleDirect.Station>();

                foreach (ScheduleDirect.Map map in root.map)
                {
                    var channelNumber = GetChannelNumber(map);

                    var station = allStations.FirstOrDefault(item => string.Equals(item.stationID, map.stationID, StringComparison.OrdinalIgnoreCase));
                    if (station == null)
                    {
                        station = new ScheduleDirect.Station
                        {
                            stationID = map.stationID
                        };
                    }

                    var name = channelNumber;

                    var channelInfo = new ChannelInfo
                    {
                        Number = channelNumber,
                        Name   = name
                    };

                    if (station != null)
                    {
                        if (!string.IsNullOrWhiteSpace(station.name))
                        {
                            channelInfo.Name = station.name;
                        }

                        channelInfo.Id       = station.stationID;
                        channelInfo.CallSign = station.callsign;

                        if (station.logo != null)
                        {
                            channelInfo.ImageUrl = station.logo.URL;
                            channelInfo.HasImage = true;
                        }
                    }

                    list.Add(channelInfo);
                }
            }

            return(list);
        }
Esempio n. 27
0
 public Task <List <NameIdPair> > GetLineups(ListingsProviderInfo info, string country, string location)
 {
     return(GetHeadends(info, country, location, CancellationToken.None));
 }
Esempio n. 28
0
        public async Task <IEnumerable <ProgramInfo> > GetProgramsAsync(ListingsProviderInfo info, string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
        {
            if (string.IsNullOrWhiteSpace(channelId))
            {
                throw new ArgumentNullException("channelId");
            }

            // Normalize incoming input
            channelId = channelId.Replace(".json.schedulesdirect.org", string.Empty, StringComparison.OrdinalIgnoreCase).TrimStart('I');

            List <ProgramInfo> programsInfo = new List <ProgramInfo>();

            var token = await GetToken(info, cancellationToken).ConfigureAwait(false);

            if (string.IsNullOrWhiteSpace(token))
            {
                _logger.Warn("SchedulesDirect token is empty, returning empty program list");
                return(programsInfo);
            }

            if (string.IsNullOrWhiteSpace(info.ListingsId))
            {
                _logger.Warn("ListingsId is null, returning empty program list");
                return(programsInfo);
            }

            var dates = GetScheduleRequestDates(startDateUtc, endDateUtc);

            string stationID = channelId;

            _logger.Info("Channel Station ID is: " + stationID);
            List <ScheduleDirect.RequestScheduleForChannel> requestList =
                new List <ScheduleDirect.RequestScheduleForChannel>()
            {
                new ScheduleDirect.RequestScheduleForChannel()
                {
                    stationID = stationID,
                    date      = dates
                }
            };

            var requestString = _jsonSerializer.SerializeToString(requestList);

            _logger.Debug("Request string for schedules is: " + requestString);

            var httpOptions = new HttpRequestOptions()
            {
                Url               = ApiUrl + "/schedules",
                UserAgent         = UserAgent,
                CancellationToken = cancellationToken,
                // The data can be large so give it some extra time
                TimeoutMs            = 60000,
                LogErrorResponseBody = true
            };

            httpOptions.RequestHeaders["token"] = token;

            httpOptions.RequestContent = requestString;
            using (var response = await Post(httpOptions, true, info).ConfigureAwait(false))
            {
                StreamReader reader         = new StreamReader(response.Content);
                string       responseString = reader.ReadToEnd();
                var          dailySchedules = _jsonSerializer.DeserializeFromString <List <ScheduleDirect.Day> >(responseString);
                _logger.Debug("Found " + dailySchedules.Count + " programs on " + stationID + " ScheduleDirect");

                httpOptions = new HttpRequestOptions()
                {
                    Url                  = ApiUrl + "/programs",
                    UserAgent            = UserAgent,
                    CancellationToken    = cancellationToken,
                    LogErrorResponseBody = true,
                    // The data can be large so give it some extra time
                    TimeoutMs = 60000
                };

                httpOptions.RequestHeaders["token"] = token;

                List <string> programsID = new List <string>();
                programsID = dailySchedules.SelectMany(d => d.programs.Select(s => s.programID)).Distinct().ToList();
                var requestBody = "[\"" + string.Join("\", \"", programsID) + "\"]";
                httpOptions.RequestContent = requestBody;

                using (var innerResponse = await Post(httpOptions, true, info).ConfigureAwait(false))
                {
                    StreamReader innerReader = new StreamReader(innerResponse.Content);
                    responseString = innerReader.ReadToEnd();

                    var programDetails =
                        _jsonSerializer.DeserializeFromString <List <ScheduleDirect.ProgramDetails> >(
                            responseString);
                    var programDict = programDetails.ToDictionary(p => p.programID, y => y);

                    var programIdsWithImages =
                        programDetails.Where(p => p.hasImageArtwork).Select(p => p.programID)
                        .ToList();

                    var images = await GetImageForPrograms(info, programIdsWithImages, cancellationToken);

                    var schedules = dailySchedules.SelectMany(d => d.programs);
                    foreach (ScheduleDirect.Program schedule in schedules)
                    {
                        //_logger.Debug("Proccesing Schedule for statio ID " + stationID +
                        //              " which corresponds to channel " + channelNumber + " and program id " +
                        //              schedule.programID + " which says it has images? " +
                        //              programDict[schedule.programID].hasImageArtwork);

                        if (images != null)
                        {
                            var imageIndex = images.FindIndex(i => i.programID == schedule.programID.Substring(0, 10));
                            if (imageIndex > -1)
                            {
                                var programEntry = programDict[schedule.programID];

                                var data = images[imageIndex].data ?? new List <ScheduleDirect.ImageData>();
                                data = data.OrderByDescending(GetSizeOrder).ToList();

                                programEntry.primaryImage = GetProgramImage(ApiUrl, data, "Logo", true, 600);
                                //programEntry.thumbImage = GetProgramImage(ApiUrl, data, "Iconic", false);
                                //programEntry.bannerImage = GetProgramImage(ApiUrl, data, "Banner", false) ??
                                //    GetProgramImage(ApiUrl, data, "Banner-L1", false) ??
                                //    GetProgramImage(ApiUrl, data, "Banner-LO", false) ??
                                //    GetProgramImage(ApiUrl, data, "Banner-LOT", false);
                            }
                        }

                        programsInfo.Add(GetProgram(channelId, schedule, programDict[schedule.programID]));
                    }
                }
            }

            return(programsInfo);
        }
Esempio n. 29
0
        private async Task <string> GetToken(ListingsProviderInfo info, CancellationToken cancellationToken)
        {
            var username = info.Username;

            // Reset the token if there's no username
            if (string.IsNullOrWhiteSpace(username))
            {
                return(null);
            }

            var password = info.Password;

            if (string.IsNullOrWhiteSpace(password))
            {
                return(null);
            }

            // Avoid hammering SD
            if ((DateTime.UtcNow - _lastErrorResponse).TotalMinutes < 1)
            {
                return(null);
            }

            NameValuePair savedToken = null;

            if (!_tokens.TryGetValue(username, out savedToken))
            {
                savedToken = new NameValuePair();
                _tokens.TryAdd(username, savedToken);
            }

            if (!string.IsNullOrWhiteSpace(savedToken.Name) && !string.IsNullOrWhiteSpace(savedToken.Value))
            {
                long ticks;
                if (long.TryParse(savedToken.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out ticks))
                {
                    // If it's under 24 hours old we can still use it
                    if (DateTime.UtcNow.Ticks - ticks < TimeSpan.FromHours(20).Ticks)
                    {
                        return(savedToken.Name);
                    }
                }
            }

            await _tokenSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);

            try
            {
                var result = await GetTokenInternal(username, password, cancellationToken).ConfigureAwait(false);

                savedToken.Name  = result;
                savedToken.Value = DateTime.UtcNow.Ticks.ToString(CultureInfo.InvariantCulture);
                return(result);
            }
            catch (HttpException ex)
            {
                if (ex.StatusCode.HasValue)
                {
                    if ((int)ex.StatusCode.Value == 400)
                    {
                        _tokens.Clear();
                        _lastErrorResponse = DateTime.UtcNow;
                    }
                }
                throw;
            }
            finally
            {
                _tokenSemaphore.Release();
            }
        }
Esempio n. 30
0
        private ProgramInfo GetProgramInfo(XmlTvProgram p, ListingsProviderInfo info)
        {
            var episodeTitle = p.Episode == null ? null : p.Episode.Title;

            var programInfo = new ProgramInfo
            {
                ChannelId       = p.ChannelId,
                EndDate         = GetDate(p.EndDate),
                EpisodeNumber   = p.Episode == null ? null : p.Episode.Episode,
                EpisodeTitle    = episodeTitle,
                Genres          = p.Categories,
                StartDate       = GetDate(p.StartDate),
                Name            = p.Title,
                Overview        = p.Description,
                ProductionYear  = !p.CopyrightDate.HasValue ? (int?)null : p.CopyrightDate.Value.Year,
                SeasonNumber    = p.Episode == null ? null : p.Episode.Series,
                IsSeries        = p.Episode != null,
                IsRepeat        = p.IsPreviouslyShown && !p.IsNew,
                IsPremiere      = p.Premiere != null,
                IsKids          = p.Categories.Any(c => info.KidsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)),
                IsMovie         = p.Categories.Any(c => info.MovieCategories.Contains(c, StringComparer.OrdinalIgnoreCase)),
                IsNews          = p.Categories.Any(c => info.NewsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)),
                IsSports        = p.Categories.Any(c => info.SportsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)),
                ImageUrl        = p.Icon != null && !String.IsNullOrEmpty(p.Icon.Source) ? p.Icon.Source : null,
                HasImage        = p.Icon != null && !String.IsNullOrEmpty(p.Icon.Source),
                OfficialRating  = p.Rating != null && !String.IsNullOrEmpty(p.Rating.Value) ? p.Rating.Value : null,
                CommunityRating = p.StarRating.HasValue ? p.StarRating.Value : (float?)null,
                SeriesId        = p.Episode != null?p.Title.GetMD5().ToString("N") : null
            };

            if (!string.IsNullOrWhiteSpace(p.ProgramId))
            {
                programInfo.ShowId = p.ProgramId;
            }
            else
            {
                var uniqueString = (p.Title ?? string.Empty) + (episodeTitle ?? string.Empty) + (p.IceTvEpisodeNumber ?? string.Empty);

                if (programInfo.SeasonNumber.HasValue)
                {
                    uniqueString = "-" + programInfo.SeasonNumber.Value.ToString(CultureInfo.InvariantCulture);
                }
                if (programInfo.EpisodeNumber.HasValue)
                {
                    uniqueString = "-" + programInfo.EpisodeNumber.Value.ToString(CultureInfo.InvariantCulture);
                }

                programInfo.ShowId = uniqueString.GetMD5().ToString("N");

                // If we don't have valid episode info, assume it's a unique program, otherwise recordings might be skipped
                if (programInfo.IsSeries && !programInfo.IsRepeat)
                {
                    if ((programInfo.EpisodeNumber ?? 0) == 0)
                    {
                        programInfo.ShowId = programInfo.ShowId + programInfo.StartDate.Ticks.ToString(CultureInfo.InvariantCulture);
                    }
                }
            }

            // Construct an id from the channel and start date
            programInfo.Id = String.Format("{0}_{1:O}", p.ChannelId, p.StartDate);

            if (programInfo.IsMovie)
            {
                programInfo.IsSeries      = false;
                programInfo.EpisodeNumber = null;
                programInfo.EpisodeTitle  = null;
            }

            return(programInfo);
        }