diff --git a/API/Controllers/ReaderController.cs b/API/Controllers/ReaderController.cs index 746d3a6ce..2e0bc0e9d 100644 --- a/API/Controllers/ReaderController.cs +++ b/API/Controllers/ReaderController.cs @@ -106,8 +106,9 @@ namespace API.Controllers { foreach (var chapter in volume.Chapters) { - var userProgress = user.Progresses.SingleOrDefault(x => x.ChapterId == chapter.Id && x.AppUserId == user.Id); - if (userProgress == null) // I need to get all chapters and generate new user progresses for them? + var userProgress = GetUserProgressForChapter(user, chapter); + + if (userProgress == null) { user.Progresses.Add(new AppUserProgress { @@ -137,6 +138,31 @@ namespace API.Controllers return BadRequest("There was an issue saving progress"); } + private static AppUserProgress GetUserProgressForChapter(AppUser user, Chapter chapter) + { + AppUserProgress userProgress = null; + try + { + userProgress = + user.Progresses.SingleOrDefault(x => x.ChapterId == chapter.Id && x.AppUserId == user.Id); + } + catch (Exception) + { + // There is a very rare chance that user progress will duplicate current row. If that happens delete one with less pages + var progresses = user.Progresses.Where(x => x.ChapterId == chapter.Id && x.AppUserId == user.Id).ToList(); + if (progresses.Count > 1) + { + user.Progresses = new List() + { + user.Progresses.First() + }; + userProgress = user.Progresses.First(); + } + } + + return userProgress; + } + [HttpPost("mark-unread")] public async Task MarkUnread(MarkReadDto markReadDto) { @@ -147,23 +173,12 @@ namespace API.Controllers { foreach (var chapter in volume.Chapters) { - var userProgress = user.Progresses.SingleOrDefault(x => x.ChapterId == chapter.Id && x.AppUserId == user.Id); - if (userProgress == null) - { - user.Progresses.Add(new AppUserProgress - { - PagesRead = 0, - VolumeId = volume.Id, - SeriesId = markReadDto.SeriesId, - ChapterId = chapter.Id - }); - } - else - { - userProgress.PagesRead = 0; - userProgress.SeriesId = markReadDto.SeriesId; - userProgress.VolumeId = volume.Id; - } + var userProgress = GetUserProgressForChapter(user, chapter); + + if (userProgress == null) continue; + userProgress.PagesRead = 0; + userProgress.SeriesId = markReadDto.SeriesId; + userProgress.VolumeId = volume.Id; } } diff --git a/API/Data/Seed.cs b/API/Data/Seed.cs index 7185b403d..838277931 100644 --- a/API/Data/Seed.cs +++ b/API/Data/Seed.cs @@ -9,6 +9,7 @@ using API.Entities.Enums; using API.Services; using Kavita.Common; using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; namespace API.Data { @@ -69,5 +70,21 @@ namespace API.Data await context.SaveChangesAsync(); } + + public static async Task SeedSeriesMetadata(DataContext context) + { + await context.Database.EnsureCreatedAsync(); + + context.Database.EnsureCreated(); + var series = await context.Series + .Include(s => s.Metadata).ToListAsync(); + + foreach (var s in series) + { + s.Metadata ??= new SeriesMetadata(); + } + + await context.SaveChangesAsync(); + } } } diff --git a/Dockerfile.alpine b/Dockerfile.alpine new file mode 100644 index 000000000..faacfa823 --- /dev/null +++ b/Dockerfile.alpine @@ -0,0 +1,28 @@ +#This Dockerfile is for the musl alpine build of Kavita. +FROM alpine:latest + +MAINTAINER Chris P + +#Installs the needed dependencies +RUN apk update && apk add --no-cache wget curl pwgen icu-dev bash + +#Downloads Kavita, unzips and moves the folders to where they need to be +RUN wget https://github.com/Kareadita/Kavita/releases/download/v0.3.7/kavita-linux-musl-x64.tar.gz \ + && tar -xzf kavita*.tar.gz \ + && mv Kavita/ /kavita/ \ + && rm kavita*.gz \ + && chmod +x /kavita/Kavita + +#Creates the needed folders +RUN mkdir /manga /kavita/data /kavita/temp /kavita/cache + +RUN sed -i 's/Data source=kavita.db/Data source=data\/kavita.db/g' /kavita/appsettings.json + +COPY entrypoint.sh /entrypoint.sh + +EXPOSE 5000 + +WORKDIR /kavita + +ENTRYPOINT ["/bin/bash"] +CMD ["/entrypoint.sh"] diff --git a/Dockerfile.arm b/Dockerfile.arm new file mode 100644 index 000000000..e28430a38 --- /dev/null +++ b/Dockerfile.arm @@ -0,0 +1,27 @@ +#This Dockerfile pulls the latest git commit and builds Kavita from source + +#Production image +FROM ubuntu:focal + +#Move the output files to where they need to be +COPY Kavita /kavita + +#Installs program dependencies +RUN apt-get update \ + && apt-get install -y libicu-dev libssl1.1 pwgen \ + && rm -rf /var/lib/apt/lists/* + +#Creates the manga storage directory +RUN mkdir /kavita/data + +RUN cp /kavita/appsettings.Development.json /kavita/appsettings.json \ + && sed -i 's/Data source=kavita.db/Data source=data\/kavita.db/g' /kavita/appsettings.json + +COPY entrypoint.sh /entrypoint.sh + +EXPOSE 5000 + +WORKDIR /kavita + +ENTRYPOINT ["/bin/bash"] +CMD ["/entrypoint.sh"] diff --git a/Kavita.Common/Kavita.Common.csproj b/Kavita.Common/Kavita.Common.csproj index d5b17196c..85e968d75 100644 --- a/Kavita.Common/Kavita.Common.csproj +++ b/Kavita.Common/Kavita.Common.csproj @@ -4,7 +4,7 @@ net5.0 kavitareader.com Kavita - 0.4.3.0 + 0.4.3.1 en diff --git a/build_target.sh b/build_target.sh new file mode 100644 index 000000000..56c54ba79 --- /dev/null +++ b/build_target.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +mkdir Projects + +cd Projects + +git clone https://github.com/Kareadita/Kavita.git +git clone https://github.com/Kareadita/Kavita-webui.git + +cd Kavita +chmod +x build.sh + +#Builds program based on the target platform + +if [ "$TARGETPLATFORM" == "linux/amd64" ] +then + ./build.sh linux-x64 + mv /Projects/Kavita/_output/linux-x64 /Projects/Kavita/_output/build +elif [ "$TARGETPLATFORM" == "linux/arm/v7" ] +then + ./build.sh linux-arm + mv /Projects/Kavita/_output/linux-arm /Projects/Kavita/_output/build +elif [ "$TARGETPLATFORM" == "linux/arm64" ] +then + ./build.sh linux-arm64 + mv /Projects/Kavita/_output/linux-arm64 /Projects/Kavita/_output/build +fi