This commit is contained in:
dengqn 2024-07-23 22:21:48 +08:00
parent 4716b9cdb4
commit 1eb8a769a6
4 changed files with 104 additions and 20 deletions

View File

@ -0,0 +1,30 @@
package com.dengqn.igps2xingzhe.config;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.io.Serial;
import java.io.Serializable;
/**
* @author dengqn
* @since 2024/7/20 11:23
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Configuration
@ConfigurationProperties(prefix = "user.giant")
public class Giant implements Serializable {
@Serial
private static final long serialVersionUID = 1996804203171936839L;
private Boolean enable;
private String username;
private String password;
}

View File

@ -7,6 +7,7 @@ import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.io.Serial;
import java.io.Serializable;
/**
@ -20,6 +21,7 @@ import java.io.Serializable;
@Configuration
@ConfigurationProperties(prefix = "user.igps")
public class IGPSport implements Serializable {
@Serial
private static final long serialVersionUID = 3004387713475397922L;
private String username;

View File

@ -10,8 +10,10 @@ import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.AsymmetricAlgorithm;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONUtil;
import com.dengqn.igps2xingzhe.config.Giant;
import com.dengqn.igps2xingzhe.config.IGPSport;
import com.dengqn.igps2xingzhe.config.XingZhe;
import com.dengqn.igps2xingzhe.vo.IGPSActivity;
@ -49,6 +51,7 @@ import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 同步
@ -68,24 +71,49 @@ public class Trigger {
@Value("${dataDir:/data}")
private String fileDir;
@Autowired
private Giant giant;
@Autowired
private XingZhe xingZhe;
@Autowired
private IGPSport igpSport;
private static final String GIANT_TOKEN_KEY = "GIANT_TOKEN_KEY";
private static final Map<String, Object> contextCache = new ConcurrentHashMap<>(4);
@GetMapping("/sync/igps2xingzhe")
public ResponseEntity<String> onSyncIGPS2XingZhe() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
// 1. 登录行者
xingzheLogin();
// 2. 登录igps
igpsLogin();
// 3. 登录捷安特
giantLogin();
// 3. 获取igps活动
syncIgpsActicities();
return ResponseEntity.ok("ok");
}
private void giantLogin() throws IOException {
if (!giant.getEnable()) {
return;
}
// clear cookie
httpClient.execute(ClassicRequestBuilder.get("https://ridelife.giant.com.cn/web/login.html/index.php/api/login").build());
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(CollUtil.toList(
new BasicNameValuePair("username", giant.getUsername()),
new BasicNameValuePair("password", giant.getPassword())
));
ClassicRequestBuilder igpsLoginReq = ClassicRequestBuilder
.post("https://ridelife.giant.com.cn/index.php/api/login")
.setEntity(formEntity);
CloseableHttpResponse response = (CloseableHttpResponse) httpClient.execute(igpsLoginReq.build());
String responseData = new String(IoUtil.readBytes(response.getEntity().getContent()));
String token = JSONUtil.parseObj(responseData).getStr("user_token");
contextCache.put(GIANT_TOKEN_KEY, token);
}
private void syncIgpsActicities() throws IOException {
CloseableHttpResponse activityResp = (CloseableHttpResponse) httpClient.execute(ClassicRequestBuilder.get("https://my.igpsport.com/Activity/MyActivityList").build());
String activityRespStr = new String(IoUtil.readBytes(activityResp.getEntity().getContent()));
@ -100,27 +128,49 @@ public class Trigger {
log.info("文件已存在" + filePath);
continue;
}
// 下载文件
String downloadUrl = "https://my.igpsport.com/fit/activity?type=0&rideid=" + activity.getRideId();
log.info("尝试下载" + downloadUrl);
CloseableHttpResponse downloadResp = (CloseableHttpResponse) httpClient.execute(ClassicRequestBuilder.get(downloadUrl).build());
InputStream downloadInputStream = downloadResp.getEntity().getContent();
long copied = IoUtil.copy(downloadInputStream, new FileOutputStream(filePath));
log.info("{} bytes copied", copied);
downloadFileFromIgps(activity, filePath);
// 上传到xingzhe
String uploadUrl = "https://www.imxingzhe.com/api/v4/upload_fits";
HttpEntity uploadForm = MultipartEntityBuilder.create()
.addPart("upload_file_name", new FileBody(new File(filePath)))
.addPart("title", new StringBody(activity.getFileName(), ContentType.create("text/plain", Charset.defaultCharset())))
.addPart("device", new StringBody("3", ContentType.create("text/plain", Charset.defaultCharset())))
.addPart("sport", new StringBody("3", ContentType.create("text/plain", Charset.defaultCharset())))
.build();
uploadToXingZhe(activity, filePath);
// sync to giant app
uploadToGiant(filePath);
}
}
CloseableHttpResponse uploadResponse = (CloseableHttpResponse) httpClient.execute(ClassicRequestBuilder.post(uploadUrl).setEntity(uploadForm).build());
log.info("upload result: {}", new String(IoUtil.readBytes(uploadResponse.getEntity().getContent())));
private void downloadFileFromIgps(IGPSActivity activity, String filePath) throws IOException {
String downloadUrl = "https://my.igpsport.com/fit/activity?type=0&rideid=" + activity.getRideId();
log.info("尝试下载" + downloadUrl);
CloseableHttpResponse downloadResp = (CloseableHttpResponse) httpClient.execute(ClassicRequestBuilder.get(downloadUrl).build());
InputStream downloadInputStream = downloadResp.getEntity().getContent();
long copied = IoUtil.copy(downloadInputStream, new FileOutputStream(filePath));
log.info("{} bytes copied", copied);
}
private void uploadToXingZhe(IGPSActivity activity, String filePath) throws IOException {
String uploadUrl = "https://www.imxingzhe.com/api/v4/upload_fits";
HttpEntity uploadForm = MultipartEntityBuilder.create()
.addPart("upload_file_name", new FileBody(new File(filePath)))
.addPart("title", new StringBody(activity.getFileName(), ContentType.create("text/plain", Charset.defaultCharset())))
.addPart("device", new StringBody("3", ContentType.create("text/plain", Charset.defaultCharset())))
.addPart("sport", new StringBody("3", ContentType.create("text/plain", Charset.defaultCharset())))
.build();
CloseableHttpResponse uploadResponse = (CloseableHttpResponse) httpClient.execute(ClassicRequestBuilder.post(uploadUrl).setEntity(uploadForm).build());
log.info("upload to xingzhe result: {}", new String(IoUtil.readBytes(uploadResponse.getEntity().getContent())));
}
private void uploadToGiant(String filePath) throws IOException {
if (giant.getEnable()) {
String giantUploadUrl = "https://ridelife.giant.com.cn/index.php/api/upload_fit";
cn.hutool.http.HttpRequest formed = HttpUtil.createPost(giantUploadUrl)
.form("files[]", new File[]{new File(filePath)})
.form("brand", "giant")
.form("device", "bike_computer")
.form("token", contextCache.getOrDefault(GIANT_TOKEN_KEY, "").toString());
cn.hutool.http.HttpResponse execute = formed.execute();
log.info("upload to giant result: {}", execute.body());
}
}

View File

@ -12,4 +12,6 @@ user.xingzhe.pubKey: "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDmuQkBbijudDAJgfffDe
user.igps.username: xxx
user.igps.password: xxx
user.giant.enable: false
user.giant.username: xxx
user.giant.password: xxx