Skip to content

Commit

Permalink
Notify users of fallback contact via DM first
Browse files Browse the repository at this point in the history
Fall back to server channel ping as the last resort
  • Loading branch information
Willdotwhite committed Apr 21, 2024
1 parent 5d1a653 commit 1f4fadb
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 23 deletions.
52 changes: 52 additions & 0 deletions api/src/main/kotlin/com/gmtkgamejam/bot/BotMessageBuilder.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.gmtkgamejam.bot

import com.gmtkgamejam.services.PostService
import org.javacord.api.entity.message.embed.EmbedBuilder
import org.javacord.api.entity.user.User

class BotMessageBuilder {

private val postService = PostService()

fun canBuildEmbedFromUser(sender: User): Boolean = postService.getPostByAuthorId(sender.id.toString()) != null

fun embedMessage(recipient: User, sender: User): EmbedBuilder {
val post = postService.getPostByAuthorId(sender.id.toString())!!

val shortDescription = if (post.description.length > 240) post.description.take(237) + "..." else post.description

val embed = EmbedBuilder()
.setTitle("${sender.name} wants to get in contact!")
.setDescription("Hey there ${recipient.name}! ${sender.name} wants to get in touch - this is a summary of their current post on the Team Finder!")
.setAuthor("GMTK Team Finder", "https://findyourjam.team/", "https://findyourjam.team/logos/jam-logo-stacked.webp")
.addField("Description", shortDescription)

// Add optional fields - turns out this includes timezones
if (post.skillsSought?.isNotEmpty() == true) {
embed.addField("${sender.name} is looking for:", post.skillsSought.toString())
}
if (post.skillsPossessed?.isNotEmpty() == true) {
embed.addField("${sender.name} can bring:", post.skillsPossessed.toString())
}
if (post.preferredTools?.isNotEmpty() == true) {
embed.addField("Engine(s)", post.preferredTools.toString())
}
if (post.timezoneOffsets.isNotEmpty()) {
embed.addField("Timezone(s)", post.timezoneOffsets.map { if (it < 0) "UTC-$it" else "UTC+$it" }.toString())
}

embed
.addField("Like what you see?", "Check out their full post here to see more! https://findyourjam.team/gmtk/${post.id}/")
.setFooter("Feedback? DM @dotwo in the #developing-gtmk-team-finder-app channel")

return embed
}

// TODO: Add a variety of messages to mix things up a bit?
fun basicMessage(recipient: User, sender: User): String {
return """
Hey ${recipient.mentionTag}, ${sender.mentionTag} wants to get in contact about your Team Finder post!"
They don't have a post on the Team Finder yet, so why not drop them a message and find out more?
""".trimIndent()
}
}
25 changes: 25 additions & 0 deletions api/src/main/kotlin/com/gmtkgamejam/bot/DiscordBot.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.gmtkgamejam.bot

import com.gmtkgamejam.Config
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.future.await
import kotlinx.coroutines.withContext
import org.javacord.api.DiscordApi
import org.javacord.api.DiscordApiBuilder
import org.javacord.api.entity.channel.ServerTextChannel
Expand All @@ -13,6 +15,7 @@ import org.javacord.api.exception.DiscordException
import org.javacord.api.exception.MissingPermissionsException
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import kotlin.jvm.optionals.getOrElse

class DiscordBot {

Expand All @@ -24,6 +27,8 @@ class DiscordBot {

private lateinit var channel: ServerTextChannel

private val messageBuilder = BotMessageBuilder()

private val approvedUsers: MutableList<String> = mutableListOf()

init {
Expand Down Expand Up @@ -51,6 +56,26 @@ class DiscordBot {
val recipient: User = api.getUserById(recipientUserId).await()
val sender: User = api.getUserById(senderUserId).await()

val dmChannel = recipient.privateChannel.getOrElse { recipient.openPrivateChannel().get() }

val messageSendAttempt = if (messageBuilder.canBuildEmbedFromUser(sender)) {
dmChannel.sendMessage(messageBuilder.embedMessage(recipient, sender))
} else {
dmChannel.sendMessage(messageBuilder.basicMessage(recipient, sender))
}

try {
withContext(Dispatchers.IO) {
messageSendAttempt.get()
}
} catch (ex: InterruptedException) {
createFallbackChannelPingMessage(recipient, sender)
} catch (ex: java.util.concurrent.ExecutionException) {
createFallbackChannelPingMessage(recipient, sender)
}
}

private suspend fun createFallbackChannelPingMessage(recipient: User, sender: User) {
val messageContents = "Hey ${recipient.mentionTag}, ${sender.mentionTag} wants to get in contact about your Team Finder post!"
// TODO: Validate message actually sent, give error otherwise
channel.sendMessage(messageContents).await()
Expand Down
24 changes: 14 additions & 10 deletions api/src/main/kotlin/com/gmtkgamejam/models/posts/Skills.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package com.gmtkgamejam.models.posts

enum class Skills {
ART_2D,
ART_3D,
CODE,
DESIGN_PRODUCTION,
SFX,
MUSIC,
TESTING_SUPPORT,
TEAM_LEAD,
OTHER;
enum class Skills(private var readableName: String) {
ART_2D("2D Art"),
ART_3D("3D Art"),
CODE("Code"),
DESIGN_PRODUCTION("Design/Production"),
SFX("SFX"),
MUSIC("Music"),
TESTING_SUPPORT("Testing/Support"),
TEAM_LEAD("Team lead"),
OTHER("Other");

override fun toString(): String {
return readableName;
}
}
26 changes: 15 additions & 11 deletions api/src/main/kotlin/com/gmtkgamejam/models/posts/Tools.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package com.gmtkgamejam.models.posts

// For the time being, Tool == Engine
enum class Tools {
UNITY,
CONSTRUCT,
GAME_MAKER_STUDIO,
GODOT,
TWINE,
BITSY,
UNREAL,
RPG_MAKER,
PICO_8,
OTHER,
enum class Tools(private var readableName: String) {
UNITY("Unity"),
CONSTRUCT("Construct"),
GAME_MAKER_STUDIO("Game Maker Studio"),
GODOT("Godot"),
TWINE("Twine"),
BITSY("Bitsy"),
UNREAL("Unreal"),
RPG_MAKER("RPG Maker"),
PICO_8("PICO 8"),
OTHER("Other");

override fun toString(): String {
return readableName;
}
}
2 changes: 1 addition & 1 deletion ui/src/pages/post/Post.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ const MessageOnDiscordButton: React.FC<{
{canPostAuthorBeDMd && <DiscordMessageButton authorId={authorId} author={author} isLoggedIn={isLoggedIn} />}

{inDiscordServer
? <DiscordPingButton authorId={authorId} createBotDmMutation={createBotDmMutation} message={fallbackPingMessage} />
? <DiscordPingButton authorId={authorId} authorName={author} createBotDmMutation={createBotDmMutation} message={fallbackPingMessage} />
: <>
<p>Sorry, you can&apos;t contact this user right now.</p>
<p>
Expand Down
17 changes: 16 additions & 1 deletion ui/src/pages/post/components/DiscordPingButton.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,37 @@
import React from "react";
import {toast} from "react-hot-toast";

export const DiscordPingButton: React.FC<{
authorId: string,
authorName: string,
createBotDmMutation: any,
message: string
}> = ({
authorId,
authorName,
createBotDmMutation,
message,
}) => {

const onClick = () => {
createBotDmMutation.mutate({
recipientId: authorId,
}, {
onSuccess: () => {
toast(`${authorName} has just been notified that you want to get in touch!`);
},

});
};

return (
<>
<p className="mb-2">{message}</p>
<span className="mb-6 p-2 rounded inline-flex cursor-pointer rounded-xl border border-theme-l-7 text-theme-l-7">
<a
target="_blank"
rel="noreferrer"
onClick={() => createBotDmMutation.mutate({ recipientId: authorId })}
onClick={onClick}
className="text-sm"
>
Ping them on Discord
Expand Down

0 comments on commit 1f4fadb

Please sign in to comment.