1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
package moe.nea.ledger.modules
import com.google.gson.JsonElement
import com.google.gson.JsonPrimitive
import moe.nea.ledger.DevUtil
import moe.nea.ledger.LedgerLogger
import moe.nea.ledger.TriggerCommand
import moe.nea.ledger.config.LedgerConfig
import moe.nea.ledger.config.MainOptions
import moe.nea.ledger.events.RegistrationFinishedEvent
import moe.nea.ledger.events.TriggerEvent
import moe.nea.ledger.gen.BuildConfig
import moe.nea.ledger.utils.ErrorUtil
import moe.nea.ledger.utils.MinecraftExecutor
import moe.nea.ledger.utils.di.Inject
import moe.nea.ledger.utils.network.RequestUtil
import moe.nea.libautoupdate.CurrentVersion
import moe.nea.libautoupdate.GithubReleaseUpdateData
import moe.nea.libautoupdate.GithubReleaseUpdateSource
import moe.nea.libautoupdate.PotentialUpdate
import moe.nea.libautoupdate.UpdateContext
import moe.nea.libautoupdate.UpdateData
import moe.nea.libautoupdate.UpdateTarget
import moe.nea.libautoupdate.UpdateUtils
import net.minecraft.util.ChatComponentText
import net.minecraft.util.ChatStyle
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import java.util.concurrent.CompletableFuture
class UpdateChecker @Inject constructor(
val errorUtil: ErrorUtil,
val requestUtil: RequestUtil,
) {
@Inject
lateinit var minecraftExecutor: MinecraftExecutor
val updater = UpdateContext(
NightlyAwareGithubUpdateSource("nea89o", "LocalTransactionLedger"),
if (DevUtil.isDevEnv) UpdateTarget { listOf() }
else UpdateTarget.deleteAndSaveInTheSameFolder(UpdateChecker::class.java),
object : CurrentVersion {
override fun display(): String {
return BuildConfig.VERSION
}
override fun isOlderThan(element: JsonElement?): Boolean {
if (element !is JsonPrimitive || !element.isString) return true
val newHash = element.asString // TODO: change once i support non nightly update streams
val length = minOf(newHash.length, BuildConfig.GIT_COMMIT.length)
if (newHash.substring(0, length).equals(BuildConfig.GIT_COMMIT.substring(0, length), ignoreCase = true))
return false
return true
}
override fun toString(): String {
return "{gitversion:${BuildConfig.GIT_COMMIT}, version:${BuildConfig.FULL_VERSION}}"
}
},
"ledger"
)
class NightlyAwareGithubUpdateSource(owner: String, repository: String) :
GithubReleaseUpdateSource(owner, repository) {
override fun selectUpdate(updateStream: String, releases: List<GithubRelease>): UpdateData? {
if (updateStream == "nightly") {
return findAsset(releases.find { it.tagName == "nightly" })
}
return super.selectUpdate(updateStream, releases.filter { it.tagName != "nightly" })
}
val releaseRegex = "commit: `(?<hash>[a-f0-9]+)`".toPattern()
override fun findAsset(release: GithubRelease?): UpdateData? {
val update = super.findAsset(release) as GithubReleaseUpdateData? ?: return null
return GithubReleaseUpdateData(
update.versionName,
releaseRegex.matcher(update.releaseDescription)
.takeIf { it.find() }
?.run { group("hash") }
?.let(::JsonPrimitive)
?: update.versionNumber,
update.sha256,
update.download,
update.releaseDescription,
update.targetCommittish,
update.createdAt,
update.publishedAt,
update.htmlUrl
)
}
}
init {
UpdateUtils.patchConnection {
this.requestUtil.enhanceConnection(it)
}
}
var latestUpdate: PotentialUpdate? = null
var hasNotified = false
@SubscribeEvent
fun onStartup(event: RegistrationFinishedEvent) {
if (config.main.updateCheck == MainOptions.UpdateCheckBehaviour.NONE) return
launchUpdateCheck()
}
fun launchUpdateCheck() {
errorUtil.listenToFuture(
updater.checkUpdate("nightly")
.thenAcceptAsync(
{
latestUpdate = it
informAboutUpdates(it)
}, minecraftExecutor)
)
}
@Inject
lateinit var config: LedgerConfig
@Inject
lateinit var triggerCommand: TriggerCommand
val installTrigger = "execute-download"
@Inject
lateinit var logger: LedgerLogger
fun informAboutUpdates(potentialUpdate: PotentialUpdate) {
if (hasNotified) return
hasNotified = true
if (!potentialUpdate.isUpdateAvailable) return
logger.printOut(
ChatComponentText("§aThere is a new update for LocalTransactionLedger. Click here to automatically download and install it.")
.setChatStyle(ChatStyle().setChatClickEvent(triggerCommand.getTriggerCommandLine(installTrigger))))
if (config.main.updateCheck == MainOptions.UpdateCheckBehaviour.FULL) {
downloadUpdate()
}
}
var updateFuture: CompletableFuture<Void>? = null
fun downloadUpdate() {
val l = latestUpdate ?: return
if (updateFuture != null) return
// TODO: inject into findAsset to overwrite the tag id with the commit id
logger.printOut("§aTrying to download ledger update ${l.update.versionName}")
updateFuture =
latestUpdate?.launchUpdate()
?.thenAcceptAsync(
{
logger.printOut("§aLedger update downloaded. It will automatically apply after your next restart.")
}, minecraftExecutor)
?.let(errorUtil::listenToFuture)
}
@SubscribeEvent
fun onTrigger(event: TriggerEvent) {
if (event.action == installTrigger) {
event.isCanceled = true
downloadUpdate()
}
}
}
|