@@ -184,6 +184,15 @@ public void LoadAccounts()
184184 _accounts = new ( ) ;
185185 NoAccountsFound ? . Invoke ( ) ;
186186 }
187+
188+ if ( _accounts . Any ( ) )
189+ {
190+ _ = Task . Run ( async ( ) =>
191+ {
192+ await Task . Delay ( 3000 ) ;
193+ await ValidateAllAccountsAsync ( ) ;
194+ } ) ;
195+ }
187196 }
188197
189198 public void SaveAccounts ( )
@@ -1458,5 +1467,94 @@ private void FallbackToSystemProtocol(long placeId = 0, string serverId = "")
14581467 acc . Username . Equals ( identifier , StringComparison . OrdinalIgnoreCase ) ||
14591468 acc . UserId . ToString ( ) == identifier ) ;
14601469 }
1470+
1471+ public async Task < bool > ValidateAccountAsync ( AltAccount account )
1472+ {
1473+ const string LOG_IDENT_VALIDATE = $ "{ LOG_IDENT } ::ValidateAccount";
1474+
1475+ try
1476+ {
1477+ string decryptedCookie = UnprotectString ( account . SecurityToken ) ;
1478+
1479+ if ( string . IsNullOrEmpty ( decryptedCookie ) )
1480+ {
1481+ App . Logger . WriteLine ( LOG_IDENT_VALIDATE , $ "Account { account . Username } : No valid cookie found") ;
1482+ return false ;
1483+ }
1484+
1485+ var handler = new HttpClientHandler { CookieContainer = new CookieContainer ( ) } ;
1486+ handler . CookieContainer . Add ( new Cookie ( ".ROBLOSECURITY" , decryptedCookie , "/" , ".roblox.com" ) ) ;
1487+
1488+ using var client = new HttpClient ( handler ) ;
1489+
1490+ var response = await client . GetAsync ( "https://users.roblox.com/v1/users/authenticated" ) ;
1491+
1492+ bool isValid = response . StatusCode == HttpStatusCode . OK ;
1493+
1494+ App . Logger . WriteLine ( LOG_IDENT_VALIDATE , $ "Account { account . Username } : { ( isValid ? "Valid" : "Invalid" ) } (Status: { response . StatusCode } )") ;
1495+
1496+ return isValid ;
1497+ }
1498+ catch ( Exception ex )
1499+ {
1500+ App . Logger . WriteException ( LOG_IDENT_VALIDATE , ex ) ;
1501+ return false ;
1502+ }
1503+ }
1504+
1505+ public async Task ValidateAllAccountsAsync ( )
1506+ {
1507+ const string LOG_IDENT_VALIDATE_ALL = $ "{ LOG_IDENT } ::ValidateAllAccounts";
1508+
1509+ App . Logger . WriteLine ( LOG_IDENT_VALIDATE_ALL , "Starting validation of all accounts..." ) ;
1510+
1511+ var invalidAccounts = new List < AltAccount > ( ) ;
1512+
1513+ foreach ( var account in _accounts . ToList ( ) )
1514+ {
1515+ bool isValid = await ValidateAccountAsync ( account ) ;
1516+
1517+ if ( ! isValid )
1518+ {
1519+ invalidAccounts . Add ( account ) ;
1520+ App . Logger . WriteLine ( LOG_IDENT_VALIDATE_ALL , $ "Account { account . Username } is invalid and will be removed") ;
1521+ }
1522+ else
1523+ {
1524+ App . Logger . WriteLine ( LOG_IDENT_VALIDATE_ALL , $ "Account { account . Username } is valid, continuing to next account") ;
1525+ }
1526+ }
1527+
1528+ foreach ( var invalidAccount in invalidAccounts )
1529+ {
1530+ Application . Current . Dispatcher . Invoke ( ( ) =>
1531+ {
1532+ var result = Frontend . ShowMessageBox (
1533+ $ "Account '{ invalidAccount . DisplayName } ' (@{ invalidAccount . Username } ) is no longer valid and will be removed.\n \n Reason: Cookie expired or invalid",
1534+ MessageBoxImage . Warning ,
1535+ MessageBoxButton . OK
1536+ ) ;
1537+
1538+ RemoveAccount ( invalidAccount ) ;
1539+ } ) ;
1540+ }
1541+
1542+ if ( invalidAccounts . Count > 0 )
1543+ {
1544+ App . Logger . WriteLine ( LOG_IDENT_VALIDATE_ALL , $ "Removed { invalidAccounts . Count } invalid accounts") ;
1545+
1546+ if ( ActiveAccount != null && invalidAccounts . Any ( acc => acc . UserId == ActiveAccount . UserId ) )
1547+ {
1548+ ActiveAccount = _accounts . FirstOrDefault ( ) ;
1549+ ActiveAccountChanged ? . Invoke ( ActiveAccount ) ;
1550+ }
1551+
1552+ SaveAccounts ( ) ;
1553+ }
1554+ else
1555+ {
1556+ App . Logger . WriteLine ( LOG_IDENT_VALIDATE_ALL , "All accounts are valid" ) ;
1557+ }
1558+ }
14611559 }
14621560}
0 commit comments