Bläddra i källkod

Merge pull request #286 from Bond-009/cleanup

Clean up HttpClientManager, LiveTvManager and InstallationManager
Joshua M. Boniface 6 år sedan
förälder
incheckning
89a3db9346

+ 5 - 4
Emby.Server.Implementations/ApplicationHost.cs

@@ -640,15 +640,14 @@ namespace Emby.Server.Implementations
         /// Gets the exports.
         /// </summary>
         /// <typeparam name="T"></typeparam>
-        /// <param name="manageLiftime">if set to <c>true</c> [manage liftime].</param>
+        /// <param name="manageLifetime">if set to <c>true</c> [manage lifetime].</param>
         /// <returns>IEnumerable{``0}.</returns>
         public IEnumerable<T> GetExports<T>(bool manageLifetime = true)
         {
             var parts = GetExportTypes<T>()
                 .Select(CreateInstanceSafe)
                 .Where(i => i != null)
-                .Cast<T>()
-                .ToList();
+                .Cast<T>();
 
             if (manageLifetime)
             {
@@ -703,7 +702,7 @@ namespace Emby.Server.Implementations
         /// <summary>
         /// Runs the startup tasks.
         /// </summary>
-        public async Task RunStartupTasks()
+        public Task RunStartupTasks()
         {
             Resolve<ITaskManager>().AddTasks(GetExports<IScheduledTask>(false));
 
@@ -736,6 +735,8 @@ namespace Emby.Server.Implementations
             Logger.LogInformation("All entry points have started");
 
             //LoggerFactory.RemoveConsoleOutput();
+
+            return Task.CompletedTask;
         }
 
         private void RunEntryPoints(IEnumerable<IServerEntryPoint> entryPoints, bool isBeforeStartup)

+ 52 - 93
Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs

@@ -5,18 +5,16 @@ using System.Globalization;
 using System.IO;
 using System.Linq;
 using System.Net;
-using System.Net.Sockets;
+using System.Net.Cache;
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
-using Emby.Server.Implementations.IO;
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Model.IO;
 using Microsoft.Extensions.Logging;
 using MediaBrowser.Model.Net;
-using MediaBrowser.Controller.IO;
 
 namespace Emby.Server.Implementations.HttpClientManager
 {
@@ -125,59 +123,38 @@ namespace Emby.Server.Implementations.HttpClientManager
 
         private WebRequest GetRequest(HttpRequestOptions options, string method)
         {
-            var url = options.Url;
+            string url = options.Url;
 
-            var uriAddress = new Uri(url);
-            var userInfo = uriAddress.UserInfo;
+            Uri uriAddress = new Uri(url);
+            string userInfo = uriAddress.UserInfo;
             if (!string.IsNullOrWhiteSpace(userInfo))
             {
                 _logger.LogInformation("Found userInfo in url: {0} ... url: {1}", userInfo, url);
                 url = url.Replace(userInfo + "@", string.Empty);
             }
 
-            var request = CreateWebRequest(url);
-            var httpWebRequest = request as HttpWebRequest;
+            WebRequest request = CreateWebRequest(url);
 
-            if (httpWebRequest != null)
+            if (request is HttpWebRequest httpWebRequest)
             {
                 AddRequestHeaders(httpWebRequest, options);
 
                 if (options.EnableHttpCompression)
                 {
-                    if (options.DecompressionMethod.HasValue)
-                    {
-                        httpWebRequest.AutomaticDecompression = options.DecompressionMethod.Value == CompressionMethod.Gzip
-                            ? DecompressionMethods.GZip
-                            : DecompressionMethods.Deflate;
-                    }
-                    else
+                    httpWebRequest.AutomaticDecompression = DecompressionMethods.Deflate;
+                    if (options.DecompressionMethod.HasValue
+                        && options.DecompressionMethod.Value == CompressionMethod.Gzip)
                     {
-                        httpWebRequest.AutomaticDecompression = DecompressionMethods.Deflate;
+                        httpWebRequest.AutomaticDecompression = DecompressionMethods.GZip;
                     }
                 }
                 else
                 {
                     httpWebRequest.AutomaticDecompression = DecompressionMethods.None;
                 }
-            }
-
-
-
-            request.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.BypassCache);
-
-            if (httpWebRequest != null)
-            {
-                if (options.EnableKeepAlive)
-                {
-                    httpWebRequest.KeepAlive = true;
-                }
-            }
 
-            request.Method = method;
-            request.Timeout = options.TimeoutMs;
+                httpWebRequest.KeepAlive = options.EnableKeepAlive;
 
-            if (httpWebRequest != null)
-            {
                 if (!string.IsNullOrEmpty(options.Host))
                 {
                     httpWebRequest.Host = options.Host;
@@ -189,6 +166,11 @@ namespace Emby.Server.Implementations.HttpClientManager
                 }
             }
 
+            request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
+
+            request.Method = method;
+            request.Timeout = options.TimeoutMs;
+
             if (!string.IsNullOrWhiteSpace(userInfo))
             {
                 var parts = userInfo.Split(':');
@@ -215,7 +197,7 @@ namespace Emby.Server.Implementations.HttpClientManager
         {
             var hasUserAgent = false;
 
-            foreach (var header in options.RequestHeaders.ToList())
+            foreach (var header in options.RequestHeaders)
             {
                 if (string.Equals(header.Key, "Accept", StringComparison.OrdinalIgnoreCase))
                 {
@@ -379,10 +361,7 @@ namespace Emby.Server.Implementations.HttpClientManager
             {
                 try
                 {
-                    // TODO: We can always put this in the options object if needed
-                    var requestEncoding = Encoding.UTF8;
-
-                    var bytes = options.RequestContentBytes ?? requestEncoding.GetBytes(options.RequestContent ?? string.Empty);
+                    var bytes = options.RequestContentBytes ?? Encoding.UTF8.GetBytes(options.RequestContent ?? string.Empty);
 
                     var contentType = options.RequestContentType ?? "application/x-www-form-urlencoded";
 
@@ -392,7 +371,6 @@ namespace Emby.Server.Implementations.HttpClientManager
                     }
 
                     httpWebRequest.ContentType = contentType;
-
                     httpWebRequest.ContentLength = bytes.Length;
                     (await httpWebRequest.GetRequestStreamAsync().ConfigureAwait(false)).Write(bytes, 0, bytes.Length);
                 }
@@ -409,10 +387,7 @@ namespace Emby.Server.Implementations.HttpClientManager
 
             if ((DateTime.UtcNow - client.LastTimeout).TotalSeconds < TimeoutSeconds)
             {
-                if (options.ResourcePool != null)
-                {
-                    options.ResourcePool.Release();
-                }
+                options.ResourcePool?.Release();
 
                 throw new HttpException(string.Format("Connection to {0} timed out", options.Url)) { IsTimedOut = true };
             }
@@ -457,7 +432,6 @@ namespace Emby.Server.Implementations.HttpClientManager
                     using (var stream = httpResponse.GetResponseStream())
                     {
                         var memoryStream = new MemoryStream();
-
                         await stream.CopyToAsync(memoryStream).ConfigureAwait(false);
 
                         memoryStream.Position = 0;
@@ -476,10 +450,7 @@ namespace Emby.Server.Implementations.HttpClientManager
             }
             finally
             {
-                if (options.ResourcePool != null)
-                {
-                    options.ResourcePool.Release();
-                }
+                options.ResourcePool?.Release();
             }
         }
 
@@ -488,13 +459,9 @@ namespace Emby.Server.Implementations.HttpClientManager
             var responseInfo = new HttpResponseInfo(disposable)
             {
                 Content = content,
-
                 StatusCode = httpResponse.StatusCode,
-
                 ContentType = httpResponse.ContentType,
-
                 ContentLength = contentLength,
-
                 ResponseUrl = httpResponse.ResponseUri.ToString()
             };
 
@@ -511,11 +478,8 @@ namespace Emby.Server.Implementations.HttpClientManager
             var responseInfo = new HttpResponseInfo
             {
                 TempFilePath = tempFile,
-
                 StatusCode = httpResponse.StatusCode,
-
                 ContentType = httpResponse.ContentType,
-
                 ContentLength = contentLength
             };
 
@@ -619,22 +583,20 @@ namespace Emby.Server.Implementations.HttpClientManager
 
                     var contentLength = GetContentLength(httpResponse);
 
-                    if (!contentLength.HasValue)
+                    if (contentLength.HasValue)
                     {
-                        // We're not able to track progress
-                        using (var stream = httpResponse.GetResponseStream())
+                        using (var fs = _fileSystem.GetFileStream(tempFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
                         {
-                            using (var fs = _fileSystem.GetFileStream(tempFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
-                            {
-                                await stream.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, options.CancellationToken).ConfigureAwait(false);
-                            }
+                            await httpResponse.GetResponseStream().CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, options.CancellationToken).ConfigureAwait(false);
                         }
                     }
                     else
                     {
+                        // We're not able to track progress
+                        using (var stream = httpResponse.GetResponseStream())
                         using (var fs = _fileSystem.GetFileStream(tempFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
                         {
-                            await httpResponse.GetResponseStream().CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, options.CancellationToken).ConfigureAwait(false);
+                            await stream.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, options.CancellationToken).ConfigureAwait(false);
                         }
                     }
 
@@ -650,10 +612,7 @@ namespace Emby.Server.Implementations.HttpClientManager
             }
             finally
             {
-                if (options.ResourcePool != null)
-                {
-                    options.ResourcePool.Release();
-                }
+                options.ResourcePool?.Release();
             }
         }
 
@@ -810,35 +769,38 @@ namespace Emby.Server.Implementations.HttpClientManager
 
             var isSuccessful = statusCode >= HttpStatusCode.OK && statusCode <= (HttpStatusCode)299;
 
-            if (!isSuccessful)
+            if (isSuccessful)
             {
-                if (options.LogErrorResponseBody)
+                return;
+            }
+
+            if (options.LogErrorResponseBody)
+            {
+                try
                 {
-                    try
+                    using (var stream = response.GetResponseStream())
                     {
-                        using (var stream = response.GetResponseStream())
+                        if (stream != null)
                         {
-                            if (stream != null)
+                            using (var reader = new StreamReader(stream))
                             {
-                                using (var reader = new StreamReader(stream))
-                                {
-                                    var msg = reader.ReadToEnd();
+                                var msg = reader.ReadToEnd();
 
-                                    _logger.LogError(msg);
-                                }
+                                _logger.LogError(msg);
                             }
                         }
                     }
-                    catch
-                    {
-
-                    }
                 }
-                throw new HttpException(response.StatusDescription)
+                catch
                 {
-                    StatusCode = response.StatusCode
-                };
+
+                }
             }
+
+            throw new HttpException(response.StatusDescription)
+            {
+                StatusCode = response.StatusCode
+            };
         }
 
         private Task<WebResponse> GetResponseAsync(WebRequest request, TimeSpan timeout)
@@ -859,13 +821,10 @@ namespace Emby.Server.Implementations.HttpClientManager
 
         private static void TimeoutCallback(object state, bool timedOut)
         {
-            if (timedOut)
+            if (timedOut && state != null)
             {
                 WebRequest request = (WebRequest)state;
-                if (state != null)
-                {
-                    request.Abort();
-                }
+                request.Abort();
             }
         }
 
@@ -880,13 +839,13 @@ namespace Emby.Server.Implementations.HttpClientManager
 
             public void OnError(Task<WebResponse> task)
             {
-                if (task.Exception != null)
+                if (task.Exception == null)
                 {
-                    taskCompletion.TrySetException(task.Exception);
+                    taskCompletion.TrySetException(Enumerable.Empty<Exception>());
                 }
                 else
                 {
-                    taskCompletion.TrySetException(new List<Exception>());
+                    taskCompletion.TrySetException(task.Exception);
                 }
             }
         }

+ 79 - 117
Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs

@@ -16,8 +16,6 @@ using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 using MediaBrowser.Model.Extensions;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Providers;
 using MediaBrowser.Model.Entities;
 
 namespace Emby.Server.Implementations.LiveTv.Listings
@@ -32,9 +30,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings
 
         private const string ApiUrl = "https://json.schedulesdirect.org/20141201";
 
-        private readonly Dictionary<string, Dictionary<string, ScheduleDirect.Station>> _channelPairingCache =
-            new Dictionary<string, Dictionary<string, ScheduleDirect.Station>>(StringComparer.OrdinalIgnoreCase);
-
         public SchedulesDirect(ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IApplicationHost appHost)
         {
             _logger = logger;
@@ -74,33 +69,29 @@ namespace Emby.Server.Implementations.LiveTv.Listings
             // 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.IsNullOrEmpty(token))
             {
                 _logger.LogWarning("SchedulesDirect token is empty, returning empty program list");
-                return programsInfo;
+
+                return Enumerable.Empty<ProgramInfo>();
             }
 
             var dates = GetScheduleRequestDates(startDateUtc, endDateUtc);
 
-            string stationID = channelId;
-
-            _logger.LogInformation("Channel Station ID is: " + stationID);
-            List<ScheduleDirect.RequestScheduleForChannel> requestList =
-                new List<ScheduleDirect.RequestScheduleForChannel>()
+            _logger.LogInformation("Channel Station ID is: {ChannelID}", channelId);
+            var requestList = new List<ScheduleDirect.RequestScheduleForChannel>()
+                {
+                    new ScheduleDirect.RequestScheduleForChannel()
                     {
-                        new ScheduleDirect.RequestScheduleForChannel()
-                        {
-                            stationID = stationID,
-                            date = dates
-                        }
-                    };
+                        stationID = channelId,
+                        date = dates
+                    }
+                };
 
             var requestString = _jsonSerializer.SerializeToString(requestList);
-            _logger.LogDebug("Request string for schedules is: " + requestString);
+            _logger.LogDebug("Request string for schedules is: {RequestString}", requestString);
 
             var httpOptions = new HttpRequestOptions()
             {
@@ -109,16 +100,17 @@ namespace Emby.Server.Implementations.LiveTv.Listings
                 CancellationToken = cancellationToken,
                 // The data can be large so give it some extra time
                 TimeoutMs = 60000,
-                LogErrorResponseBody = true
+                LogErrorResponseBody = true,
+                RequestContent = requestString
             };
 
             httpOptions.RequestHeaders["token"] = token;
 
-            httpOptions.RequestContent = requestString;
             using (var response = await Post(httpOptions, true, info).ConfigureAwait(false))
+            using (StreamReader reader = new StreamReader(response.Content))
             {
                 var dailySchedules = await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.Day>>(response.Content).ConfigureAwait(false);
-                _logger.LogDebug("Found {ScheduleCount} programs on {StationID} ScheduleDirect", dailySchedules.Count, stationID);
+                _logger.LogDebug("Found {ScheduleCount} programs on {ChannelID} ScheduleDirect", dailySchedules.Count, channelId);
 
                 httpOptions = new HttpRequestOptions()
                 {
@@ -132,14 +124,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings
 
                 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;
-
-                double wideAspect = 1.77777778;
+                var programsID = dailySchedules.SelectMany(d => d.programs.Select(s => s.programID)).Distinct();
+                httpOptions.RequestContent = "[\"" + string.Join("\", \"", programsID) + "\"]";
 
                 using (var innerResponse = await Post(httpOptions, true, info).ConfigureAwait(false))
+                using (StreamReader innerReader = new StreamReader(innerResponse.Content))
                 {
                     var programDetails = await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.ProgramDetails>>(innerResponse.Content).ConfigureAwait(false);
                     var programDict = programDetails.ToDictionary(p => p.programID, y => y);
@@ -150,8 +139,8 @@ namespace Emby.Server.Implementations.LiveTv.Listings
 
                     var images = await GetImageForPrograms(info, programIdsWithImages, cancellationToken).ConfigureAwait(false);
 
-                    var schedules = dailySchedules.SelectMany(d => d.programs);
-                    foreach (ScheduleDirect.Program schedule in schedules)
+                    List<ProgramInfo> programsInfo = new List<ProgramInfo>();
+                    foreach (ScheduleDirect.Program schedule in dailySchedules.SelectMany(d => d.programs))
                     {
                         //_logger.LogDebug("Proccesing Schedule for statio ID " + stationID +
                         //              " which corresponds to channel " + channelNumber + " and program id " +
@@ -165,15 +154,17 @@ namespace Emby.Server.Implementations.LiveTv.Listings
                             {
                                 var programEntry = programDict[schedule.programID];
 
-                                var allImages = (images[imageIndex].data ?? new List<ScheduleDirect.ImageData>()).ToList();
-                                var imagesWithText = allImages.Where(i => string.Equals(i.text, "yes", StringComparison.OrdinalIgnoreCase)).ToList();
-                                var imagesWithoutText = allImages.Where(i => string.Equals(i.text, "no", StringComparison.OrdinalIgnoreCase)).ToList();
+                                var allImages = images[imageIndex].data ?? new List<ScheduleDirect.ImageData>();
+                                var imagesWithText = allImages.Where(i => string.Equals(i.text, "yes", StringComparison.OrdinalIgnoreCase));
+                                var imagesWithoutText = allImages.Where(i => string.Equals(i.text, "no", StringComparison.OrdinalIgnoreCase));
 
-                                double desiredAspect = 0.666666667;
+                                const double desiredAspect = 0.666666667;
 
                                 programEntry.primaryImage = GetProgramImage(ApiUrl, imagesWithText, true, desiredAspect) ??
                                     GetProgramImage(ApiUrl, allImages, true, desiredAspect);
 
+                                const double wideAspect = 1.77777778;
+
                                 programEntry.thumbImage = GetProgramImage(ApiUrl, imagesWithText, true, wideAspect);
 
                                 // Don't supply the same image twice
@@ -193,18 +184,16 @@ namespace Emby.Server.Implementations.LiveTv.Listings
 
                         programsInfo.Add(GetProgram(channelId, schedule, programDict[schedule.programID]));
                     }
+                    return programsInfo;
                 }
             }
-
-            return programsInfo;
         }
 
         private int GetSizeOrder(ScheduleDirect.ImageData image)
         {
             if (!string.IsNullOrWhiteSpace(image.height))
             {
-                int value;
-                if (int.TryParse(image.height, out value))
+                if (int.TryParse(image.height, out int value))
                 {
                     return value;
                 }
@@ -225,9 +214,8 @@ namespace Emby.Server.Implementations.LiveTv.Listings
             {
                 channelNumber = map.atscMajor + "." + map.atscMinor;
             }
-            channelNumber = channelNumber.TrimStart('0');
 
-            return channelNumber;
+            return channelNumber.TrimStart('0');
         }
 
         private bool IsMovie(ScheduleDirect.ProgramDetails programInfo)
@@ -382,8 +370,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
 
             if (details.movie != null)
             {
-                int year;
-                if (!string.IsNullOrEmpty(details.movie.year) && int.TryParse(details.movie.year, out year))
+                if (!string.IsNullOrEmpty(details.movie.year) && int.TryParse(details.movie.year, out int year))
                 {
                     info.ProductionYear = year;
                 }
@@ -414,18 +401,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings
             return date;
         }
 
-        private string GetProgramImage(string apiUrl, List<ScheduleDirect.ImageData> images, bool returnDefaultImage, double desiredAspect)
+        private string GetProgramImage(string apiUrl, IEnumerable<ScheduleDirect.ImageData> images, bool returnDefaultImage, double desiredAspect)
         {
-            string url = null;
-
-            var matches = images;
-
-            matches = matches
-                .OrderBy(i => Math.Abs(desiredAspect - GetApsectRatio(i)))
+            var match = images
+                .OrderBy(i => Math.Abs(desiredAspect - GetAspectRatio(i)))
                 .ThenByDescending(GetSizeOrder)
-                .ToList();
-
-            var match = matches.FirstOrDefault();
+                .FirstOrDefault();
 
             if (match == null)
             {
@@ -434,22 +415,21 @@ namespace Emby.Server.Implementations.LiveTv.Listings
 
             var uri = match.uri;
 
-            if (!string.IsNullOrWhiteSpace(uri))
+            if (string.IsNullOrWhiteSpace(uri))
             {
-                if (uri.IndexOf("http", StringComparison.OrdinalIgnoreCase) != -1)
-                {
-                    url = uri;
-                }
-                else
-                {
-                    url = apiUrl + "/image/" + uri;
-                }
+                return null;
+            }
+            else if (uri.IndexOf("http", StringComparison.OrdinalIgnoreCase) != -1)
+            {
+                return uri;
+            }
+            else
+            {
+                return apiUrl + "/image/" + uri;
             }
-            //_logger.LogDebug("URL for image is : " + url);
-            return url;
         }
 
-        private double GetApsectRatio(ScheduleDirect.ImageData i)
+        private double GetAspectRatio(ScheduleDirect.ImageData i)
         {
             int width = 0;
             int height = 0;
@@ -614,8 +594,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
 
             if (!string.IsNullOrEmpty(savedToken.Name) && !string.IsNullOrEmpty(savedToken.Value))
             {
-                long ticks;
-                if (long.TryParse(savedToken.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out ticks))
+                if (long.TryParse(savedToken.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out long ticks))
                 {
                     // If it's under 24 hours old we can still use it
                     if (DateTime.UtcNow.Ticks - ticks < TimeSpan.FromHours(20).Ticks)
@@ -685,8 +664,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
                 }
             }
 
-            var newToken = await GetToken(providerInfo, options.CancellationToken).ConfigureAwait(false);
-            options.RequestHeaders["token"] = newToken;
+            options.RequestHeaders["token"] = await GetToken(providerInfo, options.CancellationToken).ConfigureAwait(false);;
             return await Post(options, false, providerInfo).ConfigureAwait(false);
         }
 
@@ -724,8 +702,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
                 }
             }
 
-            var newToken = await GetToken(providerInfo, options.CancellationToken).ConfigureAwait(false);
-            options.RequestHeaders["token"] = newToken;
+            options.RequestHeaders["token"] = await GetToken(providerInfo, options.CancellationToken).ConfigureAwait(false);
             return await Get(options, false, providerInfo).ConfigureAwait(false);
         }
 
@@ -743,9 +720,9 @@ namespace Emby.Server.Implementations.LiveTv.Listings
             //_logger.LogInformation("Obtaining token from Schedules Direct from addres: " + httpOptions.Url + " with body " +
             // httpOptions.RequestContent);
 
-            using (var responce = await Post(httpOptions, false, null).ConfigureAwait(false))
+            using (var response = await Post(httpOptions, false, null).ConfigureAwait(false))
             {
-                var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Token>(responce.Content).ConfigureAwait(false);
+                var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Token>(response.Content).ConfigureAwait(false);
                 if (root.message == "OK")
                 {
                     _logger.LogInformation("Authenticated with Schedules Direct token: " + root.token);
@@ -828,13 +805,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings
             try
             {
                 using (var httpResponse = await Get(options, false, null).ConfigureAwait(false))
+                using (var response = httpResponse.Content)
                 {
-                    using (var response = httpResponse.Content)
-                    {
-                        var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Lineups>(response).ConfigureAwait(false);
+                    var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Lineups>(response).ConfigureAwait(false);
 
-                        return root.lineups.Any(i => string.Equals(info.ListingsId, i.lineup, StringComparison.OrdinalIgnoreCase));
-                    }
+                    return root.lineups.Any(i => string.Equals(info.ListingsId, i.lineup, StringComparison.OrdinalIgnoreCase));
                 }
             }
             catch (HttpException ex)
@@ -913,54 +888,41 @@ namespace Emby.Server.Implementations.LiveTv.Listings
             var list = new List<ChannelInfo>();
 
             using (var httpResponse = await Get(httpOptions, true, info).ConfigureAwait(false))
+            using (var response = httpResponse.Content)
             {
-                using (var response = httpResponse.Content)
-                {
-                    var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Channel>(response).ConfigureAwait(false);
-                    _logger.LogInformation("Found " + root.map.Count + " channels on the lineup on ScheduleDirect");
-                    _logger.LogInformation("Mapping Stations to Channel");
-
-                    var allStations = root.stations ?? new List<ScheduleDirect.Station>();
+                var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Channel>(response).ConfigureAwait(false);
+                _logger.LogInformation("Found {ChannelCount} channels on the lineup on ScheduleDirect", root.map.Count);
+                _logger.LogInformation("Mapping Stations to Channel");
 
-                    foreach (ScheduleDirect.Map map in root.map)
-                    {
-                        var channelNumber = GetChannelNumber(map);
+                var allStations = root.stations ?? Enumerable.Empty<ScheduleDirect.Station>();
 
-                        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;
+                foreach (ScheduleDirect.Map map in root.map)
+                {
+                    var channelNumber = GetChannelNumber(map);
 
-                        var channelInfo = new ChannelInfo
+                    var station = allStations.FirstOrDefault(item => string.Equals(item.stationID, map.stationID, StringComparison.OrdinalIgnoreCase));
+                    if (station == null)
+                    {
+                        station = new ScheduleDirect.Station
                         {
-                            Number = channelNumber,
-                            Name = name
+                            stationID = map.stationID
                         };
+                    }
 
-                        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;
-                            }
-                        }
+                    var channelInfo = new ChannelInfo
+                    {
+                        Id = station.stationID,
+                        CallSign = station.callsign,
+                        Number = channelNumber,
+                        Name = string.IsNullOrWhiteSpace(station.name) ? channelNumber : station.name
+                    };
 
-                        list.Add(channelInfo);
+                    if (station.logo != null)
+                    {
+                        channelInfo.ImageUrl = station.logo.URL;
                     }
+
+                    list.Add(channelInfo);
                 }
             }
 

+ 84 - 165
Emby.Server.Implementations/LiveTv/LiveTvManager.cs

@@ -132,9 +132,7 @@ namespace Emby.Server.Implementations.LiveTv
             {
                 service.DataSourceChanged += service_DataSourceChanged;
 
-                var embyTv = service as EmbyTV.EmbyTV;
-
-                if (embyTv != null)
+                if (service is EmbyTV.EmbyTV embyTv)
                 {
                     embyTv.TimerCreated += EmbyTv_TimerCreated;
                     embyTv.TimerCancelled += EmbyTv_TimerCancelled;
@@ -251,18 +249,15 @@ namespace Emby.Server.Implementations.LiveTv
                 mediaSourceId = null;
             }
 
-            MediaSourceInfo info;
-            bool isVideo;
-            ILiveTvService service;
-            ILiveStream liveStream;
-
             var channel = (LiveTvChannel)_libraryManager.GetItemById(id);
-            isVideo = channel.ChannelType == ChannelType.TV;
-            service = GetService(channel);
+
+            bool isVideo = channel.ChannelType == ChannelType.TV;
+            ILiveTvService service = GetService(channel);
             _logger.LogInformation("Opening channel stream from {0}, external channel Id: {1}", service.Name, channel.ExternalId);
 
-            var supportsManagedStream = service as ISupportsDirectStreamProvider;
-            if (supportsManagedStream != null)
+            MediaSourceInfo info;
+            ILiveStream liveStream;
+            if (service is ISupportsDirectStreamProvider supportsManagedStream)
             {
                 liveStream = await supportsManagedStream.GetChannelStreamWithDirectStreamProvider(channel.ExternalId, mediaSourceId, currentLiveStreams, cancellationToken).ConfigureAwait(false);
                 info = liveStream.MediaSource;
@@ -303,14 +298,12 @@ namespace Emby.Server.Implementations.LiveTv
                 throw new NotImplementedException();
             }
 
-            var list = sources.ToList();
-
-            foreach (var source in list)
+            foreach (var source in sources)
             {
                 Normalize(source, service, baseItem.ChannelType == ChannelType.TV);
             }
 
-            return list;
+            return sources;
         }
 
         private ILiveTvService GetService(LiveTvChannel item)
@@ -542,13 +535,11 @@ namespace Emby.Server.Implementations.LiveTv
         {
             var id = _tvDtoService.GetInternalProgramId(info.Id);
 
-            LiveTvProgram item = null;
-            allExistingPrograms.TryGetValue(id, out item);
-
             var isNew = false;
             var forceUpdate = false;
 
-            if (item == null)
+            LiveTvProgram item;
+            if (!allExistingPrograms.TryGetValue(id, out item))
             {
                 isNew = true;
                 item = new LiveTvProgram
@@ -783,11 +774,9 @@ namespace Emby.Server.Implementations.LiveTv
 
             var dto = _dtoService.GetBaseItemDto(program, new DtoOptions(), user);
 
-            var list = new List<Tuple<BaseItemDto, string, string>>();
-
-            var externalSeriesId = program.ExternalSeriesId;
-
-            list.Add(new Tuple<BaseItemDto, string, string>(dto, program.ExternalId, externalSeriesId));
+            var list = new List<Tuple<BaseItemDto, string, string>>() {
+                new Tuple<BaseItemDto, string, string>(dto, program.ExternalId, program.ExternalSeriesId)
+            };
 
             await AddRecordingInfo(list, cancellationToken).ConfigureAwait(false);
 
@@ -928,13 +917,11 @@ namespace Emby.Server.Implementations.LiveTv
                 programs = programs.Take(query.Limit.Value);
             }
 
-            var result = new QueryResult<BaseItem>
-            {
-                Items = programs.ToArray(),
-                TotalRecordCount = totalCount
-            };
-
-            return result;
+            return new QueryResult<BaseItem>
+                {
+                    Items = programs.ToArray(),
+                    TotalRecordCount = totalCount
+                };
         }
 
         public QueryResult<BaseItemDto> GetRecommendedPrograms(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken)
@@ -948,17 +935,11 @@ namespace Emby.Server.Implementations.LiveTv
 
             var internalResult = GetRecommendedProgramsInternal(query, options, cancellationToken);
 
-            var user = query.User;
-
-            var returnArray = _dtoService.GetBaseItemDtos(internalResult.Items, options, user);
-
-            var result = new QueryResult<BaseItemDto>
-            {
-                Items = returnArray,
-                TotalRecordCount = internalResult.TotalRecordCount
-            };
-
-            return result;
+            return new QueryResult<BaseItemDto>
+                {
+                    Items = _dtoService.GetBaseItemDtos(internalResult.Items, options, query.User),
+                    TotalRecordCount = internalResult.TotalRecordCount
+                };
         }
 
         private int GetRecommendationScore(LiveTvProgram program, User user, bool factorChannelWatchCount)
@@ -977,28 +958,26 @@ namespace Emby.Server.Implementations.LiveTv
 
             var channel = _libraryManager.GetItemById(program.ChannelId);
 
-            if (channel != null)
+            if (channel == null)
             {
-                var channelUserdata = _userDataManager.GetUserData(user, channel);
+                return score;
+            }
 
-                if (channelUserdata.Likes ?? false)
-                {
-                    score += 2;
-                }
-                else if (!(channelUserdata.Likes ?? true))
-                {
-                    score -= 2;
-                }
+            var channelUserdata = _userDataManager.GetUserData(user, channel);
 
-                if (channelUserdata.IsFavorite)
-                {
-                    score += 3;
-                }
+            if (channelUserdata.Likes.HasValue)
+            {
+                score += channelUserdata.Likes.Value ? 2 : -2;
+            }
 
-                if (factorChannelWatchCount)
-                {
-                    score += channelUserdata.PlayCount;
-                }
+            if (channelUserdata.IsFavorite)
+            {
+                score += 3;
+            }
+
+            if (factorChannelWatchCount)
+            {
+                score += channelUserdata.PlayCount;
             }
 
             return score;
@@ -1153,7 +1132,6 @@ namespace Emby.Server.Implementations.LiveTv
 
             var numComplete = 0;
             var parentFolder = GetInternalLiveTvFolder(cancellationToken);
-            var parentFolderId = parentFolder.Id;
 
             foreach (var channelInfo in allChannelsList)
             {
@@ -1239,30 +1217,11 @@ namespace Emby.Server.Implementations.LiveTv
 
                         programs.Add(programItem.Id);
 
-                        if (program.IsMovie)
-                        {
-                            isMovie = true;
-                        }
-
-                        if (program.IsSeries)
-                        {
-                            iSSeries = true;
-                        }
-
-                        if (program.IsSports)
-                        {
-                            isSports = true;
-                        }
-
-                        if (program.IsNews)
-                        {
-                            isNews = true;
-                        }
-
-                        if (program.IsKids)
-                        {
-                            isKids = true;
-                        }
+                        isMovie |= program.IsMovie;
+                        iSSeries |= program.IsSeries;
+                        isSports |= program.IsSports;
+                        isNews |= program.IsNews;
+                        isKids |= program.IsKids;
                     }
 
                     _logger.LogDebug("Channel {0} has {1} new programs and {2} updated programs", currentChannel.Name, newPrograms.Count, updatedPrograms.Count);
@@ -1304,8 +1263,7 @@ namespace Emby.Server.Implementations.LiveTv
                 }
 
                 numComplete++;
-                double percent = numComplete;
-                percent /= allChannelsList.Count;
+                double percent = numComplete / allChannelsList.Count;
 
                 progress.Report(85 * percent + 15);
             }
@@ -1320,7 +1278,6 @@ namespace Emby.Server.Implementations.LiveTv
             {
                 IncludeItemTypes = validTypes,
                 DtoOptions = new DtoOptions(false)
-
             });
 
             var numComplete = 0;
@@ -1351,8 +1308,7 @@ namespace Emby.Server.Implementations.LiveTv
                 }
 
                 numComplete++;
-                double percent = numComplete;
-                percent /= list.Count;
+                double percent = numComplete / list.Count;
 
                 progress.Report(100 * percent);
             }
@@ -1414,28 +1370,22 @@ namespace Emby.Server.Implementations.LiveTv
                     excludeItemTypes.Add(typeof(Episode).Name);
                 }
             }
-            if (query.IsSports.HasValue)
+            if (query.IsSports ?? false)
             {
-                if (query.IsSports.Value)
-                {
-                    genres.Add("Sports");
-                }
+                genres.Add("Sports");
             }
-            if (query.IsKids.HasValue)
+            if (query.IsKids ?? false)
             {
-                if (query.IsKids.Value)
-                {
-                    genres.Add("Kids");
-                    genres.Add("Children");
-                    genres.Add("Family");
-                }
+                genres.Add("Kids");
+                genres.Add("Children");
+                genres.Add("Family");
             }
 
             var limit = query.Limit;
 
-            if ((query.IsInProgress ?? false))
+            if (query.IsInProgress ?? false)
             {
-                limit = (query.Limit ?? 10) * 2;
+                // limit = (query.Limit ?? 10) * 2;
                 limit = null;
 
                 //var allActivePaths = EmbyTV.EmbyTV.Current.GetAllActiveRecordings().Select(i => i.Path).ToArray();
@@ -1467,7 +1417,7 @@ namespace Emby.Server.Implementations.LiveTv
                 DtoOptions = dtoOptions
             });
 
-            if ((query.IsInProgress ?? false))
+            if (query.IsInProgress ?? false)
             {
                 result.Items = result
                     .Items
@@ -1494,60 +1444,33 @@ namespace Emby.Server.Implementations.LiveTv
 
                 dto.StartDate = program.StartDate;
                 dto.EpisodeTitle = program.EpisodeTitle;
-
-                if (program.IsRepeat)
-                {
-                    dto.IsRepeat = program.IsRepeat;
-                }
-                if (program.IsMovie)
-                {
-                    dto.IsMovie = program.IsMovie;
-                }
-                if (program.IsSeries)
-                {
-                    dto.IsSeries = program.IsSeries;
-                }
-                if (program.IsSports)
-                {
-                    dto.IsSports = program.IsSports;
-                }
-                if (program.IsLive)
-                {
-                    dto.IsLive = program.IsLive;
-                }
-                if (program.IsNews)
-                {
-                    dto.IsNews = program.IsNews;
-                }
-                if (program.IsKids)
-                {
-                    dto.IsKids = program.IsKids;
-                }
-                if (program.IsPremiere)
-                {
-                    dto.IsPremiere = program.IsPremiere;
-                }
+                dto.IsRepeat |= program.IsRepeat;
+                dto.IsMovie |= program.IsMovie;
+                dto.IsSeries |= program.IsSeries;
+                dto.IsSports |= program.IsSports;
+                dto.IsLive |= program.IsLive;
+                dto.IsNews |= program.IsNews;
+                dto.IsKids |= program.IsKids;
+                dto.IsPremiere |= program.IsPremiere;
 
                 if (hasChannelInfo || hasChannelImage)
                 {
-                    var channel = _libraryManager.GetItemById(program.ChannelId) as LiveTvChannel;
+                    var channel = _libraryManager.GetItemById(program.ChannelId);
 
-                    if (channel != null)
+                    if (channel is LiveTvChannel liveChannel)
                     {
-                        dto.ChannelName = channel.Name;
-                        dto.MediaType = channel.MediaType;
-                        dto.ChannelNumber = channel.Number;
+                        dto.ChannelName = liveChannel.Name;
+                        dto.MediaType = liveChannel.MediaType;
+                        dto.ChannelNumber = liveChannel.Number;
 
-                        if (hasChannelImage && channel.HasImage(ImageType.Primary))
+                        if (hasChannelImage && liveChannel.HasImage(ImageType.Primary))
                         {
-                            dto.ChannelPrimaryImageTag = _tvDtoService.GetImageTag(channel);
+                            dto.ChannelPrimaryImageTag = _tvDtoService.GetImageTag(liveChannel);
                         }
                     }
                 }
 
-                var externalSeriesId = program.ExternalSeriesId;
-
-                programTuples.Add(new Tuple<BaseItemDto, string, string>(dto, program.ExternalId, externalSeriesId));
+                programTuples.Add(new Tuple<BaseItemDto, string, string>(dto, program.ExternalId, program.ExternalSeriesId));
             }
 
             return AddRecordingInfo(programTuples, CancellationToken.None);
@@ -2037,19 +1960,13 @@ namespace Emby.Server.Implementations.LiveTv
 
         private async Task<Tuple<SeriesTimerInfo, ILiveTvService>> GetNewTimerDefaultsInternal(CancellationToken cancellationToken, LiveTvProgram program = null)
         {
-            var service = program != null ?
-                GetService(program) :
-                null;
-
-            if (service == null)
-            {
-                service = _services.First();
-            }
-
+            ILiveTvService service = null;
             ProgramInfo programInfo = null;
 
-            if (program != null)
+            if(program != null)
             {
+                service = GetService(program);
+
                 var channel = _libraryManager.GetItemById(program.ChannelId);
 
                 programInfo = new ProgramInfo
@@ -2077,6 +1994,11 @@ namespace Emby.Server.Implementations.LiveTv
                     Name = program.Name,
                     OfficialRating = program.OfficialRating
                 };
+            } 
+
+            if (service == null)
+            {
+                service = _services.First();
             }
 
             var info = await service.GetNewTimerDefaultsAsync(cancellationToken, programInfo).ConfigureAwait(false);
@@ -2147,8 +2069,7 @@ namespace Emby.Server.Implementations.LiveTv
             info.Priority = defaultValues.Priority;
 
             string newTimerId = null;
-            var supportsNewTimerIds = service as ISupportsNewTimerIds;
-            if (supportsNewTimerIds != null)
+            if (service is ISupportsNewTimerIds supportsNewTimerIds)
             {
                 newTimerId = await supportsNewTimerIds.CreateTimer(info, cancellationToken).ConfigureAwait(false);
                 newTimerId = _tvDtoService.GetInternalTimerId(newTimerId);
@@ -2192,8 +2113,7 @@ namespace Emby.Server.Implementations.LiveTv
             info.Priority = defaultValues.Priority;
 
             string newTimerId = null;
-            var supportsNewTimerIds = service as ISupportsNewTimerIds;
-            if (supportsNewTimerIds != null)
+            if (service is ISupportsNewTimerIds supportsNewTimerIds)
             {
                 newTimerId = await supportsNewTimerIds.CreateSeriesTimer(info, cancellationToken).ConfigureAwait(false);
                 newTimerId = _tvDtoService.GetInternalSeriesTimerId(newTimerId).ToString("N");
@@ -2354,8 +2274,7 @@ namespace Emby.Server.Implementations.LiveTv
                 throw new ResourceNotFoundException();
             }
 
-            var configurable = provider as IConfigurableTunerHost;
-            if (configurable != null)
+            if (provider is IConfigurableTunerHost configurable)
             {
                 await configurable.Validate(info).ConfigureAwait(false);
             }

+ 3 - 3
Emby.Server.Implementations/Updates/InstallationManager.cs

@@ -549,13 +549,13 @@ namespace Emby.Server.Implementations.Updates
             // Do plugin-specific processing
             if (isPlugin)
             {
-                if (plugin != null)
+                if (plugin == null)
                 {
-                    OnPluginUpdated(plugin, package);
+                    OnPluginInstalled(package);
                 }
                 else
                 {
-                    OnPluginInstalled(package);
+                    OnPluginUpdated(plugin, package);
                 }
             }
         }

+ 2 - 5
MediaBrowser.Common/Net/IHttpClient.cs

@@ -1,7 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Threading;
+using System.IO;
 using System.Threading.Tasks;
 
 namespace MediaBrowser.Common.Net
@@ -56,4 +53,4 @@ namespace MediaBrowser.Common.Net
         /// <returns>Task{HttpResponseInfo}.</returns>
         Task<HttpResponseInfo> GetTempFileResponse(HttpRequestOptions options);
     }
-}
+}

+ 2 - 2
MediaBrowser.Providers/Movies/MovieDbProvider.cs

@@ -146,7 +146,7 @@ namespace MediaBrowser.Providers.Movies
                 return _tmdbSettings;
             }
 
-            using (var response = await GetMovieDbResponse(new HttpRequestOptions
+            using (HttpResponseInfo response = await GetMovieDbResponse(new HttpRequestOptions
             {
                 Url = string.Format(TmdbConfigUrl, ApiKey),
                 CancellationToken = cancellationToken,
@@ -154,7 +154,7 @@ namespace MediaBrowser.Providers.Movies
 
             }).ConfigureAwait(false))
             {
-                using (var json = response.Content)
+                using (Stream json = response.Content)
                 {
                     _tmdbSettings = await _jsonSerializer.DeserializeFromStreamAsync<TmdbSettingsResult>(json).ConfigureAwait(false);