mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-09 03:04:19 -04:00
Sentry Integration (#212)
* Fixed a parsing case * Integrated Sentry into the solution with anonymous users. Fixed some parsing issues and added BuildInfo into a separate project. * Fixed some bad parser regex * Removed bad reference to NLog * Cleanup of some files not needed
This commit is contained in:
parent
6fc5e535df
commit
c8adaee3eb
33
.github/workflows/nightly-docker.yml
vendored
Normal file
33
.github/workflows/nightly-docker.yml
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
-
|
||||
name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
-
|
||||
name: Build and push
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
push: true
|
||||
tags: user/app:latest
|
||||
-
|
||||
name: Image digest
|
||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
@ -61,7 +61,6 @@ namespace API.Tests.Parser
|
||||
[InlineData("[Hidoi]_Amaenaideyo_MS_vol01_chp02.rar", "1")]
|
||||
[InlineData("NEEDLESS_Vol.4_-_Simeon_6_v2_[SugoiSugoi].rar", "4")]
|
||||
[InlineData("Okusama wa Shougakusei c003 (v01) [bokuwaNEET]", "1")]
|
||||
|
||||
public void ParseVolumeTest(string filename, string expected)
|
||||
{
|
||||
Assert.Equal(expected, API.Parser.Parser.ParseVolume(filename));
|
||||
@ -137,6 +136,7 @@ namespace API.Tests.Parser
|
||||
[InlineData("Okusama wa Shougakusei c003 (v01) [bokuwaNEET]", "Okusama wa Shougakusei")]
|
||||
[InlineData("VanDread-v01-c001[MD].zip", "VanDread")]
|
||||
[InlineData("Momo The Blood Taker - Chapter 027 Violent Emotion.cbz", "Momo The Blood Taker")]
|
||||
[InlineData("Green Worldz - Chapter 112 Final Chapter (End).cbz", "Green Worldz")]
|
||||
public void ParseSeriesTest(string filename, string expected)
|
||||
{
|
||||
Assert.Equal(expected, API.Parser.Parser.ParseSeries(filename));
|
||||
@ -225,6 +225,7 @@ namespace API.Tests.Parser
|
||||
[InlineData("Corpse Party -The Anthology- Sachikos game of love Hysteric Birthday 2U Extra Chapter", true)]
|
||||
[InlineData("Ani-Hina Art Collection.cbz", true)]
|
||||
[InlineData("Gifting The Wonderful World With Blessings! - 3 Side Stories [yuNS][Unknown]", true)]
|
||||
[InlineData("Yuki Merry - 4-Komga Anthology", true)]
|
||||
public void ParseMangaSpecialTest(string input, bool expected)
|
||||
{
|
||||
Assert.Equal(expected, !string.IsNullOrEmpty(API.Parser.Parser.ParseMangaSpecial(input)));
|
||||
|
@ -12,6 +12,23 @@
|
||||
<ApplicationIcon>../favicon.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Set the Product and Version info for our own projects -->
|
||||
<PropertyGroup>
|
||||
<Product>Kavita</Product>
|
||||
<Company>kareadita.github.io</Company>
|
||||
<Copyright>Copyright 2020-$([System.DateTime]::Now.ToString('yyyy')) kareadita.github.io (GNU General Public v3)</Copyright>
|
||||
|
||||
<!-- Should be replaced by CI -->
|
||||
<AssemblyVersion>0.4.1</AssemblyVersion>
|
||||
<AssemblyConfiguration>$(Configuration)-dev</AssemblyConfiguration>
|
||||
|
||||
<GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
|
||||
<GenerateAssemblyInformationalVersionAttribute>false</GenerateAssemblyInformationalVersionAttribute>
|
||||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
||||
|
||||
<Deterministic Condition="$(AssemblyVersion.EndsWith('*'))">False</Deterministic>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.1.1" />
|
||||
<PackageReference Include="ExCSS" Version="4.1.0" />
|
||||
@ -33,6 +50,7 @@
|
||||
<PackageReference Include="NetVips" Version="2.0.0" />
|
||||
<PackageReference Include="NetVips.Native" Version="8.10.6" />
|
||||
<PackageReference Include="NReco.Logging.File" Version="1.1.1" />
|
||||
<PackageReference Include="Sentry.AspNetCore" Version="3.3.4" />
|
||||
<PackageReference Include="SharpCompress" Version="0.28.1" />
|
||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="8.20.0.28934">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
@ -65,4 +83,8 @@
|
||||
<_ContentIncludedByDefault Remove="logs\kavita.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Kavita.Common\Kavita.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using API.DTOs;
|
||||
using API.Entities;
|
||||
@ -148,6 +149,7 @@ namespace API.Controllers
|
||||
public async Task<ActionResult<IEnumerable<SeriesDto>>> GetRecentlyAdded(int libraryId = 0, int limit = 20)
|
||||
{
|
||||
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(User.GetUsername());
|
||||
if (user == null) return Ok(Array.Empty<SeriesDto>());
|
||||
return Ok(await _unitOfWork.SeriesRepository.GetRecentlyAdded(user.Id, libraryId, limit));
|
||||
}
|
||||
|
||||
@ -155,6 +157,7 @@ namespace API.Controllers
|
||||
public async Task<ActionResult<IEnumerable<SeriesDto>>> GetInProgress(int libraryId = 0, int limit = 20)
|
||||
{
|
||||
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(User.GetUsername());
|
||||
if (user == null) return Ok(Array.Empty<SeriesDto>());
|
||||
return Ok(await _unitOfWork.SeriesRepository.GetInProgress(user.Id, libraryId, limit));
|
||||
}
|
||||
|
||||
|
@ -1,20 +1,40 @@
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
|
||||
WORKDIR /app
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
#This Dockerfile pulls the latest git commit and builds Kavita from source
|
||||
FROM mcr.microsoft.com/dotnet/sdk:5.0-focal AS builder
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
|
||||
WORKDIR /src
|
||||
COPY ["API/API.csproj", "API/"]
|
||||
RUN dotnet restore "API/API.csproj"
|
||||
COPY . .
|
||||
WORKDIR "/src/API"
|
||||
RUN dotnet build "API.csproj" -c Release -o /app/build
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ARG TARGETPLATFORM
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish "API.csproj" -c Release -o /app/publish
|
||||
#Installs nodejs and npm
|
||||
RUN curl -fsSL https://deb.nodesource.com/setup_14.x | bash - \
|
||||
&& apt-get install -y nodejs \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app/publish .
|
||||
ENTRYPOINT ["dotnet", "API.dll"]
|
||||
#Builds app based on platform
|
||||
COPY build_target.sh /build_target.sh
|
||||
RUN /build_target.sh
|
||||
|
||||
#Production image
|
||||
FROM ubuntu:focal
|
||||
|
||||
#Move the output files to where they need to be
|
||||
COPY --from=builder /Projects/Kavita/_output/build/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 /manga /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"]
|
@ -92,7 +92,7 @@ namespace API.Parser
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
// Momo The Blood Taker - Chapter 027 Violent Emotion.cbz
|
||||
new Regex(
|
||||
@"(?<Series>.*) (\b|_|-)(?:chapter)",
|
||||
@"(?<Series>.*)(\b|_|-|\s)(?:chapter)(\b|_|-|\s)\d",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
// Historys Strongest Disciple Kenichi_v11_c90-98.zip, Killing Bites Vol. 0001 Ch. 0001 - Galactica Scanlations (gb)
|
||||
new Regex(
|
||||
@ -101,7 +101,7 @@ namespace API.Parser
|
||||
//Ichinensei_ni_Nacchattara_v01_ch01_[Taruby]_v1.1.zip must be before [Suihei Kiki]_Kasumi_Otoko_no_Ko_[Taruby]_v1.1.zip
|
||||
// due to duplicate version identifiers in file.
|
||||
new Regex(
|
||||
@"(?<Series>.*)(v|s)\d+(-\d+)?(_| )",
|
||||
@"(?<Series>.*)(v|s)\d+(-\d+)?(_|\s)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
//[Suihei Kiki]_Kasumi_Otoko_no_Ko_[Taruby]_v1.1.zip
|
||||
new Regex(
|
||||
@ -121,7 +121,7 @@ namespace API.Parser
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
// Tonikaku Kawaii (Ch 59-67) (Ongoing)
|
||||
new Regex(
|
||||
@"(?<Series>.*)( |_)\((c |ch |chapter )",
|
||||
@"(?<Series>.*)(\s|_)\((c\s|ch\s|chapter\s)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
// Black Bullet (This is very loose, keep towards bottom)
|
||||
new Regex(
|
||||
@ -364,7 +364,7 @@ namespace API.Parser
|
||||
{
|
||||
// All Keywords, does not account for checking if contains volume/chapter identification. Parser.Parse() will handle.
|
||||
new Regex(
|
||||
@"(?<Special>Specials?|OneShot|One\-Shot|Omake|Extra( Chapter)?|Art Collection|Side( |_)Stories)",
|
||||
@"(?<Special>Specials?|OneShot|One\-Shot|Omake|Extra( Chapter)?|Art Collection|Side( |_)Stories|(?<!The\s)Anthology)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,11 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using API.Data;
|
||||
using API.Entities;
|
||||
using Kavita.Common;
|
||||
using Kavita.Common.EnvironmentInfo;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
@ -9,18 +13,22 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sentry;
|
||||
|
||||
namespace API
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
private static readonly int HttpPort = 5000;
|
||||
|
||||
protected Program()
|
||||
{
|
||||
}
|
||||
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
// Before anything, check if JWT has been generated properly or if user still has default
|
||||
|
||||
var host = CreateHostBuilder(args).Build();
|
||||
|
||||
using var scope = host.Services.CreateScope();
|
||||
@ -55,6 +63,36 @@ namespace API
|
||||
options.Protocols = HttpProtocols.Http1AndHttp2;
|
||||
});
|
||||
});
|
||||
|
||||
webBuilder.UseSentry(options =>
|
||||
{
|
||||
options.Dsn = "https://40f4e7b49c094172a6f99d61efb2740f@o641015.ingest.sentry.io/5757423";
|
||||
options.MaxBreadcrumbs = 200;
|
||||
options.AttachStacktrace = true;
|
||||
options.Debug = false;
|
||||
options.SendDefaultPii = false;
|
||||
options.DiagnosticLevel = SentryLevel.Debug;
|
||||
options.ShutdownTimeout = TimeSpan.FromSeconds(5);
|
||||
options.Release = BuildInfo.Version.ToString();
|
||||
options.AddExceptionFilterForType<OutOfMemoryException>();
|
||||
options.AddExceptionFilterForType<NetVips.VipsException>();
|
||||
options.AddExceptionFilterForType<InvalidDataException>();
|
||||
options.ConfigureScope(scope =>
|
||||
{
|
||||
scope.User = new User()
|
||||
{
|
||||
Id = HashUtil.AnonymousToken()
|
||||
};
|
||||
scope.Contexts.App.Name = BuildInfo.AppName;
|
||||
scope.Contexts.App.Version = BuildInfo.Version.ToString();
|
||||
scope.Contexts.App.StartTime = DateTime.UtcNow;
|
||||
scope.Contexts.App.Hash = HashUtil.AnonymousToken();
|
||||
scope.Contexts.App.Build = BuildInfo.Release;
|
||||
scope.SetTag("culture", Thread.CurrentThread.CurrentCulture.Name);
|
||||
scope.SetTag("branch", BuildInfo.Branch);
|
||||
});
|
||||
|
||||
});
|
||||
webBuilder.UseStartup<Startup>();
|
||||
});
|
||||
}
|
||||
|
@ -1,12 +1,14 @@
|
||||
using System;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using API.Extensions;
|
||||
using API.Interfaces;
|
||||
using API.Middleware;
|
||||
using API.Services;
|
||||
using Hangfire;
|
||||
using Hangfire.MemoryStorage;
|
||||
using Kavita.Common.EnvironmentInfo;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
@ -131,7 +133,7 @@ namespace API
|
||||
applicationLifetime.ApplicationStopping.Register(OnShutdown);
|
||||
applicationLifetime.ApplicationStarted.Register(() =>
|
||||
{
|
||||
Console.WriteLine("Kavita - v0.4.1");
|
||||
Console.WriteLine("Kavita - v" + BuildInfo.Version);
|
||||
});
|
||||
|
||||
// Any services that should be bootstrapped go here
|
||||
@ -140,10 +142,10 @@ namespace API
|
||||
|
||||
private void OnShutdown()
|
||||
{
|
||||
Console.WriteLine("Server is shutting down. Going to dispose Hangfire");
|
||||
//this code is called when the application stops
|
||||
Console.WriteLine("Server is shutting down. Please allow a few seconds to stop any background jobs...");
|
||||
TaskScheduler.Client.Dispose();
|
||||
System.Threading.Thread.Sleep(1000);
|
||||
Console.WriteLine("You may now close the application window.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
56
Kavita.Common/EnvironmentInfo/BuildInfo.cs
Normal file
56
Kavita.Common/EnvironmentInfo/BuildInfo.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Kavita.Common.EnvironmentInfo
|
||||
{
|
||||
public static class BuildInfo
|
||||
{
|
||||
static BuildInfo()
|
||||
{
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
|
||||
Version = assembly.GetName().Version;
|
||||
|
||||
var attributes = assembly.GetCustomAttributes(true);
|
||||
|
||||
Branch = "unknown";
|
||||
|
||||
var config = attributes.OfType<AssemblyConfigurationAttribute>().FirstOrDefault();
|
||||
if (config != null)
|
||||
{
|
||||
Branch = config.Configuration;
|
||||
}
|
||||
|
||||
Release = $"{Version}-{Branch}";
|
||||
}
|
||||
|
||||
public static string AppName { get; } = "Kavita";
|
||||
|
||||
public static Version Version { get; }
|
||||
public static string Branch { get; }
|
||||
public static string Release { get; }
|
||||
|
||||
public static DateTime BuildDateTime
|
||||
{
|
||||
get
|
||||
{
|
||||
var fileLocation = Assembly.GetCallingAssembly().Location;
|
||||
return new FileInfo(fileLocation).LastWriteTimeUtc;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsDebug
|
||||
{
|
||||
get
|
||||
{
|
||||
#if DEBUG
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
148
Kavita.Common/EnvironmentInfo/IOsInfo.cs
Normal file
148
Kavita.Common/EnvironmentInfo/IOsInfo.cs
Normal file
@ -0,0 +1,148 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Kavita.Common.EnvironmentInfo
|
||||
{
|
||||
public class OsInfo : IOsInfo
|
||||
{
|
||||
public static Os Os { get; }
|
||||
|
||||
public static bool IsNotWindows => !IsWindows;
|
||||
public static bool IsLinux => Os == Os.Linux || Os == Os.LinuxMusl || Os == Os.Bsd;
|
||||
public static bool IsOsx => Os == Os.Osx;
|
||||
public static bool IsWindows => Os == Os.Windows;
|
||||
|
||||
// this needs to not be static so we can mock it
|
||||
public bool IsDocker { get; }
|
||||
|
||||
public string Version { get; }
|
||||
public string Name { get; }
|
||||
public string FullName { get; }
|
||||
|
||||
static OsInfo()
|
||||
{
|
||||
var platform = Environment.OSVersion.Platform;
|
||||
|
||||
switch (platform)
|
||||
{
|
||||
case PlatformID.Win32NT:
|
||||
{
|
||||
Os = Os.Windows;
|
||||
break;
|
||||
}
|
||||
|
||||
case PlatformID.MacOSX:
|
||||
case PlatformID.Unix:
|
||||
{
|
||||
Os = GetPosixFlavour();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public OsInfo(IEnumerable<IOsVersionAdapter> versionAdapters)
|
||||
{
|
||||
OsVersionModel osInfo = null;
|
||||
|
||||
foreach (var osVersionAdapter in versionAdapters.Where(c => c.Enabled))
|
||||
{
|
||||
try
|
||||
{
|
||||
osInfo = osVersionAdapter.Read();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Couldn't get OS Version info: " + e.Message);
|
||||
}
|
||||
|
||||
if (osInfo != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (osInfo != null)
|
||||
{
|
||||
Name = osInfo.Name;
|
||||
Version = osInfo.Version;
|
||||
FullName = osInfo.FullName;
|
||||
}
|
||||
else
|
||||
{
|
||||
Name = Os.ToString();
|
||||
FullName = Name;
|
||||
}
|
||||
|
||||
if (IsLinux && File.Exists("/proc/1/cgroup") && File.ReadAllText("/proc/1/cgroup").Contains("/docker/"))
|
||||
{
|
||||
IsDocker = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static Os GetPosixFlavour()
|
||||
{
|
||||
var output = RunAndCapture("uname", "-s");
|
||||
|
||||
if (output.StartsWith("Darwin"))
|
||||
{
|
||||
return Os.Osx;
|
||||
}
|
||||
else if (output.Contains("BSD"))
|
||||
{
|
||||
return Os.Bsd;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if ISMUSL
|
||||
return Os.LinuxMusl;
|
||||
#else
|
||||
return Os.Linux;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private static string RunAndCapture(string filename, string args)
|
||||
{
|
||||
var p = new Process
|
||||
{
|
||||
StartInfo =
|
||||
{
|
||||
FileName = filename,
|
||||
Arguments = args,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardOutput = true
|
||||
}
|
||||
};
|
||||
|
||||
p.Start();
|
||||
|
||||
// To avoid deadlocks, always read the output stream first and then wait.
|
||||
var output = p.StandardOutput.ReadToEnd();
|
||||
p.WaitForExit(1000);
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IOsInfo
|
||||
{
|
||||
string Version { get; }
|
||||
string Name { get; }
|
||||
string FullName { get; }
|
||||
|
||||
bool IsDocker { get; }
|
||||
}
|
||||
|
||||
public enum Os
|
||||
{
|
||||
Windows,
|
||||
Linux,
|
||||
Osx,
|
||||
LinuxMusl,
|
||||
Bsd
|
||||
}
|
||||
}
|
8
Kavita.Common/EnvironmentInfo/IOsVersionAdapter.cs
Normal file
8
Kavita.Common/EnvironmentInfo/IOsVersionAdapter.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace Kavita.Common.EnvironmentInfo
|
||||
{
|
||||
public interface IOsVersionAdapter
|
||||
{
|
||||
bool Enabled { get; }
|
||||
OsVersionModel Read();
|
||||
}
|
||||
}
|
27
Kavita.Common/EnvironmentInfo/OsVersionModel.cs
Normal file
27
Kavita.Common/EnvironmentInfo/OsVersionModel.cs
Normal file
@ -0,0 +1,27 @@
|
||||
namespace Kavita.Common.EnvironmentInfo
|
||||
{
|
||||
public class OsVersionModel
|
||||
{
|
||||
public OsVersionModel(string name, string version, string fullName = null)
|
||||
{
|
||||
Name = Trim(name);
|
||||
Version = Trim(version);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(fullName))
|
||||
{
|
||||
fullName = $"{Name} {Version}";
|
||||
}
|
||||
|
||||
FullName = Trim(fullName);
|
||||
}
|
||||
|
||||
private static string Trim(string source)
|
||||
{
|
||||
return source.Trim().Trim('"', '\'');
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
public string FullName { get; }
|
||||
public string Version { get; }
|
||||
}
|
||||
}
|
37
Kavita.Common/HashUtil.cs
Normal file
37
Kavita.Common/HashUtil.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Kavita.Common
|
||||
{
|
||||
public static class HashUtil
|
||||
{
|
||||
public static string CalculateCrc(string input)
|
||||
{
|
||||
uint mCrc = 0xffffffff;
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(input);
|
||||
foreach (byte myByte in bytes)
|
||||
{
|
||||
mCrc ^= (uint)myByte << 24;
|
||||
for (var i = 0; i < 8; i++)
|
||||
{
|
||||
if ((Convert.ToUInt32(mCrc) & 0x80000000) == 0x80000000)
|
||||
{
|
||||
mCrc = (mCrc << 1) ^ 0x04C11DB7;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCrc <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $"{mCrc:x8}";
|
||||
}
|
||||
|
||||
public static string AnonymousToken()
|
||||
{
|
||||
var seed = $"{Environment.ProcessorCount}_{Environment.OSVersion.Platform}_{Environment.MachineName}_{Environment.UserName}";
|
||||
return HashUtil.CalculateCrc(seed);
|
||||
}
|
||||
}
|
||||
}
|
24
Kavita.Common/Kavita.Common.csproj
Normal file
24
Kavita.Common/Kavita.Common.csproj
Normal file
@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<Company>kareadita.github.io</Company>
|
||||
<Product>Kavita</Product>
|
||||
<AssemblyVersion>0.4.1</AssemblyVersion>
|
||||
<NeutralLanguage>en</NeutralLanguage>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Sentry" Version="3.3.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="JetBrains.ReSharper.TestRunner.Merged, Version=1.3.1.55, Culture=neutral, PublicKeyToken=5c492ec4f3eccde3">
|
||||
<HintPath>D:\Program Files\JetBrains\JetBrains Rider 2020.3.2\lib\ReSharperHost\TestRunner\netcoreapp2.0\JetBrains.ReSharper.TestRunner.Merged.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Win32.Registry, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files\dotnet\shared\Microsoft.NETCore.App\5.0.5\Microsoft.Win32.Registry.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
14
Kavita.sln
14
Kavita.sln
@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "API", "API\API.csproj", "{1
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "API.Tests", "API.Tests\API.Tests.csproj", "{6F7910F2-1B95-4570-A490-519C8935B9D1}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kavita.Common", "Kavita.Common\Kavita.Common.csproj", "{165A86F5-9E74-4C05-9305-A6F0BA32C9EE}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -44,5 +46,17 @@ Global
|
||||
{6F7910F2-1B95-4570-A490-519C8935B9D1}.Release|x64.Build.0 = Release|Any CPU
|
||||
{6F7910F2-1B95-4570-A490-519C8935B9D1}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{6F7910F2-1B95-4570-A490-519C8935B9D1}.Release|x86.Build.0 = Release|Any CPU
|
||||
{165A86F5-9E74-4C05-9305-A6F0BA32C9EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{165A86F5-9E74-4C05-9305-A6F0BA32C9EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{165A86F5-9E74-4C05-9305-A6F0BA32C9EE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{165A86F5-9E74-4C05-9305-A6F0BA32C9EE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{165A86F5-9E74-4C05-9305-A6F0BA32C9EE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{165A86F5-9E74-4C05-9305-A6F0BA32C9EE}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{165A86F5-9E74-4C05-9305-A6F0BA32C9EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{165A86F5-9E74-4C05-9305-A6F0BA32C9EE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{165A86F5-9E74-4C05-9305-A6F0BA32C9EE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{165A86F5-9E74-4C05-9305-A6F0BA32C9EE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{165A86F5-9E74-4C05-9305-A6F0BA32C9EE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{165A86F5-9E74-4C05-9305-A6F0BA32C9EE}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
@ -10,12 +10,13 @@ your manga collection with your friends and family!
|
||||
|
||||
|
||||
## Goals:
|
||||
* Serve up Manga (cbr, cbz, zip/rar, raw images) and Books (epub, mobi, azw, djvu, pdf)
|
||||
* Provide Reader for Manga and Books (Light Novels) via web app that is responsive
|
||||
* Provide customization themes (server installed) for web app
|
||||
* Serve up Manga/Webtoons/Comics (cbr, cbz, zip/rar, raw images) and Books (epub, mobi, azw, djvu, pdf)
|
||||
* Provide Readers via web app that is responsive
|
||||
* Provide a dark theme for web app
|
||||
* Provide hooks into metadata providers to fetch Manga data
|
||||
* Metadata should allow for collections, want to read integration from 3rd party services, genres.
|
||||
* Ability to manage users, access, and ratings
|
||||
* Ability to sync ratings and reviews to external services
|
||||
|
||||
## How to Build
|
||||
- Ensure you've cloned Kavita-webui. You should have Projects/Kavita and Projects/Kavita-webui
|
||||
|
Loading…
x
Reference in New Issue
Block a user