Skip to content

Commit

Permalink
Fixing bug <- Sending Image to all participants
Browse files Browse the repository at this point in the history
  • Loading branch information
patbaumgartner committed Apr 30, 2022
1 parent b2d7461 commit 4f0dbed
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 35 deletions.
11 changes: 5 additions & 6 deletions .mvn/wrapper/MavenWrapperDownloader.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,19 @@ public class MavenWrapperDownloader {
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";

/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
".mvn/wrapper/maven-wrapper.properties";

/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
".mvn/wrapper/maven-wrapper.jar";

/**
* Name of the property which should be used to override the default download url for the wrapper.
Expand Down Expand Up @@ -80,7 +79,7 @@ public static void main(String args[]) {
if (!outputFile.getParentFile().exists()) {
if (!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
Expand Down
42 changes: 28 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@

# Lovebox Telegram Sender

The app allows to send messages via Telegram Bot to a single Lovebox instance. Text messages and photos with captions
The app allows to send messages via Telegram Bot to a single Lovebox instance. Text messages and
photos with captions
are supported. Other message types (e.g. Stickers, Audio, etc.) will lead to a default message.

## Application Setup

To set up the app a few ids and values need to be retrieved on the Lovebox API. The following curl commands help to find
the needed data on an existing account. Make sure you have set up your account via the Android or iOS app already.
To set up the app a few ids and values need to be retrieved on the Lovebox API. The following curl
commands help to find
the needed data on an existing account. Make sure you have set up your account via the Android or
iOS app already.

### Login with Password

Expand Down Expand Up @@ -129,15 +132,18 @@ curl --location --request POST 'https://app-api.loveboxlove.com/v1/graphql' \

### Setting up a Telegram Bot

To create a chatbot on Telegram, you need to contact the [@BotFather](https://telegram.me/BotFather), which is a bot
To create a chatbot on Telegram, you need to contact the [@BotFather](https://telegram.me/BotFather)
, which is a bot
used to create other bots.

The command you need is `/newbot` which leads to the next steps to create your bot. Follow the instructions and get the
The command you need is `/newbot` which leads to the next steps to create your bot. Follow the
instructions and get the
bot `username`, and `token`.

### Adjusting SpringBoot's application.properties

Running the app from the source needs adjustments according to your settings. Adjusting the `application.properties`
Running the app from the source needs adjustments according to your settings. Adjusting
the `application.properties`
in the sources or passing them as Java options or CLI arguments to the app.

```properties
Expand All @@ -157,7 +163,8 @@ bot.token=4072971853:ABEojZ42uNA6YYn_c7DF8RH0UOorqXuveSQ

### Setting Environment Variables e.g. for Docker

The folling snippet can be passed as `.env` and read by the `docker-compose.yml` or used to be passed directly to the
The folling snippet can be passed as `.env` and read by the `docker-compose.yml` or used to be
passed directly to the
`docker run` command.

```bash
Expand Down Expand Up @@ -201,16 +208,19 @@ mvn spring-boot:build-image \

### Fixing Known Issues with Missing Fonts

Since the app uses fonts, we need to make sure that fonts are part of the docker container. The containers produced
Since the app uses fonts, we need to make sure that fonts are part of the docker container. The
containers produced
above throw and exception when using them
`java.lang.NullPointerException: Cannot load from short array because "sun.awt.FontConfiguration.head" is null`

[Andreas Ahlensdorf](https://github.com/aahlenst) describes nicely the font problem in his blog
post [Prerequisites for Font Support in AdoptOpenJDK
](https://blog.adoptopenjdk.net/2021/01/prerequisites-for-font-support-in-adoptopenjdk/).

After more research, it seems that the only solution to add fonts to the buildpack base image is to create a OCI run
image by extending the base one. See the `Dockerfile.base-cnb` file how a patch with the additional font packages might
After more research, it seems that the only solution to add fonts to the buildpack base image is to
create a OCI run
image by extending the base one. See the `Dockerfile.base-cnb` file how a patch with the additional
font packages might
look like.

Build the `runImage` locally with the following command.
Expand All @@ -219,14 +229,16 @@ Build the `runImage` locally with the following command.
docker build --no-cache -f Dockerfile.base-cnb -t patbaumgartner/run:base-cnb .
```

Since we run the pull policy in the `mvn spring-boot:build-image` command with IF_NOT_PRESENT, we need to make sure that
Since we run the pull policy in the `mvn spring-boot:build-image` command with IF_NOT_PRESENT, we
need to make sure that
the newest version of the builder is locally available.

``` bash
docker pull paketobuildpacks/builder:base
```

Finally, passing to the `spring-boot-maven-plugin` the `runImage` to build the docker container containing the fonts.
Finally, passing to the `spring-boot-maven-plugin` the `runImage` to build the docker container
containing the fonts.

```bash
mvn spring-boot:build-image \
Expand All @@ -239,8 +251,10 @@ mvn spring-boot:build-image \

## Credits

Reverse engineering (unpinning certificates) was done with [APKLab](https://github.com/APKLab/APKLab) and
the [Lovebox APK](https://www.apkmonk.com/app/love.lovebox.loveboxapp/) provided by [apkmonk](https://www.apkmonk.com).
Reverse engineering (unpinning certificates) was done
with [APKLab](https://github.com/APKLab/APKLab) and
the [Lovebox APK](https://www.apkmonk.com/app/love.lovebox.loveboxapp/) provided
by [apkmonk](https://www.apkmonk.com).
Postman was used to capture the REST calls from the mobile app. The
article [Capturing Http Requests](https://learning.postman.com/docs/sending-requests/capturing-request-data/capturing-http-requests/)
covers everything needed. After a Postman
Expand Down
5 changes: 3 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,9 @@
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Base64;
import java.util.NoSuchElementException;
Expand All @@ -37,7 +35,7 @@ public record ImageService(ResourceLoader resourceLoader) {
public static final String FONT_NAME = "Sans";

@SneakyThrows
public Pair<String, InputStream> resizeImageToPair(File file, String text) {
public Pair<String, byte[]> resizeImageToPair(File file, String text) {
BufferedImage originalImage = ImageIO.read(file);
BufferedImage resizedImage =
Scalr.resize(
Expand Down Expand Up @@ -68,7 +66,7 @@ public Pair<String, InputStream> resizeImageToPair(File file, String text) {
}

@SneakyThrows
public Pair<String, InputStream> createTextImageToPair(String message) {
public Pair<String, byte[]> createTextImageToPair(String message) {
BufferedImage image = new BufferedImage(DISPLAY_WIDTH, DISPLAY_HEIGHT, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = image.createGraphics();

Expand All @@ -91,7 +89,7 @@ public Pair<String, InputStream> createTextImageToPair(String message) {
}

@SneakyThrows
public Pair<String, InputStream> createFixedImageToPair() {
public Pair<String, byte[]> createFixedImageToPair() {
Resource resource = resourceLoader.getResource("lovebox.jpeg");
Image image = ImageIO.read(resource.getInputStream());
image = image.getScaledInstance(DISPLAY_WIDTH, DISPLAY_HEIGHT, Image.SCALE_SMOOTH);
Expand Down Expand Up @@ -147,11 +145,11 @@ protected void drawCenteredMessage(Graphics2D graphics, String text) {
}
}

protected Pair constructImagePair(BufferedImage image) throws IOException {
protected Pair<String, byte[]> constructImagePair(BufferedImage image) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
ImageIO.write(image, "png", output);
String base64Image = Base64.getEncoder().encodeToString(output.toByteArray());

return new Pair("data:image/png;base64," + base64Image, new ByteArrayInputStream(output.toByteArray()));
return new Pair("data:image/png;base64," + base64Image, output.toByteArray());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import com.patbaumgartner.lovebox.telegram.sender.services.LoveboxService;
import com.patbaumgartner.lovebox.telegram.sender.utils.Pair;
import com.patbaumgartner.lovebox.telegram.sender.utils.Tripple;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
Expand Down Expand Up @@ -45,7 +45,7 @@ public class LoveboxBot extends TelegramLongPollingBot {
@Scheduled(fixedRate = 10_000)
public void readMessageBox() {
List<Pair<String, String>> messages = loveboxService.getMessagesByBox();
messages.stream().forEach(p -> {
messages.forEach(p -> {
loveboxMessageStore.computeIfPresent(p.left(), (key, value) -> {
if (!value.equals(p.right())) {
Message message = telegramMessageStore.get(p.left());
Expand Down Expand Up @@ -80,7 +80,7 @@ public void onUpdateReceived(Update update) {
return;
}

Pair<String, InputStream> imagePair = null;
Pair<String, byte[]> imagePair = null;

// Create Lovebox Image
try {
Expand Down Expand Up @@ -109,7 +109,7 @@ public void onUpdateReceived(Update update) {
// Send/respond Message
for (long chatId : chatIds) {
Message sentMessage = sendPhotoMessage(chatId, text, imagePair, statusTripple);
telegramMessageStore.put(statusTripple.left(), sentMessage);
telegramMessageStore.putIfAbsent(statusTripple.left(), sentMessage);
}
}
}
Expand Down Expand Up @@ -143,10 +143,10 @@ protected void sendTextMessage(long chatId, String text) {
}
}

protected Message sendPhotoMessage(long chatId, String text, Pair<String, InputStream> imagePair, Tripple<String, LocalDateTime, String> statusTripple) {
protected Message sendPhotoMessage(long chatId, String text, Pair<String, byte[]> imagePair, Tripple<String, LocalDateTime, String> statusTripple) {
SendPhoto message = new SendPhoto();
message.setChatId(String.valueOf(chatId));
message.setPhoto(new InputFile(imagePair.right(), "image.png"));
message.setPhoto(new InputFile(new ByteArrayInputStream(imagePair.right()), "image.png"));

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
String formattedDateTime = ZonedDateTime.of(statusTripple.middle(), ZoneId.of("Europe/London"))
Expand Down

0 comments on commit 4f0dbed

Please sign in to comment.