From e6ea00e22deb63f58942358e5044f24fcf0ce8b0 Mon Sep 17 00:00:00 2001 From: guqing <1484563614@qq.com> Date: Thu, 5 Dec 2024 18:05:41 +0800 Subject: [PATCH] feat: add RSS feed for subscribing to post lists by tag slug --- .../feed/provider/TagPostRssProvider.java | 71 +++++++++++++++++++ .../run/halo/feed/service/PostService.java | 5 ++ .../halo/feed/service/PostServiceImpl.java | 22 ++++++ .../resources/extensions/ext-definition.yaml | 10 +++ 4 files changed, 108 insertions(+) create mode 100644 app/src/main/java/run/halo/feed/provider/TagPostRssProvider.java diff --git a/app/src/main/java/run/halo/feed/provider/TagPostRssProvider.java b/app/src/main/java/run/halo/feed/provider/TagPostRssProvider.java new file mode 100644 index 0000000..ea89fac --- /dev/null +++ b/app/src/main/java/run/halo/feed/provider/TagPostRssProvider.java @@ -0,0 +1,71 @@ +package run.halo.feed.provider; + +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.server.ServerRequest; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import run.halo.app.content.PostContentService; +import run.halo.app.extension.ListResult; +import run.halo.app.extension.ReactiveExtensionClient; +import run.halo.app.infra.ExternalLinkProcessor; +import run.halo.app.infra.ExternalUrlSupplier; +import run.halo.app.infra.SystemInfoGetter; +import run.halo.app.plugin.ReactiveSettingFetcher; +import run.halo.feed.BasicProp; +import run.halo.feed.RSS2; +import run.halo.feed.RssRouteItem; +import run.halo.feed.service.PostService; + +@Component +public class TagPostRssProvider extends AbstractPostRssProvider implements RssRouteItem { + + public TagPostRssProvider(PostService postService, ReactiveExtensionClient client, + ExternalLinkProcessor externalLinkProcessor, ReactiveSettingFetcher settingFetcher, + PostContentService postContentService, ExternalUrlSupplier externalUrlSupplier, + SystemInfoGetter systemInfoGetter) { + super(postService, client, externalLinkProcessor, settingFetcher, postContentService, + externalUrlSupplier, systemInfoGetter); + } + + @Override + public Mono pathPattern() { + return BasicProp.getBasicProp(settingFetcher) + .filter(BasicProp::isEnableCategories) + .map(prop -> "/tags/{slug}.xml"); + } + + @Override + @NonNull + public String displayName() { + return "标签文章订阅"; + } + + @Override + public String description() { + return "按标签订阅站点文章"; + } + + public Mono handler(ServerRequest request) { + var slug = request.pathVariable("slug"); + return super.handler(request) + .flatMap(rss2 -> postService.getTagBySlug(slug) + .doOnNext(tag -> { + var displayName = tag.getSpec().getDisplayName(); + var permalink = tag.getStatusOrDefault().getPermalink(); + rss2.setTitle("标签:" + displayName + " - " + rss2.getTitle()); + rss2.setLink(externalLinkProcessor.processLink(permalink)); + }) + .thenReturn(rss2) + ); + } + + @Override + protected Flux listPosts(ServerRequest request) { + var tagSlug = request.pathVariable("slug"); + return listPostsByFunc(basicProp -> + postService.listPostByTagSlug(basicProp.getOutputNum(), tagSlug) + .flatMapIterable(ListResult::getItems) + ); + } +} diff --git a/app/src/main/java/run/halo/feed/service/PostService.java b/app/src/main/java/run/halo/feed/service/PostService.java index befc542..60a4561 100644 --- a/app/src/main/java/run/halo/feed/service/PostService.java +++ b/app/src/main/java/run/halo/feed/service/PostService.java @@ -3,6 +3,7 @@ import reactor.core.publisher.Mono; import run.halo.app.core.extension.content.Category; import run.halo.app.core.extension.content.Post; +import run.halo.app.core.extension.content.Tag; import run.halo.app.extension.ListResult; public interface PostService { @@ -10,7 +11,11 @@ public interface PostService { Mono> listPostByCategorySlug(int size, String categorySlug); + Mono> listPostByTagSlug(int size, String tagSlug); + Mono> listPostByAuthor(int size, String author); Mono getCategoryBySlug(String categorySlug); + + Mono getTagBySlug(String slug); } diff --git a/app/src/main/java/run/halo/feed/service/PostServiceImpl.java b/app/src/main/java/run/halo/feed/service/PostServiceImpl.java index 599cf1c..0f68d3d 100644 --- a/app/src/main/java/run/halo/feed/service/PostServiceImpl.java +++ b/app/src/main/java/run/halo/feed/service/PostServiceImpl.java @@ -11,6 +11,7 @@ import reactor.core.publisher.Mono; import run.halo.app.core.extension.content.Category; import run.halo.app.core.extension.content.Post; +import run.halo.app.core.extension.content.Tag; import run.halo.app.extension.ListOptions; import run.halo.app.extension.ListResult; import run.halo.app.extension.PageRequestImpl; @@ -39,6 +40,17 @@ public Mono> listPostByCategorySlug(int size, String categorySl }); } + @Override + public Mono> listPostByTagSlug(int size, String slug) { + return getTagBySlug(slug) + .flatMap(tag -> { + var tagName = tag.getMetadata().getName(); + return client.listBy(Post.class, + buildPostListOptions(in("spec.tags", tagName)), + PageRequestImpl.ofSize(size).withSort(defaultSort())); + }); + } + @Override public Mono> listPostByAuthor(int size, String author) { return client.listBy(Post.class, buildPostListOptions(in("spec.owner", author)), @@ -55,6 +67,16 @@ public Mono getCategoryBySlug(String categorySlug) { .flatMap(listResult -> Mono.justOrEmpty(ListResult.first(listResult))); } + @Override + public Mono getTagBySlug(String slug) { + return client.listBy(Tag.class, ListOptions.builder() + .fieldQuery(equal("spec.slug", slug)) + .build(), + PageRequestImpl.ofSize(1) + ) + .flatMap(listResult -> Mono.justOrEmpty(ListResult.first(listResult))); + } + ListOptions buildPostListOptions() { return buildPostListOptions(null); } diff --git a/app/src/main/resources/extensions/ext-definition.yaml b/app/src/main/resources/extensions/ext-definition.yaml index 4e704de..cb4211f 100644 --- a/app/src/main/resources/extensions/ext-definition.yaml +++ b/app/src/main/resources/extensions/ext-definition.yaml @@ -21,6 +21,16 @@ spec: --- apiVersion: plugin.halo.run/v1alpha1 kind: ExtensionDefinition +metadata: + name: feed-tag-post-rss-item +spec: + className: run.halo.feed.provider.TagPostRssProvider + extensionPointName: feed-rss-route-item + displayName: "标签文章订阅" + description: "用于生成按照标签订阅文章列表的 RSS 订阅源" +--- +apiVersion: plugin.halo.run/v1alpha1 +kind: ExtensionDefinition metadata: name: feed-author-post-rss-item spec: