This commit is contained in:
2025-01-19 20:24:39 +01:00
parent 07645cf11a
commit cf98081644
5 changed files with 114 additions and 29 deletions

View File

@@ -33,4 +33,10 @@ public class VacatureResource {
public Vacature getVacature() throws IOException { public Vacature getVacature() throws IOException {
return vacatureService.getVacature(); return vacatureService.getVacature();
} }
@GET
@Path("/clean")
public void cleanVacatures() throws IOException {
vacatureService.cleanVacatures();
}
} }

View File

@@ -5,6 +5,7 @@ import jakarta.inject.Inject;
import nl.veenm.jobfindr.domain.Vacature; import nl.veenm.jobfindr.domain.Vacature;
import nl.veenm.jobfindr.domain.VacatureDetail; import nl.veenm.jobfindr.domain.VacatureDetail;
import nl.veenm.jobfindr.repository.VacatureDetailRepository; import nl.veenm.jobfindr.repository.VacatureDetailRepository;
import org.jboss.logging.Logger;
import org.jsoup.Jsoup; import org.jsoup.Jsoup;
import org.jsoup.nodes.Document; import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element; import org.jsoup.nodes.Element;
@@ -19,10 +20,14 @@ import java.util.stream.Collectors;
@ApplicationScoped @ApplicationScoped
public class ScraperService { public class ScraperService {
private static final Logger log = Logger.getLogger(ScraperService.class);
public List<Vacature> scrapeVacatures(String url) throws IOException { public List<Vacature> scrapeVacatures(String url) throws IOException {
// Maak verbinding met de website // Maak verbinding met de website
Document doc = Jsoup.connect(url).get(); Document doc = Jsoup.connect(url).get();
log.info("Scraping vacatures from " + url);
// Selecteer alle vacature-elementen // Selecteer alle vacature-elementen
Elements vacatureElements = doc.select("div.mt-2.text-overflow-ellipsis"); Elements vacatureElements = doc.select("div.mt-2.text-overflow-ellipsis");

View File

@@ -4,6 +4,7 @@ import io.quarkus.mailer.Mail;
import io.quarkus.mailer.Mailer; import io.quarkus.mailer.Mailer;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import nl.veenm.jobfindr.domain.Vacature; import nl.veenm.jobfindr.domain.Vacature;
import org.jboss.logging.Logger;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
@@ -11,6 +12,8 @@ import java.util.List;
@ApplicationScoped @ApplicationScoped
public class EmailService { public class EmailService {
private static final Logger log = Logger.getLogger(EmailService.class);
private final Mailer mailer; private final Mailer mailer;
public EmailService(Mailer mailer) { public EmailService(Mailer mailer) {
@@ -18,39 +21,64 @@ public class EmailService {
} }
public void stuurVacatureEmail(String recipient, List<Vacature> vacatures) { public void stuurVacatureEmail(String recipient, List<Vacature> vacatures) {
// Bouw de inhoud van de e-mail // Bouw de HTML-inhoud van de e-mail
StringBuilder emailBody = new StringBuilder(); StringBuilder emailBody = new StringBuilder();
emailBody.append("Lieve Danthe,\n\n"); emailBody.append("<html>")
emailBody.append("Hier zijn de nieuwste vacatures die ik heb gevonden:\n\n"); .append("<head>")
.append("<style>")
.append("body { font-family: Arial, sans-serif; line-height: 1.6; }")
.append("h1 { color: #333; }")
.append("h2 { color: #555; }")
.append("p { color: #666; }")
.append("ul { padding-left: 20px; }")
.append("li { margin-bottom: 10px; }")
.append(".vacature { margin-bottom: 20px; padding: 10px; border: 1px solid #ddd; border-radius: 5px; background-color: #f9f9f9; }")
.append(".vacature h2 { margin: 0; font-size: 18px; color: #333; }")
.append(".vacature p { margin: 5px 0; }")
.append(".footer { margin-top: 30px; font-size: 14px; color: #999; }")
.append("</style>")
.append("</head>")
.append("<body>")
.append("<h1>Lieve Danthe,</h1>")
.append("<p>Hier zijn de nieuwste vacatures die ik heb gevonden:</p>")
.append("<div>");
for (Vacature vacature : vacatures) { for (Vacature vacature : vacatures) {
emailBody.append("- ").append(vacature.getTitel()).append("\n"); emailBody.append("<div class=\"vacature\">")
emailBody.append(" Locatie: ").append(vacature.getLocatie()).append("\n"); .append("<h2>").append(vacature.getTitel()).append("</h2>")
emailBody.append(" Details: ").append("\n"); .append("<p><strong>Locatie:</strong> ").append(vacature.getLocatie()).append("</p>")
emailBody.append(" -Geplaatst: ").append(vacature.getDetail().getGeplaatst()).append("\n"); .append("<p><strong>Geplaatst:</strong> ").append(vacature.getDetail().getGeplaatst()).append("</p>")
emailBody.append(" -Sluitingsdatum: ").append(vacature.getDetail().getSluitingsdatum()).append("\n"); .append("<p><strong>Sluitingsdatum:</strong> ").append(vacature.getDetail().getSluitingsdatum()).append("</p>")
emailBody.append(" -Salaris: ").append(vacature.getDetail().getSalaris()).append("\n"); .append("<p><strong>Salaris:</strong> ").append(vacature.getDetail().getSalaris()).append("</p>")
emailBody.append(" -Aantal uren: ").append(vacature.getDetail().getAantalUren()).append("\n"); .append("<p><strong>Aantal uren:</strong> ").append(vacature.getDetail().getAantalUren()).append("</p>")
emailBody.append(" -FTE: ").append(vacature.getDetail().getFte()).append("\n"); .append("<p><strong>FTE:</strong> ").append(vacature.getDetail().getFte()).append("</p>")
emailBody.append(" -Startdatum: ").append(vacature.getDetail().getStartdatum()).append("\n"); .append("<p><strong>Startdatum:</strong> ").append(vacature.getDetail().getStartdatum()).append("</p>")
emailBody.append(" -Soort vacature: ").append(vacature.getDetail().getSoortVacature()).append("\n"); .append("<p><strong>Soort vacature:</strong> ").append(vacature.getDetail().getSoortVacature()).append("</p>")
emailBody.append(" -Dienstverband: ").append(vacature.getDetail().getDienstverband()).append("\n"); .append("<p><strong>Dienstverband:</strong> ").append(vacature.getDetail().getDienstverband()).append("</p>")
emailBody.append(" -Zij-instromers: ").append(vacature.getDetail().getZijInstromers()).append("\n"); .append("<p><strong>Zij-instromers:</strong> ").append(vacature.getDetail().getZijInstromers()).append("</p>")
emailBody.append(" Link: ").append(vacature.getUrl()).append("\n\n"); .append("<p><a href=\"").append(vacature.getUrl()).append("\" style=\"color: #007bff; text-decoration: none;\">Bekijk vacature</a></p>")
.append("</div>");
} }
emailBody.append("Met vriendelijke groet,\n"); emailBody.append("</div>")
emailBody.append("Het vacatureteam\n"); .append("<div class=\"footer\">")
emailBody.append("(a.k.a je vriendje)"); .append("Met vriendelijke groet,<br>")
.append("Het vacatureteam<br>")
.append("(a.k.a je vriendje)")
.append("</div>")
.append("</body>")
.append("</html>");
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
String date = now.getDayOfYear() + "-" + now.getMonth().getValue(); String date = now.getDayOfMonth() + "-" + now.getMonthValue() + "-" + now.getYear();
String subject = "[%s] Nieuwe vacatures gevonden"; String subject = String.format("[%s] Nieuwe vacatures gevonden", date);
// Verstuur de e-mail // Verstuur de e-mail met HTML-inhoud
mailer.send(Mail.withText(recipient, String.format(subject, date), emailBody.toString())); log.info("Sending email to " + recipient);
mailer.send(Mail.withHtml(recipient, subject, emailBody.toString()));
} }
} }

View File

@@ -8,9 +8,12 @@ import nl.veenm.jobfindr.domain.Vacature;
import nl.veenm.jobfindr.repository.VacatureDetailRepository; import nl.veenm.jobfindr.repository.VacatureDetailRepository;
import nl.veenm.jobfindr.repository.VacatureRepository; import nl.veenm.jobfindr.repository.VacatureRepository;
import nl.veenm.jobfindr.scrapers.ScraperService; import nl.veenm.jobfindr.scrapers.ScraperService;
import org.jboss.logging.Logger;
import java.io.IOException; import java.io.IOException;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -29,12 +32,13 @@ public class VacatureService {
@Inject @Inject
VacatureDetailRepository vacatureDetailRepository; VacatureDetailRepository vacatureDetailRepository;
private static final Logger logger = Logger.getLogger(VacatureService.class);
public List<Vacature> getServices() throws IOException { public List<Vacature> getServices() throws IOException {
List<Vacature> vacatures = new ArrayList<>(); List<Vacature> vacatures = new ArrayList<>();
vacatures.addAll(scraperService.scrapeVacatures("https://www.meesterbaan.nl/vacatures/50-km?trefwoord=duits&locatie=Apeldoorn")); vacatures.addAll(scraperService.scrapeVacatures("https://www.meesterbaan.nl/vacatures/50-km?trefwoord=duits&locatie=Apeldoorn"));
vacatures.addAll(scraperService.scrapeVacatures("https://www.meesterbaan.nl/vacatures/50-km?trefwoord=frans&locatie=Apeldoorn")); vacatures.addAll(scraperService.scrapeVacatures("https://www.meesterbaan.nl/vacatures/50-km?trefwoord=frans&locatie=Apeldoorn"));
emailService.stuurVacatureEmail("vanveenmel11@gmail.com", vacatures); emailService.stuurVacatureEmail("vanveenmel11@gmail.com", vacatures);
// emailService.stuurVacatureEmail("danthefranken@gmail.com", vacatures);
return vacatures; return vacatures;
} }
@@ -70,23 +74,21 @@ public class VacatureService {
if (!newVacatures.isEmpty()) { if (!newVacatures.isEmpty()) {
// Sla de nieuwe vacatures op // Sla de nieuwe vacatures op
newVacatures.forEach(vacature -> { newVacatures.forEach(vacature -> {
System.out.println(newVacatures.size());
vacature.setDatum(today); vacature.setDatum(today);
vacatureDetailRepository.persist(vacature.getDetail()); vacatureDetailRepository.persist(vacature.getDetail());
vacatureRepository.persist(vacature); vacatureRepository.persist(vacature);
}); });
// Verstuur een e-mail // Verstuur een e-mail
// emailService.stuurVacatureEmail("danthefranken@gmail.com", newVacatures); emailService.stuurVacatureEmail("danthefranken@gmail.com", newVacatures);
emailService.stuurVacatureEmail("vanveenmel11@gmail.com", newVacatures); emailService.stuurVacatureEmail("vanveenmel11@gmail.com", newVacatures);
System.out.println("Nieuwe vacatures verstuurd en opgeslagen."); logger.info("Nieuwe vacatures verstuurd en opgeslagen.");
} else { } else {
System.out.println("Geen nieuwe vacatures gevonden."); logger.info("Geen nieuwe vacatures gevonden.");
} }
} }
@Scheduled(cron = "0 0 9 * * ?") @Scheduled(cron = "0 0 9 * * ?")
@Scheduled(cron = "0 53 13 * * ?")
@Scheduled(cron = "0 0 17 * * ?") @Scheduled(cron = "0 0 17 * * ?")
@Transactional @Transactional
void dagelijksControleerEnVerstuur() throws IOException { void dagelijksControleerEnVerstuur() throws IOException {
@@ -94,11 +96,43 @@ public class VacatureService {
} }
public List<Vacature> getAllVacatures() { public List<Vacature> getAllVacatures() {
logger.info("Get all vacatures");
return vacatureRepository.listAll(); return vacatureRepository.listAll();
} }
public Vacature getVacature() throws IOException { public Vacature getVacature() throws IOException {
return scraperService.getVacatureDetails(new Vacature()); return scraperService.getVacatureDetails(new Vacature());
} }
@Scheduled(cron = "0 0 0 * * ?")
@Transactional
public void cleanVacatures() {
logger.info("Cleaning vacatures");
getAllVacatures().forEach(vacature -> {
var date = convertStringToLocalDate(vacature.getDetail().getSluitingsdatum());
var today = LocalDate.now();
if (date != null) {
if (date.isBefore(today)) {
logger.info("Deleting vacature " + vacature.getTitel());
vacatureDetailRepository.delete(vacature.getDetail());
vacatureRepository.delete(vacature);
}
}
});
}
public static LocalDate convertStringToLocalDate(String dateString) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
try {
return LocalDate.parse(dateString, formatter);
} catch (DateTimeParseException e) {
logger.error("Ongeldige datumstring: " + dateString);
return null; // Of gooi een aangepaste exception als dat gewenst is
}
}
} }

View File

@@ -1,3 +1,4 @@
# Mailer configuratie
quarkus.mailer.from=${MAILER_FROM} quarkus.mailer.from=${MAILER_FROM}
quarkus.mailer.host=${MAILER_HOST} quarkus.mailer.host=${MAILER_HOST}
quarkus.mailer.port=${MAILER_PORT} quarkus.mailer.port=${MAILER_PORT}
@@ -20,4 +21,15 @@ quarkus.http.cors.origins=${CORS_ORIGINS}
quarkus.http.cors.methods=GET, POST, PUT, DELETE, OPTIONS quarkus.http.cors.methods=GET, POST, PUT, DELETE, OPTIONS
quarkus.http.cors.headers=Content-Type, Authorization quarkus.http.cors.headers=Content-Type, Authorization
#Logger
# Instellen van het logniveau (mogelijkheden: TRACE, DEBUG, INFO, WARN, ERROR, OFF)
quarkus.log.level=INFO
# Configureren van het formatteren van logs
quarkus.log.console.format=%d{yyyy-MM-dd} %d{HH:mm:ss} %-5p [%c] (%s%e)%n
# Logs naar een bestand sturen
quarkus.log.file.enable=true
quarkus.log.file.path=logs/app.log
quarkus.log.file.format=%d{yyyy-MM-dd} %d{HH:mm:ss} %-5p [%c] (%s%e)%n