Skip to content

Commit 897254d

Browse files
author
OnlyFart
committed
1 parent 19054ce commit 897254d

10 files changed

+185
-1
lines changed

Diff for: Core/Core.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<TargetFramework>net8.0</TargetFramework>
55
<LangVersion>latestmajor</LangVersion>
66
<PackageId>Core</PackageId>
7-
<Version>2.3.3</Version>
7+
<Version>2.4.0</Version>
88
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
99
</PropertyGroup>
1010

Diff for: Core/Logic/Getters/FanFicusGetter.cs

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Net;
5+
using System.Net.Http.Headers;
6+
using System.Net.Http.Json;
7+
using System.Threading.Tasks;
8+
using Core.Configs;
9+
using Core.Extensions;
10+
using Core.Types.Book;
11+
using Core.Types.Common;
12+
using Core.Types.FanFicus;
13+
using HtmlAgilityPack;
14+
using Microsoft.Extensions.Logging;
15+
16+
namespace Core.Logic.Getters;
17+
18+
public class FanFicusGetter : GetterBase {
19+
public FanFicusGetter(BookGetterConfig config) : base(config) { }
20+
21+
protected override Uri SystemUrl => new("https://fanficus.com/");
22+
23+
private readonly Uri _apiHost = new("https://fanficus-server-mirror-879c30cd977f.herokuapp.com/");
24+
25+
protected override string GetId(Uri url) {
26+
return url.GetSegment(2);
27+
}
28+
29+
public override async Task Authorize() {
30+
if (!Config.HasCredentials) {
31+
return;
32+
}
33+
34+
var response = await Config.Client.PostAsJsonAsync(_apiHost.MakeRelativeUri("api/v1/user/login"), GenerateAuthData());
35+
if (response.StatusCode == HttpStatusCode.OK) {
36+
var user = await response.Content.ReadFromJsonAsync<FanFicusApiResponse<FanFicusUser>>();
37+
Config.Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", user.Value.Token);
38+
Config.Logger.LogInformation("Успешно авторизовались");
39+
} else {
40+
throw new Exception("Не удалось авторизоваться. Неверный пароль или имейл");
41+
}
42+
}
43+
44+
private object GenerateAuthData() {
45+
return new {
46+
username = Config.Options.Login,
47+
password = Config.Options.Password,
48+
};
49+
}
50+
51+
public override async Task<Book> Get(Uri url) {
52+
var bookId = GetId(url);
53+
54+
url = SystemUrl.MakeRelativeUri($"/post/{bookId}");
55+
var response = await Config.Client.GetFromJsonWithTriesAsync<FanFicusApiResponse<FanFicusBook>>(_apiHost.MakeRelativeUri($"api/v1/post/{bookId}"));
56+
57+
var book = new Book(url) {
58+
Cover = await GetCover(response.Value, url),
59+
Chapters = await FillChapters(bookId),
60+
Title = response.Value.Title,
61+
Author = GetAuthor(response.Value),
62+
Annotation = response.Value.Description
63+
};
64+
65+
return book;
66+
}
67+
68+
private Author GetAuthor(FanFicusBook book) {
69+
var creator = book.Creators.FirstOrDefault();
70+
return creator == default ? new Author("FanFicus") : new Author(creator.NickName, SystemUrl.MakeRelativeUri($"/user/{creator.Id}"));
71+
}
72+
73+
private async Task<IEnumerable<FanFicusPart>> GetToc(string bookId) {
74+
var response = await Config.Client.GetFromJsonWithTriesAsync<FanFicusApiResponse<FanFicusPart[]>>(_apiHost.MakeRelativeUri($"/api/v1/post/{bookId}/post-part"));
75+
return SliceToc(response.Value, c => c.Title);
76+
}
77+
78+
private async Task<IEnumerable<Chapter>> FillChapters(string bookId) {
79+
var result = new List<Chapter>();
80+
if (Config.Options.NoChapters) {
81+
return result;
82+
}
83+
84+
foreach (var fanFicusPart in await GetToc(bookId)) {
85+
var chapter = new Chapter {
86+
Title = fanFicusPart.Title
87+
};
88+
89+
Config.Logger.LogInformation($"Загружаю главу {fanFicusPart.Title.CoverQuotes()}");
90+
91+
var chapterDoc = await GetChapter(bookId, fanFicusPart);
92+
if (chapterDoc != default) {
93+
chapter.Images = await GetImages(chapterDoc, SystemUrl);
94+
chapter.Content = chapterDoc.DocumentNode.InnerHtml;
95+
}
96+
97+
result.Add(chapter);
98+
}
99+
100+
return result;
101+
}
102+
103+
private async Task<HtmlDocument> GetChapter(string bookId, FanFicusPart fanFicusPart) {
104+
var response = await Config.Client.GetFromJsonWithTriesAsync<FanFicusApiResponse<FanFicusChapter>>(_apiHost.MakeRelativeUri($"api/v1/post/{bookId}/post-part/{fanFicusPart.Id}"));
105+
return response.Value.Text.AsHtmlDoc();
106+
}
107+
108+
private Task<TempFile> GetCover(FanFicusBook doc, Uri uri) {
109+
var imagePath = doc.Images.FirstOrDefault()?.Url;
110+
return !string.IsNullOrWhiteSpace(imagePath) ? SaveImage(uri.MakeRelativeUri(imagePath)) : Task.FromResult(default(TempFile));
111+
}
112+
}

Diff for: Core/Types/FanFicus/FanFicusApiResponse.cs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace Core.Types.FanFicus;
4+
5+
public class FanFicusApiResponse<T> {
6+
[JsonPropertyName("value")]
7+
public T Value { get; set; }
8+
}

Diff for: Core/Types/FanFicus/FanFicusBook.cs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace Core.Types.FanFicus;
4+
5+
public class FanFicusBook {
6+
[JsonPropertyName("title")]
7+
public string Title { get; set; }
8+
9+
[JsonPropertyName("description")]
10+
public string Description { get; set; }
11+
12+
[JsonPropertyName("creatorId")]
13+
public FanFicusCreator[] Creators { get; set; }
14+
15+
[JsonPropertyName("images")]
16+
public FanFicusImage[] Images { get; set; }
17+
}

Diff for: Core/Types/FanFicus/FanFicusChapter.cs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace Core.Types.FanFicus;
4+
5+
public class FanFicusChapter {
6+
[JsonPropertyName("text")]
7+
public string Text { get; set; }
8+
}

Diff for: Core/Types/FanFicus/FanFicusCreator.cs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace Core.Types.FanFicus;
4+
5+
public class FanFicusCreator {
6+
[JsonPropertyName("_id")]
7+
public string Id { get; set; }
8+
9+
[JsonPropertyName("nickName")]
10+
public string NickName { get; set; }
11+
}

Diff for: Core/Types/FanFicus/FanFicusImage.cs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace Core.Types.FanFicus;
4+
5+
public class FanFicusImage {
6+
[JsonPropertyName("url")]
7+
public string Url { get; set; }
8+
}

Diff for: Core/Types/FanFicus/FanFicusPart.cs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace Core.Types.FanFicus;
4+
5+
public class FanFicusPart {
6+
[JsonPropertyName("_id")]
7+
public string Id { get; set; }
8+
9+
[JsonPropertyName("title")]
10+
public string Title { get; set; }
11+
}

Diff for: Core/Types/FanFicus/FanFicusUser.cs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace Core.Types.FanFicus;
4+
5+
public class FanFicusUser {
6+
[JsonPropertyName("token")]
7+
public string Token { get; set; }
8+
}

Diff for: README.md

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
* https://dreame.com/
3232
* https://erolate.com/
3333
* https://eznovels.com/
34+
* https://fanficus.com/
3435
* https://fb2.top/
3536
* https://ficbook.net/
3637
* https://fictionbook.ru/

0 commit comments

Comments
 (0)