Skip to content

Instantly share code, notes, and snippets.

@JarvisCraft
Created May 20, 2019 22:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JarvisCraft/c853a1ec979234db706dedb24a1dc31b to your computer and use it in GitHub Desktop.
Save JarvisCraft/c853a1ec979234db706dedb24a1dc31b to your computer and use it in GitHub Desktop.
CatOBot handler scripts
import com.vk.api.sdk.callback.CallbackApi
import com.vk.api.sdk.objects.messages.AudioMessage
import com.vk.api.sdk.objects.messages.Message
import groovy.transform.Canonical
import groovy.transform.builder.Builder
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import ru.progrm_jarvis.catobot.CatOBot
import ru.progrm_jarvis.catobot.ai.RecognitionResult
import ru.progrm_jarvis.catobot.image.CatImage
import ru.progrm_jarvis.catobot.util.CollectionUtil
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ExecutionException
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.function.Function
import java.util.stream.Stream
return (bot) -> {
return new VkCallbackHandler(bot)
} as Function<CatOBot, CallbackApi>
@Canonical
class VkCallbackHandler extends CallbackApi {
protected static Logger log = LoggerFactory.getLogger("VK-Handler")
protected final CatOBot bot
protected ExecutorService executor
protected Messages messages
VkCallbackHandler(final CatOBot bot) {
this.bot = bot
executor = Executors.newCachedThreadPool()
log.info("Loading messages for VK-handler")
messages = loadMessages()
log.info("Loaded messages for VK-handler: {}", messages)
}
@SuppressWarnings("GrMethodMayBeStatic")
Messages loadMessages() {
new Messages()
}
@Override
void messageNew(final Integer groupId, final Message message) {
executor.submit(() -> {
log.debug("Received VK message: {}", message)
AudioMessage audioMessage
for(attachment in message.attachments) {
attachment = attachment.audioMessage
if (attachment != null) {
audioMessage = attachment
break
}
}
CompletableFuture<Optional<RecognitionResult>> recognition
if (audioMessage != null) {
def audioStream = bot.vk.toMp3InputStream(audioMessage)
if (audioStream.present) recognition = bot.recognizer.recognizeSpeech(audioStream.get(), null)
else {
sendRandomMessage(message, messages.unavailableAudioMessage)
return
}
} else recognition = bot.recognizer.recognizeMessage(message.text, null)
recognition.whenComplete((result, x) -> {
if (result.present) {
final def entities = result.get().entities
// check if the message relates to the bot
if (message.getPeerId() >= 2000000000) {
// this means that the message is from a chat which means
// that a mention-check should be performed
// should contain `general` or `vk` mention
def mention = entities.getAsJsonArray("mention")
if (mention == null || mention.isEmpty()) return
mention = mention.get(0).asJsonObject.get("value").asString
if (mention != "general" && mention != "vk") return
}
def intent = entities .getAsJsonArray("intent")
if (intent == null || intent.empty) {
sendRandomMessage(message, messages.noIntent)
return
}
intent = intent.get(0).asJsonObject
switch (intent.get("value").asString) {
case "get_cat_images":
def imagesCount
def numberJson = entities.getAsJsonArray("number")
if (numberJson == null || numberJson.empty) imagesCount = 1
else imagesCount = Math.max(
1, Math.min(10, numberJson.get(0).asJsonObject.get("value").asInt)
)
bot.vk.sendCatImages(
message.peerId, message.id, bot.catImages.pickRandomCatImages(imagesCount, null
)
.parallelStream()
.flatMap { imageFuture ->
def image
try {
image = imageFuture.get()
} catch (InterruptedException | ExecutionException e) {
log.error("An exception occurred while getting one of the images", e)
return Stream.empty()
}
return image.map(Stream::of).orElseGet(Stream::empty)
}
.toArray() as CatImage[])
break
}
} else bot.vk.sendCatsUnavailable(message.peerId, message.id)
})
})
}
protected void sendRandomMessage(final Message message, final List<String> messages) {
final def text = CollectionUtil.getRandom(messages)
if (text.present) {
final def vk = bot.vk, peer = message.peerId
vk.client.messages()
.send(vk.groupActor)
.peerId(peer)
.randomId(vk.getRandomMessageId(peer))
.replyTo(message.id)
.message(text.get())
.execute()
}
}
@Builder
@Canonical
static class Messages {
List<String> noIntent = ["Unknown action"]
List<String> unavailableAudioMessage = ["Unavailable audio-message"]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment