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 )
{
obj = obj . Where ( i = > ! i . prerelease ) . 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 ; }
}
}
}