Some checks failed
Deploy Production Server / if_merged (pull_request) Failing after 2m31s
383 lines
15 KiB
Java
383 lines
15 KiB
Java
package fr.titionfire.ffsaf.utils;
|
|
|
|
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
|
|
import fr.titionfire.ffsaf.data.model.MembreModel;
|
|
import io.smallrye.mutiny.Uni;
|
|
import jakarta.ws.rs.core.HttpHeaders;
|
|
import jakarta.ws.rs.core.MediaType;
|
|
import jakarta.ws.rs.core.Response;
|
|
import jodd.net.MimeTypes;
|
|
import org.apache.tika.Tika;
|
|
import org.jboss.logging.Logger;
|
|
|
|
import java.io.*;
|
|
import java.net.URISyntaxException;
|
|
import java.net.URLConnection;
|
|
import java.nio.file.Files;
|
|
import java.util.Calendar;
|
|
import java.util.Date;
|
|
import java.util.concurrent.CompletableFuture;
|
|
import java.util.concurrent.Future;
|
|
|
|
|
|
public class Utils {
|
|
private static final Logger LOGGER = Logger.getLogger(Utils.class);
|
|
|
|
public static String HTML_HEADER = """
|
|
<!DOCTYPE html>
|
|
<html data-lt-installed="true">
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>%s</title>
|
|
<style>
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
line-height: 1.6;
|
|
color: #333;
|
|
max-width: 600px;
|
|
margin: 0 auto;
|
|
padding: 20px;
|
|
}
|
|
|
|
.header {
|
|
background-color: #003366;
|
|
color: white;
|
|
padding: 20px;
|
|
text-align: center;
|
|
border-radius: 5px 5px 0 0;
|
|
}
|
|
|
|
.content {
|
|
padding: 20px;
|
|
background-color: #f9f9f9;
|
|
border-radius: 0 0 5px 5px;
|
|
border: 1px solid #ddd;
|
|
border-top: none;
|
|
}
|
|
|
|
.button {
|
|
display: inline-block;
|
|
padding: 10px 20px;
|
|
background-color: #003366;
|
|
color: white !important;
|
|
text-decoration: none;
|
|
border-radius: 5px;
|
|
margin: 15px 0;
|
|
}
|
|
|
|
.footer {
|
|
margin-top: 20px;
|
|
font-size: 0.9em;
|
|
color: #666;
|
|
text-align: center;
|
|
}
|
|
|
|
.highlight {
|
|
font-weight: bold;
|
|
color: #003366;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body data-gramm="false" data-lt-tmp-id="lt-957854">
|
|
<div class="header">
|
|
<div><img src="https://intra.ffsaf.fr/Logo-FFSAF-2023.png" alt="ffsaf" height="128">
|
|
<h1>Fédération France Soft Armored Fighting</h1>
|
|
</div>
|
|
</div>
|
|
<div class="content">
|
|
<p>Bonjour,</p>
|
|
""";
|
|
public static String HTML_FOOTER = """
|
|
<p>Cordialement,<br>L’équipe de la FFSAF</p>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
""";
|
|
|
|
public static int getSaison() {
|
|
return getSaison(new Date());
|
|
}
|
|
|
|
public static int getSaison(Date date) {
|
|
Calendar calendar = Calendar.getInstance();
|
|
calendar.setTime(date);
|
|
|
|
if (calendar.get(Calendar.MONTH) >= Calendar.SEPTEMBER) {
|
|
return calendar.get(Calendar.YEAR);
|
|
} else {
|
|
return calendar.get(Calendar.YEAR) - 1;
|
|
}
|
|
}
|
|
|
|
public static Calendar toCalendar(Date date) {
|
|
Calendar cal = Calendar.getInstance();
|
|
cal.setTime(date);
|
|
return cal;
|
|
}
|
|
|
|
public static Categorie getCategoryFormBirthDate(Date birth_date, Date currentDate) {
|
|
|
|
int currentSaison = getSaison(currentDate);
|
|
int birthYear = toCalendar(birth_date).get(Calendar.YEAR);
|
|
|
|
int diff = currentSaison - birthYear;
|
|
if (diff < 6) {
|
|
return Categorie.SUPER_MINI;
|
|
} else if (diff < 8) {
|
|
return Categorie.MINI_POUSSIN;
|
|
} else if (diff < 10) {
|
|
return Categorie.POUSSIN;
|
|
} else if (diff < 12) {
|
|
return Categorie.BENJAMIN;
|
|
} else if (diff < 14) {
|
|
return Categorie.MINIME;
|
|
} else if (diff < 16) {
|
|
return Categorie.CADET;
|
|
} else if (diff < 18) {
|
|
return Categorie.JUNIOR;
|
|
} else if (diff < 25) {
|
|
return Categorie.SENIOR1;
|
|
} else if (diff < 35) {
|
|
return Categorie.SENIOR2;
|
|
} else if (diff < 45) {
|
|
return Categorie.VETERAN1;
|
|
} else {
|
|
return Categorie.VETERAN2;
|
|
}
|
|
}
|
|
|
|
public static Uni<String> moveMedia(long idSrc, long idDest, String media, String dirSrc, String dirDst) {
|
|
return Uni.createFrom().nullItem().map(__ -> {
|
|
File dirFile = new File(media, dirSrc);
|
|
if (!dirFile.exists())
|
|
return "Not found";
|
|
|
|
File dirDestFile = new File(media, dirDst);
|
|
if (!dirDestFile.exists())
|
|
if (!dirDestFile.mkdirs())
|
|
return "Fail to create directory " + dirDestFile;
|
|
|
|
FilenameFilter filter = (directory, filename) -> filename.startsWith(idSrc + ".");
|
|
File[] files = dirFile.listFiles(filter);
|
|
if (files == null || files.length == 0)
|
|
return "Not found";
|
|
|
|
FilenameFilter filter2 = (directory, filename) -> filename.startsWith(idDest + ".");
|
|
File[] files2 = dirDestFile.listFiles(filter2);
|
|
if (files2 != null) {
|
|
for (File file : files2) {
|
|
//noinspection ResultOfMethodCallIgnored
|
|
file.delete();
|
|
}
|
|
}
|
|
|
|
for (File file : files) {
|
|
//noinspection ResultOfMethodCallIgnored
|
|
file.renameTo(new File(dirDestFile,
|
|
file.getName().replaceFirst(String.valueOf(idSrc), String.valueOf(idDest))));
|
|
}
|
|
|
|
return "Ok";
|
|
});
|
|
}
|
|
|
|
public static Future<String> replacePhoto(long id, byte[] input, String media, String dir) {
|
|
return CompletableFuture.supplyAsync(() -> {
|
|
if (input == null || input.length == 0)
|
|
return "OK";
|
|
|
|
try (InputStream is = new BufferedInputStream(new ByteArrayInputStream(input))) {
|
|
String mimeType;
|
|
try {
|
|
Tika tika = new Tika();
|
|
mimeType = tika.detect(is);// Magic.getMagicMatch(input, false).getMimeType();
|
|
} catch (IOException e) {
|
|
mimeType = URLConnection.guessContentTypeFromStream(is);
|
|
}
|
|
String[] detectedExtensions = MimeTypes.findExtensionsByMimeTypes(mimeType, false);
|
|
if (detectedExtensions.length == 0)
|
|
throw new IOException("Fail to detect file extension for MIME type " + mimeType);
|
|
|
|
File dirFile = new File(media, dir);
|
|
if (!dirFile.exists())
|
|
if (!dirFile.mkdirs())
|
|
throw new IOException("Fail to create directory " + dir);
|
|
|
|
FilenameFilter filter = (directory, filename) -> filename.startsWith(id + ".");
|
|
File[] files = dirFile.listFiles(filter);
|
|
if (files != null) {
|
|
for (File file : files) {
|
|
//noinspection ResultOfMethodCallIgnored
|
|
file.delete();
|
|
}
|
|
}
|
|
|
|
String extension = "." + detectedExtensions[0];
|
|
Files.write(new File(dirFile, id + extension).toPath(), input);
|
|
return "OK";
|
|
} catch (IOException e) {
|
|
return e.getMessage();
|
|
}
|
|
});
|
|
}
|
|
|
|
public static Uni<Response> getMediaFile(long id, String media, String dirname,
|
|
Uni<?> uniBase) throws URISyntaxException {
|
|
return getMediaFile(id, media, dirname, null, uniBase, true);
|
|
}
|
|
|
|
public static Uni<Response> getMediaFileNoDefault(long id, String media, String dirname,
|
|
Uni<?> uniBase) throws URISyntaxException {
|
|
return getMediaFile(id, media, dirname, null, uniBase, false);
|
|
}
|
|
|
|
public static Uni<Response> getMediaFile(long id, String media, String dirname, String out_filename,
|
|
Uni<?> uniBase, boolean default_) throws URISyntaxException {
|
|
Future<Pair<File, byte[]>> future = CompletableFuture.supplyAsync(() -> {
|
|
FilenameFilter filter = (directory, filename) -> filename.startsWith(id + ".");
|
|
File[] files = new File(media, dirname).listFiles(filter);
|
|
if (files != null && files.length > 0) {
|
|
File file = files[0];
|
|
try {
|
|
byte[] data = Files.readAllBytes(file.toPath());
|
|
return new Pair<>(file, data);
|
|
} catch (IOException ignored) {
|
|
}
|
|
}
|
|
return null;
|
|
});
|
|
|
|
Future<byte[]> future2 = CompletableFuture.supplyAsync(() -> {
|
|
try (InputStream st = Utils.class.getClassLoader().getResourceAsStream("asset/blank-profile-picture.png")) {
|
|
if (st == null)
|
|
return null;
|
|
return st.readAllBytes();
|
|
} catch (IOException ignored) {
|
|
}
|
|
return null;
|
|
});
|
|
|
|
return uniBase.chain(__ -> Uni.createFrom().future(future)
|
|
.chain(filePair -> {
|
|
if (filePair == null) {
|
|
if (default_) {
|
|
return Uni.createFrom().future(future2).map(data -> {
|
|
if (data == null)
|
|
return Response.noContent().build();
|
|
|
|
String mimeType = "image/apng";
|
|
Response.ResponseBuilder resp = Response.ok(data);
|
|
resp.type(MediaType.APPLICATION_OCTET_STREAM);
|
|
resp.header(HttpHeaders.CONTENT_LENGTH, data.length);
|
|
resp.header(HttpHeaders.CONTENT_TYPE, mimeType);
|
|
resp.header(HttpHeaders.CONTENT_DISPOSITION,
|
|
"inline; " + ((out_filename == null) ? "" : "filename=\"" + out_filename + "\""));
|
|
return resp.build();
|
|
});
|
|
} else {
|
|
Response.ResponseBuilder resp = Response.status(404);
|
|
resp.header(HttpHeaders.CACHE_CONTROL, "max-age=600");
|
|
return Uni.createFrom().item(resp.build());
|
|
}
|
|
} else {
|
|
return Uni.createFrom().item(() -> {
|
|
String mimeType = URLConnection.guessContentTypeFromName(filePair.getKey().getName());
|
|
|
|
|
|
String filename = out_filename;
|
|
if (filename != null && (filename.length() < 5 || filename.lastIndexOf(
|
|
'.') <= filename.length() - 6)) {
|
|
filename += filePair.getKey().getName()
|
|
.substring(filePair.getKey().getName().lastIndexOf('.'));
|
|
}
|
|
|
|
Response.ResponseBuilder resp = Response.ok(filePair.getValue());
|
|
resp.type(MediaType.APPLICATION_OCTET_STREAM);
|
|
resp.header(HttpHeaders.CONTENT_LENGTH, filePair.getValue().length);
|
|
resp.header(HttpHeaders.CONTENT_TYPE, mimeType);
|
|
resp.header(HttpHeaders.CONTENT_DISPOSITION,
|
|
"inline; " + ((filename == null) ? "" : "filename=\"" + filename + "\""));
|
|
return resp.build();
|
|
});
|
|
}
|
|
}));
|
|
}
|
|
|
|
public static Uni<?> deleteMedia(long id, String media, String dir) {
|
|
return Uni.createFrom().nullItem().map(__ -> {
|
|
File dirFile = new File(media, dir);
|
|
if (!dirFile.exists())
|
|
return "OK";
|
|
|
|
FilenameFilter filter = (directory, filename) -> filename.startsWith(id + ".");
|
|
File[] files = dirFile.listFiles(filter);
|
|
if (files != null) {
|
|
for (File file : files) {
|
|
//noinspection ResultOfMethodCallIgnored
|
|
file.delete();
|
|
}
|
|
}
|
|
return "Ok";
|
|
});
|
|
}
|
|
|
|
public static int getDaysBeforeCompetition(Date date) {
|
|
Calendar calendar = Calendar.getInstance();
|
|
calendar.setTime(date);
|
|
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
|
calendar.set(Calendar.MINUTE, 0);
|
|
calendar.set(Calendar.SECOND, 0);
|
|
|
|
Calendar now = Calendar.getInstance();
|
|
now.set(Calendar.HOUR_OF_DAY, 0);
|
|
now.set(Calendar.MINUTE, 0);
|
|
now.set(Calendar.SECOND, 0);
|
|
|
|
return (int) ((calendar.getTimeInMillis() - now.getTimeInMillis()) / (1000 * 60 * 60 * 24));
|
|
}
|
|
|
|
public static String formatPrenom(String input) {
|
|
if (input == null || input.isEmpty()) {
|
|
return input;
|
|
}
|
|
|
|
StringBuilder result = new StringBuilder();
|
|
String[] mots = input.split(" ");
|
|
|
|
for (String mot : mots) {
|
|
if (!mot.isEmpty()) {
|
|
String[] parties = mot.split("[-']");
|
|
StringBuilder motFormate = new StringBuilder();
|
|
|
|
for (int i = 0; i < parties.length; i++) {
|
|
if (!parties[i].isEmpty()) {
|
|
String premiereLettre = parties[i].substring(0, 1).toUpperCase();
|
|
String reste = parties[i].substring(1).toLowerCase();
|
|
motFormate.append(premiereLettre).append(reste);
|
|
}
|
|
|
|
if (i < parties.length - 1) {
|
|
motFormate.append(mot.charAt(mot.indexOf(parties[i]) + parties[i].length()));
|
|
}
|
|
}
|
|
result.append(motFormate).append(" ");
|
|
}
|
|
}
|
|
return result.toString().trim();
|
|
}
|
|
|
|
public static String getFullName(Object ...models) {
|
|
for (Object model : models){
|
|
if (model == null)
|
|
continue;
|
|
if (model instanceof MembreModel membreModel)
|
|
return membreModel.getFname() + " " + membreModel.getLname();
|
|
if (model instanceof CompetitionGuestModel guestModel)
|
|
return guestModel.getFname() + " " + guestModel.getLname();
|
|
}
|
|
return "";
|
|
}
|
|
}
|