Skip to content

Commit

Permalink
Notify users of fallback contact via DM instead of channel ping
Browse files Browse the repository at this point in the history
  • Loading branch information
Willdotwhite committed Apr 21, 2024
1 parent 5d1a653 commit a6d5daf
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 35 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()
}
}
18 changes: 9 additions & 9 deletions api/src/main/kotlin/com/gmtkgamejam/bot/DiscordBot.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import com.gmtkgamejam.Config
import kotlinx.coroutines.future.await
import org.javacord.api.DiscordApi
import org.javacord.api.DiscordApiBuilder
import org.javacord.api.entity.channel.ServerTextChannel
import org.javacord.api.entity.intent.Intent
import org.javacord.api.entity.message.MessageBuilder
import org.javacord.api.entity.server.Server
Expand All @@ -13,6 +12,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 @@ -22,7 +22,7 @@ class DiscordBot {

private lateinit var server: Server

private lateinit var channel: ServerTextChannel
private val messageBuilder = BotMessageBuilder()

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

Expand All @@ -31,16 +31,12 @@ class DiscordBot {
val builder = DiscordApiBuilder().setToken(token).setIntents(Intent.GUILD_MEMBERS)

val guildId = Config.getString("jam.guildId")
val channelName = Config.getString("bot.pingChannel")

try {
api = builder.login().join()
server = api.getServerById(guildId).get()

channel = api.getServerTextChannelsByNameIgnoreCase(channelName).first()
logger.info("Discord bot is online and ready for action!")
} catch (ex: NoSuchElementException) { // NoSuchElementException triggered by calling `.first()` on Collection
logger.warn("Discord bot could not connect to pingChannel [$channelName] - ping message integration offline.")
} catch (ex: Exception) {
logger.warn("Discord bot could not be initialised - continuing...")
logger.warn(ex.toString())
Expand All @@ -51,9 +47,13 @@ class DiscordBot {
val recipient: User = api.getUserById(recipientUserId).await()
val sender: User = api.getUserById(senderUserId).await()

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()
val dmChannel = recipient.privateChannel.getOrElse { recipient.openPrivateChannel().get() }

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

suspend fun doesUserHaveValidPermissions(userId: String): Boolean {
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;
}
}
3 changes: 0 additions & 3 deletions api/src/main/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@ jam {
}

bot {
pingChannel = "jam-team-notifs"
pingChannel = ${?DISCORD_NOTIFICATION_CHANNEL}

token = default_token_to_let_app_start
token = ${?DISCORD_BOT_TOKEN}

Expand Down
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 a6d5daf

Please sign in to comment.