1.4.3原版

This commit is contained in:
anian
2026-03-15 23:33:02 +08:00
commit 54fb39d15c
135 changed files with 14156 additions and 0 deletions
@@ -0,0 +1,9 @@
package la.moony.friends.service;
import la.moony.friends.vo.RssDetail;
import reactor.core.publisher.Mono;
public interface RssDetailService {
Mono<RssDetail> fetchRssDetail(String rssUrl, int fetchLimitNumber);
}
@@ -0,0 +1,13 @@
package la.moony.friends.service;
import la.moony.friends.ListedRssSyncLog;
import la.moony.friends.query.RssSyncLogQuery;
import reactor.core.publisher.Mono;
import run.halo.app.extension.ListResult;
public interface RssFeedSyncLogService {
Mono<ListResult<ListedRssSyncLog>> listRssSyncLog(RssSyncLogQuery query);
Mono<Void> publishRssFeedSyncEvent(String name);
}
@@ -0,0 +1,53 @@
package la.moony.friends.service.impl;
import com.rometools.rome.feed.synd.SyndEntry;
import com.rometools.rome.feed.synd.SyndFeed;
import com.rometools.rome.io.SyndFeedInput;
import com.rometools.rome.io.XmlReader;
import la.moony.friends.service.RssDetailService;
import la.moony.friends.vo.RssDetail;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
@Component
public class RssDetailServiceImpl implements RssDetailService {
@Override
public Mono<RssDetail> fetchRssDetail(String rssUrl, int fetchLimitNumber) {
RssDetail rssDetail = new RssDetail();
try {
// 创建 SyndFeedInput 对象并从 URL 获取 RSS 提要
SyndFeedInput input = new SyndFeedInput();
SyndFeed feed = input.build(new XmlReader(new URL(rssUrl)));
RssDetail.Channel channel = new RssDetail.Channel();
channel.setTitle(feed.getTitle());
channel.setLink(feed.getLink());
channel.setDescription(feed.getDescription());
rssDetail.setChannel(channel);
List<RssDetail.Item> items = new ArrayList<>();
int count = 0;
for (SyndEntry syndEntry : feed.getEntries()) {
RssDetail.Item item = new RssDetail.Item();
item.setTitle(syndEntry.getTitle());
item.setLink(syndEntry.getLink());
item.setAuthor(syndEntry.getAuthor());
item.setDescription(syndEntry.getDescription().getValue());
item.setPubDate(syndEntry.getPublishedDate().toInstant());
items.add(item);
count++;
if (count >= fetchLimitNumber) {
break;
}
}
channel.setItems(items);
}catch (Exception e) {
e.printStackTrace();
}
return Mono.just(rssDetail);
}
}
@@ -0,0 +1,97 @@
package la.moony.friends.service.impl;
import la.moony.friends.ListedRssSyncLog;
import la.moony.friends.RssFeedSyncEvent;
import la.moony.friends.extension.CronFriendPost;
import la.moony.friends.extension.Link;
import la.moony.friends.extension.RssFeedSyncLog;
import la.moony.friends.query.RssSyncLogQuery;
import la.moony.friends.service.RssFeedSyncLogService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.ListResult;
import run.halo.app.extension.PageRequestImpl;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.extension.router.selector.FieldSelector;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import static run.halo.app.extension.index.query.QueryFactory.equal;
import static run.halo.app.extension.index.query.QueryFactory.isNull;
@Component
public class RssFeedSyncLogServiceImpl implements RssFeedSyncLogService {
private final ReactiveExtensionClient client;
private final ApplicationEventPublisher eventPublisher;
public RssFeedSyncLogServiceImpl(ReactiveExtensionClient client,
ApplicationEventPublisher eventPublisher) {
this.client = client;
this.eventPublisher = eventPublisher;
}
@Override
public Mono<ListResult<ListedRssSyncLog>> listRssSyncLog(RssSyncLogQuery query) {
return buildListOptions(query)
.flatMap(listOptions -> client.listBy(Link.class, listOptions,
PageRequestImpl.of(query.getPage(), query.getSize(), query.getSort())
))
.flatMap(listResult -> Flux.fromStream(listResult.get())
.map(this::getListedRssSyncLog)
.flatMapSequential(Function.identity())
.collectList()
.map(listedApplications -> new ListResult<>(listResult.getPage(), listResult.getSize(),
listResult.getTotal(), listedApplications)
)
.defaultIfEmpty(ListResult.emptyResult())
);
}
private Mono<ListedRssSyncLog> getListedRssSyncLog(Link link) {
Assert.notNull(link, "The link must not be null.");
var listedRssSyncLog = new ListedRssSyncLog().setLink(link);
var logMono = client.fetch(RssFeedSyncLog.class,"sync-log-"+link.getMetadata().getName())
.doOnNext(listedRssSyncLog::setLog);
return Mono.when(logMono)
.thenReturn(listedRssSyncLog);
}
Mono<ListOptions> buildListOptions(RssSyncLogQuery query) {
return Mono.just(query.toListOptions());
}
public Mono<Void> publishRssFeedSyncEvent(String name) {
CronFriendPost cron = new CronFriendPost();
CronFriendPost.CronSpec cronSpec = new CronFriendPost.CronSpec();
cronSpec.setSuccessfulRetainLimit(5);
cronSpec.setDisableSyncList(new ArrayList<>());
cron.setSpec(cronSpec);
return client.fetch(CronFriendPost.class, "cron-friends-default")
.defaultIfEmpty(cron)
.flatMap(cronFriendPost -> {
var spec = cronFriendPost.getSpec();
int successfulRetainLimit = spec.getSuccessfulRetainLimit();
List<String> disableSyncList = spec.getDisableSyncList();
int sum = successfulRetainLimit == 0 ? 5 : successfulRetainLimit;
var listOptions = new ListOptions();
FieldSelector fieldSelector = FieldSelector.of(isNull("metadata.deletionTimestamp"));
if (!StringUtils.equals(name,"all")) {
fieldSelector = fieldSelector.andQuery(equal("metadata.name",name));
}
listOptions.setFieldSelector(fieldSelector);
return client.listAll(Link.class, listOptions, Sort.by("metadata.creationTimestamp"))
.doOnNext(link -> eventPublisher.publishEvent(new RssFeedSyncEvent(this, link,sum,disableSyncList)))
.then();
});
}
}