Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

20 add logg system #21

Merged
merged 16 commits into from
Dec 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:
- package-ecosystem: "" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"

13 changes: 13 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,21 @@
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
</properties>

<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>


<dependencies>
<!-- Dependencies -->
<dependency>
<groupId>com.github.forax</groupId>
<artifactId>beautiful_logger</artifactId>
<version>0.10.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
Expand Down
13 changes: 12 additions & 1 deletion src/main/java/io/github/mathieusoysal/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,46 @@

import com.fasterxml.jackson.core.exc.StreamReadException;
import com.fasterxml.jackson.databind.DatabindException;
import com.github.forax.beautifullogger.Logger;

import io.github.mathieusoysal.exceptions.ApiRequestFailedException;
import io.github.mathieusoysal.exceptions.PropertiesNotFoundRuntimeException;
import io.github.mathieusoysal.logement.data.DataCollector;
import io.github.mathieusoysal.logement.data.DataSaver;

public class App {

private static final Logger LOGGER = Logger.getLogger();
private static final String MAIL_PROPERTIES_NAME = "MAIL";
private static final String PASSWORD_PROPERTIES_NAME = "PASSWORD";

public static void main(String[] args)
throws StreamReadException, DatabindException, ApiRequestFailedException, IOException,
InterruptedException {
LOGGER.info(() -> "Starting application");
var logements = DataCollector.getAvailableLogementsWithConnection(getEmail(), getPassword());
DataSaver.createArchiveLogements(logements);
LOGGER.info(() -> "Application finished");
}

private static String getEmail() {
LOGGER.info(() -> "Getting email from environment variables");
String email = System.getenv(MAIL_PROPERTIES_NAME);
if (email == null)
{
LOGGER.error(() -> "Email not found in environment variables");
throw new PropertiesNotFoundRuntimeException(MAIL_PROPERTIES_NAME);
}
return email;
}

private static String getPassword() {
LOGGER.info(() -> "Getting password from environment variables");
String password = System.getenv(PASSWORD_PROPERTIES_NAME);
if (password == null)
{
LOGGER.error(() -> "Password not found in environment variables");
throw new PropertiesNotFoundRuntimeException(PASSWORD_PROPERTIES_NAME);
}
return password;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import java.io.IOException;
import java.nio.file.Paths;
import java.util.List;
import java.util.function.BooleanSupplier;

import com.fasterxml.jackson.core.exc.StreamReadException;
import com.fasterxml.jackson.databind.DatabindException;
import com.github.forax.beautifullogger.Logger;
import com.microsoft.playwright.Browser;
import com.microsoft.playwright.Browser.NewContextOptions;
import com.microsoft.playwright.BrowserContext;
Expand All @@ -27,6 +27,8 @@
import io.github.mathieusoysal.logement.pojo.Logement;

public class DataCollector {
private static final Logger LOGGER = Logger.getLogger();
private static final String LINK_TO_GET_ALL_LOGEMENTS = "https://trouverunlogement.lescrous.fr/api/fr/search/32";
private static final String BODY_POST_TO_GET_LOGEMENTS = "{\r\n \"idTool\": 32,\r\n \"need_aggregation\": false,\r\n \"page\": 1,\r\n \"pageSize\": 2500,\r\n \"sector\": null,\r\n \"occupationModes\": [],\r\n \"location\": [\r\n {\r\n \"lon\": -9.9079,\r\n \"lat\": 51.7087\r\n },\r\n {\r\n \"lon\": 14.3224,\r\n \"lat\": 40.5721\r\n }\r\n ],\r\n \"residence\": null,\r\n \"precision\": 9,\r\n \"equipment\": [],\r\n \"price\": {\r\n \"min\": 0,\r\n \"max\": 10000000\r\n }\r\n}";
private static final RequestOptions REQUEST_TO_GET_LOGEMENTS = RequestOptions.create()
.setMethod("POST")
Expand All @@ -36,55 +38,76 @@ public class DataCollector {
public static List<Logement> getAvailableLogementsWithoutConnection()
throws ApiRequestFailedException, StreamReadException, DatabindException, IOException {
List<Logement> logements;
LOGGER.info(() -> "Creating profil to request logements");
try (Playwright playwright = Playwright.create()) {
LOGGER.info(() -> "profil created");
LOGGER.info(() -> "Requesting logements from " + LINK_TO_GET_ALL_LOGEMENTS);
var respons = playwright.request().newContext()
.head("https://trouverunlogement.lescrous.fr/api/fr/search/32", REQUEST_TO_GET_LOGEMENTS);
.head(LINK_TO_GET_ALL_LOGEMENTS, REQUEST_TO_GET_LOGEMENTS);
if (!respons.ok())
throw new ApiRequestFailedException(respons);
LOGGER.info(() -> "Logements received");
logements = Convertor.getLogementsFromBruteJsonString(respons.text());
}
LOGGER.info(() -> "profil closed");
return logements;
}

public static List<Logement> getAllLogementsWithoutConnection()
throws ApiRequestFailedException, StreamReadException, DatabindException, IOException {
LOGGER.info(() -> "Getting all logements");
List<Logement> logements;
LOGGER.info(() -> "Creating profil to request logements");
try (Playwright playwright = Playwright.create()) {
var respons = playwright.request().newContext()
.head("https://trouverunlogement.lescrous.fr/api/fr/search/29", REQUEST_TO_GET_LOGEMENTS);
if (!respons.ok())
if (!respons.ok()) {
LOGGER.error(() -> "Request failed");
throw new ApiRequestFailedException(respons);
}
LOGGER.info(() -> "Request succeed");
logements = Convertor.getLogementsFromBruteJsonString(respons.text());
}
LOGGER.info(() -> "profil closed");
LOGGER.info(() -> "All logements received");
return logements;
}

public static List<Logement> getAvailableLogementsWithConnection(String email, String password)
throws ApiRequestFailedException, StreamReadException, DatabindException, IOException,
InterruptedException {
LOGGER.info(() -> "Getting available logements");
LOGGER.info(() -> "Creating profil to request logements");
Playwright playwright = Playwright.create();
Browser browser = playwright.chromium().launch(new BrowserType.LaunchOptions());
BrowserContext context = browser.newContext(new NewContextOptions().setScreenSize(1920, 1080));
Page page = context.newPage();
List<Logement> logements;
try {

context.tracing().start(new Tracing.StartOptions()
.setScreenshots(true)
.setSnapshots(true)
.setSources(true));
goToLoginPage(page);
selectLoginOption(playwright, page);
connectToTheCrous(email, password, playwright, page);
LOGGER.info(() -> "Going to logements page");
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Lancer une recherche"))
.click();
page.waitForLoadState();
LOGGER.info(() -> "Requesting logements from " + LINK_TO_GET_ALL_LOGEMENTS);
var respons = page.request()
.head("https://trouverunlogement.lescrous.fr/api/fr/search/32",
.head(LINK_TO_GET_ALL_LOGEMENTS,
REQUEST_TO_GET_LOGEMENTS);
if (!respons.ok())
if (!respons.ok()) {
LOGGER.error(() -> "Request failed");
throw new ApiRequestFailedException(respons);
}
LOGGER.info(() -> "Logements received");
logements = Convertor.getLogementsFromBruteJsonString(respons.text());
} catch (TimeoutError | LoginOptionCantBeSelectedError | CannotBeConnectedError e) {
LOGGER.error("Request failed", e);
context.tracing().stop(new Tracing.StopOptions()
.setPath(Paths.get("trace.zip")));
throw e;
Expand All @@ -93,11 +116,13 @@ public static List<Logement> getAvailableLogementsWithConnection(String email, S
context.close();
browser.close();
playwright.close();
LOGGER.info(() -> "profil closed");
}
return logements;
}

private static void goToLoginPage(Page page) {
LOGGER.info(() -> "Going to login page");
page.navigate("https://trouverunlogement.lescrous.fr/tools/32/search");
page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName("Identification")).click();
page.waitForLoadState();
Expand All @@ -106,6 +131,7 @@ private static void goToLoginPage(Page page) {
private static void selectLoginOption(Playwright playwright, Page page) {
playwright.selectors().setTestIdAttribute("id");
String currentUrl = page.url();
LOGGER.info(() -> "Selecting login option");
try {
page.locator("#boxlogin div").nth(0).click();
if (page.url().equals(currentUrl))
Expand All @@ -117,30 +143,38 @@ private static void selectLoginOption(Playwright playwright, Page page) {
page.waitForLoadState(LoadState.DOMCONTENTLOADED);
waitForUrlChange(currentUrl, page);
} catch (TimeoutError e) {
LOGGER.error(() -> "Login option can't be selected");
throw new LoginOptionCantBeSelectedError(e.getMessage(), page.content());
}
LOGGER.info(() -> "Login option selected");
}

private static void connectToTheCrous(String email, String password, Playwright playwright, Page page) {
LOGGER.info(() -> "Connecting to the crous");
playwright.selectors().setTestIdAttribute("type");
String currentUrl = page.url();
try {
fillForm(email, password, page);
waitForPageLoad(page);
waitForUrlChange(currentUrl, page);
} catch (TimeoutError e) {
LOGGER.error(() -> "Can't connect to the crous");
throw new CannotBeConnectedError(e.getMessage(), page.content());
}
LOGGER.info(() -> "Connected to the crous");
}

private static void fillForm(String email, String password, Page page) {
LOGGER.info(() -> "Filling form");
var emailField = page.getByTestId("email");
emailField.hover();
emailField.click();
emailField.fill(email);
var passwordField = page.getByTestId("password");
passwordField.click();
passwordField.fill(password);
LOGGER.info(() -> "Form filled");
LOGGER.info(() -> "Submitting form");
passwordField.press("Enter");
}

Expand Down
38 changes: 33 additions & 5 deletions src/main/java/io/github/mathieusoysal/logement/data/DataSaver.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.time.DateTimeException;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
Expand All @@ -12,15 +13,21 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.github.forax.beautifullogger.Logger;

import io.github.mathieusoysal.logement.pojo.Logement;

public class DataSaver {
private static final Logger LOGGER = Logger.getLogger();

public static File createArchiveFolder() {
LOGGER.info(() -> "getting archive folder");
File archiveFolder = new File("archive");
if (!archiveFolder.exists())
if (!archiveFolder.exists()) {
archiveFolder.mkdir();
LOGGER.info(() -> "Archive folder created");
}

return archiveFolder;
}

Expand All @@ -33,33 +40,54 @@ public static File createArchiveLogements(List<Logement> logements) throws JsonP
}

private static void writeLogementsDataInsideArchiveFile(String logementsJson, File archiveFile) {
LOGGER.info(() -> "Writing logements to file");
try (FileWriter fileWriter = new FileWriter(archiveFile)) {
fileWriter.write(logementsJson);
} catch (IOException e) {
LOGGER.error("Error while writing logements to file", e);
throw new RuntimeException("Error while writing logements to file", e);
}
LOGGER.info(() -> "Logements written to file");
}

private static File getArchiveFile(File archiveFolder) throws DateTimeException {
LOGGER.info(() -> "Getting archive file");
String archiveFileName = OffsetDateTime.now().toLocalTime().format(DateTimeFormatter.ofPattern("HH"));
Stream.of(archiveFolder.listFiles())
.filter(file -> file.getName().equals(archiveFileName))
.findFirst()
.ifPresent(File::delete);
return new File(archiveFolder, archiveFileName);
.ifPresent(file -> {
LOGGER.error(() -> "Archive file already exists");
try {
Files.delete(file.toPath());
} catch (IOException e) {
LOGGER.error("Error while deleting archive file", e);
e.printStackTrace();
}
LOGGER.info(() -> "Archive file deleted");
});
var archiveFile = new File(archiveFolder, archiveFileName);
LOGGER.info(() -> "Archive file got");
return archiveFile;
}

private static String convertLogementsToJson(List<Logement> logements) throws JsonProcessingException {
LOGGER.info(() -> "Converting logements to json");
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
return ow.writeValueAsString(logements);
var result = ow.writeValueAsString(logements);
LOGGER.info(() -> "Logements converted to json");
return result;
}

private static File getArchiveFolderForCurrentDate() {
LOGGER.info(() -> "Getting archive folder for current date");
File archiveFolder = createArchiveFolder();
String archiveFolderName = OffsetDateTime.now().toLocalDate().toString();
File archiveFile = new File(archiveFolder, archiveFolderName);
if (!archiveFile.exists())
if (!archiveFile.exists()) {
archiveFile.mkdir();
LOGGER.info(() -> "Archive folder for current date created");
}
return archiveFile;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.fasterxml.jackson.core.exc.StreamReadException;
import com.fasterxml.jackson.databind.DatabindException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.forax.beautifullogger.Logger;

import io.github.mathieusoysal.logement.Address;
import io.github.mathieusoysal.logement.BedKind;
Expand All @@ -16,24 +17,32 @@
import io.github.mathieusoysal.logement.TransportUnitOfMeasure;

public class Convertor {
private static final Logger LOGGER = Logger.getLogger();

private Convertor() {
}

static List<Item> getItemsFromJsonFile(File file) throws StreamReadException, DatabindException, IOException {
LOGGER.info(() -> "Reading json file for convertion to java object");
ObjectMapper objectMapper = new ObjectMapper();
Input results = objectMapper.readValue(file, Input.class);
LOGGER.info(() -> "Json file converted to java object");
return results.getResults().getItems();
}

static List<Item> getItemsFromJsonString(String json) throws StreamReadException, DatabindException, IOException {
LOGGER.info(() -> "Reading json string for convertion to java object");
ObjectMapper objectMapper = new ObjectMapper();
Input results = objectMapper.readValue(json, Input.class);
LOGGER.info(() -> "Json string converted to java object");
return results.getResults().getItems();
}

static List<Logement> convertItemsToLogements(List<Item> items) {
return items.stream().map(Convertor::convertItemToLogement).toList();
LOGGER.info(() -> "Converting items to logements");
var result = items.stream().map(Convertor::convertItemToLogement).toList();
LOGGER.info(() -> "Items converted to logements");
return result;
}

public static List<Logement> getLogementsFromBruteJsonFile(File file)
Expand Down
Loading