예제 #1
0
 public Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings)
 {
     return GetListingsProvider(info.Country).Validate(info, validateLogin, validateListings);
 }
예제 #2
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;
            }
        }
예제 #3
0
 public Task<List<NameIdPair>> GetLineups(ListingsProviderInfo info, string country, string location)
 {
     return GetHeadends(info, country, location, CancellationToken.None);
 }
예제 #4
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();
            }
        }
예제 #5
0
        private async Task<Stream> Get(HttpRequestOptions options,
            bool enableRetry,
            ListingsProviderInfo providerInfo)
        {
            try
            {
                return await _httpClient.Get(options).ConfigureAwait(false);
            }
            catch (HttpException ex)
            {
                _tokens.Clear();

                if (!ex.StatusCode.HasValue || (int)ex.StatusCode.Value >= 500)
                {
                    enableRetry = false;
                }

                if (!enableRetry)
                {
                    throw;
                }
            }

            var newToken = await GetToken(providerInfo, options.CancellationToken).ConfigureAwait(false);
            options.RequestHeaders["token"] = newToken;
            return await Get(options, false, providerInfo).ConfigureAwait(false);
        }
예제 #6
0
        public async Task<ListingsProviderInfo> SaveListingProvider(ListingsProviderInfo info, bool validateLogin, bool validateListings)
        {
            info = (ListingsProviderInfo)_jsonSerializer.DeserializeFromString(_jsonSerializer.SerializeToString(info), typeof(ListingsProviderInfo));

            var provider = _listingProviders.FirstOrDefault(i => string.Equals(info.Type, i.Type, StringComparison.OrdinalIgnoreCase));

            if (provider == null)
            {
                throw new ResourceNotFoundException();
            }

            await provider.Validate(info, validateLogin, validateListings).ConfigureAwait(false);

            var config = GetConfiguration();

            var index = config.ListingProviders.FindIndex(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase));

            if (index == -1 || string.IsNullOrWhiteSpace(info.Id))
            {
                info.Id = Guid.NewGuid().ToString("N");
                config.ListingProviders.Add(info);
            }
            else
            {
                config.ListingProviders[index] = info;
            }

            _config.SaveConfiguration("livetv", config);

            _taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>();

            return info;
        }
예제 #7
0
        private async Task<List<ScheduleDirect.ShowImages>> GetImageForPrograms(
            ListingsProviderInfo info,
            List<string> programIds,
           CancellationToken cancellationToken)
        {
            var imageIdString = "[";

            programIds.ForEach(i =>
            {
                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;
        }
예제 #8
0
파일: XmlTv.cs 프로젝트: rezafouladian/Emby
 public async Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings)
 {
     // Check that the path or url is valid. If not, throw a file not found exception
 }
예제 #9
0
파일: XmlTv.cs 프로젝트: rezafouladian/Emby
 public Task<List<NameIdPair>> GetLineups(ListingsProviderInfo info, string country, string location)
 {
     // In theory this should never be called because there is always only one lineup
     throw new NotImplementedException();
 }
예제 #10
0
파일: XmlTv.cs 프로젝트: rezafouladian/Emby
 public Task<IEnumerable<ProgramInfo>> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, string channelName, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
 {
     throw new NotImplementedException();
 }
예제 #11
0
파일: XmlTv.cs 프로젝트: rezafouladian/Emby
 public async Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels, CancellationToken cancellationToken)
 {
     // Might not be needed
 }
예제 #12
0
        private ProgramInfo GetProgramInfo(XmlTvProgram p, ListingsProviderInfo info)
        {
            var programInfo = 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
            };

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

            return programInfo;
        }
예제 #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 => GetProgramInfo(p, info));
        }
예제 #14
0
 public Task<List<NameIdPair>> GetLineups(ListingsProviderInfo info, string country, string location)
 {
     return GetListingsProvider(country).GetLineups(country, location);
 }
예제 #15
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(), null);
            var results = reader.GetChannels();

            // Should this method be async?
            return results.Select(c => new NameIdPair() { Id = c.Id, Name = c.DisplayName }).ToList();
        }
예제 #16
0
파일: EmbyTV.cs 프로젝트: softworkz/Emby
        public async Task<List<ChannelInfo>> GetChannelsForListingsProvider(ListingsProviderInfo listingsProvider, CancellationToken cancellationToken)
        {
            var list = new List<ChannelInfo>();

            foreach (var hostInstance in _liveTvManager.TunerHosts)
            {
                try
                {
                    var channels = await hostInstance.GetChannels(cancellationToken).ConfigureAwait(false);

                    list.AddRange(channels);
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error getting channels", ex);
                }
            }

            return list
                .Where(i => IsListingProviderEnabledForTuner(listingsProvider, i.TunerHostId))
                .ToList();
        }
예제 #17
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(), null);
            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();
        }
예제 #18
0
파일: EmbyTV.cs 프로젝트: softworkz/Emby
        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);
        }
예제 #19
0
        public async Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels,
            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");
            }

            ClearPairCache(listingsId);

            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;

            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");
                foreach (ScheduleDirect.Map map in root.map)
                {
                    var channelNumber = map.logicalChannelNumber;

                    if (string.IsNullOrWhiteSpace(channelNumber))
                    {
                        channelNumber = map.channel;
                    }
                    if (string.IsNullOrWhiteSpace(channelNumber))
                    {
                        channelNumber = map.atscMajor + "." + map.atscMinor;
                    }
                    channelNumber = channelNumber.TrimStart('0');

                    _logger.Debug("Found channel: " + channelNumber + " in Schedules Direct");
                    var schChannel = root.stations.FirstOrDefault(item => item.stationID == map.stationID);

                    AddToChannelPairCache(listingsId, channelNumber, schChannel);
                }
                _logger.Info("Added " + GetChannelPairCacheCount(listingsId) + " channels to the dictionary");

                foreach (ChannelInfo channel in channels)
                {
                    var station = GetStation(listingsId, channel.Number, channel.Name);

                    if (station != null)
                    {
                        if (station.logo != null)
                        {
                            channel.ImageUrl = station.logo.URL;
                            channel.HasImage = true;
                        }
                        string channelName = station.name;
                        channel.Name = channelName;
                    }
                    else
                    {
                        _logger.Info("Schedules Direct doesnt have data for channel: " + channel.Number + " " + channel.Name);
                    }
                }
            }
        }
예제 #20
0
파일: EmbyTV.cs 프로젝트: softworkz/Emby
        private Dictionary<string, string> GetChannelMappings(ListingsProviderInfo info)
        {
            var dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

            foreach (var mapping in info.ChannelMappings)
            {
                dict[mapping.Name] = mapping.Value;
            }

            return dict;
        }
예제 #21
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;
        }
예제 #22
0
        public async Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels,
            CancellationToken cancellationToken)
        {
            if (string.IsNullOrWhiteSpace(info.ListingsId))
            {
                throw new Exception("ListingsId required");
            }

            var token = await GetToken(info, cancellationToken);

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

            _channelPair.Clear();

            var httpOptions = new HttpRequestOptions()
            {
                Url = ApiUrl + "/lineups/" + info.ListingsId,
                UserAgent = UserAgent,
                CancellationToken = cancellationToken
            };

            httpOptions.RequestHeaders["token"] = token;

            using (var response = await _httpClient.Get(httpOptions))
            {
                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");
                foreach (ScheduleDirect.Map map in root.map)
                {
                    var channel = (map.channel ?? (map.atscMajor + "." + map.atscMinor)).TrimStart('0');
                    _logger.Debug("Found channel: " + channel + " in Schedules Direct");
                    var schChannel = root.stations.FirstOrDefault(item => item.stationID == map.stationID);

                    if (!_channelPair.ContainsKey(channel) && channel != "0.0" && schChannel != null)
                    {
                        _channelPair.TryAdd(channel, schChannel);
                    }
                }
                _logger.Info("Added " + _channelPair.Count() + " channels to the dictionary");

                foreach (ChannelInfo channel in channels)
                {
                    //  Helper.logger.Info("Modifyin channel " + channel.Number);
                    if (_channelPair.ContainsKey(channel.Number))
                    {
                        string channelName;
                        if (_channelPair[channel.Number].logo != null)
                        {
                            channel.ImageUrl = _channelPair[channel.Number].logo.URL;
                            channel.HasImage = true;
                        }
                        if (_channelPair[channel.Number].affiliate != null)
                        {
                            channelName = _channelPair[channel.Number].affiliate;
                        }
                        else
                        {
                            channelName = _channelPair[channel.Number].name;
                        }
                        channel.Name = channelName;
                    }
                    else
                    {
                        _logger.Info("Schedules Direct doesnt have data for channel: " + channel.Number + " " +
                                     channel.Name);
                    }
                }
            }
        }
예제 #23
0
        public async Task<IEnumerable<ProgramInfo>> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, string channelName, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
        {
            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);

            ScheduleDirect.Station station = GetStation(info.ListingsId, channelNumber, channelName);

            if (station == null)
            {
                _logger.Info("No Schedules Direct Station found for channel {0} with name {1}", channelNumber, channelName);
                return programsInfo;
            }

            string stationID = station.stationID;

            _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 " + channelNumber + " 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 images = await GetImageForPrograms(info, programDetails.Where(p => p.hasImageArtwork).Select(p => p.programID).ToList(), 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)
                            {
                                programDict[schedule.programID].images = GetProgramLogo(ApiUrl, images[imageIndex]);
                            }
                        }

                        programsInfo.Add(GetProgram(channelNumber, schedule, programDict[schedule.programID]));
                    }
                    _logger.Info("Finished with EPGData");
                }
            }

            return programsInfo;
        }
예제 #24
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
            });
        }
예제 #25
0
        private async Task AddLineupToAccount(ListingsProviderInfo info, CancellationToken cancellationToken)
        {
            var token = await GetToken(info, cancellationToken);

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

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

            _logger.Info("Adding new LineUp ");

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

            httpOptions.RequestHeaders["token"] = token;

            using (var response = await _httpClient.SendAsync(httpOptions, "PUT"))
            {
            }
        }
예제 #26
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(), null);
            var results = reader.GetChannels().ToList();

            if (channels != null)
            {
                channels.ForEach(c =>
                {
                    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;
                    }
                });
            }
        }
예제 #27
0
        public async Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings)
        {
            if (validateLogin)
            {
                if (string.IsNullOrWhiteSpace(info.Username))
                {
                    throw new ArgumentException("Username is required");
                }
                if (string.IsNullOrWhiteSpace(info.Password))
                {
                    throw new ArgumentException("Password is required");
                }
            }
            if (validateListings)
            {
                if (string.IsNullOrWhiteSpace(info.ListingsId))
                {
                    throw new ArgumentException("Listings Id required");
                }

                var hasLineup = await HasLineup(info, CancellationToken.None).ConfigureAwait(false);

                if (!hasLineup)
                {
                    await AddLineupToAccount(info, CancellationToken.None).ConfigureAwait(false);
                }
            }
        }
예제 #28
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) && !File.Exists(info.Path))
            {
                throw new FileNotFoundException("Could not find the XmlTv file specified:", info.Path);
            }

            return Task.FromResult(true);
        }
예제 #29
0
        public async Task<List<ChannelInfo>> GetChannels(ListingsProviderInfo info, CancellationToken cancellationToken)
        {
            var listingsId = info.ListingsId;
            if (string.IsNullOrWhiteSpace(listingsId))
            {
                throw new Exception("ListingsId required");
            }

            await AddMetadata(info, new List<ChannelInfo>(), cancellationToken).ConfigureAwait(false);

            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");
                foreach (ScheduleDirect.Map map in root.map)
                {
                    var channelNumber = map.logicalChannelNumber;

                    if (string.IsNullOrWhiteSpace(channelNumber))
                    {
                        channelNumber = map.channel;
                    }
                    if (string.IsNullOrWhiteSpace(channelNumber))
                    {
                        channelNumber = map.atscMajor + "." + map.atscMinor;
                    }
                    channelNumber = channelNumber.TrimStart('0');

                    var name = channelNumber;
                    var station = GetStation(listingsId, channelNumber, null);

                    if (station != null)
                    {
                        name = station.name;
                    }

                    list.Add(new ChannelInfo
                    {
                        Number = channelNumber,
                        Name = name
                    });
                }
            }

            return list;
        }
예제 #30
0
 public Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels, CancellationToken cancellationToken)
 {
     return GetListingsProvider(info.Country).AddMetadata(info, channels, cancellationToken);
 }