2024-09-01 18:10:03 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								using  System.Security.Cryptography ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								using  System.Text.Json ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								using  AIStudio.Provider ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								using  AIStudio.Tools.Rust ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// ReSharper disable NotAccessedPositionalProperty.Local 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								namespace  AIStudio.Tools ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/// <summary> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/// Calling Rust functions. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/// </summary> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								public  sealed  class  RustService  :  IDisposable 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    private  readonly  HttpClient  http ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    private  readonly  JsonSerializerOptions  jsonRustSerializerOptions  =  new ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        PropertyNamingPolicy  =  JsonNamingPolicy . SnakeCaseLower , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    private  ILogger < RustService > ?  logger ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    private  Encryption ?  encryptor ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    private  readonly  string  apiPort ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    private  readonly  string  certificateFingerprint ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  RustService ( string  apiPort ,  string  certificateFingerprint ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this . apiPort  =  apiPort ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this . certificateFingerprint  =  certificateFingerprint ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        var  certificateValidationHandler  =  new  HttpClientHandler 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ServerCertificateCustomValidationCallback  =  ( _ ,  certificate ,  _ ,  _ )  = > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if ( certificate  is  null ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                var  currentCertificateFingerprint  =  certificate . GetCertHashString ( HashAlgorithmName . SHA256 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  currentCertificateFingerprint  = =  certificateFingerprint ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this . http  =  new  HttpClient ( certificateValidationHandler ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            BaseAddress  =  new  Uri ( $"https://127.0.0.1:{apiPort}" ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            DefaultRequestVersion  =  Version . Parse ( "2.0" ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            DefaultVersionPolicy  =  HttpVersionPolicy . RequestVersionOrHigher , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this . http . DefaultRequestHeaders . AddApiToken ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  void  SetLogger ( ILogger < RustService >  logService ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this . logger  =  logService ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  void  SetEncryptor ( Encryption  encryptionService ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this . encryptor  =  encryptionService ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  async  Task < int >  GetAppPort ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        Console . WriteLine ( "Trying to get app port from Rust runtime..." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Note I: In the production environment, the Rust runtime is already running 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // and listening on the given port. In the development environment, the IDE 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // starts the Rust runtime in parallel with the .NET runtime. Since the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // Rust runtime needs some time to start, we have to wait for it to be ready. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        const  int  MAX_TRIES  =  160 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        var  tris  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        var  wait4Try  =  TimeSpan . FromMilliseconds ( 250 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        var  url  =  new  Uri ( $"https://127.0.0.1:{this.apiPort}/system/dotnet/port" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        while  ( tris + +  <  MAX_TRIES ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Note II: We use a new HttpClient instance for each try to avoid 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // .NET is caching the result. When we use the same HttpClient 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // instance, we would always get the same result (403 forbidden), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // without even trying to connect to the Rust server. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            using  var  initialHttp  =  new  HttpClient ( new  HttpClientHandler 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // Note III: We have to create also a new HttpClientHandler instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // for each try to avoid .NET is caching the result. This is necessary 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // because it gets disposed when the HttpClient instance gets disposed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ServerCertificateCustomValidationCallback  =  ( _ ,  certificate ,  _ ,  _ )  = > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    if ( certificate  is  null ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    var  currentCertificateFingerprint  =  certificate . GetCertHashString ( HashAlgorithmName . SHA256 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    return  currentCertificateFingerprint  = =  this . certificateFingerprint ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            initialHttp . DefaultRequestVersion  =  Version . Parse ( "2.0" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            initialHttp . DefaultVersionPolicy  =  HttpVersionPolicy . RequestVersionOrHigher ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            initialHttp . DefaultRequestHeaders . AddApiToken ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            try 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                var  response  =  await  initialHttp . GetAsync ( url ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( ! response . IsSuccessStatusCode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    Console . WriteLine ( $"Try {tris}/{MAX_TRIES} to get the app port from Rust runtime" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    await  Task . Delay ( wait4Try ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                var  appPortContent  =  await  response . Content . ReadAsStringAsync ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                var  appPort  =  int . Parse ( appPortContent ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                Console . WriteLine ( $"Received app port from Rust runtime: '{appPort}'" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  appPort ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            catch  ( Exception  e ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                Console . WriteLine ( $"Error: Was not able to get the app port from Rust runtime: '{e.Message}'" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                Console . WriteLine ( e . InnerException ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                throw ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        Console . WriteLine ( "Failed to receive the app port from Rust runtime." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  async  Task  AppIsReady ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        const  string  URL  =  "/system/dotnet/ready" ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this . logger ! . LogInformation ( "Notifying Rust runtime that the app is ready." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        try 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            var  response  =  await  this . http . GetAsync ( URL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ! response . IsSuccessStatusCode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                this . logger ! . LogError ( $"Failed to notify Rust runtime that the app is ready: '{response.StatusCode}'" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        catch  ( Exception  e ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this . logger ! . LogError ( e ,  "Failed to notify the Rust runtime that the app is ready." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            throw ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  async  Task < string >  GetConfigDirectory ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        var  response  =  await  this . http . GetAsync ( "/system/directories/config" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! response . IsSuccessStatusCode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this . logger ! . LogError ( $"Failed to get the config directory from Rust: '{response.StatusCode}'" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  string . Empty ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  await  response . Content . ReadAsStringAsync ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  async  Task < string >  GetDataDirectory ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        var  response  =  await  this . http . GetAsync ( "/system/directories/data" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! response . IsSuccessStatusCode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this . logger ! . LogError ( $"Failed to get the data directory from Rust: '{response.StatusCode}'" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  string . Empty ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  await  response . Content . ReadAsStringAsync ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// <summary> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// Tries to copy the given text to the clipboard. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// </summary> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// <param name="snackbar">The snackbar to show the result.</param> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// <param name="text">The text to copy to the clipboard.</param> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  async  Task  CopyText2Clipboard ( ISnackbar  snackbar ,  string  text ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        var  message  =  "Successfully copied the text to your clipboard" ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        var  iconColor  =  Color . Error ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        var  severity  =  Severity . Error ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        try 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            var  encryptedText  =  await  text . Encrypt ( this . encryptor ! ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            var  response  =  await  this . http . PostAsync ( "/clipboard/set" ,  new  StringContent ( encryptedText . EncryptedData ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ! response . IsSuccessStatusCode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                this . logger ! . LogError ( $"Failed to copy the text to the clipboard due to an network error: '{response.StatusCode}'" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                message  =  "Failed to copy the text to your clipboard." ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-05 09:13:40 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            var  state  =  await  response . Content . ReadFromJsonAsync < SetClipboardResponse > ( this . jsonRustSerializerOptions ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-01 18:10:03 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ! state . Success ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                this . logger ! . LogError ( "Failed to copy the text to the clipboard." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                message  =  "Failed to copy the text to your clipboard." ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            iconColor  =  Color . Success ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            severity  =  Severity . Success ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this . logger ! . LogDebug ( "Successfully copied the text to the clipboard." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        finally 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            snackbar . Add ( message ,  severity ,  config  = > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                config . Icon  =  Icons . Material . Filled . ContentCopy ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                config . IconSize  =  Size . Large ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                config . IconColor  =  iconColor ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  async  Task < UpdateResponse >  CheckForUpdate ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        try 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-08 09:17:10 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            var  cts  =  new  CancellationTokenSource ( TimeSpan . FromSeconds ( 45 ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-05 09:13:40 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            var  response  =  await  this . http . GetFromJsonAsync < UpdateResponse > ( "/updates/check" ,  this . jsonRustSerializerOptions ,  cts . Token ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this . logger ! . LogInformation ( $"Checked for an update: update available='{response.UpdateIsAvailable}'; error='{response.Error}'; next version='{response.NewVersion}'; changelog len='{response.Changelog.Length}'" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  response ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-01 18:10:03 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        catch  ( Exception  e ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this . logger ! . LogError ( e ,  "Failed to check for an update." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  new  UpdateResponse 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                Error  =  true , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                UpdateIsAvailable  =  false , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  async  Task  InstallUpdate ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        try 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            var  cts  =  new  CancellationTokenSource ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            await  this . http . GetAsync ( "/updates/install" ,  cts . Token ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        catch  ( Exception  e ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            Console . WriteLine ( e ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            throw ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// <summary> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// Try to get the API key for the given provider. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// </summary> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// <param name="provider">The provider to get the API key for.</param> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// <returns>The requested secret.</returns> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  async  Task < RequestedSecret >  GetAPIKey ( IProvider  provider ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        var  secretRequest  =  new  SelectSecretRequest ( $"provider::{provider.Id}::{provider.InstanceName}::api_key" ,  Environment . UserName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        var  result  =  await  this . http . PostAsJsonAsync ( "/secrets/get" ,  secretRequest ,  this . jsonRustSerializerOptions ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! result . IsSuccessStatusCode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this . logger ! . LogError ( $"Failed to get the API key for provider '{provider.Id}' due to an API issue: '{result.StatusCode}'" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  new  RequestedSecret ( false ,  new  EncryptedText ( string . Empty ) ,  "Failed to get the API key due to an API issue." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        
							 
						 
					
						
							
								
									
										
										
										
											2024-09-05 09:13:40 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        var  secret  =  await  result . Content . ReadFromJsonAsync < RequestedSecret > ( this . jsonRustSerializerOptions ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-01 18:10:03 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! secret . Success ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this . logger ! . LogError ( $"Failed to get the API key for provider '{provider.Id}': '{secret.Issue}'" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  secret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// <summary> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// Try to store the API key for the given provider. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// </summary> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// <param name="provider">The provider to store the API key for.</param> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// <param name="key">The API key to store.</param> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// <returns>The store secret response.</returns> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  async  Task < StoreSecretResponse >  SetAPIKey ( IProvider  provider ,  string  key ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        var  encryptedKey  =  await  this . encryptor ! . Encrypt ( key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        var  request  =  new  StoreSecretRequest ( $"provider::{provider.Id}::{provider.InstanceName}::api_key" ,  Environment . UserName ,  encryptedKey ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        var  result  =  await  this . http . PostAsJsonAsync ( "/secrets/store" ,  request ,  this . jsonRustSerializerOptions ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! result . IsSuccessStatusCode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this . logger ! . LogError ( $"Failed to store the API key for provider '{provider.Id}' due to an API issue: '{result.StatusCode}'" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  new  StoreSecretResponse ( false ,  "Failed to get the API key due to an API issue." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        
							 
						 
					
						
							
								
									
										
										
										
											2024-09-05 09:13:40 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        var  state  =  await  result . Content . ReadFromJsonAsync < StoreSecretResponse > ( this . jsonRustSerializerOptions ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-01 18:10:03 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! state . Success ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this . logger ! . LogError ( $"Failed to store the API key for provider '{provider.Id}': '{state.Issue}'" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  state ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// <summary> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// Tries to delete the API key for the given provider. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// </summary> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// <param name="provider">The provider to delete the API key for.</param> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /// <returns>The delete secret response.</returns> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  async  Task < DeleteSecretResponse >  DeleteAPIKey ( IProvider  provider ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        var  request  =  new  SelectSecretRequest ( $"provider::{provider.Id}::{provider.InstanceName}::api_key" ,  Environment . UserName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        var  result  =  await  this . http . PostAsJsonAsync ( "/secrets/delete" ,  request ,  this . jsonRustSerializerOptions ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! result . IsSuccessStatusCode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this . logger ! . LogError ( $"Failed to delete the API key for provider '{provider.Id}' due to an API issue: '{result.StatusCode}'" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  new  DeleteSecretResponse { Success  =  false ,  WasEntryFound  =  false ,  Issue  =  "Failed to delete the API key due to an API issue." } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        
							 
						 
					
						
							
								
									
										
										
										
											2024-09-05 09:13:40 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        var  state  =  await  result . Content . ReadFromJsonAsync < DeleteSecretResponse > ( this . jsonRustSerializerOptions ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-01 18:10:03 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! state . Success ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this . logger ! . LogError ( $"Failed to delete the API key for provider '{provider.Id}': '{state.Issue}'" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  state ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    #region  IDisposable 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  void  Dispose ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this . http . Dispose ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    #endregion 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}