diff --git a/docker-compose.yml b/docker-compose.yml
index 062c7e3..7a3ed20 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -20,6 +20,7 @@ services:
- DB_USER=recording
- DB_PASSWORD=recording
- APPENDER_TYPE=json-console
+ - KIBANA=true
depends_on:
- db
- elasticsearch
diff --git a/pom.xml b/pom.xml
index 83a95c8..a751e9a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
recording-bot
com.wire.bots
- 0.3.2
+ 0.3.3
Recording Bot
Recording Bot Service For Wire
@@ -103,6 +103,21 @@
zip4j
${zip4j.version}
+
+ io.prometheus
+ simpleclient
+ ${prometheus.version}
+
+
+ io.prometheus
+ simpleclient_dropwizard
+ ${prometheus.version}
+
+
+ io.prometheus
+ simpleclient_servlet
+ ${prometheus.version}
+
diff --git a/recording.yaml b/recording.yaml
index 0f5a92b..e43963e 100644
--- a/recording.yaml
+++ b/recording.yaml
@@ -20,6 +20,9 @@ token: ${SERVICE_TOKEN:-}
apiHost: ${WIRE_API_HOST:-https://prod-nginz-https.wire.com}
url: ${PUBLIC_URL:-https://recording.services.wire.com}
salt: ${SALT:-abc}
+kibana: ${KIBANA:-}
+delete: ${DELETE:-}
+edit: ${EDIT:-}
database:
driverClass: org.postgresql.Driver
diff --git a/src/main/java/com/wire/bots/recording/DAO/EventsDAO.java b/src/main/java/com/wire/bots/recording/DAO/EventsDAO.java
index 71d35f5..5b05d32 100644
--- a/src/main/java/com/wire/bots/recording/DAO/EventsDAO.java
+++ b/src/main/java/com/wire/bots/recording/DAO/EventsDAO.java
@@ -35,4 +35,7 @@ int insert(@Bind("messageId") UUID messageId,
@SqlUpdate("DELETE FROM Events WHERE messageId = :messageId")
int delete(@Bind("messageId") UUID messageId);
+
+ @SqlUpdate("DELETE FROM Events WHERE conversationId = :conversationId")
+ int clear(@Bind("conversationId") UUID conversationId);
}
diff --git a/src/main/java/com/wire/bots/recording/MessageHandler.java b/src/main/java/com/wire/bots/recording/MessageHandler.java
index b1f34f6..2ed5ee3 100644
--- a/src/main/java/com/wire/bots/recording/MessageHandler.java
+++ b/src/main/java/com/wire/bots/recording/MessageHandler.java
@@ -13,9 +13,7 @@
import com.wire.lithium.ClientRepo;
import com.wire.xenon.MessageHandlerBase;
import com.wire.xenon.WireClient;
-import com.wire.xenon.assets.FileAsset;
-import com.wire.xenon.assets.FileAssetPreview;
-import com.wire.xenon.assets.MessageText;
+import com.wire.xenon.assets.*;
import com.wire.xenon.backend.models.Conversation;
import com.wire.xenon.backend.models.Member;
import com.wire.xenon.backend.models.NewBot;
@@ -45,7 +43,8 @@ public class MessageHandler extends MessageHandlerBase {
private static final String HELP = "Available commands:\n" +
"`/pdf` - receive previous messages in PDF format\n" +
"`/public` - publish this conversation\n" +
- "`/private` - stop publishing this conversation";
+ "`/private` - stop publishing this conversation\n" +
+ "`/clear` - clear the history";
private final ChannelsDAO channelsDAO;
private final StorageFactory storageFactory;
@@ -183,7 +182,9 @@ public void onText(WireClient client, TextMessage msg) {
persist(convId, userId, botId, messageId, type, msg);
- kibana(type, msg, client);
+ if (config.kibana) {
+ kibana(type, msg, client);
+ }
} catch (Exception e) {
Logger.exception(e, "OnText: %s", client.getId());
}
@@ -204,10 +205,15 @@ public void onEditText(WireClient client, EditedTextMessage msg) {
try {
persist(convId, userId, botId, messageId, type, msg);
- /* UUID replacingMessageId = msg.getReplacingMessageId();
- int update = eventsDAO.update(replacingMessageId, type, payload);
- */
- kibana(type, msg, client);
+
+ if (config.edit) {
+ UUID replacingMessageId = msg.getReplacingMessageId();
+ eventsDAO.update(replacingMessageId, type, msg.getText());
+ }
+
+ if (config.kibana) {
+ kibana(type, msg, client);
+ }
} catch (Exception e) {
Logger.exception(e, "onEditText: %s", client.getId());
}
@@ -222,7 +228,10 @@ public void onDelete(WireClient client, DeletedTextMessage msg) {
String type = "conversation.otr-message-add.delete-text";
persist(convId, userId, botId, messageId, type, msg);
- //eventsDAO.delete(msg.getDeletedMessageId());
+
+ if (config.delete) {
+ eventsDAO.delete(msg.getDeletedMessageId());
+ }
}
@Override
@@ -344,13 +353,18 @@ public void onUserUpdate(UUID id, UUID userId) {
}
@Override
- public void onEvent(WireClient client, UUID userId, Messages.GenericMessage genericMessage) {
+ public void onEvent(WireClient client, UUID userId, Messages.GenericMessage event) {
UUID botId = client.getId();
UUID convId = client.getConversationId();
Logger.info("onEvent: bot: %s, conv: %s, from: %s", botId, convId, userId);
generateHtml(client, botId, convId);
+
+ // User clicked on a Poll Button
+ if (event.hasButtonAction()) {
+ handlePollAction(client, userId, event);
+ }
}
private void generateHtml(WireClient client, UUID botId, UUID convId) {
@@ -367,6 +381,31 @@ private void generateHtml(WireClient client, UUID botId, UUID convId) {
}
}
+ private void handlePollAction(WireClient client, UUID userId, Messages.GenericMessage event) {
+ try {
+ final UUID conversationId = client.getConversationId();
+ final Messages.ButtonAction action = event.getButtonAction();
+ final UUID pollId = UUID.fromString(action.getReferenceMessageId());
+ final String answer = action.getButtonId();
+
+ ButtonActionConfirmation confirmation = new ButtonActionConfirmation(
+ pollId,
+ answer);
+
+ client.send(confirmation, userId);
+
+ if (Objects.equals(answer, "yes")) {
+ int records = eventsDAO.clear(conversationId);
+ client.send(new MessageText(String.format("Deleted %d messages", records)), userId);
+ }
+
+ // Delete the Poll message
+ client.send(new MessageDelete(pollId));
+ } catch (Exception e) {
+ Logger.exception(e, "handlePollAction: %s", client.getId());
+ }
+ }
+
private boolean command(WireClient client, UUID userId, UUID botId, UUID convId, String cmd) throws Exception {
// Only owner of the bot can run commands
NewBot state = storageFactory.create(botId).getState();
@@ -417,6 +456,14 @@ private boolean command(WireClient client, UUID userId, UUID botId, UUID convId,
client.send(fileAsset, userId);
return true;
}
+ case "/clear": {
+ Poll poll = new Poll();
+ poll.addText("Are you sure you want to delete the whole history for this group?\nThis cannot be undone!");
+ poll.addButton("yes", "Yes");
+ poll.addButton("no", "No");
+ client.send(poll, userId);
+ return true;
+ }
case "/public": {
channelsDAO.insert(convId, botId);
String key = Helper.key(convId.toString(), config.salt);
diff --git a/src/main/java/com/wire/bots/recording/Service.java b/src/main/java/com/wire/bots/recording/Service.java
index f1b56ff..bb69cee 100644
--- a/src/main/java/com/wire/bots/recording/Service.java
+++ b/src/main/java/com/wire/bots/recording/Service.java
@@ -30,11 +30,12 @@
import io.dropwizard.configuration.SubstitutingSourceProvider;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
-import io.federecio.dropwizard.swagger.SwaggerBundle;
-import io.federecio.dropwizard.swagger.SwaggerBundleConfiguration;
-
import java.util.concurrent.ExecutorService;
+import io.prometheus.client.CollectorRegistry;
+import io.prometheus.client.dropwizard.DropwizardExports;
+import io.prometheus.client.exporter.MetricsServlet;
+
public class Service extends Server {
public static Service instance;
@@ -71,6 +72,9 @@ protected MessageHandlerBase createHandler(Config config, Environment env) {
}
protected void onRun(Config config, Environment env) {
+ CollectorRegistry.defaultRegistry.register(new DropwizardExports(env.metrics()));
+ env.getApplicationContext().addServlet(MetricsServlet.class, "/metrics");
+
ExecutorService warmup = env.lifecycle().executorService("warmup").build();
warmup.submit(() -> messageHandler.warmup(getRepo()));
}
diff --git a/src/main/java/com/wire/bots/recording/model/Config.java b/src/main/java/com/wire/bots/recording/model/Config.java
index 3b5840c..b49a042 100644
--- a/src/main/java/com/wire/bots/recording/model/Config.java
+++ b/src/main/java/com/wire/bots/recording/model/Config.java
@@ -29,4 +29,8 @@ public class Config extends Configuration {
public String url;
@NotNull
public String salt;
+ public boolean kibana;
+
+ public boolean delete = true;
+ public boolean edit = true;
}