diff --git a/pom.xml b/pom.xml index 51c9794..b7dd170 100644 --- a/pom.xml +++ b/pom.xml @@ -70,8 +70,8 @@ com.github.seratch - jslack - 3.3.0 + jslack-lightning + 3.4.2 javax.websocket diff --git a/src/main/java/com/botdarr/Application.java b/src/main/java/com/botdarr/Application.java deleted file mode 100644 index a74def5..0000000 --- a/src/main/java/com/botdarr/Application.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.botdarr; - -import com.botdarr.commands.Command; - -import java.util.List; - -public interface Application { - void init(List commands) throws Exception; -} diff --git a/src/main/java/com/botdarr/BotdarrApplication.java b/src/main/java/com/botdarr/BotdarrApplication.java index 65a1a5e..e7716ba 100644 --- a/src/main/java/com/botdarr/BotdarrApplication.java +++ b/src/main/java/com/botdarr/BotdarrApplication.java @@ -1,10 +1,15 @@ package com.botdarr; -import com.botdarr.database.Bootstrap; +import com.botdarr.clients.ChatClientBootstrap; +import com.botdarr.database.DatabaseBootstrap; public class BotdarrApplication { public static void main(String[] args) throws Exception { - Bootstrap.init(); - Config.getChatClientType().init(); + // bootstrap the database + DatabaseBootstrap.init(); + + // boostrap the chat client/bot + ChatClientBootstrap chatClientBootstrap = Config.getChatClientBootstrap(); + chatClientBootstrap.init(); } } diff --git a/src/main/java/com/botdarr/Config.java b/src/main/java/com/botdarr/Config.java index 8072650..781925b 100644 --- a/src/main/java/com/botdarr/Config.java +++ b/src/main/java/com/botdarr/Config.java @@ -1,7 +1,10 @@ package com.botdarr; -import com.botdarr.clients.ChatClientType; -import com.botdarr.commands.StatusCommand; +import com.botdarr.clients.ChatClientBootstrap; +import com.botdarr.clients.discord.DiscordBootstrap; +import com.botdarr.clients.matrix.MatrixBootstrap; +import com.botdarr.clients.slack.SlackBootstrap; +import com.botdarr.clients.telegram.TelegramBootstrap; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.util.Strings; @@ -34,22 +37,22 @@ private Config() { properties = new Properties(); properties.load(input); - for (ChatClientType possibleChatClientType : ChatClientType.values()) { - if (possibleChatClientType.isConfigured(properties) && chatClientType != null) { + List availableBootstraps = Arrays.asList( + new DiscordBootstrap(), + new MatrixBootstrap(), + new SlackBootstrap(), + new TelegramBootstrap()); + for (ChatClientBootstrap possibleChatClientType : availableBootstraps) { + if (possibleChatClientType.isConfigured(properties) && chatClientBootstrap != null) { throw new RuntimeException("You cannot configure more than one chat client"); } if (possibleChatClientType.isConfigured(properties)) { - chatClientType = possibleChatClientType; + chatClientBootstrap = possibleChatClientType; } } - if (chatClientType == null) { - String allChatClientTypes = Arrays.asList(ChatClientType.values()) - .stream() - .sorted(Comparator.comparing(ChatClientType::getReadableName)) - .map(ChatClientType::getReadableName) - .collect(Collectors.joining(", ")); - throw new RuntimeException("You don't have " + allChatClientTypes + " configured, please configure one"); + if (chatClientBootstrap == null) { + throw new RuntimeException("You don't have any chat clients configured, please configure one"); } this.isRaddarrEnabled = @@ -85,15 +88,7 @@ private Config() { String configuredPrefix = properties.getProperty(Config.Constants.COMMAND_PREFIX); if (!Strings.isEmpty(configuredPrefix)) { - if (configuredPrefix.length() > 1) { - throw new RuntimeException("Command prefix must be a single character"); - } - if (chatClientType == ChatClientType.SLACK && configuredPrefix.equals("/")) { - throw new RuntimeException("Cannot use / command prefix in slack since /help command was deprecated by slack"); - } - if (chatClientType == ChatClientType.MATRIX && configuredPrefix.equals("/")) { - throw new RuntimeException("Cannot use / command prefix in matrix since /help command is used by element by default"); - } + chatClientBootstrap.validatePrefix(configuredPrefix); } } catch (Exception ex) { LOGGER.error("Error loading properties file", ex); @@ -117,8 +112,8 @@ public static boolean isLidarrEnabled() { return getConfig().isLidarrEnabled; } - public static ChatClientType getChatClientType() { - return getConfig().chatClientType; + public static ChatClientBootstrap getChatClientBootstrap() { + return getConfig().chatClientBootstrap; } public static List getExistingItemBlacklistPaths() { @@ -134,7 +129,7 @@ public static List getStatusEndpoints() { if (splitEndpoint.length != 3) { LOGGER.warn("Status endpoint not formatted correctly, usage - name:hostname:port, endpoint=" + endpoint); } - statusEndPoints.add(new StatusEndPoint(splitEndpoint[0], splitEndpoint[1], Integer.valueOf(splitEndpoint[2]))); + statusEndPoints.add(new StatusEndPoint(splitEndpoint[0], splitEndpoint[1], Integer.parseInt(splitEndpoint[2]))); } } StatusEndPoint endpoint; @@ -166,7 +161,7 @@ public static int getTimeout() { try { return Integer.parseInt(Config.getProperty(Config.Constants.TIMEOUT)); } catch (NumberFormatException e) { - LOGGER.error("Error parsing timeout", e); + LOGGER.trace("Error parsing timeout, using default timeout", e); } return 5000; } @@ -355,7 +350,7 @@ public static final class Constants { public static final String MAX_SHOW_REQUESTS_PER_USER = "max-show-requests-per-user"; /** - * The max of artist requests per user per configured threshold + * The max amount of artist requests per user per configured threshold */ public static final String MAX_ARTIST_REQUESTS_PER_USER = "max-artist-requests-per-user"; @@ -400,6 +395,6 @@ public static final class Constants { private final boolean isRaddarrEnabled; private final boolean isSonarrEnabled; private final boolean isLidarrEnabled; - private ChatClientType chatClientType = null; + private ChatClientBootstrap chatClientBootstrap = null; private static final Logger LOGGER = LogManager.getLogger(); } \ No newline at end of file diff --git a/src/main/java/com/botdarr/api/AddStrategy.java b/src/main/java/com/botdarr/api/AddStrategy.java index ce563a2..04b4657 100644 --- a/src/main/java/com/botdarr/api/AddStrategy.java +++ b/src/main/java/com/botdarr/api/AddStrategy.java @@ -1,18 +1,18 @@ package com.botdarr.api; -import com.botdarr.clients.ChatClientResponse; -import com.botdarr.clients.ChatClientResponseBuilder; +import com.botdarr.commands.responses.CommandResponse; +import com.botdarr.commands.responses.ErrorResponse; +import com.botdarr.commands.responses.InfoResponse; import com.botdarr.utilities.ListUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.List; public abstract class AddStrategy { - public AddStrategy(ChatClientResponseBuilder chatClientResponseBuilder, ContentType contentType) { - this.chatClientResponseBuilder = chatClientResponseBuilder; + public AddStrategy(ContentType contentType) { this.contentDisplayName = contentType.getDisplayName(); } @@ -20,10 +20,10 @@ public AddStrategy(ChatClientResponseBuilder chatC public abstract List lookupItemById(String id) throws Exception; public abstract boolean doesItemExist(T content); public abstract String getItemId(T item); - public abstract ChatClientResponse addContent(T content); - public abstract ChatClientResponse getResponse(T item); + public abstract CommandResponse addContent(T content); + public abstract CommandResponse getResponse(T item); - public ChatClientResponse addWithSearchId(String searchText, String id) { + public CommandResponse addWithSearchId(String searchText, String id) { try { List items = lookupContent(searchText); if (items.isEmpty()) { @@ -32,39 +32,38 @@ public ChatClientResponse addWithSearchId(String searchText, String id) { } if (items.isEmpty()) { LOGGER.warn("Search id " + id + "yielded no " + this.contentDisplayName + "s, stopping"); - return chatClientResponseBuilder.createErrorMessage("No " + this.contentDisplayName + "s found"); + return new ErrorResponse("No " + this.contentDisplayName + "s found"); } for (T item : items) { if (getItemId(item).equalsIgnoreCase(id)) { if (doesItemExist(item)) { - return chatClientResponseBuilder.createErrorMessage(this.contentDisplayName + " already exists"); + return new ErrorResponse(this.contentDisplayName + " already exists"); } - ChatClientResponse chatClientResponse = addContent(item); - return chatClientResponse; + return addContent(item); } } - return chatClientResponseBuilder.createErrorMessage("Could not find " + contentDisplayName + " with search text=" + searchText + " and id=" + id); + return new ErrorResponse("Could not find " + contentDisplayName + " with search text=" + searchText + " and id=" + id); } catch (Throwable e) { LOGGER.error("Error trying to add " + contentDisplayName, e); - return chatClientResponseBuilder.createErrorMessage("Error adding content, e=" + e.getMessage()); + return new ErrorResponse("Error adding content, e=" + e.getMessage()); } } - public List addWithSearchTitle(String searchText) { + public List addWithSearchTitle(String searchText) { try { List items = lookupContent(searchText); if (items.size() == 0) { - return Arrays.asList(chatClientResponseBuilder.createInfoMessage("No " + contentDisplayName + "s found")); + return Collections.singletonList(new InfoResponse("No " + contentDisplayName + "s found")); } if (items.size() == 1) { T item = items.get(0); if (doesItemExist(item)) { - return Arrays.asList(chatClientResponseBuilder.createErrorMessage(contentDisplayName + " already exists")); + return Collections.singletonList(new ErrorResponse(contentDisplayName + " already exists")); } - return Arrays.asList(addContent(items.get(0))); + return Collections.singletonList(addContent(items.get(0))); } - List restOfItems = new ArrayList<>(); + List restOfItems = new ArrayList<>(); for (T item : items) { if (doesItemExist(item)) { //skip existing items @@ -74,19 +73,18 @@ public List addWithSearchTitle(String searchText) { } if (restOfItems.size() > 1) { restOfItems = ListUtils.subList(restOfItems, MAX_RESULTS_TO_SHOW); - restOfItems.add(0, chatClientResponseBuilder.createInfoMessage("Too many " + contentDisplayName + "s found, please narrow search or increase max results to show")); + restOfItems.add(0, new InfoResponse("Too many " + contentDisplayName + "s found, please narrow search or increase max results to show")); } if (restOfItems.size() == 0) { - return Arrays.asList(chatClientResponseBuilder.createInfoMessage("No new " + contentDisplayName + "s found, check existing " + contentDisplayName + "s")); + return Collections.singletonList(new InfoResponse("No new " + contentDisplayName + "s found, check existing " + contentDisplayName + "s")); } return restOfItems; } catch (Throwable e) { LOGGER.error("Error trying to add " + contentDisplayName, e); - return Arrays.asList(chatClientResponseBuilder.createErrorMessage("Error trying to add " + contentDisplayName + ", for search text=" + searchText + ", e=" + e.getMessage())); + return Collections.singletonList(new ErrorResponse("Error trying to add " + contentDisplayName + ", for search text=" + searchText + ", e=" + e.getMessage())); } } - private final ChatClientResponseBuilder chatClientResponseBuilder; private final String contentDisplayName; private static Logger LOGGER = LogManager.getLogger(); private final int MAX_RESULTS_TO_SHOW = new ApiRequests().getMaxResultsToShow(); diff --git a/src/main/java/com/botdarr/api/Api.java b/src/main/java/com/botdarr/api/Api.java index 436f478..3103978 100644 --- a/src/main/java/com/botdarr/api/Api.java +++ b/src/main/java/com/botdarr/api/Api.java @@ -4,6 +4,8 @@ import com.botdarr.clients.ChatClient; import com.botdarr.clients.ChatClientResponse; import com.botdarr.clients.ChatClientResponseBuilder; +import com.botdarr.clients.discord.DiscordResponse; +import com.botdarr.commands.responses.CommandResponse; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.util.Strings; @@ -26,12 +28,7 @@ public interface Api { /** * Gets all the in-progress downloads */ - List downloads(); - - /** - * Notifications that are sent every 10 minutes - */ - void sendPeriodicNotifications(ChatClient chatClient); + List downloads(); /** * Data cached from jda directly in the api diff --git a/src/main/java/com/botdarr/api/ApiRequestType.java b/src/main/java/com/botdarr/api/ApiRequestType.java index 22b0d9b..672358a 100644 --- a/src/main/java/com/botdarr/api/ApiRequestType.java +++ b/src/main/java/com/botdarr/api/ApiRequestType.java @@ -10,7 +10,7 @@ public enum ApiRequestType { SHOW(Config.Constants.MAX_SHOW_REQUESTS_PER_USER), ARTIST(Config.Constants.MAX_ARTIST_REQUESTS_PER_USER); - private ApiRequestType(String configProperty) { + ApiRequestType(String configProperty) { this.maxRequestsPerUserProperty = configProperty; } @@ -29,7 +29,7 @@ public boolean isConfigured() { } public int getMaxRequestsAllowed() { - return Integer.valueOf(Config.getProperty(maxRequestsPerUserProperty)); + return Integer.parseInt(Config.getProperty(maxRequestsPerUserProperty)); } private final String maxRequestsPerUserProperty; diff --git a/src/main/java/com/botdarr/api/ApiRequests.java b/src/main/java/com/botdarr/api/ApiRequests.java index 7ed93e2..061175f 100644 --- a/src/main/java/com/botdarr/api/ApiRequests.java +++ b/src/main/java/com/botdarr/api/ApiRequests.java @@ -17,7 +17,7 @@ public int getMaxDownloadsToShow() { String maxDownloadsToShow = Config.getProperty(Config.Constants.MAX_DOWNLOADS_TO_SHOW); if (!Strings.isEmpty(maxDownloadsToShow)) { try { - return Integer.valueOf(maxDownloadsToShow); + return Integer.parseInt(maxDownloadsToShow); } catch (NumberFormatException e) { LOGGER.error("Invalid max downloads to show configuration", e); } @@ -29,7 +29,7 @@ public int getMaxResultsToShow() { String maxResultsToShow = Config.getProperty(Config.Constants.MAX_RESULTS_TO_SHOW); if (!Strings.isEmpty(maxResultsToShow)) { try { - return Integer.valueOf(maxResultsToShow); + return Integer.parseInt(maxResultsToShow); } catch (NumberFormatException e) { LOGGER.error("Invalid max results to show configuration", e); } @@ -48,8 +48,7 @@ public boolean checkRequestLimits(ApiRequestType requestType) { try { ApiRequestThreshold.valueOf(maxRequestsThreshold); } catch (Exception e) { - String allRequestThresholds = Arrays.asList(ApiRequestThreshold.values()) - .stream() + String allRequestThresholds = Arrays.stream(ApiRequestThreshold.values()) .sorted(Comparator.comparing(ApiRequestThreshold::getReadableName)) .map(ApiRequestThreshold::getReadableName) .collect(Collectors.joining(", ")); diff --git a/src/main/java/com/botdarr/api/DownloadsStrategy.java b/src/main/java/com/botdarr/api/DownloadsStrategy.java index c49586f..9f3ff83 100644 --- a/src/main/java/com/botdarr/api/DownloadsStrategy.java +++ b/src/main/java/com/botdarr/api/DownloadsStrategy.java @@ -1,7 +1,7 @@ package com.botdarr.api; -import com.botdarr.clients.ChatClientResponse; -import com.botdarr.clients.ChatClientResponseBuilder; +import com.botdarr.commands.responses.CommandResponse; +import com.botdarr.commands.responses.InfoResponse; import com.botdarr.connections.ConnectionHelper; import com.botdarr.utilities.ListUtils; import com.google.gson.JsonArray; @@ -15,54 +15,52 @@ import java.util.Collections; import java.util.List; -public abstract class DownloadsStrategy { +public abstract class DownloadsStrategy { public DownloadsStrategy(Api api, String url, - ChatClientResponseBuilder chatClientResponseBuilder, ContentType contentType) { this.api = api; this.url = url; - this.chatClientResponseBuilder = chatClientResponseBuilder; this.contentType = contentType; } - public abstract ChatClientResponse getResponse(JsonElement rawElement); + public abstract CommandResponse getResponse(JsonElement rawElement); - public List downloads() { + public List downloads() { if (MAX_DOWNLOADS_TO_SHOW <= 0) { return Collections.emptyList(); } - List chatClientResponses = getContentDownloads(); + List chatClientResponses = getContentDownloads(); if (chatClientResponses.isEmpty()) { - chatClientResponses.add(chatClientResponseBuilder.createInfoMessage("No " + this.contentType.getDisplayName() + "s downloading")); + chatClientResponses.add(new InfoResponse("No " + this.contentType.getDisplayName() + "s downloading")); } return chatClientResponses; } - public List getContentDownloads() { - return ConnectionHelper.makeGetRequest(this.api, this.url, new ConnectionHelper.SimpleMessageEmbedResponseHandler(chatClientResponseBuilder) { + public List getContentDownloads() { + return ConnectionHelper.makeGetRequest(this.api, this.url, new ConnectionHelper.SimpleMessageEmbedResponseHandler() { @Override - public List onConnectException(HttpHostConnectException e) { + public List onConnectException(HttpHostConnectException e) { String message = "Error trying to connect to " + DownloadsStrategy.this.api.getApiUrl(DownloadsStrategy.this.url); LOGGER.error(message); return Collections.emptyList(); } @Override - public List onSuccess(String response) { + public List onSuccess(String response) { return parseContent(response); } }); } - public List parseContent(String response) { - List chatClientResponses = new ArrayList<>(); + public List parseContent(String response) { + List chatClientResponses = new ArrayList<>(); JsonParser parser = new JsonParser(); JsonArray json = parser.parse(response).getAsJsonArray(); boolean tooManyDownloads = json.size() >= MAX_DOWNLOADS_TO_SHOW; for (int i = 0; i < json.size(); i++) { - ChatClientResponse chatClientResponse = getResponse(json.get(i)); + CommandResponse chatClientResponse = getResponse(json.get(i)); if (chatClientResponse == null) { continue; } @@ -70,14 +68,13 @@ public List parseContent(String response) { } if (tooManyDownloads && !chatClientResponses.isEmpty()) { chatClientResponses = ListUtils.subList(chatClientResponses, MAX_DOWNLOADS_TO_SHOW); - chatClientResponses.add(0, chatClientResponseBuilder.createInfoMessage("Too many downloads, limiting results to " + MAX_DOWNLOADS_TO_SHOW)); + chatClientResponses.add(0, new InfoResponse("Too many downloads, limiting results to " + MAX_DOWNLOADS_TO_SHOW)); } return chatClientResponses; } private final Api api; private final String url; - private final ChatClientResponseBuilder chatClientResponseBuilder; private final int MAX_DOWNLOADS_TO_SHOW = new ApiRequests().getMaxDownloadsToShow(); private final ContentType contentType; private static Logger LOGGER = LogManager.getLogger(); diff --git a/src/main/java/com/botdarr/api/LookupStrategy.java b/src/main/java/com/botdarr/api/LookupStrategy.java index eb69eab..3c54b7d 100644 --- a/src/main/java/com/botdarr/api/LookupStrategy.java +++ b/src/main/java/com/botdarr/api/LookupStrategy.java @@ -1,32 +1,33 @@ package com.botdarr.api; -import com.botdarr.clients.ChatClientResponse; -import com.botdarr.clients.ChatClientResponseBuilder; +import com.botdarr.commands.responses.CommandResponse; +import com.botdarr.commands.responses.ErrorResponse; +import com.botdarr.commands.responses.InfoResponse; import com.botdarr.utilities.ListUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.List; public abstract class LookupStrategy { - public LookupStrategy(ChatClientResponseBuilder chatClientResponseBuilder, ContentType contentType) { - this.chatClientResponseBuilder = chatClientResponseBuilder; + public LookupStrategy(ContentType contentType) { this.contentType = contentType; } public abstract T lookupExistingItem(T lookupItem); public abstract List lookup(String searchTerm) throws Exception; - public abstract ChatClientResponse getNewOrExistingItem(T lookupItem, T existingItem, boolean findNew); + public abstract CommandResponse getExistingItem(T existingItem); + public abstract CommandResponse getNewItem(T lookupItem); public abstract boolean isPathBlacklisted(T item); - public List lookup(String search, boolean findNew) { + public List lookup(String search, boolean findNew) { try { - List responses = new ArrayList<>(); + List responses = new ArrayList<>(); List lookupItems = lookup(search); if (lookupItems == null) { - return Arrays.asList(chatClientResponseBuilder.createErrorMessage("Something failed during lookup for search term=" + search)); + return Collections.singletonList(new ErrorResponse("Something failed during lookup for search term=" + search)); } for (T lookupItem : lookupItems) { T existingItem = lookupExistingItem(lookupItem); @@ -35,27 +36,26 @@ public List lookup(String search, boolean findNew) { //skip any items that have blacklisted paths continue; } - boolean skip = findNew ? isExistingItem : !isExistingItem; + boolean skip = findNew == isExistingItem; if (skip) { continue; } - responses.add(getNewOrExistingItem(lookupItem, existingItem, findNew)); + responses.add(isExistingItem ? getExistingItem(existingItem) : getNewItem(lookupItem)); } if (responses.size() == 0) { - return Arrays.asList(chatClientResponseBuilder.createErrorMessage("Could not find any " + (findNew ? "new" : "existing") + " " + this.contentType.getDisplayName() + "s for search term=" + search)); + return Collections.singletonList(new ErrorResponse("Could not find any " + (findNew ? "new" : "existing") + " " + this.contentType.getDisplayName() + "s for search term=" + search)); } if (responses.size() > MAX_RESULTS_TO_SHOW) { responses = ListUtils.subList(responses, MAX_RESULTS_TO_SHOW); - responses.add(0, chatClientResponseBuilder.createInfoMessage("Too many " + this.contentType.getDisplayName() + "s found, limiting results to " + MAX_RESULTS_TO_SHOW)); + responses.add(0, new InfoResponse("Too many " + this.contentType.getDisplayName() + "s found, limiting results to " + MAX_RESULTS_TO_SHOW)); } return responses; } catch (Exception e) { LOGGER.error("Error trying to lookup " + this.contentType.getDisplayName() + ", searchText=" + search, e); - return Arrays.asList(chatClientResponseBuilder.createErrorMessage("Error looking up " + this.contentType.getDisplayName() + ", e=" + e.getMessage())); + return Collections.singletonList(new ErrorResponse("Error looking up " + this.contentType.getDisplayName() + ", e=" + e.getMessage())); } } - private final ChatClientResponseBuilder chatClientResponseBuilder; private static Logger LOGGER = LogManager.getLogger(); private final int MAX_RESULTS_TO_SHOW = new ApiRequests().getMaxResultsToShow(); private final ContentType contentType; diff --git a/src/main/java/com/botdarr/api/PeriodicNotificationStrategy.java b/src/main/java/com/botdarr/api/PeriodicNotificationStrategy.java deleted file mode 100644 index cfc97e8..0000000 --- a/src/main/java/com/botdarr/api/PeriodicNotificationStrategy.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.botdarr.api; - -import com.botdarr.clients.ChatClientResponse; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.List; - -public abstract class PeriodicNotificationStrategy { - public PeriodicNotificationStrategy(ContentType contentType, DownloadsStrategy downloadsStrategy) { - this.contentType = contentType; - this.downloadsStrategy = downloadsStrategy; - } - - public abstract void sendToConfiguredChannels(List downloads); - - public void sendPeriodicNotifications() { - if (MAX_DOWNLOADS_TO_SHOW <= 0) { - LOGGER.debug("Bot configured to show no downloads"); - return; - } - List downloads = downloadsStrategy.getContentDownloads(); - if (downloads != null && !downloads.isEmpty()) { - sendToConfiguredChannels(downloads); - } else { - LOGGER.debug("No " + this.contentType + " downloads available for sending"); - } - } - - private final DownloadsStrategy downloadsStrategy; - private final ContentType contentType; - private final int MAX_DOWNLOADS_TO_SHOW = new ApiRequests().getMaxDownloadsToShow(); - private static final Logger LOGGER = LogManager.getLogger(); -} diff --git a/src/main/java/com/botdarr/api/lidarr/LidarrApi.java b/src/main/java/com/botdarr/api/lidarr/LidarrApi.java index 9d549ca..376f115 100644 --- a/src/main/java/com/botdarr/api/lidarr/LidarrApi.java +++ b/src/main/java/com/botdarr/api/lidarr/LidarrApi.java @@ -3,10 +3,8 @@ import com.botdarr.Config; import com.botdarr.api.*; import com.botdarr.api.sonarr.SonarrUrls; -import com.botdarr.clients.ChatClient; -import com.botdarr.clients.ChatClientResponse; -import com.botdarr.clients.ChatClientResponseBuilder; import com.botdarr.commands.CommandContext; +import com.botdarr.commands.responses.*; import com.botdarr.connections.ConnectionHelper; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.ObjectMapper; @@ -26,10 +24,6 @@ import java.util.List; public class LidarrApi implements Api { - public LidarrApi(ChatClientResponseBuilder chatClientResponseBuilder) { - this.chatClientResponseBuilder = chatClientResponseBuilder; - } - @Override public String getUrlBase() { return Config.getProperty(Config.Constants.LIDARR_URL_BASE); @@ -41,20 +35,10 @@ public String getApiUrl(String path) { } @Override - public List downloads() { + public List downloads() { return getDownloadsStrategy().downloads(); } - @Override - public void sendPeriodicNotifications(ChatClient chatClient) { - new PeriodicNotificationStrategy(ContentType.ARTIST, getDownloadsStrategy()) { - @Override - public void sendToConfiguredChannels(List downloads) { - chatClient.sendToConfiguredChannels(downloads); - } - }.sendPeriodicNotifications(); - } - @Override public void cacheData() { new CacheProfileStrategy() { @@ -140,16 +124,16 @@ public String getApiToken() { return Config.Constants.LIDARR_TOKEN; } - public ChatClientResponse addArtistWithId(String id, String artistName) { + public CommandResponse addArtistWithId(String id, String artistName) { return getArtistAddStrategy().addWithSearchId(artistName, id); } - public List addArtist(String artistToSearch) { + public List addArtist(String artistToSearch) { return getArtistAddStrategy().addWithSearchTitle(artistToSearch); } - public List lookupArtists(String search, boolean findNew) { - return new LookupStrategy(chatClientResponseBuilder, ContentType.ARTIST) { + public List lookupArtists(String search, boolean findNew) { + return new LookupStrategy(ContentType.ARTIST) { @Override public LidarrArtist lookupExistingItem(LidarrArtist lookupItem) { @@ -162,8 +146,13 @@ public List lookup(String searchTerm) throws Exception { } @Override - public ChatClientResponse getNewOrExistingItem(LidarrArtist lookupItem, LidarrArtist existingItem, boolean findNew) { - return chatClientResponseBuilder.getNewOrExistingArtist(lookupItem, existingItem, findNew); + public CommandResponse getExistingItem(LidarrArtist existingItem) { + return new ExistingMusicArtistResponse(existingItem); + } + + @Override + public CommandResponse getNewItem(LidarrArtist lookupItem) { + return new NewMusicArtistResponse(lookupItem); } @Override @@ -179,7 +168,7 @@ public boolean isPathBlacklisted(LidarrArtist item) { } private AddStrategy getArtistAddStrategy() { - return new AddStrategy(chatClientResponseBuilder, ContentType.ARTIST) { + return new AddStrategy(ContentType.ARTIST) { @Override public List lookupContent(String search) throws Exception { return lookupArtists(search); @@ -202,30 +191,29 @@ public String getItemId(LidarrArtist item) { } @Override - public ChatClientResponse addContent(LidarrArtist content) { + public CommandResponse addContent(LidarrArtist content) { return addArtist(content); } @Override - public ChatClientResponse getResponse(LidarrArtist item) { - return chatClientResponseBuilder.getArtistResponse(item); + public CommandResponse getResponse(LidarrArtist item) { + return new MusicArtistResponse(item); } }; } private DownloadsStrategy getDownloadsStrategy() { - return new DownloadsStrategy(this, LidarrUrls.DOWNLOAD_BASE, chatClientResponseBuilder, ContentType.ARTIST) { + return new DownloadsStrategy(this, LidarrUrls.DOWNLOAD_BASE, ContentType.ARTIST) { @Override - public ChatClientResponse getResponse(JsonElement rawElement) { + public CommandResponse getResponse(JsonElement rawElement) { LidarrQueueRecord lidarrQueueRecord = new Gson().fromJson(rawElement, LidarrQueueRecord.class); - Integer artistId = lidarrQueueRecord.getArtistId(); - return chatClientResponseBuilder.getArtistDownloadResponses(lidarrQueueRecord); + return new MusicArtistDownloadResponse(lidarrQueueRecord); } @Override - public List getContentDownloads() { - return ConnectionHelper.makeGetRequest(LidarrApi.this, LidarrUrls.DOWNLOAD_BASE, new ConnectionHelper.SimpleMessageEmbedResponseHandler(chatClientResponseBuilder) { + public List getContentDownloads() { + return ConnectionHelper.makeGetRequest(LidarrApi.this, LidarrUrls.DOWNLOAD_BASE, new ConnectionHelper.SimpleMessageEmbedResponseHandler() { @Override - public List onSuccess(String response) { + public List onSuccess(String response) { JsonParser parser = new JsonParser(); JsonObject json = parser.parse(response).getAsJsonObject(); return parseContent(json.get("records").toString()); @@ -252,20 +240,20 @@ public List onSuccess(String response) { ); } - private ChatClientResponse addArtist(LidarrArtist lidarrArtist) { + private CommandResponse addArtist(LidarrArtist lidarrArtist) { lidarrArtist.setMonitored(true); lidarrArtist.setRootFolderPath(Config.getProperty(Config.Constants.LIDARR_PATH) + "/"); String lidarrProfileName = Config.getProperty(Config.Constants.LIDARR_DEFAULT_QUALITY_PROFILE); LidarrQualityProfile lidarrQualityProfile = LIDARR_CACHE.getQualityProfile(lidarrProfileName.toLowerCase()); if (lidarrQualityProfile == null) { - return chatClientResponseBuilder.createErrorMessage("Could not find lidarr profile for default " + lidarrProfileName); + return new ErrorResponse("Could not find lidarr profile for default " + lidarrProfileName); } String lidarrMetadataProfileName = Config.getProperty(Config.Constants.LIDARR_DEFAULT_METADATA_PROFILE); LidarrMetadataProfile lidarrMetadataProfile = LIDARR_CACHE.getMetadataProfile(lidarrMetadataProfileName.toLowerCase()); if (lidarrMetadataProfile == null) { - return chatClientResponseBuilder.createErrorMessage("Could not find lidarr metadata profile for default " + lidarrProfileName); + return new ErrorResponse("Could not find lidarr metadata profile for default " + lidarrProfileName); } lidarrArtist.setMetadataProfileId(lidarrMetadataProfile.getId()); lidarrArtist.setQualityProfileId(lidarrQualityProfile.getId()); @@ -290,7 +278,7 @@ private ChatClientResponse addArtist(LidarrArtist lidarrArtist) { ApiRequestType apiRequestType = ApiRequestType.ARTIST; if (apiRequests.checkRequestLimits(apiRequestType) && !apiRequests.canMakeRequests(apiRequestType, username)) { ApiRequestThreshold requestThreshold = ApiRequestThreshold.valueOf(Config.getProperty(Config.Constants.MAX_REQUESTS_THRESHOLD)); - return chatClientResponseBuilder.createErrorMessage("Could not add artist, user " + username + " has exceeded max artist requests for " + requestThreshold.getReadableName()); + return new ErrorResponse("Could not add artist, user " + username + " has exceeded max artist requests for " + requestThreshold.getReadableName()); } try (CloseableHttpResponse response = client.execute(post)) { if (LOGGER.isDebugEnabled()) { @@ -300,21 +288,20 @@ private ChatClientResponse addArtist(LidarrArtist lidarrArtist) { } int statusCode = response.getStatusLine().getStatusCode(); if (statusCode != 200 && statusCode != 201) { - return chatClientResponseBuilder.createErrorMessage("Could not add artist, status-code=" + statusCode + ", reason=" + response.getStatusLine().getReasonPhrase()); + return new ErrorResponse("Could not add artist, status-code=" + statusCode + ", reason=" + response.getStatusLine().getReasonPhrase()); } //cache artist after successful response LIDARR_CACHE.addArtist(lidarrArtist); LogManager.getLogger("AuditLog").info("User " + username + " added " + lidarrArtist.getArtistName()); apiRequests.auditRequest(apiRequestType, username, lidarrArtist.getArtistName()); - return chatClientResponseBuilder.createSuccessMessage("Artist " + lidarrArtist.getArtistName() + " added, lidarr-detail=" + response.getStatusLine().getReasonPhrase()); + return new SuccessResponse("Artist " + lidarrArtist.getArtistName() + " added, lidarr-detail=" + response.getStatusLine().getReasonPhrase()); } } catch (IOException e) { LOGGER.error("Error trying to add artist", e); - return chatClientResponseBuilder.createErrorMessage("Error adding artist, error=" + e.getMessage()); + return new ErrorResponse("Error adding artist, error=" + e.getMessage()); } } - private final ChatClientResponseBuilder chatClientResponseBuilder; private static final LidarrCache LIDARR_CACHE = new LidarrCache(); public static final String ADD_ARTIST_COMMAND_FIELD_PREFIX = "Add artist command"; } diff --git a/src/main/java/com/botdarr/commands/LidarrCommands.java b/src/main/java/com/botdarr/api/lidarr/LidarrCommands.java similarity index 71% rename from src/main/java/com/botdarr/commands/LidarrCommands.java rename to src/main/java/com/botdarr/api/lidarr/LidarrCommands.java index 74abfdb..fa2194b 100644 --- a/src/main/java/com/botdarr/commands/LidarrCommands.java +++ b/src/main/java/com/botdarr/api/lidarr/LidarrCommands.java @@ -1,9 +1,13 @@ -package com.botdarr.commands; +package com.botdarr.api.lidarr; import com.botdarr.api.lidarr.LidarrApi; -import com.botdarr.clients.ChatClientResponse; +import com.botdarr.commands.BaseCommand; +import com.botdarr.commands.Command; +import com.botdarr.commands.CommandProcessor; +import com.botdarr.commands.responses.CommandResponse; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class LidarrCommands { @@ -12,36 +16,36 @@ public static List getCommands(LidarrApi lidarrApi) { add(new BaseCommand("music artist add", "music artist add ", "Adds an artist using search text (i.e., music add Dre Fudgington)") { @Override - public CommandResponse execute(String artistToSearch) { - return new CommandResponse<>(lidarrApi.addArtist(artistToSearch)); + public List execute(String artistToSearch) { + return lidarrApi.addArtist(artistToSearch); } }); add(new BaseCommand("music artist id add", "music artist id add ", "Adds an artist using lidarr artist id and artist name (i.e., music artist id add F894MN4-F84J4 Beastie Girls). The easiest" + " way to use this command is using the find commands to find new artists, which have the add commands or you can use thumbs reaction (in slack/discord)") { @Override - public CommandResponse execute(String command) { + public List execute(String command) { int lastSpace = command.lastIndexOf(" "); if (lastSpace == -1) { throw new RuntimeException("Missing expected arguments - usage: music artist id add ARTIST_NAME_HERE ARTIST_ID_HERE"); } String searchText = command.substring(0, lastSpace); String id = command.substring(lastSpace + 1); - return new CommandResponse<>(lidarrApi.addArtistWithId(id, searchText)); + return Collections.singletonList(lidarrApi.addArtistWithId(id, searchText)); } }); add(new BaseCommand("music artist find existing", "music artist find existing ", "Finds an existing artist using lidarr (i.e., music artist find existing ArtistA)") { @Override - public CommandResponse execute(String command) { - return new CommandResponse<>(lidarrApi.lookupArtists(command, false)); + public List execute(String command) { + return lidarrApi.lookupArtists(command, false); } }); add(new BaseCommand("music artist find new", "music artist find new ", "Finds a new artist using lidarr (i.e., music find new artist ArtistB)") { @Override - public CommandResponse execute(String command) { - return new CommandResponse<>(lidarrApi.lookupArtists(command, true)); + public List execute(String command) { + return lidarrApi.lookupArtists(command, true); } }); add(new BaseCommand("music downloads", "Shows all the active artist downloading in lidarr") { @@ -51,8 +55,8 @@ public boolean hasArguments() { } @Override - public CommandResponse execute(String command) { - return new CommandResponse<>(lidarrApi.downloads()); + public List execute(String command) { + return lidarrApi.downloads(); } }); }}; diff --git a/src/main/java/com/botdarr/api/radarr/RadarrApi.java b/src/main/java/com/botdarr/api/radarr/RadarrApi.java index ab6c711..80e3cf1 100644 --- a/src/main/java/com/botdarr/api/radarr/RadarrApi.java +++ b/src/main/java/com/botdarr/api/radarr/RadarrApi.java @@ -2,10 +2,8 @@ import com.botdarr.Config; import com.botdarr.api.*; -import com.botdarr.clients.ChatClientResponseBuilder; import com.botdarr.commands.CommandContext; -import com.botdarr.clients.ChatClient; -import com.botdarr.clients.ChatClientResponse; +import com.botdarr.commands.responses.*; import com.botdarr.connections.ConnectionHelper; import com.google.gson.*; import org.apache.commons.io.IOUtils; @@ -22,10 +20,6 @@ import java.util.*; public class RadarrApi implements Api { - public RadarrApi(ChatClientResponseBuilder chatClientResponseBuilder) { - this.chatClientResponseBuilder = chatClientResponseBuilder; - } - @Override public String getUrlBase() { return Config.getProperty(Config.Constants.RADARR_URL_BASE); @@ -36,8 +30,8 @@ public String getApiUrl(String path) { return getApiUrl(Config.Constants.RADARR_URL, Config.Constants.RADARR_TOKEN, "v3/" + path); } - public List lookup(String search, boolean findNew) { - return new LookupStrategy(chatClientResponseBuilder, ContentType.MOVIE) { + public List lookup(String search, boolean findNew) { + return new LookupStrategy(ContentType.MOVIE) { @Override public RadarrMovie lookupExistingItem(RadarrMovie lookupItem) { @@ -50,8 +44,13 @@ public List lookup(String searchTerm) throws Exception { } @Override - public ChatClientResponse getNewOrExistingItem(RadarrMovie lookupItem, RadarrMovie existingItem, boolean findNew) { - return chatClientResponseBuilder.getNewOrExistingMovie(lookupItem, existingItem, findNew); + public CommandResponse getExistingItem(RadarrMovie existingItem) { + return new ExistingMovieResponse(existingItem); + } + + @Override + public CommandResponse getNewItem(RadarrMovie lookupItem) { + return new NewMovieResponse(lookupItem); } @Override @@ -62,41 +61,31 @@ public boolean isPathBlacklisted(RadarrMovie item) { } @Override - public List downloads() { + public List downloads() { return getDownloadsStrategy().downloads(); } - public List addWithTitle(String searchText) { + public List addWithTitle(String searchText) { return getAddStrategy().addWithSearchTitle(searchText); } - public ChatClientResponse addWithId(String searchText, String tmdbId) { + public CommandResponse addWithId(String searchText, String tmdbId) { return getAddStrategy().addWithSearchId(searchText, tmdbId); } - public List getProfiles() { + public List getProfiles() { Collection profiles = RADARR_CACHE.getQualityProfiles(); if (profiles == null || profiles.isEmpty()) { - return Arrays.asList(chatClientResponseBuilder.createErrorMessage("Found 0 profiles, please setup Radarr with at least one profile")); + return Collections.singletonList(new ErrorResponse("Found 0 profiles, please setup Radarr with at least one profile")); } - List profileMessages = new ArrayList<>(); + List profileMessages = new ArrayList<>(); for (RadarrProfile radarrProfile : profiles) { - profileMessages.add(chatClientResponseBuilder.getMovieProfile(radarrProfile)); + profileMessages.add(new MovieProfileResponse(radarrProfile)); } return profileMessages; } - @Override - public void sendPeriodicNotifications(ChatClient chatClient) { - new PeriodicNotificationStrategy(ContentType.MOVIE, getDownloadsStrategy()) { - @Override - public void sendToConfiguredChannels(List downloads) { - chatClient.sendToConfiguredChannels(downloads); - } - }.sendPeriodicNotifications(); - } - @Override public void cacheData() { new CacheProfileStrategy() { @@ -148,11 +137,11 @@ public String getApiToken() { return Config.Constants.RADARR_TOKEN; } - public List discover() { - return ConnectionHelper.makeGetRequest(this, RadarrUrls.DISCOVER_MOVIES, "&includeRecommendations=true", new ConnectionHelper.SimpleEntityResponseHandler>() { + public List discover() { + return ConnectionHelper.makeGetRequest(this, RadarrUrls.DISCOVER_MOVIES, "&includeRecommendations=true", new ConnectionHelper.SimpleEntityResponseHandler>() { @Override - public List onSuccess(String response) throws Exception { - List recommendedMovies = new ArrayList<>(); + public List onSuccess(String response) throws Exception { + List recommendedMovies = new ArrayList<>(); if (response == null || response.isEmpty() || response.equalsIgnoreCase("[]")) { LOGGER.warn("Found no response when looking for movie recommendations"); return Collections.emptyList(); @@ -166,17 +155,17 @@ public List onSuccess(String response) throws Exception { break; } RadarrMovie radarrMovie = new Gson().fromJson(json.get(i), RadarrMovie.class); - recommendedMovies.add(chatClientResponseBuilder.getDiscoverableMovies(radarrMovie)); + recommendedMovies.add(new DiscoverMovieResponse(radarrMovie)); } return recommendedMovies; } }); } - private DownloadsStrategy getDownloadsStrategy() { - return new DownloadsStrategy(this, RadarrUrls.DOWNLOAD_BASE, chatClientResponseBuilder, ContentType.MOVIE) { + private DownloadsStrategy getDownloadsStrategy() { + return new DownloadsStrategy(this, RadarrUrls.DOWNLOAD_BASE, ContentType.MOVIE) { @Override - public ChatClientResponse getResponse(JsonElement rawElement) { + public CommandResponse getResponse(JsonElement rawElement) { RadarrQueue radarrQueue = new Gson().fromJson(rawElement, RadarrQueue.class); RadarrMovie radarrMovie = RADARR_CACHE.getExistingMovieWithRadarrId(radarrQueue.getMovieId()); if (radarrMovie == null) { @@ -191,17 +180,17 @@ public ChatClientResponse getResponse(JsonElement rawElement) { return null; } - return chatClientResponseBuilder.getMovieDownloadResponses(radarrQueue); + return new MovieDownloadResponse(radarrQueue); } @Override - public List getContentDownloads() { + public List getContentDownloads() { return ConnectionHelper.makeGetRequest( RadarrApi.this, RadarrUrls.DOWNLOAD_BASE, - new ConnectionHelper.SimpleMessageEmbedResponseHandler(chatClientResponseBuilder) { + new ConnectionHelper.SimpleMessageEmbedResponseHandler() { @Override - public List onSuccess(String response) { + public List onSuccess(String response) { if (response == null || response.isEmpty() || response.equals("{}")) { return new ArrayList<>(); } @@ -215,7 +204,7 @@ public List onSuccess(String response) { } private AddStrategy getAddStrategy() { - return new AddStrategy(chatClientResponseBuilder, ContentType.MOVIE) { + return new AddStrategy(ContentType.MOVIE) { @Override public List lookupContent(String search) throws Exception { return lookupMovies(search); @@ -237,18 +226,18 @@ public String getItemId(RadarrMovie item) { } @Override - public ChatClientResponse addContent(RadarrMovie content) { + public CommandResponse addContent(RadarrMovie content) { return addMovie(content); } @Override - public ChatClientResponse getResponse(RadarrMovie item) { - return chatClientResponseBuilder.getMovieResponse(item); + public CommandResponse getResponse(RadarrMovie item) { + return new MovieResponse(item); } }; } - private ChatClientResponse addMovie(RadarrMovie radarrMovie) { + private CommandResponse addMovie(RadarrMovie radarrMovie) { //make sure we specify where the movie should get downloaded radarrMovie.setRootFolderPath(Config.getProperty(Config.Constants.RADARR_PATH)); //make sure the movie is monitored @@ -257,7 +246,7 @@ private ChatClientResponse addMovie(RadarrMovie radarrMovie) { String radarrProfileName = Config.getProperty(Config.Constants.RADARR_DEFAULT_PROFILE); RadarrProfile radarrProfile = RADARR_CACHE.getProfile(radarrProfileName.toLowerCase()); if (radarrProfile == null) { - return chatClientResponseBuilder.createErrorMessage("Could not find radarr profile for default " + radarrProfileName); + return new ErrorResponse("Could not find radarr profile for default " + radarrProfileName); } radarrMovie.setQualityProfileId((int) radarrProfile.getId()); @@ -269,7 +258,7 @@ private ChatClientResponse addMovie(RadarrMovie radarrMovie) { post.setEntity(new StringEntity(json)); if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Client request=" + post.toString()); + LOGGER.debug("Client request=" + post); LOGGER.debug("Client data=" + (json)); } @@ -278,7 +267,7 @@ private ChatClientResponse addMovie(RadarrMovie radarrMovie) { ApiRequestType apiRequestType = ApiRequestType.MOVIE; if (apiRequests.checkRequestLimits(apiRequestType) && !apiRequests.canMakeRequests(apiRequestType, username)) { ApiRequestThreshold requestThreshold = ApiRequestThreshold.valueOf(Config.getProperty(Config.Constants.MAX_REQUESTS_THRESHOLD)); - return chatClientResponseBuilder.createErrorMessage("Could not add movie, user " + username + " has exceeded max movie requests for " + requestThreshold.getReadableName()); + return new ErrorResponse("Could not add movie, user " + username + " has exceeded max movie requests for " + requestThreshold.getReadableName()); } try (CloseableHttpResponse response = client.execute(post)) { if (LOGGER.isDebugEnabled()) { @@ -288,17 +277,17 @@ private ChatClientResponse addMovie(RadarrMovie radarrMovie) { } int statusCode = response.getStatusLine().getStatusCode(); if (statusCode != 200 && statusCode != 201) { - return chatClientResponseBuilder.createErrorMessage("Could not add movie, status-code=" + statusCode + ", reason=" + response.getStatusLine().getReasonPhrase()); + return new ErrorResponse("Could not add movie, status-code=" + statusCode + ", reason=" + response.getStatusLine().getReasonPhrase()); } //cache data after a successful request RADARR_CACHE.add(radarrMovie); LogManager.getLogger("AuditLog").info("User " + username + " added " + radarrMovie.getTitle()); apiRequests.auditRequest(apiRequestType, username, radarrMovie.getTitle()); - return chatClientResponseBuilder.createSuccessMessage("Movie " + radarrMovie.getTitle() + " added, radarr-detail=" + response.getStatusLine().getReasonPhrase()); + return new SuccessResponse("Movie " + radarrMovie.getTitle() + " added, radarr-detail=" + response.getStatusLine().getReasonPhrase()); } } catch (IOException e) { LOGGER.error("Error trying to add movie", e); - return chatClientResponseBuilder.createErrorMessage("Error adding movie, error=" + e.getMessage()); + return new ErrorResponse("Error adding movie, error=" + e.getMessage()); } } @@ -341,7 +330,6 @@ private boolean isPathBlacklisted(RadarrMovie item) { return false; } - private final ChatClientResponseBuilder chatClientResponseBuilder; - private static final RadarrCache RADARR_CACHE = new RadarrCache(); + private static RadarrCache RADARR_CACHE = new RadarrCache(); public static final String ADD_MOVIE_COMMAND_FIELD_PREFIX = "Add movie command"; } diff --git a/src/main/java/com/botdarr/commands/RadarrCommands.java b/src/main/java/com/botdarr/api/radarr/RadarrCommands.java similarity index 73% rename from src/main/java/com/botdarr/commands/RadarrCommands.java rename to src/main/java/com/botdarr/api/radarr/RadarrCommands.java index 13c5f25..907efff 100644 --- a/src/main/java/com/botdarr/commands/RadarrCommands.java +++ b/src/main/java/com/botdarr/api/radarr/RadarrCommands.java @@ -1,11 +1,13 @@ -package com.botdarr.commands; +package com.botdarr.api.radarr; -import com.botdarr.clients.ChatClientResponse; -import com.botdarr.api.radarr.RadarrApi; +import com.botdarr.commands.BaseCommand; +import com.botdarr.commands.Command; +import com.botdarr.commands.CommandProcessor; +import com.botdarr.commands.responses.CommandResponse; import org.apache.logging.log4j.util.Strings; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.List; public class RadarrCommands { @@ -18,14 +20,14 @@ public boolean hasArguments() { } @Override - public CommandResponse execute(String command) { - return new CommandResponse<>(radarrApi.discover()); + public List execute(String command) { + return radarrApi.discover(); } }); add(new BaseCommand("movie id add", "movie id add ", "Adds a movie using search text and tmdb id (i.e., movie id add John Wick 484737). The easiest" + " way to use this command is to use \"movie find new TITLE\", then the results will contain the movie add command for you") { @Override - public CommandResponse execute(String command) { + public List execute(String command) { int lastSpace = command.lastIndexOf(" "); if (lastSpace == -1) { throw new RuntimeException("Missing expected arguments - usage: movie id add MOVIE_TITLE_HERE MOVIE_ID_HERE"); @@ -34,15 +36,15 @@ public CommandResponse execute(String command) { String id = command.substring(lastSpace + 1); validateMovieTitle(searchText); validateMovieId(id); - return new CommandResponse(radarrApi.addWithId(searchText, id)); + return Collections.singletonList(radarrApi.addWithId(searchText, id)); } }); add(new BaseCommand("movie title add", "movie title add ", "Adds a movie with just a title. Since many movies can have same title or very similar titles, the trakt" + " search can return multiple movies, if we detect multiple new films, we will return those films, otherwise we will add the single film.") { @Override - public CommandResponse execute(String searchText) { + public List execute(String searchText) { validateMovieTitle(searchText); - return new CommandResponse(radarrApi.addWithTitle(searchText)); + return radarrApi.addWithTitle(searchText); } }); add(new BaseCommand("movie profiles", "Displays all the profiles available to search for movies under (i.e., movie title add MOVIE_TITLE_HERE)") { @@ -52,22 +54,22 @@ public boolean hasArguments() { } @Override - public CommandResponse execute(String command) { - return new CommandResponse(radarrApi.getProfiles()); + public List execute(String command) { + return radarrApi.getProfiles(); } }); add(new BaseCommand("movie find new", "movie find new ", "Finds a new movie using radarr (i.e., movie find new John Wick)") { @Override - public CommandResponse execute(String searchText) { + public List execute(String searchText) { validateMovieTitle(searchText); - return new CommandResponse(radarrApi.lookup(searchText, true)); + return radarrApi.lookup(searchText, true); } }); add(new BaseCommand("movie find existing", "movie find existing ", "Finds an existing movie using radarr (i.e., movie find existing Princess Fudgecake)") { @Override - public CommandResponse execute(String searchText) { + public List execute(String searchText) { validateMovieTitle(searchText); - return new CommandResponse(radarrApi.lookup(searchText, false)); + return radarrApi.lookup(searchText, false); } }); add(new BaseCommand("movie downloads", "Shows all the active movies downloading in radarr") { @@ -77,8 +79,8 @@ public boolean hasArguments() { } @Override - public CommandResponse execute(String command) { - return new CommandResponse(radarrApi.downloads()); + public List execute(String command) { + return radarrApi.downloads(); } }); }}; diff --git a/src/main/java/com/botdarr/api/radarr/RadarrQueue.java b/src/main/java/com/botdarr/api/radarr/RadarrQueue.java index 1b8aa07..c724ddf 100644 --- a/src/main/java/com/botdarr/api/radarr/RadarrQueue.java +++ b/src/main/java/com/botdarr/api/radarr/RadarrQueue.java @@ -33,6 +33,10 @@ public long getMovieId() { return movieId; } + public void setMovieId(long movieId) { + this.movieId = movieId; + } + public String getTitle() { return title; } diff --git a/src/main/java/com/botdarr/api/sonarr/SonarrApi.java b/src/main/java/com/botdarr/api/sonarr/SonarrApi.java index 14e5329..92309a8 100644 --- a/src/main/java/com/botdarr/api/sonarr/SonarrApi.java +++ b/src/main/java/com/botdarr/api/sonarr/SonarrApi.java @@ -2,11 +2,8 @@ import com.botdarr.Config; import com.botdarr.api.*; -import com.botdarr.api.radarr.RadarrMovie; -import com.botdarr.clients.ChatClient; -import com.botdarr.clients.ChatClientResponse; -import com.botdarr.clients.ChatClientResponseBuilder; import com.botdarr.commands.CommandContext; +import com.botdarr.commands.responses.*; import com.botdarr.connections.ConnectionHelper; import com.google.gson.*; import org.apache.http.client.methods.CloseableHttpResponse; @@ -21,10 +18,6 @@ import java.util.*; public class SonarrApi implements Api { - public SonarrApi(ChatClientResponseBuilder chatClientResponseBuilder) { - this.chatClientResponseBuilder = chatClientResponseBuilder; - } - @Override public String getUrlBase() { return Config.getProperty(Config.Constants.SONARR_URL_BASE); @@ -36,20 +29,20 @@ public String getApiUrl(String path) { } @Override - public List downloads() { + public List downloads() { return getDownloadsStrategy().downloads(); } - public ChatClientResponse addWithId(String searchText, String id) { + public CommandResponse addWithId(String searchText, String id) { return getAddStrategy().addWithSearchId(searchText, id); } - public List addWithTitle(String searchText) { + public List addWithTitle(String searchText) { return getAddStrategy().addWithSearchTitle(searchText); } - public List lookup(String search, boolean findNew) { - return new LookupStrategy(chatClientResponseBuilder, ContentType.SHOW) { + public List lookup(String search, boolean findNew) { + return new LookupStrategy(ContentType.SHOW) { @Override public SonarrShow lookupExistingItem(SonarrShow lookupItem) { @@ -62,8 +55,13 @@ public List lookup(String searchTerm) throws Exception { } @Override - public ChatClientResponse getNewOrExistingItem(SonarrShow lookupItem, SonarrShow existingItem, boolean findNew) { - return chatClientResponseBuilder.getNewOrExistingShow(lookupItem, existingItem, findNew); + public CommandResponse getExistingItem(SonarrShow existingItem) { + return new ExistingShowResponse(existingItem); + } + + @Override + public CommandResponse getNewItem(SonarrShow lookupItem) { + return new NewShowResponse(lookupItem); } @Override @@ -73,29 +71,19 @@ public boolean isPathBlacklisted(SonarrShow item) { }.lookup(search, findNew); } - public List getProfiles() { + public List getProfiles() { Collection profiles = SONARR_CACHE.getQualityProfiles(); if (profiles == null || profiles.isEmpty()) { - return Arrays.asList(chatClientResponseBuilder.createErrorMessage("Found 0 profiles, please setup Sonarr with at least one profile")); + return Collections.singletonList(new ErrorResponse("Found 0 profiles, please setup Sonarr with at least one profile")); } - List profileMessages = new ArrayList<>(); + List profileMessages = new ArrayList<>(); for (SonarrProfile sonarrProfile : profiles) { - profileMessages.add(chatClientResponseBuilder.getShowProfile(sonarrProfile)); + profileMessages.add(new ShowProfileResponse(sonarrProfile)); } return profileMessages; } - @Override - public void sendPeriodicNotifications(ChatClient chatClient) { - new PeriodicNotificationStrategy(ContentType.SHOW, getDownloadsStrategy()) { - @Override - public void sendToConfiguredChannels(List downloads) { - chatClient.sendToConfiguredChannels(downloads); - } - }.sendPeriodicNotifications(); - } - @Override public void cacheData() { new CacheProfileStrategy() { @@ -148,7 +136,7 @@ public String getApiToken() { } private AddStrategy getAddStrategy() { - return new AddStrategy(chatClientResponseBuilder, ContentType.SHOW) { + return new AddStrategy(ContentType.SHOW) { @Override public List lookupContent(String search) throws Exception { return lookupShows(search); @@ -171,21 +159,21 @@ public String getItemId(SonarrShow item) { } @Override - public ChatClientResponse addContent(SonarrShow content) { + public CommandResponse addContent(SonarrShow content) { return addShow(content); } @Override - public ChatClientResponse getResponse(SonarrShow item) { - return chatClientResponseBuilder.getShowResponse(item); + public CommandResponse getResponse(SonarrShow item) { + return new ShowResponse(item); } }; } private DownloadsStrategy getDownloadsStrategy() { - return new DownloadsStrategy(this, SonarrUrls.DOWNLOAD_BASE, chatClientResponseBuilder, ContentType.SHOW) { + return new DownloadsStrategy(this, SonarrUrls.DOWNLOAD_BASE, ContentType.SHOW) { @Override - public ChatClientResponse getResponse(JsonElement rawElement) { + public CommandResponse getResponse(JsonElement rawElement) { SonarrQueue showQueue = new Gson().fromJson(rawElement, SonarrQueue.class); SonarQueueEpisode episode = showQueue.getEpisode(); if (episode == null) { @@ -199,15 +187,15 @@ public ChatClientResponse getResponse(JsonElement rawElement) { return null; } if (isPathBlacklisted(sonarrShow)) { - //TODO: log + LOGGER.warn("The following show is blacklisted: " + sonarrShow.getTitle() + " from being displayed in downloads"); return null; } - return chatClientResponseBuilder.getShowDownloadResponses(showQueue); + return new ShowDownloadResponse(showQueue); } }; } - private ChatClientResponse addShow(SonarrShow sonarrShow) { + private CommandResponse addShow(SonarrShow sonarrShow) { String title = sonarrShow.getTitle(); //make sure we specify where the show should get downloaded sonarrShow.setPath(Config.getProperty(Config.Constants.SONARR_PATH) + "/" + title); @@ -219,7 +207,7 @@ private ChatClientResponse addShow(SonarrShow sonarrShow) { String sonarrProfileName = Config.getProperty(Config.Constants.SONARR_DEFAULT_PROFILE); SonarrProfile sonarrProfile = SONARR_CACHE.getProfile(sonarrProfileName.toLowerCase()); if (sonarrProfile == null) { - return chatClientResponseBuilder.createErrorMessage("Could not find sonarr profile for default " + sonarrProfile); + return new ErrorResponse("Could not find sonarr profile for default " + sonarrProfile); } sonarrShow.setQualityProfileId((int) sonarrProfile.getId()); String username = CommandContext.getConfig().getUsername(); @@ -227,7 +215,7 @@ private ChatClientResponse addShow(SonarrShow sonarrShow) { ApiRequestType apiRequestType = ApiRequestType.SHOW; if (apiRequests.checkRequestLimits(apiRequestType) && !apiRequests.canMakeRequests(apiRequestType, username)) { ApiRequestThreshold requestThreshold = ApiRequestThreshold.valueOf(Config.getProperty(Config.Constants.MAX_REQUESTS_THRESHOLD)); - return chatClientResponseBuilder.createErrorMessage("Could not add show, user " + username + " has exceeded max show requests for " + requestThreshold.getReadableName()); + return new ErrorResponse("Could not add show, user " + username + " has exceeded max show requests for " + requestThreshold.getReadableName()); } try (CloseableHttpClient client = HttpClientBuilder.create().build()) { HttpPost post = new HttpPost(getApiUrl(SonarrUrls.SERIES_BASE)); @@ -238,17 +226,17 @@ private ChatClientResponse addShow(SonarrShow sonarrShow) { try (CloseableHttpResponse response = client.execute(post)) { int statusCode = response.getStatusLine().getStatusCode(); if (statusCode != 200 && statusCode != 201) { - return chatClientResponseBuilder.createErrorMessage("Could not add show, status-code=" + statusCode + ", reason=" + response.getStatusLine().getReasonPhrase()); + return new ErrorResponse("Could not add show, status-code=" + statusCode + ", reason=" + response.getStatusLine().getReasonPhrase()); } //cache show after successful request SONARR_CACHE.add(sonarrShow); LogManager.getLogger("AuditLog").info("User " + username + " added " + title); apiRequests.auditRequest(apiRequestType, username, title); - return chatClientResponseBuilder.createSuccessMessage("Show " + title + " added, sonarr-detail=" + response.getStatusLine().getReasonPhrase()); + return new SuccessResponse("Show " + title + " added, sonarr-detail=" + response.getStatusLine().getReasonPhrase()); } } catch (IOException e) { LOGGER.error("Error trying to add show=" + title, e); - return chatClientResponseBuilder.createErrorMessage("Error adding show=" + title + ", error=" + e.getMessage()); + return new ErrorResponse("Error adding show=" + title + ", error=" + e.getMessage()); } } @@ -267,7 +255,7 @@ public List onSuccess(String response) { }); } - private ExclusionStrategy excludeUnnecessaryFields = new ExclusionStrategy() { + private final ExclusionStrategy excludeUnnecessaryFields = new ExclusionStrategy() { @Override public boolean shouldSkipField(FieldAttributes fieldAttributes) { //profileId breaks the post request to /series for some reason and I don't believe its a required field @@ -289,7 +277,6 @@ private boolean isPathBlacklisted(SonarrShow item) { return false; } - private final ChatClientResponseBuilder chatClientResponseBuilder; private static final SonarrCache SONARR_CACHE = new SonarrCache(); public static final String ADD_SHOW_COMMAND_FIELD_PREFIX = "Add show command"; } diff --git a/src/main/java/com/botdarr/commands/SonarrCommands.java b/src/main/java/com/botdarr/api/sonarr/SonarrCommands.java similarity index 74% rename from src/main/java/com/botdarr/commands/SonarrCommands.java rename to src/main/java/com/botdarr/api/sonarr/SonarrCommands.java index 3fd9934..5816165 100644 --- a/src/main/java/com/botdarr/commands/SonarrCommands.java +++ b/src/main/java/com/botdarr/api/sonarr/SonarrCommands.java @@ -1,10 +1,13 @@ -package com.botdarr.commands; +package com.botdarr.api.sonarr; -import com.botdarr.api.sonarr.SonarrApi; -import com.botdarr.clients.ChatClientResponse; +import com.botdarr.commands.BaseCommand; +import com.botdarr.commands.Command; +import com.botdarr.commands.CommandProcessor; +import com.botdarr.commands.responses.CommandResponse; import org.apache.logging.log4j.util.Strings; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class SonarrCommands { @@ -14,7 +17,7 @@ public static List getCommands(SonarrApi sonarrApi) { "Adds a show using search text and tmdb id (i.e., show id add 30 rock 484737). The easiest" + " way to use this command is to use \"show find new \", then the results will contain the show add command for you") { @Override - public CommandResponse execute(String command) { + public List execute(String command) { int lastSpace = command.lastIndexOf(" "); if (lastSpace == -1) { throw new RuntimeException("Missing expected arguments - usage: show id add SHOW_TITLE_HERE SHOW_ID_HERE"); @@ -23,16 +26,16 @@ public CommandResponse execute(String command) { String id = command.substring(lastSpace + 1); validateShowTitle(searchText); validateShowId(id); - return new CommandResponse(sonarrApi.addWithId(searchText, id)); + return Collections.singletonList(sonarrApi.addWithId(searchText, id)); } }); add(new BaseCommand("show title add", "show title add ", "Adds a show with just a title. Since there can be multiple shows that match search criteria" + " we will either add the show or return all the shows that match your search.") { @Override - public CommandResponse execute(String command) { + public List execute(String command) { validateShowTitle(command); - return new CommandResponse(sonarrApi.addWithTitle(command)); + return sonarrApi.addWithTitle(command); } }); add(new BaseCommand("show downloads", "Shows all the active shows downloading in sonarr") { @@ -42,8 +45,8 @@ public boolean hasArguments() { } @Override - public CommandResponse execute(String command) { - return new CommandResponse(sonarrApi.downloads()); + public List execute(String command) { + return sonarrApi.downloads(); } }); add(new BaseCommand("show profiles", "Displays all the profiles available to search for shows under (i.e., show add ANY)") { @@ -53,22 +56,22 @@ public boolean hasArguments() { } @Override - public CommandResponse execute(String command) { - return new CommandResponse(sonarrApi.getProfiles()); + public List execute(String command) { + return sonarrApi.getProfiles(); } }); add(new BaseCommand("show find existing", "show find existing ", "Finds a existing show using sonarr (i.e., show find existing Ahh! Real fudgecakes)") { @Override - public CommandResponse execute(String command) { + public List execute(String command) { validateShowTitle(command); - return new CommandResponse(sonarrApi.lookup(command, false)); + return sonarrApi.lookup(command, false); } }); add(new BaseCommand("show find new", "show find new ", "Finds a new show using sonarr (i.e., show find new Fresh Prince of Fresh air)") { @Override - public CommandResponse execute(String command) { + public List execute(String command) { validateShowTitle(command); - return new CommandResponse(sonarrApi.lookup(command, true)); + return sonarrApi.lookup(command, true); } }); }}; diff --git a/src/main/java/com/botdarr/clients/ChatClientBootstrap.java b/src/main/java/com/botdarr/clients/ChatClientBootstrap.java new file mode 100644 index 0000000..0a70628 --- /dev/null +++ b/src/main/java/com/botdarr/clients/ChatClientBootstrap.java @@ -0,0 +1,103 @@ +package com.botdarr.clients; + +import com.botdarr.api.*; +import com.botdarr.Config; +import com.botdarr.api.lidarr.LidarrApi; +import com.botdarr.api.lidarr.LidarrCommands; +import com.botdarr.api.radarr.RadarrApi; +import com.botdarr.api.radarr.RadarrCommands; +import com.botdarr.api.sonarr.SonarrApi; +import com.botdarr.api.sonarr.SonarrCommands; +import com.botdarr.clients.telegram.TelegramResponse; +import com.botdarr.commands.*; +import com.botdarr.commands.responses.CommandResponse; +import com.botdarr.scheduling.Scheduler; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.*; + +public abstract class ChatClientBootstrap { + public abstract void init() throws Exception; + public abstract boolean isConfigured(Properties properties); + public void validatePrefix(String configuredPrefix) { + if (configuredPrefix.length() > 1) { + throw new RuntimeException("Command prefix must be a single character"); + } + } + + protected static ApisAndCommandConfig buildConfig() { + RadarrApi radarrApi = new RadarrApi(); + SonarrApi sonarrApi = new SonarrApi(); + LidarrApi lidarrApi = new LidarrApi(); + + List radarrCommands = RadarrCommands.getCommands(radarrApi); + List sonarrCommands = SonarrCommands.getCommands(sonarrApi); + List lidarrCommands = LidarrCommands.getCommands(lidarrApi); + + List commands = new ArrayList<>(); + List apis = new ArrayList<>(); + if (Config.isRadarrEnabled()) { + commands.addAll(radarrCommands); + apis.add(radarrApi); + } + if (Config.isSonarrEnabled()) { + commands.addAll(sonarrCommands); + apis.add(sonarrApi); + } + if (Config.isLidarrEnabled()) { + commands.addAll(lidarrCommands); + apis.add(lidarrApi); + } + if (!Config.getStatusEndpoints().isEmpty()) { + commands.add(new StatusCommand()); + } + commands.addAll(HelpCommands.getCommands(radarrCommands, sonarrCommands, lidarrCommands)); + return new ApisAndCommandConfig(apis, commands); + } + + protected void initScheduling(ChatClient chatClient, ChatClientResponseBuilder responseBuilder, List apis) { + Scheduler scheduler = Scheduler.getScheduler(); + //make sure to always cache before doing any notifications + scheduler.initApiCaching(apis); + scheduler.initApiNotifications(apis, chatClient, responseBuilder); + } + + protected static void runAndProcessCommands(String message, + String username, + ChatClientResponseBuilder responseBuilder, + ChatSender chatSender) { + List commandResponses = + commandProcessor.processRequestMessage(buildConfig().getCommands(), message, username); + if (commandResponses != null) { + //if there is a response, format it for given response builder + for (CommandResponse commandResponse : commandResponses) { + //convert command response into chat client specific response + T telegramResponse = commandResponse.convertToChatClientResponse(responseBuilder); + //then send the response + chatSender.send(telegramResponse); + } + } + } + + protected static class ApisAndCommandConfig { + private ApisAndCommandConfig(List apis, List commands) { + this.apis = apis; + this.commands = commands; + } + + public List getApis() { + return apis; + } + + public List getCommands() { + return commands; + } + + private final List apis; + private final List commands; + } + + protected static CommandProcessor commandProcessor = new CommandProcessor(); + protected static final Logger LOGGER = LogManager.getLogger(ChatClientBootstrap.class); +} diff --git a/src/main/java/com/botdarr/clients/ChatClientData.java b/src/main/java/com/botdarr/clients/ChatClientData.java new file mode 100644 index 0000000..faf8699 --- /dev/null +++ b/src/main/java/com/botdarr/clients/ChatClientData.java @@ -0,0 +1,4 @@ +package com.botdarr.clients; + +public interface ChatClientData { +} diff --git a/src/main/java/com/botdarr/clients/ChatClientResponse.java b/src/main/java/com/botdarr/clients/ChatClientResponse.java index 03cd604..7555020 100644 --- a/src/main/java/com/botdarr/clients/ChatClientResponse.java +++ b/src/main/java/com/botdarr/clients/ChatClientResponse.java @@ -1,4 +1,4 @@ package com.botdarr.clients; -//marker interface for different type of responses -public interface ChatClientResponse {} +public interface ChatClientResponse { +} diff --git a/src/main/java/com/botdarr/clients/ChatClientResponseBuilder.java b/src/main/java/com/botdarr/clients/ChatClientResponseBuilder.java index 6a19f3a..519c238 100644 --- a/src/main/java/com/botdarr/clients/ChatClientResponseBuilder.java +++ b/src/main/java/com/botdarr/clients/ChatClientResponseBuilder.java @@ -1,53 +1,45 @@ package com.botdarr.clients; -import com.botdarr.api.lidarr.LidarrArtist; -import com.botdarr.api.lidarr.LidarrQueueRecord; -import com.botdarr.api.radarr.RadarrMovie; -import com.botdarr.api.radarr.RadarrProfile; -import com.botdarr.api.radarr.RadarrQueue; -import com.botdarr.api.sonarr.SonarrProfile; -import com.botdarr.api.sonarr.SonarrQueue; -import com.botdarr.api.sonarr.SonarrShow; -import com.botdarr.commands.Command; +import com.botdarr.commands.responses.*; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; -import java.util.List; -import java.util.Map; import java.util.stream.Collectors; public interface ChatClientResponseBuilder { - T getHelpResponse(); - T getMusicHelpResponse(List lidarCommands); - T getMoviesHelpResponse(List radarrCommands); - T getShowsHelpResponse(List sonarrCommands); - T getShowResponse(SonarrShow show); - T getArtistResponse(LidarrArtist lidarrArtist); - T getMovieResponse(RadarrMovie radarrMovie); - T getShowDownloadResponses(SonarrQueue sonarrShow); - T getMovieDownloadResponses(RadarrQueue radarrQueue); - T getArtistDownloadResponses(LidarrQueueRecord lidarrQueue); - T createErrorMessage(String message); - T createInfoMessage(String message); - T createSuccessMessage(String message); - T getShowProfile(SonarrProfile sonarrProfile); - T getMovieProfile(RadarrProfile radarrProfile); - T getNewOrExistingShow(SonarrShow sonarrShow, SonarrShow existingShow, boolean findNew); - T getNewOrExistingMovie(RadarrMovie lookupMovie, RadarrMovie existingMovie, boolean findNew); - T getNewOrExistingArtist(LidarrArtist lookupArtist, LidarrArtist existingArtist, boolean findNew); - T getDiscoverableMovies(RadarrMovie radarrMovie); - T getStatusCommandResponse(Map endpointStatuses); + T build(HelpResponse helpResponse); + T build(MusicHelpResponse musicHelpResponse); + T build(MoviesHelpResponse moviesHelpResponse); + T build(ShowsHelpResponse showsHelpResponse); + T build(ShowResponse showResponse); + T build(MusicArtistResponse musicArtistResponse); + T build(MovieResponse movieResponse); + T build(ShowDownloadResponse showDownloadResponse); + T build(MovieDownloadResponse movieDownloadResponse); + T build(MusicArtistDownloadResponse musicArtistDownloadResponse); + T build(ErrorResponse errorResponse); + T build(InfoResponse infoResponse); + T build(SuccessResponse successResponse); + T build(ShowProfileResponse showProfileResponse); + T build(MovieProfileResponse movieProfileResponse); + T build(NewShowResponse newShowResponse); + T build(ExistingShowResponse existingShowResponse); + T build(NewMovieResponse newMovieResponse); + T build(ExistingMovieResponse existingMovieResponse); + T build(NewMusicArtistResponse newMusicArtistResponse); + T build(ExistingMusicArtistResponse exitingMusicArtistResponse); + T build(DiscoverMovieResponse discoverMovieResponse); + T build(StatusCommandResponse statusCommandResponse); static String getVersion() throws IOException { ClassLoader classloader = Thread.currentThread().getContextClassLoader(); InputStream is = classloader.getResourceAsStream("version.txt"); if (is != null) { try (BufferedReader br = new BufferedReader(new InputStreamReader(is, Charset.defaultCharset()))) { - String versionTxt = br.lines().collect(Collectors.joining(System.lineSeparator())); - return versionTxt; + return br.lines().collect(Collectors.joining(System.lineSeparator())); } } return "local"; diff --git a/src/main/java/com/botdarr/clients/ChatClientSender.java b/src/main/java/com/botdarr/clients/ChatClientSender.java new file mode 100644 index 0000000..59d0c8d --- /dev/null +++ b/src/main/java/com/botdarr/clients/ChatClientSender.java @@ -0,0 +1,5 @@ +package com.botdarr.clients; + +public interface ChatClientSender { + public void send(Z response, T data); +} diff --git a/src/main/java/com/botdarr/clients/ChatClientType.java b/src/main/java/com/botdarr/clients/ChatClientType.java deleted file mode 100644 index 3a0865e..0000000 --- a/src/main/java/com/botdarr/clients/ChatClientType.java +++ /dev/null @@ -1,388 +0,0 @@ -package com.botdarr.clients; - -import com.botdarr.api.*; -import com.botdarr.Config; -import com.botdarr.api.lidarr.LidarrApi; -import com.botdarr.api.radarr.RadarrApi; -import com.botdarr.api.sonarr.SonarrApi; -import com.botdarr.clients.matrix.MatrixChatClient; -import com.botdarr.clients.matrix.MatrixResponse; -import com.botdarr.clients.matrix.MatrixResponseBuilder; -import com.botdarr.commands.*; -import com.botdarr.clients.discord.DiscordChatClient; -import com.botdarr.clients.discord.DiscordResponse; -import com.botdarr.clients.discord.DiscordResponseBuilder; -import com.botdarr.scheduling.Scheduler; -import com.botdarr.clients.slack.SlackChatClient; -import com.botdarr.clients.slack.SlackMessage; -import com.botdarr.clients.slack.SlackResponse; -import com.botdarr.clients.slack.SlackResponseBuilder; -import com.botdarr.clients.telegram.TelegramChatClient; -import com.botdarr.clients.telegram.TelegramResponse; -import com.botdarr.clients.telegram.TelegramResponseBuilder; -import com.github.seratch.jslack.Slack; -import com.github.seratch.jslack.api.model.User; -import com.github.seratch.jslack.api.model.block.LayoutBlock; -import com.github.seratch.jslack.api.model.block.SectionBlock; -import com.github.seratch.jslack.api.model.block.composition.MarkdownTextObject; -import com.github.seratch.jslack.api.rtm.RTMMessageHandler; -import com.google.gson.Gson; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.pengrad.telegrambot.UpdatesListener; -import com.pengrad.telegrambot.model.Update; -import net.dv8tion.jda.api.JDA; -import net.dv8tion.jda.api.JDABuilder; -import net.dv8tion.jda.api.entities.Message; -import net.dv8tion.jda.api.entities.MessageEmbed; -import net.dv8tion.jda.api.entities.MessageHistory; -import net.dv8tion.jda.api.events.GenericEvent; -import net.dv8tion.jda.api.events.ReadyEvent; -import net.dv8tion.jda.api.events.message.MessageReceivedEvent; -import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionAddEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.util.Strings; - -import javax.annotation.Nonnull; -import java.util.*; -import java.util.concurrent.Callable; - -import static com.botdarr.api.lidarr.LidarrApi.ADD_ARTIST_COMMAND_FIELD_PREFIX; -import static com.botdarr.api.radarr.RadarrApi.ADD_MOVIE_COMMAND_FIELD_PREFIX; -import static com.botdarr.api.sonarr.SonarrApi.ADD_SHOW_COMMAND_FIELD_PREFIX; - -public enum ChatClientType { - MATRIX() { - @Override - public void init() throws Exception { - MatrixChatClient chatClient = new MatrixChatClient(); - ChatClientResponseBuilder responseChatClientResponseBuilder = new MatrixResponseBuilder(); - ApisAndCommandConfig config = buildConfig(responseChatClientResponseBuilder); - initScheduling(chatClient, config.apis); - chatClient.addListener((roomId, sender, content) -> { - Scheduler.getScheduler().executeCommand(() -> { - CommandResponse commandResponse = - commandProcessor.processMessage(config.commands, content, sender, responseChatClientResponseBuilder); - if (commandResponse != null) { - chatClient.sendMessage(commandResponse, roomId); - } - return null; - }); - }); - chatClient.listen(); - } - - @Override - public boolean isConfigured(Properties properties) { - return - !Strings.isBlank(properties.getProperty(Config.Constants.MATRIX_USERNAME)) && - !Strings.isBlank(properties.getProperty(Config.Constants.MATRIX_PASSWORD)) && - !Strings.isBlank(properties.getProperty(Config.Constants.MATRIX_ROOM)) && - !Strings.isBlank(properties.getProperty(Config.Constants.MATRIX_HOME_SERVER)); - } - - @Override - public String getReadableName() { - return "Matrix"; - } - }, - TELEGRAM() { - private boolean isUsingChannels() { - String telegramGroups = Config.getProperty(Config.Constants.TELEGRAM_PRIVATE_GROUPS); - return telegramGroups == null || telegramGroups.isEmpty(); - } - @Override - public void init() throws Exception { - ChatClientResponseBuilder responseChatClientResponseBuilder = new TelegramResponseBuilder(); - ApisAndCommandConfig config = buildConfig(responseChatClientResponseBuilder); - TelegramChatClient telegramChatClient = new TelegramChatClient(); - - initScheduling(telegramChatClient, config.apis); - telegramChatClient.addUpdateListener(list -> { - try { - for (Update update : list) { - com.pengrad.telegrambot.model.Message message = isUsingChannels() ? update.channelPost() : update.message(); - if (message != null && !Strings.isEmpty(message.text())) { - String text = message.text(); - //TODO: the telegram api doesn't seem return "from" field in channel posts for some reason - //for now we leave the author as "telegram" till a better solution arises - String author = "telegram"; - Scheduler.getScheduler().executeCommand(() -> { - CommandResponse commandResponse = - commandProcessor.processMessage(config.commands, text, author, responseChatClientResponseBuilder); - if (commandResponse != null) { - telegramChatClient.sendMessage(commandResponse, message.chat()); - } - return null; - }); - } - } - } catch (Throwable t) { - LOGGER.error("Error during telegram updates", t); - } - return UpdatesListener.CONFIRMED_UPDATES_ALL; - }); - } - - @Override - public boolean isConfigured(Properties properties) { - boolean isTelegramConfigured = !Strings.isBlank(properties.getProperty(Config.Constants.TELEGRAM_TOKEN)); - boolean telegramPrivateChannelsExist = !Strings.isBlank(properties.getProperty(Config.Constants.TELEGRAM_PRIVATE_CHANNELS)); - boolean telegramPrivateGroupsExist = !Strings.isBlank(properties.getProperty(Config.Constants.TELEGRAM_PRIVATE_GROUPS)); - if (isTelegramConfigured && telegramPrivateChannelsExist && telegramPrivateGroupsExist) { - throw new RuntimeException("Cannot configure telegram for private channels and groups, you must pick one or the other"); - } - return isTelegramConfigured && (telegramPrivateChannelsExist || telegramPrivateGroupsExist); - } - - @Override - public String getReadableName() { - return "Telegram"; - } - }, - DISCORD() { - @Override - public void init() throws Exception { - try { - ChatClientResponseBuilder responseChatClientResponseBuilder = new DiscordResponseBuilder(); - ApisAndCommandConfig config = buildConfig(responseChatClientResponseBuilder); - - - JDA jda = JDABuilder.createDefault((Config.getProperty(Config.Constants.DISCORD_TOKEN))).addEventListeners(new ListenerAdapter() { - @Override - public void onGenericEvent(@Nonnull GenericEvent event) { - super.onGenericEvent(event); - } - - @Override - public void onReady(@Nonnull ReadyEvent event) { - LogManager.getLogger("com.botdarr.clients.discord").info("Connected to discord"); - ChatClient chatClient = new DiscordChatClient(event.getJDA()); - //start the scheduler threads that send notifications and cache data periodically - initScheduling(chatClient, config.apis); - super.onReady(event); - } - - @Override - public void onGuildMessageReactionAdd(@Nonnull GuildMessageReactionAddEvent event) { - if (event.getReactionEmote().getName().equalsIgnoreCase(THUMBS_UP_EMOTE)) { - MessageHistory.MessageRetrieveAction me = event.getChannel().getHistoryAround(event.getMessageId(), 1); - me.queue(messageHistory -> { - List messageHistories = messageHistory.getRetrievedHistory(); - messageLoop: - for (Message message : messageHistories) { - List embeds = message.getEmbeds(); - fieldLoop: - for (MessageEmbed.Field field : embeds.get(0).getFields()) { - if (field.getName().equals(ADD_MOVIE_COMMAND_FIELD_PREFIX) || - field.getName().equals(ADD_SHOW_COMMAND_FIELD_PREFIX) || - field.getName().equals(ADD_ARTIST_COMMAND_FIELD_PREFIX)) { - //capture/process the command - handleCommand(event.getJDA(), field.getValue(), event.getUser().getName(), event.getChannel().getName()); - break messageLoop; - } - } - } - }); - } - super.onGuildMessageReactionAdd(event); - } - - @Override - public void onMessageReceived(@Nonnull MessageReceivedEvent event) { - handleCommand(event.getJDA(), event.getMessage().getContentStripped(), event.getAuthor().getName(), event.getChannel().getName()); - LogManager.getLogger("com.botdarr.clients.discord").debug(event.getMessage().getContentRaw()); - super.onMessageReceived(event); - } - - private void handleCommand(JDA jda, String message, String author, String channelName) { - //build chat client - DiscordChatClient discordChatClient = new DiscordChatClient(jda); - - //capture/process command - Scheduler.getScheduler().executeCommand(() -> { - CommandResponse commandResponse = commandProcessor.processMessage( - config.commands, - message, - author, - responseChatClientResponseBuilder); - if (commandResponse != null) { - //then send the response - discordChatClient.sendMessage(commandResponse, channelName); - } - return null; - }); - } - - private static final String THUMBS_UP_EMOTE = "\uD83D\uDC4D"; - }).build(); - jda.awaitReady(); - } catch (Throwable e) { - LogManager.getLogger("com.botdarr.clients.discord").error("Error caught during main", e); - throw e; - } - } - - @Override - public boolean isConfigured(Properties properties) { - return - !Strings.isBlank(properties.getProperty(Config.Constants.DISCORD_TOKEN)) && - !Strings.isBlank(properties.getProperty(Config.Constants.DISCORD_CHANNELS)); - } - - @Override - public String getReadableName() { - return "Discord"; - } - }, - SLACK() { - @Override - public void init() throws Exception { - JsonParser jsonParser = new JsonParser(); - SlackChatClient slackChatClient = new SlackChatClient(Slack.getInstance().rtm(Config.getProperty(Config.Constants.SLACK_BOT_TOKEN))); - - ChatClientResponseBuilder responseChatClientResponseBuilder = new SlackResponseBuilder(); - ApisAndCommandConfig config = buildConfig(responseChatClientResponseBuilder); - - slackChatClient.addMessageHandler(new RTMMessageHandler() { - @Override - public void handle(String message) { - JsonObject json = jsonParser.parse(message).getAsJsonObject(); - SlackMessage slackMessage = new Gson().fromJson(json, SlackMessage.class); - if (slackMessage.getType() != null) { - if (slackMessage.getType().equalsIgnoreCase("message")) { - User user = slackChatClient.getUser(slackMessage.getUserId()); - if (user == null) { - LOGGER.debug("Could not find user for slack message " + slackMessage); - return; - } - handleCommand(slackMessage.getText(), user.getName(), slackMessage.getChannel()); - } else if (slackMessage.getType().equalsIgnoreCase("reaction_added") && slackMessage.getReaction().equalsIgnoreCase("+1")) { - //thumbsup = +1 in slack for some reason - try { - //search public channels first - List conversationMessages = slackChatClient.getPublicMessages(slackMessage); - if (conversationMessages == null || conversationMessages.isEmpty()) { - //check private channels if necessary - conversationMessages = slackChatClient.getPrivateMessages(slackMessage); - } - if (conversationMessages != null) { - conversationMessageLoop: - for (com.github.seratch.jslack.api.model.Message conversationMessage : conversationMessages) { - for (LayoutBlock layoutBlock : conversationMessage.getBlocks()) { - if (layoutBlock.getType().equals("section")) { - SectionBlock sectionBlock = (SectionBlock) layoutBlock; - if (sectionBlock.getText() instanceof MarkdownTextObject) { - String markdownText = ((MarkdownTextObject) sectionBlock.getText()).getText(); - if (markdownText != null && - (markdownText.startsWith(ADD_MOVIE_COMMAND_FIELD_PREFIX) || markdownText.startsWith(ADD_SHOW_COMMAND_FIELD_PREFIX))) { - String postProcessedCommand = markdownText - .replaceAll(ADD_MOVIE_COMMAND_FIELD_PREFIX + " - ", "") - .replaceAll(ADD_SHOW_COMMAND_FIELD_PREFIX + " - ", ""); - handleCommand(postProcessedCommand, slackChatClient.getUser(slackMessage.getUserId()).getName(), slackMessage.getItem().getChannel()); - break conversationMessageLoop; - } - } - } - } - } - } - } catch (Exception e) { - LogManager.getLogger("com.botdarr.clients.slack").error("Error fetching conversation history", e); - } - } - } - LogManager.getLogger("com.botdarr.clients.slack").debug(json); - } - - private void handleCommand(String text, String userId, String channel) { - Scheduler.getScheduler().executeCommand(() -> { - //capture/process the command - CommandResponse commandResponse = commandProcessor.processMessage( - config.commands, - text, - userId, - responseChatClientResponseBuilder); - if (commandResponse != null) { - //then send the response - slackChatClient.sendMessage(commandResponse, channel); - } - return null; - }); - } - }); - - //start the scheduler threads that send notifications and cache data periodically - initScheduling(slackChatClient, config.apis); - - slackChatClient.connect(); - } - - @Override - public boolean isConfigured(Properties properties) { - return - !Strings.isBlank(properties.getProperty(Config.Constants.SLACK_BOT_TOKEN)) && - !Strings.isBlank(properties.getProperty(Config.Constants.SLACK_CHANNELS)); - } - - @Override - public String getReadableName() { - return "Slack"; - } - }; - - void initScheduling(ChatClient chatClient, List apis) { - Scheduler scheduler = Scheduler.getScheduler(); - //make sure to always cache before doing any notifications - scheduler.initApiCaching(apis); - scheduler.initApiNotifications(apis, chatClient); - } - - public abstract void init() throws Exception; - public abstract boolean isConfigured(Properties properties); - public abstract String getReadableName(); - - private static ApisAndCommandConfig buildConfig(ChatClientResponseBuilder responseChatClientResponseBuilder) { - RadarrApi radarrApi = new RadarrApi(responseChatClientResponseBuilder); - SonarrApi sonarrApi = new SonarrApi(responseChatClientResponseBuilder); - LidarrApi lidarrApi = new LidarrApi(responseChatClientResponseBuilder); - - List radarrCommands = RadarrCommands.getCommands(radarrApi); - List sonarrCommands = SonarrCommands.getCommands(sonarrApi); - List lidarrCommands = LidarrCommands.getCommands(lidarrApi); - - List commands = new ArrayList<>(); - List apis = new ArrayList<>(); - if (Config.isRadarrEnabled()) { - commands.addAll(radarrCommands); - apis.add(radarrApi); - } - if (Config.isSonarrEnabled()) { - commands.addAll(sonarrCommands); - apis.add(sonarrApi); - } - if (Config.isLidarrEnabled()) { - commands.addAll(lidarrCommands); - apis.add(lidarrApi); - } - if (!Config.getStatusEndpoints().isEmpty()) { - commands.add(new StatusCommand<>(responseChatClientResponseBuilder)); - } - commands.addAll(HelpCommands.getCommands(responseChatClientResponseBuilder, radarrCommands, sonarrCommands, lidarrCommands)); - return new ApisAndCommandConfig(apis, commands); - } - - private static class ApisAndCommandConfig { - private ApisAndCommandConfig(List apis, List commands) { - this.apis = apis; - this.commands = commands; - } - private final List apis; - private final List commands; - } - - private static CommandProcessor commandProcessor = new CommandProcessor(); - private static final Logger LOGGER = LogManager.getLogger(ChatClientType.class); -} diff --git a/src/main/java/com/botdarr/clients/ChatSender.java b/src/main/java/com/botdarr/clients/ChatSender.java new file mode 100644 index 0000000..93a1c52 --- /dev/null +++ b/src/main/java/com/botdarr/clients/ChatSender.java @@ -0,0 +1,5 @@ +package com.botdarr.clients; + +public interface ChatSender { + void send(T chatClientResponse); +} \ No newline at end of file diff --git a/src/main/java/com/botdarr/clients/discord/DiscordBootstrap.java b/src/main/java/com/botdarr/clients/discord/DiscordBootstrap.java new file mode 100644 index 0000000..5a06447 --- /dev/null +++ b/src/main/java/com/botdarr/clients/discord/DiscordBootstrap.java @@ -0,0 +1,113 @@ +package com.botdarr.clients.discord; + +import com.botdarr.Config; +import com.botdarr.clients.ChatClient; +import com.botdarr.clients.ChatClientBootstrap; +import com.botdarr.clients.ChatClientResponseBuilder; +import com.botdarr.scheduling.Scheduler; +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.JDABuilder; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.entities.MessageHistory; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.ReadyEvent; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionAddEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.util.Strings; + +import javax.annotation.Nonnull; +import java.util.List; +import java.util.Properties; + +import static com.botdarr.api.lidarr.LidarrApi.ADD_ARTIST_COMMAND_FIELD_PREFIX; +import static com.botdarr.api.radarr.RadarrApi.ADD_MOVIE_COMMAND_FIELD_PREFIX; +import static com.botdarr.api.sonarr.SonarrApi.ADD_SHOW_COMMAND_FIELD_PREFIX; + +public class DiscordBootstrap extends ChatClientBootstrap { + @Override + public void init() throws Exception { + try { + ChatClientBootstrap.ApisAndCommandConfig config = buildConfig(); + ChatClientResponseBuilder responseBuilder = new DiscordResponseBuilder(); + + JDA jda = JDABuilder.createDefault((Config.getProperty(Config.Constants.DISCORD_TOKEN))).addEventListeners(new ListenerAdapter() { + @Override + public void onGenericEvent(@Nonnull GenericEvent event) { + super.onGenericEvent(event); + } + + @Override + public void onReady(@Nonnull ReadyEvent event) { + LogManager.getLogger("com.botdarr.clients.discord").info("Connected to discord"); + ChatClient chatClient = new DiscordChatClient(event.getJDA()); + //start the scheduler threads that send notifications and cache data periodically + initScheduling(chatClient, responseBuilder, config.getApis()); + super.onReady(event); + } + + @Override + public void onGuildMessageReactionAdd(@Nonnull GuildMessageReactionAddEvent event) { + if (event.getReactionEmote().getName().equalsIgnoreCase(THUMBS_UP_EMOTE)) { + MessageHistory.MessageRetrieveAction me = event.getChannel().getHistoryAround(event.getMessageId(), 1); + me.queue(messageHistory -> { + List messageHistories = messageHistory.getRetrievedHistory(); + messageLoop: + for (Message message : messageHistories) { + List embeds = message.getEmbeds(); + for (MessageEmbed.Field field : embeds.get(0).getFields()) { + String name = field.getName(); + if (Strings.isEmpty(name)) { + continue; + } + if (name.equals(ADD_MOVIE_COMMAND_FIELD_PREFIX) || + name.equals(ADD_SHOW_COMMAND_FIELD_PREFIX) || + name.equals(ADD_ARTIST_COMMAND_FIELD_PREFIX)) { + //capture/process the command + handleCommand(event.getJDA(), field.getValue(), event.getUser().getName(), event.getChannel().getName()); + break messageLoop; + } + } + } + }); + } + super.onGuildMessageReactionAdd(event); + } + + @Override + public void onMessageReceived(@Nonnull MessageReceivedEvent event) { + handleCommand(event.getJDA(), event.getMessage().getContentStripped(), event.getAuthor().getName(), event.getChannel().getName()); + LogManager.getLogger("com.botdarr.clients.discord").debug(event.getMessage().getContentRaw()); + super.onMessageReceived(event); + } + + private void handleCommand(JDA jda, String message, String author, String channelName) { + //build chat client + DiscordChatClient discordChatClient = new DiscordChatClient(jda); + + //capture/process command + Scheduler.getScheduler().executeCommand(() -> { + runAndProcessCommands(message, author, responseBuilder, chatClientResponse -> { + discordChatClient.sendMessage(chatClientResponse, channelName); + }); + return null; + }); + } + + private static final String THUMBS_UP_EMOTE = "\uD83D\uDC4D"; + }).build(); + jda.awaitReady(); + } catch (Throwable e) { + LogManager.getLogger("com.botdarr.clients.discord").error("Error caught during main", e); + throw e; + } + } + + @Override + public boolean isConfigured(Properties properties) { + return !Strings.isBlank(properties.getProperty(Config.Constants.DISCORD_TOKEN)) && + !Strings.isBlank(properties.getProperty(Config.Constants.DISCORD_CHANNELS)); + } +} diff --git a/src/main/java/com/botdarr/clients/discord/DiscordChatClient.java b/src/main/java/com/botdarr/clients/discord/DiscordChatClient.java index 2ac790e..a387110 100644 --- a/src/main/java/com/botdarr/clients/discord/DiscordChatClient.java +++ b/src/main/java/com/botdarr/clients/discord/DiscordChatClient.java @@ -2,7 +2,6 @@ import com.botdarr.Config; import com.botdarr.clients.ChatClient; -import com.botdarr.commands.CommandResponse; import com.google.common.base.Splitter; import com.google.common.collect.Sets; import net.dv8tion.jda.api.JDA; @@ -16,26 +15,17 @@ public DiscordChatClient(JDA readyEventJda) { this.jda = readyEventJda; } - public void sendMessage(DiscordResponse chatClientResponse, String channelName) { - sendMessages(channel -> channel.sendMessage(chatClientResponse.getMessage()).queue(), channelName); - } - - public void sendMessage(List chatClientResponses, String channelName) { + @Override + public void sendToConfiguredChannels(List chatClientResponses) { sendMessages(channel -> { for (DiscordResponse discordResponse : chatClientResponses) { channel.sendMessage(discordResponse.getMessage()).queue(); } - }, channelName); + }, null); } - public void sendMessage(CommandResponse commandResponse, String targetChannel) { - if (commandResponse.getSingleChatClientResponse() != null) { - sendMessage(commandResponse.getSingleChatClientResponse(), targetChannel); - } else if (commandResponse.getMultipleChatClientResponses() != null) { - sendMessage(commandResponse.getMultipleChatClientResponses(), targetChannel); - } else { - //TODO: err - } + public void sendMessage(DiscordResponse chatClientResponse, String channelName) { + sendMessages(channel -> channel.sendMessage(chatClientResponse.getMessage()).queue(), channelName); } private void sendMessages(MessageSender messageSender, String channelName) { @@ -51,11 +41,6 @@ private void sendMessages(MessageSender messageSender, String channelName) { } } - @Override - public void sendToConfiguredChannels(List chatClientResponses) { - sendMessage(chatClientResponses, null); - } - private interface MessageSender { void send(TextChannel channel); } diff --git a/src/main/java/com/botdarr/clients/discord/DiscordResponseBuilder.java b/src/main/java/com/botdarr/clients/discord/DiscordResponseBuilder.java index fb1a858..f4de1a0 100644 --- a/src/main/java/com/botdarr/clients/discord/DiscordResponseBuilder.java +++ b/src/main/java/com/botdarr/clients/discord/DiscordResponseBuilder.java @@ -2,12 +2,14 @@ import com.botdarr.Config; import com.botdarr.api.lidarr.LidarrArtist; +import com.botdarr.api.lidarr.LidarrCommands; import com.botdarr.api.lidarr.LidarrQueueRecord; import com.botdarr.api.lidarr.LidarrQueueStatusMessage; import com.botdarr.api.sonarr.*; import com.botdarr.clients.ChatClientResponseBuilder; import com.botdarr.api.radarr.*; import com.botdarr.commands.*; +import com.botdarr.commands.responses.*; import com.botdarr.utilities.ListUtils; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.MessageEmbed; @@ -27,7 +29,7 @@ public class DiscordResponseBuilder implements ChatClientResponseBuilder { @Override - public DiscordResponse getHelpResponse() { + public DiscordResponse build(HelpResponse helpResponse) { EmbedBuilder embedBuilder = new EmbedBuilder(); embedBuilder.setTitle("Commands"); try { @@ -60,23 +62,24 @@ public DiscordResponse getHelpResponse() { } @Override - public DiscordResponse getMusicHelpResponse(List lidarCommands) { - return getListOfCommands(lidarCommands); + public DiscordResponse build(MusicHelpResponse musicHelpResponse) { + return getListOfCommands(musicHelpResponse.getLidarrCommands()); } @Override - public DiscordResponse getMoviesHelpResponse(List radarrCommands) { - return getListOfCommands(radarrCommands); + public DiscordResponse build(MoviesHelpResponse moviesHelpResponse) { + return getListOfCommands(moviesHelpResponse.getRadarrCommands()); } @Override - public DiscordResponse getShowsHelpResponse(List sonarrCommands) { - return getListOfCommands(sonarrCommands); + public DiscordResponse build(ShowsHelpResponse showsHelpResponse) { + return getListOfCommands(showsHelpResponse.getSonarrCommands()); } @Override - public DiscordResponse getShowResponse(SonarrShow show) { + public DiscordResponse build(ShowResponse showResponse) { EmbedBuilder embedBuilder = new EmbedBuilder(); + SonarrShow show = showResponse.getShow(); embedBuilder.setTitle(show.getTitle()); embedBuilder.addField("TvdbId", String.valueOf(show.getTvdbId()), false); embedBuilder.addField(ADD_SHOW_COMMAND_FIELD_PREFIX, SonarrCommands.getAddShowCommandStr(show.getTitle(), show.getTvdbId()), false); @@ -85,8 +88,9 @@ public DiscordResponse getShowResponse(SonarrShow show) { } @Override - public DiscordResponse getArtistResponse(LidarrArtist lidarrArtist) { + public DiscordResponse build(MusicArtistResponse musicArtistResponse) { EmbedBuilder embedBuilder = new EmbedBuilder(); + LidarrArtist lidarrArtist = musicArtistResponse.getArtist(); embedBuilder.setTitle(lidarrArtist.getArtistName()); embedBuilder.addField("Id", String.valueOf(lidarrArtist.getForeignArtistId()), false); embedBuilder.addField(ADD_ARTIST_COMMAND_FIELD_PREFIX, LidarrCommands.getAddArtistCommandStr(lidarrArtist.getArtistName(), lidarrArtist.getForeignArtistId()), false); @@ -95,8 +99,9 @@ public DiscordResponse getArtistResponse(LidarrArtist lidarrArtist) { } @Override - public DiscordResponse getShowDownloadResponses(SonarrQueue showQueue) { + public DiscordResponse build(ShowDownloadResponse showDownloadResponse) { EmbedBuilder embedBuilder = new EmbedBuilder(); + SonarrQueue showQueue = showDownloadResponse.getShowQueue(); SonarQueueEpisode episode = showQueue.getEpisode(); embedBuilder.setTitle(showQueue.getSonarrQueueShow().getTitle()); embedBuilder.addField("Season/Episode", "S" + episode.getSeasonNumber() + "E" + episode.getEpisodeNumber(), true); @@ -119,8 +124,9 @@ public DiscordResponse getShowDownloadResponses(SonarrQueue showQueue) { } @Override - public DiscordResponse getMovieDownloadResponses(RadarrQueue radarrQueue) { + public DiscordResponse build(MovieDownloadResponse movieDownloadResponse) { EmbedBuilder embedBuilder = new EmbedBuilder(); + RadarrQueue radarrQueue = movieDownloadResponse.getRadarrQueue(); embedBuilder.setTitle(radarrQueue.getTitle()); embedBuilder.addField("Quality", radarrQueue.getQuality().getQuality().getName(), true); embedBuilder.addField("Status", radarrQueue.getStatus(), true); @@ -136,8 +142,9 @@ public DiscordResponse getMovieDownloadResponses(RadarrQueue radarrQueue) { } @Override - public DiscordResponse getArtistDownloadResponses(LidarrQueueRecord lidarrQueueRecord) { + public DiscordResponse build(MusicArtistDownloadResponse musicArtistDownloadResponse) { EmbedBuilder embedBuilder = new EmbedBuilder(); + LidarrQueueRecord lidarrQueueRecord = musicArtistDownloadResponse.getQueueRecord(); embedBuilder.setTitle(lidarrQueueRecord.getTitle()); embedBuilder.addField("Time Left", lidarrQueueRecord.getTimeleft() == null ? "unknown" : lidarrQueueRecord.getTimeleft(), true); embedBuilder.addField("Status", lidarrQueueRecord.getStatus(), true); @@ -152,9 +159,10 @@ public DiscordResponse getArtistDownloadResponses(LidarrQueueRecord lidarrQueueR } @Override - public DiscordResponse getShowProfile(SonarrProfile sonarrProfile) { + public DiscordResponse build(ShowProfileResponse showProfileResponse) { EmbedBuilder embedBuilder = new EmbedBuilder(); embedBuilder.setTitle("Profile"); + SonarrProfile sonarrProfile = showProfileResponse.getShowProfile(); embedBuilder.addField("Name", sonarrProfile.getName(), false); embedBuilder.addField("Cutoff", sonarrProfile.getCutoff().getName(), false); embedBuilder.addBlankField(false); @@ -171,9 +179,10 @@ public DiscordResponse getShowProfile(SonarrProfile sonarrProfile) { } @Override - public DiscordResponse getMovieProfile(RadarrProfile radarrProfile) { + public DiscordResponse build(MovieProfileResponse movieProfileResponse) { EmbedBuilder embedBuilder = new EmbedBuilder(); embedBuilder.setTitle("Profile"); + RadarrProfile radarrProfile = movieProfileResponse.getRadarrProfile(); embedBuilder.addField("Name", radarrProfile.getName(), false); embedBuilder.addField("Cutoff", "" + radarrProfile.getCutoff(), false); embedBuilder.addBlankField(false); @@ -190,93 +199,122 @@ public DiscordResponse getMovieProfile(RadarrProfile radarrProfile) { } @Override - public DiscordResponse getNewOrExistingShow(SonarrShow sonarrShow, SonarrShow existingShow, boolean findNew) { + public DiscordResponse build(NewShowResponse newShowResponse) { EmbedBuilder embedBuilder = new EmbedBuilder(); + SonarrShow sonarrShow = newShowResponse.getNewShow(); embedBuilder.setTitle(sonarrShow.getTitle()); embedBuilder.addField("TvdbId", "" + sonarrShow.getTvdbId(), true); - if (findNew) { - embedBuilder.addField(ADD_SHOW_COMMAND_FIELD_PREFIX, SonarrCommands.getAddShowCommandStr(sonarrShow.getTitle(), sonarrShow.getTvdbId()), false); - } else { - embedBuilder.addField("Id", "" + existingShow.getId(), true); - if (existingShow.getSeasons() != null) { - embedBuilder.addField("Number of seasons", "" + existingShow.getSeasons().size(), true); - for (SonarrSeason sonarrSeason : existingShow.getSeasons()) { - embedBuilder.addField("", - "Season#" + sonarrSeason.getSeasonNumber() + - ",Available Epsiodes=" + sonarrSeason.getStatistics().getEpisodeCount() + ",Total Epsiodes=" + sonarrSeason.getStatistics().getTotalEpisodeCount(), false); - } + embedBuilder.addField(ADD_SHOW_COMMAND_FIELD_PREFIX, SonarrCommands.getAddShowCommandStr(sonarrShow.getTitle(), sonarrShow.getTvdbId()), false); + embedBuilder.setImage(sonarrShow.getRemotePoster()); + return new DiscordResponse(embedBuilder.build()); + } + + @Override + public DiscordResponse build(ExistingShowResponse existingShowResponse) { + EmbedBuilder embedBuilder = new EmbedBuilder(); + SonarrShow existingShow = existingShowResponse.getExistingShow(); + embedBuilder.setTitle(existingShow.getTitle()); + embedBuilder.addField("TvdbId", "" + existingShow.getTvdbId(), true); + embedBuilder.addField("Id", "" + existingShow.getId(), true); + if (existingShow.getSeasons() != null) { + embedBuilder.addField("Number of seasons", "" + existingShow.getSeasons().size(), true); + for (SonarrSeason sonarrSeason : existingShow.getSeasons()) { + embedBuilder.addField("", + "Season#" + sonarrSeason.getSeasonNumber() + + ",Available Epsiodes=" + sonarrSeason.getStatistics().getEpisodeCount() + ",Total Epsiodes=" + sonarrSeason.getStatistics().getTotalEpisodeCount(), false); } } - embedBuilder.setImage(sonarrShow.getRemotePoster()); + embedBuilder.setImage(existingShow.getRemotePoster()); return new DiscordResponse(embedBuilder.build()); } @Override - public DiscordResponse getNewOrExistingMovie(RadarrMovie radarrMovie, RadarrMovie existingMovie, boolean findNew) { + public DiscordResponse build(NewMovieResponse newMovieResponse) { EmbedBuilder embedBuilder = new EmbedBuilder(); + RadarrMovie radarrMovie = newMovieResponse.getRadarrMovie(); embedBuilder.setTitle(radarrMovie.getTitle()); embedBuilder.addField("TmdbId", String.valueOf(radarrMovie.getTmdbId()), false); - if (findNew) { - embedBuilder.addField(ADD_MOVIE_COMMAND_FIELD_PREFIX, RadarrCommands.getAddMovieCommandStr(radarrMovie.getTitle(), radarrMovie.getTmdbId()), false); - } else { - embedBuilder.addField("Id", String.valueOf(existingMovie.getId()), false); - embedBuilder.addField("Downloaded", String.valueOf((existingMovie.getSizeOnDisk() > 0)), false); - embedBuilder.addField("Has File", String.valueOf(existingMovie.isHasFile()), false); - } + embedBuilder.addField(ADD_MOVIE_COMMAND_FIELD_PREFIX, RadarrCommands.getAddMovieCommandStr(radarrMovie.getTitle(), radarrMovie.getTmdbId()), false); embedBuilder.setImage(radarrMovie.getRemotePoster()); return new DiscordResponse(embedBuilder.build()); } @Override - public DiscordResponse getNewOrExistingArtist(LidarrArtist lookupArtist, LidarrArtist existingArtist, boolean findNew) { + public DiscordResponse build(ExistingMovieResponse existingMovieResponse) { EmbedBuilder embedBuilder = new EmbedBuilder(); + RadarrMovie radarrMovie = existingMovieResponse.getRadarrMovie(); + embedBuilder.setTitle(radarrMovie.getTitle()); + embedBuilder.addField("TmdbId", String.valueOf(radarrMovie.getTmdbId()), false); + embedBuilder.addField("Id", String.valueOf(radarrMovie.getId()), false); + embedBuilder.addField("Downloaded", String.valueOf((radarrMovie.getSizeOnDisk() > 0)), false); + embedBuilder.addField("Has File", String.valueOf(radarrMovie.isHasFile()), false); + embedBuilder.setImage(radarrMovie.getRemotePoster()); + return new DiscordResponse(embedBuilder.build()); + } + + @Override + public DiscordResponse build(NewMusicArtistResponse newMusicArtistResponse) { + EmbedBuilder embedBuilder = new EmbedBuilder(); + LidarrArtist lookupArtist = newMusicArtistResponse.getLidarrArtist(); String artistDetail = " (" + lookupArtist.getDisambiguation() + ")"; embedBuilder.setTitle(lookupArtist.getArtistName() + (Strings.isEmpty(lookupArtist.getDisambiguation()) ? "" : artistDetail)); - if (findNew) { - embedBuilder.addField(ADD_ARTIST_COMMAND_FIELD_PREFIX, LidarrCommands.getAddArtistCommandStr(lookupArtist.getArtistName(), lookupArtist.getForeignArtistId()), false); - } + embedBuilder.addField(ADD_ARTIST_COMMAND_FIELD_PREFIX, LidarrCommands.getAddArtistCommandStr(lookupArtist.getArtistName(), lookupArtist.getForeignArtistId()), false); embedBuilder.setImage(lookupArtist.getRemotePoster()); return new DiscordResponse(embedBuilder.build()); } @Override - public DiscordResponse getMovieResponse(RadarrMovie radarrMovie) { + public DiscordResponse build(ExistingMusicArtistResponse existingMusicArtistResponse) { EmbedBuilder embedBuilder = new EmbedBuilder(); - embedBuilder.setTitle(radarrMovie.getTitle()); - embedBuilder.addField("TmdbId", "" + radarrMovie.getTmdbId(), false); - embedBuilder.addField(ADD_MOVIE_COMMAND_FIELD_PREFIX, RadarrCommands.getAddMovieCommandStr(radarrMovie.getTitle(), radarrMovie.getTmdbId()), false); - embedBuilder.setImage(radarrMovie.getRemotePoster()); + LidarrArtist lookupArtist = existingMusicArtistResponse.getLidarrArtist(); + String artistDetail = " (" + lookupArtist.getDisambiguation() + ")"; + embedBuilder.setTitle(lookupArtist.getArtistName() + (Strings.isEmpty(lookupArtist.getDisambiguation()) ? "" : artistDetail)); + embedBuilder.setImage(lookupArtist.getRemotePoster()); return new DiscordResponse(embedBuilder.build()); } @Override - public DiscordResponse getDiscoverableMovies(RadarrMovie radarrMovie) { - return getMovieResponse(radarrMovie); + public DiscordResponse build(MovieResponse movieResponse) { + return getMovieResponse(movieResponse.getRadarrMovie()); + } + + @Override + public DiscordResponse build(DiscoverMovieResponse discoverMovieResponse) { + return getMovieResponse(discoverMovieResponse.getRadarrMovie()); } @Override - public DiscordResponse getStatusCommandResponse(Map endpointStatuses) { + public DiscordResponse build(StatusCommandResponse statusCommandResponse) { EmbedBuilder embedBuilder = new EmbedBuilder(); embedBuilder.setTitle("Endpoint Statuses"); - for (Map.Entry endpointStatusEntry : endpointStatuses.entrySet()) { + for (Map.Entry endpointStatusEntry : statusCommandResponse.getEndpoints().entrySet()) { embedBuilder.addField(endpointStatusEntry.getKey(), endpointStatusEntry.getValue() ? "\uD83D\uDFE2" : "\uD83D\uDD34", false); } return new DiscordResponse(embedBuilder.build()); } @Override - public DiscordResponse createErrorMessage(String message) { - return new DiscordResponse(createErrorMessageEmbed(message)); + public DiscordResponse build(ErrorResponse errorResponse) { + return new DiscordResponse(createErrorMessageEmbed(errorResponse.getErrorMessage())); } @Override - public DiscordResponse createInfoMessage(String message) { - return new DiscordResponse(createInfoMessageEmbed(message)); + public DiscordResponse build(InfoResponse infoResponse) { + return new DiscordResponse(createInfoMessageEmbed(infoResponse.getInfoMessage())); } @Override - public DiscordResponse createSuccessMessage(String message) { - return new DiscordResponse(createSuccessMessageEmbed(message)); + public DiscordResponse build(SuccessResponse successResponse) { + return new DiscordResponse(createSuccessMessageEmbed(successResponse.getSuccessMessage())); + } + + private DiscordResponse getMovieResponse(RadarrMovie radarrMovie) { + EmbedBuilder embedBuilder = new EmbedBuilder(); + embedBuilder.setTitle(radarrMovie.getTitle()); + embedBuilder.addField("TmdbId", "" + radarrMovie.getTmdbId(), false); + embedBuilder.addField(ADD_MOVIE_COMMAND_FIELD_PREFIX, RadarrCommands.getAddMovieCommandStr(radarrMovie.getTitle(), radarrMovie.getTmdbId()), false); + embedBuilder.setImage(radarrMovie.getRemotePoster()); + return new DiscordResponse(embedBuilder.build()); } private MessageEmbed createInfoMessageEmbed(String message) { diff --git a/src/main/java/com/botdarr/clients/matrix/MatrixBootstrap.java b/src/main/java/com/botdarr/clients/matrix/MatrixBootstrap.java new file mode 100644 index 0000000..8625f76 --- /dev/null +++ b/src/main/java/com/botdarr/clients/matrix/MatrixBootstrap.java @@ -0,0 +1,46 @@ +package com.botdarr.clients.matrix; + +import com.botdarr.Config; +import com.botdarr.clients.ChatClientResponseBuilder; +import com.botdarr.clients.ChatClientBootstrap; +import com.botdarr.scheduling.Scheduler; +import org.apache.logging.log4j.util.Strings; + +import java.util.Properties; + +public class MatrixBootstrap extends ChatClientBootstrap { + + @Override + public void init() throws Exception { + MatrixChatClient chatClient = new MatrixChatClient(); + ChatClientResponseBuilder responseChatClientResponseBuilder = new MatrixResponseBuilder(); + ChatClientBootstrap.ApisAndCommandConfig config = buildConfig(); + initScheduling(chatClient, responseChatClientResponseBuilder, config.getApis()); + chatClient.addListener((roomId, sender, content) -> { + Scheduler.getScheduler().executeCommand(() -> { + runAndProcessCommands(content, sender, responseChatClientResponseBuilder, chatClientResponse -> { + chatClient.sendMessage(chatClientResponse, roomId); + }); + return null; + }); + }); + chatClient.listen(); + } + + @Override + public boolean isConfigured(Properties properties) { + return + !Strings.isBlank(properties.getProperty(Config.Constants.MATRIX_USERNAME)) && + !Strings.isBlank(properties.getProperty(Config.Constants.MATRIX_PASSWORD)) && + !Strings.isBlank(properties.getProperty(Config.Constants.MATRIX_ROOM)) && + !Strings.isBlank(properties.getProperty(Config.Constants.MATRIX_HOME_SERVER)); + } + + @Override + public void validatePrefix(String configuredPrefix) { + super.validatePrefix(configuredPrefix); + if (configuredPrefix.equals("/")) { + throw new RuntimeException("Cannot use / command prefix in matrix since /help command is used by element by default"); + } + } +} diff --git a/src/main/java/com/botdarr/clients/matrix/MatrixChatClient.java b/src/main/java/com/botdarr/clients/matrix/MatrixChatClient.java index 8f1d385..86fc417 100644 --- a/src/main/java/com/botdarr/clients/matrix/MatrixChatClient.java +++ b/src/main/java/com/botdarr/clients/matrix/MatrixChatClient.java @@ -8,7 +8,6 @@ import com.botdarr.clients.matrix.transactions.sync.MatrixSyncJoinRoom; import com.botdarr.clients.matrix.transactions.sync.MatrixSyncResponse; import com.botdarr.clients.matrix.transactions.sync.MatrixSyncRooms; -import com.botdarr.commands.CommandResponse; import com.botdarr.connections.ConnectionHelper; import com.google.gson.Gson; import org.apache.http.client.methods.*; @@ -58,17 +57,8 @@ public void sendToConfiguredChannels(List chatClientResponses) { } } - public void sendMessage(CommandResponse commandResponse, String roomId) { - if (commandResponse.getSingleChatClientResponse() != null) { - sendMatrixResponse(commandResponse.getSingleChatClientResponse(), roomId); - - } else if (commandResponse.getMultipleChatClientResponses() != null) { - for (MatrixResponse response : commandResponse.getMultipleChatClientResponses()) { - sendMatrixResponse(response, roomId); - } - } else { - //TODO: err - } + public void sendMessage(MatrixResponse response, String roomId) { + sendMatrixResponse(response, roomId); } public void addListener(MatrixMessageListener listener) { diff --git a/src/main/java/com/botdarr/clients/matrix/MatrixResponseBuilder.java b/src/main/java/com/botdarr/clients/matrix/MatrixResponseBuilder.java index 95c61d4..3efa08f 100644 --- a/src/main/java/com/botdarr/clients/matrix/MatrixResponseBuilder.java +++ b/src/main/java/com/botdarr/clients/matrix/MatrixResponseBuilder.java @@ -2,12 +2,14 @@ import com.botdarr.Config; import com.botdarr.api.lidarr.LidarrArtist; +import com.botdarr.api.lidarr.LidarrCommands; import com.botdarr.api.lidarr.LidarrQueueRecord; import com.botdarr.api.lidarr.LidarrQueueStatusMessage; import com.botdarr.api.radarr.*; import com.botdarr.api.sonarr.*; import com.botdarr.clients.ChatClientResponseBuilder; import com.botdarr.commands.*; +import com.botdarr.commands.responses.*; import com.botdarr.utilities.ListUtils; import org.apache.logging.log4j.util.Strings; @@ -22,7 +24,7 @@ public class MatrixResponseBuilder implements ChatClientResponseBuilder { @Override - public MatrixResponse getHelpResponse() { + public MatrixResponse build(HelpResponse helpResponse) { try { MatrixResponse matrixResponse = new MatrixResponse(); matrixResponse.addContent("Version: " + ChatClientResponseBuilder.getVersion() + ""); @@ -55,41 +57,44 @@ public MatrixResponse getHelpResponse() { } @Override - public MatrixResponse getMusicHelpResponse(List lidarCommands) { - return getListOfCommands(lidarCommands); + public MatrixResponse build(MusicHelpResponse musicHelpResponse) { + return getListOfCommands(musicHelpResponse.getLidarrCommands()); } @Override - public MatrixResponse getMoviesHelpResponse(List radarrCommands) { - return getListOfCommands(radarrCommands); + public MatrixResponse build(MoviesHelpResponse moviesHelpResponse) { + return getListOfCommands(moviesHelpResponse.getRadarrCommands()); } @Override - public MatrixResponse getShowsHelpResponse(List sonarrCommands) { - return getListOfCommands(sonarrCommands); + public MatrixResponse build(ShowsHelpResponse showsHelpResponse) { + return getListOfCommands(showsHelpResponse.getSonarrCommands()); } @Override - public MatrixResponse getShowResponse(SonarrShow show) { + public MatrixResponse build(ShowResponse showResponse) { + SonarrShow show = showResponse.getShow(); MatrixResponse matrixResponse = new MatrixResponse(); matrixResponse.addContent("Title - " + show.getTitle()); - matrixResponse.addContent("TvdbId - " + String.valueOf(show.getTvdbId())); + matrixResponse.addContent("TvdbId - " + show.getTvdbId()); matrixResponse.addContent("" + ADD_SHOW_COMMAND_FIELD_PREFIX + " - " + SonarrCommands.getAddShowCommandStr(show.getTitle(), show.getTvdbId())); matrixResponse.addImage(show.getRemotePoster()); return matrixResponse; } @Override - public MatrixResponse getArtistResponse(LidarrArtist lidarrArtist) { + public MatrixResponse build(MusicArtistResponse musicArtistResponse) { + LidarrArtist lidarrArtist = musicArtistResponse.getArtist(); MatrixResponse matrixResponse = new MatrixResponse(); matrixResponse.addContent("Artist Name - " + lidarrArtist.getArtistName()); - matrixResponse.addContent("Id - " + String.valueOf(lidarrArtist.getForeignArtistId())); + matrixResponse.addContent("Id - " + lidarrArtist.getForeignArtistId()); matrixResponse.addContent("" + ADD_ARTIST_COMMAND_FIELD_PREFIX + " - " + LidarrCommands.getAddArtistCommandStr(lidarrArtist.getArtistName(), lidarrArtist.getForeignArtistId())); return matrixResponse; } @Override - public MatrixResponse getMovieResponse(RadarrMovie radarrMovie) { + public MatrixResponse build(MovieResponse movieResponse) { + RadarrMovie radarrMovie = movieResponse.getRadarrMovie(); MatrixResponse matrixResponse = new MatrixResponse(); matrixResponse.addContent("Movie Title - " + radarrMovie.getTitle()); matrixResponse.addContent("TmdbId - " + radarrMovie.getTmdbId()); @@ -98,21 +103,22 @@ public MatrixResponse getMovieResponse(RadarrMovie radarrMovie) { } @Override - public MatrixResponse getShowDownloadResponses(SonarrQueue sonarrShow) { + public MatrixResponse build(ShowDownloadResponse showDownloadResponse) { + SonarrQueue sonarrQueue = showDownloadResponse.getShowQueue(); MatrixResponse matrixResponse = new MatrixResponse(); - SonarQueueEpisode episode = sonarrShow.getEpisode(); - matrixResponse.addContent("Title - " + sonarrShow.getSonarrQueueShow().getTitle()); + SonarQueueEpisode episode = sonarrQueue.getEpisode(); + matrixResponse.addContent("Title - " + sonarrQueue.getSonarrQueueShow().getTitle()); matrixResponse.addContent("Season/Episode - " + "S" + episode.getSeasonNumber() + "E" + episode.getEpisodeNumber()); - matrixResponse.addContent("Quality - " + sonarrShow.getQuality().getQuality().getName()); - matrixResponse.addContent("Status - " + sonarrShow.getStatus()); - matrixResponse.addContent("Time Left - " + (sonarrShow.getTimeleft() == null ? "unknown" : sonarrShow.getTimeleft()) + ""); + matrixResponse.addContent("Quality - " + sonarrQueue.getQuality().getQuality().getName()); + matrixResponse.addContent("Status - " + sonarrQueue.getStatus()); + matrixResponse.addContent("Time Left - " + (sonarrQueue.getTimeleft() == null ? "unknown" : sonarrQueue.getTimeleft()) + ""); String overview = episode.getTitle() + ": " + episode.getOverview(); if (overview.length() > 1024) { overview = overview.substring(0, 1024); } matrixResponse.addContent("Overview - " + overview); - if (sonarrShow.getStatusMessages() != null) { - for (SonarrQueueStatusMessages statusMessage : sonarrShow.getStatusMessages()) { + if (sonarrQueue.getStatusMessages() != null) { + for (SonarrQueueStatusMessages statusMessage : sonarrQueue.getStatusMessages()) { for (String message : statusMessage.getMessages()) { matrixResponse.addContent("Download message - " + message); } @@ -122,7 +128,8 @@ public MatrixResponse getShowDownloadResponses(SonarrQueue sonarrShow) { } @Override - public MatrixResponse getMovieDownloadResponses(RadarrQueue radarrQueue) { + public MatrixResponse build(MovieDownloadResponse movieDownloadResponse) { + RadarrQueue radarrQueue = movieDownloadResponse.getRadarrQueue(); MatrixResponse matrixResponse = new MatrixResponse(); matrixResponse.addContent("Title - " + radarrQueue.getTitle()); matrixResponse.addContent("Quality - " + radarrQueue.getQuality().getQuality().getName()); @@ -139,7 +146,8 @@ public MatrixResponse getMovieDownloadResponses(RadarrQueue radarrQueue) { } @Override - public MatrixResponse getArtistDownloadResponses(LidarrQueueRecord lidarrQueue) { + public MatrixResponse build(MusicArtistDownloadResponse musicArtistDownloadResponse) { + LidarrQueueRecord lidarrQueue = musicArtistDownloadResponse.getQueueRecord(); MatrixResponse matrixResponse = new MatrixResponse(); matrixResponse.addContent("Title - " + lidarrQueue.getTitle()); matrixResponse.addContent("Time Left - " + (lidarrQueue.getTimeleft() == null ? "unknown" : lidarrQueue.getTimeleft()) + ""); @@ -155,28 +163,29 @@ public MatrixResponse getArtistDownloadResponses(LidarrQueueRecord lidarrQueue) } @Override - public MatrixResponse createErrorMessage(String message) { + public MatrixResponse build(ErrorResponse errorResponse) { MatrixResponse matrixResponse = new MatrixResponse(); - matrixResponse.addContent("" + message + ""); + matrixResponse.addContent("" + errorResponse.getErrorMessage() + ""); return matrixResponse; } @Override - public MatrixResponse createInfoMessage(String message) { + public MatrixResponse build(InfoResponse infoResponse) { MatrixResponse matrixResponse = new MatrixResponse(); - matrixResponse.addContent("" + message + ""); + matrixResponse.addContent("" + infoResponse.getInfoMessage() + ""); return matrixResponse; } @Override - public MatrixResponse createSuccessMessage(String message) { + public MatrixResponse build(SuccessResponse successResponse) { MatrixResponse matrixResponse = new MatrixResponse(); - matrixResponse.addContent("" + message + ""); + matrixResponse.addContent("" + successResponse.getSuccessMessage() + ""); return matrixResponse; } @Override - public MatrixResponse getShowProfile(SonarrProfile sonarrProfile) { + public MatrixResponse build(ShowProfileResponse showProfileResponse) { + SonarrProfile sonarrProfile = showProfileResponse.getShowProfile(); MatrixResponse matrixResponse = new MatrixResponse(); matrixResponse.addContent("Profile"); matrixResponse.addContent("Name - " + sonarrProfile.getName()); @@ -191,7 +200,8 @@ public MatrixResponse getShowProfile(SonarrProfile sonarrProfile) { } @Override - public MatrixResponse getMovieProfile(RadarrProfile radarrProfile) { + public MatrixResponse build(MovieProfileResponse movieProfileResponse) { + RadarrProfile radarrProfile = movieProfileResponse.getRadarrProfile(); MatrixResponse matrixResponse = new MatrixResponse(); matrixResponse.addContent("Profile"); matrixResponse.addContent("Name - " + radarrProfile.getName()); @@ -206,58 +216,84 @@ public MatrixResponse getMovieProfile(RadarrProfile radarrProfile) { } @Override - public MatrixResponse getNewOrExistingShow(SonarrShow sonarrShow, SonarrShow existingShow, boolean findNew) { + public MatrixResponse build(NewShowResponse newShowResponse) { + SonarrShow sonarrShow = newShowResponse.getNewShow(); MatrixResponse matrixResponse = new MatrixResponse(); matrixResponse.addContent("Title - " + sonarrShow.getTitle()); matrixResponse.addContent("TvdbId - " + sonarrShow.getTvdbId()); - if (findNew) { - matrixResponse.addContent("" + ADD_SHOW_COMMAND_FIELD_PREFIX + " - " + SonarrCommands.getAddShowCommandStr(sonarrShow.getTitle(), sonarrShow.getTvdbId())); - } else { - matrixResponse.addContent("Id - " + existingShow.getId()); - if (existingShow.getSeasons() != null) { - matrixResponse.addContent("Number of seasons - " + existingShow.getSeasons().size()); - for (SonarrSeason sonarrSeason : existingShow.getSeasons()) { - matrixResponse.addContent( - "Season#" + sonarrSeason.getSeasonNumber() + - ",Available Epsiodes=" + sonarrSeason.getStatistics().getEpisodeCount() + - ",Total Epsiodes=" + sonarrSeason.getStatistics().getTotalEpisodeCount()); - } - } - } + matrixResponse.addContent("" + ADD_SHOW_COMMAND_FIELD_PREFIX + " - " + SonarrCommands.getAddShowCommandStr(sonarrShow.getTitle(), sonarrShow.getTvdbId())); matrixResponse.addImage(sonarrShow.getRemotePoster()); return matrixResponse; } @Override - public MatrixResponse getNewOrExistingMovie(RadarrMovie lookupMovie, RadarrMovie existingMovie, boolean findNew) { + public MatrixResponse build(ExistingShowResponse existingShowResponse) { + SonarrShow existingShow = existingShowResponse.getExistingShow(); MatrixResponse matrixResponse = new MatrixResponse(); - matrixResponse.addContent("Title - " + lookupMovie.getTitle()); - matrixResponse.addContent("TmdbId - " + String.valueOf(lookupMovie.getTmdbId())); - if (findNew) { - matrixResponse.addContent("" + ADD_MOVIE_COMMAND_FIELD_PREFIX + " - " + RadarrCommands.getAddMovieCommandStr(lookupMovie.getTitle(), lookupMovie.getTmdbId())); - } else { - matrixResponse.addContent("Id - " + existingMovie.getId()); - matrixResponse.addContent("Downloaded - " + String.valueOf((existingMovie.getSizeOnDisk() > 0))); - matrixResponse.addContent("Has File - " + String.valueOf(existingMovie.isHasFile())); + matrixResponse.addContent("Title - " + existingShow.getTitle()); + matrixResponse.addContent("TvdbId - " + existingShow.getTvdbId()); + matrixResponse.addContent("Id - " + existingShow.getId()); + if (existingShow.getSeasons() != null) { + matrixResponse.addContent("Number of seasons - " + existingShow.getSeasons().size()); + for (SonarrSeason sonarrSeason : existingShow.getSeasons()) { + matrixResponse.addContent( + "Season#" + sonarrSeason.getSeasonNumber() + + ",Available Epsiodes=" + sonarrSeason.getStatistics().getEpisodeCount() + + ",Total Epsiodes=" + sonarrSeason.getStatistics().getTotalEpisodeCount()); + } } - matrixResponse.addImage(lookupMovie.getRemotePoster()); + matrixResponse.addImage(existingShow.getRemotePoster()); return matrixResponse; } @Override - public MatrixResponse getNewOrExistingArtist(LidarrArtist lookupArtist, LidarrArtist existingArtist, boolean findNew) { + public MatrixResponse build(NewMovieResponse newMovieResponse) { + RadarrMovie radarrMovie = newMovieResponse.getRadarrMovie(); MatrixResponse matrixResponse = new MatrixResponse(); - String artistDetail = " (" + lookupArtist.getDisambiguation() + ")"; - matrixResponse.addContent("Title - " + (lookupArtist.getArtistName() + (Strings.isEmpty(lookupArtist.getDisambiguation()) ? "" : artistDetail))); - if (findNew) { - matrixResponse.addContent("" + ADD_ARTIST_COMMAND_FIELD_PREFIX + " - " + LidarrCommands.getAddArtistCommandStr(lookupArtist.getArtistName(), lookupArtist.getForeignArtistId())); - } - matrixResponse.addImage(lookupArtist.getRemotePoster()); + matrixResponse.addContent("Title - " + radarrMovie.getTitle()); + matrixResponse.addContent("TmdbId - " + radarrMovie.getTmdbId()); + matrixResponse.addContent("" + ADD_MOVIE_COMMAND_FIELD_PREFIX + " - " + RadarrCommands.getAddMovieCommandStr(radarrMovie.getTitle(), radarrMovie.getTmdbId())); + matrixResponse.addImage(radarrMovie.getRemotePoster()); + return matrixResponse; + } + + @Override + public MatrixResponse build(ExistingMovieResponse existingMovieResponse) { + RadarrMovie radarrMovie = existingMovieResponse.getRadarrMovie(); + MatrixResponse matrixResponse = new MatrixResponse(); + matrixResponse.addContent("Title - " + radarrMovie.getTitle()); + matrixResponse.addContent("TmdbId - " + radarrMovie.getTmdbId()); + matrixResponse.addContent("Id - " + radarrMovie.getId()); + matrixResponse.addContent("Downloaded - " + (radarrMovie.getSizeOnDisk() > 0)); + matrixResponse.addContent("Has File - " + radarrMovie.isHasFile()); + matrixResponse.addImage(radarrMovie.getRemotePoster()); + return matrixResponse; + } + + @Override + public MatrixResponse build(NewMusicArtistResponse newMusicArtistResponse) { + LidarrArtist lidarrArtist = newMusicArtistResponse.getLidarrArtist(); + MatrixResponse matrixResponse = new MatrixResponse(); + String artistDetail = " (" + lidarrArtist.getDisambiguation() + ")"; + matrixResponse.addContent("Title - " + (lidarrArtist.getArtistName() + (Strings.isEmpty(lidarrArtist.getDisambiguation()) ? "" : artistDetail))); + matrixResponse.addContent("" + ADD_ARTIST_COMMAND_FIELD_PREFIX + " - " + LidarrCommands.getAddArtistCommandStr(lidarrArtist.getArtistName(), lidarrArtist.getForeignArtistId())); + matrixResponse.addImage(lidarrArtist.getRemotePoster()); + return matrixResponse; + } + + @Override + public MatrixResponse build(ExistingMusicArtistResponse existingMusicArtistResponse) { + LidarrArtist lidarrArtist = existingMusicArtistResponse.getLidarrArtist(); + MatrixResponse matrixResponse = new MatrixResponse(); + String artistDetail = " (" + lidarrArtist.getDisambiguation() + ")"; + matrixResponse.addContent("Title - " + (lidarrArtist.getArtistName() + (Strings.isEmpty(lidarrArtist.getDisambiguation()) ? "" : artistDetail))); + matrixResponse.addImage(lidarrArtist.getRemotePoster()); return matrixResponse; } @Override - public MatrixResponse getDiscoverableMovies(RadarrMovie radarrMovie) { + public MatrixResponse build(DiscoverMovieResponse discoverMovieResponse) { + RadarrMovie radarrMovie = discoverMovieResponse.getRadarrMovie(); MatrixResponse matrixResponse = new MatrixResponse(); matrixResponse.addContent("Title - " + radarrMovie.getTitle()); matrixResponse.addContent("TmdbId - " + radarrMovie.getTmdbId()); @@ -269,11 +305,11 @@ public MatrixResponse getDiscoverableMovies(RadarrMovie radarrMovie) { } @Override - public MatrixResponse getStatusCommandResponse(Map endpointStatuses) { + public MatrixResponse build(StatusCommandResponse statusCommandResponse) { MatrixResponse matrixResponse = new MatrixResponse(); matrixResponse.addRawContent(""); matrixResponse.addRawContent(""); - for (Map.Entry endpointStatusEntry : endpointStatuses.entrySet()) { + for (Map.Entry endpointStatusEntry : statusCommandResponse.getEndpoints().entrySet()) { matrixResponse.addRawContent(""); matrixResponse.addRawContent("
EndpointStatuses
"); matrixResponse.addRawContent(endpointStatusEntry.getKey()); diff --git a/src/main/java/com/botdarr/clients/slack/SlackBootstrap.java b/src/main/java/com/botdarr/clients/slack/SlackBootstrap.java new file mode 100644 index 0000000..5a21958 --- /dev/null +++ b/src/main/java/com/botdarr/clients/slack/SlackBootstrap.java @@ -0,0 +1,117 @@ +package com.botdarr.clients.slack; + +import com.botdarr.Config; +import com.botdarr.clients.ChatClientBootstrap; +import com.botdarr.clients.ChatClientResponseBuilder; +import com.botdarr.scheduling.Scheduler; +import com.github.seratch.jslack.Slack; +import com.github.seratch.jslack.api.model.Message; +import com.github.seratch.jslack.api.model.User; +import com.github.seratch.jslack.api.model.block.LayoutBlock; +import com.github.seratch.jslack.api.model.block.SectionBlock; +import com.github.seratch.jslack.api.model.block.composition.MarkdownTextObject; +import com.github.seratch.jslack.api.rtm.RTMMessageHandler; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.util.Strings; + +import java.util.List; +import java.util.Properties; + +import static com.botdarr.api.radarr.RadarrApi.ADD_MOVIE_COMMAND_FIELD_PREFIX; +import static com.botdarr.api.sonarr.SonarrApi.ADD_SHOW_COMMAND_FIELD_PREFIX; + +public class SlackBootstrap extends ChatClientBootstrap { + + @Override + public void init() throws Exception { + JsonParser jsonParser = new JsonParser(); + SlackChatClient slackChatClient = new SlackChatClient(Slack.getInstance().rtm(Config.getProperty(Config.Constants.SLACK_BOT_TOKEN))); + + ChatClientResponseBuilder responseChatClientResponseBuilder = new SlackResponseBuilder(); + ChatClientBootstrap.ApisAndCommandConfig config = buildConfig(); + + slackChatClient.addMessageHandler(new RTMMessageHandler() { + @Override + public void handle(String message) { + JsonObject json = jsonParser.parse(message).getAsJsonObject(); + SlackMessage slackMessage = new Gson().fromJson(json, SlackMessage.class); + if (slackMessage.getType() != null) { + if (slackMessage.getType().equalsIgnoreCase("message")) { + User user = slackChatClient.getUser(slackMessage.getUserId()); + if (user == null) { + LOGGER.debug("Could not find user for slack message " + slackMessage); + return; + } + handleCommand(slackMessage.getText(), user.getName(), slackMessage.getChannel()); + } else if (slackMessage.getType().equalsIgnoreCase("reaction_added") && slackMessage.getReaction().equalsIgnoreCase("+1")) { + //thumbsup = +1 in slack for some reason + try { + //search public channels first + List conversationMessages = slackChatClient.getPublicMessages(slackMessage); + if (conversationMessages == null || conversationMessages.isEmpty()) { + //check private channels if necessary + conversationMessages = slackChatClient.getPrivateMessages(slackMessage); + } + if (conversationMessages != null) { + conversationMessageLoop: + for (com.github.seratch.jslack.api.model.Message conversationMessage : conversationMessages) { + for (LayoutBlock layoutBlock : conversationMessage.getBlocks()) { + if (layoutBlock.getType().equals("section")) { + SectionBlock sectionBlock = (SectionBlock) layoutBlock; + if (sectionBlock.getText() instanceof MarkdownTextObject) { + String markdownText = ((MarkdownTextObject) sectionBlock.getText()).getText(); + if (markdownText != null && + (markdownText.startsWith(ADD_MOVIE_COMMAND_FIELD_PREFIX) || markdownText.startsWith(ADD_SHOW_COMMAND_FIELD_PREFIX))) { + String postProcessedCommand = markdownText + .replaceAll(ADD_MOVIE_COMMAND_FIELD_PREFIX + " - ", "") + .replaceAll(ADD_SHOW_COMMAND_FIELD_PREFIX + " - ", ""); + handleCommand(postProcessedCommand, slackChatClient.getUser(slackMessage.getUserId()).getName(), slackMessage.getItem().getChannel()); + break conversationMessageLoop; + } + } + } + } + } + } + } catch (Exception e) { + LogManager.getLogger("com.botdarr.clients.slack").error("Error fetching conversation history", e); + } + } + } + LogManager.getLogger("com.botdarr.clients.slack").debug(json); + } + + private void handleCommand(String text, String userId, String channel) { + Scheduler.getScheduler().executeCommand(() -> { + runAndProcessCommands(text, userId, responseChatClientResponseBuilder, chatClientResponse -> { + slackChatClient.sendMessage(chatClientResponse, channel); + }); + return null; + }); + } + }); + + //start the scheduler threads that send notifications and cache data periodically + initScheduling(slackChatClient, responseChatClientResponseBuilder, config.getApis()); + + slackChatClient.connect(); + } + + @Override + public boolean isConfigured(Properties properties) { + return + !Strings.isBlank(properties.getProperty(Config.Constants.SLACK_BOT_TOKEN)) && + !Strings.isBlank(properties.getProperty(Config.Constants.SLACK_CHANNELS)); + } + + @Override + public void validatePrefix(String configuredPrefix) { + super.validatePrefix(configuredPrefix); + if (configuredPrefix.equals("/")) { + throw new RuntimeException("Cannot use / command prefix in slack since /help command was deprecated by slack"); + } + } +} diff --git a/src/main/java/com/botdarr/clients/slack/SlackChatClient.java b/src/main/java/com/botdarr/clients/slack/SlackChatClient.java index a21d63e..6bf8f63 100644 --- a/src/main/java/com/botdarr/clients/slack/SlackChatClient.java +++ b/src/main/java/com/botdarr/clients/slack/SlackChatClient.java @@ -2,7 +2,6 @@ import com.botdarr.Config; import com.botdarr.clients.ChatClient; -import com.botdarr.commands.CommandResponse; import com.github.seratch.jslack.Slack; import com.github.seratch.jslack.api.methods.SlackApiException; import com.github.seratch.jslack.api.methods.request.chat.ChatPostMessageRequest; @@ -90,16 +89,6 @@ public void sendMessage(List chatClientResponses, String channel) }, channel); } - public void sendMessage(CommandResponse commandResponse, String targetChannel) { - if (commandResponse.getSingleChatClientResponse() != null) { - sendMessage(commandResponse.getSingleChatClientResponse(), targetChannel); - } else if (commandResponse.getMultipleChatClientResponses() != null) { - sendMessage(commandResponse.getMultipleChatClientResponses(), targetChannel); - } else { - //TODO: err - } - } - public List getPublicMessages(SlackMessage slackMessage) throws IOException, SlackApiException { return Slack.getInstance().methods().conversationsHistory(ConversationsHistoryRequest.builder() .token(Config.getProperty(Config.Constants.SLACK_USER_TOKEN)) diff --git a/src/main/java/com/botdarr/clients/slack/SlackResponseBuilder.java b/src/main/java/com/botdarr/clients/slack/SlackResponseBuilder.java index 6332030..a715bf4 100644 --- a/src/main/java/com/botdarr/clients/slack/SlackResponseBuilder.java +++ b/src/main/java/com/botdarr/clients/slack/SlackResponseBuilder.java @@ -2,26 +2,23 @@ import com.botdarr.Config; import com.botdarr.api.lidarr.LidarrArtist; +import com.botdarr.api.lidarr.LidarrCommands; import com.botdarr.api.lidarr.LidarrQueueRecord; import com.botdarr.api.lidarr.LidarrQueueStatusMessage; import com.botdarr.api.radarr.*; import com.botdarr.api.sonarr.*; import com.botdarr.clients.ChatClientResponseBuilder; import com.botdarr.commands.*; +import com.botdarr.commands.responses.*; import com.botdarr.utilities.ListUtils; -import com.github.seratch.jslack.api.model.block.ContextBlock; -import com.github.seratch.jslack.api.model.block.ContextBlockElement; -import com.github.seratch.jslack.api.model.block.ImageBlock; -import com.github.seratch.jslack.api.model.block.SectionBlock; +import com.github.seratch.jslack.api.model.block.*; import com.github.seratch.jslack.api.model.block.composition.MarkdownTextObject; import com.github.seratch.jslack.api.model.block.composition.PlainTextObject; +import com.github.seratch.jslack.api.model.block.element.ButtonElement; import org.apache.logging.log4j.util.Strings; import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.util.*; import static com.botdarr.api.lidarr.LidarrApi.ADD_ARTIST_COMMAND_FIELD_PREFIX; import static com.botdarr.api.radarr.RadarrApi.ADD_MOVIE_COMMAND_FIELD_PREFIX; @@ -32,14 +29,21 @@ public class SlackResponseBuilder implements ChatClientResponseBuilder { @Override - public SlackResponse getHelpResponse() { + public SlackResponse build(HelpResponse helpResponse) { SlackResponse slackResponse = new SlackResponse(); try { slackResponse.addBlock(SectionBlock.builder() - .fields(Arrays.asList(PlainTextObject.builder().emoji(true).text("Version: " + ChatClientResponseBuilder.getVersion()).build())) + .fields(Collections.singletonList(PlainTextObject.builder().emoji(true).text("Version: " + ChatClientResponseBuilder.getVersion()).build())) .text(MarkdownTextObject.builder().text("*Commands*").build()) .build()); + slackResponse.addBlock( + ActionsBlock.builder().elements( + Collections.singletonList( + ButtonElement.builder().text( + PlainTextObject.builder().text("hello").build()) + .build())) + .build()); boolean radarrEnabled = Config.isRadarrEnabled(); boolean sonarrEnabled = Config.isSonarrEnabled(); boolean lidarrEnabled = Config.isLidarrEnabled(); @@ -78,22 +82,23 @@ public SlackResponse getHelpResponse() { } @Override - public SlackResponse getMusicHelpResponse(List lidarCommands) { - return getListOfCommands(lidarCommands); + public SlackResponse build(MusicHelpResponse musicHelpResponse) { + return getListOfCommands(musicHelpResponse.getLidarrCommands()); } @Override - public SlackResponse getMoviesHelpResponse(List radarrCommands) { - return getListOfCommands(radarrCommands); + public SlackResponse build(MoviesHelpResponse moviesHelpResponse) { + return getListOfCommands(moviesHelpResponse.getRadarrCommands()); } @Override - public SlackResponse getShowsHelpResponse(List sonarrCommands) { - return getListOfCommands(sonarrCommands); + public SlackResponse build(ShowsHelpResponse showsHelpResponse) { + return getListOfCommands(showsHelpResponse.getSonarrCommands()); } @Override - public SlackResponse getShowResponse(SonarrShow show) { + public SlackResponse build(ShowResponse showResponse) { + SonarrShow show = showResponse.getShow(); SlackResponse slackResponse = new SlackResponse(); slackResponse.addBlock(SectionBlock.builder() .text(MarkdownTextObject.builder().text("*Title* - " + show.getTitle()).build()) @@ -116,7 +121,8 @@ public SlackResponse getShowResponse(SonarrShow show) { } @Override - public SlackResponse getArtistResponse(LidarrArtist lidarrArtist) { + public SlackResponse build(MusicArtistResponse musicArtistResponse) { + LidarrArtist lidarrArtist = musicArtistResponse.getArtist(); SlackResponse slackResponse = new SlackResponse(); slackResponse.addBlock(SectionBlock.builder() .text(MarkdownTextObject.builder().text("*Artist Name* - " + lidarrArtist.getArtistName()).build()) @@ -139,7 +145,8 @@ public SlackResponse getArtistResponse(LidarrArtist lidarrArtist) { } @Override - public SlackResponse getShowDownloadResponses(SonarrQueue showQueue) { + public SlackResponse build(ShowDownloadResponse showDownloadResponse) { + SonarrQueue showQueue = showDownloadResponse.getShowQueue(); SonarQueueEpisode episode = showQueue.getEpisode(); SlackResponse slackResponse = new SlackResponse(); slackResponse.addBlock(SectionBlock.builder() @@ -181,7 +188,8 @@ public SlackResponse getShowDownloadResponses(SonarrQueue showQueue) { } @Override - public SlackResponse getMovieDownloadResponses(RadarrQueue radarrQueue) { + public SlackResponse build(MovieDownloadResponse movieDownloadResponse) { + RadarrQueue radarrQueue = movieDownloadResponse.getRadarrQueue(); SlackResponse slackResponse = new SlackResponse(); slackResponse.addBlock(SectionBlock.builder() .text(MarkdownTextObject.builder().text("*Title* - " + radarrQueue.getTitle()).build()) @@ -212,7 +220,8 @@ public SlackResponse getMovieDownloadResponses(RadarrQueue radarrQueue) { } @Override - public SlackResponse getArtistDownloadResponses(LidarrQueueRecord lidarrQueueRecord) { + public SlackResponse build(MusicArtistDownloadResponse musicArtistDownloadResponse) { + LidarrQueueRecord lidarrQueueRecord = musicArtistDownloadResponse.getQueueRecord(); SlackResponse slackResponse = new SlackResponse(); slackResponse.addBlock(SectionBlock.builder() .text(MarkdownTextObject.builder().text("*Title* - " + lidarrQueueRecord.getTitle()).build()) @@ -240,34 +249,35 @@ public SlackResponse getArtistDownloadResponses(LidarrQueueRecord lidarrQueueRec } @Override - public SlackResponse createErrorMessage(String message) { + public SlackResponse build(ErrorResponse errorResponse) { SlackResponse slackResponse = new SlackResponse(); slackResponse.addBlock(SectionBlock.builder() - .text(MarkdownTextObject.builder().text("*Error* - " + message).build()) + .text(MarkdownTextObject.builder().text("*Error* - " + errorResponse.getErrorMessage()).build()) .build()); return slackResponse; } @Override - public SlackResponse createInfoMessage(String message) { + public SlackResponse build(InfoResponse infoResponse) { SlackResponse slackResponse = new SlackResponse(); slackResponse.addBlock(SectionBlock.builder() - .text(MarkdownTextObject.builder().text("*Info* - " + message).build()) + .text(MarkdownTextObject.builder().text("*Info* - " + infoResponse.getInfoMessage()).build()) .build()); return slackResponse; } @Override - public SlackResponse createSuccessMessage(String message) { + public SlackResponse build(SuccessResponse successResponse) { SlackResponse slackResponse = new SlackResponse(); slackResponse.addBlock(SectionBlock.builder() - .text(MarkdownTextObject.builder().text("*Success* - " + message).build()) + .text(MarkdownTextObject.builder().text("*Success* - " + successResponse.getSuccessMessage()).build()) .build()); return slackResponse; } @Override - public SlackResponse getShowProfile(SonarrProfile sonarrProfile) { + public SlackResponse build(ShowProfileResponse showProfileResponse) { + SonarrProfile sonarrProfile = showProfileResponse.getShowProfile(); SlackResponse slackResponse = new SlackResponse(); slackResponse.addBlock(SectionBlock.builder() .text(MarkdownTextObject.builder().text("*Profile*").build()) @@ -295,7 +305,8 @@ public SlackResponse getShowProfile(SonarrProfile sonarrProfile) { } @Override - public SlackResponse getMovieProfile(RadarrProfile radarrProfile) { + public SlackResponse build(MovieProfileResponse movieProfileResponse) { + RadarrProfile radarrProfile = movieProfileResponse.getRadarrProfile(); SlackResponse slackResponse = new SlackResponse(); slackResponse.addBlock(SectionBlock.builder() .text(MarkdownTextObject.builder().text("*Profile*").build()) @@ -323,7 +334,8 @@ public SlackResponse getMovieProfile(RadarrProfile radarrProfile) { } @Override - public SlackResponse getNewOrExistingShow(SonarrShow sonarrShow, SonarrShow existingShow, boolean findNew) { + public SlackResponse build(NewShowResponse newShowResponse) { + SonarrShow sonarrShow = newShowResponse.getNewShow(); SlackResponse slackResponse = new SlackResponse(); slackResponse.addBlock(SectionBlock.builder() .text(MarkdownTextObject.builder().text("*Title* - " + sonarrShow.getTitle()).build()) @@ -331,31 +343,9 @@ public SlackResponse getNewOrExistingShow(SonarrShow sonarrShow, SonarrShow exis slackResponse.addBlock(SectionBlock.builder() .text(MarkdownTextObject.builder().text("TvdbId - " + sonarrShow.getTvdbId()).build()) .build()); - if (findNew) { - slackResponse.addBlock(SectionBlock.builder() - .text(MarkdownTextObject.builder().text(ADD_SHOW_COMMAND_FIELD_PREFIX + " - " + SonarrCommands.getAddShowCommandStr(sonarrShow.getTitle(), sonarrShow.getTvdbId())).build()) - .build()); - } else { - slackResponse.addBlock(SectionBlock.builder() - .text(MarkdownTextObject.builder().text("Id - " + existingShow.getId()).build()) - .build()); - if (existingShow.getSeasons() != null) { - List contextBlockElements = new ArrayList<>(); - contextBlockElements.add(PlainTextObject.builder() - .text("Number of seasons - " + existingShow.getSeasons().size()) - .build()); - for (SonarrSeason sonarrSeason : existingShow.getSeasons()) { - contextBlockElements.add(PlainTextObject.builder() - .text("Season#" + sonarrSeason.getSeasonNumber() + - ",Available Epsiodes=" + sonarrSeason.getStatistics().getEpisodeCount() + ",Total Epsiodes=" + sonarrSeason.getStatistics().getTotalEpisodeCount()) + slackResponse.addBlock(SectionBlock.builder() + .text(MarkdownTextObject.builder().text(ADD_SHOW_COMMAND_FIELD_PREFIX + " - " + SonarrCommands.getAddShowCommandStr(sonarrShow.getTitle(), sonarrShow.getTvdbId())).build()) .build()); - } - - slackResponse.addBlock(ContextBlock.builder() - .elements(contextBlockElements) - .build()); - } - } slackResponse.addBlock(ImageBlock.builder() .imageUrl(sonarrShow.getRemotePoster()) .altText(sonarrShow.getTitle() + " poster") @@ -364,7 +354,43 @@ public SlackResponse getNewOrExistingShow(SonarrShow sonarrShow, SonarrShow exis } @Override - public SlackResponse getNewOrExistingMovie(RadarrMovie lookupMovie, RadarrMovie existingMovie, boolean findNew) { + public SlackResponse build(ExistingShowResponse existingShowResponse) { + SonarrShow sonarrShow = existingShowResponse.getExistingShow(); + SlackResponse slackResponse = new SlackResponse(); + slackResponse.addBlock(SectionBlock.builder() + .text(MarkdownTextObject.builder().text("*Title* - " + sonarrShow.getTitle()).build()) + .build()); + slackResponse.addBlock(SectionBlock.builder() + .text(MarkdownTextObject.builder().text("TvdbId - " + sonarrShow.getTvdbId()).build()) + .build()); + slackResponse.addBlock(SectionBlock.builder() + .text(MarkdownTextObject.builder().text("Id - " + sonarrShow.getId()).build()) + .build()); + if (sonarrShow.getSeasons() != null) { + List contextBlockElements = new ArrayList<>(); + contextBlockElements.add(PlainTextObject.builder() + .text("Number of seasons - " + sonarrShow.getSeasons().size()) + .build()); + for (SonarrSeason sonarrSeason : sonarrShow.getSeasons()) { + contextBlockElements.add(PlainTextObject.builder() + .text("Season#" + sonarrSeason.getSeasonNumber() + + ",Available Epsiodes=" + sonarrSeason.getStatistics().getEpisodeCount() + ",Total Epsiodes=" + sonarrSeason.getStatistics().getTotalEpisodeCount()) + .build()); + } + slackResponse.addBlock(ContextBlock.builder() + .elements(contextBlockElements) + .build()); + } + slackResponse.addBlock(ImageBlock.builder() + .imageUrl(sonarrShow.getRemotePoster()) + .altText(sonarrShow.getTitle() + " poster") + .build()); + return slackResponse; + } + + @Override + public SlackResponse build(NewMovieResponse newMovieResponse) { + RadarrMovie lookupMovie = newMovieResponse.getRadarrMovie(); SlackResponse slackResponse = new SlackResponse(); slackResponse.addBlock(SectionBlock.builder() .text(MarkdownTextObject.builder().text("*Title* - " + lookupMovie.getTitle()).build()) @@ -372,21 +398,10 @@ public SlackResponse getNewOrExistingMovie(RadarrMovie lookupMovie, RadarrMovie slackResponse.addBlock(SectionBlock.builder() .text(MarkdownTextObject.builder().text("TmdbId - " + lookupMovie.getTmdbId()).build()) .build()); - if (findNew) { - slackResponse.addBlock(SectionBlock.builder() - .text(MarkdownTextObject.builder().text(ADD_MOVIE_COMMAND_FIELD_PREFIX + " - " + RadarrCommands.getAddMovieCommandStr(lookupMovie.getTitle(), lookupMovie.getTmdbId())).build()) - .build()); - } else { - slackResponse.addBlock(SectionBlock.builder() - .text(MarkdownTextObject.builder().text("Id - " + existingMovie.getId()).build()) - .build()); - slackResponse.addBlock(SectionBlock.builder() - .text(MarkdownTextObject.builder().text("Downloaded - " + (existingMovie.getSizeOnDisk() > 0)).build()) - .build()); - slackResponse.addBlock(SectionBlock.builder() - .text(MarkdownTextObject.builder().text("Has File - " + existingMovie.isHasFile()).build()) - .build()); - } + slackResponse.addBlock(ActionsBlock.builder().elements(Collections.singletonList(ButtonElement.builder().text(PlainTextObject.builder().text("hello").build()).build())).build()); + slackResponse.addBlock(SectionBlock.builder() + .text(MarkdownTextObject.builder().text(ADD_MOVIE_COMMAND_FIELD_PREFIX + " - " + RadarrCommands.getAddMovieCommandStr(lookupMovie.getTitle(), lookupMovie.getTmdbId())).build()) + .build()); slackResponse.addBlock(ImageBlock.builder() .imageUrl(lookupMovie.getRemotePoster()) .altText(lookupMovie.getTitle() + " poster") @@ -395,18 +410,44 @@ public SlackResponse getNewOrExistingMovie(RadarrMovie lookupMovie, RadarrMovie } @Override - public SlackResponse getNewOrExistingArtist(LidarrArtist lookupArtist, LidarrArtist existingArtist, boolean findNew) { + public SlackResponse build(ExistingMovieResponse existingMovieResponse) { + RadarrMovie lookupMovie = existingMovieResponse.getRadarrMovie(); + SlackResponse slackResponse = new SlackResponse(); + slackResponse.addBlock(SectionBlock.builder() + .text(MarkdownTextObject.builder().text("*Title* - " + lookupMovie.getTitle()).build()) + .build()); + slackResponse.addBlock(SectionBlock.builder() + .text(MarkdownTextObject.builder().text("TmdbId - " + lookupMovie.getTmdbId()).build()) + .build()); + slackResponse.addBlock(ActionsBlock.builder().elements(Collections.singletonList(ButtonElement.builder().text(PlainTextObject.builder().text("hello").build()).build())).build()); + slackResponse.addBlock(SectionBlock.builder() + .text(MarkdownTextObject.builder().text("Id - " + lookupMovie.getId()).build()) + .build()); + slackResponse.addBlock(SectionBlock.builder() + .text(MarkdownTextObject.builder().text("Downloaded - " + (lookupMovie.getSizeOnDisk() > 0)).build()) + .build()); + slackResponse.addBlock(SectionBlock.builder() + .text(MarkdownTextObject.builder().text("Has File - " + lookupMovie.isHasFile()).build()) + .build()); + slackResponse.addBlock(ImageBlock.builder() + .imageUrl(lookupMovie.getRemotePoster()) + .altText(lookupMovie.getTitle() + " poster") + .build()); + return slackResponse; + } + + @Override + public SlackResponse build(NewMusicArtistResponse newMusicArtistResponse) { + LidarrArtist lookupArtist = newMusicArtistResponse.getLidarrArtist(); SlackResponse slackResponse = new SlackResponse(); String artistDetail = " (" + lookupArtist.getDisambiguation() + ")"; slackResponse.addBlock(SectionBlock.builder() .text(MarkdownTextObject.builder().text("*Artist Name* - " + lookupArtist.getArtistName() + (Strings.isEmpty(lookupArtist.getDisambiguation()) ? "" : artistDetail)).build()) .build()); - if (findNew) { - slackResponse.addBlock(SectionBlock.builder() - .text(MarkdownTextObject.builder().text(ADD_ARTIST_COMMAND_FIELD_PREFIX + " - " + - LidarrCommands.getAddArtistCommandStr(lookupArtist.getArtistName(), lookupArtist.getForeignArtistId())).build()) - .build()); - } + slackResponse.addBlock(SectionBlock.builder() + .text(MarkdownTextObject.builder().text(ADD_ARTIST_COMMAND_FIELD_PREFIX + " - " + + LidarrCommands.getAddArtistCommandStr(lookupArtist.getArtistName(), lookupArtist.getForeignArtistId())).build()) + .build()); slackResponse.addBlock(ImageBlock.builder() .imageUrl(lookupArtist.getRemotePoster()) .altText(lookupArtist.getArtistName() + " poster") @@ -415,40 +456,37 @@ public SlackResponse getNewOrExistingArtist(LidarrArtist lookupArtist, LidarrArt } @Override - public SlackResponse getMovieResponse(RadarrMovie radarrMovie) { + public SlackResponse build(ExistingMusicArtistResponse existingMusicArtistResponse) { + LidarrArtist lookupArtist = existingMusicArtistResponse.getLidarrArtist(); SlackResponse slackResponse = new SlackResponse(); + String artistDetail = " (" + lookupArtist.getDisambiguation() + ")"; slackResponse.addBlock(SectionBlock.builder() - .text(MarkdownTextObject.builder().text("*Title* - " + radarrMovie.getTitle()).build()) - .build()); - slackResponse.addBlock(SectionBlock.builder() - .text(MarkdownTextObject.builder().text("TmdbId - " + radarrMovie.getTmdbId()).build()) - .build()); - slackResponse.addBlock(SectionBlock.builder() - .text(MarkdownTextObject.builder().text(ADD_MOVIE_COMMAND_FIELD_PREFIX + " - " + RadarrCommands.getAddMovieCommandStr(radarrMovie.getTitle(), radarrMovie.getTmdbId())).build()) - .build()); - if (!Strings.isBlank(radarrMovie.getRemotePoster())) { - //if there is no poster to display, slack will fail to render all the blocks - //so make sure there is one before trying to render - slackResponse.addBlock(ImageBlock.builder() - .imageUrl(radarrMovie.getRemotePoster()) - .altText(radarrMovie.getTitle() + " poster") - .build()); - } + .text(MarkdownTextObject.builder().text("*Artist Name* - " + lookupArtist.getArtistName() + (Strings.isEmpty(lookupArtist.getDisambiguation()) ? "" : artistDetail)).build()) + .build()); + slackResponse.addBlock(ImageBlock.builder() + .imageUrl(lookupArtist.getRemotePoster()) + .altText(lookupArtist.getArtistName() + " poster") + .build()); return slackResponse; } @Override - public SlackResponse getDiscoverableMovies(RadarrMovie radarrMovie) { - return getMovieResponse(radarrMovie); + public SlackResponse build(MovieResponse movieResponse) { + return getMovieResponse(movieResponse.getRadarrMovie()); } @Override - public SlackResponse getStatusCommandResponse(Map endpointStatuses) { + public SlackResponse build(DiscoverMovieResponse discoverMovieResponse) { + return getMovieResponse(discoverMovieResponse.getRadarrMovie()); + } + + @Override + public SlackResponse build(StatusCommandResponse statusCommandResponse) { SlackResponse slackResponse = new SlackResponse(); slackResponse.addBlock(SectionBlock.builder() .text(MarkdownTextObject.builder().text("*Endpoint Statuses*").build()) .build()); - for (Map.Entry endpointStatusEntry : endpointStatuses.entrySet()) { + for (Map.Entry endpointStatusEntry : statusCommandResponse.getEndpoints().entrySet()) { slackResponse.addBlock(SectionBlock.builder() .text(MarkdownTextObject.builder().text(endpointStatusEntry.getKey() + " - " + (endpointStatusEntry.getValue() ? "\uD83D\uDFE2" : "\uD83D\uDD34")).build()) .build()); @@ -456,6 +494,28 @@ public SlackResponse getStatusCommandResponse(Map endpointStatu return slackResponse; } + private SlackResponse getMovieResponse(RadarrMovie radarrMovie) { + SlackResponse slackResponse = new SlackResponse(); + slackResponse.addBlock(SectionBlock.builder() + .text(MarkdownTextObject.builder().text("*Title* - " + radarrMovie.getTitle()).build()) + .build()); + slackResponse.addBlock(SectionBlock.builder() + .text(MarkdownTextObject.builder().text("TmdbId - " + radarrMovie.getTmdbId()).build()) + .build()); + slackResponse.addBlock(SectionBlock.builder() + .text(MarkdownTextObject.builder().text(ADD_MOVIE_COMMAND_FIELD_PREFIX + " - " + RadarrCommands.getAddMovieCommandStr(radarrMovie.getTitle(), radarrMovie.getTmdbId())).build()) + .build()); + if (!Strings.isBlank(radarrMovie.getRemotePoster())) { + //if there is no poster to display, slack will fail to render all the blocks + //so make sure there is one before trying to render + slackResponse.addBlock(ImageBlock.builder() + .imageUrl(radarrMovie.getRemotePoster()) + .altText(radarrMovie.getTitle() + " poster") + .build()); + } + return slackResponse; + } + private SlackResponse getListOfCommands(List commands) { SlackResponse slackResponse = new SlackResponse(); slackResponse.addBlock(SectionBlock.builder() diff --git a/src/main/java/com/botdarr/clients/telegram/TelegramBootstrap.java b/src/main/java/com/botdarr/clients/telegram/TelegramBootstrap.java new file mode 100644 index 0000000..7ae7c03 --- /dev/null +++ b/src/main/java/com/botdarr/clients/telegram/TelegramBootstrap.java @@ -0,0 +1,59 @@ +package com.botdarr.clients.telegram; + +import com.botdarr.Config; +import com.botdarr.clients.ChatClientBootstrap; +import com.botdarr.clients.ChatClientResponseBuilder; +import com.botdarr.scheduling.Scheduler; +import com.pengrad.telegrambot.UpdatesListener; +import com.pengrad.telegrambot.model.Update; +import org.apache.logging.log4j.util.Strings; + +import java.util.Properties; + +public class TelegramBootstrap extends ChatClientBootstrap { + private boolean isUsingChannels() { + String telegramGroups = Config.getProperty(Config.Constants.TELEGRAM_PRIVATE_GROUPS); + return telegramGroups == null || telegramGroups.isEmpty(); + } + @Override + public void init() throws Exception { + ChatClientResponseBuilder responseChatClientResponseBuilder = new TelegramResponseBuilder(); + ChatClientBootstrap.ApisAndCommandConfig config = buildConfig(); + TelegramChatClient telegramChatClient = new TelegramChatClient(); + + initScheduling(telegramChatClient, responseChatClientResponseBuilder, config.getApis()); + telegramChatClient.addUpdateListener(list -> { + try { + for (Update update : list) { + com.pengrad.telegrambot.model.Message message = isUsingChannels() ? update.channelPost() : update.message(); + if (message != null && !Strings.isEmpty(message.text())) { + String text = message.text(); + //TODO: the telegram api doesn't seem return "from" field in channel posts for some reason + //for now we leave the author as "telegram" till a better solution arises + String author = "telegram"; + Scheduler.getScheduler().executeCommand(() -> { + runAndProcessCommands(text, author, responseChatClientResponseBuilder, chatClientResponse -> { + telegramChatClient.sendMessage(chatClientResponse, message.chat()); + }); + return null; + }); + } + } + } catch (Throwable t) { + LOGGER.error("Error during telegram updates", t); + } + return UpdatesListener.CONFIRMED_UPDATES_ALL; + }); + } + + @Override + public boolean isConfigured(Properties properties) { + boolean isTelegramConfigured = !Strings.isBlank(properties.getProperty(Config.Constants.TELEGRAM_TOKEN)); + boolean telegramPrivateChannelsExist = !Strings.isBlank(properties.getProperty(Config.Constants.TELEGRAM_PRIVATE_CHANNELS)); + boolean telegramPrivateGroupsExist = !Strings.isBlank(properties.getProperty(Config.Constants.TELEGRAM_PRIVATE_GROUPS)); + if (isTelegramConfigured && telegramPrivateChannelsExist && telegramPrivateGroupsExist) { + throw new RuntimeException("Cannot configure telegram for private channels and groups, you must pick one or the other"); + } + return isTelegramConfigured && (telegramPrivateChannelsExist || telegramPrivateGroupsExist); + } +} diff --git a/src/main/java/com/botdarr/clients/telegram/TelegramChatClient.java b/src/main/java/com/botdarr/clients/telegram/TelegramChatClient.java index 97493c1..2ee2167 100644 --- a/src/main/java/com/botdarr/clients/telegram/TelegramChatClient.java +++ b/src/main/java/com/botdarr/clients/telegram/TelegramChatClient.java @@ -2,7 +2,6 @@ import com.botdarr.Config; import com.botdarr.clients.ChatClient; -import com.botdarr.commands.CommandResponse; import com.google.common.base.Splitter; import com.google.common.collect.Sets; import com.pengrad.telegrambot.TelegramBot; @@ -44,16 +43,6 @@ public void sendMessage(List telegramResponses, Chat chat) { }, chat); } - public void sendMessage(CommandResponse commandResponse, Chat chat) { - if (commandResponse.getSingleChatClientResponse() != null) { - sendMessage(commandResponse.getSingleChatClientResponse(), chat); - } else if (commandResponse.getMultipleChatClientResponses() != null) { - sendMessage(commandResponse.getMultipleChatClientResponses(), chat); - } else { - //TODO: err - } - } - private String getMessageEndpoint() { String channels = Config.getProperty(Config.Constants.TELEGRAM_PRIVATE_CHANNELS); if (Strings.isBlank(channels)) { diff --git a/src/main/java/com/botdarr/clients/telegram/TelegramResponse.java b/src/main/java/com/botdarr/clients/telegram/TelegramResponse.java index 344af1c..48d455e 100644 --- a/src/main/java/com/botdarr/clients/telegram/TelegramResponse.java +++ b/src/main/java/com/botdarr/clients/telegram/TelegramResponse.java @@ -13,7 +13,7 @@ public TelegramResponse(List containerTags) { public String getHtml() { StringBuilder stringBuilder = new StringBuilder(); for (DomContent domContent : domContent) { - stringBuilder.append(domContent.render() + "\n"); + stringBuilder.append(domContent.render()).append("\n"); } return stringBuilder.toString(); } diff --git a/src/main/java/com/botdarr/clients/telegram/TelegramResponseBuilder.java b/src/main/java/com/botdarr/clients/telegram/TelegramResponseBuilder.java index 7f8e13a..92fc8ca 100644 --- a/src/main/java/com/botdarr/clients/telegram/TelegramResponseBuilder.java +++ b/src/main/java/com/botdarr/clients/telegram/TelegramResponseBuilder.java @@ -2,12 +2,14 @@ import com.botdarr.Config; import com.botdarr.api.lidarr.LidarrArtist; +import com.botdarr.api.lidarr.LidarrCommands; import com.botdarr.api.lidarr.LidarrQueueRecord; import com.botdarr.api.lidarr.LidarrQueueStatusMessage; import com.botdarr.api.radarr.*; import com.botdarr.api.sonarr.*; import com.botdarr.clients.ChatClientResponseBuilder; import com.botdarr.commands.*; +import com.botdarr.commands.responses.*; import com.botdarr.utilities.ListUtils; import j2html.tags.DomContent; import org.apache.logging.log4j.util.Strings; @@ -27,7 +29,7 @@ public class TelegramResponseBuilder implements ChatClientResponseBuilder { @Override - public TelegramResponse getHelpResponse() { + public TelegramResponse build(HelpResponse helpResponse) { try { List domContents = new ArrayList<>(); domContents.add(code("Version: " + ChatClientResponseBuilder.getVersion())); @@ -57,22 +59,23 @@ public TelegramResponse getHelpResponse() { } @Override - public TelegramResponse getMusicHelpResponse(List lidarCommands) { - return new TelegramResponse(getListOfCommands(lidarCommands)); + public TelegramResponse build(MusicHelpResponse musicHelpResponse) { + return new TelegramResponse(getListOfCommands(musicHelpResponse.getLidarrCommands())); } @Override - public TelegramResponse getMoviesHelpResponse(List radarrCommands) { - return new TelegramResponse(getListOfCommands(radarrCommands)); + public TelegramResponse build(MoviesHelpResponse moviesHelpResponse) { + return new TelegramResponse(getListOfCommands(moviesHelpResponse.getRadarrCommands())); } @Override - public TelegramResponse getShowsHelpResponse(List sonarrCommands) { - return new TelegramResponse(getListOfCommands(sonarrCommands)); + public TelegramResponse build(ShowsHelpResponse showsHelpResponse) { + return new TelegramResponse(getListOfCommands(showsHelpResponse.getSonarrCommands())); } @Override - public TelegramResponse getShowResponse(SonarrShow show) { + public TelegramResponse build(ShowResponse showResponse) { + SonarrShow show = showResponse.getShow(); List domContents = new ArrayList<>(); domContents.add(b("*Title* - " + show.getTitle())); domContents.add(code("TvdbId - " + show.getTvdbId())); @@ -82,7 +85,8 @@ public TelegramResponse getShowResponse(SonarrShow show) { } @Override - public TelegramResponse getArtistResponse(LidarrArtist lidarrArtist) { + public TelegramResponse build(MusicArtistResponse musicArtistResponse) { + LidarrArtist lidarrArtist = musicArtistResponse.getArtist(); List domContents = new ArrayList<>(); domContents.add(b("*Artist Name* - " + lidarrArtist.getArtistName())); domContents.add(code("Id - " + lidarrArtist.getForeignArtistId())); @@ -92,17 +96,17 @@ public TelegramResponse getArtistResponse(LidarrArtist lidarrArtist) { } @Override - public TelegramResponse getShowDownloadResponses(SonarrQueue showQueue) { + public TelegramResponse build(ShowDownloadResponse showDownloadResponse) { + SonarrQueue showQueue = showDownloadResponse.getShowQueue(); SonarQueueEpisode episode = showQueue.getEpisode(); List domContents = new ArrayList<>(); domContents.add(b(showQueue.getSonarrQueueShow().getTitle())); - StringBuilder queueDetails = new StringBuilder(); - queueDetails.append("Season/Episode - " + "S" + episode.getSeasonNumber() + "E" + episode.getEpisodeNumber() + "\n"); - queueDetails.append("Quality - " + showQueue.getQuality().getQuality().getName() + "\n"); - queueDetails.append("Status - " + showQueue.getStatus() + "\n"); - queueDetails.append("Time Left - " + (showQueue.getTimeleft() == null ? "unknown" : showQueue.getTimeleft()) + "\n"); - domContents.add(code(queueDetails.toString())); + String queueDetails = "Season/Episode - " + "S" + episode.getSeasonNumber() + "E" + episode.getEpisodeNumber() + "\n" + + "Quality - " + showQueue.getQuality().getQuality().getName() + "\n" + + "Status - " + showQueue.getStatus() + "\n" + + "Time Left - " + (showQueue.getTimeleft() == null ? "unknown" : showQueue.getTimeleft()) + "\n"; + domContents.add(code(queueDetails)); String overview = episode.getTitle() + ": " + episode.getOverview(); if (overview.length() > VALUE_MAX_LENGTH) { @@ -113,7 +117,7 @@ public TelegramResponse getShowDownloadResponses(SonarrQueue showQueue) { StringBuilder statusMessageBuilder = new StringBuilder(); for (SonarrQueueStatusMessages statusMessage : showQueue.getStatusMessages()) { for (String message : statusMessage.getMessages()) { - statusMessageBuilder.append("Download Message - " + message + "\n"); + statusMessageBuilder.append("Download Message - ").append(message).append("\n"); } } domContents.add(code(statusMessageBuilder.toString())); @@ -122,17 +126,18 @@ public TelegramResponse getShowDownloadResponses(SonarrQueue showQueue) { } @Override - public TelegramResponse getMovieDownloadResponses(RadarrQueue radarrQueue) { + public TelegramResponse build(MovieDownloadResponse movieDownloadResponse) { + RadarrQueue radarrQueue = movieDownloadResponse.getRadarrQueue(); List domContents = new ArrayList<>(); domContents.add(b(radarrQueue.getTitle())); StringBuilder details = new StringBuilder(); - details.append("Quality - " + radarrQueue.getQuality().getQuality().getName() + "\n"); - details.append("Status - " + radarrQueue.getStatus() + "\n"); - details.append("Time Left - " + (radarrQueue.getTimeleft() == null ? "unknown" : radarrQueue.getTimeleft() + "\n")); + details.append("Quality - ").append(radarrQueue.getQuality().getQuality().getName()).append("\n"); + details.append("Status - ").append(radarrQueue.getStatus()).append("\n"); + details.append("Time Left - ").append(radarrQueue.getTimeleft() == null ? "unknown" : radarrQueue.getTimeleft() + "\n"); if (radarrQueue.getStatusMessages() != null) { for (RadarrQueueStatusMessages statusMessage : radarrQueue.getStatusMessages()) { for (String message : statusMessage.getMessages()) { - details.append("Download message - " + message + "\n"); + details.append("Download message - ").append(message).append("\n"); } } } @@ -141,17 +146,18 @@ public TelegramResponse getMovieDownloadResponses(RadarrQueue radarrQueue) { } @Override - public TelegramResponse getArtistDownloadResponses(LidarrQueueRecord lidarrQueueRecord) { + public TelegramResponse build(MusicArtistDownloadResponse musicArtistDownloadResponse) { + LidarrQueueRecord lidarrQueueRecord = musicArtistDownloadResponse.getQueueRecord(); List domContents = new ArrayList<>(); domContents.add(b(lidarrQueueRecord.getTitle())); StringBuilder details = new StringBuilder(); - details.append("Status - " + lidarrQueueRecord.getStatus() + "\n"); - details.append("Time Left - " + (lidarrQueueRecord.getTimeleft() == null ? "unknown" : lidarrQueueRecord.getTimeleft() + "\n")); + details.append("Status - ").append(lidarrQueueRecord.getStatus()).append("\n"); + details.append("Time Left - ").append(lidarrQueueRecord.getTimeleft() == null ? "unknown" : lidarrQueueRecord.getTimeleft() + "\n"); if (lidarrQueueRecord.getStatusMessages() != null) { //limit messages to 5, since lidarr can really throw a ton of status messages for (LidarrQueueStatusMessage statusMessage : ListUtils.subList(lidarrQueueRecord.getStatusMessages(), 5)) { for (String message : statusMessage.getMessages()) { - details.append("Download message - " + message + "\n"); + details.append("Download message - ").append(message).append("\n"); } } } @@ -160,28 +166,29 @@ public TelegramResponse getArtistDownloadResponses(LidarrQueueRecord lidarrQueue } @Override - public TelegramResponse createErrorMessage(String message) { + public TelegramResponse build(ErrorResponse errorResponse) { List domContents = new ArrayList<>(); - domContents.add(b("Error! - " + message)); + domContents.add(b("Error! - " + errorResponse.getErrorMessage())); return new TelegramResponse(domContents); } @Override - public TelegramResponse createInfoMessage(String message) { + public TelegramResponse build(InfoResponse infoResponse) { List domContents = new ArrayList<>(); - domContents.add(b("Info! - " + message)); + domContents.add(b("Info! - " + infoResponse.getInfoMessage())); return new TelegramResponse(domContents); } @Override - public TelegramResponse createSuccessMessage(String message) { + public TelegramResponse build(SuccessResponse successResponse) { List domContents = new ArrayList<>(); - domContents.add(u(b("Success! - " + message))); + domContents.add(u(b("Success! - " + successResponse.getSuccessMessage()))); return new TelegramResponse(domContents); } @Override - public TelegramResponse getShowProfile(SonarrProfile sonarrProfile) { + public TelegramResponse build(ShowProfileResponse showProfileResponse) { + SonarrProfile sonarrProfile = showProfileResponse.getShowProfile(); List domContents = new ArrayList<>(); domContents.add(b("Profile")); domContents.add(text("Name - " + sonarrProfile.getName())); @@ -191,7 +198,7 @@ public TelegramResponse getShowProfile(SonarrProfile sonarrProfile) { for (int k = 0; k < sonarrProfile.getItems().size(); k++) { SonarrProfileQualityItem sonarrProfileQualityItem = sonarrProfile.getItems().get(k); if (sonarrProfileQualityItem.isAllowed()) { - qualityItems.append("Quality - name=" + sonarrProfileQualityItem.getQuality().getName() + ", resolution=" + sonarrProfileQualityItem.getQuality().getResolution() + "\n"); + qualityItems.append("Quality - name=").append(sonarrProfileQualityItem.getQuality().getName()).append(", resolution=").append(sonarrProfileQualityItem.getQuality().getResolution()).append("\n"); } } domContents.add(code(qualityItems.toString())); @@ -200,7 +207,8 @@ public TelegramResponse getShowProfile(SonarrProfile sonarrProfile) { } @Override - public TelegramResponse getMovieProfile(RadarrProfile radarrProfile) { + public TelegramResponse build(MovieProfileResponse movieProfileResponse) { + RadarrProfile radarrProfile = movieProfileResponse.getRadarrProfile(); List domContents = new ArrayList<>(); domContents.add(b("Profile")); domContents.add(text("Name - " + radarrProfile.getName())); @@ -210,7 +218,7 @@ public TelegramResponse getMovieProfile(RadarrProfile radarrProfile) { for (int k = 0; k < radarrProfile.getItems().size(); k++) { RadarrProfileQualityItem radarrProfileQualityItem = radarrProfile.getItems().get(k); if (radarrProfileQualityItem.isAllowed() && radarrProfileQualityItem.getQuality() != null) { - qualityItems.append("Quality - name=" + radarrProfileQualityItem.getQuality().getName() + ", resolution=" + radarrProfileQualityItem.getQuality().getResolution() + "\n"); + qualityItems.append("Quality - name=").append(radarrProfileQualityItem.getQuality().getName()).append(", resolution=").append(radarrProfileQualityItem.getQuality().getResolution()).append("\n"); } } domContents.add(code(qualityItems.toString())); @@ -219,79 +227,112 @@ public TelegramResponse getMovieProfile(RadarrProfile radarrProfile) { } @Override - public TelegramResponse getNewOrExistingShow(SonarrShow sonarrShow, SonarrShow existingShow, boolean findNew) { + public TelegramResponse build(NewShowResponse newShowResponse) { + SonarrShow sonarrShow = newShowResponse.getNewShow(); List domContents = new ArrayList<>(); domContents.add(b("*Title* - " + sonarrShow.getTitle())); domContents.add(code("TvdbId - " + sonarrShow.getTvdbId())); - if (findNew) { - domContents.add(u(ADD_SHOW_COMMAND_FIELD_PREFIX + " - " + SonarrCommands.getAddShowCommandStr(sonarrShow.getTitle(), sonarrShow.getTvdbId()))); - } else { - StringBuilder existingShowDetails = new StringBuilder(); - existingShowDetails.append("Number of seasons - " + existingShow.getSeasons().size() + "\n"); - for (SonarrSeason sonarrSeason : existingShow.getSeasons()) { - existingShowDetails.append("Season#" + sonarrSeason.getSeasonNumber() + - ",Available Epsiodes=" + sonarrSeason.getStatistics().getEpisodeCount() + ",Total Epsiodes=" + sonarrSeason.getStatistics().getTotalEpisodeCount() + "\n"); - } - domContents.add(code(existingShowDetails.toString())); + domContents.add(u(ADD_SHOW_COMMAND_FIELD_PREFIX + " - " + SonarrCommands.getAddShowCommandStr(sonarrShow.getTitle(), sonarrShow.getTvdbId()))); + domContents.add(a(sonarrShow.getRemotePoster())); + return new TelegramResponse(domContents); + } + + @Override + public TelegramResponse build(ExistingShowResponse existingShowResponse) { + SonarrShow sonarrShow = existingShowResponse.getExistingShow(); + List domContents = new ArrayList<>(); + domContents.add(b("*Title* - " + sonarrShow.getTitle())); + domContents.add(code("TvdbId - " + sonarrShow.getTvdbId())); + StringBuilder existingShowDetails = new StringBuilder(); + existingShowDetails.append("Number of seasons - ").append(sonarrShow.getSeasons().size()).append("\n"); + for (SonarrSeason sonarrSeason : sonarrShow.getSeasons()) { + existingShowDetails + .append("Season#") + .append(sonarrSeason.getSeasonNumber()) + .append(",Available Epsiodes=") + .append(sonarrSeason.getStatistics().getEpisodeCount()) + .append(",Total Epsiodes=") + .append(sonarrSeason.getStatistics().getTotalEpisodeCount()) + .append("\n"); } + domContents.add(code(existingShowDetails.toString())); domContents.add(a(sonarrShow.getRemotePoster())); return new TelegramResponse(domContents); } @Override - public TelegramResponse getNewOrExistingMovie(RadarrMovie lookupMovie, RadarrMovie existingMovie, boolean findNew) { + public TelegramResponse build(NewMovieResponse newMovieResponse) { + RadarrMovie lookupMovie = newMovieResponse.getRadarrMovie(); List domContents = new ArrayList<>(); domContents.add(b(lookupMovie.getTitle())); - if (findNew) { - domContents.add(u(ADD_MOVIE_COMMAND_FIELD_PREFIX + " - " + RadarrCommands.getAddMovieCommandStr(lookupMovie.getTitle(), lookupMovie.getTmdbId()))); - } else { - StringBuilder existingDetails = new StringBuilder(); - existingDetails.append("Id - " + existingMovie.getId() + "\n"); - existingDetails.append("Downloaded - " + (existingMovie.getSizeOnDisk() > 0) + "\n"); - existingDetails.append("Has File - " + existingMovie.isHasFile() + "\n"); - domContents.add(code(existingDetails.toString())); - } + domContents.add(u(ADD_MOVIE_COMMAND_FIELD_PREFIX + " - " + RadarrCommands.getAddMovieCommandStr(lookupMovie.getTitle(), lookupMovie.getTmdbId()))); domContents.add(a(lookupMovie.getRemotePoster())); return new TelegramResponse(domContents); } @Override - public TelegramResponse getNewOrExistingArtist(LidarrArtist lookupArtist, LidarrArtist existingArtist, boolean findNew) { + public TelegramResponse build(ExistingMovieResponse existingMovieResponse) { + RadarrMovie lookupMovie = existingMovieResponse.getRadarrMovie(); + List domContents = new ArrayList<>(); + domContents.add(b(lookupMovie.getTitle())); + String existingDetails = "Id - " + lookupMovie.getId() + "\n" + + "Downloaded - " + (lookupMovie.getSizeOnDisk() > 0) + "\n" + + "Has File - " + lookupMovie.isHasFile() + "\n"; + domContents.add(code(existingDetails)); + domContents.add(a(lookupMovie.getRemotePoster())); + return new TelegramResponse(domContents); + } + + @Override + public TelegramResponse build(NewMusicArtistResponse newMusicArtistResponse) { + LidarrArtist lookupArtist = newMusicArtistResponse.getLidarrArtist(); List domContents = new ArrayList<>(); String artistDetail = " (" + lookupArtist.getDisambiguation() + ")"; domContents.add(b(lookupArtist.getArtistName() + (Strings.isEmpty(lookupArtist.getDisambiguation()) ? "" : artistDetail))); - if (findNew) { - domContents.add(u(ADD_ARTIST_COMMAND_FIELD_PREFIX + " - " + LidarrCommands.getAddArtistCommandStr(lookupArtist.getArtistName(), lookupArtist.getForeignArtistId()))); - } + domContents.add(u(ADD_ARTIST_COMMAND_FIELD_PREFIX + " - " + LidarrCommands.getAddArtistCommandStr(lookupArtist.getArtistName(), lookupArtist.getForeignArtistId()))); domContents.add(a(lookupArtist.getRemotePoster())); return new TelegramResponse(domContents); } @Override - public TelegramResponse getMovieResponse(RadarrMovie radarrMovie) { + public TelegramResponse build(ExistingMusicArtistResponse existingMusicArtistResponse) { + LidarrArtist lookupArtist = existingMusicArtistResponse.getLidarrArtist(); List domContents = new ArrayList<>(); - domContents.add(b(radarrMovie.getTitle())); - domContents.add(text("TmdbId - " + radarrMovie.getTmdbId())); - domContents.add(u(b(ADD_MOVIE_COMMAND_FIELD_PREFIX + " - " + RadarrCommands.getAddMovieCommandStr(radarrMovie.getTitle(), radarrMovie.getTmdbId())))); - domContents.add(a(radarrMovie.getRemotePoster())); + String artistDetail = " (" + lookupArtist.getDisambiguation() + ")"; + domContents.add(b(lookupArtist.getArtistName() + (Strings.isEmpty(lookupArtist.getDisambiguation()) ? "" : artistDetail))); + domContents.add(a(lookupArtist.getRemotePoster())); return new TelegramResponse(domContents); } @Override - public TelegramResponse getDiscoverableMovies(RadarrMovie radarrMovie) { - return getMovieResponse(radarrMovie); + public TelegramResponse build(MovieResponse movieResponse) { + return getMovieResponse(movieResponse.getRadarrMovie()); + } + + @Override + public TelegramResponse build(DiscoverMovieResponse discoverMovieResponse) { + return getMovieResponse(discoverMovieResponse.getRadarrMovie()); } @Override - public TelegramResponse getStatusCommandResponse(Map endpointStatuses) { + public TelegramResponse build(StatusCommandResponse statusCommandResponse) { List domContents = new ArrayList<>(); domContents.add(u(b("*Endpoint Statuses*"))); - for (Map.Entry endpointStatusEntry : endpointStatuses.entrySet()) { + for (Map.Entry endpointStatusEntry : statusCommandResponse.getEndpoints().entrySet()) { domContents.add(text(endpointStatusEntry.getKey() + " - " + (endpointStatusEntry.getValue() ? "\uD83D\uDFE2" : "\uD83D\uDD34"))); } return new TelegramResponse(domContents); } + private TelegramResponse getMovieResponse(RadarrMovie radarrMovie) { + List domContents = new ArrayList<>(); + domContents.add(b(radarrMovie.getTitle())); + domContents.add(text("TmdbId - " + radarrMovie.getTmdbId())); + domContents.add(u(b(ADD_MOVIE_COMMAND_FIELD_PREFIX + " - " + RadarrCommands.getAddMovieCommandStr(radarrMovie.getTitle(), radarrMovie.getTmdbId())))); + domContents.add(a(radarrMovie.getRemotePoster())); + return new TelegramResponse(domContents); + } + private List getListOfCommands(List commands) { List domContents = new ArrayList<>(); domContents.add(u(b("*Commands*"))); diff --git a/src/main/java/com/botdarr/commands/Command.java b/src/main/java/com/botdarr/commands/Command.java index b2f6f36..eaa4ace 100644 --- a/src/main/java/com/botdarr/commands/Command.java +++ b/src/main/java/com/botdarr/commands/Command.java @@ -1,17 +1,19 @@ package com.botdarr.commands; -import com.botdarr.clients.ChatClientResponse; +import com.botdarr.commands.responses.CommandResponse; + +import java.util.List; public interface Command { - public String getCommandText(); - public String getDescription(); - public String getIdentifier(); - public default String getCommandUsage() { + String getCommandText(); + String getDescription(); + String getIdentifier(); + default String getCommandUsage() { return ""; } - public default boolean hasArguments() { + default boolean hasArguments() { //by default all commands have arguments unless explicitly overridden return true; } - public CommandResponse execute(String command); + List execute(String command); } diff --git a/src/main/java/com/botdarr/commands/CommandProcessor.java b/src/main/java/com/botdarr/commands/CommandProcessor.java index f112aef..ba2031d 100644 --- a/src/main/java/com/botdarr/commands/CommandProcessor.java +++ b/src/main/java/com/botdarr/commands/CommandProcessor.java @@ -1,20 +1,20 @@ package com.botdarr.commands; import com.botdarr.Config; -import com.botdarr.api.Api; import com.botdarr.clients.ChatClientResponse; -import com.botdarr.clients.ChatClientResponseBuilder; +import com.botdarr.commands.responses.CommandResponse; +import com.botdarr.commands.responses.ErrorResponse; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.util.Strings; +import java.util.Collections; import java.util.List; public class CommandProcessor { - public CommandResponse processMessage(List apiCommands, - String strippedMessage, - String username, - ChatClientResponseBuilder chatClientResponseBuilder) { + public List processRequestMessage(List apiCommands, + String strippedMessage, + String username) { try { String rawMessage = strippedMessage.toLowerCase(); String commandPrefix = getPrefix(); @@ -37,12 +37,12 @@ public CommandResponse processMess } } } - return new CommandResponse(chatClientResponseBuilder.createErrorMessage("Invalid command - type " + commandPrefix + "help for command usage")); + return Collections.singletonList(new ErrorResponse("Invalid command - type " + commandPrefix + "help for command usage")); } } catch (Throwable e) { LOGGER.error("Error trying to execute command " + strippedMessage, e); - return new CommandResponse(chatClientResponseBuilder.createErrorMessage("Error trying to parse command " + strippedMessage + ", error=" + e.getMessage())); + return Collections.singletonList(new ErrorResponse("Error trying to parse command " + strippedMessage + ", error=" + e.getMessage())); } return null; } diff --git a/src/main/java/com/botdarr/commands/CommandResponse.java b/src/main/java/com/botdarr/commands/CommandResponse.java deleted file mode 100644 index ccb58d4..0000000 --- a/src/main/java/com/botdarr/commands/CommandResponse.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.botdarr.commands; - -import com.botdarr.clients.ChatClientResponse; - -import java.util.List; - -public class CommandResponse { - public CommandResponse(T singleChatClientResponse) { - this.singleChatClientResponse = singleChatClientResponse; - } - - public CommandResponse(List multipleChatClientResponses) { - this.multipleChatClientResponses = multipleChatClientResponses; - } - - public T getSingleChatClientResponse() { - return singleChatClientResponse; - } - - public List getMultipleChatClientResponses() { - return multipleChatClientResponses; - } - - private T singleChatClientResponse; - private List multipleChatClientResponses; -} diff --git a/src/main/java/com/botdarr/commands/HelpCommands.java b/src/main/java/com/botdarr/commands/HelpCommands.java index cd0f48e..e8a45bc 100644 --- a/src/main/java/com/botdarr/commands/HelpCommands.java +++ b/src/main/java/com/botdarr/commands/HelpCommands.java @@ -1,39 +1,38 @@ package com.botdarr.commands; -import com.botdarr.clients.ChatClientResponse; -import com.botdarr.clients.ChatClientResponseBuilder; +import com.botdarr.commands.responses.*; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class HelpCommands { - public static List getCommands(ChatClientResponseBuilder chatClientResponseBuilder, - List radarrCommands, + public static List getCommands(List radarrCommands, List sonarrCommands, List lidarrCommands) { return new ArrayList() {{ add(new BaseHelpCommand("help", "") { @Override - public CommandResponse execute(String command) { - return new CommandResponse(chatClientResponseBuilder.getHelpResponse()); + public List execute(String command) { + return Collections.singletonList(new HelpResponse()); } }); add(new BaseHelpCommand("movies help", "") { @Override - public CommandResponse execute(String command) { - return new CommandResponse(chatClientResponseBuilder.getMoviesHelpResponse(radarrCommands)); + public List execute(String command) { + return Collections.singletonList(new MoviesHelpResponse(radarrCommands)); } }); add(new BaseHelpCommand("shows help", "") { @Override - public CommandResponse execute(String command) { - return new CommandResponse(chatClientResponseBuilder.getShowsHelpResponse(sonarrCommands)); + public List execute(String command) { + return Collections.singletonList(new ShowsHelpResponse(sonarrCommands)); } }); add(new BaseHelpCommand("music help", "") { @Override - public CommandResponse execute(String command) { - return new CommandResponse(chatClientResponseBuilder.getMusicHelpResponse(lidarrCommands)); + public List execute(String command) { + return Collections.singletonList(new MusicHelpResponse(lidarrCommands)); } }); }}; diff --git a/src/main/java/com/botdarr/commands/StatusCommand.java b/src/main/java/com/botdarr/commands/StatusCommand.java index d342318..d83aec4 100644 --- a/src/main/java/com/botdarr/commands/StatusCommand.java +++ b/src/main/java/com/botdarr/commands/StatusCommand.java @@ -1,26 +1,27 @@ package com.botdarr.commands; import com.botdarr.Config; -import com.botdarr.clients.ChatClientResponse; -import com.botdarr.clients.ChatClientResponseBuilder; +import com.botdarr.commands.responses.CommandResponse; +import com.botdarr.commands.responses.ErrorResponse; +import com.botdarr.commands.responses.StatusCommandResponse; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -public class StatusCommand extends BaseCommand { - public StatusCommand(ChatClientResponseBuilder responseChatClientResponseBuilder) { +public class StatusCommand extends BaseCommand { + public StatusCommand() { super(STATUS_COMMAND, STATUS_COMMAND_DESCRIPTION); - this.responseChatClientResponseBuilder = responseChatClientResponseBuilder; } @Override - public CommandResponse execute(String command) { + public List execute(String command) { List endpoints = Config.getStatusEndpoints(); if (!endpoints.isEmpty()) { Map endpointStatuses = new HashMap<>(); @@ -33,12 +34,10 @@ public CommandResponse execute(String command) { endpointStatuses.put(endPoint.name, false); } } - return new CommandResponse(responseChatClientResponseBuilder.getStatusCommandResponse(endpointStatuses)); + return Collections.singletonList(new StatusCommandResponse(endpointStatuses)); } - return new CommandResponse( - responseChatClientResponseBuilder.createErrorMessage("No status endpoints configured")); + return Collections.singletonList(new ErrorResponse("No status endpoints configured")); } - private final ChatClientResponseBuilder responseChatClientResponseBuilder; public static class StatusEndPoint { public StatusEndPoint(String name, String hostname, int port) { diff --git a/src/main/java/com/botdarr/commands/responses/CommandResponse.java b/src/main/java/com/botdarr/commands/responses/CommandResponse.java new file mode 100644 index 0000000..278cfa9 --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/CommandResponse.java @@ -0,0 +1,8 @@ +package com.botdarr.commands.responses; + +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +public interface CommandResponse { + public T convertToChatClientResponse(ChatClientResponseBuilder builder); +} diff --git a/src/main/java/com/botdarr/commands/responses/DiscoverMovieResponse.java b/src/main/java/com/botdarr/commands/responses/DiscoverMovieResponse.java new file mode 100644 index 0000000..448b990 --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/DiscoverMovieResponse.java @@ -0,0 +1,21 @@ +package com.botdarr.commands.responses; + +import com.botdarr.api.radarr.RadarrMovie; +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +public class DiscoverMovieResponse implements CommandResponse { + private final RadarrMovie radarrMovie; + public DiscoverMovieResponse(RadarrMovie radarrMovie) { + this.radarrMovie = radarrMovie; + } + + public RadarrMovie getRadarrMovie() { + return radarrMovie; + } + + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/ErrorResponse.java b/src/main/java/com/botdarr/commands/responses/ErrorResponse.java new file mode 100644 index 0000000..a957166 --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/ErrorResponse.java @@ -0,0 +1,18 @@ +package com.botdarr.commands.responses; + +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +public class ErrorResponse implements CommandResponse { + private final String errorMessage; + public ErrorResponse(String errorMessage) { + this.errorMessage = errorMessage; + } + public String getErrorMessage() { + return errorMessage; + } + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/ExistingMovieResponse.java b/src/main/java/com/botdarr/commands/responses/ExistingMovieResponse.java new file mode 100644 index 0000000..3055ec4 --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/ExistingMovieResponse.java @@ -0,0 +1,19 @@ +package com.botdarr.commands.responses; + +import com.botdarr.api.radarr.RadarrMovie; +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +public class ExistingMovieResponse implements CommandResponse { + private final RadarrMovie existingMovie; + public ExistingMovieResponse(RadarrMovie existingItem) { + this.existingMovie = existingItem; + } + public RadarrMovie getRadarrMovie() { + return existingMovie; + } + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/ExistingMusicArtistResponse.java b/src/main/java/com/botdarr/commands/responses/ExistingMusicArtistResponse.java new file mode 100644 index 0000000..9491c81 --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/ExistingMusicArtistResponse.java @@ -0,0 +1,21 @@ +package com.botdarr.commands.responses; + +import com.botdarr.api.lidarr.LidarrArtist; +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +public class ExistingMusicArtistResponse implements CommandResponse { + private final LidarrArtist existingItem; + public ExistingMusicArtistResponse(LidarrArtist existingItem) { + this.existingItem = existingItem; + } + + public LidarrArtist getLidarrArtist() { + return existingItem; + } + + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/ExistingShowResponse.java b/src/main/java/com/botdarr/commands/responses/ExistingShowResponse.java new file mode 100644 index 0000000..1f5453b --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/ExistingShowResponse.java @@ -0,0 +1,19 @@ +package com.botdarr.commands.responses; + +import com.botdarr.api.sonarr.SonarrShow; +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +public class ExistingShowResponse implements CommandResponse { + private final SonarrShow existingShow; + public ExistingShowResponse(SonarrShow existingShow) { + this.existingShow = existingShow; + } + public SonarrShow getExistingShow() { + return existingShow; + } + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/HelpResponse.java b/src/main/java/com/botdarr/commands/responses/HelpResponse.java new file mode 100644 index 0000000..66ec1ec --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/HelpResponse.java @@ -0,0 +1,11 @@ +package com.botdarr.commands.responses; + +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +public class HelpResponse implements CommandResponse { + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/InfoResponse.java b/src/main/java/com/botdarr/commands/responses/InfoResponse.java new file mode 100644 index 0000000..660742f --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/InfoResponse.java @@ -0,0 +1,18 @@ +package com.botdarr.commands.responses; + +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +public class InfoResponse implements CommandResponse { + private final String infoMessage; + public InfoResponse(String infoMessage) { + this.infoMessage = infoMessage; + } + public String getInfoMessage() { + return infoMessage; + } + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/MovieDownloadResponse.java b/src/main/java/com/botdarr/commands/responses/MovieDownloadResponse.java new file mode 100644 index 0000000..e168738 --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/MovieDownloadResponse.java @@ -0,0 +1,20 @@ +package com.botdarr.commands.responses; + +import com.botdarr.api.radarr.RadarrQueue; +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +public class MovieDownloadResponse implements CommandResponse { + private final RadarrQueue radarrQueue; + public MovieDownloadResponse(RadarrQueue radarrQueue) { + this.radarrQueue = radarrQueue; + } + public RadarrQueue getRadarrQueue() { + return radarrQueue; + } + + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/MovieProfileResponse.java b/src/main/java/com/botdarr/commands/responses/MovieProfileResponse.java new file mode 100644 index 0000000..19a65f7 --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/MovieProfileResponse.java @@ -0,0 +1,19 @@ +package com.botdarr.commands.responses; + +import com.botdarr.api.radarr.RadarrProfile; +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +public class MovieProfileResponse implements CommandResponse { + private final RadarrProfile radarrProfile; + public MovieProfileResponse(RadarrProfile radarrProfile) { + this.radarrProfile = radarrProfile; + } + public RadarrProfile getRadarrProfile() { + return radarrProfile; + } + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/MovieResponse.java b/src/main/java/com/botdarr/commands/responses/MovieResponse.java new file mode 100644 index 0000000..e0d012f --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/MovieResponse.java @@ -0,0 +1,19 @@ +package com.botdarr.commands.responses; + +import com.botdarr.api.radarr.RadarrMovie; +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +public class MovieResponse implements CommandResponse { + private final RadarrMovie movie; + public MovieResponse(RadarrMovie item) { + this.movie = item; + } + public RadarrMovie getRadarrMovie() { + return movie; + } + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/MoviesHelpResponse.java b/src/main/java/com/botdarr/commands/responses/MoviesHelpResponse.java new file mode 100644 index 0000000..5fbf65a --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/MoviesHelpResponse.java @@ -0,0 +1,24 @@ +package com.botdarr.commands.responses; + +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; +import com.botdarr.commands.Command; + +import java.util.List; + +public class MoviesHelpResponse implements CommandResponse { + private final List radarrCommands; + + public MoviesHelpResponse(List radarrCommands) { + this.radarrCommands = radarrCommands; + } + + public List getRadarrCommands() { + return radarrCommands; + } + + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/MusicArtistDownloadResponse.java b/src/main/java/com/botdarr/commands/responses/MusicArtistDownloadResponse.java new file mode 100644 index 0000000..bb657d7 --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/MusicArtistDownloadResponse.java @@ -0,0 +1,21 @@ +package com.botdarr.commands.responses; + +import com.botdarr.api.lidarr.LidarrQueueRecord; +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +public class MusicArtistDownloadResponse implements CommandResponse { + private final LidarrQueueRecord lidarrQueueRecord; + public MusicArtistDownloadResponse(LidarrQueueRecord lidarrQueueRecord) { + this.lidarrQueueRecord = lidarrQueueRecord; + } + + public LidarrQueueRecord getQueueRecord() { + return this.lidarrQueueRecord; + } + + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/MusicArtistResponse.java b/src/main/java/com/botdarr/commands/responses/MusicArtistResponse.java new file mode 100644 index 0000000..dca7804 --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/MusicArtistResponse.java @@ -0,0 +1,21 @@ +package com.botdarr.commands.responses; + +import com.botdarr.api.lidarr.LidarrArtist; +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +public class MusicArtistResponse implements CommandResponse { + private final LidarrArtist lidarrArtist; + public MusicArtistResponse(LidarrArtist lidarrArtist) { + this.lidarrArtist = lidarrArtist; + } + + public LidarrArtist getArtist() { + return lidarrArtist; + } + + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/MusicHelpResponse.java b/src/main/java/com/botdarr/commands/responses/MusicHelpResponse.java new file mode 100644 index 0000000..e8cc6ab --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/MusicHelpResponse.java @@ -0,0 +1,24 @@ +package com.botdarr.commands.responses; + +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; +import com.botdarr.commands.Command; + +import java.util.List; + +public class MusicHelpResponse implements CommandResponse { + private final List lidarrCommands; + + public MusicHelpResponse(List lidarrCommands) { + this.lidarrCommands = lidarrCommands; + } + + public List getLidarrCommands() { + return lidarrCommands; + } + + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/NewMovieResponse.java b/src/main/java/com/botdarr/commands/responses/NewMovieResponse.java new file mode 100644 index 0000000..c7eda6d --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/NewMovieResponse.java @@ -0,0 +1,19 @@ +package com.botdarr.commands.responses; + +import com.botdarr.api.radarr.RadarrMovie; +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +public class NewMovieResponse implements CommandResponse { + private final RadarrMovie newMovie; + public NewMovieResponse(RadarrMovie lookupItem) { + this.newMovie = lookupItem; + } + public RadarrMovie getRadarrMovie() { + return newMovie; + } + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/NewMusicArtistResponse.java b/src/main/java/com/botdarr/commands/responses/NewMusicArtistResponse.java new file mode 100644 index 0000000..3809d44 --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/NewMusicArtistResponse.java @@ -0,0 +1,21 @@ +package com.botdarr.commands.responses; + +import com.botdarr.api.lidarr.LidarrArtist; +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +public class NewMusicArtistResponse implements CommandResponse { + private final LidarrArtist lookupItem; + public NewMusicArtistResponse(LidarrArtist lookupItem) { + this.lookupItem = lookupItem; + } + + public LidarrArtist getLidarrArtist() { + return this.lookupItem; + } + + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/NewShowResponse.java b/src/main/java/com/botdarr/commands/responses/NewShowResponse.java new file mode 100644 index 0000000..824103c --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/NewShowResponse.java @@ -0,0 +1,19 @@ +package com.botdarr.commands.responses; + +import com.botdarr.api.sonarr.SonarrShow; +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +public class NewShowResponse implements CommandResponse { + private final SonarrShow newShow; + public NewShowResponse(SonarrShow newShow) { + this.newShow = newShow; + } + public SonarrShow getNewShow() { + return newShow; + } + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/ShowDownloadResponse.java b/src/main/java/com/botdarr/commands/responses/ShowDownloadResponse.java new file mode 100644 index 0000000..8ead06b --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/ShowDownloadResponse.java @@ -0,0 +1,20 @@ +package com.botdarr.commands.responses; + +import com.botdarr.api.sonarr.SonarrQueue; +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +public class ShowDownloadResponse implements CommandResponse { + private final SonarrQueue showQueue; + public ShowDownloadResponse(SonarrQueue showQueue) { + this.showQueue = showQueue; + } + public SonarrQueue getShowQueue() { + return showQueue; + } + + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/ShowProfileResponse.java b/src/main/java/com/botdarr/commands/responses/ShowProfileResponse.java new file mode 100644 index 0000000..466b459 --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/ShowProfileResponse.java @@ -0,0 +1,19 @@ +package com.botdarr.commands.responses; + +import com.botdarr.api.sonarr.SonarrProfile; +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +public class ShowProfileResponse implements CommandResponse { + private final SonarrProfile showProfile; + public ShowProfileResponse(SonarrProfile showProfile) { + this.showProfile = showProfile; + } + public SonarrProfile getShowProfile() { + return showProfile; + } + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/ShowResponse.java b/src/main/java/com/botdarr/commands/responses/ShowResponse.java new file mode 100644 index 0000000..b9a5695 --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/ShowResponse.java @@ -0,0 +1,19 @@ +package com.botdarr.commands.responses; + +import com.botdarr.api.sonarr.SonarrShow; +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +public class ShowResponse implements CommandResponse { + private final SonarrShow show; + public ShowResponse(SonarrShow show) { + this.show = show; + } + public SonarrShow getShow() { + return show; + } + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/ShowsHelpResponse.java b/src/main/java/com/botdarr/commands/responses/ShowsHelpResponse.java new file mode 100644 index 0000000..161fae3 --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/ShowsHelpResponse.java @@ -0,0 +1,24 @@ +package com.botdarr.commands.responses; + +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; +import com.botdarr.commands.Command; + +import java.util.List; + +public class ShowsHelpResponse implements CommandResponse { + private final List sonarrCommands; + + public ShowsHelpResponse(List sonarrCommands) { + this.sonarrCommands = sonarrCommands; + } + + public List getSonarrCommands() { + return sonarrCommands; + } + + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/StatusCommandResponse.java b/src/main/java/com/botdarr/commands/responses/StatusCommandResponse.java new file mode 100644 index 0000000..4653560 --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/StatusCommandResponse.java @@ -0,0 +1,20 @@ +package com.botdarr.commands.responses; + +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +import java.util.Map; + +public class StatusCommandResponse implements CommandResponse { + private final Map endpointStatuses; + public StatusCommandResponse(Map endpointStatuses) { + this.endpointStatuses = endpointStatuses; + } + public Map getEndpoints() { + return endpointStatuses; + } + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/commands/responses/SuccessResponse.java b/src/main/java/com/botdarr/commands/responses/SuccessResponse.java new file mode 100644 index 0000000..b887e0e --- /dev/null +++ b/src/main/java/com/botdarr/commands/responses/SuccessResponse.java @@ -0,0 +1,18 @@ +package com.botdarr.commands.responses; + +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; + +public class SuccessResponse implements CommandResponse { + private final String successMessage; + public SuccessResponse(String successMessage) { + this.successMessage = successMessage; + } + public String getSuccessMessage() { + return successMessage; + } + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return builder.build(this); + } +} diff --git a/src/main/java/com/botdarr/connections/ConnectionHelper.java b/src/main/java/com/botdarr/connections/ConnectionHelper.java index 9f999a2..08d2edb 100644 --- a/src/main/java/com/botdarr/connections/ConnectionHelper.java +++ b/src/main/java/com/botdarr/connections/ConnectionHelper.java @@ -2,8 +2,8 @@ import com.botdarr.api.Api; import com.botdarr.Config; -import com.botdarr.clients.ChatClientResponse; -import com.botdarr.clients.ChatClientResponseBuilder; +import com.botdarr.commands.responses.CommandResponse; +import com.botdarr.commands.responses.ErrorResponse; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.*; import org.apache.http.conn.HttpHostConnectException; @@ -14,7 +14,7 @@ import org.apache.logging.log4j.Logger; import java.io.IOException; -import java.util.Arrays; +import java.util.Collections; import java.util.List; public class ConnectionHelper { @@ -73,26 +73,24 @@ public static T makeRequest(RequestHandler requestHandler, ResponseHandler> { + public static abstract class SimpleMessageEmbedResponseHandler implements ResponseHandler> { @Override - public List onConnectException(HttpHostConnectException e) { + public List onConnectException(HttpHostConnectException e) { return onException(e); } - public SimpleMessageEmbedResponseHandler(ChatClientResponseBuilder chatClientResponseBuilder) { - this.chatClientResponseBuilder = chatClientResponseBuilder; + public SimpleMessageEmbedResponseHandler() { } @Override - public List onFailure(int statusCode, String reason) { - return Arrays.asList(chatClientResponseBuilder.createErrorMessage("Request failed with status code=" + statusCode + ", reason=" + reason)); + public List onFailure(int statusCode, String reason) { + return Collections.singletonList(new ErrorResponse("Request failed with status code=" + statusCode + ", reason=" + reason)); } @Override - public List onException(Exception e) { - return Arrays.asList(chatClientResponseBuilder.createErrorMessage("Requested failed with exception, e=" + e.getMessage() + ",class=" + e.getClass())); + public List onException(Exception e) { + return Collections.singletonList(new ErrorResponse("Requested failed with exception, e=" + e.getMessage() + ",class=" + e.getClass())); } - private ChatClientResponseBuilder chatClientResponseBuilder; } public static abstract class SimpleEntityResponseHandler implements ResponseHandler { diff --git a/src/main/java/com/botdarr/database/Bootstrap.java b/src/main/java/com/botdarr/database/DatabaseBootstrap.java similarity index 92% rename from src/main/java/com/botdarr/database/Bootstrap.java rename to src/main/java/com/botdarr/database/DatabaseBootstrap.java index e9fa1ff..db398fc 100644 --- a/src/main/java/com/botdarr/database/Bootstrap.java +++ b/src/main/java/com/botdarr/database/DatabaseBootstrap.java @@ -10,11 +10,11 @@ import java.sql.DriverManager; import java.sql.SQLException; -public class Bootstrap { - private Bootstrap() {} +public class DatabaseBootstrap { + private DatabaseBootstrap() {} public static void init() { - Bootstrap bootstrap = new Bootstrap(); + DatabaseBootstrap bootstrap = new DatabaseBootstrap(); if (!bootstrap.databaseExists()) { bootstrap.createDatabase(); } diff --git a/src/main/java/com/botdarr/scheduling/Scheduler.java b/src/main/java/com/botdarr/scheduling/Scheduler.java index 236710c..e0911c6 100644 --- a/src/main/java/com/botdarr/scheduling/Scheduler.java +++ b/src/main/java/com/botdarr/scheduling/Scheduler.java @@ -2,9 +2,13 @@ import com.botdarr.api.Api; import com.botdarr.clients.ChatClient; +import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; +import com.botdarr.commands.responses.CommandResponse; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.util.Collections; import java.util.List; import java.util.concurrent.*; @@ -21,12 +25,16 @@ public static Scheduler getScheduler() { } - public void initApiNotifications(List apis, ChatClient chatClient) { + public void initApiNotifications(List apis, ChatClient chatClient, ChatClientResponseBuilder responseBuilder) { if (notificationFuture == null) { notificationFuture = Executors.newScheduledThreadPool(1).scheduleWithFixedDelay(() -> { try { for (Api api : apis) { - api.sendPeriodicNotifications(chatClient); + List downloads = api.downloads(); + for (CommandResponse commandResponse : downloads) { + T response = commandResponse.convertToChatClientResponse(responseBuilder); + chatClient.sendToConfiguredChannels(Collections.singletonList(response)); + } } } catch (Throwable e) { LOGGER.error("Error during api notification", e); diff --git a/src/main/resources/version.txt b/src/main/resources/version.txt index fff6bf3..e230c83 100644 --- a/src/main/resources/version.txt +++ b/src/main/resources/version.txt @@ -1 +1 @@ -5.2.3 \ No newline at end of file +5.3.0 \ No newline at end of file diff --git a/src/test/java/com/botdarr/ConfigTests.java b/src/test/java/com/botdarr/ConfigTests.java index 8963a0c..3682e45 100644 --- a/src/test/java/com/botdarr/ConfigTests.java +++ b/src/test/java/com/botdarr/ConfigTests.java @@ -61,7 +61,7 @@ public void getConfig_invalidCommandPrefixConfigured() throws Exception { public void getConfig_noChatClientsConfigured() throws Exception { writeFakePropertiesFile(new Properties()); expectedException.expect(RuntimeException.class); - expectedException.expectMessage("You don't have Discord, Matrix, Slack, Telegram configured, please configure one"); + expectedException.expectMessage("You don't have any chat clients configured, please configure one"); Config.getProperty(""); } diff --git a/src/test/java/com/botdarr/TestClientResponse.java b/src/test/java/com/botdarr/TestClientResponse.java new file mode 100644 index 0000000..a005931 --- /dev/null +++ b/src/test/java/com/botdarr/TestClientResponse.java @@ -0,0 +1,6 @@ +package com.botdarr; + +import com.botdarr.clients.ChatClientResponse; + +public class TestClientResponse implements ChatClientResponse { +} diff --git a/src/test/java/com/botdarr/TestResponse.java b/src/test/java/com/botdarr/TestCommandResponse.java similarity index 53% rename from src/test/java/com/botdarr/TestResponse.java rename to src/test/java/com/botdarr/TestCommandResponse.java index 9258e13..4db5ee2 100644 --- a/src/test/java/com/botdarr/TestResponse.java +++ b/src/test/java/com/botdarr/TestCommandResponse.java @@ -3,16 +3,18 @@ import com.botdarr.api.radarr.RadarrMovie; import com.botdarr.api.radarr.RadarrQueue; import com.botdarr.clients.ChatClientResponse; +import com.botdarr.clients.ChatClientResponseBuilder; +import com.botdarr.commands.responses.CommandResponse; -public class TestResponse implements ChatClientResponse { - public TestResponse() {} - public TestResponse(RadarrMovie radarrMovie) { +public class TestCommandResponse implements CommandResponse { + public TestCommandResponse() {} + public TestCommandResponse(RadarrMovie radarrMovie) { this.radarrMovie = radarrMovie; } - public TestResponse(String responseMessage) { + public TestCommandResponse(String responseMessage) { this.responseMessage = responseMessage; } - public TestResponse(RadarrQueue radarrQueue) { + public TestCommandResponse(RadarrQueue radarrQueue) { this.radarrQueue = radarrQueue; } @@ -31,4 +33,9 @@ public RadarrQueue getRadarrQueue() { private String responseMessage; private RadarrMovie radarrMovie; private RadarrQueue radarrQueue; + + @Override + public T convertToChatClientResponse(ChatClientResponseBuilder builder) { + return null; + } } \ No newline at end of file diff --git a/src/test/java/com/botdarr/TestResponseBuilder.java b/src/test/java/com/botdarr/TestResponseBuilder.java index 41154cd..8aebf89 100644 --- a/src/test/java/com/botdarr/TestResponseBuilder.java +++ b/src/test/java/com/botdarr/TestResponseBuilder.java @@ -1,118 +1,122 @@ package com.botdarr; -import com.botdarr.api.lidarr.LidarrArtist; -import com.botdarr.api.lidarr.LidarrQueueRecord; -import com.botdarr.api.radarr.RadarrMovie; -import com.botdarr.api.radarr.RadarrProfile; -import com.botdarr.api.radarr.RadarrQueue; -import com.botdarr.api.sonarr.SonarrProfile; -import com.botdarr.api.sonarr.SonarrQueue; -import com.botdarr.api.sonarr.SonarrShow; import com.botdarr.clients.ChatClientResponseBuilder; -import com.botdarr.commands.Command; +import com.botdarr.commands.responses.*; -import java.util.List; -import java.util.Map; +public class TestResponseBuilder implements ChatClientResponseBuilder { -public class TestResponseBuilder implements ChatClientResponseBuilder { + @Override + public TestClientResponse build(HelpResponse helpResponse) { + return new TestClientResponse(); + } + + @Override + public TestClientResponse build(MusicHelpResponse musicHelpResponse) { + return new TestClientResponse(); + } + + @Override + public TestClientResponse build(MoviesHelpResponse moviesHelpResponse) { + return new TestClientResponse(); + } @Override - public TestResponse getHelpResponse() { - return new TestResponse(); + public TestClientResponse build(ShowsHelpResponse showsHelpResponse) { + return new TestClientResponse(); } @Override - public TestResponse getMusicHelpResponse(List lidarCommands) { - return new TestResponse(); + public TestClientResponse build(ShowResponse showResponse) { + return new TestClientResponse(); } @Override - public TestResponse getMoviesHelpResponse(List radarrCommands) { - return new TestResponse(); + public TestClientResponse build(MusicArtistResponse musicArtistResponse) { + return new TestClientResponse(); } @Override - public TestResponse getShowsHelpResponse(List sonarrCommands) { - return new TestResponse(); + public TestClientResponse build(MovieResponse movieResponse) { + return new TestClientResponse(); } @Override - public TestResponse getShowResponse(SonarrShow show) { - return new TestResponse(); + public TestClientResponse build(ShowDownloadResponse showDownloadResponse) { + return new TestClientResponse(); } @Override - public TestResponse getArtistResponse(LidarrArtist lidarrArtist) { - return new TestResponse(); + public TestClientResponse build(MovieDownloadResponse movieDownloadResponse) { + return new TestClientResponse(); } @Override - public TestResponse getShowDownloadResponses(SonarrQueue sonarrShow) { - return new TestResponse(); + public TestClientResponse build(MusicArtistDownloadResponse musicArtistDownloadResponse) { + return new TestClientResponse(); } @Override - public TestResponse getMovieDownloadResponses(RadarrQueue radarrQueue) { - return new TestResponse(radarrQueue); + public TestClientResponse build(ErrorResponse errorResponse) { + return new TestClientResponse(); } @Override - public TestResponse getArtistDownloadResponses(LidarrQueueRecord lidarrQueueRecord) { - return new TestResponse(); + public TestClientResponse build(InfoResponse infoResponse) { + return new TestClientResponse(); } @Override - public TestResponse createErrorMessage(String message) { - return new TestResponse(message); + public TestClientResponse build(SuccessResponse successResponse) { + return new TestClientResponse(); } @Override - public TestResponse createInfoMessage(String message) { - return new TestResponse(message); + public TestClientResponse build(ShowProfileResponse showProfileResponse) { + return new TestClientResponse(); } @Override - public TestResponse createSuccessMessage(String message) { - return new TestResponse(message); + public TestClientResponse build(MovieProfileResponse movieProfileResponse) { + return new TestClientResponse(); } @Override - public TestResponse getShowProfile(SonarrProfile sonarrProfile) { - return new TestResponse(); + public TestClientResponse build(NewShowResponse newShowResponse) { + return new TestClientResponse(); } @Override - public TestResponse getMovieProfile(RadarrProfile radarrProfile) { - return new TestResponse(); + public TestClientResponse build(ExistingShowResponse existingShowResponse) { + return new TestClientResponse(); } @Override - public TestResponse getNewOrExistingShow(SonarrShow sonarrShow, SonarrShow existingShow, boolean findNew) { - return new TestResponse(); + public TestClientResponse build(NewMovieResponse newMovieResponse) { + return new TestClientResponse(); } @Override - public TestResponse getNewOrExistingMovie(RadarrMovie lookupMovie, RadarrMovie existingMovie, boolean findNew) { - return new TestResponse(lookupMovie); + public TestClientResponse build(ExistingMovieResponse existingMovieResponse) { + return new TestClientResponse(); } @Override - public TestResponse getNewOrExistingArtist(LidarrArtist lookupArtist, LidarrArtist existingArtist, boolean findNew) { - return new TestResponse(); + public TestClientResponse build(NewMusicArtistResponse newMusicArtistResponse) { + return new TestClientResponse(); } @Override - public TestResponse getMovieResponse(RadarrMovie radarrMovie) { - return new TestResponse(radarrMovie); + public TestClientResponse build(ExistingMusicArtistResponse exitingMusicArtistResponse) { + return new TestClientResponse(); } @Override - public TestResponse getDiscoverableMovies(RadarrMovie radarrMovie) { - return new TestResponse(radarrMovie); + public TestClientResponse build(DiscoverMovieResponse discoverMovieResponse) { + return new TestClientResponse(); } @Override - public TestResponse getStatusCommandResponse(Map endpointStatuses) { - return new TestResponse(); + public TestClientResponse build(StatusCommandResponse statusCommandResponse) { + return new TestClientResponse(); } } \ No newline at end of file diff --git a/src/test/java/com/botdarr/api/AddStrategyTests.java b/src/test/java/com/botdarr/api/AddStrategyTests.java index 61ad906..ce1fc28 100644 --- a/src/test/java/com/botdarr/api/AddStrategyTests.java +++ b/src/test/java/com/botdarr/api/AddStrategyTests.java @@ -1,9 +1,11 @@ package com.botdarr.api; -import com.botdarr.TestResponse; -import com.botdarr.clients.ChatClientResponse; -import com.botdarr.clients.ChatClientResponseBuilder; +import com.botdarr.TestCommandResponse; +import com.botdarr.commands.responses.CommandResponse; +import com.botdarr.commands.responses.ErrorResponse; +import com.botdarr.commands.responses.InfoResponse; import mockit.*; +import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.logging.log4j.Logger; import org.junit.Assert; import org.junit.BeforeClass; @@ -35,9 +37,13 @@ public void addWithSearchId_noMoviesFound_errorResponse() throws Exception { mockAddStrategy.lookupContent(searchText); times = 1; result = Collections.emptyList(); logger.warn("Search id " + searchId + "yielded no movies, stopping"); mockAddStrategy.lookupItemById(searchId); times = 1; result = Collections.emptyList(); - chatClientResponseBuilder.createErrorMessage("No movies found"); times = 1; result = new TestResponse(""); }}; - Assert.assertNotNull(mockAddStrategy.addWithSearchId(searchText, searchId)); + CommandResponse commandResponse = mockAddStrategy.addWithSearchId(searchText, searchId); + Assert.assertNotNull(commandResponse); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new ErrorResponse("No movies found"), + commandResponse)); } @Test @@ -50,9 +56,13 @@ public void addWithSearchId_moviesFound_movieExistsAlready_errorResponse() throw mockAddStrategy.lookupContent(searchText); times = 1; result = Arrays.asList(movie); mockAddStrategy.getItemId(movie); times = 1; result = searchId; mockAddStrategy.doesItemExist(movie); times = 1; result = true; - chatClientResponseBuilder.createErrorMessage("movie already exists"); }}; - Assert.assertNotNull(mockAddStrategy.addWithSearchId(searchText, searchId)); + CommandResponse commandResponse = mockAddStrategy.addWithSearchId(searchText, searchId); + Assert.assertNotNull(commandResponse); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new ErrorResponse("movie already exists"), + commandResponse)); } @Test @@ -64,9 +74,13 @@ public void addWithSearchId_moviesFound_itemIdsDontMatch_errorResponse() throws new Expectations(mockAddStrategy) {{ mockAddStrategy.lookupContent(searchText); times = 1; result = Arrays.asList(movie); mockAddStrategy.getItemId(movie); times = 1; result = "unknownId"; - chatClientResponseBuilder.createErrorMessage("Could not find movie with search text=" + searchText + " and id=" + searchId); }}; - Assert.assertNotNull(mockAddStrategy.addWithSearchId(searchText, searchId)); + CommandResponse commandResponse = mockAddStrategy.addWithSearchId(searchText, searchId); + Assert.assertNotNull(commandResponse); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new ErrorResponse("Could not find movie with search text=" + searchText + " and id=" + searchId), + commandResponse)); } @Test @@ -75,16 +89,16 @@ public void addWithSearchId_moviesFound_addMovieResponseReturned() throws Except String searchText = "searchText1"; String searchId = "searchId1"; Object movie = new Object(); - TestResponse expectedResponse = new TestResponse(); + TestCommandResponse expectedResponse = new TestCommandResponse(); new Expectations(mockAddStrategy) {{ mockAddStrategy.lookupContent(searchText); times = 1; result = Arrays.asList(movie); mockAddStrategy.getItemId(movie); times = 1; result = searchId; mockAddStrategy.doesItemExist(movie); times = 1; result = false; mockAddStrategy.addContent(movie); times = 1; result = expectedResponse; }}; - ChatClientResponse chatClientResponse = mockAddStrategy.addWithSearchId(searchText, searchId); - Assert.assertNotNull(chatClientResponse); - Assert.assertEquals(expectedResponse, chatClientResponse); + CommandResponse commandResponse = mockAddStrategy.addWithSearchId(searchText, searchId); + Assert.assertNotNull(commandResponse); + Assert.assertEquals(expectedResponse, commandResponse); } @Test @@ -96,9 +110,13 @@ public void addWithSearchId_exceptionThrown_errorResponse() throws Exception { new Expectations(mockAddStrategy) {{ mockAddStrategy.lookupContent(searchText); times = 1; result = expectedException; logger.error("Error trying to add movie", expectedException); times = 1; - chatClientResponseBuilder.createErrorMessage("Error adding content, e=expected error"); times = 1; result = new TestResponse(); }}; - Assert.assertNotNull(mockAddStrategy.addWithSearchId(searchText, searchId)); + CommandResponse commandResponse = mockAddStrategy.addWithSearchId(searchText, searchId); + Assert.assertNotNull(commandResponse); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new ErrorResponse("Error adding content, e=expected error"), + commandResponse)); } @Test @@ -107,9 +125,14 @@ public void addWithSearchTitle_noMoviesFound_errorResponse() throws Exception { String searchText = "searchText1"; new Expectations(mockAddStrategy) {{ mockAddStrategy.lookupContent(searchText); times = 1; result = Collections.emptyList(); - chatClientResponseBuilder.createInfoMessage("No movies found"); times = 1; result = new TestResponse(); }}; - Assert.assertNotNull(mockAddStrategy.addWithSearchTitle(searchText)); + List commandResponses = mockAddStrategy.addWithSearchTitle(searchText); + Assert.assertNotNull(commandResponses); + Assert.assertEquals(1, commandResponses.size()); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new InfoResponse("No movies found"), + commandResponses.get(0))); } @Test @@ -118,13 +141,16 @@ public void addWithSearchTitle_oneMovieFound_alreadyExists_errorResponse() throw String searchText = "searchText1"; Object foundMovie = new Object(); new Expectations(mockAddStrategy) {{ - mockAddStrategy.lookupContent(searchText); times = 1; result = Arrays.asList(foundMovie); + mockAddStrategy.lookupContent(searchText); times = 1; result = Collections.singletonList(foundMovie); mockAddStrategy.doesItemExist(foundMovie); times = 1; result = true; - chatClientResponseBuilder.createErrorMessage("movie already exists"); times = 1; result = new TestResponse(); }}; - List responses = mockAddStrategy.addWithSearchTitle(searchText); - Assert.assertNotNull(responses); - Assert.assertEquals(1, responses.size()); + List commandResponses = mockAddStrategy.addWithSearchTitle(searchText); + Assert.assertNotNull(commandResponses); + Assert.assertEquals(1, commandResponses.size()); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new ErrorResponse("movie already exists"), + commandResponses.get(0))); } @Test @@ -132,16 +158,16 @@ public void addWithSearchTitle_oneMovieFound_doesntExist_addMovieResponseReturne MockAddStrategy mockAddStrategy = getMockAddStrategy(); String searchText = "searchText1"; Object foundMovie = new Object(); - TestResponse expectedResponse = new TestResponse(); + TestCommandResponse expectedResponse = new TestCommandResponse(); new Expectations(mockAddStrategy) {{ - mockAddStrategy.lookupContent(searchText); times = 1; result = Arrays.asList(foundMovie); + mockAddStrategy.lookupContent(searchText); times = 1; result = Collections.singletonList(foundMovie); mockAddStrategy.doesItemExist(foundMovie); times = 1; result = false; mockAddStrategy.addContent(foundMovie); times = 1; result = expectedResponse; }}; - List responses = mockAddStrategy.addWithSearchTitle(searchText); - Assert.assertNotNull(responses); - Assert.assertEquals(1, responses.size()); - Assert.assertEquals(expectedResponse, responses.get(0)); + List commandResponses = mockAddStrategy.addWithSearchTitle(searchText); + Assert.assertNotNull(commandResponses); + Assert.assertEquals(1, commandResponses.size()); + Assert.assertEquals(expectedResponse, commandResponses.get(0)); } @Test @@ -150,24 +176,26 @@ public void addWithSearchTitle_multipleMoviesFound_lessThanMaxResults_multipleAd String searchText = "searchText1"; Object foundMovie = new Object(); - TestResponse foundMovieResponse = new TestResponse(); + TestCommandResponse foundMovieResponse = new TestCommandResponse(); Object foundMovie2 = new Object(); - TestResponse foundMovieResponse2 = new TestResponse(); + TestCommandResponse foundMovieResponse2 = new TestCommandResponse(); - TestResponse expectedResponseInfoMessage = new TestResponse(); + TestCommandResponse expectedResponseInfoMessage = new TestCommandResponse(); new Expectations(mockAddStrategy) {{ mockAddStrategy.lookupContent(searchText); times = 1; result = Arrays.asList(foundMovie, foundMovie2); mockAddStrategy.doesItemExist(foundMovie); times = 1; result = false; mockAddStrategy.getResponse(foundMovie); times = 1; result = foundMovieResponse; mockAddStrategy.doesItemExist(foundMovie2); times = 1; result = false; mockAddStrategy.getResponse(foundMovie2); times = 1; result = foundMovieResponse2; - chatClientResponseBuilder.createInfoMessage("Too many movies found, please narrow search or increase max results to show"); times = 1; result = expectedResponseInfoMessage; }}; - List responses = mockAddStrategy.addWithSearchTitle(searchText); + List responses = mockAddStrategy.addWithSearchTitle(searchText); Assert.assertNotNull(responses); Assert.assertEquals(3, responses.size()); - Assert.assertEquals(expectedResponseInfoMessage, responses.get(0)); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new InfoResponse("Too many movies found, please narrow search or increase max results to show"), + responses.get(0))); Assert.assertEquals(foundMovieResponse, responses.get(1)); Assert.assertEquals(foundMovieResponse2, responses.get(2)); } @@ -179,24 +207,25 @@ public void addWithSearchTitle_multipleMoviesFound_moreThanMaxResults_multipleAd String searchText = "searchText1"; Object foundMovie = new Object(); - TestResponse foundMovieResponse = new TestResponse(); + TestCommandResponse foundMovieResponse = new TestCommandResponse(); Object foundMovie2 = new Object(); - TestResponse foundMovieResponse2 = new TestResponse(); + TestCommandResponse foundMovieResponse2 = new TestCommandResponse(); - TestResponse expectedResponseInfoMessage = new TestResponse(); new Expectations(mockAddStrategy) {{ mockAddStrategy.lookupContent(searchText); times = 1; result = Arrays.asList(foundMovie, foundMovie2); mockAddStrategy.doesItemExist(foundMovie); times = 1; result = false; mockAddStrategy.getResponse(foundMovie); times = 1; result = foundMovieResponse; mockAddStrategy.doesItemExist(foundMovie2); times = 1; result = false; mockAddStrategy.getResponse(foundMovie2); times = 1; result = foundMovieResponse2; - chatClientResponseBuilder.createInfoMessage("Too many movies found, please narrow search or increase max results to show"); times = 1; result = expectedResponseInfoMessage; }}; - List responses = mockAddStrategy.addWithSearchTitle(searchText); + List responses = mockAddStrategy.addWithSearchTitle(searchText); Assert.assertNotNull(responses); Assert.assertEquals(2, responses.size()); - Assert.assertEquals(expectedResponseInfoMessage, responses.get(0)); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new InfoResponse("Too many movies found, please narrow search or increase max results to show"), + responses.get(0))); Assert.assertEquals(foundMovieResponse, responses.get(1)); } @@ -206,16 +235,17 @@ public void addWithSearchTitle_multipleMoviesFound_allPreviouslyExist_infoRespon String searchText = "searchText1"; Object foundMovie = new Object(); Object foundMovie2 = new Object(); - TestResponse expectedResponseInfoMessage = new TestResponse(); new Expectations(mockAddStrategy) {{ mockAddStrategy.lookupContent(searchText); times = 1; result = Arrays.asList(foundMovie, foundMovie2); mockAddStrategy.doesItemExist(any); times = 2; result = true; - chatClientResponseBuilder.createInfoMessage("No new movies found, check existing movies"); times = 1; result = expectedResponseInfoMessage; }}; - List responses = mockAddStrategy.addWithSearchTitle(searchText); + List responses = mockAddStrategy.addWithSearchTitle(searchText); Assert.assertNotNull(responses); Assert.assertEquals(1, responses.size()); - Assert.assertEquals(expectedResponseInfoMessage, responses.get(0)); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new InfoResponse("No new movies found, check existing movies"), + responses.get(0))); } @Test @@ -223,20 +253,21 @@ public void addWithSearchTitle_exceptionThrown_errorResponse() throws Exception MockAddStrategy mockAddStrategy = getMockAddStrategy(); String searchText = "searchText1"; Exception expectedException = new Exception("expected error"); - TestResponse expectedResponseErrorMessage = new TestResponse(); new Expectations(mockAddStrategy) {{ mockAddStrategy.lookupContent(searchText); times = 1; result = expectedException; logger.error("Error trying to add movie", expectedException); times = 1; - chatClientResponseBuilder.createErrorMessage("Error trying to add movie, for search text=" + searchText + ", e=expected error"); times = 1; result = expectedResponseErrorMessage; }}; - List responses = mockAddStrategy.addWithSearchTitle(searchText); + List responses = mockAddStrategy.addWithSearchTitle(searchText); Assert.assertNotNull(responses); Assert.assertEquals(1, responses.size()); - Assert.assertEquals(expectedResponseErrorMessage, responses.get(0)); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new ErrorResponse("Error trying to add movie, for search text=searchText1, e=expected error"), + responses.get(0))); } private MockAddStrategy getMockAddStrategy(int maxResultsToShow) { - MockAddStrategy mockAddStrategy = new MockAddStrategy(chatClientResponseBuilder, ContentType.MOVIE); + MockAddStrategy mockAddStrategy = new MockAddStrategy(ContentType.MOVIE); Deencapsulation.setField(mockAddStrategy, "LOGGER", logger); Deencapsulation.setField(mockAddStrategy, "MAX_RESULTS_TO_SHOW", maxResultsToShow); return mockAddStrategy; @@ -249,12 +280,9 @@ private MockAddStrategy getMockAddStrategy() { @Mocked private Logger logger; - @Injectable - private ChatClientResponseBuilder chatClientResponseBuilder; - private static class MockAddStrategy extends AddStrategy { - public MockAddStrategy(ChatClientResponseBuilder chatClientResponseBuilder, ContentType contentType) { - super(chatClientResponseBuilder, contentType); + public MockAddStrategy(ContentType contentType) { + super(contentType); } @Override @@ -278,12 +306,12 @@ public String getItemId(Object item) { } @Override - public ChatClientResponse addContent(Object content) { + public CommandResponse addContent(Object content) { return null; } @Override - public ChatClientResponse getResponse(Object item) { + public CommandResponse getResponse(Object item) { return null; } } diff --git a/src/test/java/com/botdarr/api/ApiRequestsTests.java b/src/test/java/com/botdarr/api/ApiRequestsTests.java index ed98bc9..2708f46 100644 --- a/src/test/java/com/botdarr/api/ApiRequestsTests.java +++ b/src/test/java/com/botdarr/api/ApiRequestsTests.java @@ -1,7 +1,7 @@ package com.botdarr.api; import com.botdarr.Config; -import com.botdarr.database.Bootstrap; +import com.botdarr.database.DatabaseBootstrap; import com.botdarr.database.DatabaseHelper; import mockit.*; import org.junit.Assert; @@ -169,7 +169,7 @@ public void getMaxResultsToShow_configuredValueReturned() { private void testRequestThreshold(int maxRequestsToAdd, int maxRequestsAllowed, String threshold, boolean expectExceedsThreshold) throws Exception { //create temporary database new MockedDatabase(temporaryFolder.newFile()); - Bootstrap.init(); + DatabaseBootstrap.init(); ApiRequests apiRequests = new ApiRequests(); String username = "user1"; diff --git a/src/test/java/com/botdarr/api/DownloadsStrategyTests.java b/src/test/java/com/botdarr/api/DownloadsStrategyTests.java index aa95f7a..218810e 100644 --- a/src/test/java/com/botdarr/api/DownloadsStrategyTests.java +++ b/src/test/java/com/botdarr/api/DownloadsStrategyTests.java @@ -1,20 +1,17 @@ package com.botdarr.api; -import com.botdarr.TestResponse; -import com.botdarr.clients.ChatClientResponse; -import com.botdarr.clients.ChatClientResponseBuilder; -import com.google.gson.Gson; +import com.botdarr.TestCommandResponse; +import com.botdarr.commands.responses.CommandResponse; +import com.botdarr.commands.responses.InfoResponse; import com.google.gson.JsonElement; import mockit.*; +import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.logging.log4j.Logger; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.mockserver.junit.MockServerRule; -import org.mockserver.model.HttpRequest; -import org.mockserver.model.HttpResponse; -import org.mockserver.model.MediaType; import java.util.ArrayList; import java.util.List; @@ -34,7 +31,7 @@ public int getMaxDownloadsToShow() { @Test public void downloads_maxDownloadsToConfiguredToZero_noDownloadsReturned() { DownloadsStrategy mockDownloadsStrategy = getMockDownloadsStrategy(0); - List responses = mockDownloadsStrategy.downloads(); + List responses = mockDownloadsStrategy.downloads(); Assert.assertNotNull(responses); Assert.assertEquals(0, responses.size()); } @@ -42,37 +39,37 @@ public void downloads_maxDownloadsToConfiguredToZero_noDownloadsReturned() { @Test public void downloads_noDownloadsFound_infoMessageReturned() { DownloadsStrategy mockDownloadsStrategy = getMockDownloadsStrategy(1); - TestResponse expectedResponse = new TestResponse(); - new Expectations(mockDownloadsStrategy) {{ - chatClientResponseBuilder.createInfoMessage("No movies downloading"); times = 1; result = expectedResponse; - }}; - List responses = mockDownloadsStrategy.downloads(); + List responses = mockDownloadsStrategy.downloads(); Assert.assertNotNull(responses); Assert.assertEquals(1, responses.size()); - Assert.assertEquals(expectedResponse, responses.get(0)); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new InfoResponse("No movies downloading"), + responses.get(0))); } @Test public void parseContent_tooManyDownloads_infoMessageIncluded() { DownloadsStrategy mockDownloadsStrategy = getMockDownloadsStrategy(5); - TestResponse expectedInfoResponse = new TestResponse(); new Expectations(mockDownloadsStrategy) {{ - mockDownloadsStrategy.getResponse((JsonElement)any); times = 6; result = new TestResponse(); - chatClientResponseBuilder.createInfoMessage("Too many downloads, limiting results to 5"); times = 1; result = expectedInfoResponse; + mockDownloadsStrategy.getResponse((JsonElement)any); times = 6; result = new TestCommandResponse(); }}; //6 items is greater than the configured value above (5) - List responses = mockDownloadsStrategy.parseContent("[{}, {}, {}, {}, {}, {}]"); + List responses = mockDownloadsStrategy.parseContent("[{}, {}, {}, {}, {}, {}]"); Assert.assertNotNull(responses); - //even tho the max is 6, the first response is an info message + //even though the max is 6, the first response is an info message Assert.assertEquals(6, responses.size()); - Assert.assertEquals(expectedInfoResponse, responses.get(0)); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new InfoResponse("Too many downloads, limiting results to 5"), + responses.get(0))); } @Test public void getContentDownloads_endpointUnavailable_emptyResponse() { - DownloadsStrategy downloadsStrategy = new DownloadsStrategy(api, "", chatClientResponseBuilder, ContentType.MOVIE) { + DownloadsStrategy downloadsStrategy = new DownloadsStrategy(api, "", ContentType.MOVIE) { @Override - public ChatClientResponse getResponse(JsonElement rawElement) { + public CommandResponse getResponse(JsonElement rawElement) { return null; } }; @@ -88,7 +85,7 @@ public ChatClientResponse getResponse(JsonElement rawElement) { } private DownloadsStrategy getMockDownloadsStrategy(int maxDownloadsToShow) { - DownloadsStrategy mockDownloadsStrategy = new MockDownloadsStrategy(api, "", chatClientResponseBuilder, ContentType.MOVIE); + DownloadsStrategy mockDownloadsStrategy = new MockDownloadsStrategy(api, "", ContentType.MOVIE); Deencapsulation.setField(mockDownloadsStrategy, "MAX_DOWNLOADS_TO_SHOW", maxDownloadsToShow); return mockDownloadsStrategy; } @@ -102,22 +99,19 @@ private DownloadsStrategy getMockDownloadsStrategy(int maxDownloadsToShow) { @Injectable private Api api; - @Injectable - private ChatClientResponseBuilder chatClientResponseBuilder; - private static class MockDownloadsStrategy extends DownloadsStrategy { - public MockDownloadsStrategy(Api api, String url, ChatClientResponseBuilder chatClientResponseBuilder, ContentType contentType) { - super(api, url, chatClientResponseBuilder, contentType); + public MockDownloadsStrategy(Api api, String url, ContentType contentType) { + super(api, url, contentType); } @Override - public ChatClientResponse getResponse(JsonElement rawElement) { + public CommandResponse getResponse(JsonElement rawElement) { return null; } @Override - public List getContentDownloads() { + public List getContentDownloads() { return new ArrayList<>(); } } diff --git a/src/test/java/com/botdarr/api/LookupStrategyTests.java b/src/test/java/com/botdarr/api/LookupStrategyTests.java index f7b33cb..4d0163f 100644 --- a/src/test/java/com/botdarr/api/LookupStrategyTests.java +++ b/src/test/java/com/botdarr/api/LookupStrategyTests.java @@ -1,9 +1,11 @@ package com.botdarr.api; -import com.botdarr.TestResponse; -import com.botdarr.clients.ChatClientResponse; -import com.botdarr.clients.ChatClientResponseBuilder; +import com.botdarr.TestCommandResponse; +import com.botdarr.commands.responses.CommandResponse; +import com.botdarr.commands.responses.ErrorResponse; +import com.botdarr.commands.responses.InfoResponse; import mockit.*; +import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.logging.log4j.Logger; import org.junit.Assert; import org.junit.BeforeClass; @@ -31,9 +33,13 @@ public void lookup_newMovie_noMoviesFound_errorResponseReturned() throws Excepti MockLookupStrategy mockLookupStrategy = getMockLookupStrategy(1); new Expectations(mockLookupStrategy) {{ mockLookupStrategy.lookup(searchText); times = 1; result = Collections.emptyList(); - chatClientResponseBuilder.createErrorMessage("Could not find any new movies for search term=" + searchText); times = 1; result = new TestResponse(); }}; - Assert.assertNotNull(mockLookupStrategy.lookup(searchText, true)); + List responses = mockLookupStrategy.lookup(searchText, true); + Assert.assertNotNull(responses); + Assert.assertEquals(1, responses.size()); + Assert.assertTrue( + EqualsBuilder.reflectionEquals(new ErrorResponse("Could not find any new movies for search term=" + searchText), + responses.get(0))); } @Test @@ -42,11 +48,15 @@ public void lookup_newMovie_noMoviesFound_allExisting_errorResponseReturned() th MockLookupStrategy mockLookupStrategy = getMockLookupStrategy(1); Object expectedObject = new Object(); new Expectations(mockLookupStrategy) {{ - mockLookupStrategy.lookup(searchText); times = 1; result = Arrays.asList(expectedObject); + mockLookupStrategy.lookup(searchText); times = 1; result = Collections.singletonList(expectedObject); mockLookupStrategy.lookupExistingItem(expectedObject); times = 1; result = new Object(); - chatClientResponseBuilder.createErrorMessage("Could not find any new movies for search term=" + searchText); times = 1; result = new TestResponse(); }}; - Assert.assertNotNull(mockLookupStrategy.lookup(searchText, true)); + List responses = mockLookupStrategy.lookup(searchText, true); + Assert.assertNotNull(responses); + Assert.assertEquals(1, responses.size()); + Assert.assertTrue( + EqualsBuilder.reflectionEquals(new ErrorResponse("Could not find any new movies for search term=" + searchText), + responses.get(0))); } @Test @@ -55,28 +65,33 @@ public void lookup_existingMovie_noMoviesFound_noneExist_errorResponseReturned() MockLookupStrategy mockLookupStrategy = getMockLookupStrategy(1); Object expectedObject = new Object(); new Expectations(mockLookupStrategy) {{ - mockLookupStrategy.lookup(searchText); times = 1; result = Arrays.asList(expectedObject); + mockLookupStrategy.lookup(searchText); times = 1; result = Collections.singletonList(expectedObject); mockLookupStrategy.lookupExistingItem(expectedObject); times = 1; result = null; - chatClientResponseBuilder.createErrorMessage("Could not find any existing movies for search term=" + searchText); times = 1; result = new TestResponse(); }}; - Assert.assertNotNull(mockLookupStrategy.lookup(searchText, false)); + List responses = mockLookupStrategy.lookup(searchText, false); + Assert.assertNotNull(responses); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new ErrorResponse("Could not find any existing movies for search term=" + searchText), + responses.get(0))); } @Test public void lookup_newMovie_moviesFound_tooManyResultsLimited_infoResponseIncluded() throws Exception { String searchText = "searchText"; MockLookupStrategy mockLookupStrategy = getMockLookupStrategy(2); - TestResponse expectedInfoResponse = new TestResponse(); new Expectations(mockLookupStrategy) {{ mockLookupStrategy.lookup(searchText); times = 1; result = Arrays.asList(new Object(), new Object(), new Object()); mockLookupStrategy.lookupExistingItem(any); times = 3; result = null; - mockLookupStrategy.getNewOrExistingItem(any, any, true); times = 3; result = new TestResponse(); - chatClientResponseBuilder.createInfoMessage("Too many movies found, limiting results to 2"); times = 1; result = expectedInfoResponse; + mockLookupStrategy.getNewItem(any); times = 3; result = new TestCommandResponse(); }}; - List responses = mockLookupStrategy.lookup(searchText, true); + List responses = mockLookupStrategy.lookup(searchText, true); Assert.assertNotNull(responses); Assert.assertEquals(3, responses.size()); - Assert.assertEquals(expectedInfoResponse, responses.get(0)); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new InfoResponse("Too many movies found, limiting results to 2"), + responses.get(0))); } @Test @@ -84,20 +99,21 @@ public void lookup_exceptionThrown_errorResponse() throws Exception { String searchText = "searchText"; MockLookupStrategy mockLookupStrategy = getMockLookupStrategy(2); Exception expectedException = new Exception("expected error"); - TestResponse expectedErrorResponse = new TestResponse(); new Expectations(mockLookupStrategy) {{ mockLookupStrategy.lookup(searchText); times = 1; result = expectedException; logger.error("Error trying to lookup movie, searchText=searchText", expectedException); times = 1; - chatClientResponseBuilder.createErrorMessage("Error looking up movie, e=expected error"); times = 1; result = expectedErrorResponse; }}; - List responses = mockLookupStrategy.lookup(searchText, true); + List responses = mockLookupStrategy.lookup(searchText, true); Assert.assertNotNull(responses); Assert.assertEquals(1, responses.size()); - Assert.assertEquals(expectedErrorResponse, responses.get(0)); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new ErrorResponse("Error looking up movie, e=expected error"), + responses.get(0))); } private MockLookupStrategy getMockLookupStrategy(int maxResultsToShow) { - MockLookupStrategy mockLookupStrategy = new MockLookupStrategy(chatClientResponseBuilder, ContentType.MOVIE); + MockLookupStrategy mockLookupStrategy = new MockLookupStrategy(ContentType.MOVIE); Deencapsulation.setField(mockLookupStrategy, "MAX_RESULTS_TO_SHOW", maxResultsToShow); Deencapsulation.setField(mockLookupStrategy, "LOGGER", logger); return mockLookupStrategy; @@ -106,13 +122,10 @@ private MockLookupStrategy getMockLookupStrategy(int maxResultsToShow) { @Mocked private Logger logger; - @Injectable - private ChatClientResponseBuilder chatClientResponseBuilder; - private static class MockLookupStrategy extends LookupStrategy { - public MockLookupStrategy(ChatClientResponseBuilder chatClientResponseBuilder, ContentType contentType) { - super(chatClientResponseBuilder, contentType); + public MockLookupStrategy(ContentType contentType) { + super(contentType); } @Override @@ -126,7 +139,12 @@ public List lookup(String searchTerm) throws Exception { } @Override - public ChatClientResponse getNewOrExistingItem(Object lookupItem, Object existingItem, boolean findNew) { + public CommandResponse getExistingItem(Object existingItem) { + return null; + } + + @Override + public CommandResponse getNewItem(Object lookupItem) { return null; } diff --git a/src/test/java/com/botdarr/api/radarr/RadarrApiTests.java b/src/test/java/com/botdarr/api/radarr/RadarrApiTests.java index 2adfb97..83a4a51 100644 --- a/src/test/java/com/botdarr/api/radarr/RadarrApiTests.java +++ b/src/test/java/com/botdarr/api/radarr/RadarrApiTests.java @@ -1,11 +1,11 @@ package com.botdarr.api.radarr; import com.botdarr.Config; -import com.botdarr.TestResponse; -import com.botdarr.TestResponseBuilder; -import com.botdarr.commands.CommandResponse; +import com.botdarr.TestCommandResponse; +import com.botdarr.commands.responses.*; import com.google.gson.Gson; import mockit.Deencapsulation; +import org.apache.commons.lang3.builder.EqualsBuilder; import org.junit.*; import org.junit.rules.TemporaryFolder; import org.mockserver.junit.MockServerRule; @@ -32,8 +32,8 @@ public void afterEachTest() { } @Test - public void discover_existingMoviesNotReturned() { - RadarrApi radarrApi = new RadarrApi(new TestResponseBuilder()); + public void discover_existingMoviesNotReturned() { + RadarrApi radarrApi = new RadarrApi(); HttpRequest request = HttpRequest.request() .withMethod("GET") .withPath("/api/v3/importlist/movie") @@ -51,20 +51,22 @@ public void discover_existingMoviesNotReturned() { .withBody(new Gson().toJson(new RadarrMovie[] {expectedRadarrMovie}), MediaType.APPLICATION_JSON)); //trigger api - CommandResponse commandResponse = new CommandResponse(radarrApi.discover()); + List commandResponse = radarrApi.discover(); //verify request was sent mockServerRule.getClient().verify(request); //verify response data - List testResponses = commandResponse.getMultipleChatClientResponses(); - Assert.assertEquals(testResponses.size(), 1); - Assert.assertEquals(expectedRadarrMovie.getTitle(), testResponses.get(0).getRadarrMovie().getTitle()); + Assert.assertEquals(commandResponse.size(), 1); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new DiscoverMovieResponse(expectedRadarrMovie), + commandResponse.get(0), false, null, true)); } @Test - public void discover_maxResults() { - RadarrApi radarrApi = new RadarrApi(new TestResponseBuilder()); + public void discover_maxResults() { + RadarrApi radarrApi = new RadarrApi(); HttpRequest request = HttpRequest.request() .withMethod("GET") .withPath("/api/v3/importlist/movie") @@ -86,20 +88,19 @@ public void discover_maxResults() { .withBody(new Gson().toJson(radarrMovies), MediaType.APPLICATION_JSON)); //trigger api - CommandResponse commandResponse = new CommandResponse(radarrApi.discover()); + List commandResponse = radarrApi.discover(); //verify request was sent mockServerRule.getClient().verify(request); //verify response data - List testResponses = commandResponse.getMultipleChatClientResponses(); //verify the max (20) even though the mock server returned 40 (see above) - Assert.assertEquals(20, testResponses.size()); + Assert.assertEquals(20, commandResponse.size()); } @Test - public void lookup_maxResults() { - RadarrApi radarrApi = new RadarrApi(new TestResponseBuilder()); + public void lookup_maxResults() { + RadarrApi radarrApi = new RadarrApi(); HttpRequest request = HttpRequest.request() .withMethod("GET") .withPath("/api/v3/movie/lookup") @@ -121,22 +122,24 @@ public void lookup_maxResults() { .withBody(new Gson().toJson(radarrMovies), MediaType.APPLICATION_JSON)); //trigger api - CommandResponse commandResponse = new CommandResponse(radarrApi.lookup("searchTerm", true)); + List commandResponse = radarrApi.lookup("searchTerm", true); //verify request was sent mockServerRule.getClient().verify(request); //verify response data - List testResponses = commandResponse.getMultipleChatClientResponses(); //verify the max (20) even though the mock server returned 40 (see above) - Assert.assertEquals(21, testResponses.size()); + Assert.assertEquals(21, commandResponse.size()); //verify the first message is a message about the fact too many movies were returned by the server - Assert.assertEquals(testResponses.get(0).getResponseMessage(), "Too many movies found, limiting results to 20"); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new InfoResponse("Too many movies found, limiting results to 20"), + commandResponse.get(0), false, null, true)); } @Test - public void lookup_existingMoviesNotReturned() { - RadarrApi radarrApi = new RadarrApi(new TestResponseBuilder()); + public void lookup_existingMoviesNotReturned() { + RadarrApi radarrApi = new RadarrApi(); HttpRequest request = HttpRequest.request() .withMethod("GET") .withPath("/api/v3/movie/lookup") @@ -158,21 +161,23 @@ public void lookup_existingMoviesNotReturned() { .withBody(new Gson().toJson(new RadarrMovie[] {expectedRadarrMovie}), MediaType.APPLICATION_JSON)); //trigger api - CommandResponse commandResponse = new CommandResponse(radarrApi.lookup("searchTerm", true)); + List commandResponse = radarrApi.lookup("searchTerm", true); //verify request was sent mockServerRule.getClient().verify(request); //verify response data - List testResponses = commandResponse.getMultipleChatClientResponses(); //there should only be 1 response stating no new movies could be found - Assert.assertEquals(1, testResponses.size()); - Assert.assertEquals("Could not find any new movies for search term=searchTerm", testResponses.get(0).getResponseMessage()); + Assert.assertEquals(1, commandResponse.size()); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new ErrorResponse("Could not find any new movies for search term=searchTerm"), + commandResponse.get(0), false, null, true)); } @Test - public void lookup_existingMoviesReturned() { - RadarrApi radarrApi = new RadarrApi(new TestResponseBuilder()); + public void lookup_existingMoviesReturned() { + RadarrApi radarrApi = new RadarrApi(); HttpRequest request = HttpRequest.request() .withMethod("GET") .withPath("/api/v3/movie/lookup") @@ -194,22 +199,23 @@ public void lookup_existingMoviesReturned() { .withBody(new Gson().toJson(new RadarrMovie[] {expectedRadarrMovie}), MediaType.APPLICATION_JSON)); //trigger api - CommandResponse commandResponse = new CommandResponse(radarrApi.lookup("searchTerm", false)); + List commandResponse = radarrApi.lookup("searchTerm", false); //verify request was sent mockServerRule.getClient().verify(request); //verify response data - List testResponses = commandResponse.getMultipleChatClientResponses(); //since we looking up not new films, existing movies can be returned, and should be the only result - Assert.assertEquals(1, testResponses.size()); - Assert.assertEquals(expectedRadarrMovie.getTitle(), testResponses.get(0).getRadarrMovie().getTitle()); - Assert.assertEquals(expectedRadarrMovie.getTmdbId(), testResponses.get(0).getRadarrMovie().getTmdbId()); + Assert.assertEquals(1, commandResponse.size()); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new ExistingMovieResponse(expectedRadarrMovie), + commandResponse.get(0), false, null, true)); } @Test - public void downloads_noDownloadsFound() { - RadarrApi radarrApi = new RadarrApi(new TestResponseBuilder()); + public void downloads_noDownloadsFound() { + RadarrApi radarrApi = new RadarrApi(); HttpRequest request = HttpRequest.request() .withMethod("GET") .withPath("/api/v3/queue") @@ -223,29 +229,42 @@ public void downloads_noDownloadsFound() { .withBody(new Gson().toJson(new RadarrQueuePage()), MediaType.APPLICATION_JSON)); //trigger api - CommandResponse commandResponse = new CommandResponse(radarrApi.downloads()); + List commandResponse = radarrApi.downloads(); //verify request was sent mockServerRule.getClient().verify(request); //verify response data - List testResponses = commandResponse.getMultipleChatClientResponses(); //since nothing is downloading we should only get back 1 response with a message about no downloads - Assert.assertEquals(1, testResponses.size()); - Assert.assertEquals("No movies downloading", testResponses.get(0).getResponseMessage()); + Assert.assertEquals(1, commandResponse.size()); + Assert.assertTrue( + EqualsBuilder.reflectionEquals(new InfoResponse("No movies downloading"), + commandResponse.get(0))); } @Test - public void downloads_downloadsFound() { - RadarrApi radarrApi = new RadarrApi(new TestResponseBuilder()); + public void downloads_downloadsFound() { + RadarrApi radarrApi = new RadarrApi(); + RadarrCache radarrCache = new RadarrCache(); + Deencapsulation.setField(radarrApi, "RADARR_CACHE", radarrCache); HttpRequest request = HttpRequest.request() .withMethod("GET") .withPath("/api/v3/queue") .withQueryStringParameter("apiKey", "FSJDkjmf#$Kf3"); + long radarrMovieId = 1; + String radarrMovieTitle = "title1"; + RadarrQueue radarrQueue = new RadarrQueue(); radarrQueue.setTimeleft("05:00"); radarrQueue.setStatus("DOWNLOADING"); + radarrQueue.setMovieId(radarrMovieId); + radarrQueue.setTitle(radarrMovieTitle); + + RadarrMovie existingMovie = new RadarrMovie(); + existingMovie.setId(radarrMovieId); + existingMovie.setTitle(radarrMovieTitle); + radarrCache.add(existingMovie); //setup expected response in mock server RadarrQueuePage radarrQueuePage = new RadarrQueuePage(); @@ -257,22 +276,23 @@ public void downloads_downloadsFound() { .withBody(new Gson().toJson(radarrQueuePage), MediaType.APPLICATION_JSON)); //trigger api - CommandResponse commandResponse = new CommandResponse(radarrApi.downloads()); + List commandResponse = radarrApi.downloads(); //verify request was sent mockServerRule.getClient().verify(request); //verify response data - List testResponses = commandResponse.getMultipleChatClientResponses(); //only movie is downloading, verify all properties - Assert.assertEquals(1, testResponses.size()); - Assert.assertEquals("05:00", testResponses.get(0).getRadarrQueue().getTimeleft()); - Assert.assertEquals("DOWNLOADING", testResponses.get(0).getRadarrQueue().getStatus()); + Assert.assertEquals(1, commandResponse.size()); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new MovieDownloadResponse(radarrQueue), + commandResponse.get(0), false, null, true)); } @Test - public void addWithTitle_noMoviesFound() { - RadarrApi radarrApi = new RadarrApi(new TestResponseBuilder()); + public void addWithTitle_noMoviesFound() { + RadarrApi radarrApi = new RadarrApi(); HttpRequest request = HttpRequest.request() .withMethod("GET") .withPath("/api/v3/movie/lookup") @@ -287,21 +307,23 @@ public void addWithTitle_noMoviesFound() { .withBody(new Gson().toJson(new RadarrMovie[] {}), MediaType.APPLICATION_JSON)); //trigger api - CommandResponse commandResponse = new CommandResponse(radarrApi.addWithTitle("searchTerm")); + List commandResponse = radarrApi.addWithTitle("searchTerm"); //verify request was sent mockServerRule.getClient().verify(request); //verify response data - List testResponses = commandResponse.getMultipleChatClientResponses(); //no movies should be found, the only response should be a message - Assert.assertEquals(1, testResponses.size()); - Assert.assertEquals("No movies found", testResponses.get(0).getResponseMessage()); + Assert.assertEquals(1, commandResponse.size()); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new InfoResponse("No movies found"), + commandResponse.get(0), false, null, true)); } @Test - public void addWithTitle_foundExistingMovieWithSingleResult() { - RadarrApi radarrApi = new RadarrApi(new TestResponseBuilder()); + public void addWithTitle_foundExistingMovieWithSingleResult() { + RadarrApi radarrApi = new RadarrApi(); HttpRequest request = HttpRequest.request() .withMethod("GET") .withPath("/api/v3/movie/lookup") @@ -323,21 +345,23 @@ public void addWithTitle_foundExistingMovieWithSingleRe .withBody(new Gson().toJson(new RadarrMovie[] {expectedRadarrMovie}), MediaType.APPLICATION_JSON)); //trigger api - CommandResponse commandResponse = new CommandResponse(radarrApi.addWithTitle("searchTerm")); + List commandResponse = radarrApi.addWithTitle("searchTerm"); //verify request was sent mockServerRule.getClient().verify(request); //verify response data - List testResponses = commandResponse.getMultipleChatClientResponses(); //no movies should be found, the only response should be a message - Assert.assertEquals(1, testResponses.size()); - Assert.assertEquals("movie already exists", testResponses.get(0).getResponseMessage()); + Assert.assertEquals(1, commandResponse.size()); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new ErrorResponse("movie already exists"), + commandResponse.get(0), false, null, true)); } @Test - public void addWithTitle_foundExistingMovieWithMultipleResults() { - RadarrApi radarrApi = new RadarrApi(new TestResponseBuilder()); + public void addWithTitle_foundExistingMovieWithMultipleResults() { + RadarrApi radarrApi = new RadarrApi(); HttpRequest request = HttpRequest.request() .withMethod("GET") .withPath("/api/v3/movie/lookup") @@ -364,21 +388,23 @@ public void addWithTitle_foundExistingMovieWithMultiple .withBody(new Gson().toJson(new RadarrMovie[] {expectedRadarrMovie, expectedRadarrMovie2}), MediaType.APPLICATION_JSON)); //trigger api - CommandResponse commandResponse = new CommandResponse(radarrApi.addWithTitle("movie1")); + List commandResponse = radarrApi.addWithTitle("movie1"); //verify request was sent mockServerRule.getClient().verify(request); //verify response data - List testResponses = commandResponse.getMultipleChatClientResponses(); //no movies should be found, the only response should be a message - Assert.assertEquals(1, testResponses.size()); - Assert.assertEquals("No new movies found, check existing movies", testResponses.get(0).getResponseMessage()); + Assert.assertEquals(1, commandResponse.size()); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new InfoResponse("No new movies found, check existing movies"), + commandResponse.get(0), false, null, true)); } @Test - public void addWithTitle_foundManyResultsLimitedToMax() { - RadarrApi radarrApi = new RadarrApi(new TestResponseBuilder()); + public void addWithTitle_foundManyResultsLimitedToMax() { + RadarrApi radarrApi = new RadarrApi(); HttpRequest request = HttpRequest.request() .withMethod("GET") .withPath("/api/v3/movie/lookup") @@ -401,42 +427,43 @@ public void addWithTitle_foundManyResultsLimitedToMax() .withBody(new Gson().toJson(radarrMovies.toArray()), MediaType.APPLICATION_JSON)); //trigger api - CommandResponse commandResponse = new CommandResponse(radarrApi.addWithTitle("movie")); + List commandResponse = radarrApi.addWithTitle("movie"); //verify request was sent mockServerRule.getClient().verify(request); //verify response data - List testResponses = commandResponse.getMultipleChatClientResponses(); //even though we sent 30 movies, the default api limit is 20 //with the first message being a message about too many movies found added to the list (making the length 21) - Assert.assertEquals(21, testResponses.size()); - Assert.assertEquals("Too many movies found, please narrow search or increase max results to show", testResponses.get(0).getResponseMessage()); + Assert.assertEquals(21, commandResponse.size()); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new InfoResponse("Too many movies found, please narrow search or increase max results to show"), + commandResponse.get(0), false, null, true)); } @Test - public void downloads_downloadsFoundButConfiguredToShowNone() { + public void downloads_downloadsFoundButConfiguredToShowNone() { Properties properties = getDefaultProperties(); properties.put("max-downloads-to-show", "0"); writeFakePropertiesFile(properties); - RadarrApi radarrApi = new RadarrApi(new TestResponseBuilder()); + RadarrApi radarrApi = new RadarrApi(); //trigger api - CommandResponse commandResponse = new CommandResponse(radarrApi.downloads()); + List commandResponse = radarrApi.downloads(); //verify response data - List testResponses = commandResponse.getMultipleChatClientResponses(); //only movie is downloading, but our config explicitly states no downloads should be shown - Assert.assertEquals(0, testResponses.size()); + Assert.assertEquals(0, commandResponse.size()); } @Test - public void addWithId_movieAlreadyExists() { + public void addWithId_movieAlreadyExists() { RadarrMovie existingMovie = getRadarrMovie(1, 2, "movie1"); List radarrMovies = new ArrayList<>(); radarrMovies.add(existingMovie); - RadarrApi radarrApi = new RadarrApi(new TestResponseBuilder()); + RadarrApi radarrApi = new RadarrApi(); RadarrCache radarrCache = Deencapsulation.getField(radarrApi, "RADARR_CACHE"); radarrCache.add(existingMovie); @@ -455,11 +482,13 @@ public void addWithId_movieAlreadyExists() { .respond(expectedResponse); //trigger api - CommandResponse commandResponse = new CommandResponse(radarrApi.addWithId("movie1", "2")); + CommandResponse commandResponse = radarrApi.addWithId("movie1", "2"); //verify response data - TestResponse testResponses = commandResponse.getSingleChatClientResponse(); - Assert.assertEquals("movie already exists", testResponses.getResponseMessage()); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new ErrorResponse("movie already exists"), + commandResponse, false, null, true)); } private RadarrMovie getRadarrMovie(long id, long tmdbId, String title) { diff --git a/src/test/java/com/botdarr/commands/CommandProcessorTests.java b/src/test/java/com/botdarr/commands/CommandProcessorTests.java index ddb15a1..9aac68e 100644 --- a/src/test/java/com/botdarr/commands/CommandProcessorTests.java +++ b/src/test/java/com/botdarr/commands/CommandProcessorTests.java @@ -1,11 +1,16 @@ package com.botdarr.commands; -import com.botdarr.TestResponse; -import com.botdarr.TestResponseBuilder; +import com.botdarr.TestCommandResponse; import com.botdarr.api.lidarr.LidarrApi; +import com.botdarr.api.lidarr.LidarrCommands; import com.botdarr.api.radarr.RadarrApi; +import com.botdarr.api.radarr.RadarrCommands; import com.botdarr.api.sonarr.SonarrApi; +import com.botdarr.api.sonarr.SonarrCommands; +import com.botdarr.commands.responses.CommandResponse; +import com.botdarr.commands.responses.ErrorResponse; import mockit.*; +import org.apache.commons.lang3.builder.EqualsBuilder; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -93,7 +98,7 @@ public void processMessage_invalidMovieIdForAddCommand() { @Test public void processMessage_validMovieTitleAndIdForAddCommand() { new Expectations() {{ - radarrApi.addWithId("princess5", "46475"); times = 1; result = new TestResponse(); + radarrApi.addWithId("princess5", "46475"); times = 1; result = new TestCommandResponse(); }}; validateValidCommand("!movie id add Princess5 46475"); } @@ -101,7 +106,7 @@ public void processMessage_validMovieTitleAndIdForAddCommand() { @Test public void processMessage_validMovieWithSpacesInTitleForAddCommand() { new Expectations() {{ - radarrApi.addWithId("princess 5", "46475"); times = 1; result = new TestResponse(); + radarrApi.addWithId("princess 5", "46475"); times = 1; result = new TestCommandResponse(); }}; validateValidCommand("!movie id add Princess 5 46475"); } @@ -116,7 +121,7 @@ public void processMessage_invalidMovieTitleForAddCommand() { @Test public void processMessage_validMovieTitleForAddCommand() { new Expectations() {{ - radarrApi.addWithTitle("princess5"); times = 1; result = new TestResponse(); + radarrApi.addWithTitle("princess5"); times = 1; result = new TestCommandResponse(); }}; validateValidCommand("!movie title add Princess5"); } @@ -124,7 +129,7 @@ public void processMessage_validMovieTitleForAddCommand() { @Test public void processMessage_validMovieTitleWithSpacesForAddCommand() { new Expectations() {{ - radarrApi.addWithTitle("princess 5"); times = 1; result = new TestResponse(); + radarrApi.addWithTitle("princess 5"); times = 1; result = new TestCommandResponse(); }}; validateValidCommand("!movie title add Princess 5"); } @@ -139,7 +144,7 @@ public void processMessage_invalidMovieTitleForFindNewMovieCommand() { @Test public void processMessage_validMovieTitleForFindNewMovieCommand() { new Expectations() {{ - radarrApi.lookup("princess5", true); times = 1; result = new TestResponse(); + radarrApi.lookup("princess5", true); times = 1; result = new TestCommandResponse(); }}; validateValidCommand("!movie find new Princess5"); } @@ -147,7 +152,7 @@ public void processMessage_validMovieTitleForFindNewMovieCommand() { @Test public void processMessage_validMovieTitleWithSpacesForFindNewMovieCommand() { new Expectations() {{ - radarrApi.lookup("princess 5", true); times = 1; result = new TestResponse(); + radarrApi.lookup("princess 5", true); times = 1; result = new TestCommandResponse(); }}; validateValidCommand("!movie find new Princess 5"); } @@ -162,7 +167,7 @@ public void processMessage_invalidMovieTitleForFindExistingMovieCommand() { @Test public void processMessage_validMovieTitleForFindExistingMovieCommand() { new Expectations() {{ - radarrApi.lookup("princess5", false); times = 1; result = new TestResponse(); + radarrApi.lookup("princess5", false); times = 1; result = new TestCommandResponse(); }}; validateValidCommand("!movie find existing Princess5"); } @@ -170,7 +175,7 @@ public void processMessage_validMovieTitleForFindExistingMovieCommand() { @Test public void processMessage_validMovieTitleWithSpacesForFindExistingMovieCommand() { new Expectations() {{ - radarrApi.lookup("princess 5", false); times = 1; result = new TestResponse(); + radarrApi.lookup("princess 5", false); times = 1; result = new TestCommandResponse(); }}; validateValidCommand("!movie find existing Princess 5"); } @@ -206,7 +211,7 @@ public void processMessage_invalidShowIdForAddCommand() { @Test public void processMessage_validShowTitleAndIdForAddCommand() { new Expectations() {{ - sonarrApi.addWithId("princess5", "46475"); times = 1; result = new TestResponse(); + sonarrApi.addWithId("princess5", "46475"); times = 1; result = new TestCommandResponse(); }}; validateValidCommand("!show id add Princess5 46475"); } @@ -221,7 +226,7 @@ public void processMessage_invalidShowTitleForAddCommand() { @Test public void processMessage_validShowTitleForAddCommand() { new Expectations() {{ - sonarrApi.addWithTitle("princess5"); times = 1; result = new TestResponse(); + sonarrApi.addWithTitle("princess5"); times = 1; result = new TestCommandResponse(); }}; validateValidCommand("!show title add Princess5"); } @@ -229,7 +234,7 @@ public void processMessage_validShowTitleForAddCommand() { @Test public void processMessage_validShowTitleWithSpacesForAddCommand() { new Expectations() {{ - sonarrApi.addWithTitle("princess 5"); times = 1; result = new TestResponse(); + sonarrApi.addWithTitle("princess 5"); times = 1; result = new TestCommandResponse(); }}; validateValidCommand("!show title add Princess 5"); } @@ -244,7 +249,7 @@ public void processMessage_invalidShowTitleForFindNewShowCommand() { @Test public void processMessage_validShowTitleForFindNewShowCommand() { new Expectations() {{ - sonarrApi.lookup("princess5", true); times = 1; result = new TestResponse(); + sonarrApi.lookup("princess5", true); times = 1; result = new TestCommandResponse(); }}; validateValidCommand("!show find new Princess5"); } @@ -252,7 +257,7 @@ public void processMessage_validShowTitleForFindNewShowCommand() { @Test public void processMessage_validShowTitleWithSpacesForFindNewShowCommand() { new Expectations() {{ - sonarrApi.lookup("princess 5", true); times = 1; result = new TestResponse(); + sonarrApi.lookup("princess 5", true); times = 1; result = new TestCommandResponse(); }}; validateValidCommand("!show find new Princess 5"); } @@ -267,7 +272,7 @@ public void processMessage_invalidShowTitleForFindExistingShowCommand() { @Test public void processMessage_validShowTitleForFindExistingShowCommand() { new Expectations() {{ - sonarrApi.lookup("princess5", false); times = 1; result = new TestResponse(); + sonarrApi.lookup("princess5", false); times = 1; result = new TestCommandResponse(); }}; validateValidCommand("!show find existing Princess5"); } @@ -275,7 +280,7 @@ public void processMessage_validShowTitleForFindExistingShowCommand() { @Test public void processMessage_validShowTitleWithSpacesForFindExistingShowCommand() { new Expectations() {{ - sonarrApi.lookup("princess 5", false); times = 1; result = new TestResponse(); + sonarrApi.lookup("princess 5", false); times = 1; result = new TestCommandResponse(); }}; validateValidCommand("!show find existing Princess 5"); } @@ -297,19 +302,30 @@ private void validateInvalidCommandIdentifier(String invalidCommand) { private void validateValidCommand(String validCommand) { CommandProcessor commandProcessor = new CommandProcessor(); - CommandResponse commandResponse = - commandProcessor.processMessage(getCommandsToTest(), validCommand, "user1", responseBuilder); - //we are just making sure no response is returned as another tests validates that part of the command/api - if (commandResponse.getSingleChatClientResponse() != null && commandResponse.getSingleChatClientResponse() instanceof TestResponse) { - Assert.assertNull(commandResponse.getSingleChatClientResponse().getResponseMessage()); + List commandResponses = + commandProcessor.processRequestMessage(getCommandsToTest(), validCommand, "user1"); + //we are just making sure no error responses are returned since they signify a failure with the command + if (commandResponses != null) { + for (CommandResponse response: commandResponses) { + Assert.assertNotNull(response); + Assert.assertNotEquals(ErrorResponse.class, response.getClass()); + } } } - private void validateInvalidCommand(String invalidCommand, String expectedMessage) { + private void validateInvalidCommand(String invalidCommand, String expectedErrorResponseString) { CommandProcessor commandProcessor = new CommandProcessor(); - CommandResponse commandResponse = - commandProcessor.processMessage(getCommandsToTest(), invalidCommand, "user1", responseBuilder); - Assert.assertEquals(expectedMessage, commandResponse.getSingleChatClientResponse().getResponseMessage()); + List commandResponses = + commandProcessor.processRequestMessage(getCommandsToTest(), invalidCommand, "user1"); + if (commandResponses != null) { + Assert.assertEquals(1, commandResponses.size()); + CommandResponse commandResponse = commandResponses.get(0); + Assert.assertNotNull(commandResponse); + Assert.assertTrue( + EqualsBuilder.reflectionEquals( + new ErrorResponse(expectedErrorResponseString), + commandResponse, false, null, true)); + } } private void mockCommandPrefix(String prefix) { @@ -325,7 +341,7 @@ private List getCommandsToTest() { List radarrCommands = RadarrCommands.getCommands(radarrApi); List sonarrCommands = SonarrCommands.getCommands(sonarrApi); List lidarrCommands = LidarrCommands.getCommands(lidarrApi); - List commands = new ArrayList<>(HelpCommands.getCommands(responseBuilder, radarrCommands, sonarrCommands, lidarrCommands)); + List commands = new ArrayList<>(HelpCommands.getCommands(radarrCommands, sonarrCommands, lidarrCommands)); commands.addAll(radarrCommands); commands.addAll(sonarrCommands); commands.addAll(lidarrCommands); @@ -340,6 +356,4 @@ private List getCommandsToTest() { @Injectable private LidarrApi lidarrApi; - - private TestResponseBuilder responseBuilder = new TestResponseBuilder(); }