");
matrixResponse.addRawContent("");
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 |