11package io.github.grassproject.framework.github
22
3- @ExperimentalStdlibApi
4- internal object GithubAPI {
3+ import com.google.gson.Gson
4+ import com.google.gson.JsonObject
5+ import io.github.grassproject.framework.core.GPPlugin
6+ import io.github.grassproject.framework.util.GPLogger
7+ import java.io.File
8+ import java.net.HttpURLConnection
9+ import java.net.URL
10+ import java.nio.file.Files
11+ import java.nio.file.StandardCopyOption
12+
13+ @Deprecated(" TEST" )
14+ object GithubAPI {
15+ private const val ORG = " GrassProject"
16+ private const val REPO = " GPFramework"
17+ private const val GITHUB_API = " https://api.github.com/repos/${ORG } /${REPO } /releases/latest"
18+
19+ fun isLatest (instance : GPPlugin ): Boolean {
20+ val latest = getLatest() ? : return true
21+ val latestRaw = latest.get(" ver" ).asString
22+ val currentRaw = instance.version
23+
24+ fun parseVersion (ver : String ): Pair <List <Int >, String?> {
25+ val parts = ver.split(" -" , limit = 2 )
26+ val numbers = parts[0 ].split(" ." ).mapNotNull { it.toIntOrNull() }
27+ val tag = if (parts.size > 1 ) parts[1 ].lowercase() else null
28+ return numbers to tag
29+ }
30+
31+ val (latestNums, latestTag) = parseVersion(latestRaw)
32+ val (currentNums, currentTag) = parseVersion(currentRaw)
33+
34+ val maxLen = maxOf(latestNums.size, currentNums.size)
35+ for (i in 0 until maxLen) {
36+ val cur = currentNums.getOrNull(i) ? : 0
37+ val lat = latestNums.getOrNull(i) ? : 0
38+ if (cur < lat) return false
39+ if (cur > lat) return true
40+ }
41+
42+ return when {
43+ currentTag == null && latestTag != null -> true
44+ currentTag != null && latestTag == null -> false
45+ currentTag == null && latestTag == null -> true
46+ else -> {
47+ val order = listOf (" ALPHA" , " BETA" , " RC" , " SNAPSHOT" )
48+ val curIndex = order.indexOfFirst { currentTag!! .contains(it) }
49+ .takeIf { it >= 0 } ? : Int .MAX_VALUE
50+ val latIndex = order.indexOfFirst { latestTag!! .contains(it) }
51+ .takeIf { it >= 0 } ? : Int .MAX_VALUE
52+ curIndex >= latIndex
53+ }
54+ }
55+ }
56+
57+ fun downloadAndReplace (plugin : GPPlugin ): Boolean {
58+ val latest = getLatest() ? : return false
59+ val downloadUrl = latest.get(" download" )?.asString ? : return false
60+
61+
62+ return try {
63+ val pluginsDir = File (" plugins" )
64+ val newFile = File (pluginsDir, " ${plugin.name} .jar.new" )
65+ URL (downloadUrl).openStream().use { input ->
66+ Files .copy(input, newFile.toPath(), StandardCopyOption .REPLACE_EXISTING )
67+ }
68+ GPLogger .info(" 새 버전을 다운로드했습니다. 서버 재시작 후 적용됩니다." )
69+ true
70+ } catch (e: Exception ) {
71+ GPLogger .warning(" Fail to download UPDATE: ${e.message} " )
72+ false
73+ }
74+ }
75+
76+ fun getLatest (): JsonObject {
77+ val json= JsonObject ()
78+ val data= Gson ().fromJson(fetchData(GITHUB_API ), JsonObject ::class .java)
79+
80+ json.addProperty(" ver" , data.get(" tag_name" ).asString)
81+ json.addProperty(" published" , data.get(" published_at" ).asString)
82+
83+ val assets = data.getAsJsonArray(" assets" )
84+ val downloadUrl = assets[0 ].asJsonObject.get(" browser_download_url" ).asString
85+ json.addProperty(" download" , downloadUrl)
86+
87+ return json
88+ }
89+
90+ private fun fetchData (url : String ): String {
91+ return URL (url).httpRequest {
92+ requestMethod = " GET"
93+ setRequestProperty(" Accept" , " application/vnd.github.v3+json" )
94+ // setRequestProperty("Authorization", "")
95+ inputStream.bufferedReader().use { it.readText() }
96+ }
97+ }
98+
99+ private fun <T > URL.httpRequest (requester : (HttpURLConnection .() -> T )): T {
100+ return with (openConnection() as HttpURLConnection ) { requester.invoke(this ) }
101+ }
5102}
0 commit comments