1
+ import com.google.gson.JsonObject
2
+ import com.lambda.client.LambdaMod
3
+ import com.lambda.client.command.CommandManager
4
+ import com.lambda.client.event.events.ConnectionEvent
5
+ import com.lambda.client.module.Category
6
+ import com.lambda.client.plugin.api.PluginModule
7
+
8
+ import com.lambda.client.event.events.PacketEvent
9
+ import com.lambda.client.manager.managers.FriendManager
10
+ import com.lambda.client.manager.managers.MessageManager
11
+ import com.lambda.client.manager.managers.MessageManager.newMessageModifier
12
+ import com.lambda.client.mixin.extension.textComponent
13
+ import com.lambda.client.module.modules.chat.ChatTimestamp
14
+ import com.lambda.client.util.TickTimer
15
+ import com.lambda.client.util.TimeUnit
16
+ import com.lambda.client.util.text.MessageDetection
17
+ import com.lambda.client.util.text.MessageSendHelper
18
+ import com.lambda.client.util.text.MessageSendHelper.sendServerMessage
19
+ import com.lambda.client.util.text.format
20
+ import com.lambda.client.util.text.formatValue
21
+ import com.lambda.client.util.threads.defaultScope
22
+ import com.lambda.client.util.threads.safeListener
23
+ import com.lambda.commons.utils.ConnectionUtils
24
+ import com.lambda.commons.utils.SystemUtils
25
+ import com.lambda.event.listener.listener
26
+ import kotlinx.coroutines.Dispatchers
27
+ import kotlinx.coroutines.launch
28
+ import net.minecraft.network.play.server.SPacketChat
29
+ import net.minecraft.util.text.TextFormatting
30
+ import net.minecraftforge.fml.common.gameevent.TickEvent
31
+ import org.apache.commons.io.IOUtils
32
+
33
+ internal object ChatPlusDiscordNotifs: PluginModule(
34
+ name = " DiscordNotifs" ,
35
+ category = Category .CHAT ,
36
+ description = " Sends your chat to a set Discord channel" ,
37
+ pluginMain = ChatPlusPlugin
38
+ ) {
39
+ private val timeout by setting(" Timeout" , true )
40
+ private val timeoutTime by setting(" Seconds" , 10 , 0 .. 120 , 5 , { timeout })
41
+ private val time by setting(" Timestamp" , true )
42
+ private val importantPings by setting(" Important Pings" , false )
43
+ private val connectionChange by setting(" Connection Change" , true , description = " When you get disconnected or reconnected to the server" )
44
+ private val all by setting(" All Messages" , false )
45
+ private val direct by setting(" DMs" , true , { ! all })
46
+ private val queue by setting(" Queue Position" , true , { ! all })
47
+ private val restart by setting(" Restart" , true , { ! all }, description = " Server restart notifications" )
48
+
49
+ val url = setting(" URL" , " unchanged" )
50
+ val pingID = setting(" Ping ID" , " unchanged" )
51
+ val avatar = setting(" Avatar" , " ${LambdaMod .GITHUB_LINK } /assets/raw/assets/assets/icons/kamiGithub.png" )
52
+
53
+ private const val username = " ${LambdaMod .NAME } ${LambdaMod .VERSION } "
54
+ private val server: String get() = mc.currentServerData?.serverIP ? : " the server"
55
+ private val timer = TickTimer (TimeUnit .SECONDS )
56
+
57
+ /* Listeners to send the messages */
58
+ init {
59
+ safeListener<PacketEvent .Receive > {
60
+ if (it.packet !is SPacketChat ) return @safeListener
61
+ val message = (it.packet as SPacketChat ).chatComponent.unformattedText
62
+
63
+ if (timeout(message) && shouldSend(message)) {
64
+ sendMessage(getPingID(message) + getMessageType(message, server) + getTime() + message)
65
+ }
66
+ }
67
+
68
+ listener<ConnectionEvent .Connect > {
69
+ if (! connectionChange) return @listener
70
+ sendMessage(getPingID(" KamiBlueMessageType1" ) + getTime() + getMessageType(" KamiBlueMessageType1" , server))
71
+ }
72
+
73
+ listener<ConnectionEvent .Disconnect > {
74
+ if (! connectionChange) return @listener
75
+ sendMessage(getPingID(" KamiBlueMessageType2" ) + getTime() + getMessageType(" KamiBlueMessageType2" , server))
76
+ }
77
+
78
+ /* Always on status code */
79
+ safeListener<TickEvent .ClientTickEvent > {
80
+ if (url.value == " unchanged" ) {
81
+ MessageSendHelper .sendErrorMessage(chatName + " You must first set a webhook url with the " +
82
+ formatValue(" ${CommandManager .prefix} discordnotifs" ) +
83
+ " command" )
84
+ disable()
85
+ } else if (pingID.value == " unchanged" && importantPings) {
86
+ MessageSendHelper .sendErrorMessage(chatName + " For Pings to work, you must set a Discord ID with the " +
87
+ formatValue(" ${CommandManager .prefix} discordnotifs" ) +
88
+ " command" )
89
+ disable()
90
+ }
91
+ }
92
+ }
93
+
94
+ private fun shouldSend (message : String ): Boolean {
95
+ return all
96
+ || direct && MessageDetection .Direct .ANY detect message
97
+ || restart && MessageDetection .Server .RESTART detect message
98
+ || queue && MessageDetection .Server .QUEUE detect message
99
+ }
100
+
101
+ private fun getMessageType (message : String , server : String ): String {
102
+ if (direct && MessageDetection .Direct .RECEIVE detect message) return " You got a direct message!\n "
103
+ if (direct && MessageDetection .Direct .SENT detect message) return " You sent a direct message!\n "
104
+ if (message == " KamiBlueMessageType1" ) return " Connected to $server "
105
+ return if (message == " KamiBlueMessageType2" ) " Disconnected from $server " else " "
106
+ }
107
+
108
+ private fun timeout (message : String ) = ! timeout
109
+ || restart && MessageDetection .Server .RESTART detect message
110
+ || direct && MessageDetection .Direct .ANY detect message
111
+ || timer.tick(timeoutTime.toLong())
112
+
113
+ /* Text formatting and misc methods */
114
+ private fun getPingID (message : String ) = if (message == " KamiBlueMessageType1"
115
+ || message == " KamiBlueMessageType2"
116
+ || direct && MessageDetection .Direct .ANY detect message
117
+ || restart && MessageDetection .Server .RESTART detect message
118
+ || importantPings && MessageDetection .Server .QUEUE_IMPORTANT detect message) formatPingID()
119
+ else " "
120
+
121
+ private fun formatPingID (): String {
122
+ return if (! importantPings) " " else " <@!${pingID.value} >: "
123
+ }
124
+
125
+ private fun getTime () =
126
+ if (! time) " "
127
+ else ChatTimestamp .time
128
+
129
+ private fun sendMessage (content : String ) {
130
+ defaultScope.launch(Dispatchers .IO ) {
131
+ ConnectionUtils .runConnection(
132
+ url.value,
133
+ { connection ->
134
+ val bytes = JsonObject ().run {
135
+ addProperty(" username" , username)
136
+ addProperty(" content" , content)
137
+ addProperty(" avatar_url" , avatar.value)
138
+ toString().toByteArray(Charsets .UTF_8 )
139
+ }
140
+
141
+ connection.setRequestProperty(" Content-Type" , " application/json; charset=UTF-8" )
142
+ connection.setRequestProperty(" Accept" , " application/json" )
143
+ connection.setRequestProperty(" User-Agent" , " " )
144
+
145
+ connection.requestMethod = " POST"
146
+ connection.outputStream.use {
147
+ it.write(bytes)
148
+ }
149
+
150
+ val response = connection.inputStream.use {
151
+ IOUtils .toString(it, Charsets .UTF_8 )
152
+ }
153
+
154
+ if (response.isNotEmpty()) {
155
+ LambdaMod .LOG .info(" Unexpected response from DiscordNotifs http request: $response " )
156
+ }
157
+ },
158
+ {
159
+ LambdaMod .LOG .warn(" Error while sending webhook" , it)
160
+ },
161
+ )
162
+ }
163
+ }
164
+ }
0 commit comments