Skip to content

Commit ce3ec75

Browse files
committed
Spigot/CB 1.5 & Paper/Folia 1.0
* Moved from Maven to Gradle * Removed /discordbroadcast * A new Paper/Folia version! * Added a "/mainc" subcommand: Show some information about the main connection * Added a "/discordcmds" subcommand: Show the registered commands for the bot * Added a "/broadcast" subcommand: Same function as the old "/discordbroadcast" * Added a "/reload" subcommand * Added a few modules that contain shared code * Added DiscordContext: A class that manages the bot, channels, commands, and has methods for sending messages. The main API to be used. * Added MessageParts: Data holder for formatting messages from Discord to Minecraft * Added DSerial & DSerialAdvnt: 2 (de)serializers for messages. The main difference between them is that DSerialAdvnt also uses Kyori Adventure, thus it is used for Spigot & Paper/Folia. * Added 2 Cancellable Bukkit Events: BridgeDiscordReceiveEvent (triggered when a discord user sends a message) & BridgeMinecraftReceiveEvent (triggered when a player sends a message) * Fixes the bug where mentioning users in Minecraft wouldn't work in no way. It now works when the mentioned user has interacted with the bot (e.g. sent a message in the bridge channel) * The Folia support is very experimental 👍 * Added javadocs for a lot of methods
1 parent c2923d7 commit ce3ec75

File tree

62 files changed

+2692
-529
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+2692
-529
lines changed

.gitignore

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
.gradle
2+
build/
3+
!gradle/wrapper/gradle-wrapper.jar
4+
!**/src/main/**/build/
5+
!**/src/test/**/build/
6+
7+
### IntelliJ IDEA ###
8+
.idea/modules.xml
9+
.idea/jarRepositories.xml
10+
.idea/compiler.xml
11+
.idea/libraries/
12+
*.iws
13+
*.iml
14+
*.ipr
15+
out/
16+
!**/src/main/**/out/
17+
!**/src/test/**/out/
18+
19+
### Eclipse ###
20+
.apt_generated
21+
.classpath
22+
.factorypath
23+
.project
24+
.settings
25+
.springBeans
26+
.sts4-cache
27+
bin/
28+
!**/src/main/**/bin/
29+
!**/src/test/**/bin/
30+
31+
### NetBeans ###
32+
/nbproject/private/
33+
/nbbuild/
34+
/dist/
35+
/nbdist/
36+
/.nb-gradle/
37+
38+
### VS Code ###
39+
.vscode/
40+
41+
### Mac OS ###
42+
.DS_Store
43+
44+
/craftbukkit/cb
45+
/craftbukkit/lib

DSerial/build.gradle.kts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
plugins { kotlin("jvm") version "2.2.0" }
2+
3+
group = rootProject.group
4+
5+
dependencies { api(kotlin("stdlib-jdk8")) }
6+
7+
kotlin { jvmToolchain(8) }
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package me.lukiiy.discordBridge.api.serialize
2+
3+
import me.lukiiy.discordBridge.api.serialize.DSerial.fromDiscord
4+
import me.lukiiy.discordBridge.api.serialize.DSerial.toDiscord
5+
import net.dv8tion.jda.api.entities.Message
6+
7+
8+
object DSerial {
9+
@JvmStatic
10+
val styles = mapOf(
11+
'l' to "**",
12+
'o' to "*",
13+
'n' to "__",
14+
'm' to "~~",
15+
'k' to "||"
16+
)
17+
18+
@JvmStatic val reverseStyles = styles.entries.associate { it.value to it.key }
19+
@JvmStatic val regex = Regex("(${styles.values.joinToString("|") { Regex.escape(it) }})(.+?)\\1")
20+
21+
/**
22+
* Convert a legacy string into a Discord markdown-usable string
23+
* @see [fromDiscord]
24+
* @return A Discord Markdown formatted string
25+
*/
26+
@JvmStatic
27+
fun toDiscord(input: String): String {
28+
val result = StringBuilder()
29+
var i = 0
30+
31+
while (i < input.length) {
32+
if (input[i] == '§' && i + 1 < input.length) {
33+
val markdown = styles[input[i + 1]]
34+
35+
if (markdown != null) {
36+
val start = i + 2
37+
val end = input.indexOf('§', start).takeIf { it != -1 } ?: input.length
38+
result.append(markdown).append(input.substring(start, end)).append(markdown)
39+
i = end
40+
continue
41+
}
42+
}
43+
result.append(input[i])
44+
i++
45+
}
46+
47+
return result.toString().replace(Regex("§."), "")
48+
}
49+
50+
/**
51+
* Convert a Discord Markdown formatted string into a legacy string
52+
* @see [toDiscord]
53+
* @return A legacy string
54+
*/
55+
@JvmStatic
56+
fun fromDiscord(input: String): String {
57+
return regex.replace(input) { match ->
58+
val code = reverseStyles[match.groupValues[1]] ?: return@replace match.value
59+
"§$code$match.groupValues[2]§r"
60+
}
61+
}
62+
63+
/**
64+
* Gets and returns a list of little information about a [Message]'s attachments and embends.
65+
* Not intended for external use.
66+
* @return A list of somewhat usable information
67+
*/
68+
@JvmStatic
69+
fun listAttachments(message: Message): List<String> {
70+
val result = mutableListOf<String>()
71+
72+
message.attachments.forEach { result.add("§8[${it.fileName.substringAfterLast('.', "file")} file]§f") }
73+
if (message.embeds.isNotEmpty()) result.add(" §8[${message.embeds.size} embed file(s)]§f")
74+
75+
return result
76+
}
77+
}

DSerialAdvnt/build.gradle.kts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
plugins { kotlin("jvm") version "2.2.0" }
2+
3+
group = rootProject.group
4+
5+
dependencies {
6+
api("net.kyori:adventure-text-minimessage:4.22.0")
7+
api("net.kyori:adventure-text-serializer-legacy:4.22.0")
8+
api("net.kyori:adventure-text-serializer-plain:4.22.0")
9+
implementation(kotlin("stdlib-jdk8"))
10+
}
11+
12+
kotlin { jvmToolchain(8) }
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package me.lukiiy.discordBridge.api.serialize
2+
3+
import me.lukiiy.discordBridge.BridgeDefaults
4+
import me.lukiiy.discordBridge.api.serialize.DSerialAdvnt.fromDiscord
5+
import me.lukiiy.discordBridge.api.serialize.DSerialAdvnt.toDiscord
6+
import net.dv8tion.jda.api.entities.Message
7+
import net.kyori.adventure.text.Component
8+
import net.kyori.adventure.text.TextComponent
9+
import net.kyori.adventure.text.TranslatableComponent
10+
import net.kyori.adventure.text.event.ClickEvent
11+
import net.kyori.adventure.text.format.Style
12+
import net.kyori.adventure.text.format.TextColor
13+
import net.kyori.adventure.text.format.TextDecoration
14+
import net.kyori.adventure.text.minimessage.MiniMessage
15+
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
16+
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer
17+
18+
object DSerialAdvnt {
19+
@JvmStatic val MINI = MiniMessage.miniMessage()
20+
21+
@JvmStatic val styles = mapOf(
22+
"b" to "**",
23+
"bold" to "**",
24+
"i" to "*",
25+
"italic" to "*",
26+
"u" to "__",
27+
"underlined" to "__",
28+
"s" to "~~",
29+
"strikethrough" to "~~",
30+
"obfuscated" to "||"
31+
)
32+
33+
@JvmStatic val reverseStyles = styles.entries.associate { it.value to it.key }
34+
@JvmStatic val regex = Regex("(${styles.values.joinToString("|") { Regex.escape(it) }})(.+?)\\1") // A pattern that can match discord md styles
35+
36+
/**
37+
* Convert a component into a Discord markdown-usable string
38+
* @see [fromDiscord]
39+
* @return A Discord Markdown formatted string
40+
*/
41+
@JvmStatic
42+
fun toDiscord(component: Component): String {
43+
val parts = mutableListOf<Pair<String, Set<TextDecoration>>>()
44+
45+
component.iterateStyled { text, style ->
46+
if (text.isNotEmpty()) parts.add(text to TextDecoration.entries.filter { style.hasDecoration(it) }.toSet())
47+
}
48+
49+
return buildString {
50+
var i = 0
51+
52+
while (i < parts.size) {
53+
val (text, decs) = parts[i]
54+
val grouped = StringBuilder(text)
55+
56+
while (i + 1 < parts.size && parts[i + 1].second == decs) grouped.append(parts[++i].first)
57+
58+
val tags = decs.mapNotNull { styles[it.name.lowercase()] }
59+
append(tags.joinToString("") + grouped + tags.reversed().joinToString(""))
60+
61+
i++
62+
}
63+
}
64+
}
65+
66+
/**
67+
* Convert a component into a Discord markdown-usable string
68+
* @see [fromDiscord]
69+
* @return A Discord Markdown formatted string
70+
*/
71+
@JvmStatic fun toDiscord(string: String): String = toDiscord(LegacyComponentSerializer.legacySection().deserialize(string))
72+
73+
/**
74+
* Convert a Discord Markdown formatted string into a component
75+
* @see [toDiscord]
76+
* @return A component
77+
*/
78+
@JvmStatic fun fromDiscord(s: String): Component = MINI.deserialize(regex.replace(s) { match -> reverseStyles[match.groupValues[1]]?.let { "<$it>${match.groupValues[2]}</$it>" } ?: match.value })
79+
80+
private fun Component.iterateStyled(consumer: (String, Style) -> Unit) {
81+
when (this) {
82+
is TextComponent -> consumer(content(), style())
83+
is TranslatableComponent -> consumer(key(), style())
84+
}
85+
86+
children().forEach { it.iterateStyled(consumer) }
87+
}
88+
89+
/**
90+
* Gets and returns a list of little information about a [Message]'s attachments and embends.
91+
* Not intended for external use.
92+
* @return A list of somewhat usable information
93+
*/
94+
@JvmStatic
95+
fun listAttachments(message: Message): List<Component> {
96+
val result = mutableListOf<Component>()
97+
val color = TextColor.color(0x40566b)
98+
val embeds = message.embeds
99+
100+
if (embeds.isNotEmpty()) result.add(Component.text("[${embeds.size} embed file(s)]", color))
101+
102+
message.attachments.forEach {
103+
result.add(Component.text("[${it.fileName.substringAfterLast('.', "file")} file]").color(color).clickEvent(ClickEvent.openUrl(it.url)))
104+
}
105+
106+
return result
107+
}
108+
109+
// Colors from BridgeDefaults
110+
@JvmStatic val bridgeBlue = TextColor.fromHexString(BridgeDefaults.HEX_PRIMARY)
111+
@JvmStatic val bridgeFaint = TextColor.fromHexString(BridgeDefaults.FAINTED)
112+
@JvmStatic val bridgeList = TextColor.fromHexString(BridgeDefaults.LIST)
113+
}

README.md

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,29 @@
11
# DiscordBridge
22

3-
> Minecraft 1.16.5+ Spigot/Paper Plugin
4-
> *Requires Java 17 or higher.*
3+
> Minecraft 1.16.5+ Spigot Plugin | 1.20.6+ Paper/Folia Plugin | Craftbukkit 1060 (b1.7.3) Plugin
54
---
65

7-
Creates a chat bridge between Discord & Minecraft.
6+
A somewhat cool plugin that creates a chat bridge between Discord & Minecraft.
87

9-
| Command | Description | Permission |
10-
|:-------------------|:-------------------------------:|-------------------:|
11-
| `discordbroadcast` | Broadcasts a message to Discord | dcbridge.broadcast |
12-
| `discordbridge` | Reloads the plugin | dcbridge.reload |
8+
| Command | Description | Permission |
9+
|:---|:---:|---:|
10+
| `discordbridge` | Main command, with many subcommands! | dcbridge.reload |
1311

14-
### Discord features
12+
> [!IMPORTANT]
13+
> [how 2 setup](https://github.com/Lukiiy/DiscordBridge/wiki/Setup)
14+
15+
## Discord features
1516

1617
| Command | Description | Roles |
1718
|:----------------|:-----------------------------:|-------------:|
1819
| `console` | Executes a command as console | Console |
1920

20-
## Here, have some tutorials!
21+
### Currently implemented hooks
2122

22-
[how 2 setup](https://github.com/Lukiiy/DiscordBridge/wiki/Setup)
23+
**Spigot:** PlaceholderAPI
24+
**Paper:** PlaceholderAPI, Advancements, Folia
2325

2426
### For developers
2527

26-
You can use the .jar file as a dependency.
28+
Feel free to make your own addons. For an example, refer to [DCBridge-Advancements](https://github.com/Lukiiy/DCBridge-Advancements).
29+
You can use the **.jar** file as a dependency.

build.gradle.kts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
plugins { java }
2+
3+
group = "me.lukiiy"
4+
description = project.property("description")?.toString()
5+
6+
repositories {
7+
mavenCentral()
8+
gradlePluginPortal()
9+
}
10+
11+
dependencies {}
12+
13+
subprojects {
14+
apply(plugin = "java")
15+
16+
repositories {
17+
mavenCentral()
18+
gradlePluginPortal()
19+
}
20+
21+
if (project.name != "common") dependencies { implementation(project(":common")) }
22+
}
23+
24+
tasks {
25+
jar { enabled = false }
26+
}

common/build.gradle.kts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
plugins { kotlin("jvm") version "2.2.0" }
2+
3+
group = rootProject.group
4+
5+
dependencies {
6+
api("net.dv8tion:JDA:5.6.1") {
7+
exclude(module = "opus-java")
8+
}
9+
api(kotlin("stdlib-jdk8"))
10+
}
11+
12+
kotlin { jvmToolchain(8) }
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package me.lukiiy.discordBridge
2+
3+
object BridgeDefaults {
4+
@JvmStatic val HEX_PRIMARY = "#647ff8"
5+
@JvmStatic val FAINTED = "#7175a3"
6+
@JvmStatic val LIST = "#6d7494"
7+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package me.lukiiy.discordBridge.api
2+
3+
import net.dv8tion.jda.api.interactions.commands.CommandInteraction
4+
import net.dv8tion.jda.api.interactions.commands.build.CommandData
5+
6+
/**
7+
* A simple Discord command plate
8+
*/
9+
interface CommandPlate {
10+
fun command(): CommandData
11+
12+
fun interaction(interaction: CommandInteraction)
13+
}

0 commit comments

Comments
 (0)