2019-10-12 18:03:45 +00:00
using System ;
2020-04-02 16:41:50 +00:00
using System.Reactive ;
using System.Reactive.Linq ;
2020-04-04 14:33:58 +00:00
using System.Security ;
2019-12-06 05:29:17 +00:00
using System.Threading.Tasks ;
2019-10-12 18:03:45 +00:00
using CG.Web.MegaApiClient ;
2020-04-02 16:41:50 +00:00
using ReactiveUI ;
2019-10-12 18:03:45 +00:00
using Wabbajack.Common ;
2020-04-06 20:48:54 +00:00
using Wabbajack.Common.Serialization.Json ;
2019-10-12 18:03:45 +00:00
2019-10-16 03:10:34 +00:00
namespace Wabbajack.Lib.Downloaders
2019-10-12 18:03:45 +00:00
{
2020-04-04 13:54:09 +00:00
public class MegaDownloader : IUrlDownloader , INeedsLoginCredentials
2019-10-12 18:03:45 +00:00
{
2020-04-02 16:41:50 +00:00
public MegaApiClient MegaApiClient ;
private const string DataName = "mega-cred" ;
2020-04-04 14:33:58 +00:00
public LoginReturnMessage LoginWithCredentials ( string username , SecureString password )
2020-04-04 13:54:09 +00:00
{
MegaApiClient . AuthInfos authInfos ;
try
{
2020-04-04 14:33:58 +00:00
authInfos = MegaApiClient . GenerateAuthInfos ( username , password . ToNormalString ( ) ) ;
2020-04-04 13:54:09 +00:00
}
catch ( ApiException e )
{
return e . ApiResultCode switch
{
ApiResultCode . BadArguments = > new LoginReturnMessage ( $"Email or password was wrong! {e.Message}" ,
true ) ,
ApiResultCode . InternalError = > new LoginReturnMessage (
$"Internal error occured! Please report this to the Wabbajack Team! {e.Message}" , true ) ,
_ = > new LoginReturnMessage ( $"Error generating authentication information! {e.Message}" , true )
} ;
}
try
{
MegaApiClient . Login ( authInfos ) ;
}
catch ( ApiException e )
{
return e . ApiResultCode switch
{
2020-04-10 10:47:29 +00:00
ApiResultCode . TwoFactorAuthenticationError = > new LoginReturnMessage (
$"Two-Factor Authentication needs to be disabled before login! {e.Message}" , true ) ,
2020-04-04 13:54:09 +00:00
ApiResultCode . InternalError = > new LoginReturnMessage (
$"Internal error occured! Please report this to the Wabbajack Team! {e.Message}" , true ) ,
_ = > new LoginReturnMessage ( $"Error during login: {e.Message}" , true )
} ;
}
if ( MegaApiClient . IsLoggedIn )
authInfos . ToEcryptedJson ( DataName ) ;
return new LoginReturnMessage ( "Logged in successfully, you can now close this window." ,
! MegaApiClient . IsLoggedIn | | ! Utils . HaveEncryptedJson ( DataName ) ) ;
}
2020-04-02 16:41:50 +00:00
public MegaDownloader ( )
{
MegaApiClient = new MegaApiClient ( ) ;
TriggerLogin = ReactiveCommand . Create ( ( ) = > { } ,
IsLoggedIn . Select ( b = > ! b ) . ObserveOnGuiThread ( ) ) ;
ClearLogin = ReactiveCommand . Create ( ( ) = > Utils . CatchAndLog ( ( ) = > Utils . DeleteEncryptedJson ( DataName ) ) ,
IsLoggedIn . ObserveOnGuiThread ( ) ) ;
}
2020-04-09 20:20:34 +00:00
public async Task < AbstractDownloadState ? > GetDownloaderState ( dynamic archiveINI , bool quickMode )
2019-10-12 18:03:45 +00:00
{
2019-11-21 15:51:57 +00:00
var url = archiveINI ? . General ? . directURL ;
2019-10-16 11:44:45 +00:00
return GetDownloaderState ( url ) ;
}
2020-04-09 20:20:34 +00:00
public AbstractDownloadState ? GetDownloaderState ( string url )
2019-10-16 11:44:45 +00:00
{
2020-04-27 18:49:22 +00:00
if ( url ! = null & & ( url . StartsWith ( Consts . MegaPrefix ) | | url . StartsWith ( Consts . MegaFilePrefix ) ) )
2020-04-09 20:20:34 +00:00
return new State ( url ) ;
2019-10-12 18:03:45 +00:00
return null ;
}
2019-12-07 02:45:13 +00:00
public async Task Prepare ( )
2019-10-12 22:15:20 +00:00
{
}
2020-04-06 20:48:54 +00:00
[JsonName("MegaDownloader")]
2019-10-12 21:37:16 +00:00
public class State : HTTPDownloader . State
2019-10-12 18:03:45 +00:00
{
2020-04-09 20:20:34 +00:00
public State ( string url )
: base ( url )
{
}
2020-04-04 22:55:17 +00:00
private static MegaApiClient MegaApiClient = > DownloadDispatcher . GetInstance < MegaDownloader > ( ) . MegaApiClient ;
2020-04-02 16:41:50 +00:00
2020-04-29 12:26:44 +00:00
private static AsyncLock _loginLock = new AsyncLock ( ) ;
private static async Task MegaLogin ( )
2019-10-12 18:03:45 +00:00
{
2020-04-29 12:26:44 +00:00
using var _ = await _loginLock . WaitAsync ( ) ;
2020-04-04 14:43:42 +00:00
if ( MegaApiClient . IsLoggedIn )
return ;
if ( ! Utils . HaveEncryptedJson ( DataName ) )
2020-04-02 16:41:50 +00:00
{
Utils . Status ( "Logging into MEGA (as anonymous)" ) ;
2020-04-29 12:26:44 +00:00
await MegaApiClient . LoginAnonymousAsync ( ) ;
2020-04-04 14:43:42 +00:00
}
else
2020-04-04 13:54:09 +00:00
{
Utils . Status ( "Logging into MEGA with saved credentials." ) ;
var authInfo = Utils . FromEncryptedJson < MegaApiClient . AuthInfos > ( DataName ) ;
2020-04-29 12:26:44 +00:00
await MegaApiClient . LoginAsync ( authInfo ) ;
2020-04-02 16:41:50 +00:00
}
2020-04-04 14:43:42 +00:00
}
2020-03-25 22:30:43 +00:00
public override async Task < bool > Download ( Archive a , AbsolutePath destination )
2019-10-12 18:03:45 +00:00
{
2020-04-29 12:26:44 +00:00
await MegaLogin ( ) ;
2020-04-02 16:41:50 +00:00
2019-11-21 15:51:57 +00:00
var fileLink = new Uri ( Url ) ;
2019-10-12 18:03:45 +00:00
Utils . Status ( $"Downloading MEGA file: {a.Name}" ) ;
2020-04-04 22:15:55 +00:00
await MegaApiClient . DownloadFileAsync ( fileLink , ( string ) destination , new Progress < double > ( p = > Utils . Status ( $"Downloading MEGA File: {a.Name}" , Percent . FactoryPutInRange ( p ) ) ) ) ;
2020-01-18 19:57:26 +00:00
return true ;
2019-10-12 18:03:45 +00:00
}
2020-01-13 22:55:55 +00:00
public override async Task < bool > Verify ( Archive a )
2019-10-12 18:03:45 +00:00
{
2020-04-29 12:26:44 +00:00
await MegaLogin ( ) ;
2020-04-02 16:41:50 +00:00
2019-11-21 15:51:57 +00:00
var fileLink = new Uri ( Url ) ;
2019-10-12 18:03:45 +00:00
try
{
2020-04-26 09:31:00 +00:00
var node = await MegaApiClient . GetNodeFromLinkAsync ( fileLink ) ;
2020-04-27 18:49:22 +00:00
return node ! = null ;
2019-10-12 18:03:45 +00:00
}
catch ( Exception )
{
return false ;
}
}
}
2020-04-02 16:41:50 +00:00
public ReactiveCommand < Unit , Unit > TriggerLogin { get ; }
public ReactiveCommand < Unit , Unit > ClearLogin { get ; }
public IObservable < bool > IsLoggedIn = > Utils . HaveEncryptedJsonObservable ( DataName ) ;
public string SiteName = > "MEGA" ;
public IObservable < string > MetaInfo = > Observable . Return ( "" ) ;
public Uri SiteURL = > new Uri ( "https://mega.nz/" ) ;
public Uri IconUri = > new Uri ( "https://mega.nz/favicon.ico" ) ;
2019-10-12 18:03:45 +00:00
}
}