feat: add option to disable OCR (#768)

fixes #344
refs #767
This commit is contained in:
Alexander ADAM 2024-09-07 22:27:48 +02:00 committed by GitHub
parent 8f1ff56d34
commit c2d7f3ebc6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 221 additions and 62 deletions

View File

@ -1,9 +1,9 @@
package com.sismics.docs.core.constant;
/**
* Configuration parameters.
* Configuration parameters.
*
* @author jtremeaux
* @author jtremeaux
*/
public enum ConfigType {
/**
@ -20,6 +20,11 @@ public enum ConfigType {
*/
GUEST_LOGIN,
/**
* OCR enabled.
*/
OCR_ENABLED,
/**
* Default language.
*/

View File

@ -8,13 +8,12 @@ import java.util.ResourceBundle;
/**
* Configuration parameter utilities.
*
* @author jtremeaux
*
*/
public class ConfigUtil {
/**
* Returns the textual value of a configuration parameter.
*
*
* @param configType Type of the configuration parameter
* @return Textual value of the configuration parameter
* @throws IllegalStateException Configuration parameter undefined
@ -30,7 +29,7 @@ public class ConfigUtil {
/**
* Returns the configuration resource bundle.
*
*
* @return Resource bundle
*/
public static ResourceBundle getConfigBundle() {
@ -39,14 +38,14 @@ public class ConfigUtil {
/**
* Returns the integer value of a configuration parameter.
*
*
* @param configType Type of the configuration parameter
* @return Integer value of the configuration parameter
* @throws IllegalStateException Configuration parameter undefined
*/
public static int getConfigIntegerValue(ConfigType configType) {
String value = getConfigStringValue(configType);
return Integer.parseInt(value);
}
@ -65,14 +64,28 @@ public class ConfigUtil {
/**
* Returns the boolean value of a configuration parameter.
*
*
* @param configType Type of the configuration parameter
* @return Boolean value of the configuration parameter
* @throws IllegalStateException Configuration parameter undefined
*/
public static boolean getConfigBooleanValue(ConfigType configType) {
String value = getConfigStringValue(configType);
return Boolean.parseBoolean(value);
}
/**
* Returns the boolean value of a configuration parameter with a default value.
*
* @param configType Type of the configuration parameter
* @param defaultValue Default value to return if the configuration parameter is undefined
* @return Boolean value of the configuration parameter
*/
public static boolean getConfigBooleanValue(ConfigType configType, boolean defaultValue) {
try {
return getConfigBooleanValue(configType);
} catch (IllegalStateException e) {
return defaultValue;
}
}
}

View File

@ -3,6 +3,8 @@ package com.sismics.docs.core.util.format;
import com.google.common.io.Closer;
import com.sismics.docs.core.constant.Constants;
import com.sismics.docs.core.util.FileUtil;
import com.sismics.docs.core.util.ConfigUtil;
import com.sismics.docs.core.constant.ConfigType;
import com.sismics.util.mime.MimeType;
import org.apache.pdfbox.io.MemoryUsageSetting;
import org.apache.pdfbox.pdmodel.PDDocument;
@ -22,7 +24,6 @@ import java.nio.file.Path;
/**
* Image format handler.
*
* @author bgamard
*/
public class ImageFormatHandler implements FormatHandler {
/**
@ -45,7 +46,7 @@ public class ImageFormatHandler implements FormatHandler {
@Override
public String extractContent(String language, Path file) throws Exception {
if (language == null) {
if (language == null || !ConfigUtil.getConfigBooleanValue(ConfigType.OCR_ENABLED, true)) {
return null;
}

View File

@ -2,6 +2,8 @@ package com.sismics.docs.core.util.format;
import com.google.common.io.Closer;
import com.sismics.docs.core.util.FileUtil;
import com.sismics.docs.core.util.ConfigUtil;
import com.sismics.docs.core.constant.ConfigType;
import com.sismics.util.mime.MimeType;
import org.apache.pdfbox.io.MemoryUsageSetting;
import org.apache.pdfbox.multipdf.PDFMergerUtility;
@ -53,7 +55,7 @@ public class PdfFormatHandler implements FormatHandler {
}
// No text content, try to OCR it
if (language != null && content != null && content.trim().isEmpty()) {
if (language != null && content != null && content.trim().isEmpty() && ConfigUtil.getConfigBooleanValue(ConfigType.OCR_ENABLED, true)) {
StringBuilder sb = new StringBuilder();
try (InputStream inputStream = Files.newInputStream(file);
PDDocument pdfDocument = PDDocument.load(inputStream)) {

View File

@ -39,7 +39,7 @@ abstract class DbOpenHelper {
private static final Logger log = LoggerFactory.getLogger(DbOpenHelper.class);
private final JdbcConnectionAccess jdbcConnectionAccess;
private final List<Exception> exceptions = new ArrayList<>();
private Formatter formatter;
@ -99,7 +99,7 @@ abstract class DbOpenHelper {
onCreate();
oldVersion = 0;
}
// Execute update script
ResourceBundle configBundle = ConfigUtil.getConfigBundle();
Integer currentVersion = Integer.parseInt(configBundle.getString("db.version"));
@ -126,7 +126,7 @@ abstract class DbOpenHelper {
/**
* Execute all upgrade scripts in ascending order for a given version.
*
*
* @param version Version number
* @throws Exception e
*/
@ -136,7 +136,7 @@ abstract class DbOpenHelper {
return name.matches("dbupdate-" + versionString + "-\\d+\\.sql");
});
Collections.sort(fileNameList);
for (String fileName : fileNameList) {
if (log.isInfoEnabled()) {
log.info(MessageFormat.format("Executing script: {0}", fileName));
@ -145,16 +145,16 @@ abstract class DbOpenHelper {
executeScript(is);
}
}
/**
* Execute a SQL script. All statements must be one line only.
*
*
* @param inputScript Script to execute
* @throws IOException e
*/
private void executeScript(InputStream inputScript) throws IOException {
List<String> lines = CharStreams.readLines(new InputStreamReader(inputScript));
for (String sql : lines) {
if (Strings.isNullOrEmpty(sql) || sql.startsWith("--")) {
continue;
@ -178,13 +178,13 @@ abstract class DbOpenHelper {
}
public abstract void onCreate() throws Exception;
public abstract void onUpgrade(int oldVersion, int newVersion) throws Exception;
/**
* Returns a List of all Exceptions which occured during the export.
* Returns a List of all Exceptions which occurred during the export.
*
* @return A List containig the Exceptions occured during the export
* @return A List containing the Exceptions occurred during the export
*/
public List<?> getExceptions() {
return exceptions;
@ -192,7 +192,7 @@ abstract class DbOpenHelper {
/**
* Format the output SQL statements.
*
*
* @param format True to format
*/
public void setFormat(boolean format) {

View File

@ -1 +1 @@
db.version=30
db.version=31

View File

@ -0,0 +1,7 @@
-- DBUPDATE-031-0.SQL
-- Insert a new setting for OCR recognition
insert into T_CONFIG (CFG_ID_C, CFG_VALUE_C) values ('OCR_ENABLED', 'true');
-- Update the database version
update T_CONFIG set CFG_VALUE_C = '31' where CFG_ID_C = 'DB_VERSION';

View File

@ -1,3 +1,3 @@
api.current_version=${project.version}
api.min_version=1.0
db.version=30
db.version=31

View File

@ -47,7 +47,7 @@ import java.util.*;
/**
* General app REST resource.
*
*
* @author jtremeaux
*/
@Path("/app")
@ -56,11 +56,11 @@ public class AppResource extends BaseResource {
* Logger.
*/
private static final Logger log = LoggerFactory.getLogger(AppResource.class);
/**
* Returns informations about the application.
* Returns information about the application.
*
* @api {get} /app Get application informations
* @api {get} /app Get application information
* @apiName GetApp
* @apiGroup App
* @apiSuccess {String} current_version API current version
@ -85,6 +85,7 @@ public class AppResource extends BaseResource {
String currentVersion = configBundle.getString("api.current_version");
String minVersion = configBundle.getString("api.min_version");
Boolean guestLogin = ConfigUtil.getConfigBooleanValue(ConfigType.GUEST_LOGIN);
Boolean ocrEnabled = ConfigUtil.getConfigBooleanValue(ConfigType.OCR_ENABLED, true);
String defaultLanguage = ConfigUtil.getConfigStringValue(ConfigType.DEFAULT_LANGUAGE);
UserDao userDao = new UserDao();
DocumentDao documentDao = new DocumentDao();
@ -98,6 +99,7 @@ public class AppResource extends BaseResource {
.add("current_version", currentVersion.replace("-SNAPSHOT", ""))
.add("min_version", minVersion)
.add("guest_login", guestLogin)
.add("ocr_enabled", ocrEnabled)
.add("default_language", defaultLanguage)
.add("queued_tasks", AppContext.getInstance().getQueuedTaskCount())
.add("total_memory", Runtime.getRuntime().totalMemory())
@ -140,6 +142,34 @@ public class AppResource extends BaseResource {
return Response.ok().build();
}
/**
* Enable/disable OCR.
*
* @api {post} /app/ocr Enable/disable OCR
* @apiName PostAppOcr
* @apiGroup App
* @apiParam {Boolean} enabled If true, enable OCR
* @apiError (client) ForbiddenError Access denied
* @apiPermission admin
* @apiVersion 1.5.0
*
* @param enabled If true, enable OCR
* @return Response
*/
@POST
@Path("ocr")
public Response ocr(@FormParam("enabled") Boolean enabled) {
if (!authenticate()) {
throw new ForbiddenClientException();
}
checkBaseFunction(BaseFunction.ADMIN);
ConfigDao configDao = new ConfigDao();
configDao.update(ConfigType.OCR_ENABLED, enabled.toString());
return Response.ok().build();
}
/**
* General application configuration.
*
@ -240,7 +270,7 @@ public class AppResource extends BaseResource {
return Response.ok().entity(response.build()).build();
}
/**
* Configure the SMTP server.
*
@ -546,13 +576,13 @@ public class AppResource extends BaseResource {
throw new ServerException("ServerError", "MEMORY appender not configured");
}
MemoryAppender memoryAppender = (MemoryAppender) appender;
// Find the logs
LogCriteria logCriteria = new LogCriteria()
.setMinLevel(Level.toLevel(StringUtils.stripToNull(minLevel)))
.setTag(StringUtils.stripToNull(tag))
.setMessage(StringUtils.stripToNull(message));
PaginatedList<LogEntry> paginatedList = PaginatedLists.create(limit, offset);
memoryAppender.find(logCriteria, paginatedList);
JsonArrayBuilder logs = Json.createArrayBuilder();
@ -563,14 +593,14 @@ public class AppResource extends BaseResource {
.add("tag", logEntry.getTag())
.add("message", logEntry.getMessage()));
}
JsonObjectBuilder response = Json.createObjectBuilder()
.add("total", paginatedList.getResultCount())
.add("logs", logs);
return Response.ok().entity(response.build()).build();
}
/**
* Destroy and rebuild the search index.
*
@ -592,7 +622,7 @@ public class AppResource extends BaseResource {
throw new ForbiddenClientException();
}
checkBaseFunction(BaseFunction.ADMIN);
RebuildIndexAsyncEvent rebuildIndexAsyncEvent = new RebuildIndexAsyncEvent();
ThreadLocalContext.get().addAsyncEvent(rebuildIndexAsyncEvent);
@ -601,7 +631,7 @@ public class AppResource extends BaseResource {
.add("status", "ok");
return Response.ok().entity(response.build()).build();
}
/**
* Clean storage.
*
@ -623,7 +653,7 @@ public class AppResource extends BaseResource {
throw new ForbiddenClientException();
}
checkBaseFunction(BaseFunction.ADMIN);
// Get all files
FileDao fileDao = new FileDao();
List<File> fileList = fileDao.findAll(0, Integer.MAX_VALUE);
@ -632,7 +662,7 @@ public class AppResource extends BaseResource {
fileMap.put(file.getId(), file);
}
log.info("Checking {} files", fileMap.size());
// Check if each stored file is valid
try (DirectoryStream<java.nio.file.Path> storedFileList = Files.newDirectoryStream(DirectoryUtil.getStorageDirectory())) {
for (java.nio.file.Path storedFile : storedFileList) {
@ -646,7 +676,7 @@ public class AppResource extends BaseResource {
} catch (IOException e) {
throw new ServerException("FileError", "Error deleting orphan files", e);
}
// Hard delete orphan audit logs
EntityManager em = ThreadLocalContext.get().getEntityManager();
StringBuilder sb = new StringBuilder("delete from T_AUDIT_LOG al where al.LOG_ID_C in (select al.LOG_ID_C from T_AUDIT_LOG al ");
@ -660,7 +690,7 @@ public class AppResource extends BaseResource {
sb.append(" where d.DOC_ID_C is null and a.ACL_ID_C is null and c.COM_ID_C is null and f.FIL_ID_C is null and t.TAG_ID_C is null and u.USE_ID_C is null and g.GRP_ID_C is null)");
Query q = em.createNativeQuery(sb.toString());
log.info("Deleting {} orphan audit logs", q.executeUpdate());
// Soft delete orphan ACLs
sb = new StringBuilder("update T_ACL a set ACL_DELETEDATE_D = :dateNow where a.ACL_ID_C in (select a.ACL_ID_C from T_ACL a ");
sb.append(" left join T_SHARE s on s.SHA_ID_C = a.ACL_TARGETID_C ");
@ -672,37 +702,37 @@ public class AppResource extends BaseResource {
q = em.createNativeQuery(sb.toString());
q.setParameter("dateNow", new Date());
log.info("Deleting {} orphan ACLs", q.executeUpdate());
// Soft delete orphan comments
q = em.createNativeQuery("update T_COMMENT set COM_DELETEDATE_D = :dateNow where COM_ID_C in (select c.COM_ID_C from T_COMMENT c left join T_DOCUMENT d on d.DOC_ID_C = c.COM_IDDOC_C and d.DOC_DELETEDATE_D is null where d.DOC_ID_C is null)");
q.setParameter("dateNow", new Date());
log.info("Deleting {} orphan comments", q.executeUpdate());
// Soft delete orphan document tag links
q = em.createNativeQuery("update T_DOCUMENT_TAG set DOT_DELETEDATE_D = :dateNow where DOT_ID_C in (select dt.DOT_ID_C from T_DOCUMENT_TAG dt left join T_DOCUMENT d on dt.DOT_IDDOCUMENT_C = d.DOC_ID_C and d.DOC_DELETEDATE_D is null left join T_TAG t on t.TAG_ID_C = dt.DOT_IDTAG_C and t.TAG_DELETEDATE_D is null where d.DOC_ID_C is null or t.TAG_ID_C is null)");
q.setParameter("dateNow", new Date());
log.info("Deleting {} orphan document tag links", q.executeUpdate());
// Soft delete orphan shares
q = em.createNativeQuery("update T_SHARE set SHA_DELETEDATE_D = :dateNow where SHA_ID_C in (select s.SHA_ID_C from T_SHARE s left join T_ACL a on a.ACL_TARGETID_C = s.SHA_ID_C and a.ACL_DELETEDATE_D is null where a.ACL_ID_C is null)");
q.setParameter("dateNow", new Date());
log.info("Deleting {} orphan shares", q.executeUpdate());
// Soft delete orphan tags
q = em.createNativeQuery("update T_TAG set TAG_DELETEDATE_D = :dateNow where TAG_ID_C in (select t.TAG_ID_C from T_TAG t left join T_USER u on u.USE_ID_C = t.TAG_IDUSER_C and u.USE_DELETEDATE_D is null where u.USE_ID_C is null)");
q.setParameter("dateNow", new Date());
log.info("Deleting {} orphan tags", q.executeUpdate());
// Soft delete orphan documents
q = em.createNativeQuery("update T_DOCUMENT set DOC_DELETEDATE_D = :dateNow where DOC_ID_C in (select d.DOC_ID_C from T_DOCUMENT d left join T_USER u on u.USE_ID_C = d.DOC_IDUSER_C and u.USE_DELETEDATE_D is null where u.USE_ID_C is null)");
q.setParameter("dateNow", new Date());
log.info("Deleting {} orphan documents", q.executeUpdate());
// Soft delete orphan files
q = em.createNativeQuery("update T_FILE set FIL_DELETEDATE_D = :dateNow where FIL_ID_C in (select f.FIL_ID_C from T_FILE f left join T_USER u on u.USE_ID_C = f.FIL_IDUSER_C and u.USE_DELETEDATE_D is null where u.USE_ID_C is null)");
q.setParameter("dateNow", new Date());
log.info("Deleting {} orphan files", q.executeUpdate());
// Hard delete softly deleted data
log.info("Deleting {} soft deleted document tag links", em.createQuery("delete DocumentTag where deleteDate is not null").executeUpdate());
log.info("Deleting {} soft deleted ACLs", em.createQuery("delete Acl where deleteDate is not null").executeUpdate());
@ -713,7 +743,7 @@ public class AppResource extends BaseResource {
log.info("Deleting {} soft deleted documents", em.createQuery("delete Document where deleteDate is not null").executeUpdate());
log.info("Deleting {} soft deleted users", em.createQuery("delete User where deleteDate is not null").executeUpdate());
log.info("Deleting {} soft deleted groups", em.createQuery("delete Group where deleteDate is not null").executeUpdate());
// Always return OK
JsonObjectBuilder response = Json.createObjectBuilder()
.add("status", "ok");

View File

@ -21,6 +21,15 @@ angular.module('docs').controller('SettingsConfig', function($scope, $rootScope,
});
};
// Enable/disable OCR
$scope.changeOcrEnabled = function (enabled) {
Restangular.one('app').post('ocr', {
enabled: enabled
}).then(function () {
$scope.app.ocr_enabled = enabled;
});
};
// Fetch the current theme configuration
Restangular.one('theme').get().then(function (data) {
$scope.theme = data;
@ -36,7 +45,7 @@ angular.module('docs').controller('SettingsConfig', function($scope, $rootScope,
$rootScope.appName = $scope.theme.name;
});
};
// Send an image
$scope.sendingImage = false;
$scope.sendImage = function (type, image) {
@ -108,4 +117,4 @@ angular.module('docs').controller('SettingsConfig', function($scope, $rootScope,
$scope.loadWebhooks();
});
};
});
});

View File

@ -421,6 +421,10 @@
"smtp_username": "SMTP-Benutzername",
"smtp_password": "SMTP-Passwort",
"smtp_updated": "SMTP-Konfiguration erfolgreich aktualisiert",
"title_ocr": "Texterkennung (OCR)",
"message_ocr": "OCR ist eine Technologie, die es ermöglicht, Text aus Bildern zu extrahieren. Es wird verwendet, um den Inhalt von Bildern zu durchsuchen und zu indizieren. Diese Funktionalität setzt voraus, dass die Tesseract auf Ihrem Server installiert ist.",
"enable_ocr": "OCR aktivieren",
"disable_ocr": "OCR deaktivieren",
"webhooks": "Webhooks",
"webhooks_explain": "Webhooks werden aufgerufen, wenn das angegebene Ereignis eintritt. Die angegebene URL wird mit einer JSON-Payload gepostet, die den Ereignisnamen und die ID der betreffenden Ressource enthält.",
"webhook_event": "Ereignisse",

View File

@ -421,6 +421,10 @@
"smtp_username": "SMTP username",
"smtp_password": "SMTP password",
"smtp_updated": "SMTP configuration updated successfully",
"title_ocr": "Optical Character Recognition (OCR)",
"message_ocr": "OCR is a feature that extracts text from images and PDF files. This feature requires a working Tesseract installation on the server.",
"enable_ocr": "Enable OCR",
"disable_ocr": "Disable OCR",
"webhooks": "Webhooks",
"webhooks_explain": "Webhooks will be called when the specified event occur. The given URL will be POST-ed with a JSON payload containing the event name and the ID of the concerned resource.",
"webhook_event": "Event",

View File

@ -31,6 +31,17 @@
</div>
</form>
<h2>
<span translate="settings.config.title_ocr"></span>
<span class="label" ng-class="{ 'label-success': app.ocr_enabled, 'label-danger': !app.ocr_enabled }">
{{ app.ocr_enabled ? 'enabled' : 'disabled' | translate }}
</h2>
<p translate="settings.config.message_ocr" translate-values="{ appName: appName }"></p>
<div ng-if="app">
<button ng-if="!app.ocr_enabled" class="btn btn-primary" ng-click="changeOcrEnabled(true)">{{ 'settings.config.enable_ocr' | translate }}</button>
<button ng-if="app.ocr_enabled" class="btn btn-danger" ng-click="changeOcrEnabled(false)">{{ 'settings.config.disable_ocr' | translate }}</button>
</div>
<h2 translate="settings.config.title_theme"></h2>
<form class="form-horizontal" name="editColorForm" novalidate>
<div class="form-group">
@ -196,4 +207,4 @@
</td>
</tr>
</table>
</div>
</div>

View File

@ -1,3 +1,3 @@
api.current_version=${project.version}
api.min_version=1.0
db.version=30
db.version=31

View File

@ -29,7 +29,7 @@ import org.junit.Test;
/**
* Test the app resource.
*
*
* @author jtremeaux
*/
public class TestAppResource extends BaseJerseyTest {
@ -46,7 +46,7 @@ public class TestAppResource extends BaseJerseyTest {
public void testAppResource() {
// Login admin
String adminToken = adminToken();
// Check the application info
JsonObject json = target().path("/app").request()
.get(JsonObject.class);
@ -58,6 +58,7 @@ public class TestAppResource extends BaseJerseyTest {
Assert.assertTrue(totalMemory > 0 && totalMemory > freeMemory);
Assert.assertEquals(0, json.getJsonNumber("queued_tasks").intValue());
Assert.assertFalse(json.getBoolean("guest_login"));
Assert.assertFalse(json.getBoolean("ocr_enabled"));
Assert.assertEquals("eng", json.getString("default_language"));
Assert.assertTrue(json.containsKey("global_storage_current"));
Assert.assertTrue(json.getJsonNumber("active_user_count").longValue() > 0);
@ -67,13 +68,13 @@ public class TestAppResource extends BaseJerseyTest {
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
.post(Entity.form(new Form()));
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
// Clean storage
response = target().path("/app/batch/clean_storage").request()
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
.post(Entity.form(new Form()));
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
// Change the default language
response = target().path("/app/config").request()
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
@ -104,7 +105,7 @@ public class TestAppResource extends BaseJerseyTest {
public void testLogResource() {
// Login admin
String adminToken = adminToken();
// Check the logs (page 1)
JsonObject json = target().path("/app/log")
.queryParam("level", "DEBUG")
@ -116,7 +117,7 @@ public class TestAppResource extends BaseJerseyTest {
Long date1 = logs.getJsonObject(0).getJsonNumber("date").longValue();
Long date2 = logs.getJsonObject(9).getJsonNumber("date").longValue();
Assert.assertTrue(date1 >= date2);
// Check the logs (page 2)
json = target().path("/app/log")
.queryParam("offset", "10")
@ -194,7 +195,7 @@ public class TestAppResource extends BaseJerseyTest {
target().path("/document/list").request()
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, guestToken)
.get(JsonObject.class);
// Disable guest login (clean up state)
target().path("/app/guest_login").request()
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
@ -202,6 +203,37 @@ public class TestAppResource extends BaseJerseyTest {
.param("enabled", "false")), JsonObject.class);
}
/**
* Test the ocr setting
*/
@Test
public void testOcrSetting() {
// Login admin
String adminToken = adminToken();
// Get OCR configuration
JsonObject json = target().path("/app/ocr").request()
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
.get(JsonObject.class);
if (!configInboxChanged) {
Assert.assertFalse(json.getBoolean("enabled"));
}
// Change OCR configuration
target().path("/app/ocr").request()
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
.post(Entity.form(new Form()
.param("enabled", "true")
), JsonObject.class);
configInboxChanged = true;
// Get OCR configuration
json = target().path("/app/ocr").request()
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
.get(JsonObject.class);
Assert.assertTrue(json.getBoolean("enabled"));
}
/**
* Test SMTP configuration changes.
*/

41
scripts/dev_setup.sh Executable file
View File

@ -0,0 +1,41 @@
#!/bin/bash
install_macos_dependencies() {
brew install openjdk@11
export JAVA_HOME=/usr/local/opt/openjdk@11
brew install maven
brew install node
npm install -g grunt-cli
brew install tesseract
brew install ffmpeg
brew install mediainfo
}
install_ubuntu_debian_dependencies() {
sudo apt update
sudo apt install -y openjdk-11-jdk maven nodejs npm tesseract-ocr ffmpeg mediainfo
sudo npm install -g grunt-cli
}
install_fedora_dependencies() {
sudo dnf install -y java-11-openjdk-devel maven nodejs npm tesseract ffmpeg mediainfo
sudo npm install -g grunt-cli
}
echo "📥 Installing dependencies"
if [[ "$OSTYPE" == "darwin"* ]]; then
install_macos_dependencies
elif [[ -f /etc/debian_version ]]; then
install_ubuntu_debian_dependencies
elif [[ -f /etc/fedora-release ]]; then
install_fedora_dependencies
else
echo "❔ Unsupported OS. Feel free to contribute!"
exit 1
fi
echo "✅ Dependencies installed."
mvn clean -DskipTests install
echo "You can start the server with 'mvn jetty:run' and then access it at http://localhost:8080/docs-web/src/"