Skip to content

Commit

Permalink
feat: restructure RSS generation to support extension by other plugins (
Browse files Browse the repository at this point in the history
#39)

### What this PR does?
重写 RSS 生成并支持被其他插件扩展

```release-note
重写 RSS 生成并支持被其他插件扩展
```
  • Loading branch information
guqing authored Dec 5, 2024
1 parent 857696c commit cff7c7e
Show file tree
Hide file tree
Showing 40 changed files with 1,621 additions and 834 deletions.
1 change: 1 addition & 0 deletions .github/workflows/cd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ jobs:
with:
app-id: app-KhIVw
skip-node-setup: true
artifacts-path: 'app/build/libs'
1 change: 1 addition & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ jobs:
uses: halo-sigs/reusable-workflows/.github/workflows/plugin-ci.yaml@v1
with:
skip-node-setup: true
artifacts-path: 'app/build/libs'
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,4 @@ application-local.properties

/admin-frontend/node_modules/
/workplace/
*/workplace/
104 changes: 95 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,92 @@

Halo 2.0 的 RSS 订阅链接生成插件

## 如何扩展 RSS 源

> 从 feed 插件 v1.4.0 版本开始,支持扩展 RSS 功能。
`feed` 插件提供了扩展点,允许其他插件扩展 RSS 源。

### 步骤 1:在插件中引入 feed 依赖

在你的插件项目中添加 `feed` 插件的依赖:

```groovy
dependencies {
// ...
compileOnly "run.halo.feed:api:{version}"
}
```

`{version}` 替换为实际的 `feed` 插件版本号。

### 步骤 2:实现 `RssRouteItem` 扩展点接口

创建一个类实现 `run.halo.feed.RssRouteItem` 接口,提供自定义的 RSS 数据源。例如:

```java
public class MomentRssProvider implements RssRouteItem {
// 实现具体的 RSS 提供逻辑
}
```

你可以参考 [PostRssProvider](./app/src/main/java/run/halo/feed/provider/PostRssProvider.java) 示例。

### 步骤 3:声明扩展点

`src/main/resources/extensions`
目录下,声明你的扩展。你可以参考 [ext-definition.yaml](app/src/main/resources/extensions/ext-definition.yaml) 文件来完成此步骤。

### 步骤 4:定义配置类并清理 RSS 缓存

在插件中定义一个配置类,使用 `@ConditionalOnClass` 注解确保只有在 `run.halo.feed.RssRouteItem` 类存在时才会创建对应的
Bean。同时,定义事件监听器来清理缓存。

`@ConditionalOnClass` 注解只能使用 name 属性来指定类全限定名,不支持使用 value 属性。

示例代码:

```java

@Configuration
@ConditionalOnClass(name = "run.halo.feed.RssRouteItem")
@RequiredArgsConstructor
public class RssAutoConfiguration {
private final ApplicationEventPublisher eventPublisher;

@Bean
public MomentRssProvider momentRssProvider() {
return new MomentRssProvider();
}

@Async
@EventListener({MomentUpdatedEvent.class, MomentDeletedEvent.class, ContextClosedEvent.class})
public void onMomentUpdatedOrDeleted() {
var rule = CacheClearRule.forExact("/feed/moments/rss.xml");
var event = RssCacheClearRequested.forRule(this, rule);
eventPublisher.publishEvent(event);
}
}
```

此配置确保了当 `RssRouteItem` 接口存在时,插件才会自动创建 `MomentRssProvider` 并监听相关事件来清理缓存。

### 步骤 5:声明插件依赖

`plugin.yaml` 文件中声明 `feed` 插件为可选依赖,确保当 `feed` 插件存在并启用时,插件能够自动注册 RSS 源。

```yaml
apiVersion: plugin.halo.run/v1alpha1
kind: Plugin
metadata:
name: moment
spec:
pluginDependencies:
"PluginFeed?": ">=1.4.0"
```
这样,当 `feed` 插件可用时,插件会自动注册自定义的 RSS 源。

## 开发环境

```bash
Expand All @@ -28,15 +114,15 @@ cd path/to/plugin-feed

```yaml
halo:
plugin:
runtime-mode: development
classes-directories:
- "build/classes"
- "build/resources"
lib-directories:
- "libs"
fixedPluginPath:
- "/path/to/plugin-feed"
plugin:
runtime-mode: development
classes-directories:
- "build/classes"
- "build/resources"
lib-directories:
- "libs"
fixedPluginPath:
- "/path/to/plugin-feed"
```

## 使用方式
Expand Down
76 changes: 76 additions & 0 deletions api/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
plugins {
id 'java-library'
id 'maven-publish'
id "io.freefair.lombok" version "8.0.0-rc2"
}

group = 'run.halo.feed'
version = rootProject.version

java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
withSourcesJar()
}

compileJava.options.encoding = "UTF-8"
compileTestJava.options.encoding = "UTF-8"
javadoc.options.encoding = "UTF-8"

dependencies {
api platform('run.halo.tools.platform:plugin:2.20.11')
compileOnly 'run.halo.app:api'
}

test {
useJUnitPlatform()
}

publishing {
publications {
mavenJava(MavenPublication) {
from components.java
artifact tasks.sourcesJar

artifactId = 'api'
version = project.hasProperty('version') ? project.property('version') : 'unspecified'

pom {
name = 'RSS'
description = '为站点生成 RSS 订阅链接'
url = 'https://www.halo.run/store/apps/app-KhIVw'

licenses {
license {
name = 'GPL-3.0'
url = 'https://github.com/halo-dev/plugin-feed/blob/main/LICENSE'
}
}

developers {
developer {
id = 'guqing'
name = 'guqing'
email = '[email protected]'
}
}

scm {
connection = 'scm:git:[email protected]:halo-dev/plugin-feed.git'
developerConnection = 'scm:git:[email protected]:halo-dev/plugin-feed.git'
url = 'https://github.com/halo-dev/plugin-feed'
}
}
}
}
repositories {
maven {
url = version.endsWith('-SNAPSHOT') ? 'https://s01.oss.sonatype.org/content/repositories/snapshots/' :
'https://s01.oss.sonatype.org/content/repositories/releases/'
credentials {
username = project.findProperty("ossr.user") ?: System.getenv("OSSR_USERNAME")
password = project.findProperty("ossr.password") ?: System.getenv("OSSR_PASSWORD")
}
}
}
}
40 changes: 40 additions & 0 deletions api/src/main/java/run/halo/feed/CacheClearRule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package run.halo.feed;

import org.springframework.util.Assert;

public record CacheClearRule(Type type, String value) {
public CacheClearRule {
Assert.notNull(type, "Type cannot be null");
Assert.notNull(value, "Value cannot be null");
if (type == Type.EXACT && !value.startsWith("/")) {
throw new IllegalArgumentException("Exact value must start with /");
}
}

public static CacheClearRule forPrefix(String prefix) {
return new CacheClearRule(Type.PREFIX, prefix);
}

public static CacheClearRule forExact(String exact) {
return new CacheClearRule(Type.EXACT, exact);
}

public static CacheClearRule forContains(String contains) {
return new CacheClearRule(Type.CONTAINS, contains);
}

@Override
public String toString() {
return "CacheClearRule{" +
"type=" + type +
", value='" + value + '\'' +
'}';
}

public enum Type {
PREFIX,
EXACT,
CONTAINS
}
}

Loading

0 comments on commit cff7c7e

Please sign in to comment.