Skip to content

Commit 8e0aa41

Browse files
committed
Add /compare command
1 parent b4c971f commit 8e0aa41

File tree

3 files changed

+81
-23
lines changed

3 files changed

+81
-23
lines changed

Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ RUN GRADLE_OPTS="-Xmx256m" gradle shadowJar --build-cache --stacktrace --no-daem
1313

1414
FROM openjdk:11
1515
WORKDIR /app
16-
COPY --from=builder /usr/src/java-code/build/libs/SimilarImagesBot-1.0.1-all.jar .
16+
COPY --from=builder /usr/src/java-code/build/libs/SimilarImagesBot-1.0.2-all.jar .
1717
ENV BOT_TOKEN '' \
1818
ADMIN_ID 0 \
1919
MODE 'once'
20-
ENTRYPOINT ["java", "-jar", "/app/SimilarImagesBot-1.0.1-all.jar"]
20+
ENTRYPOINT ["java", "-jar", "/app/SimilarImagesBot-1.0.2-all.jar"]

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ sourceCompatibility = 11
88
targetCompatibility = 11
99
mainClassName = 'com.annimon.similarimagesbot.Main'
1010
group 'com.annimon'
11-
version '1.0.1'
11+
version '1.0.2'
1212

1313
repositories {
1414
jcenter()

src/main/java/com/annimon/similarimagesbot/BotHandler.java

Lines changed: 78 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
package com.annimon.similarimagesbot;
22

3+
import com.annimon.similarimagesbot.data.ImageResult;
34
import com.annimon.similarimagesbot.data.Post;
45
import com.annimon.similarimagesbot.data.SimilarImagesInfo;
56
import com.pengrad.telegrambot.TelegramBot;
67
import com.pengrad.telegrambot.UpdatesListener;
78
import com.pengrad.telegrambot.model.Message;
89
import com.pengrad.telegrambot.model.PhotoSize;
910
import com.pengrad.telegrambot.model.Update;
11+
import com.pengrad.telegrambot.model.request.InputMediaPhoto;
1012
import com.pengrad.telegrambot.model.request.ParseMode;
1113
import com.pengrad.telegrambot.request.DeleteMessage;
14+
import com.pengrad.telegrambot.request.ForwardMessage;
1215
import com.pengrad.telegrambot.request.GetFile;
1316
import com.pengrad.telegrambot.request.GetUpdates;
17+
import com.pengrad.telegrambot.request.SendMediaGroup;
1418
import com.pengrad.telegrambot.request.SendMessage;
19+
import com.pengrad.telegrambot.response.SendResponse;
1520
import java.awt.image.BufferedImage;
1621
import java.io.IOException;
1722
import java.net.URL;
@@ -21,13 +26,21 @@
2126
import java.util.Comparator;
2227
import java.util.List;
2328
import java.util.Objects;
29+
import java.util.Optional;
2430
import java.util.Set;
31+
import java.util.function.Predicate;
32+
import java.util.regex.Matcher;
2533
import java.util.regex.Pattern;
2634
import java.util.stream.Collectors;
2735
import javax.imageio.ImageIO;
2836

2937
public class BotHandler {
3038

39+
private final Comparator<PhotoSize> photoSizeComparator = Comparator
40+
.comparingInt(ps -> ps.width() * ps.height());
41+
private final Pattern delPattern = Pattern.compile("/del(\\d+)m(\\d+)");
42+
private final Pattern comparePattern = Pattern.compile("/compare(\\d+)m(\\d+)x(\\d+)");
43+
3144
private final TelegramBot bot;
3245
private final ImageIndexer indexer;
3346
private long adminId;
@@ -58,32 +71,64 @@ public void runOnce() {
5871
}
5972

6073
private Set<Post> processAdminCommands(List<Update> updates) {
61-
final var delPattern = Pattern.compile("/del(\\d+)m(\\d+)");
6274
return updates.stream()
6375
.map(Update::message)
6476
.filter(Objects::nonNull)
6577
.filter(msg -> msg.chat().id() == adminId)
6678
.map(Message::text)
6779
.filter(Objects::nonNull)
68-
.map(command -> {
69-
final var m = delPattern.matcher(command);
70-
if (m.find()) {
71-
final var channelId = Long.parseLong("-100" + m.group(1));
72-
final var messageId = Integer.parseInt(m.group(2));
73-
bot.execute(new DeleteMessage(channelId, messageId));
74-
try {
75-
indexer.deleteImage(channelId, messageId);
76-
} catch (SQLException ex) {
77-
System.err.println("Cannot delete image in db");
78-
}
79-
return new Post(channelId, messageId);
80-
}
81-
return null;
82-
})
80+
.map(command -> Optional.<Post>empty()
81+
.or(() -> processDelCommand(delPattern.matcher(command)))
82+
.or(() -> processCompareCommand(comparePattern.matcher(command)))
83+
.orElse(null))
8384
.filter(Objects::nonNull)
8485
.collect(Collectors.toSet());
8586
}
8687

88+
private Optional<Post> processDelCommand(Matcher m) {
89+
if (!m.find()) {
90+
return Optional.empty();
91+
}
92+
final var channelId = Long.parseLong("-100" + m.group(1));
93+
final var messageId = Integer.parseInt(m.group(2));
94+
bot.execute(new DeleteMessage(channelId, messageId));
95+
try {
96+
indexer.deleteImage(channelId, messageId);
97+
} catch (SQLException ex) {
98+
System.err.println("Cannot delete image in db");
99+
}
100+
return Optional.of(new Post(channelId, messageId));
101+
}
102+
103+
private Optional<Post> processCompareCommand(Matcher m) {
104+
if (!m.find()) {
105+
return Optional.empty();
106+
}
107+
final var channelId = Long.parseLong("-100" + m.group(1));
108+
final var messageA = Integer.parseInt(m.group(2));
109+
final var messageB = Integer.parseInt(m.group(3));
110+
111+
// Forward and get photo to compare
112+
var sentA = bot.execute(new ForwardMessage(adminId, channelId, messageA));
113+
var sentB = bot.execute(new ForwardMessage(adminId, channelId, messageB));
114+
final Predicate<SendResponse> hasPhoto = (r) -> r.isOk() && r.message().photo() != null;
115+
if (hasPhoto.test(sentA) && hasPhoto.test(sentB)) {
116+
final var photoA = getBiggestPhoto(sentA.message().photo());
117+
final var photoB = getBiggestPhoto(sentB.message().photo());
118+
bot.execute(new SendMediaGroup(adminId,
119+
new InputMediaPhoto(photoA.fileId()).caption("Post " + messageA),
120+
new InputMediaPhoto(photoB.fileId()).caption("Post " + messageB) ));
121+
}
122+
// Clean up if one of the images already deleted
123+
if (sentA.message() != null) {
124+
bot.execute(new DeleteMessage(adminId, sentA.message().messageId()));
125+
}
126+
if (sentB.message() != null) {
127+
bot.execute(new DeleteMessage(adminId, sentB.message().messageId()));
128+
}
129+
return Optional.empty();
130+
}
131+
87132
private void processUpdates(List<Update> updates, Set<Post> ignoredPosts) {
88133
final List<Message> channelPosts = getChannelPostsWithPhotos(updates);
89134
final var similarImagesInfos = new ArrayList<SimilarImagesInfo>();
@@ -120,13 +165,20 @@ private List<Message> getChannelPostsWithPhotos(List<Update> updates) {
120165
private void sendReport(List<SimilarImagesInfo> infos) {
121166
String report = infos.stream().map(info -> {
122167
final var post = info.getOriginalPost();
168+
final var channelId = post.getChannelId().toString().replace("-100", "");
123169
String text = "For post " + formatPostLink(post) + " found:\n";
170+
// Matching results
124171
text += info.getResults().stream()
125172
.map(r -> String.format(" %s, dst: %.2f", formatPostLink(r.getPost()), r.getDistance()))
126173
.collect(Collectors.joining("\n"));
127-
text += String.format("%n/del%sm%d",
128-
post.getChannelId().toString().replace("-100", ""),
129-
post.getMessageId());
174+
// /compare command
175+
text += info.getResults().stream()
176+
.map(ImageResult::getPost)
177+
.map(p -> String.format("/compare%sm%dx%d",
178+
channelId, post.getMessageId(), p.getMessageId()))
179+
.collect(Collectors.joining("\n"));
180+
// /del command
181+
text += String.format("%n/del%sm%d", channelId, post.getMessageId());
130182
return text;
131183
}).collect(Collectors.joining("\n\n"));
132184

@@ -152,7 +204,13 @@ private String linkToMessage(Long chatId, Integer messageId) {
152204

153205
private PhotoSize getSmallestPhoto(PhotoSize[] photoSizes) {
154206
return Arrays.stream(photoSizes)
155-
.min(Comparator.comparingInt(ps -> ps.width() * ps.height()))
207+
.min(photoSizeComparator)
208+
.orElse(photoSizes[0]);
209+
}
210+
211+
private PhotoSize getBiggestPhoto(PhotoSize[] photoSizes) {
212+
return Arrays.stream(photoSizes)
213+
.max(photoSizeComparator)
156214
.orElse(photoSizes[0]);
157215
}
158216
}

0 commit comments

Comments
 (0)