Skip to content

Commit

Permalink
Merge pull request #111 from Suwayomi/serverVersionApi
Browse files Browse the repository at this point in the history
Added Meta Info API Service for Suwayomi
  • Loading branch information
aless2003 authored Apr 9, 2024
2 parents 3d673f2 + 00d15aa commit e8b0bdc
Show file tree
Hide file tree
Showing 4 changed files with 232 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

package online.hatsunemiku.tachideskvaadinui.data.tachidesk;

import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.Getter;

/** Represents the version of the Suwayomi Server. */
@Getter
public class ServerVersion {

/** The version of the server. Format: vX.Y.Z */
private final String version;

/** The revision of the server. Format: r1234 */
private final String revision;

/**
* Creates a new instance of the {@link ServerVersion} class.
*
* @param version the version of the server
* @param revision the revision of the server
*/
// Private constructor so only Spring can create instances of this class
@JsonCreator
private ServerVersion(String version, String revision) {
this.version = version;
this.revision = revision;
}

/**
* Gets the major version of the server. For example if the version is v1.2.3, this method will
* return 1.
*
* @return the major version of the server
*/
public int getMajorVersion() {
String majorVersion = version.substring(1, version.indexOf('.'));
return Integer.parseInt(majorVersion);
}

/**
* Gets the minor version of the server. For example if the version is v1.2.3, this method will
* return 2.
*
* @return the minor version of the server
*/
public int getMinorVersion() {
int firstDot = version.indexOf('.');
int secondDot = version.indexOf('.', firstDot + 1);
String minorVersion = version.substring(firstDot + 1, secondDot);
return Integer.parseInt(minorVersion);
}

/**
* Gets the patch version of the server. For example if the version is v1.2.3, this method will
* return 3.
*
* @return the patch version of the server
*/
public int getPatchVersion() {
int lastDot = version.lastIndexOf('.');
String patchVersion = version.substring(lastDot + 1);
return Integer.parseInt(patchVersion);
}

/**
* Gets the revision number of the server. For example if the revision is r1234, this method will
* return 1234.
*
* @return the revision number of the server
*/
public int getRevisionNumber() {
String revisionNumber = revision.substring(1);
return Integer.parseInt(revisionNumber);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

package online.hatsunemiku.tachideskvaadinui.services;

import java.util.Optional;
import online.hatsunemiku.tachideskvaadinui.data.tachidesk.ServerVersion;
import online.hatsunemiku.tachideskvaadinui.services.client.suwayomi.SuwayomiMetaClient;
import org.springframework.stereotype.Service;

/**
* Responsible for retrieving data from the Suwayomi Server. This class is an abstraction over the
* {@link SuwayomiMetaClient} class and provides methods for retrieving data from the Suwayomi
* Server.
*/
@Service
public class SuwayomiService {

private final SuwayomiMetaClient metaClient;

/**
* Creates a new instance of the {@link SuwayomiService} class.
*
* @param metaClient the {@link SuwayomiMetaClient} used for retrieving data from the Suwayomi
* Server.
*/
public SuwayomiService(SuwayomiMetaClient metaClient) {
this.metaClient = metaClient;
}

/**
* Retrieves the version of the Suwayomi Server. This method will block until the response is
* received.
*
* @return either the version of the Suwayomi Server if successful or an empty {@link Optional} if
* an error occurred.
*/
public Optional<ServerVersion> getServerVersion() {
try {
return Optional.of(metaClient.getServerVersion());
} catch (Exception e) {
return Optional.empty();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

package online.hatsunemiku.tachideskvaadinui.services.client.suwayomi;

import online.hatsunemiku.tachideskvaadinui.data.tachidesk.ServerVersion;
import online.hatsunemiku.tachideskvaadinui.services.WebClientService;
import org.intellij.lang.annotations.Language;
import org.springframework.stereotype.Component;

/** Retrieves metadata about the Suwayomi Server through its API. */
@Component
public class SuwayomiMetaClient {

private final WebClientService webClientService;

/**
* Creates a new instance of the {@link SuwayomiMetaClient} class.
*
* @param webClientService the {@link WebClientService} used for making API requests to the
* Suwayomi Server.
*/
public SuwayomiMetaClient(WebClientService webClientService) {
this.webClientService = webClientService;
}

/**
* Retrieves the version of the Suwayomi Server though its API. This method will block until the
* response is received.
*
* @return the version of the Suwayomi Server.
*/
public ServerVersion getServerVersion() {
var client = webClientService.getDgsGraphQlClient();

@Language("graphql")
String query =
"""
query {
aboutServer {
version
revision
}
}
""";

var response = client.reactiveExecuteQuery(query).block();

if (response == null) {
throw new RuntimeException("Failed to retrieve server version");
}

return response.extractValueAsObject("aboutServer", ServerVersion.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,27 @@
import jakarta.annotation.PreDestroy;
import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
import online.hatsunemiku.tachideskvaadinui.data.Meta;
import online.hatsunemiku.tachideskvaadinui.data.server.event.ServerEventPublisher;
import online.hatsunemiku.tachideskvaadinui.data.settings.Settings;
import online.hatsunemiku.tachideskvaadinui.data.settings.event.UrlChangeEvent;
import online.hatsunemiku.tachideskvaadinui.services.SettingsService;
import online.hatsunemiku.tachideskvaadinui.services.SuwayomiService;
import online.hatsunemiku.tachideskvaadinui.utils.BrowserUtils;
import online.hatsunemiku.tachideskvaadinui.utils.SerializationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

/**
* Is responsible for starting the Suwayomi (previously Tachidesk) server. Additionally, it checks
* if the server is running and publishes an event if it is.
*/
@Service
@Slf4j
public class TachideskStarter {
Expand All @@ -35,11 +40,23 @@ public class TachideskStarter {
private ScheduledExecutorService startChecker;
private final SettingsService settingsService;
private final ServerEventPublisher serverEventPublisher;

private final SuwayomiService suwayomiApi;

/**
* Creates a new instance of the {@link TachideskStarter} class.
*
* @param settingsService The {@link SettingsService} used for retrieving settings.
* @param serverEventPublisher The {@link ServerEventPublisher} used for publishing server events
* to the application.
* @param suwayomiApi The {@link SuwayomiService} used for checking if the server is running.
*/
public TachideskStarter(
SettingsService settingsService, ServerEventPublisher serverEventPublisher) {
SettingsService settingsService,
ServerEventPublisher serverEventPublisher,
SuwayomiService suwayomiApi) {
this.settingsService = settingsService;
this.serverEventPublisher = serverEventPublisher;
this.suwayomiApi = suwayomiApi;
}

public void startJar(File projectDir) {
Expand Down Expand Up @@ -153,20 +170,35 @@ private void checkIfServerIsRunning() {
startChecker = null;
}

/**
* Checks if the server is running. It both checks if the server process exists and if the server
* is reachable and gives a valid response.
*
* @return {@code true} if the server is running, {@code false} otherwise.
*/
private boolean checkServerConnection() {
if (serverProcess == null) {
throw new RuntimeException("Server process is null");
}

try {
HttpURLConnection connection =
(HttpURLConnection) new URL("http://localhost:4567/api/graphql").openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(500);
connection.connect();
int code = connection.getResponseCode();
return code == 200;
} catch (IOException e) {
var optional = suwayomiApi.getServerVersion();

if (optional.isEmpty()) {
return false;
}

var version = optional.get();

logger.info(
"Server version: Major={},Minor={},Patch={} with Revision={}",
version.getMajorVersion(),
version.getMinorVersion(),
version.getPatchVersion(),
version.getRevisionNumber());
return true;
} catch (Exception e) {
logger.info("Server not running", e);
return false;
}
}
Expand Down

0 comments on commit e8b0bdc

Please sign in to comment.