diff --git a/build.gradle.kts b/build.gradle.kts index ea14242..8c13313 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -20,10 +20,10 @@ dependencies { embed(kotlin("stdlib-jdk8")) implementation("org.spongepowered:spongeapi:7.0.0") implementation("com.squareup.retrofit2:retrofit:2.5.0") -} - -tasks.withType { - kotlinOptions.jvmTarget = "1.8" + implementation("com.squareup.retrofit2:converter-gson:2.5.0") + implementation("com.squareup.retrofit2:adapter-rxjava2:2.5.0") + implementation("io.reactivex.rxjava2:rxkotlin:2.2.0") + implementation("com.squareup.okhttp3:logging-interceptor:3.12.0") } val jar: Jar by tasks @@ -31,4 +31,9 @@ jar.apply { from(configurations["embed"].map { if (it.isDirectory) it as Any else zipTree(it) }) -} \ No newline at end of file +} + +val compileKotlin: KotlinCompile by tasks +compileKotlin.kotlinOptions { + jvmTarget = "1.8" +} diff --git a/src/main/java/com/m4kvn/loginnotification/Main.kt b/src/main/java/com/m4kvn/loginnotification/Main.kt index 40c3adf..813edeb 100644 --- a/src/main/java/com/m4kvn/loginnotification/Main.kt +++ b/src/main/java/com/m4kvn/loginnotification/Main.kt @@ -1,15 +1,31 @@ package com.m4kvn.loginnotification +import com.m4kvn.loginnotification.service.discord.DiscordService +import io.reactivex.rxkotlin.subscribeBy +import io.reactivex.schedulers.Schedulers +import ninja.leaping.configurate.ConfigurationNode +import ninja.leaping.configurate.hocon.HoconConfigurationLoader +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor import org.slf4j.Logger import org.spongepowered.api.Sponge +import org.spongepowered.api.config.ConfigDir import org.spongepowered.api.event.Listener +import org.spongepowered.api.event.entity.living.humanoid.player.TargetPlayerEvent +import org.spongepowered.api.event.game.state.GameLoadCompleteEvent import org.spongepowered.api.event.game.state.GameStartedServerEvent +import org.spongepowered.api.event.game.state.GameStoppedServerEvent import org.spongepowered.api.event.network.ClientConnectionEvent import org.spongepowered.api.plugin.Plugin import org.spongepowered.api.text.Text import org.spongepowered.api.text.format.TextColors +import retrofit2.Retrofit +import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory +import retrofit2.converter.gson.GsonConverterFactory +import java.nio.file.Path import javax.inject.Inject + @Plugin( id = "login-notification", name = "Login Notification", @@ -18,19 +34,101 @@ import javax.inject.Inject ) class Main { + @Inject + lateinit var logger: Logger + + @Inject + @ConfigDir(sharedRoot = false) + lateinit var privateConfigDir: Path + + private val baseUrl = "https://discordapp.com/api/webhooks/" + + private val discord: DiscordService by lazy { + val interceptor = HttpLoggingInterceptor(HttpLoggingInterceptor + .Logger { logger.debug(it) }) + .apply { level = HttpLoggingInterceptor.Level.BODY } + val client = OkHttpClient.Builder() + .addInterceptor(interceptor) + .build() + val retrofit = Retrofit.Builder() + .client(client) + .addConverterFactory(GsonConverterFactory.create()) + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + .baseUrl(baseUrl) + .build() + retrofit.create(DiscordService::class.java) + } + + private val configLoader: HoconConfigurationLoader by lazy { + HoconConfigurationLoader.builder() + .setPath(privateConfigDir) + .build() + } + + private val configRoot: ConfigurationNode by lazy { + if (configLoader.canLoad()) + configLoader.load() else + configLoader.createEmptyNode() + } + + private val discordUrl: String + get() = configRoot.getNode("discord", "webhook").getString("") + + @Listener + fun onGameLoadComplete(event: GameLoadCompleteEvent) { + configRoot.getNode("discord", "webhook").apply { + if (getString("").isNullOrBlank()) { + value = "" + info("Please add your discord webhook url to config file.") + } + } + if (configLoader.canSave()) { + configLoader.save(configRoot) + } + } + @Listener fun onServerStart(event: GameStartedServerEvent) { - info("Sponge Server Plugin Login Notification on Start.") + val message = "Server Started (${Sponge.getServer().motd.toPlain()})" + info(message) + discord.postChannelMessage(discordUrl, mapOf("content" to message)) + .subscribeOn(Schedulers.io()) + .subscribeBy(onError = { + it.printStackTrace() + }) + } + + @Listener + fun onServerStop(event: GameStoppedServerEvent) { + val message = "Server stopped (${Sponge.getServer().motd.toPlain()})" + info(message) + discord.postChannelMessage(discordUrl, mapOf("content" to message)) + .subscribeOn(Schedulers.io()) + .subscribeBy(onError = { + it.printStackTrace() + }) } @Listener fun onJoin(event: ClientConnectionEvent.Join) { - info("onJoin=${event.targetEntity.displayNameData.displayName().get().toPlain()}") + val message = "Player joined (${event.playerName})" + info(message) + discord.postChannelMessage(discordUrl, mapOf("content" to message)) + .subscribeOn(Schedulers.io()) + .subscribeBy(onError = { + it.printStackTrace() + }) } @Listener fun onDisconnect(event: ClientConnectionEvent.Disconnect) { - info("onDisconnect=${event.targetEntity.displayNameData.displayName().get().toPlain()}") + val message = "Player disconnected (${event.playerName})" + info(message) + discord.postChannelMessage(discordUrl, mapOf("content" to message)) + .subscribeOn(Schedulers.io()) + .subscribeBy(onError = { + it.printStackTrace() + }) } private fun info(message: String) { @@ -38,4 +136,7 @@ class Main { .color(TextColors.AQUA).build() Sponge.getGame().server.console.sendMessage(text) } + + private val TargetPlayerEvent.playerName: String + get() = targetEntity.displayNameData.displayName().get().toPlain() } \ No newline at end of file diff --git a/src/main/java/com/m4kvn/loginnotification/service/discord/DiscordService.kt b/src/main/java/com/m4kvn/loginnotification/service/discord/DiscordService.kt new file mode 100644 index 0000000..bab0433 --- /dev/null +++ b/src/main/java/com/m4kvn/loginnotification/service/discord/DiscordService.kt @@ -0,0 +1,20 @@ +package com.m4kvn.loginnotification.service.discord + +import io.reactivex.Completable +import retrofit2.http.Body +import retrofit2.http.Headers +import retrofit2.http.POST +import retrofit2.http.Url + +interface DiscordService { + + @Headers( + "Accept: application/json", + "Content-type: application/json" + ) + @POST + fun postChannelMessage( + @Url url: String, + @Body data: Map + ): Completable +} \ No newline at end of file