summaryrefslogtreecommitdiff
path: root/Services/FeedService.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Services/FeedService.cs')
-rw-r--r--Services/FeedService.cs212
1 files changed, 0 insertions, 212 deletions
diff --git a/Services/FeedService.cs b/Services/FeedService.cs
deleted file mode 100644
index 3744e73..0000000
--- a/Services/FeedService.cs
+++ /dev/null
@@ -1,212 +0,0 @@
-using HyperBooru.ApiModels;
-using Microsoft.EntityFrameworkCore;
-
-namespace HyperBooru.Services;
-
-public interface IFeedService {
- public Media[] LoadChunk(
- bool selectIngest,
- bool includeNsfw,
- Media? key = null,
- int count = 50,
- SortOrder sortOrder = SortOrder.ObjectId);
-
- public Media[] LoadChunk(
- bool selectIngest,
- bool includeNsfw,
- string query,
- Media? key = null,
- int count = 50,
- SortOrder sortOrder = SortOrder.ObjectId);
-
- public Media[] LoadChunk(
- bool selectIngest,
- bool includeNsfw,
- Guid tagId,
- Media? key = null,
- int count = 50,
- SortOrder sortOrder = SortOrder.ObjectId);
-
- public Media[] LoadChunk(FeedRequest feedRequest);
-}
-
-public class FeedService : IFeedService {
- private IDbContextFactory<HBContext> dbFactory;
-
- public FeedService(IDbContextFactory<HBContext> dbFactory) =>
- this.dbFactory = dbFactory;
-
- public Media[] LoadChunk(
- bool selectIngest,
- bool includeNsfw,
- Media? continuationToken,
- int count,
- SortOrder sortOrder) => LoadChunkInternal(
- selectIngest, includeNsfw, null, null, continuationToken?.Guid, count, sortOrder);
-
- public Media[] LoadChunk(
- bool selectIngest,
- bool includeNsfw,
- string query,
- Media? continuationToken,
- int count,
- SortOrder sortOrder) => LoadChunkInternal(
- selectIngest, includeNsfw, query, null, continuationToken?.Guid, count, sortOrder);
-
- public Media[] LoadChunk(
- bool selectIngest,
- bool includeNsfw,
- Guid tagId,
- Media? continuationToken,
- int count,
- SortOrder sortOrder) => LoadChunkInternal(
- selectIngest, includeNsfw, null, tagId, continuationToken?.Guid, count, sortOrder);
-
- public Media[] LoadChunk(FeedRequest feedRequest) {
- switch(feedRequest) {
- case FeedSearchRequest searchRequest:
- return LoadChunkInternal(
- selectIngest: searchRequest.SelectIngest,
- includeNsfw: searchRequest.IncludeNsfw,
- query: searchRequest.Query,
- tagId: null,
- continuationToken: searchRequest.ContinuationToken,
- count: searchRequest.Count,
- sortOrder: searchRequest.SortOrder);
- case FeedTagRequest tagRequest:
- return LoadChunkInternal(
- selectIngest: tagRequest.SelectIngest,
- includeNsfw: tagRequest.IncludeNsfw,
- query: null,
- tagId: tagRequest.TagId,
- continuationToken: tagRequest.ContinuationToken,
- count: tagRequest.Count,
- sortOrder: tagRequest.SortOrder);
- default:
- return LoadChunkInternal(
- selectIngest: feedRequest.SelectIngest,
- includeNsfw: feedRequest.IncludeNsfw,
- query: null,
- tagId: null,
- continuationToken: feedRequest.ContinuationToken,
- count: feedRequest.Count,
- sortOrder: feedRequest.SortOrder);
- }
- }
-
- private Media[] LoadChunkInternal(
- bool selectIngest,
- bool includeNsfw,
- string? query,
- Guid? tagId,
- Guid? continuationToken,
- int count,
- SortOrder sortOrder) {
-
- if(selectIngest && !includeNsfw)
- return Array.Empty<Media>();
-
- using var db = dbFactory.CreateDbContext();
-
- IQueryable<Media> media = db.Media
- .AsSingleQuery()
- .AsNoTracking()
- .Include(m => m.Tags)
- .Include(m => m.CurrentUploadedFile);
-
- if(!includeNsfw)
- media = media
- .Where(m => !TagsThatImply(db, HBContext.NsfwTag)
- .Intersect(m.Tags.Select(t => t.TagDefinitionId))
- .Any());
-
- if(selectIngest) {
- media = media
- .Where(m => m.Tags
- .Select(t => t.TagDefinitionId)
- .Contains((int) HBObjectId.IngestTag));
- } else {
- media = media
- .Where(m => !m.Tags
- .Select(t => t.TagDefinitionId)
- .Contains((int) HBObjectId.IngestTag));
- }
-
- if(query is not null) {
- media = Search(media, query);
- } else if(tagId is not null) {
- media = media
- .Where(m => TagsThatImply(db, (Guid) tagId)
- .Intersect(m.Tags.Select(t => t.TagDefinitionId))
- .Any());
- }
-
- if(continuationToken is not null)
- media = media
- .Where(m => m.ObjectId > db.Media.First(m => m.Guid == continuationToken).ObjectId);
-
- switch(sortOrder) {
- case SortOrder.ObjectId:
- media = media.OrderBy(m => m.ObjectId);
- break;
- case SortOrder.LastWriteTime:
- media = media.OrderBy(m => m.CurrentUploadedFile!.LastWriteTime);
- break;
- case SortOrder.Random:
- media = media.OrderBy(m => EF.Functions.Random());
- break;
- }
-
- return media
- .Take(count)
- .ToArray();
- }
-
- private static IQueryable<Media> Search(IQueryable<Media> media, string query) {
- // TODO: search implicit tags as well
-
- query = query.ToLower().Trim();
-
- return media
- .Where(m =>
- (m.ShortDescription != null && m.ShortDescription.ToLower().Contains(query)) ||
- (m.LongDescription != null && m.LongDescription.ToLower().Contains(query)) ||
- (m.UploadedFiles.Any(uf => uf.Filename != null && uf.Filename.ToLower().Contains(query))) ||
- (m.OcrData != null && m.OcrData.SearchableText.ToLower().Contains(query)) ||
- (m.Tags.Any(t => t.TagDefinition.Name.ToLower().Contains(query))));
- }
-
- private static IQueryable<int> TagsThatImply(HBContext db, Guid tagId) =>
- db.Database.SqlQueryRaw<int>("""
- WITH RECURSIVE basetag AS (
- SELECT "ObjectId" FROM "Objects" WHERE "Guid" = {0}
- ),
- impliedtags AS (
- SELECT
- "TagDefinitionObjectId"
- FROM
- "TagDefinitionTagDefinition"
- INNER JOIN
- basetag
- ON
- "ImplicitTagsObjectId" = basetag."ObjectId"
- UNION
- SELECT
- "TagDefinitionTagDefinition"."TagDefinitionObjectId"
- FROM
- "TagDefinitionTagDefinition"
- INNER JOIN
- impliedtags
- ON
- impliedtags."TagDefinitionObjectId" = "TagDefinitionTagDefinition"."ImplicitTagsObjectId"
- )
- SELECT DISTINCT
- "TagDefinitionObjectId" AS "Value"
- FROM impliedtags
- UNION
- SELECT
- "ObjectId" AS "Value"
- FROM
- basetag
- """, tagId);
-}