All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.github.javaclub.addons.service.impl.ConfluenceApiServiceImpl Maven / Gradle / Ivy
/*
* @(#)ConfluenceApiServiceImpl.java 2024-03-11 16:50:50
*
* Copyright (c) 2024 - 2099. All Rights Reserved.
*
*/
package com.github.javaclub.addons.service.impl;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.github.javaclub.BizException;
import com.github.javaclub.addons.domain.ConfluencePageDO;
import com.github.javaclub.addons.domain.model.HtmlArticleFetchConfig;
import com.github.javaclub.addons.service.ConfluenceApiService;
import com.github.javaclub.addons.service.spider.WikiArticleSpider;
import com.github.javaclub.monitor.component.alarm.AlarmMonitor;
import com.github.javaclub.monitor.entity.HttpInvokeResult;
import com.github.javaclub.monitor.util.HttpClientUtils;
import com.github.javaclub.ossclient.OSS;
import com.github.javaclub.toolbox.ToolBox.Files;
import com.github.javaclub.toolbox.ToolBox.Maps;
import com.github.javaclub.toolbox.ToolBox.Objects;
import com.github.javaclub.toolbox.ToolBox.Strings;
import com.github.javaclub.toolbox.ToolBox.UUID;
import com.github.javaclub.toolbox.conf.CompositeAppConfigProperties;
import com.github.javaclub.toolbox.URL;
import com.github.javaclub.toolbox.spring.BeanFactory;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
/**
* ConfluenceApiServiceImpl
*
* @author Gerald Chen
* @version $Id: ConfluenceApiServiceImpl.java 2024-03-11 16:50:50 Exp $
*/
@Service
@Slf4j
public class ConfluenceApiServiceImpl implements ConfluenceApiService {
@Value("${system.configs.confluence.rest-api-key:cm9ib3Q6Szl5RHBnV2M4enY=}")
private String restApiKey = "cm9ib3Q6Szl5RHBnV2M4enY=";
@Value("${system.configs.confluence.rest-api-url:http://wiki.idev.vip/rest/api}")
private String restApiUrl = "http://wiki.idev.vip/rest/api";
private AlarmMonitor alarmMonitor;
AlarmMonitor getAlarmMonitor() {
if (null != alarmMonitor) {
return alarmMonitor;
}
alarmMonitor = BeanFactory.getInstance().getBean(AlarmMonitor.class);
return alarmMonitor;
}
@Override
public boolean createPage(String accessKey, ConfluencePageDO page) {
String authToken = Strings.concat("Basic ", Strings.noneBlank(accessKey, restApiKey));
if (null == page) {
return false;
}
Objects.requireNotEmpty(page.getPageTitle(), "获取到文章标题为空");
Objects.requireNotEmpty(page.getPageHtml(), "获取到文章内容为空");
String payload = page.payload();
String api = Strings.concat(restApiUrl, "/content");
Map headerMap = Maps.createStringMap(
"Authorization", authToken,
"Origin", "http://wiki.idev.vip",
"Referer", "http://wiki.idev.vip/display/collects"
);
HttpInvokeResult result = HttpClientUtils.postJsonWithAnyEcho(api, payload, headerMap);
if (null == result) {
return false;
}
if (!result.isHttpOK() && Strings.isNotBlank(result.getResponseText())) {
throw new BizException(result.getResponseText());
}
return result.isHttpOK();
}
@Override
public Map createPageByFetchArticleUrl(String url) throws Exception {
if (Strings.isBlank(url)) {
throw new BizException("链接地址不能为空!");
}
URL thisUrl = URL.valueOf(url);
if (null == thisUrl) {
throw new BizException("请输入正确的链接地址!");
}
ConfluencePageDO page = this.buildPageContent(url);
boolean flag = createPage(null, page);
if (!flag) {
throw new BizException("提交保存文章失败!");
}
return page.fetchResult();
}
ConfluencePageDO buildPageContent(String url) {
// 新的文章抓取实现逻辑
WikiArticleSpider spider = this.parseSpider(url);
ConfluencePageDO page = spider.fetch(url);
if (null == page || Strings.isBlank(page.getPageHtml())) {
throw new BizException("抓取文章内容为空!");
}
String pageHtml = Strings.cleanEmoji(page.getPageHtml());
page.setPageHtml(pageHtml);
page.setFetchUrl(url);
String imgTagWiki = " ";
String img1024WidthTagWiki = " ";
// 替换img标签,使其符合confluence最佳展示效果
Pattern pattern = Pattern.compile("");
Matcher matcher = pattern.matcher(page.getPageHtml());
StringBuffer sb = new StringBuffer();
int imageNum = 0;
while (matcher.find()) {
String imgUrl = matcher.group(1);
try {
Map params = Maps.newHashMap(3);
String fetchUrl = getFetchUrl(url, imgUrl);
if (Strings.isBlank(fetchUrl)) {
String imgTag = Strings.format(imgTagWiki, imgUrl, imgUrl);
matcher.appendReplacement(sb, Matcher.quoteReplacement(imgTag));
continue;
}
byte[] bytes = Files.fetchUrlAsBytes(fetchUrl);
params.put("total", bytes.length);
String filename = Strings.concat(UUID.randomUUID(), getImageExtention(fetchUrl));
String imageUrl = OSS.get().upload(bytes, filename, params);
if (Strings.isNotBlank(imageUrl)) {
int[] widthAndHeight = Files.getWidthAndHeightByImageBytes(bytes);
boolean widthGt1024 = null != widthAndHeight && widthAndHeight.length > 0 && widthAndHeight[0] > 1024;
String imgTagFormat = widthGt1024 ? img1024WidthTagWiki : imgTagWiki;
String imgTag = Strings.format(imgTagFormat, imageUrl, imageUrl);
matcher.appendReplacement(sb, Matcher.quoteReplacement(imgTag));
imageNum++;
}
} catch (Exception e) {
String imgTag = Strings.format(imgTagWiki, imgUrl, imgUrl);
matcher.appendReplacement(sb, Matcher.quoteReplacement(imgTag));
continue;
}
}
matcher.appendTail(sb);
page.setImagesNum(imageNum);
page.setPageHtml(cleanInvalidHtml4Editor(sb.toString()));
if (log.isInfoEnabled()) {
log.info("Page HTML: {}", page.getPageHtml());
}
return page;
}
String getFetchUrl(String url, String imgUrl) {
if (imgUrl.startsWith("http://") || imgUrl.startsWith("https://")) {
return imgUrl;
}
if (imgUrl.startsWith("//")) {
URL _tURL = URL.valueOf(url);
return Strings.concat(_tURL.getProtocol(), ":", imgUrl);
}
return imgUrl;
}
String getImageExtention(String url) {
String ext = Files.getExtension(url);
if (Strings.endsWith(ext, new String[] {".jpg", ".jpeg", ".png", ".gif"})) {
return ext.toLowerCase();
}
return ".jpg";
}
String cleanInvalidHtml4Editor(String content) {
String text = content.replaceAll(" ", Strings.EMPTY);
text = text.replaceAll(" ", " ");
text = text.replaceAll(" ]*>", " ");
text = text.replaceAll(" ", " ");
text = text.replaceAll(" ]*>", " ");
text = text.replaceAll("]*>", Strings.EMPTY);
text = text.replaceAll(" ", Strings.EMPTY);
text = Strings.cleanEmoji(text);
// log.warn("Cleaned HTML: {}", text);
return text;
}
@SuppressWarnings("unchecked")
@SneakyThrows
WikiArticleSpider parseSpider(String url) {
Map confMap = parseFetchRulesMap();
for (Map.Entry e : confMap.entrySet()) {
if (!url.contains(e.getValue().getUrlMatchSegment())) {
continue;
}
Class fetcherClass = Objects.forName(e.getValue().getHtmlFetcherClass());
WikiArticleSpider spider = BeanFactory.getInstance().getBean(fetcherClass);
spider.setConfigKey(e.getKey());
return spider;
}
throw new BizException("No matched WikiArticleSpider");
}
Map parseFetchRulesMap() {
String json = CompositeAppConfigProperties.getInstance().getValue("wiki-article-spider.json");
Map map = JSONObject.parseObject(json, new TypeReference>(){});
Objects.requireTrue(null != map && 0 < map.size(), "Spider规则配置为空!");
return map;
}
public static void main(String[] args) {
try {
ConfluenceApiServiceImpl api = new ConfluenceApiServiceImpl();
String url = "https://www.jb51.net/article/34888.htm";
Map map = api.createPageByFetchArticleUrl(url);
System.out.println(JSON.toJSONString(map));
} catch (Exception e) {
e.printStackTrace();
}
}
}