feature: 开发 GitHub 项目监控, Star、Fork 有变更时钉钉通知.

pull/161/head
chen.ma 3 years ago
parent cce1719040
commit a7e431b461

@ -0,0 +1,33 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.github.dynamic-threadpool</groupId>
<artifactId>tools</artifactId>
<version>${revision}</version>
</parent>
<artifactId>open-change-tool</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
</dependency>
<dependency>
<groupId>com.dtflys.forest</groupId>
<artifactId>forest-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,18 @@
package com.github.dynamic.threadpool.openchange;
import org.springframework.context.annotation.Import;
import java.lang.annotation.*;
/**
* Change timed task.
*
* @author chen.ma
* @date 2021/10/31 13:39
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(OpenChangeNotifyConfig.class)
@Documented
public @interface EnableOpenChangeNotify {
}

@ -0,0 +1,21 @@
package com.github.dynamic.threadpool.openchange;
import com.dtflys.forest.annotation.Get;
/**
* GitHub remote.
*
* @author chen.ma
* @date 2021/10/31 10:45
*/
public interface GitHubRemote {
/**
* GitHub .
*
* @return
*/
@Get("https://api.github.com/repos/acmenlt/dynamic-threadpool")
OpenChangeInfo getGitHubItemInfo();
}

@ -0,0 +1,60 @@
package com.github.dynamic.threadpool.openchange;
import lombok.Data;
/**
* Open change info.
*
* @author chen.ma
* @date 2021/10/31 10:33
*/
@Data
public class OpenChangeInfo {
/**
* name
*/
private String name;
/**
* stars
*/
private Long stargazers_count;
/**
* forks
*/
private Long forks_count;
/**
* open issues
*/
private Long open_issues_count;
/**
* url
*/
private String html_url;
/**
* subscribers
*/
private Long subscribers_count;
/**
* default branch
*/
private String default_branch;
/**
* star_add
*/
private Long star_add;
/**
* fork_add
*/
private Long fork_add;
}

@ -0,0 +1,57 @@
package com.github.dynamic.threadpool.openchange;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.List;
/**
* Bootstrap properties.
*
* @author chen.ma
* @date 2021/6/22 09:14
*/
@Slf4j
@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = OpenChangeNotifyBootstrapProperties.PREFIX)
public class OpenChangeNotifyBootstrapProperties {
public static final String PREFIX = "spring.dynamic.thread-pool";
/**
* notifyInterval
*/
private Long notifyInterval;
/**
* notifys
*/
private List<NotifyConfig> notifys;
@Data
public static class NotifyConfig {
/**
* type
*/
private String type;
/**
* url
*/
private String url;
/**
* token
*/
private String token;
}
}

@ -0,0 +1,30 @@
package com.github.dynamic.threadpool.openchange;
import com.dtflys.forest.springboot.annotation.ForestScan;
import lombok.AllArgsConstructor;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* .
*
* @author chen.ma
* @date 2021/10/31 10:23
*/
@EnableScheduling
@AllArgsConstructor
@ImportAutoConfiguration(OpenChangeNotifyBootstrapProperties.class)
@ForestScan(basePackages = "com.github.dynamic.threadpool.openchange")
public class OpenChangeNotifyConfig {
private final GitHubRemote gitHubRemote;
private final OpenChangeNotifyBootstrapProperties bootstrapProperties;
@Bean
public OpenChangeTimedTask changeTimedTask() {
return new OpenChangeTimedTask(gitHubRemote, bootstrapProperties);
}
}

@ -0,0 +1,139 @@
package com.github.dynamic.threadpool.openchange;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.json.JSONUtil;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiRobotSendRequest;
import com.taobao.api.ApiException;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.scheduling.annotation.Scheduled;
import java.util.concurrent.TimeUnit;
/**
* Change timed task.
*
* @author chen.ma
* @date 2021/10/31 10:39
*/
@Slf4j
@RequiredArgsConstructor
public class OpenChangeTimedTask implements InitializingBean {
@NonNull
private final GitHubRemote gitHubRemote;
@NonNull
private final OpenChangeNotifyBootstrapProperties bootstrapProperties;
private OpenChangeInfo lastChangeInfo;
@Scheduled(cron = "0 0/5 * * * ?")
public void execute() {
OpenChangeInfo itemInfo = null;
try {
itemInfo = gitHubRemote.getGitHubItemInfo();
// 防止初始化调用 GitHub 403
if (lastChangeInfo == null) {
lastChangeInfo = itemInfo;
log.info("Init... GitHub Item Info :: {}", JSONUtil.toJsonStr(lastChangeInfo));
return;
}
} catch (Throwable ex) {
log.error("Failed to call GitHub API interface.", ex);
// 担心 GitHub 限制访问 403, 如异常则睡眠 5 分钟
ThreadUtil.sleep(5, TimeUnit.MINUTES);
return;
}
long addStarNum, addForkChange;
boolean starChange = (addStarNum = (itemInfo.getStargazers_count() - lastChangeInfo.getStargazers_count())) > 0;
if (starChange) {
itemInfo.setStar_add(addStarNum);
}
boolean forkChange = (addForkChange = (itemInfo.getForks_count() - lastChangeInfo.getForks_count())) > 0;
if (forkChange) {
itemInfo.setFork_add(addForkChange);
}
if (starChange == false && forkChange == false) {
log.info("Star and fork are unchanged.");
return;
}
sendDingMessage(itemInfo);
lastChangeInfo = itemInfo;
}
public void sendDingMessage(OpenChangeInfo itemInfo) {
String gitHubItemUrl = itemInfo.getHtml_url();
String markdownText = String.format(
"<font color='#2a9d8f'>[通知] </font> GitHub Star Fork 变更通知 \n\n" +
" --- \n\n " +
"<font color='#708090' size=2>项目名称HIPPO-JAVA</font> \n\n" +
"<font color='#708090' size=2>项目地址:[%s](%s)</font> \n\n" +
" --- \n\n " +
"<font color='#708090' size=2>Hippo Stars Add</font><font color='#FF8C00' size=2>%s</font> \n\n " +
"<font color='#708090' size=2>Hippo Forks Add</font><font color='#FF8C00' size=2>%s</font> \n\n " +
" --- \n\n " +
"<font color='#708090' size=2>Hippo Now Star[%d](" + gitHubItemUrl + "/stargazers)</font> \n\n" +
"<font color='#708090' size=2>Hippo Now Fork[%d](" + gitHubItemUrl + "/members)</font> \n\n" +
"<font color='#708090' size=2>Hippo Open Issue[%d](" + gitHubItemUrl + "/issues)</font> \n\n" +
"<font color='#708090' size=2>Hippo Subscribers Count[%d](" + gitHubItemUrl + "/watchers)</font> \n\n" +
" --- \n\n " +
"<font color='#708090' size=2>友情提示5 分钟内 Star Fork 有变更则通知(可配置)</font> \n\n" +
"<font color='#708090' size=2>OWNERLong-Tai</font> \n\n" +
" --- \n\n " +
"**播报时间:%s**",
itemInfo.getName().toUpperCase(),
gitHubItemUrl,
itemInfo.getStar_add() == null ? "-" : itemInfo.getStar_add().toString() + "+",
itemInfo.getFork_add() == null ? "-" : itemInfo.getFork_add().toString() + "+",
itemInfo.getStargazers_count(),
itemInfo.getForks_count(),
itemInfo.getOpen_issues_count(),
itemInfo.getSubscribers_count(),
DateUtil.now()
);
OpenChangeNotifyBootstrapProperties.NotifyConfig notifyConfig = bootstrapProperties.getNotifys().get(0);
String serverUrl = notifyConfig.getUrl() + notifyConfig.getToken();
DingTalkClient dingTalkClient = new DefaultDingTalkClient(serverUrl);
OapiRobotSendRequest request = new OapiRobotSendRequest();
request.setMsgtype("markdown");
OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
markdown.setTitle("GitHub Star Fork 变更通知");
markdown.setText(markdownText);
request.setMarkdown(markdown);
try {
dingTalkClient.execute(request);
} catch (ApiException ex) {
log.error("Ding failed to send message.", ex.getMessage());
}
}
@Override
public void afterPropertiesSet() throws Exception {
try {
lastChangeInfo = gitHubRemote.getGitHubItemInfo();
} catch (Throwable ex) {
log.error("Init error...");
}
log.info("Init success... GitHub Item Info :: {}", JSONUtil.toJsonStr(lastChangeInfo));
}
}
Loading…
Cancel
Save