mirror of
https://github.com/annimon-tutorials/Similar-Images-Bot.git
synced 2024-09-20 03:34:19 +03:00
Add /compare command
This commit is contained in:
parent
b4c971fbee
commit
8e0aa41cc0
@ -13,8 +13,8 @@ RUN GRADLE_OPTS="-Xmx256m" gradle shadowJar --build-cache --stacktrace --no-daem
|
|||||||
|
|
||||||
FROM openjdk:11
|
FROM openjdk:11
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=builder /usr/src/java-code/build/libs/SimilarImagesBot-1.0.1-all.jar .
|
COPY --from=builder /usr/src/java-code/build/libs/SimilarImagesBot-1.0.2-all.jar .
|
||||||
ENV BOT_TOKEN '' \
|
ENV BOT_TOKEN '' \
|
||||||
ADMIN_ID 0 \
|
ADMIN_ID 0 \
|
||||||
MODE 'once'
|
MODE 'once'
|
||||||
ENTRYPOINT ["java", "-jar", "/app/SimilarImagesBot-1.0.1-all.jar"]
|
ENTRYPOINT ["java", "-jar", "/app/SimilarImagesBot-1.0.2-all.jar"]
|
||||||
|
@ -8,7 +8,7 @@ sourceCompatibility = 11
|
|||||||
targetCompatibility = 11
|
targetCompatibility = 11
|
||||||
mainClassName = 'com.annimon.similarimagesbot.Main'
|
mainClassName = 'com.annimon.similarimagesbot.Main'
|
||||||
group 'com.annimon'
|
group 'com.annimon'
|
||||||
version '1.0.1'
|
version '1.0.2'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
jcenter()
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.annimon.similarimagesbot;
|
package com.annimon.similarimagesbot;
|
||||||
|
|
||||||
|
import com.annimon.similarimagesbot.data.ImageResult;
|
||||||
import com.annimon.similarimagesbot.data.Post;
|
import com.annimon.similarimagesbot.data.Post;
|
||||||
import com.annimon.similarimagesbot.data.SimilarImagesInfo;
|
import com.annimon.similarimagesbot.data.SimilarImagesInfo;
|
||||||
import com.pengrad.telegrambot.TelegramBot;
|
import com.pengrad.telegrambot.TelegramBot;
|
||||||
@ -7,11 +8,15 @@ import com.pengrad.telegrambot.UpdatesListener;
|
|||||||
import com.pengrad.telegrambot.model.Message;
|
import com.pengrad.telegrambot.model.Message;
|
||||||
import com.pengrad.telegrambot.model.PhotoSize;
|
import com.pengrad.telegrambot.model.PhotoSize;
|
||||||
import com.pengrad.telegrambot.model.Update;
|
import com.pengrad.telegrambot.model.Update;
|
||||||
|
import com.pengrad.telegrambot.model.request.InputMediaPhoto;
|
||||||
import com.pengrad.telegrambot.model.request.ParseMode;
|
import com.pengrad.telegrambot.model.request.ParseMode;
|
||||||
import com.pengrad.telegrambot.request.DeleteMessage;
|
import com.pengrad.telegrambot.request.DeleteMessage;
|
||||||
|
import com.pengrad.telegrambot.request.ForwardMessage;
|
||||||
import com.pengrad.telegrambot.request.GetFile;
|
import com.pengrad.telegrambot.request.GetFile;
|
||||||
import com.pengrad.telegrambot.request.GetUpdates;
|
import com.pengrad.telegrambot.request.GetUpdates;
|
||||||
|
import com.pengrad.telegrambot.request.SendMediaGroup;
|
||||||
import com.pengrad.telegrambot.request.SendMessage;
|
import com.pengrad.telegrambot.request.SendMessage;
|
||||||
|
import com.pengrad.telegrambot.response.SendResponse;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@ -21,13 +26,21 @@ import java.util.Arrays;
|
|||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
public class BotHandler {
|
public class BotHandler {
|
||||||
|
|
||||||
|
private final Comparator<PhotoSize> photoSizeComparator = Comparator
|
||||||
|
.comparingInt(ps -> ps.width() * ps.height());
|
||||||
|
private final Pattern delPattern = Pattern.compile("/del(\\d+)m(\\d+)");
|
||||||
|
private final Pattern comparePattern = Pattern.compile("/compare(\\d+)m(\\d+)x(\\d+)");
|
||||||
|
|
||||||
private final TelegramBot bot;
|
private final TelegramBot bot;
|
||||||
private final ImageIndexer indexer;
|
private final ImageIndexer indexer;
|
||||||
private long adminId;
|
private long adminId;
|
||||||
@ -58,16 +71,24 @@ public class BotHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Set<Post> processAdminCommands(List<Update> updates) {
|
private Set<Post> processAdminCommands(List<Update> updates) {
|
||||||
final var delPattern = Pattern.compile("/del(\\d+)m(\\d+)");
|
|
||||||
return updates.stream()
|
return updates.stream()
|
||||||
.map(Update::message)
|
.map(Update::message)
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.filter(msg -> msg.chat().id() == adminId)
|
.filter(msg -> msg.chat().id() == adminId)
|
||||||
.map(Message::text)
|
.map(Message::text)
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.map(command -> {
|
.map(command -> Optional.<Post>empty()
|
||||||
final var m = delPattern.matcher(command);
|
.or(() -> processDelCommand(delPattern.matcher(command)))
|
||||||
if (m.find()) {
|
.or(() -> processCompareCommand(comparePattern.matcher(command)))
|
||||||
|
.orElse(null))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<Post> processDelCommand(Matcher m) {
|
||||||
|
if (!m.find()) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
final var channelId = Long.parseLong("-100" + m.group(1));
|
final var channelId = Long.parseLong("-100" + m.group(1));
|
||||||
final var messageId = Integer.parseInt(m.group(2));
|
final var messageId = Integer.parseInt(m.group(2));
|
||||||
bot.execute(new DeleteMessage(channelId, messageId));
|
bot.execute(new DeleteMessage(channelId, messageId));
|
||||||
@ -76,12 +97,36 @@ public class BotHandler {
|
|||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
System.err.println("Cannot delete image in db");
|
System.err.println("Cannot delete image in db");
|
||||||
}
|
}
|
||||||
return new Post(channelId, messageId);
|
return Optional.of(new Post(channelId, messageId));
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
})
|
private Optional<Post> processCompareCommand(Matcher m) {
|
||||||
.filter(Objects::nonNull)
|
if (!m.find()) {
|
||||||
.collect(Collectors.toSet());
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
final var channelId = Long.parseLong("-100" + m.group(1));
|
||||||
|
final var messageA = Integer.parseInt(m.group(2));
|
||||||
|
final var messageB = Integer.parseInt(m.group(3));
|
||||||
|
|
||||||
|
// Forward and get photo to compare
|
||||||
|
var sentA = bot.execute(new ForwardMessage(adminId, channelId, messageA));
|
||||||
|
var sentB = bot.execute(new ForwardMessage(adminId, channelId, messageB));
|
||||||
|
final Predicate<SendResponse> hasPhoto = (r) -> r.isOk() && r.message().photo() != null;
|
||||||
|
if (hasPhoto.test(sentA) && hasPhoto.test(sentB)) {
|
||||||
|
final var photoA = getBiggestPhoto(sentA.message().photo());
|
||||||
|
final var photoB = getBiggestPhoto(sentB.message().photo());
|
||||||
|
bot.execute(new SendMediaGroup(adminId,
|
||||||
|
new InputMediaPhoto(photoA.fileId()).caption("Post " + messageA),
|
||||||
|
new InputMediaPhoto(photoB.fileId()).caption("Post " + messageB) ));
|
||||||
|
}
|
||||||
|
// Clean up if one of the images already deleted
|
||||||
|
if (sentA.message() != null) {
|
||||||
|
bot.execute(new DeleteMessage(adminId, sentA.message().messageId()));
|
||||||
|
}
|
||||||
|
if (sentB.message() != null) {
|
||||||
|
bot.execute(new DeleteMessage(adminId, sentB.message().messageId()));
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processUpdates(List<Update> updates, Set<Post> ignoredPosts) {
|
private void processUpdates(List<Update> updates, Set<Post> ignoredPosts) {
|
||||||
@ -120,13 +165,20 @@ public class BotHandler {
|
|||||||
private void sendReport(List<SimilarImagesInfo> infos) {
|
private void sendReport(List<SimilarImagesInfo> infos) {
|
||||||
String report = infos.stream().map(info -> {
|
String report = infos.stream().map(info -> {
|
||||||
final var post = info.getOriginalPost();
|
final var post = info.getOriginalPost();
|
||||||
|
final var channelId = post.getChannelId().toString().replace("-100", "");
|
||||||
String text = "For post " + formatPostLink(post) + " found:\n";
|
String text = "For post " + formatPostLink(post) + " found:\n";
|
||||||
|
// Matching results
|
||||||
text += info.getResults().stream()
|
text += info.getResults().stream()
|
||||||
.map(r -> String.format(" %s, dst: %.2f", formatPostLink(r.getPost()), r.getDistance()))
|
.map(r -> String.format(" %s, dst: %.2f", formatPostLink(r.getPost()), r.getDistance()))
|
||||||
.collect(Collectors.joining("\n"));
|
.collect(Collectors.joining("\n"));
|
||||||
text += String.format("%n/del%sm%d",
|
// /compare command
|
||||||
post.getChannelId().toString().replace("-100", ""),
|
text += info.getResults().stream()
|
||||||
post.getMessageId());
|
.map(ImageResult::getPost)
|
||||||
|
.map(p -> String.format("/compare%sm%dx%d",
|
||||||
|
channelId, post.getMessageId(), p.getMessageId()))
|
||||||
|
.collect(Collectors.joining("\n"));
|
||||||
|
// /del command
|
||||||
|
text += String.format("%n/del%sm%d", channelId, post.getMessageId());
|
||||||
return text;
|
return text;
|
||||||
}).collect(Collectors.joining("\n\n"));
|
}).collect(Collectors.joining("\n\n"));
|
||||||
|
|
||||||
@ -152,7 +204,13 @@ public class BotHandler {
|
|||||||
|
|
||||||
private PhotoSize getSmallestPhoto(PhotoSize[] photoSizes) {
|
private PhotoSize getSmallestPhoto(PhotoSize[] photoSizes) {
|
||||||
return Arrays.stream(photoSizes)
|
return Arrays.stream(photoSizes)
|
||||||
.min(Comparator.comparingInt(ps -> ps.width() * ps.height()))
|
.min(photoSizeComparator)
|
||||||
|
.orElse(photoSizes[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PhotoSize getBiggestPhoto(PhotoSize[] photoSizes) {
|
||||||
|
return Arrays.stream(photoSizes)
|
||||||
|
.max(photoSizeComparator)
|
||||||
.orElse(photoSizes[0]);
|
.orElse(photoSizes[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user