Extract Jellyfin thumbnails as a module
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
package sh.rhiobet.lalafin.api.thumbnail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
import javax.inject.Inject;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
import org.im4java.core.ConvertCmd;
|
||||
import org.im4java.core.IM4JavaException;
|
||||
import org.im4java.core.IMOperation;
|
||||
import sh.rhiobet.lalafin.api.configuration.FileApiConfiguration;
|
||||
import sh.rhiobet.lalafin.api.model.FileInfo;
|
||||
import sh.rhiobet.lalafin.api.model.FileInfoBase;
|
||||
import sh.rhiobet.lalafin.api.model.FolderInfo;
|
||||
|
||||
@ApplicationScoped
|
||||
public class JellyfinThumbnailGenerator implements ThumbnailGenerator {
|
||||
|
||||
@ConfigProperty(name = "api.thumbnail.jellyfin.paths")
|
||||
Optional<List<String>> paths;
|
||||
|
||||
@Inject
|
||||
FileApiConfiguration fileApiConfiguration;
|
||||
|
||||
@Override
|
||||
public boolean canHandle(FileInfoBase fileInfoBase) {
|
||||
if (paths.isPresent()) {
|
||||
String filePath = URLDecoder.decode(fileInfoBase.directUrl, StandardCharsets.UTF_8);
|
||||
for (String path : paths.get()) {
|
||||
if (filePath.toString().startsWith("/file" + path)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean generateThumbnail(FileInfoBase fileInfoBase, Path thumbPath) {
|
||||
if (fileInfoBase instanceof FileInfo) {
|
||||
return this.generateThumbnailForFile((FileInfo) fileInfoBase, thumbPath);
|
||||
} else if (fileInfoBase instanceof FolderInfo) {
|
||||
return this.generateThumbnailForFolder((FolderInfo) fileInfoBase, thumbPath);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean generateThumbnailForFile(FileInfo fileInfo, Path thumbPath) {
|
||||
Path filePath = Paths.get(fileApiConfiguration.directory()
|
||||
+ URLDecoder.decode(fileInfo.directUrl, StandardCharsets.UTF_8));
|
||||
|
||||
Path imgPath = filePath.resolveSibling(
|
||||
filePath.getFileName().toString().replaceAll("\\.[^.]*$", "-thumb.jpg"));
|
||||
if (Files.exists(imgPath)) {
|
||||
try {
|
||||
thumbPath.getParent().toFile().mkdirs();
|
||||
|
||||
ConvertCmd convert = new ConvertCmd();
|
||||
IMOperation op = new IMOperation();
|
||||
op.addImage(imgPath.toString());
|
||||
op.resize(200, null);
|
||||
op.addImage(thumbPath.toString());
|
||||
convert.run(op);
|
||||
|
||||
return true;
|
||||
} catch (IOException | InterruptedException | IM4JavaException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean generateThumbnailForFolder(FolderInfo folderInfo, Path thumbPath) {
|
||||
Path folderPath = Paths.get(fileApiConfiguration.directory()
|
||||
+ URLDecoder.decode(folderInfo.directUrl, StandardCharsets.UTF_8));
|
||||
|
||||
try {
|
||||
Optional<Path> imgPath;
|
||||
|
||||
Path posterPath = folderPath.resolve("poster.jpg");
|
||||
if (Files.exists(posterPath)) {
|
||||
// Check for series poster
|
||||
imgPath = Optional.of(posterPath);
|
||||
} else if (folderPath.getFileName().toString().startsWith("Season ")
|
||||
|| (folderPath.getFileName().toString().equals("Specials"))) {
|
||||
// Season folder
|
||||
String folderName = folderPath.getFileName().toString();
|
||||
if (folderName.startsWith("Season ")) {
|
||||
String seasonNumber =
|
||||
String.format("%02d", Integer.parseInt(folderName.substring(7)));
|
||||
imgPath = Optional
|
||||
.of(folderPath.resolveSibling("season" + seasonNumber + "-poster.jpg"));
|
||||
} else {
|
||||
imgPath = Optional.of(folderPath.resolveSibling("season-specials-poster.jpg"));
|
||||
}
|
||||
} else {
|
||||
imgPath = Optional.empty();
|
||||
}
|
||||
if (imgPath.isPresent()) {
|
||||
thumbPath.getParent().toFile().mkdirs();
|
||||
|
||||
ConvertCmd convert = new ConvertCmd();
|
||||
IMOperation op = new IMOperation();
|
||||
op.addImage(imgPath.get().toString());
|
||||
op.resize(200, null);
|
||||
op.addImage(thumbPath.toString());
|
||||
convert.run(op);
|
||||
|
||||
return true;
|
||||
}
|
||||
} catch (IOException | InterruptedException | IM4JavaException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package sh.rhiobet.lalafin.api.thumbnail;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import sh.rhiobet.lalafin.api.model.FileInfoBase;
|
||||
|
||||
public interface ThumbnailGenerator {
|
||||
|
||||
boolean canHandle(FileInfoBase fileInfoBase);
|
||||
|
||||
boolean generateThumbnail(FileInfoBase fileInfoBase, Path thumbPath);
|
||||
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import java.util.Optional;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
import javax.enterprise.inject.Instance;
|
||||
import javax.inject.Inject;
|
||||
import org.im4java.core.ConvertCmd;
|
||||
import org.im4java.core.IM4JavaException;
|
||||
@@ -19,19 +20,26 @@ import sh.rhiobet.lalafin.api.configuration.FileApiConfiguration;
|
||||
import sh.rhiobet.lalafin.api.model.FileInfo;
|
||||
import sh.rhiobet.lalafin.api.model.FileInfoBase;
|
||||
import sh.rhiobet.lalafin.api.model.FolderInfo;
|
||||
import sh.rhiobet.lalafin.api.thumbnail.ThumbnailGenerator;
|
||||
|
||||
@ApplicationScoped
|
||||
public class ThumbnailService {
|
||||
@Inject
|
||||
FileApiConfiguration fileApiConfiguration;
|
||||
|
||||
@Inject
|
||||
Instance<ThumbnailGenerator> generators;
|
||||
|
||||
public boolean generateThumbnail(FileInfoBase fileInfoBase, Path thumbPath) {
|
||||
for (ThumbnailGenerator generator : generators) {
|
||||
if (generator.canHandle(fileInfoBase)) {
|
||||
return generator.generateThumbnail(fileInfoBase, thumbPath);
|
||||
}
|
||||
}
|
||||
if (fileInfoBase instanceof FileInfo) {
|
||||
FileInfo fileInfo = (FileInfo) fileInfoBase;
|
||||
if (fileInfo.filename.endsWith(".zip")) {
|
||||
return this.generateThumbnailFromZip(fileInfo, thumbPath);
|
||||
} else {
|
||||
return this.generateThumbnailForFile(fileInfo, thumbPath);
|
||||
}
|
||||
} else if (fileInfoBase instanceof FolderInfo) {
|
||||
return this.generateThumbnailForFolder((FolderInfo) fileInfoBase, thumbPath);
|
||||
@@ -39,32 +47,6 @@ public class ThumbnailService {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean generateThumbnailForFile(FileInfo fileInfo, Path thumbPath) {
|
||||
Path filePath = Paths.get(fileApiConfiguration.directory()
|
||||
+ URLDecoder.decode(fileInfo.directUrl, StandardCharsets.UTF_8));
|
||||
|
||||
Path imgPath = filePath.resolveSibling(
|
||||
filePath.getFileName().toString().replaceAll("\\.[^.]*$", "-thumb.jpg"));
|
||||
if (Files.exists(imgPath)) {
|
||||
try {
|
||||
thumbPath.getParent().toFile().mkdirs();
|
||||
|
||||
ConvertCmd convert = new ConvertCmd();
|
||||
IMOperation op = new IMOperation();
|
||||
op.addImage(imgPath.toString());
|
||||
op.resize(200, null);
|
||||
op.addImage(thumbPath.toString());
|
||||
convert.run(op);
|
||||
|
||||
return true;
|
||||
} catch (IOException | InterruptedException | IM4JavaException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean generateThumbnailFromZip(FileInfo fileInfo, Path thumbPath) {
|
||||
Path zipPath = Paths.get(fileApiConfiguration.directory()
|
||||
+ URLDecoder.decode(fileInfo.directUrl, StandardCharsets.UTF_8));
|
||||
@@ -105,30 +87,10 @@ public class ThumbnailService {
|
||||
+ URLDecoder.decode(folderInfo.directUrl, StandardCharsets.UTF_8));
|
||||
|
||||
try {
|
||||
Optional<Path> imgPath;
|
||||
|
||||
Path posterPath = folderPath.resolve("poster.jpg");
|
||||
if (Files.exists(posterPath)) {
|
||||
// Check for series poster
|
||||
imgPath = Optional.of(posterPath);
|
||||
} else if (folderPath.getFileName().toString().startsWith("Season ")
|
||||
|| (folderPath.getFileName().toString().equals("Specials"))) {
|
||||
// Season folder
|
||||
String folderName = folderPath.getFileName().toString();
|
||||
if (folderName.startsWith("Season ")) {
|
||||
String seasonNumber =
|
||||
String.format("%02d", Integer.parseInt(folderName.substring(7)));
|
||||
imgPath = Optional
|
||||
.of(folderPath.resolveSibling("season" + seasonNumber + "-poster.jpg"));
|
||||
} else {
|
||||
imgPath = Optional.of(folderPath.resolveSibling("season-specials-poster.jpg"));
|
||||
}
|
||||
} else {
|
||||
imgPath = Files.list(folderPath).sorted()
|
||||
.filter(p -> !Files.isDirectory(p)
|
||||
&& (p.toString().endsWith(".png") || p.toString().endsWith(".jpg")))
|
||||
.findFirst();
|
||||
}
|
||||
Optional<Path> imgPath = Files.list(folderPath).sorted()
|
||||
.filter(p -> !Files.isDirectory(p)
|
||||
&& (p.toString().endsWith(".png") || p.toString().endsWith(".jpg")))
|
||||
.findFirst();
|
||||
if (imgPath.isPresent()) {
|
||||
thumbPath.getParent().toFile().mkdirs();
|
||||
|
||||
|
||||
@@ -31,3 +31,7 @@ api:
|
||||
roles: {} # Only users with these roles will have access to this route (empty = ALL)
|
||||
folder:
|
||||
tokens: {} # List of tokens to make some routes available trhough the public folders API
|
||||
|
||||
# thumbnail:
|
||||
# jellyfin:
|
||||
# paths: {}
|
||||
Reference in New Issue
Block a user