Merged develop in

This commit is contained in:
Joseph Milazzo 2025-04-15 13:28:53 -05:00
commit 7c692a1b46
580 changed files with 21233 additions and 9031 deletions

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
@ -409,6 +410,12 @@ public class ScrobblingService : IScrobblingService
Format = series.Library.Type.ConvertToPlusMediaFormat(series.Format),
};
if (evt.VolumeNumber is Parser.SpecialVolumeNumber)
{
// We don't process Specials because they will never match on AniList
return;
}
_unitOfWork.ScrobbleRepository.Attach(evt);
await _unitOfWork.CommitAsync();
_logger.LogDebug("Added Scrobbling Read update on {SeriesName} - Volume: {VolumeNumber} Chapter: {ChapterNumber} for User: {UserId}", series.Name, evt.VolumeNumber, evt.ChapterNumber, userId);
@ -620,8 +627,15 @@ public class ScrobblingService : IScrobblingService
{
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(userId);
if (user == null || string.IsNullOrEmpty(user.AniListAccessToken)) return;
if (user.HasRunScrobbleEventGeneration)
{
_logger.LogWarning("User {UserName} has already run scrobble event generation, Kavita will not generate more events", user.UserName);
return;
}
}
var libAllowsScrobbling = (await _unitOfWork.LibraryRepository.GetLibrariesAsync())
.ToDictionary(lib => lib.Id, lib => lib.AllowScrobbling);
@ -663,6 +677,14 @@ public class ScrobblingService : IScrobblingService
if (series.PagesRead <= 0) continue; // Since we only scrobble when things are higher, we can
await ScrobbleReadingUpdate(uId, series.Id);
}
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(uId);
if (user != null)
{
user.HasRunScrobbleEventGeneration = true;
user.ScrobbleEventGenerationRan = DateTime.UtcNow;
await _unitOfWork.CommitAsync();
}
}
}
@ -952,6 +974,7 @@ public class ScrobblingService : IScrobblingService
// Recalculate the highest volume/chapter
foreach (var readEvt in readEvents)
{
// Note: this causes skewing in the scrobble history because it makes it look like there are duplicate events
readEvt.VolumeNumber =
(int) await _unitOfWork.AppUserProgressRepository.GetHighestFullyReadVolumeForSeries(readEvt.SeriesId,
readEvt.AppUser.Id);
@ -1023,7 +1046,7 @@ public class ScrobblingService : IScrobblingService
_unitOfWork.ScrobbleRepository.Attach(new ScrobbleError()
{
Comment = "AniList token has expired and needs rotating. Scrobbling wont work until then",
Details = $"User: {evt.AppUser.UserName}",
Details = $"User: {evt.AppUser.UserName}, Expired: {TokenService.GetTokenExpiry(evt.AppUser.AniListAccessToken)}",
LibraryId = evt.LibraryId,
SeriesId = evt.SeriesId
});
@ -1120,33 +1143,22 @@ public class ScrobblingService : IScrobblingService
private static bool CanProcessScrobbleEvent(ScrobbleEvent readEvent)
{
var userProviders = GetUserProviders(readEvent.AppUser);
if (readEvent.Series.Library.Type == LibraryType.Manga && MangaProviders.Intersect(userProviders).Any())
switch (readEvent.Series.Library.Type)
{
return true;
case LibraryType.Manga when MangaProviders.Intersect(userProviders).Any():
case LibraryType.Comic when
ComicProviders.Intersect(userProviders).Any():
case LibraryType.Book when
BookProviders.Intersect(userProviders).Any():
case LibraryType.LightNovel when
LightNovelProviders.Intersect(userProviders).Any():
return true;
default:
return false;
}
if (readEvent.Series.Library.Type == LibraryType.Comic &&
ComicProviders.Intersect(userProviders).Any())
{
return true;
}
if (readEvent.Series.Library.Type == LibraryType.Book &&
BookProviders.Intersect(userProviders).Any())
{
return true;
}
if (readEvent.Series.Library.Type == LibraryType.LightNovel &&
LightNovelProviders.Intersect(userProviders).Any())
{
return true;
}
return false;
}
private static IList<ScrobbleProvider> GetUserProviders(AppUser appUser)
private static List<ScrobbleProvider> GetUserProviders(AppUser appUser)
{
var providers = new List<ScrobbleProvider>();
if (!string.IsNullOrEmpty(appUser.AniListAccessToken)) providers.Add(ScrobbleProvider.AniList);
@ -1170,18 +1182,18 @@ public class ScrobblingService : IScrobblingService
var value = tokens[index];
if (typeof(T) == typeof(int?))
{
if (int.TryParse(value, out var intValue))
if (int.TryParse(value, CultureInfo.InvariantCulture, out var intValue))
return (T)(object)intValue;
}
else if (typeof(T) == typeof(int))
{
if (int.TryParse(value, out var intValue))
if (int.TryParse(value, CultureInfo.InvariantCulture, out var intValue))
return (T)(object)intValue;
return default;
}
else if (typeof(T) == typeof(long?))
{
if (long.TryParse(value, out var longValue))
if (long.TryParse(value, CultureInfo.InvariantCulture, out var longValue))
return (T)(object)longValue;
}
else if (typeof(T) == typeof(string))
@ -1190,7 +1202,7 @@ public class ScrobblingService : IScrobblingService
}
}
return default(T?);
return default;
}
/// <summary>
@ -1223,8 +1235,7 @@ public class ScrobblingService : IScrobblingService
public static string CreateUrl(string url, long? id)
{
if (id is null or 0) return string.Empty;
return $"{url}{id}/";
return id is null or 0 ? string.Empty : $"{url}{id}/";
}