江体小程序和zlb接口开发 #1

Merged
XiangZ merged 32 commits from feat/script_v1 into master 2026-05-10 09:06:35 +00:00
11 changed files with 318 additions and 4 deletions
Showing only changes of commit b8083381b6 - Show all commits

View File

@@ -145,6 +145,14 @@
<artifactId>alibaba-dingtalk-service-sdk</artifactId> <artifactId>alibaba-dingtalk-service-sdk</artifactId>
<version>2.0.0</version> <version>2.0.0</version>
</dependency> </dependency>
<!-- aliyun dns解析 -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>alidns20150109</artifactId>
<version>3.4.7</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -0,0 +1,17 @@
package com.xiang.common.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@ConfigurationProperties(prefix = "aliyun.dns")
@Data
public class AliyunDnsPropertyConfig {
private List<String> RR;
private String rootDomain;
}

View File

@@ -3,8 +3,6 @@ package com.xiang.common.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.xiang.common.utils.RedisService;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;

View File

@@ -0,0 +1,20 @@
package com.xiang.common.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* @Author: xiang
* @Date: 2026-01-04 16:13
*/
@Getter
@RequiredArgsConstructor
public enum DingTalkBizTypeEnum implements BaseDingTalkBizType {
JT("venue", "江南体育中心"),
XB("xb", "股票基金变化通知"),
SCRIPT("script", "脚本运行通知群")
;
private final String bizName;
private final String desc;
}

View File

@@ -0,0 +1,19 @@
package com.xiang.common.factory;
import com.xiang.common.config.DingTalkRobotProperties;
import com.xiang.common.enums.DingTalkBizTypeEnum;
import com.xiang.common.utils.dingTalk.AbstractDingTalkFactory;
import com.xiang.common.utils.dingTalk.DingTalkSender;
import org.springframework.stereotype.Service;
@Service
public class ScriptDingTalkFactory extends AbstractDingTalkFactory {
public ScriptDingTalkFactory(DingTalkRobotProperties dingTalkRobotProperties, DingTalkSender dingTalkSender) {
super(dingTalkRobotProperties, dingTalkSender);
}
@Override
public void sendMsg(String msg) {
getClient(DingTalkBizTypeEnum.SCRIPT).sendDingTalkMsg(msg);
}
}

View File

@@ -0,0 +1,21 @@
package com.xiang.common.utils;
import com.google.common.collect.Maps;
import java.io.IOException;
import java.util.Map;
/**
* @Author: xiang
* @Date: 2025-06-10 16:50
*/
public class IpUtils {
private final static String PUBLIC_IP_URL = "https://api-ipv4.ip.sb/ip";
public static String getPublicIp() throws IOException {
Map<String, String> header = Maps.newHashMap();
header.put("User-Agent", "Mozilla/5.0");
return HttpService.doGet(PUBLIC_IP_URL, header, null).trim();
}
}

View File

@@ -0,0 +1,31 @@
package com.xiang.service.module.domain.schedule;
import com.xiang.common.utils.IpUtils;
import com.xiang.service.module.domain.service.IDomainService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Scheduled;
@Slf4j
@RequiredArgsConstructor
public class DomainDynamicAnalysisTask {
private final IDomainService IDomainService;
@Scheduled(cron = "0 0/30 * * * ? ")
public void dynamicDomainSchedule() {
String publicIp = "";
try {
publicIp = IpUtils.getPublicIp();
} catch (Exception e) {
log.error("获取公网ip失败", e);
}
if (StringUtils.isNotBlank(publicIp)) {
try {
IDomainService.dynamicDomainAnalysis(publicIp);
} catch (Exception e) {
log.error("动态解析公网ip失败, ip:{}", publicIp, e);
}
}
}
}

View File

@@ -0,0 +1,45 @@
package com.xiang.service.module.domain.server;
import com.xiang.common.utils.IpUtils;
import com.xiang.service.module.domain.service.IDomainService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/script/domain")
public class DomainController {
private final IDomainService domainService;
@GetMapping("/ddns")
public void dynamicDomainAnalysis() {
String publicIp = "";
try {
publicIp = IpUtils.getPublicIp();
} catch (Exception e) {
log.error("获取公网ip失败", e);
}
if (StringUtils.isNotBlank(publicIp)) {
try {
domainService.dynamicDomainAnalysis(publicIp);
} catch (Exception e) {
log.error("动态解析公网ip失败, ip:{}", publicIp, e);
}
}
}
@GetMapping("/ddns4ip")
public void dynamicDomainAnalysis(@RequestParam("ip") String ip, @RequestParam("rr") String rr) {
try {
domainService.dynamicDomainAnalysis(ip, rr);
} catch (Exception e) {
log.error("动态解析公网ip失败, ip:{}", ip, e);
}
}
}

View File

@@ -0,0 +1,15 @@
package com.xiang.service.module.domain.service;
/**
* @Author: xiang
* @Date: 2025-06-10 16:48
*/
public interface IDomainService {
/**
* 动态域名解析
* @param publicIp 动态ip
*/
void dynamicDomainAnalysis(String publicIp) throws Exception;
void dynamicDomainAnalysis(String publicIp, String rr) throws Exception;
}

View File

@@ -0,0 +1,111 @@
package com.xiang.service.module.domain.service;
import com.aliyun.alidns20150109.Client;
import com.aliyun.alidns20150109.models.AddDomainRecordRequest;
import com.aliyun.alidns20150109.models.DescribeSubDomainRecordsRequest;
import com.aliyun.alidns20150109.models.DescribeSubDomainRecordsResponse;
import com.aliyun.alidns20150109.models.DescribeSubDomainRecordsResponseBody;
import com.aliyun.alidns20150109.models.UpdateDomainRecordRequest;
import com.aliyun.teaopenapi.models.Config;
import com.xiang.common.config.AliyunDnsPropertyConfig;
import com.xiang.common.factory.ScriptDingTalkFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Author: xiang
* @Date: 2025-06-10 16:48
*/
@Service
@Slf4j
@RequiredArgsConstructor
public class IDomainServiceImpl implements IDomainService {
private static final String ACCESS_KEY_ID = "LTAI5tDMjaVF8Bbqcpp4dmvP";
private static final String ACCESS_KEY_SECRET = "nkmnaNjWQy5984C5kjyS0oDmdMKGQd";
/**
* 根域名
*/
@Value("${aliyun.dns.rootDomain}")
private String rootDomain;
/**
* 主机记录,例如 home.example.com
*/
private final AliyunDnsPropertyConfig aliyunDnsPropertyConfig;
private static final String TYPE = "A";
private final ScriptDingTalkFactory dingTalkService;
@Override
public void dynamicDomainAnalysis(String publicIp) throws Exception {
Client client = createClient();
for (String rr : aliyunDnsPropertyConfig.getRR()) {
record(client, publicIp, rr);
}
}
@Override
public void dynamicDomainAnalysis(String publicIp, String rr) throws Exception {
Client client = createClient();
record(client, publicIp, rr);
}
private void record(Client client, String publicIp, String rr) throws Exception{
// 查询记录
DescribeSubDomainRecordsRequest query = new DescribeSubDomainRecordsRequest()
.setSubDomain(rr + "." + rootDomain)
.setType(TYPE);
DescribeSubDomainRecordsResponse response = client.describeSubDomainRecords(query);
List<DescribeSubDomainRecordsResponseBody.DescribeSubDomainRecordsResponseBodyDomainRecordsRecord> records =
response.getBody().getDomainRecords().getRecord();
if (records.isEmpty()) {
log.info("未找到记录,添加记录..., ip:{}", publicIp);
addDnsRecord(client, publicIp, rr);
dingTalkService.sendMsg("动态解析公网ip成功域名" + rr + "." + rootDomain + ", 新ip:" + publicIp);
} else {
String recordId = records.get(0).getRecordId();
String currentValue = records.get(0).getValue();
if (!publicIp.equals(currentValue)) {
log.info("IP变更更新记录...,ip:{}", publicIp);
updateDnsRecord(client, recordId, publicIp, rr);
dingTalkService.sendMsg("动态解析公网ip成功域名" + rr + "." + rootDomain + ", 新ip:" + publicIp);
} else {
log.info("ip未变更无需修改ip:{}", publicIp);
}
}
}
private Client createClient() throws Exception {
Config config = new Config()
.setAccessKeyId(ACCESS_KEY_ID)
.setAccessKeySecret(ACCESS_KEY_SECRET)
.setEndpoint("alidns.cn-hangzhou.aliyuncs.com");
return new Client(config);
}
private void updateDnsRecord(Client client, String recordId, String newIp, String rr) throws Exception {
UpdateDomainRecordRequest request = new UpdateDomainRecordRequest()
.setRecordId(recordId)
.setRR(rr)
.setType(TYPE)
.setValue(newIp);
client.updateDomainRecord(request);
log.info("更新成功: newIP:{}", newIp);
}
private void addDnsRecord(Client client, String ip, String rr) throws Exception {
AddDomainRecordRequest request = new AddDomainRecordRequest()
.setDomainName(rootDomain)
.setRR(rr)
.setType(TYPE)
.setValue(ip);
client.addDomainRecord(request);
log.info("添加成功: ip:{}", ip);
}
}

View File

@@ -15,11 +15,40 @@ spring:
host: r-bp1wt59a6nfyt4e3ltpd.redis.rds.aliyuncs.com host: r-bp1wt59a6nfyt4e3ltpd.redis.rds.aliyuncs.com
port: 6379 port: 6379
password: Xiang0000 password: Xiang0000
database: 11 database: 10
timeout: 3000 timeout: 3000
lettuce: lettuce:
pool: pool:
max-active: 20 max-active: 20
max-idle: 10 max-idle: 10
min-idle: 2 min-idle: 2
max-wait: 3000 max-wait: 3000
aliyun:
dns:
rootDomain: xiangtech.xyz
RR:
- local
dingtalk:
robot:
properties:
venue:
name: 江南体育中心通知群
token: 6a218646972c684c75832b0229ea93a234778af537d7469ce96bef290faf530e
secret: SEC9018755ba86d3e5c1ed2fbfa1d6953d84bb2a6c8ebe7ed4e318457bfed5e0465
users:
- 450841600726084717
script:
name: 脚本运行通知群
token: 797be7f32062e31dec1d567f8b490a5649a5366083618e236c7a1263df1f4af3
secret: SEC9aca642c0c29c9da261462869c464d34623247583d98fc82343a0a4464abbe91
users:
- 450841600726084717
xb:
name: 股票基金变化通知群
token: ad21ead99f0fdc63aa00d6732b7b0888c17590f7612c68297edfcb71844d1437
secret: SECc09d8aad6635f1a4cbadb7c0ab365523c46299f138438cd885e445e0f5f4d730
users:
- 450841600726084717