From 233c74050e69828adf5833d796b00dbe84e3eb4b Mon Sep 17 00:00:00 2001 From: guqing <1484563614@qq.com> Date: Fri, 6 Dec 2024 17:59:20 +0800 Subject: [PATCH] feat: add rss telemetry recorder implementation --- build.gradle | 8 ++- gradle/wrapper/gradle-wrapper.properties | 2 +- src/main/java/run/halo/umami/BasicProp.java | 17 +++++ .../halo/umami/RssTelemetryUmamiRecorder.java | 63 +++++++++++++++++++ .../run/halo/umami/UmamiTrackerProcessor.java | 15 +---- src/main/resources/plugin.yaml | 2 +- 6 files changed, 90 insertions(+), 17 deletions(-) create mode 100644 src/main/java/run/halo/umami/BasicProp.java create mode 100644 src/main/java/run/halo/umami/RssTelemetryUmamiRecorder.java diff --git a/build.gradle b/build.gradle index d984bea..73edbf9 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id "com.github.node-gradle.node" version "5.0.0" - id "run.halo.plugin.devtools" version "0.0.9" + id "run.halo.plugin.devtools" version "0.4.1" id "io.freefair.lombok" version "8.0.1" id 'java' } @@ -13,13 +13,15 @@ java { } repositories { + mavenLocal() maven { url 'https://s01.oss.sonatype.org/content/repositories/snapshots' } mavenCentral() } dependencies { - implementation platform('run.halo.tools.platform:plugin:2.17.0-SNAPSHOT') + implementation platform('run.halo.tools.platform:plugin:2.20.11') compileOnly 'run.halo.app:api' + compileOnly "run.halo.feed:api:0.0.2-SNAPSHOT" testImplementation 'run.halo.app:api' testImplementation 'org.springframework.boot:spring-boot-starter-test' @@ -54,5 +56,5 @@ build { } halo { - version = "2.17" + version = "2.20.11" } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 62f495d..09523c0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/run/halo/umami/BasicProp.java b/src/main/java/run/halo/umami/BasicProp.java new file mode 100644 index 0000000..06857bb --- /dev/null +++ b/src/main/java/run/halo/umami/BasicProp.java @@ -0,0 +1,17 @@ +package run.halo.umami; + +import lombok.Data; +import reactor.core.publisher.Mono; +import run.halo.app.plugin.ReactiveSettingFetcher; + +@Data +public class BasicProp { + private String websiteId; + private String endpoint; + private String scriptName; + private String url; + + public static Mono fetch(ReactiveSettingFetcher settingFetcher) { + return settingFetcher.fetch("basic", BasicProp.class); + } +} diff --git a/src/main/java/run/halo/umami/RssTelemetryUmamiRecorder.java b/src/main/java/run/halo/umami/RssTelemetryUmamiRecorder.java new file mode 100644 index 0000000..5d3a90c --- /dev/null +++ b/src/main/java/run/halo/umami/RssTelemetryUmamiRecorder.java @@ -0,0 +1,63 @@ +package run.halo.umami; + +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; +import run.halo.app.infra.ExternalUrlSupplier; +import run.halo.app.plugin.ReactiveSettingFetcher; +import run.halo.feed.TelemetryEventInfo; +import run.halo.feed.TelemetryRecorder; + +import java.net.URL; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; + +@RequiredArgsConstructor +public class RssTelemetryUmamiRecorder implements TelemetryRecorder { + private final WebClient webClient = WebClient.builder().build(); + private final ReactiveSettingFetcher settingFetcher; + private final ExternalUrlSupplier externalUrlSupplier; + + @Override + public void record(TelemetryEventInfo eventInfo) { + var propOpt = BasicProp.fetch(settingFetcher).blockOptional(); + if (propOpt.isEmpty()) { + return; + } + var siteUrl = propOpt.get().getEndpoint(); + var webSiteId = propOpt.get().getWebsiteId(); + if (StringUtils.isBlank(siteUrl) || StringUtils.isNotBlank(webSiteId)) { + return; + } + + // https://umami.is/docs/api/sending-stats + webClient.post() + .uri(StringUtils.removeEnd(siteUrl, "/") + "/api/send") + .body(Mono.just(createBody(webSiteId, eventInfo)), Map.class) + .retrieve() + .bodyToMono(String.class) + .block(); + } + + private Map createBody(String webSiteId, TelemetryEventInfo eventInfo) { + var hostname = Optional.ofNullable(externalUrlSupplier.getRaw()) + .map(URL::getAuthority) + .orElse(StringUtils.EMPTY); + + return Map.of("payload", Map.of( + "hostname", hostname, + "language", eventInfo.getLanguage(), + "referrer", eventInfo.getReferrer(), + "screen", eventInfo.getScreen(), + "title", eventInfo.getTitle(), + "url", eventInfo.getPageUrl(), + "website", webSiteId, + "name", "Rss Reader" + ), + "type", "event" + ); + } +} diff --git a/src/main/java/run/halo/umami/UmamiTrackerProcessor.java b/src/main/java/run/halo/umami/UmamiTrackerProcessor.java index b50bfcd..fe6904a 100644 --- a/src/main/java/run/halo/umami/UmamiTrackerProcessor.java +++ b/src/main/java/run/halo/umami/UmamiTrackerProcessor.java @@ -1,6 +1,5 @@ package run.halo.umami; -import lombok.Data; import org.springframework.stereotype.Component; import org.thymeleaf.context.ITemplateContext; import org.thymeleaf.model.IModel; @@ -22,10 +21,10 @@ public UmamiTrackerProcessor(ReactiveSettingFetcher settingFetcher) { @Override public Mono process(ITemplateContext context, IModel model, IElementModelStructureHandler structureHandler) { - return settingFetcher.fetch("basic", BasicConfig.class) - .doOnNext(basicConfig -> { + return BasicProp.fetch(settingFetcher) + .doOnNext(prop -> { final IModelFactory modelFactory = context.getModelFactory(); - model.add(modelFactory.createText(trackerScript(basicConfig.getWebsiteId(), basicConfig.endpoint, basicConfig.scriptName))); + model.add(modelFactory.createText(trackerScript(prop.getWebsiteId(), prop.getEndpoint(), prop.getScriptName()))); }) .then(); } @@ -35,12 +34,4 @@ private String trackerScript(String websiteId, String endpoint, String scriptNam """.formatted(websiteId, endpoint, scriptName); } - - @Data - public static class BasicConfig { - String websiteId; - String endpoint; - String scriptName; - String url; - } } diff --git a/src/main/resources/plugin.yaml b/src/main/resources/plugin.yaml index 923dd36..568742d 100644 --- a/src/main/resources/plugin.yaml +++ b/src/main/resources/plugin.yaml @@ -7,7 +7,7 @@ metadata: spec: enabled: true version: 1.0.0 - requires: ">=2.17.0" + requires: ">=2.20.11" author: name: Halo website: https://github.com/halo-dev