| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 | using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Threading;using System.Threading.Tasks;using MediaBrowser.Common.Net;using MediaBrowser.Model.Serialization;using MediaBrowser.Model.Updates;namespace MediaBrowser.Common.Implementations.Updates{    public class GithubUpdater    {        private readonly IHttpClient _httpClient;        private readonly IJsonSerializer _jsonSerializer;        private TimeSpan _cacheLength;        public GithubUpdater(IHttpClient httpClient, IJsonSerializer jsonSerializer, TimeSpan cacheLength)        {            _httpClient = httpClient;            _jsonSerializer = jsonSerializer;            _cacheLength = cacheLength;        }        public async Task<CheckForUpdateResult> CheckForUpdateResult(string organzation, string repository, Version minVersion, PackageVersionClass updateLevel, string assetFilename, string packageName, string targetFilename, CancellationToken cancellationToken)        {            var url = string.Format("https://api.github.com/repos/{0}/{1}/releases", organzation, repository);            var options = new HttpRequestOptions            {                Url = url,                EnableKeepAlive = false,                CancellationToken = cancellationToken,                UserAgent = "Emby/3.0"            };            if (_cacheLength.Ticks > 0)            {                options.CacheMode = CacheMode.Unconditional;                options.CacheLength = _cacheLength;            }            using (var stream = await _httpClient.Get(options).ConfigureAwait(false))            {                var obj = _jsonSerializer.DeserializeFromStream<RootObject[]>(stream);                return CheckForUpdateResult(obj, minVersion, updateLevel, assetFilename, packageName, targetFilename);            }        }        private CheckForUpdateResult CheckForUpdateResult(RootObject[] obj, Version minVersion, PackageVersionClass updateLevel, string assetFilename, string packageName, string targetFilename)        {            if (updateLevel == PackageVersionClass.Release)            {                // Technically all we need to do is check that it's not pre-release                // But let's addititional checks for -beta and -dev to handle builds that might be temporarily tagged incorrectly.                obj = obj.Where(i => !i.prerelease && !i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) && !i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase)).ToArray();            }            else if (updateLevel == PackageVersionClass.Beta)            {                obj = obj.Where(i => !i.prerelease || i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase)).ToArray();            }            else if (updateLevel == PackageVersionClass.Dev)            {                obj = obj.Where(i => !i.prerelease || i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) || i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase)).ToArray();            }            var availableUpdate = obj                .Select(i => CheckForUpdateResult(i, minVersion, assetFilename, packageName, targetFilename))                .Where(i => i != null)                .OrderByDescending(i => Version.Parse(i.AvailableVersion))                .FirstOrDefault();            return availableUpdate ?? new CheckForUpdateResult            {                IsUpdateAvailable = false            };        }        private CheckForUpdateResult CheckForUpdateResult(RootObject obj, Version minVersion, string assetFilename, string packageName, string targetFilename)        {            Version version;            if (!Version.TryParse(obj.tag_name, out version))            {                return null;            }            if (version < minVersion)            {                return null;            }            var asset = (obj.assets ?? new List<Asset>()).FirstOrDefault(i => IsAsset(i, assetFilename));            if (asset == null)            {                return null;            }            return new CheckForUpdateResult            {                AvailableVersion = version.ToString(),                IsUpdateAvailable = version > minVersion,                Package = new PackageVersionInfo                {                    classification = obj.prerelease ?                        (obj.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase) ? PackageVersionClass.Dev : PackageVersionClass.Beta) :                        PackageVersionClass.Release,                    name = packageName,                    sourceUrl = asset.browser_download_url,                    targetFilename = targetFilename,                    versionStr = version.ToString(),                    requiredVersionStr = "1.0.0",                    description = obj.body,                    infoUrl = obj.html_url                }            };        }        private bool IsAsset(Asset asset, string assetFilename)        {            var downloadFilename = Path.GetFileName(asset.browser_download_url) ?? string.Empty;            if (downloadFilename.IndexOf(assetFilename, StringComparison.OrdinalIgnoreCase) != -1)            {                return true;            }            return string.Equals(assetFilename, downloadFilename, StringComparison.OrdinalIgnoreCase);        }        public class Uploader        {            public string login { get; set; }            public int id { get; set; }            public string avatar_url { get; set; }            public string gravatar_id { get; set; }            public string url { get; set; }            public string html_url { get; set; }            public string followers_url { get; set; }            public string following_url { get; set; }            public string gists_url { get; set; }            public string starred_url { get; set; }            public string subscriptions_url { get; set; }            public string organizations_url { get; set; }            public string repos_url { get; set; }            public string events_url { get; set; }            public string received_events_url { get; set; }            public string type { get; set; }            public bool site_admin { get; set; }        }        public class Asset        {            public string url { get; set; }            public int id { get; set; }            public string name { get; set; }            public object label { get; set; }            public Uploader uploader { get; set; }            public string content_type { get; set; }            public string state { get; set; }            public int size { get; set; }            public int download_count { get; set; }            public string created_at { get; set; }            public string updated_at { get; set; }            public string browser_download_url { get; set; }        }        public class Author        {            public string login { get; set; }            public int id { get; set; }            public string avatar_url { get; set; }            public string gravatar_id { get; set; }            public string url { get; set; }            public string html_url { get; set; }            public string followers_url { get; set; }            public string following_url { get; set; }            public string gists_url { get; set; }            public string starred_url { get; set; }            public string subscriptions_url { get; set; }            public string organizations_url { get; set; }            public string repos_url { get; set; }            public string events_url { get; set; }            public string received_events_url { get; set; }            public string type { get; set; }            public bool site_admin { get; set; }        }        public class RootObject        {            public string url { get; set; }            public string assets_url { get; set; }            public string upload_url { get; set; }            public string html_url { get; set; }            public int id { get; set; }            public string tag_name { get; set; }            public string target_commitish { get; set; }            public string name { get; set; }            public bool draft { get; set; }            public Author author { get; set; }            public bool prerelease { get; set; }            public string created_at { get; set; }            public string published_at { get; set; }            public List<Asset> assets { get; set; }            public string tarball_url { get; set; }            public string zipball_url { get; set; }            public string body { get; set; }        }    }}
 |