Added new end point, edited getEmails to be Async all and return 202 status code
This commit is contained in:
@@ -23,5 +23,9 @@ public class APIConstants {
|
|||||||
public static final String API_URL_USER_SET_BOOKMARK = "/user/setBookmark";
|
public static final String API_URL_USER_SET_BOOKMARK = "/user/setBookmark";
|
||||||
public static final String API_URL_USER_DELETE_BOOKMARK = "/user/deleteBookmark";
|
public static final String API_URL_USER_DELETE_BOOKMARK = "/user/deleteBookmark";
|
||||||
public static final String API_URL_USER_DELETE_ALL_BOOKMARK = "/user/deleteAllBookmark";
|
public static final String API_URL_USER_DELETE_ALL_BOOKMARK = "/user/deleteAllBookmark";
|
||||||
|
public static final String API_URL_GMAIL_GET_EMAILS = "/gmail/getEmails";
|
||||||
|
public static final String API_URL_GMAIL_GET_SCANNED_EMAILS = "/gmail/getScannedEmails";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,10 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
import org.springframework.web.servlet.view.RedirectView;
|
import org.springframework.web.servlet.view.RedirectView;
|
||||||
import static com.safeqr.app.constants.APIConstants.*;
|
import static com.safeqr.app.constants.APIConstants.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.Thread;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.CompletionException;
|
||||||
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@@ -100,14 +102,32 @@ public class GmailController {
|
|||||||
return new ResponseEntity<>(json.toString(), HttpStatus.OK);
|
return new ResponseEntity<>(json.toString(), HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(value = "/gmail/getEmails", produces = MediaType.APPLICATION_JSON_VALUE)
|
@GetMapping(value = API_URL_GMAIL_GET_SCANNED_EMAILS, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
public ResponseEntity<?> getUserEmails(@RequestHeader(name = "accessToken") String accessToken) throws IOException, InterruptedException {
|
public ResponseEntity<ScannedGmailResponseDto> getUserScannedEmails(@RequestHeader(name = "X-USER-ID") String userId) {
|
||||||
|
logger.info("Invoking GET User scanned Emails endpoint");
|
||||||
|
return ResponseEntity.ok(gmailService.fetchScannedGmail(userId));
|
||||||
|
}
|
||||||
|
@GetMapping(value = API_URL_GMAIL_GET_EMAILS, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
public ResponseEntity<?> getUserEmails(@RequestHeader(name = "accessToken") String accessToken,
|
||||||
|
@RequestHeader(name = "refreshToken") String refreshToken,
|
||||||
|
@RequestHeader(name = "X-USER-ID") String userId
|
||||||
|
) {
|
||||||
logger.info("Invoking GET Scan User Emails endpoints");
|
logger.info("Invoking GET Scan User Emails endpoints");
|
||||||
if (accessToken == null || accessToken.isEmpty()) {
|
if (accessToken == null || accessToken.isEmpty()) {
|
||||||
return new ResponseEntity<>("Access token is missing", HttpStatus.BAD_REQUEST);
|
return new ResponseEntity<>("Access token is missing", HttpStatus.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
logger.info("accessToken -> {}", accessToken);
|
||||||
|
logger.info("refreshToken -> {}", refreshToken);
|
||||||
|
logger.info("userId -> {}", userId);
|
||||||
|
|
||||||
return new ResponseEntity<>(gmailService.getEmail(accessToken), HttpStatus.OK);
|
CompletableFuture.runAsync(() -> {
|
||||||
|
gmailService.getEmailAsync(userId, accessToken, refreshToken);
|
||||||
|
}).exceptionally(throwable -> {
|
||||||
|
logger.error("Unexpected error occurred while processing emails", throwable);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
return new ResponseEntity<>("Scan Gmail Request is being processed", HttpStatus.ACCEPTED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.safeqr.app.gmail.entity;
|
||||||
|
|
||||||
|
import com.safeqr.app.qrcode.entity.QRCodeEntity;
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.hibernate.annotations.UuidGenerator;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Table(name = "gmail_cid", schema = "safeqr")
|
||||||
|
public class GmailCidEntity {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(generator = "UUID")
|
||||||
|
@UuidGenerator
|
||||||
|
@Column(updatable = false, nullable = false)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
@Column(name = "gmail_id")
|
||||||
|
private UUID gmailId;
|
||||||
|
|
||||||
|
@Column(name = "cid")
|
||||||
|
private String cid;
|
||||||
|
|
||||||
|
@Column(name = "attachment_id")
|
||||||
|
private String attachmentId;
|
||||||
|
|
||||||
|
@Column(name = "decoded_content")
|
||||||
|
private String decodedContent;
|
||||||
|
|
||||||
|
@Column(name = "qr_code_id")
|
||||||
|
private UUID qrCodeId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.safeqr.app.gmail.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.hibernate.annotations.UuidGenerator;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Table(name = "gmail_emails", schema = "safeqr")
|
||||||
|
public class GmailEmailEntity {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(generator = "UUID")
|
||||||
|
@UuidGenerator
|
||||||
|
@Column(updatable = false, nullable = false)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
@Column(name = "user_id")
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
@Column(name = "message_id")
|
||||||
|
private String messageId;
|
||||||
|
|
||||||
|
@Column(name = "thread_id")
|
||||||
|
private String threadId;
|
||||||
|
|
||||||
|
@Column(name = "history_id")
|
||||||
|
private Long historyId;
|
||||||
|
|
||||||
|
@Column(name= "subject")
|
||||||
|
private String subject;
|
||||||
|
|
||||||
|
@Column(name = "date_received")
|
||||||
|
private OffsetDateTime dateReceived;
|
||||||
|
|
||||||
|
@Column(name = "date_created")
|
||||||
|
private OffsetDateTime dateCreated;
|
||||||
|
|
||||||
|
@PrePersist
|
||||||
|
public void prePersist() {
|
||||||
|
dateCreated = OffsetDateTime.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.safeqr.app.gmail.entity;
|
||||||
|
|
||||||
|
import com.safeqr.app.qrcode.entity.QRCodeEntity;
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.hibernate.annotations.UuidGenerator;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Table(name = "gmail_urls", schema = "safeqr")
|
||||||
|
public class GmailUrlEntity {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(generator = "UUID")
|
||||||
|
@UuidGenerator
|
||||||
|
@Column(updatable = false, nullable = false)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
@Column(name = "gmail_id")
|
||||||
|
private UUID gmailId;
|
||||||
|
|
||||||
|
@Column(name = "image_url")
|
||||||
|
private String imageUrl;
|
||||||
|
|
||||||
|
@Column(name = "decoded_content")
|
||||||
|
private String decodedContent;
|
||||||
|
|
||||||
|
@Column(name = "qr_code_id")
|
||||||
|
private UUID qrCodeId;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.safeqr.app.gmail.model;
|
package com.safeqr.app.gmail.model;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.safeqr.app.qrcode.model.QRCodeModel;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -8,6 +9,7 @@ import java.util.List;
|
|||||||
@Data
|
@Data
|
||||||
public class EmailMessage {
|
public class EmailMessage {
|
||||||
private String messageId;
|
private String messageId;
|
||||||
|
private String threadId;
|
||||||
private String subject;
|
private String subject;
|
||||||
private String historyId;
|
private String historyId;
|
||||||
private String date;
|
private String date;
|
||||||
@@ -18,13 +20,18 @@ public class EmailMessage {
|
|||||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
List<QRCodeByURL> qrCodeByURL;
|
List<QRCodeByURL> qrCodeByURL;
|
||||||
|
|
||||||
public EmailMessage(String messageId, String subject, String historyId, String date) {
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
List<QRCodeModel<?>> decodedContentsDetails;
|
||||||
|
|
||||||
|
public EmailMessage(String messageId, String threadId ,String subject, String historyId, String date) {
|
||||||
this.messageId = messageId;
|
this.messageId = messageId;
|
||||||
|
this.threadId = threadId;
|
||||||
this.subject = subject;
|
this.subject = subject;
|
||||||
this.historyId = historyId;
|
this.historyId = historyId;
|
||||||
this.date = date;
|
this.date = date;
|
||||||
this.qrCodeByContentId = new ArrayList<>();
|
this.qrCodeByContentId = new ArrayList<>();
|
||||||
this.qrCodeByURL = new ArrayList<>();
|
this.qrCodeByURL = new ArrayList<>();
|
||||||
|
this.decodedContentsDetails = new ArrayList<>();
|
||||||
}
|
}
|
||||||
public void addQRCodeByContentId(QRCodeByContentId qrCode) {
|
public void addQRCodeByContentId(QRCodeByContentId qrCode) {
|
||||||
this.qrCodeByContentId.add(qrCode);
|
this.qrCodeByContentId.add(qrCode);
|
||||||
@@ -34,6 +41,10 @@ public class EmailMessage {
|
|||||||
this.qrCodeByURL.add(qrCode);
|
this.qrCodeByURL.add(qrCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addQRCodeModel(QRCodeModel<?> qrCode) {
|
||||||
|
this.decodedContentsDetails.add(qrCode);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasQRCodes() {
|
public boolean hasQRCodes() {
|
||||||
return !qrCodeByContentId.isEmpty() || !qrCodeByURL.isEmpty();
|
return !qrCodeByContentId.isEmpty() || !qrCodeByURL.isEmpty();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.safeqr.app.gmail.model;
|
package com.safeqr.app.gmail.model;
|
||||||
|
|
||||||
|
import com.safeqr.app.qrcode.model.QRCodeModel;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -14,4 +15,8 @@ public class QRCodeByContentId {
|
|||||||
private String attachmentId;
|
private String attachmentId;
|
||||||
private List<String> decodedContent;
|
private List<String> decodedContent;
|
||||||
private int totalQRCodeFound;
|
private int totalQRCodeFound;
|
||||||
|
|
||||||
|
public List<String> getDecodedContent() {
|
||||||
|
return decodedContent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.safeqr.app.gmail.repository;
|
||||||
|
|
||||||
|
import com.safeqr.app.gmail.entity.GmailCidEntity;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface GmailCidRespository extends JpaRepository<GmailCidEntity, UUID> {
|
||||||
|
List<GmailCidEntity> findByGmailId(UUID gmailId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.safeqr.app.gmail.repository;
|
||||||
|
|
||||||
|
|
||||||
|
import com.safeqr.app.gmail.entity.GmailEmailEntity;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface GmailEmailRespository extends JpaRepository<GmailEmailEntity, UUID> {
|
||||||
|
List<GmailEmailEntity> findByUserId(String userId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.safeqr.app.gmail.repository;
|
||||||
|
|
||||||
|
import com.safeqr.app.gmail.entity.GmailUrlEntity;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface GmailUrlsRespository extends JpaRepository<GmailUrlEntity, UUID> {
|
||||||
|
List<GmailUrlEntity> findByGmailId(UUID gmailId);
|
||||||
|
}
|
||||||
@@ -1,32 +1,53 @@
|
|||||||
package com.safeqr.app.gmail.service;
|
package com.safeqr.app.gmail.service;
|
||||||
|
|
||||||
import com.google.api.client.auth.oauth2.BearerToken;
|
import com.google.api.client.auth.oauth2.BearerToken;
|
||||||
|
import com.google.api.client.auth.oauth2.ClientParametersAuthentication;
|
||||||
|
import com.google.api.client.auth.oauth2.Credential;
|
||||||
|
|
||||||
|
import com.google.api.client.auth.oauth2.TokenResponse;
|
||||||
|
import com.google.api.client.googleapis.auth.oauth2.GoogleRefreshTokenRequest;
|
||||||
|
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
|
||||||
|
import com.google.api.client.http.GenericUrl;
|
||||||
import com.google.api.client.http.HttpTransport;
|
import com.google.api.client.http.HttpTransport;
|
||||||
|
import com.google.api.client.http.javanet.NetHttpTransport;
|
||||||
|
import com.google.api.client.json.JsonFactory;
|
||||||
|
import com.google.api.client.json.gson.GsonFactory;
|
||||||
|
import com.google.api.services.gmail.Gmail;
|
||||||
import com.google.api.services.gmail.model.*;
|
import com.google.api.services.gmail.model.*;
|
||||||
import com.google.zxing.*;
|
import com.google.zxing.*;
|
||||||
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
|
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
|
||||||
import com.google.zxing.common.HybridBinarizer;
|
import com.google.zxing.common.HybridBinarizer;
|
||||||
import com.google.zxing.multi.qrcode.QRCodeMultiReader;
|
import com.google.zxing.multi.qrcode.QRCodeMultiReader;
|
||||||
|
import com.google.zxing.qrcode.encoder.QRCode;
|
||||||
import com.safeqr.app.gmail.dto.ScannedGmailResponseDto;
|
import com.safeqr.app.gmail.dto.ScannedGmailResponseDto;
|
||||||
|
import com.safeqr.app.gmail.entity.GmailCidEntity;
|
||||||
|
import com.safeqr.app.gmail.entity.GmailEmailEntity;
|
||||||
|
import com.safeqr.app.gmail.entity.GmailUrlEntity;
|
||||||
import com.safeqr.app.gmail.model.EmailMessage;
|
import com.safeqr.app.gmail.model.EmailMessage;
|
||||||
import com.safeqr.app.gmail.model.QRCodeByContentId;
|
import com.safeqr.app.gmail.model.QRCodeByContentId;
|
||||||
import com.safeqr.app.gmail.model.QRCodeByURL;
|
import com.safeqr.app.gmail.model.QRCodeByURL;
|
||||||
|
import com.safeqr.app.gmail.repository.GmailCidRespository;
|
||||||
|
import com.safeqr.app.gmail.repository.GmailEmailRespository;
|
||||||
|
import com.safeqr.app.gmail.repository.GmailUrlsRespository;
|
||||||
|
import com.safeqr.app.qrcode.model.QRCodeModel;
|
||||||
|
import com.safeqr.app.qrcode.service.QRCodeTypeService;
|
||||||
|
import com.safeqr.app.user.service.UserService;
|
||||||
|
import com.safeqr.app.utils.DateParsingUtils;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
import org.jsoup.Jsoup;
|
import org.jsoup.Jsoup;
|
||||||
import org.jsoup.nodes.Document;
|
import org.jsoup.nodes.Document;
|
||||||
import org.jsoup.select.Elements;
|
import org.jsoup.select.Elements;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.dao.DataIntegrityViolationException;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import com.google.api.client.auth.oauth2.Credential;
|
|
||||||
import com.google.api.client.http.javanet.NetHttpTransport;
|
|
||||||
import com.google.api.client.json.JsonFactory;
|
|
||||||
import com.google.api.client.json.gson.GsonFactory;
|
|
||||||
import com.google.api.services.gmail.Gmail;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.*;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.lang.Thread;
|
import java.lang.Thread;
|
||||||
import java.net.ConnectException;
|
import java.net.ConnectException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
@@ -35,50 +56,288 @@ import java.net.http.HttpClient;
|
|||||||
import java.net.http.HttpRequest;
|
import java.net.http.HttpRequest;
|
||||||
import java.net.http.HttpResponse;
|
import java.net.http.HttpResponse;
|
||||||
import java.net.http.HttpTimeoutException;
|
import java.net.http.HttpTimeoutException;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static com.google.api.client.googleapis.auth.oauth2.GoogleOAuthConstants.TOKEN_SERVER_URL;
|
||||||
import static com.safeqr.app.constants.APIConstants.APPLICATION_NAME;
|
import static com.safeqr.app.constants.APIConstants.APPLICATION_NAME;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class GmailService {
|
public class GmailService {
|
||||||
|
@Value("${gmail.client.clientId}")
|
||||||
|
private String clientId;
|
||||||
|
|
||||||
|
@Value("${gmail.client.clientSecret}")
|
||||||
|
private String clientSecret;
|
||||||
|
|
||||||
|
private final GmailEmailRespository gmailEmailRespository;
|
||||||
|
private final GmailCidRespository gmailCidRespository;
|
||||||
|
private final GmailUrlsRespository gmailUrlsRespository;
|
||||||
|
private final QRCodeTypeService qrCodeTypeService;
|
||||||
|
private final UserService userService;
|
||||||
private static final Logger logger = LoggerFactory.getLogger(GmailService.class);
|
private static final Logger logger = LoggerFactory.getLogger(GmailService.class);
|
||||||
private static final HttpTransport httpTransport = new NetHttpTransport();
|
private static final HttpTransport httpTransport = new NetHttpTransport();
|
||||||
private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
|
private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
|
||||||
private static final long MAX_RESULTS = 100L;
|
private static final long MAX_RESULTS = 100L;
|
||||||
|
|
||||||
private Gmail getGmailService(String accessToken) {
|
public GmailService(GmailEmailRespository gmailEmailRespository,
|
||||||
Credential userCredentials = new Credential(BearerToken.authorizationHeaderAccessMethod()).setAccessToken(accessToken);
|
GmailCidRespository gmailCidRespository,
|
||||||
|
GmailUrlsRespository gmailUrlsRespository,
|
||||||
|
QRCodeTypeService qrCodeTypeService,
|
||||||
|
UserService userService) {
|
||||||
|
this.gmailEmailRespository = gmailEmailRespository;
|
||||||
|
this.gmailCidRespository = gmailCidRespository;
|
||||||
|
this.gmailUrlsRespository = gmailUrlsRespository;
|
||||||
|
this.qrCodeTypeService = qrCodeTypeService;
|
||||||
|
this.userService = userService;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Gmail getGmailService(String accessToken, String refreshToken) throws IOException {
|
||||||
|
Credential userCredentials = new Credential.Builder(BearerToken.authorizationHeaderAccessMethod())
|
||||||
|
.setTransport(httpTransport)
|
||||||
|
.setJsonFactory(JSON_FACTORY)
|
||||||
|
.setTokenServerUrl(new GenericUrl(TOKEN_SERVER_URL))
|
||||||
|
.setClientAuthentication(new ClientParametersAuthentication(clientId, clientSecret))
|
||||||
|
.build()
|
||||||
|
.setAccessToken(accessToken)
|
||||||
|
.setRefreshToken(refreshToken);
|
||||||
|
|
||||||
return new Gmail.Builder(httpTransport, JSON_FACTORY, userCredentials)
|
return new Gmail.Builder(httpTransport, JSON_FACTORY, userCredentials)
|
||||||
.setApplicationName(APPLICATION_NAME)
|
.setApplicationName(APPLICATION_NAME)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
// Renew the access token if it has expired using the refresh token.
|
||||||
|
private String refreshAccessToken(String refreshToken) throws IOException {
|
||||||
|
TokenResponse response = new GoogleRefreshTokenRequest(
|
||||||
|
httpTransport, JSON_FACTORY, refreshToken, clientId, clientSecret)
|
||||||
|
.execute();
|
||||||
|
return response.getAccessToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Gmail refreshAndGetGmailService(String accessToken, String refreshToken) throws IOException {
|
||||||
|
try {
|
||||||
|
return getGmailService(accessToken, refreshToken);
|
||||||
|
} catch (GoogleJsonResponseException e) {
|
||||||
|
if (e.getStatusCode() == 401) {
|
||||||
|
logger.info("Access token expired. Refreshing token...");
|
||||||
|
String newAccessToken = refreshAccessToken(refreshToken);
|
||||||
|
return getGmailService(newAccessToken, refreshToken);
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Async method to scan all emails in the user's inbox to prevent timeout.
|
||||||
|
@Async
|
||||||
|
public void getEmailAsync(String userId, String accessToken, String refreshToken) {
|
||||||
|
try {
|
||||||
|
ScannedGmailResponseDto result = getEmail(userId, accessToken, refreshToken);
|
||||||
|
CompletableFuture.completedFuture(result);
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("Error processing Gmail", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
// Scan all emails in the user's inbox.
|
// Scan all emails in the user's inbox.
|
||||||
public ScannedGmailResponseDto getEmail(String accessToken) throws IOException, InterruptedException {
|
public ScannedGmailResponseDto getEmail(String userId, String accessToken, String refreshToken) throws IOException {
|
||||||
Gmail service = getGmailService(accessToken);
|
Gmail service = refreshAndGetGmailService(accessToken, refreshToken);
|
||||||
logger.info("Gmail service initialized: {}", service);
|
logger.info("Gmail service initialized: {}", service);
|
||||||
|
|
||||||
List<EmailMessage> emailMessagesList = new ArrayList<>();
|
List<EmailMessage> emailMessagesList = new ArrayList<>();
|
||||||
String userId = "me";
|
String meUserId = "me";
|
||||||
String nextPageToken = null;
|
String nextPageToken = null;
|
||||||
// Fetching email messages with page token and setting max results, Default value is 100.
|
// Fetching email messages with page token and setting max results, Default value is 100.
|
||||||
do {
|
do {
|
||||||
ListMessagesResponse listResponse = fetchMessages(service, userId, nextPageToken);
|
|
||||||
|
// ListHistoryResponse historyResponse = service.users().history().list(meUserId)
|
||||||
|
// .setStartHistoryId(BigInteger.valueOf(689335))
|
||||||
|
// .execute();
|
||||||
|
//
|
||||||
|
// List<History> historyList = historyResponse.getHistory();
|
||||||
|
//
|
||||||
|
// for (History history : historyList) {
|
||||||
|
// logger.info("History Id: {}, Message Id: {}, Message Snippet: {}", history.getId(), history.getMessages().get(0).getId(), history.getMessages().get(0).getHistoryId());
|
||||||
|
// }
|
||||||
|
ListMessagesResponse listResponse = fetchMessages(service, meUserId, nextPageToken);
|
||||||
List<Message> messages = listResponse.getMessages();
|
List<Message> messages = listResponse.getMessages();
|
||||||
nextPageToken = listResponse.getNextPageToken();
|
nextPageToken = listResponse.getNextPageToken();
|
||||||
// Iterate all the messages and add to emailMessagesList only if it has a valid QR code.
|
|
||||||
|
// Iterate all the messages and save to gmail db only if it has a valid QR code.
|
||||||
for (Message message : messages) {
|
for (Message message : messages) {
|
||||||
EmailMessage emailMessage = processMessage(service, userId, message);
|
EmailMessage emailMessage = processMessage(service, meUserId, message);
|
||||||
if (emailMessage != null) {
|
if (emailMessage != null) {
|
||||||
emailMessagesList.add(emailMessage);
|
emailMessagesList.add(emailMessage);
|
||||||
|
// Save email message to database.
|
||||||
|
saveEmailMessageAndScanQRCode(userId, emailMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (nextPageToken != null);
|
} while (nextPageToken != null);
|
||||||
|
|
||||||
|
// Update user's history id.
|
||||||
|
// TODO: Update user's history id.
|
||||||
|
|
||||||
return new ScannedGmailResponseDto(emailMessagesList);
|
return new ScannedGmailResponseDto(emailMessagesList);
|
||||||
}
|
}
|
||||||
|
// Save email message to database and scan QR code.
|
||||||
|
private void saveEmailMessageAndScanQRCode(String userId, EmailMessage emailMessage) {
|
||||||
|
GmailEmailEntity gmailEmailEntity = saveEmailMessage(userId, emailMessage);
|
||||||
|
|
||||||
|
if (gmailEmailEntity != null) {
|
||||||
|
// Save QR codes by content ID
|
||||||
|
saveQRCodeByContentId(gmailEmailEntity, emailMessage.getQrCodeByContentId());
|
||||||
|
|
||||||
|
// Save QR codes by URL
|
||||||
|
saveQRCodeByURL(gmailEmailEntity, emailMessage.getQrCodeByURL());
|
||||||
|
} else {
|
||||||
|
logger.warn("Skipping QR code processing due to failure in saving email message.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Save to gmail_email table
|
||||||
|
private GmailEmailEntity saveEmailMessage(String userId, EmailMessage emailMessage) {
|
||||||
|
logger.info("userId: {}", userId);
|
||||||
|
OffsetDateTime dateReceived = DateParsingUtils.parseDate(emailMessage.getDate());
|
||||||
|
try {
|
||||||
|
GmailEmailEntity gmailEmailEntity = GmailEmailEntity.builder()
|
||||||
|
.userId(userId)
|
||||||
|
.messageId(emailMessage.getMessageId())
|
||||||
|
.threadId(emailMessage.getThreadId())
|
||||||
|
.historyId(Long.valueOf(emailMessage.getHistoryId()))
|
||||||
|
.subject(emailMessage.getSubject())
|
||||||
|
.dateReceived(dateReceived)
|
||||||
|
.build();
|
||||||
|
return gmailEmailRespository.save(gmailEmailEntity);
|
||||||
|
} catch (DataIntegrityViolationException e) {
|
||||||
|
if (e.getCause() instanceof org.hibernate.exception.ConstraintViolationException) {
|
||||||
|
logger.warn("Duplicate entry for userId: {}, messageId: {}", userId, emailMessage.getMessageId());
|
||||||
|
} else {
|
||||||
|
logger.error("Error saving to gmail_email table: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Error saving gmail_email table: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate through decoded contents found in attachment as content id and save to gmail_cid table
|
||||||
|
private void saveQRCodeByContentId(GmailEmailEntity gmailEmailEntity, List<QRCodeByContentId> qrCodeByContentIdList) {
|
||||||
|
qrCodeByContentIdList.forEach(cid -> {
|
||||||
|
cid.getDecodedContent().forEach(decodedContent -> {
|
||||||
|
try {
|
||||||
|
QRCodeModel<?> qrCodeModel = qrCodeTypeService.scanGmailDecodedContents(gmailEmailEntity.getUserId(), decodedContent);
|
||||||
|
GmailCidEntity gmailCidEntity = GmailCidEntity.builder()
|
||||||
|
.gmailId(gmailEmailEntity.getId())
|
||||||
|
.qrCodeId(qrCodeModel.getData().getId())
|
||||||
|
.cid(cid.getCid())
|
||||||
|
.attachmentId(cid.getAttachmentId())
|
||||||
|
.decodedContent(decodedContent)
|
||||||
|
.build();
|
||||||
|
gmailCidRespository.save(gmailCidEntity);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Error saving QR code by content ID to gmail_cid table: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Iterate through decoded content found in url and save to gmail_url table
|
||||||
|
private void saveQRCodeByURL(GmailEmailEntity gmailEmailEntity, List<QRCodeByURL> qrCodeByURLList) {
|
||||||
|
qrCodeByURLList.forEach(imageUrl -> {
|
||||||
|
imageUrl.getDecodedContent().forEach(decodedContent -> {
|
||||||
|
try {
|
||||||
|
QRCodeModel<?> qrCodeModel = qrCodeTypeService.scanGmailDecodedContents(gmailEmailEntity.getUserId(), decodedContent);
|
||||||
|
GmailUrlEntity gmailUrlEntity = GmailUrlEntity.builder()
|
||||||
|
.gmailId(gmailEmailEntity.getId())
|
||||||
|
.qrCodeId(qrCodeModel.getData().getId())
|
||||||
|
.imageUrl(imageUrl.getUrl())
|
||||||
|
.decodedContent(decodedContent)
|
||||||
|
.build();
|
||||||
|
gmailUrlsRespository.save(gmailUrlEntity);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Error saving QR code by URL to gmail_urls table: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetching Scanned Gmail from database
|
||||||
|
public ScannedGmailResponseDto fetchScannedGmail(String userId){
|
||||||
|
// Fetching all emails from gmail_email table
|
||||||
|
List<GmailEmailEntity> userEmailsList = gmailEmailRespository.findByUserId(userId);
|
||||||
|
List<EmailMessage> emailMessageList = new ArrayList<>();
|
||||||
|
|
||||||
|
if (userEmailsList != null && !userEmailsList.isEmpty()) {
|
||||||
|
userEmailsList.forEach(email -> {
|
||||||
|
EmailMessage emailMessage = new EmailMessage(
|
||||||
|
email.getMessageId(),
|
||||||
|
email.getThreadId(),
|
||||||
|
email.getSubject(),
|
||||||
|
email.getHistoryId().toString(),
|
||||||
|
email.getDateReceived().toString()
|
||||||
|
);
|
||||||
|
// Fetching all CIDs from gmail_cid table
|
||||||
|
List<GmailCidEntity> cidList = gmailCidRespository.findByGmailId(email.getId());
|
||||||
|
Map<String, QRCodeByContentId> qrCodeByContentIdMap = new HashMap<>();
|
||||||
|
|
||||||
|
for (GmailCidEntity cid : cidList) {
|
||||||
|
String key = cid.getCid() + "-" + cid.getAttachmentId();
|
||||||
|
QRCodeByContentId qrCodeByContentId = qrCodeByContentIdMap.get(key);
|
||||||
|
|
||||||
|
if (qrCodeByContentId == null) {
|
||||||
|
qrCodeByContentId = QRCodeByContentId.builder()
|
||||||
|
.cid(cid.getCid())
|
||||||
|
.attachmentId(cid.getAttachmentId())
|
||||||
|
.decodedContent(new ArrayList<>())
|
||||||
|
.totalQRCodeFound(0)
|
||||||
|
.build();
|
||||||
|
qrCodeByContentIdMap.put(key, qrCodeByContentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append decoded content to the existing list
|
||||||
|
qrCodeByContentId.getDecodedContent().add(cid.getDecodedContent());
|
||||||
|
|
||||||
|
// Fetch scanned QR code from database and add to message object
|
||||||
|
emailMessage.addQRCodeModel(qrCodeTypeService.getScannedQRCodeDetailsInModel(cid.getQrCodeId()));
|
||||||
|
|
||||||
|
qrCodeByContentId.setTotalQRCodeFound(qrCodeByContentId.getTotalQRCodeFound() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
emailMessage.setQrCodeByContentId(new ArrayList<>(qrCodeByContentIdMap.values()));
|
||||||
|
|
||||||
|
// Fetching all URLs from gmail_urls table
|
||||||
|
List<GmailUrlEntity> urlList = gmailUrlsRespository.findByGmailId(email.getId());
|
||||||
|
|
||||||
|
Map<String, QRCodeByURL> qrCodeByURLMap = new HashMap<>();
|
||||||
|
|
||||||
|
for (GmailUrlEntity url : urlList) {
|
||||||
|
String key = url.getImageUrl();
|
||||||
|
QRCodeByURL qrCodeByURL = qrCodeByURLMap.get(key);
|
||||||
|
|
||||||
|
if (qrCodeByURL == null) {
|
||||||
|
qrCodeByURL = QRCodeByURL.builder()
|
||||||
|
.url(url.getImageUrl())
|
||||||
|
.decodedContent(new ArrayList<>())
|
||||||
|
.totalQRCodeFound(0)
|
||||||
|
.build();
|
||||||
|
qrCodeByURLMap.put(key, qrCodeByURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append decoded content to the existing list
|
||||||
|
qrCodeByURL.getDecodedContent().add(url.getDecodedContent());
|
||||||
|
|
||||||
|
// Fetch scanned QR code from database and add to message object
|
||||||
|
emailMessage.addQRCodeModel(qrCodeTypeService.getScannedQRCodeDetailsInModel(url.getQrCodeId()));
|
||||||
|
qrCodeByURL.setTotalQRCodeFound(qrCodeByURL.getTotalQRCodeFound() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
emailMessage.setQrCodeByURL(new ArrayList<>(qrCodeByURLMap.values()));
|
||||||
|
|
||||||
|
emailMessageList.add(emailMessage);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return ScannedGmailResponseDto.builder().messages(emailMessageList).build();
|
||||||
|
}
|
||||||
// Fetching email messages with page token and setting max results
|
// Fetching email messages with page token and setting max results
|
||||||
private ListMessagesResponse fetchMessages(Gmail service, String userId, String pageToken) throws IOException {
|
private ListMessagesResponse fetchMessages(Gmail service, String userId, String pageToken) throws IOException {
|
||||||
return service.users().messages().list(userId)
|
return service.users().messages().list(userId)
|
||||||
@@ -104,7 +363,7 @@ public class GmailService {
|
|||||||
logger.info("Message ID: {}", message.getId());
|
logger.info("Message ID: {}", message.getId());
|
||||||
logger.info("History ID: {}", message.getHistoryId());
|
logger.info("History ID: {}", message.getHistoryId());
|
||||||
|
|
||||||
EmailMessage emailMessage = new EmailMessage(message.getId(), subject, String.valueOf(message.getHistoryId()), emailDate);
|
EmailMessage emailMessage = new EmailMessage(message.getId(), message.getThreadId(), subject, String.valueOf(message.getHistoryId()), emailDate);
|
||||||
|
|
||||||
processAttachments(service, message.getId(), parts, attachmentIds, emailMessage);
|
processAttachments(service, message.getId(), parts, attachmentIds, emailMessage);
|
||||||
processImageUrls(imageUrls, emailMessage);
|
processImageUrls(imageUrls, emailMessage);
|
||||||
@@ -290,5 +549,4 @@ public class GmailService {
|
|||||||
String lowerUrl = url.toLowerCase();
|
String lowerUrl = url.toLowerCase();
|
||||||
return lowerUrl.endsWith(".jpg") || lowerUrl.endsWith(".jpeg") || lowerUrl.endsWith(".png") || lowerUrl.endsWith(".gif") || lowerUrl.endsWith(".bmp");
|
return lowerUrl.endsWith(".jpg") || lowerUrl.endsWith(".jpeg") || lowerUrl.endsWith(".png") || lowerUrl.endsWith(".gif") || lowerUrl.endsWith(".bmp");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.safeqr.app.qrcode.model;
|
package com.safeqr.app.qrcode.model;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.safeqr.app.qrcode.entity.EmailEntity;
|
|
||||||
import com.safeqr.app.qrcode.entity.QRCodeEntity;
|
import com.safeqr.app.qrcode.entity.QRCodeEntity;
|
||||||
import com.safeqr.app.qrcode.entity.URLEntity;
|
import com.safeqr.app.qrcode.entity.URLEntity;
|
||||||
import com.safeqr.app.qrcode.service.URLVerificationService;
|
import com.safeqr.app.qrcode.service.URLVerificationService;
|
||||||
@@ -12,8 +11,6 @@ import org.slf4j.LoggerFactory;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URISyntaxException;
|
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Data
|
@Data
|
||||||
public final class URLModel extends QRCodeModel<URLEntity> {
|
public final class URLModel extends QRCodeModel<URLEntity> {
|
||||||
|
|||||||
@@ -68,13 +68,18 @@ public class QRCodeTypeService {
|
|||||||
}
|
}
|
||||||
// Get scanned qrcode details
|
// Get scanned qrcode details
|
||||||
public BaseScanResponse getScannedQRCodeDetails(UUID qrCodeId){
|
public BaseScanResponse getScannedQRCodeDetails(UUID qrCodeId){
|
||||||
|
return BaseScanResponse.builder().qrcode(getScannedQRCodeDetailsInModel(qrCodeId)).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public QRCodeModel<?> getScannedQRCodeDetailsInModel(UUID qrCodeId){
|
||||||
// Find scanned qr code in qr code table
|
// Find scanned qr code in qr code table
|
||||||
QRCodeEntity qrCodeEntity = qrCodeRepository.findById(qrCodeId)
|
QRCodeEntity qrCodeEntity = qrCodeRepository.findById(qrCodeId)
|
||||||
.orElseThrow(() -> new ResourceNotFoundExceptions("QR Code not found with id: " + qrCodeId));
|
.orElseThrow(() -> new ResourceNotFoundExceptions("QR Code not found with id: " + qrCodeId));
|
||||||
logger.info("qrCodeEntity: {}", qrCodeEntity);
|
logger.info("qrCodeEntity: {}", qrCodeEntity);
|
||||||
QRCodeModel<?> qrCodeModel = qrCodeFactoryProvider.createQRCodeInstance(qrCodeEntity);
|
QRCodeModel<?> qrCodeModel = qrCodeFactoryProvider.createQRCodeInstance(qrCodeEntity);
|
||||||
logger.info("Retrieved details: {}", qrCodeModel.getDetails());
|
logger.info("Retrieved details: {}", qrCodeModel.getDetails());
|
||||||
return BaseScanResponse.builder().qrcode(qrCodeModel).build();
|
|
||||||
|
return qrCodeModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process Scanned QR Code
|
// Process Scanned QR Code
|
||||||
@@ -109,6 +114,28 @@ public class QRCodeTypeService {
|
|||||||
|
|
||||||
return BaseScanResponse.builder().qrcode(qrCodeModel).build();
|
return BaseScanResponse.builder().qrcode(qrCodeModel).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public QRCodeModel<?> scanGmailDecodedContents(String userId, String data) {
|
||||||
|
logger.info("Scan Gmail content: userId={}, data={}", userId, data);
|
||||||
|
|
||||||
|
// Get the QR Code Type
|
||||||
|
QRCodeTypeEntity qrType = getQRCodeType(data);
|
||||||
|
|
||||||
|
// Insert the QR Code into main qrcode table
|
||||||
|
QRCodeEntity scannedQR = qrCodeRepository.save(QRCodeEntity.builder()
|
||||||
|
.userId(userId)
|
||||||
|
.contents(data)
|
||||||
|
.info(qrType)
|
||||||
|
.createdAt(LocalDateTime.now())
|
||||||
|
.build());
|
||||||
|
|
||||||
|
// Create the QR Code Instance based on the QR Code Type & insert into the respective table
|
||||||
|
QRCodeModel<?> qrCodeModel = qrCodeFactoryProvider.createQRCodeInstance(scannedQR);
|
||||||
|
qrCodeModel.setDetails();
|
||||||
|
|
||||||
|
return qrCodeModel;
|
||||||
|
}
|
||||||
// Returns Default type as text if it does not fit into any of the category
|
// Returns Default type as text if it does not fit into any of the category
|
||||||
private QRCodeTypeEntity getQRCodeType(String data) {
|
private QRCodeTypeEntity getQRCodeType(String data) {
|
||||||
return configs.stream()
|
return configs.stream()
|
||||||
|
|||||||
@@ -30,8 +30,9 @@ public class URLVerificationService {
|
|||||||
|
|
||||||
public URLEntity getURLEntityByQRCodeId(UUID qrCodeId) {
|
public URLEntity getURLEntityByQRCodeId(UUID qrCodeId) {
|
||||||
logger.info("qrCodeId retrieving: {}", qrCodeId);
|
logger.info("qrCodeId retrieving: {}", qrCodeId);
|
||||||
return urlRepository.findByQrCodeId(qrCodeId)
|
// return urlRepository.findByQrCodeId(qrCodeId)
|
||||||
.orElseThrow(() -> new ResourceNotFoundExceptions("URL not found for QR Code id: " + qrCodeId));
|
// .orElseThrow(() -> new ResourceNotFoundExceptions("URL not found for QR Code id: " + qrCodeId));
|
||||||
|
return urlRepository.findByQrCodeId(qrCodeId).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void insertDB(URLEntity urlEntity) {
|
public void insertDB(URLEntity urlEntity) {
|
||||||
|
|||||||
@@ -33,4 +33,7 @@ public class UserEntity {
|
|||||||
@Column(name = "roles", columnDefinition = "text[]")
|
@Column(name = "roles", columnDefinition = "text[]")
|
||||||
private List<String> roles;
|
private List<String> roles;
|
||||||
private String status;
|
private String status;
|
||||||
|
|
||||||
|
@Column(name = "gmail_history_id")
|
||||||
|
private Long gmailHistoryId;
|
||||||
}
|
}
|
||||||
|
|||||||
34
src/main/java/com/safeqr/app/utils/AsyncConfig.java
Normal file
34
src/main/java/com/safeqr/app/utils/AsyncConfig.java
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package com.safeqr.app.utils;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableAsync
|
||||||
|
public class AsyncConfig {
|
||||||
|
|
||||||
|
@Bean(name = "taskExecutor")
|
||||||
|
public Executor taskExecutor() {
|
||||||
|
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||||
|
|
||||||
|
// Sets the number of core threads. These threads are always kept alive.
|
||||||
|
executor.setCorePoolSize(2);
|
||||||
|
|
||||||
|
// Sets the maximum number of threads that can be created by the pool.
|
||||||
|
executor.setMaxPoolSize(2);
|
||||||
|
|
||||||
|
// Sets the size of the queue to hold tasks before they are executed.
|
||||||
|
executor.setQueueCapacity(500);
|
||||||
|
|
||||||
|
// Sets the prefix for the names of the threads created by this pool.
|
||||||
|
executor.setThreadNamePrefix("GmailProcessing-");
|
||||||
|
|
||||||
|
// Initializes the executor to apply the configuration and make it ready to use.
|
||||||
|
executor.initialize();
|
||||||
|
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
}
|
||||||
42
src/main/java/com/safeqr/app/utils/DateParsingUtils.java
Normal file
42
src/main/java/com/safeqr/app/utils/DateParsingUtils.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package com.safeqr.app.utils;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.format.DateTimeFormatterBuilder;
|
||||||
|
import java.time.temporal.ChronoField;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class DateParsingUtils {
|
||||||
|
|
||||||
|
private DateParsingUtils() {
|
||||||
|
// private constructor to hide the implicit public one
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final DateTimeFormatter INPUT_FORMATTER = new DateTimeFormatterBuilder()
|
||||||
|
.appendPattern("EEE, ")
|
||||||
|
.appendPattern("[ ]") // This makes a single space optional
|
||||||
|
.appendPattern("[ ]") // This allows for a second optional space
|
||||||
|
.appendValue(ChronoField.DAY_OF_MONTH, 1, 2, java.time.format.SignStyle.NOT_NEGATIVE)
|
||||||
|
.appendPattern(" MMM yyyy HH:mm:ss Z")
|
||||||
|
.toFormatter(Locale.ENGLISH);
|
||||||
|
|
||||||
|
private static final DateTimeFormatter OUTPUT_FORMATTER =
|
||||||
|
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS Z");
|
||||||
|
|
||||||
|
public static String parseAndFormatDate(String inputDate) {
|
||||||
|
try {
|
||||||
|
OffsetDateTime dateTime = OffsetDateTime.parse(inputDate, INPUT_FORMATTER);
|
||||||
|
return dateTime.format(OUTPUT_FORMATTER);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Error parsing date: " + inputDate, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OffsetDateTime parseDate(String inputDate) {
|
||||||
|
try {
|
||||||
|
return OffsetDateTime.parse(inputDate, INPUT_FORMATTER);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Error parsing date: " + inputDate, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user