Skip to content

Commit

Permalink
Merge branch 'pr/2'
Browse files Browse the repository at this point in the history
  • Loading branch information
darksaid98 committed May 20, 2024
2 parents 776d678 + bbd9588 commit a2457f4
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 4 deletions.
32 changes: 31 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,34 @@ But it allows for more:
* With the use of wildcard options and regex selectors it could be made to even work across modpack versions.

## Format
See `server-setup-config.yaml` for a example file how this file should be layouted.
See `server-setup-config.yaml` for a example file how this file should be layouted.

## How is this fork different than the original?
This fork has been modified to use the official CurseForge API. This has become necesarry due to the recent shutdown of the cursemeta API (a third-pary CurseForge API). With this change, an API key is needed. There are two ways to get an API key which are layed out below.

## 1. Official Way
The official way is to create a CFCore account and generate an API key. This is the easiest and most straight forward way, but CurseForge allows mod/modpack creators to disable third-parties from being able to access the download URL through the API, so some mods may not be able to be downloaded automatically.

## ~~2. The Absolutly-Not-Official Way~~ Broken Now. Use the Sequel!
~~The Absolutly-Not-Official way is to extract the key that the official CurseForge uses to access the CFCore API. Credit for this goes to this repo: https://git.sakamoto.pl/domi/curseme/-/tree/meow. If you are on linux, there is a script in that repo called getToken.sh that can be run to automate that process. From what I can tell, it is legit, but use your judgement and check out the code. For those on other OSes or who don't want to run that script:~~
1. ~~Download the Linux verson of the CurseForge client from https://curseforge.overwolf.com/. (Direct download: https://curseforge.overwolf.com/downloads/curseforge-latest-linux.zip)~~
2. ~~Open the zip using 7-zip or a simmilar program.~~
3. ~~Double click on the .AppImage to open it.~~
4. ~~Navigate to resources/app/dist/desktop and open desktop.js in an editor other than notepad (the file is too large and it crashes notepad)~~
5. ~~Search the document for `"cfCoreApiKey":` (quotes and semicolons included). This will return a single result. Copy the value in the quotes folowing the semicolon.
`"cfCoreApiKey": "#COPY THE VALUE THAT IS HERE#"`~~
6. ~~Take that value and paste it into your `server-setup-config.yaml` in the `curseForgeAPIKey` field~~

## 3. The Absolutly-Not-Official Way (The Sequel)
This is similar, but updated for the modern CurseForge app. The CurseForge app now packages the resources in an asar archive, so you need to extract the archive first, then retrieve the file.
1. Download the Linux verson of the CurseForge client from https://curseforge.overwolf.com/. (Direct download: https://curseforge.overwolf.com/downloads/curseforge-latest-linux.zip)
2. Install NodeJS from nodejs.org or your package manager.
3. Open the zip using 7-zip or a simmilar program.
4. Double click on the .AppImage to open it.
5. Navigate to the resources folder and copy the app.asar file to a working directory
6. Open your terminal and navigate to the working directory with the app.asar
7. Run `npx @electron/asar extract app.asar app`. This will extract the contents of app.asar to a folder called app.
8. Navigate to app/dist/desktop and open desktop.js in an editor other than notepad (the file is too large and it crashes notepad)
9. Search the document for `"cfCoreApiKey":` (quotes and semicolons included). This will return a single result. Copy the value in the quotes folowing the semicolon.
`"cfCoreApiKey": "#COPY THE VALUE THAT IS HERE#"`
10. Take that value and paste it into your `server-setup-config.yaml` in the `curseForgeAPIKey` field
8 changes: 7 additions & 1 deletion server-setup-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ install:
# - zip or zipfile
modpackFormat: curse

# In order to obtain the download urls for mods enclosed in a curseforge format, you must provide an
# API key. Please visit https://github.com/Ocraftyone/ServerStarter-CFCorePatch for more details
# on how to obtain a key. This can be omitted if you are using the zip modpackFormat.
curseForgeAPIKey:

# Settings which are specific to the format used, might not be needed in some casese
formatSpecific:
# optional paramenter used for curse to specify a whole project to ignore (mostly if it is client side only)
Expand Down Expand Up @@ -214,7 +219,7 @@ launch:
# For this you need to have all available JVMs on the PATH
# -> MC 1.12 to 1.16 requires java [8, 9, 10, 11]
# -> MC 1.17 requires java [17]
supportedJavaVersions: [17]
supportedJavaVersions: [ 17 ]

# Java args that are supposed to be used when the server launches
# keep in mind java args often need ' - ' in front of it to work, use clarifying parentheses to make sure it uses it correctly
Expand All @@ -241,3 +246,4 @@ launch:
- "-XX:MaxTenuringThreshold=1"
- "-Dfml.readTimeout=90" # servertimeout
- "-Dfml.queryResult=confirm" # auto /fmlconfirm

Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ data class InstallConfig(

var modpackUrl: String = "",
var modpackFormat: String = "",
var curseForgeAPIKey: String = "",
var formatSpecific: Map<String, Any> = Collections.emptyMap(),

var baseInstallPath: String = "",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package atm.bloodworkxgaming.serverstarter.packtype.curse

import atm.bloodworkxgaming.serverstarter.InternetManager
import atm.bloodworkxgaming.serverstarter.ServerStarter
import atm.bloodworkxgaming.serverstarter.ServerStarter.Companion.LOGGER
import atm.bloodworkxgaming.serverstarter.config.ConfigFile
import atm.bloodworkxgaming.serverstarter.packtype.AbstractZipbasedPackType
Expand All @@ -24,11 +25,14 @@ import java.nio.file.PathMatcher
import java.nio.file.Paths
import java.util.*
import java.util.concurrent.atomic.AtomicInteger
import java.util.logging.Logger
import java.util.regex.Pattern
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import kotlin.system.exitProcess

open class CursePackType(private val configFile: ConfigFile, internetManager: InternetManager) : AbstractZipbasedPackType(configFile, internetManager) {
open class CursePackType(private val configFile: ConfigFile, internetManager: InternetManager) :
AbstractZipbasedPackType(configFile, internetManager) {
private var forgeVersion: String = configFile.install.loaderVersion
private var mcVersion: String = configFile.install.mcVersion
private val oldFiles = File(basePath + "OLD_TO_DELETE/")
Expand Down Expand Up @@ -272,7 +276,60 @@ open class CursePackType(private val configFile: ConfigFile, internetManager: In
ignoreSet.add(o.toString())
}

val urls = requestModInformation(mods, ignoreSet)

val urls = ConcurrentLinkedQueue<String>()

LOGGER.info("Requesting Download links from CFCore API.")

if (configFile.install.curseForgeAPIKey.isEmpty()) {
LOGGER.error("No API Key provided. Please see https://github.com/Ocraftyone/ServerStarter-CFCorePatch for details on how to obtain a key")
exitProcess(1)
}

mods.parallelStream().forEach { mod ->
if (ignoreSet.isNotEmpty() && ignoreSet.contains(mod.projectID)) {
LOGGER.info("Skipping mod with projectID: " + mod.projectID)
return@forEach
}

//old code using cursemeta servers, removed fallback and made hardcoded bc the api calls are incompatable
// val url = (configFile.install.getFormatSpecificSettingOrDefault("cursemeta", "https://cursemeta.dries007.net")
// + "/" + mod.projectID + "/" + mod.fileID + ".json")//
val url = "https://api.curseforge.com/v1/mods/" + mod.projectID + "/files/" + mod.fileID + "/download-url"
LOGGER.info("Download url is: $url", true)

try {
val request = Request.Builder()
.url(url)
.header("User-Agent", "All the mods server installer.")
.header("Content-Type", "application/json")
.header("x-api-key", configFile.install.curseForgeAPIKey)
.build()

val res = internetManager.httpClient.newCall(request).execute()

if (!res.isSuccessful)
throw IOException("Request to $url was not successful.")
val body = res.body ?: throw IOException("Request to $url returned a null body.")

val jsonRes = JsonParser().parse(body.string()).asJsonObject
LOGGER.info("Response from manifest query: $jsonRes", true)

if (!jsonRes.asJsonObject.get("data").isJsonNull) {
urls.add(
// jsonRes
// .asJsonObject
// .getAsJsonPrimitive("DownloadURL").asString
jsonRes.asJsonObject.getAsJsonPrimitive("data").asString

)
} else {
LOGGER.error("Mod failed to produce download URL - ProjectID: " + mod.projectID + ", FileID: " + mod.fileID)
}
} catch (e: IOException) {
LOGGER.error("Error while trying to get URL from CFCore for mod $mod", e)
}
}

LOGGER.info("Mods to download: $urls", true)

Expand Down

0 comments on commit a2457f4

Please sign in to comment.