mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-10 15:59:33 +07:00
Harden and improve "Download Mod from Url" parser (#8924)
This commit is contained in:
@ -1642,7 +1642,8 @@ Download [modName] =
|
|||||||
Update [modName] =
|
Update [modName] =
|
||||||
Could not download mod list =
|
Could not download mod list =
|
||||||
Download mod from URL =
|
Download mod from URL =
|
||||||
Please enter the mod repository -or- archive zip url: =
|
Please enter the mod repository -or- archive zip -or- branch url: =
|
||||||
|
Invalid link! =
|
||||||
Paste from clipboard =
|
Paste from clipboard =
|
||||||
Download =
|
Download =
|
||||||
Done! =
|
Done! =
|
||||||
|
@ -323,36 +323,50 @@ object Github {
|
|||||||
//var has_wiki = false // a wiki could mean proper documentation for the mod?
|
//var has_wiki = false // a wiki could mean proper documentation for the mod?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize `this` with an url, extracting all possible fields from it.
|
* Initialize `this` with an url, extracting all possible fields from it
|
||||||
|
* (html_url, author, repoName, branchName).
|
||||||
*
|
*
|
||||||
* Allows basic repo url or complete 'zip' url from github's code->download zip menu
|
* Allow url formats:
|
||||||
|
* * Basic repo url:
|
||||||
|
* https://github.com/author/repoName
|
||||||
|
* * or complete 'zip' url from github's code->download zip menu:
|
||||||
|
* https://github.com/author/repoName/archive/refs/heads/branchName.zip
|
||||||
|
* * or the branch url same as one navigates to on github through the "branches" menu:
|
||||||
|
* https://github.com/author/repoName/tree/branchName
|
||||||
*
|
*
|
||||||
* @return `this` to allow chaining
|
* In the case of the basic repo url, an API query is sent to determine the default branch.
|
||||||
|
* Other url forms will not go online.
|
||||||
|
*
|
||||||
|
* @return `this` to allow chaining, `null` for invalid links or any other failures
|
||||||
*/
|
*/
|
||||||
fun parseUrl(url: String): Repo {
|
fun parseUrl(url: String): Repo? {
|
||||||
// Allow url formats
|
fun processMatch(matchResult: MatchResult): Repo {
|
||||||
// https://github.com/author/repoName
|
html_url = matchResult.groups[1]!!.value
|
||||||
// or
|
owner.login = matchResult.groups[2]!!.value
|
||||||
// https://github.com/author/repoName/archive/refs/heads/branchName.zip
|
name = matchResult.groups[3]!!.value
|
||||||
// and extract author, repoName, branchName
|
default_branch = matchResult.groups[4]!!.value
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
html_url = url
|
html_url = url
|
||||||
default_branch = "master"
|
default_branch = "master"
|
||||||
val matchZip = Regex("""^(.*/(.*)/(.*))/archive/(?:.*/)?([^.]+).zip$""").matchEntire(url)
|
val matchZip = Regex("""^(.*/(.*)/(.*))/archive/(?:.*/)?([^.]+).zip$""").matchEntire(url)
|
||||||
if (matchZip != null && matchZip.groups.size > 3) {
|
if (matchZip != null && matchZip.groups.size > 4)
|
||||||
html_url = matchZip.groups[1]!!.value
|
return processMatch(matchZip)
|
||||||
owner.login = matchZip.groups[2]!!.value
|
|
||||||
name = matchZip.groups[3]!!.value
|
val matchBranch = Regex("""^(.*/(.*)/(.*))/tree/([^/]+)$""").matchEntire(url)
|
||||||
default_branch = matchZip.groups[4]!!.value
|
if (matchBranch != null && matchBranch.groups.size > 4)
|
||||||
} else {
|
return processMatch(matchBranch)
|
||||||
val matchRepo = Regex("""^.*/(.*)/(.*)/?$""").matchEntire(url)
|
|
||||||
|
val matchRepo = Regex("""^.*//.*/(.+)/(.+)/?$""").matchEntire(url)
|
||||||
if (matchRepo != null && matchRepo.groups.size > 2) {
|
if (matchRepo != null && matchRepo.groups.size > 2) {
|
||||||
val repoString = download("https://api.github.com/repos/${matchRepo.groups[1]!!.value}/${matchRepo.groups[2]!!.value}")!!
|
// Query API if we got the first URL format to get the correct default branch
|
||||||
.bufferedReader().readText()
|
val response = download("https://api.github.com/repos/${matchRepo.groups[1]!!.value}/${matchRepo.groups[2]!!.value}")
|
||||||
|
?: return null
|
||||||
|
val repoString = response.bufferedReader().readText()
|
||||||
return json().fromJson(Repo::class.java, repoString)
|
return json().fromJson(Repo::class.java, repoString)
|
||||||
}
|
}
|
||||||
}
|
return null
|
||||||
return this
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,8 +400,8 @@ class ModManagementScreen(
|
|||||||
val downloadButton = "Download mod from URL".toTextButton()
|
val downloadButton = "Download mod from URL".toTextButton()
|
||||||
downloadButton.onClick {
|
downloadButton.onClick {
|
||||||
val popup = Popup(this)
|
val popup = Popup(this)
|
||||||
popup.addGoodSizedLabel("Please enter the mod repository -or- archive zip url:").row()
|
popup.addGoodSizedLabel("Please enter the mod repository -or- archive zip -or- branch url:").row()
|
||||||
val textField = UncivTextField.create("")
|
val textField = UncivTextField.create("").apply { maxLength = 666 }
|
||||||
popup.add(textField).width(stage.width / 2).row()
|
popup.add(textField).width(stage.width / 2).row()
|
||||||
val pasteLinkButton = "Paste from clipboard".toTextButton()
|
val pasteLinkButton = "Paste from clipboard".toTextButton()
|
||||||
pasteLinkButton.onClick {
|
pasteLinkButton.onClick {
|
||||||
@ -412,7 +412,12 @@ class ModManagementScreen(
|
|||||||
actualDownloadButton.onClick {
|
actualDownloadButton.onClick {
|
||||||
actualDownloadButton.setText("Downloading...".tr())
|
actualDownloadButton.setText("Downloading...".tr())
|
||||||
actualDownloadButton.disable()
|
actualDownloadButton.disable()
|
||||||
downloadMod(Github.Repo().parseUrl(textField.text)) { popup.close() }
|
val repo = Github.Repo().parseUrl(textField.text)
|
||||||
|
if (repo == null) {
|
||||||
|
ToastPopup("Invalid link!", this@ModManagementScreen)
|
||||||
|
popup.close() // Re-enabling button would be nice, but Toast doesn't work over other Popups
|
||||||
|
} else
|
||||||
|
downloadMod(repo) { popup.close() }
|
||||||
}
|
}
|
||||||
popup.add(actualDownloadButton).row()
|
popup.add(actualDownloadButton).row()
|
||||||
popup.addCloseButton()
|
popup.addCloseButton()
|
||||||
|
Reference in New Issue
Block a user