Skip to content

Commit

Permalink
Merge pull request #9 from r-follador/feature/corosapi
Browse files Browse the repository at this point in the history
Feature/corosapi
  • Loading branch information
r-follador authored Oct 19, 2024
2 parents eb3de8e + d06d474 commit 087096b
Show file tree
Hide file tree
Showing 8 changed files with 523 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/main/java/com/cubetrek/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
"/garminconnect",
"/polarconnect",
"/suuntoconnect",
"/corosconnect",
"/corosconnect/status",
"/stripe_hook").permitAll()
.anyRequest().authenticated()
)
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/com/cubetrek/database/UserThirdpartyConnect.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,22 @@ public class UserThirdpartyConnect {
@Column
private boolean suuntoEnabled = false;

@Column
private boolean corosEnabled = false;

@Column
String corosUserid;

@Convert(converter = DataEncryptDecryptConverter.class)
@Column
String corosAccessToken;

@Column
String corosRefreshToken;

@Column
Integer corosExpiresIn;


@Component
@Converter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ public interface UserThirdpartyConnectRepository extends JpaRepository<UserThird

UserThirdpartyConnect findByPolarUserid(String PolarUserid);

UserThirdpartyConnect findByCorosUserid(String CorosUserid);

UserThirdpartyConnect findBySuuntoUserid(String suuntoUserid);

UserThirdpartyConnect findByUser(Users user);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.cubetrek.upload.corosapi;

import com.cubetrek.database.UserThirdpartyConnect;
import com.cubetrek.database.Users;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;


@Component
public class CorosHistoricDataRequestedListener implements ApplicationListener<CorosHistoricDataRequestedListener.OnEvent> {

Logger logger = LoggerFactory.getLogger(CorosHistoricDataRequestedListener.class);

@Autowired
ApplicationEventPublisher eventPublisher;

final String corosBaseURL = "https://open.coros.com/"; //live

@Async
@Override
public void onApplicationEvent(OnEvent event) {
this.requestHistoricData(event);
}

final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");

public void requestHistoricData(OnEvent event) {
logger.info("Coros: Requesting Historic Data for user "+event.getUser().getId());

LocalDate currentDate = LocalDate.now();
String formattedCurrentDate = currentDate.format(formatter);
LocalDate date30DaysAgo = currentDate.minusDays(30);
String formattedDate30DaysAgo = date30DaysAgo.format(formatter);

final String requestUrl = corosBaseURL+"v2/coros/sport/list?token="+event.getUtc().getCorosAccessToken()
+"&openId="+event.getUtc().getCorosUserid()
+"&startDate="+formattedDate30DaysAgo
+"&endDate="+formattedCurrentDate;

logger.info("Request Url: "+requestUrl);

RestTemplate restTemplate = new RestTemplate();

String response = restTemplate.getForObject(requestUrl, String.class);

logger.info("response string: "+response);

ArrayList<String> fitUrls = new ArrayList<>();


try {
JsonNode rootNode = (new ObjectMapper()).readTree(response);
CorospingController.findFitUrls(rootNode, fitUrls);
} catch (JsonProcessingException e) {
logger.error("Coros: Failed getting historic data",e);
return;
}

for (String fitUrl : fitUrls) {
eventPublisher.publishEvent(new CorosNewFileEventListener.OnEvent(event.getUtc().getCorosUserid(), fitUrl));
}
}

@Getter
@Setter
static public class OnEvent extends ApplicationEvent {
Users user;
UserThirdpartyConnect utc;

public OnEvent(Users user, UserThirdpartyConnect utc) {
super(user);
this.user = user;
this.utc = utc;
}
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package com.cubetrek.upload.corosapi;

import com.cubetrek.ExceptionHandling;
import com.cubetrek.database.UserThirdpartyConnect;
import com.cubetrek.database.UserThirdpartyConnectRepository;
import com.cubetrek.database.Users;
import com.cubetrek.upload.StorageService;
import com.cubetrek.upload.UploadResponse;
import lombok.Getter;
import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.Objects;


@Component
public class CorosNewFileEventListener implements ApplicationListener<CorosNewFileEventListener.OnEvent> {

Logger logger = LoggerFactory.getLogger(CorosNewFileEventListener.class);

@Autowired
private UserThirdpartyConnectRepository userThirdpartyConnectRepository;
@Autowired
private StorageService storageService;

@Async
@Override
public void onApplicationEvent(OnEvent event) {
this.downloadFile(event);
}

public void downloadFile(OnEvent event) {

if (!event.getUrl().contains(".fit")) {
logger.error("Coros: will not download file, no Fit extenstion: "+event.getUrl());
return;
}

UserThirdpartyConnect userThirdpartyConnect = userThirdpartyConnectRepository.findByCorosUserid(event.getUserId());
if (userThirdpartyConnect == null){
logger.error("Coros: pull file failed: Unknown User id: "+event.getUserId());
return;
}
Users user = userThirdpartyConnect.getUser();
String filename = "coros-"+event.getUrl().substring(event.getUrl().lastIndexOf('/') + 1);
UploadResponse uploadResponse = null;
try {

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<byte[]> response = restTemplate.getForEntity(event.getUrl(), byte[].class);

if (response.getStatusCode().is2xxSuccessful()) {
uploadResponse = storageService.store(user, Objects.requireNonNull(response.getBody()), filename);
} else {
logger.error("Coros: pull file failed: User id: "+user.getId()+", User Coros ID '"+event.getUserId()+"', File Url '"+event.getUrl()+"'");
logger.error("Response status code: "+response.getStatusCode());
}
} catch (NullPointerException e) {
logger.error("Coros: pull file failed: User id: "+user.getId()+", User Polar ID '"+event.getUserId()+"', File Url '"+event.getUrl()+"'");
logger.error("Coros", e);
} catch (ExceptionHandling.FileNotAccepted e) {
//Already logged in StorageService, do nothing
}

if (uploadResponse != null)
logger.info("Coros: download file successful: User id: "+user.getId()+"; Track ID: "+uploadResponse.getTrackID());
else
logger.error("Coros: download file failed: User id: "+user.getId()+", User Polar Id '"+event.userId+"', CallbackURL '"+event.getUrl()+"'");
}

@Getter
@Setter
static public class OnEvent extends ApplicationEvent {
String userId;
String url;

public OnEvent(String userId, String url) {
super(userId);
this.userId = userId;
this.url = url;
}
}


}
Loading

0 comments on commit 087096b

Please sign in to comment.