Skip to content

Commit 98f6d15

Browse files
authored
Merge pull request #71 from tarna/update-checker
feat: added update checker
2 parents 1c23e74 + 68eff4f commit 98f6d15

File tree

6 files changed

+145
-4
lines changed

6 files changed

+145
-4
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Discord: https://discord.onelitefeather.net
1919

2020
## Permissions
2121
- `attollo.use` - Allows the player to use the elevator
22+
- `attollo.update` - Allows the player to receive update notifications
2223

2324
## Configuration
2425
```yaml

build.gradle.kts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ repositories {
4646
dependencies {
4747
compileOnly("io.papermc.paper:paper-api:$minecraftVersion-R0.1-SNAPSHOT")
4848
implementation("net.kyori:adventure-text-minimessage:4.17.0")
49-
49+
implementation("com.github.zafarkhaja:java-semver:0.10.2")
5050

5151
// testing
5252
testImplementation(kotlin("test"))
@@ -77,6 +77,10 @@ bukkit {
7777
description = "Allows the player to use the plugin"
7878
default = Default.TRUE
7979
}
80+
register("attollo.update") {
81+
description = "Allows the player to see update notifications"
82+
default = Default.OP
83+
}
8084
}
8185
commands {
8286
register("attollo") {

src/main/kotlin/dev/themeinerlp/attollo/Attollo.kt

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package dev.themeinerlp.attollo
22

33
import dev.themeinerlp.attollo.listener.AttolloListener
4+
import dev.themeinerlp.attollo.listener.UpdateCheckerListener
5+
import dev.themeinerlp.attollo.service.UpdateService
46
import org.bukkit.Material
57
import org.bukkit.plugin.java.JavaPlugin
68

79
open class Attollo : JavaPlugin() {
810

9-
1011
lateinit var elevatorBlock: Material
12+
lateinit var updateService: UpdateService
13+
1114
override fun onLoad() {
1215
saveDefaultConfig()
1316
}
@@ -23,6 +26,18 @@ open class Attollo : JavaPlugin() {
2326
elevatorBlock = material ?: Material.DAYLIGHT_DETECTOR
2427
logger.info("Using elevatorBlock: $elevatorBlock")
2528
server.pluginManager.registerEvents(AttolloListener(this), this)
29+
updateChecker()
30+
}
31+
32+
override fun onDisable() {
33+
updateService.shutdown()
34+
}
35+
36+
private fun updateChecker() {
37+
updateService = UpdateService(this)
38+
updateService.run()
39+
updateService.notifyConsole(componentLogger)
40+
server.pluginManager.registerEvents(UpdateCheckerListener(this), this)
2641
}
2742

28-
}
43+
}
Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,16 @@
11
package dev.themeinerlp.attollo
22

3+
import java.net.URI
4+
import java.net.http.HttpRequest
5+
6+
7+
38
const val USE_PERMISSION = "attollo.use"
4-
const val BYTEBIN_BASE_URL = "https://paste.grim.ac/data"
9+
const val NOTIFY_UPDATE_PERMISSION = "attollo.update"
10+
const val BYTEBIN_BASE_URL = "https://paste.grim.ac/data"
11+
12+
const val NOTIFY_PLAYER_UPDATE_MESSAGE = "<yellow><download_url>Your version (<local_version>) is older than our latest published version (<remote_version>). Please update as soon as possible to get continued support. Or click me to get on the download page!"
13+
const val NOTIFY_CONSOLE_UPDATE_MESSAGE = "<yellow>Your version (<local_version>) is older than our latest published version (<remote_version>). Please update as soon as possible to get continued support. Or use this link <download_url>."
14+
15+
val LATEST_RELEASE_VERSION_URI = URI.create("https://hangar.papermc.io/api/v1/projects/Attollo/latestrelease")
16+
val LATEST_RELEASE_VERSION_REQUEST = HttpRequest.newBuilder().GET().uri(LATEST_RELEASE_VERSION_URI).build()
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package dev.themeinerlp.attollo.listener
2+
3+
import dev.themeinerlp.attollo.Attollo
4+
import dev.themeinerlp.attollo.NOTIFY_UPDATE_PERMISSION
5+
import org.bukkit.event.EventHandler
6+
import org.bukkit.event.Listener
7+
import org.bukkit.event.player.PlayerJoinEvent
8+
9+
class UpdateCheckerListener(private val attollo: Attollo) : Listener {
10+
11+
@EventHandler
12+
fun onJoin(event: PlayerJoinEvent) {
13+
val player = event.player
14+
if (player.isOp || player.hasPermission(NOTIFY_UPDATE_PERMISSION)) {
15+
attollo.updateService.notifyPlayer(player)
16+
}
17+
}
18+
19+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package dev.themeinerlp.attollo.service
2+
3+
import com.github.zafarkhaja.semver.Version
4+
import dev.themeinerlp.attollo.*
5+
import net.kyori.adventure.text.Component
6+
import net.kyori.adventure.text.event.ClickEvent
7+
import net.kyori.adventure.text.logger.slf4j.ComponentLogger
8+
import net.kyori.adventure.text.minimessage.MiniMessage
9+
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder
10+
import org.bukkit.Bukkit
11+
import org.bukkit.entity.Player
12+
import org.slf4j.LoggerFactory
13+
import java.io.IOException
14+
import java.net.http.HttpClient
15+
import java.net.http.HttpResponse
16+
17+
class UpdateService(plugin: Attollo) : Runnable {
18+
private val hangarClient = HttpClient.newBuilder().build()
19+
private val LOGGER = LoggerFactory.getLogger(UpdateService::class.java)
20+
private val localVersion = Version.parse(plugin.pluginMeta.version)
21+
private var remoteVersion: Version? = null
22+
private val scheduler = Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, this, 0, 20 * 60 * 60 * 3)
23+
private val DOWNLOAD_URL = "https://hangar.papermc.io/OneLiteFeather/Attollo/versions/%s"
24+
25+
26+
override fun run() {
27+
val remoteVersion: Version? = getNewerVersion()
28+
if (remoteVersion != null) {
29+
this.remoteVersion = remoteVersion
30+
for (onlinePlayer in Bukkit.getOnlinePlayers()) {
31+
if (onlinePlayer.isOp || onlinePlayer.hasPermission(NOTIFY_UPDATE_PERMISSION)) {
32+
notifyPlayer(localVersion, remoteVersion, onlinePlayer)
33+
}
34+
}
35+
}
36+
}
37+
38+
fun notifyConsole(logger: ComponentLogger) {
39+
if (this.remoteVersion != null && remoteVersion?.isHigherThan(this.localVersion) == true) {
40+
logger.warn(
41+
MiniMessage.miniMessage().deserialize(
42+
NOTIFY_CONSOLE_UPDATE_MESSAGE,
43+
Placeholder.component("local_version", Component.text(localVersion.toString())),
44+
Placeholder.component("remote_version", Component.text(remoteVersion.toString())),
45+
Placeholder.component("download_url", Component.text(DOWNLOAD_URL.format(remoteVersion.toString())))
46+
)
47+
)
48+
}
49+
}
50+
51+
fun notifyPlayer(player: Player) {
52+
if (this.remoteVersion != null && remoteVersion?.isHigherThan(this.localVersion) == true) {
53+
notifyPlayer(this.localVersion, this.remoteVersion, player)
54+
}
55+
}
56+
57+
private fun notifyPlayer(localVersion: Version, remoteVersion: Version?, player: Player) {
58+
player.sendMessage(
59+
MiniMessage.miniMessage().deserialize(
60+
NOTIFY_PLAYER_UPDATE_MESSAGE,
61+
Placeholder.component("local_version", Component.text(localVersion.toString())),
62+
Placeholder.component("remote_version", Component.text(remoteVersion.toString())),
63+
Placeholder.styling("download_url", ClickEvent.openUrl(DOWNLOAD_URL.format(remoteVersion.toString())))
64+
)
65+
)
66+
}
67+
68+
private fun getNewerVersion(): Version? {
69+
try {
70+
val httpResponse = hangarClient.send(
71+
LATEST_RELEASE_VERSION_REQUEST,
72+
HttpResponse.BodyHandlers.ofString()
73+
)
74+
val remoteVersion = Version.parse(httpResponse.body())
75+
if (remoteVersion.isHigherThan(this.localVersion)) {
76+
return remoteVersion
77+
}
78+
} catch (e: IOException) {
79+
LOGGER.error("Something went wrong to check updates", e)
80+
} catch (e: InterruptedException) {
81+
LOGGER.error("Something went wrong to check updates", e)
82+
}
83+
return null
84+
}
85+
86+
fun shutdown() {
87+
hangarClient.shutdownNow()
88+
scheduler.cancel()
89+
}
90+
}

0 commit comments

Comments
 (0)