More efficient session validity checks. Jellyfin session detection.
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using Cinema.Webshare;
|
||||
|
||||
@@ -17,6 +15,7 @@ public sealed class Session
|
||||
private static readonly Uri WebshareApiUri = LinkGenerator.WebshareApiUri;
|
||||
private static readonly TimeSpan InitialLoginBackoff = new TimeSpan(4 * TimeSpan.TicksPerSecond);
|
||||
private static readonly TimeSpan MaxLoginBackoff = new TimeSpan(8 * TimeSpan.TicksPerMinute);
|
||||
private static readonly TimeSpan TokenValidPeriod = new TimeSpan(120 * TimeSpan.TicksPerSecond);
|
||||
|
||||
private readonly string _userName;
|
||||
private readonly string _password;
|
||||
@@ -26,6 +25,7 @@ public sealed class Session
|
||||
|
||||
private DateTime _nextLoginTrial;
|
||||
private TimeSpan _nextLoginBackoff;
|
||||
private DateTime _nextValidTrial;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a session from credentials and optionally a possibly live token.
|
||||
@@ -74,52 +74,62 @@ public sealed class Session
|
||||
/// <returns>True if the local instance data are valid. -or- False otherwise.</returns>
|
||||
private async Task<bool> EnsureValidAsync(CancellationToken cancel)
|
||||
{
|
||||
if (!await RefreshUserDataAsync(cancel))
|
||||
DateTime now = DateTime.Now;
|
||||
|
||||
if (_token != null && (_isVip ?? false) && now < _nextValidTrial)
|
||||
// Fast track positive check
|
||||
return true;
|
||||
|
||||
if (await RefreshUserDataAsync(cancel) && (_isVip ?? false))
|
||||
{
|
||||
DateTime now = DateTime.Now;
|
||||
if (now > _nextLoginTrial)
|
||||
// Valid VIP (slower with API check)
|
||||
_nextValidTrial = now + TokenValidPeriod;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (now > _nextLoginTrial)
|
||||
{
|
||||
// Try to log in again
|
||||
string? token;
|
||||
try
|
||||
{
|
||||
// Try to login again
|
||||
string? token;
|
||||
try
|
||||
{
|
||||
string? salt;
|
||||
if ((salt = await GetSaltAsync(_userName, cancel)) == null
|
||||
|| (token = await GetTokenAsync(_userName, _password.HashPassword(salt), cancel)) == null)
|
||||
{
|
||||
// Login failed
|
||||
token = null;
|
||||
}
|
||||
}
|
||||
catch
|
||||
string? salt;
|
||||
if ((salt = await GetSaltAsync(_userName, cancel)) == null
|
||||
|| (token = await GetTokenAsync(_userName, _password.HashPassword(salt), cancel)) == null)
|
||||
{
|
||||
// Login failed
|
||||
token = null;
|
||||
}
|
||||
|
||||
if (token != null)
|
||||
{
|
||||
_nextLoginBackoff = InitialLoginBackoff;
|
||||
_token = token;
|
||||
if (await RefreshUserDataAsync(cancel))
|
||||
return true;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
TimeSpan nextBackoff = new TimeSpan(2 * _nextLoginBackoff.Ticks);
|
||||
if (nextBackoff > MaxLoginBackoff)
|
||||
nextBackoff = MaxLoginBackoff;
|
||||
_nextLoginTrial = now + nextBackoff;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
token = null;
|
||||
}
|
||||
|
||||
_token = null;
|
||||
_isVip = null;
|
||||
_vipDaysLeft = null;
|
||||
return false;
|
||||
if (token != null && await RefreshUserDataAsync(cancel) && (_isVip ?? false))
|
||||
{
|
||||
// Valid token with VIP
|
||||
_nextLoginBackoff = InitialLoginBackoff;
|
||||
_token = token;
|
||||
_nextValidTrial = now + TokenValidPeriod;
|
||||
return true;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid, no token or not VIP ...
|
||||
TimeSpan nextBackoff = new TimeSpan(2 * _nextLoginBackoff.Ticks);
|
||||
if (nextBackoff > MaxLoginBackoff)
|
||||
nextBackoff = MaxLoginBackoff;
|
||||
_nextLoginTrial = now + nextBackoff;
|
||||
}
|
||||
}
|
||||
else
|
||||
return true;
|
||||
|
||||
// ... still invalid, no token or not VIP
|
||||
_token = null;
|
||||
_isVip = null;
|
||||
_vipDaysLeft = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user